Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: nRF51_Vdd TextLCD BME280
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 "platform/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 bool unaligned_src = (((size_t) buf / sizeof(uint32_t) * sizeof(uint32_t)) != (size_t) buf); 00111 chunk = std::min(current_sector_size - (addr % current_sector_size), size); 00112 // Need to use the internal page buffer in any of these two cases: 00113 // 1. Size is not page aligned 00114 // 2. Source buffer is not aligned to uint32_t. This is not supported by many targets (although 00115 // the pointer they accept is of uint8_t). 00116 if (unaligned_src || (chunk < page_size)) { 00117 chunk = std::min(chunk, page_size); 00118 memcpy(_page_buf, buf, chunk); 00119 if (chunk < page_size) { 00120 memset(_page_buf + chunk, 0xFF, page_size - chunk); 00121 } 00122 prog_buf = _page_buf; 00123 prog_size = page_size; 00124 } else { 00125 chunk = chunk / page_size * page_size; 00126 prog_buf = buf; 00127 prog_size = chunk; 00128 } 00129 if (flash_program_page(&_flash, addr, prog_buf, prog_size)) { 00130 ret = -1; 00131 break; 00132 } 00133 size -= chunk; 00134 addr += chunk; 00135 buf += chunk; 00136 } 00137 _mutex->unlock(); 00138 00139 return ret; 00140 } 00141 00142 bool FlashIAP::is_aligned_to_sector(uint32_t addr, uint32_t size) 00143 { 00144 uint32_t current_sector_size = flash_get_sector_size(&_flash, addr); 00145 if (!is_aligned(size, current_sector_size) || 00146 !is_aligned(addr, current_sector_size)) { 00147 return false; 00148 } else { 00149 return true; 00150 } 00151 } 00152 00153 int FlashIAP::erase(uint32_t addr, uint32_t size) 00154 { 00155 uint32_t current_sector_size; 00156 uint32_t flash_size = flash_get_size(&_flash); 00157 uint32_t flash_start_addr = flash_get_start_address(&_flash); 00158 uint32_t flash_end_addr = flash_start_addr + flash_size; 00159 uint32_t erase_end_addr = addr + size; 00160 00161 if (erase_end_addr > flash_end_addr) { 00162 return -1; 00163 } else if (erase_end_addr < flash_end_addr) { 00164 uint32_t following_sector_size = flash_get_sector_size(&_flash, erase_end_addr); 00165 if (!is_aligned(erase_end_addr, following_sector_size)) { 00166 return -1; 00167 } 00168 } 00169 00170 int32_t ret = 0; 00171 _mutex->lock(); 00172 while (size) { 00173 ret = flash_erase_sector(&_flash, addr); 00174 if (ret != 0) { 00175 ret = -1; 00176 break; 00177 } 00178 current_sector_size = flash_get_sector_size(&_flash, addr); 00179 size -= current_sector_size; 00180 addr += current_sector_size; 00181 } 00182 _mutex->unlock(); 00183 return ret; 00184 } 00185 00186 uint32_t FlashIAP::get_page_size() const 00187 { 00188 return flash_get_page_size(&_flash); 00189 } 00190 00191 uint32_t FlashIAP::get_sector_size(uint32_t addr) const 00192 { 00193 return flash_get_sector_size(&_flash, addr); 00194 } 00195 00196 uint32_t FlashIAP::get_flash_start() const 00197 { 00198 return flash_get_start_address(&_flash); 00199 } 00200 00201 uint32_t FlashIAP::get_flash_size() const 00202 { 00203 return flash_get_size(&_flash); 00204 } 00205 00206 } 00207 00208 #endif
Generated on Tue Jul 12 2022 15:15:45 by
