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 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
Generated on Tue Jul 12 2022 14:23:47 by
