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.
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 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 12:44:08 by
