Gleb Klochkov / Mbed OS Climatcontroll_Main

Dependencies:   esp8266-driver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers FlashIAP.cpp Source File

FlashIAP.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2017 ARM Limited
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining a copy
00005  * of this software and associated documentation files (the "Software"), to deal
00006  * in the Software without restriction, including without limitation the rights
00007  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00008  * copies of the Software, and to permit persons to whom the Software is
00009  * furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice shall be included in
00012  * all copies or substantial portions of the Software.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00020  * SOFTWARE.
00021  */
00022 
00023 #include <stdio.h>
00024 #include <string.h>
00025 #include <algorithm>
00026 #include "FlashIAP.h"
00027 #include "mbed_assert.h"
00028 
00029 
00030 #ifdef DEVICE_FLASH
00031 
00032 namespace mbed {
00033 
00034 SingletonPtr<PlatformMutex>  FlashIAP::_mutex;
00035 
00036 static inline bool is_aligned(uint32_t number, uint32_t alignment)
00037 {
00038     if ((number % alignment) != 0) {
00039         return false;
00040     } else {
00041         return true;
00042     }
00043 }
00044 
00045 FlashIAP::FlashIAP()
00046 {
00047 
00048 }
00049 
00050 FlashIAP::~FlashIAP()
00051 {
00052 
00053 }
00054 
00055 int FlashIAP::init()
00056 {
00057     int ret = 0;
00058     _mutex->lock();
00059     if (flash_init(&_flash)) {
00060         ret = -1;
00061     }
00062     uint32_t page_size = get_page_size();
00063     _page_buf = new uint8_t[page_size];
00064 
00065     _mutex->unlock();
00066     return ret;
00067 }
00068 
00069 int FlashIAP::deinit()
00070 {
00071     int ret = 0;
00072     _mutex->lock();
00073     if (flash_free(&_flash)) {
00074         ret = -1;
00075     }
00076     delete[] _page_buf;
00077     _mutex->unlock();
00078     return ret;
00079 }
00080 
00081 
00082 int FlashIAP::read(void *buffer, uint32_t addr, uint32_t size)
00083 {
00084     int32_t ret = -1;
00085     _mutex->lock();
00086     ret = flash_read(&_flash, addr, (uint8_t *) buffer, size);
00087     _mutex->unlock();
00088     return ret;
00089 }
00090 
00091 int FlashIAP::program(const void *buffer, uint32_t addr, uint32_t size)
00092 {
00093     uint32_t page_size = get_page_size();
00094     uint32_t flash_size = flash_get_size(&_flash);
00095     uint32_t flash_start_addr = flash_get_start_address(&_flash);
00096     uint32_t chunk, prog_size;
00097     const uint8_t *buf = (uint8_t *) buffer;
00098     const uint8_t *prog_buf;
00099 
00100     // addr should be aligned to page size
00101     if (!is_aligned(addr, page_size) || (!buffer) ||
00102         ((addr + size) > (flash_start_addr + flash_size))) {
00103         return -1;
00104     }
00105 
00106     int ret = 0;
00107     _mutex->lock();
00108     while (size) {
00109         uint32_t current_sector_size = flash_get_sector_size(&_flash, addr);
00110         chunk = std::min(current_sector_size - (addr % current_sector_size), size);
00111         if (chunk < page_size) {
00112             memcpy(_page_buf, buf, chunk);
00113             memset(_page_buf + chunk, 0xFF, page_size - chunk);
00114             prog_buf = _page_buf;
00115             prog_size = page_size;
00116         } else {
00117             chunk = chunk / page_size * page_size;
00118             prog_buf = buf;
00119             prog_size = chunk;
00120         }
00121         if (flash_program_page(&_flash, addr, prog_buf, prog_size)) {
00122             ret = -1;
00123             break;
00124         }
00125         size -= chunk;
00126         addr += chunk;
00127         buf += chunk;
00128     }
00129     _mutex->unlock();
00130 
00131     return ret;
00132 }
00133 
00134 bool FlashIAP::is_aligned_to_sector(uint32_t addr, uint32_t size)
00135 {
00136     uint32_t current_sector_size = flash_get_sector_size(&_flash, addr);
00137     if (!is_aligned(size, current_sector_size) ||
00138         !is_aligned(addr, current_sector_size)) {
00139         return false;
00140     } else {
00141         return true;
00142     }
00143 }
00144 
00145 int FlashIAP::erase(uint32_t addr, uint32_t size)
00146 {
00147     uint32_t current_sector_size;
00148     uint32_t flash_size = flash_get_size(&_flash);
00149     uint32_t flash_start_addr = flash_get_start_address(&_flash);
00150     uint32_t flash_end_addr = flash_start_addr + flash_size;
00151     uint32_t erase_end_addr = addr + size;
00152 
00153     if (erase_end_addr > flash_end_addr) {
00154         return -1;
00155     } else if (erase_end_addr < flash_end_addr){
00156         uint32_t following_sector_size = flash_get_sector_size(&_flash, erase_end_addr);
00157         if (!is_aligned(erase_end_addr, following_sector_size)) {
00158             return -1;
00159         }
00160     }
00161 
00162     int32_t ret = 0;
00163     _mutex->lock();
00164     while (size) {
00165         ret = flash_erase_sector(&_flash, addr);
00166         if (ret != 0) {
00167             ret = -1;
00168             break;
00169         }
00170         current_sector_size = flash_get_sector_size(&_flash, addr);
00171         size -= current_sector_size;
00172         addr += current_sector_size;
00173     }
00174     _mutex->unlock();
00175     return ret;
00176 }
00177 
00178 uint32_t FlashIAP::get_page_size() const
00179 {
00180     return flash_get_page_size(&_flash);
00181 }
00182 
00183 uint32_t FlashIAP::get_sector_size(uint32_t addr) const
00184 {
00185     return flash_get_sector_size(&_flash, addr);
00186 }
00187 
00188 uint32_t FlashIAP::get_flash_start() const
00189 {
00190     return flash_get_start_address(&_flash);
00191 }
00192 
00193 uint32_t FlashIAP::get_flash_size() const
00194 {
00195     return flash_get_size(&_flash);
00196 }
00197 
00198 }
00199 
00200 #endif