Tiny storage(file) system on MCU internal flash memory for Nucleo F4xx. The purpose of SOFBlock class is to provide a way to write data on flash memory in the same way of file handling class in the file system.
SOF_dev_stm32_l4xx.cpp
00001 /** 00002 * @file SOF_dev_stm32_l4xx.c 00003 * 00004 * @brief Flash device access interface for STM32 L4xx series 00005 * 00006 * 00007 * History: 00008 */ 00009 00010 #include <stdio.h> 00011 #include "SOF_dev.h" 00012 #include <string.h> 00013 00014 #include "mbed.h" 00015 00016 #include "stm32l4xx_hal_flash.h" 00017 00018 #define DCRLF "\r\n" 00019 00020 #if 0 00021 extern Serial pc; 00022 #define DPRINTF pc.printf 00023 #define DASSERT(cond) \ 00024 if (!(cond)) { \ 00025 pc.printf("%s:%d assertion failed! '%s\r\n"\ 00026 , __FILE__, __LINE__, #cond); \ 00027 } 00028 #else 00029 #define DPRINTF(...) 00030 #define DASSERT(...) 00031 #endif 00032 00033 // 1024*4*sizeof(byte) = 4Kbyte flash must (application) 00034 // 00035 // STM32L4xx flash area 00036 // bank address size page (virtual_sector) 00037 // 1 0x08000000 2k 0 00038 // 1 0x08000800 2k 1 00039 // 1 0x08001000 2k 2 00040 // 00041 // 1 0x0803C000 2k 120 11 00042 // 1 0x0803C800 2k 121 11 00043 // 1 0x0803D000 2k 122 11 00044 // 1 0x0803D800 2k 123 11 00045 // 1 0x0803E000 2k 124 11 <-- ここを11セクタの先頭とする 00046 // 1 0x0803E800 2k 125 11 00047 // 1 0x0803F000 2k 126 11 00048 // 1 0x0803F800 2k 127 11 <-- STM32L432KC ここまで (256KB) 00049 // 00050 // 1 0x0807C000 2k 248 11 00051 // 1 0x0807C800 2k 249 11 00052 // 1 0x0807D000 2k 250 11 00053 // 1 0x0807D800 2k 251 11 00054 // 1 0x0807E000 2k 252 11 00055 // 1 0x0807E800 2k 253 11 00056 // 1 0x0807F000 2k 254 11 00057 // 1 0x0807F800 2k 255 11 <-- 512KB 00058 #define REQ_SECTOR 11 00059 #define PAGE_SIZE 2048 00060 #define START_ADDRESS 0x0803E000 //11セクタの先頭アドレス 00061 00062 /*--- sector11 table ---*/ 00063 #if defined(STM32L431xx) || defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L442xx) || defined(STM32L443xx) 00064 static const SOF_SectorSpec_t _sec11_spec[] = { 00065 // page address size 00066 {124, START_ADDRESS+0x0000, PAGE_SIZE}, 00067 {125, START_ADDRESS+0x0800, PAGE_SIZE}, 00068 {126, START_ADDRESS+0x1000, PAGE_SIZE}, 00069 {127, START_ADDRESS+0x1800, PAGE_SIZE},//last page 00070 }; 00071 #elif defined(STM32L451xx) || defined(STM32L452xx) || defined(STM32L462xx) 00072 static const SOF_SectorSpec_t _sec11_spec_example[] = { 00073 {255, START_ADDRESS+0x0000, PAGE_SIZE},//last page 00074 }; 00075 #else 00076 #error "Not supported device" 00077 #endif 00078 00079 #define N_PAGE_SPEC (sizeof(_sec11_spec)/sizeof(_sec11_spec[0])) 00080 #define PAGE_NO(page) _sec11_spec[0].sec_no //top page 00081 #define PAGE_ADDR(page) _sec11_spec[0].sec_addr //top address 00082 00083 static const SOF_SectorSpec_t _sec11_dummy = { 00084 // ここ重要。ページの最後をセットすること 00085 REQ_SECTOR, START_ADDRESS, PAGE_SIZE*N_PAGE_SPEC 00086 }; 00087 00088 static uint64_t _data64w = 0; 00089 static uint64_t _data64b = 0; 00090 static int32_t _offset_addr_w = -1; 00091 static int32_t _offset_addr_b = -1; 00092 00093 static inline size_t handle_to_sector_index(SOF_DevHandle_t hdev) 00094 { 00095 DASSERT(hdev == REQ_SECTOR); 00096 return hdev; 00097 } 00098 00099 int SOF_dev_is_valid_sector(uint8_t sector_index) 00100 { 00101 return sector_index == REQ_SECTOR; 00102 } 00103 00104 const SOF_SectorSpec_t *SOF_dev_info_by_index(uint8_t sector_index) 00105 { 00106 DASSERT(SOF_dev_is_valid_sector(sector_index)); 00107 return &_sec11_dummy; 00108 } 00109 00110 const SOF_SectorSpec_t *SOF_dev_info(SOF_DevHandle_t hdev) 00111 { 00112 uint8_t sector_index = handle_to_sector_index(hdev); 00113 return SOF_dev_info_by_index(sector_index); 00114 } 00115 00116 SOF_DevHandle_t SOF_dev_open(uint8_t sector_index) 00117 { 00118 DPRINTF("SOF_dev_open %d\r\n", sector_index); 00119 _data64w = _data64b = 0; 00120 _offset_addr_w = -1; 00121 _offset_addr_b = -1; 00122 00123 DASSERT(sector_index == REQ_SECTOR); 00124 return (SOF_DevHandle_t)sector_index; 00125 } 00126 00127 void SOF_dev_close(SOF_DevHandle_t hdev) 00128 { 00129 uint8_t sector_index = handle_to_sector_index(hdev); 00130 DPRINTF("SOF_dev_close %d\r\n", sector_index); 00131 00132 //if write pending, must write 00133 // 00134 if(_offset_addr_w >= 0){ 00135 SOF_dev_write_word(sector_index, _offset_addr_w + 4, 0);//+4:write finish 00136 } 00137 if(_offset_addr_b >= 0){ 00138 SOF_dev_write_byte(sector_index, _offset_addr_b + 7, 0);//+7:write finish 00139 } 00140 } 00141 00142 uint8_t *SOF_dev_get_hw_addr(SOF_DevHandle_t hdev) 00143 { 00144 uint8_t sector_index = handle_to_sector_index(hdev); 00145 return (uint8_t *)PAGE_ADDR(sector_index); 00146 } 00147 00148 /*--- hdev is sector (11 only by application) ---*/ 00149 void SOF_dev_erase(SOF_DevHandle_t hdev) 00150 { 00151 uint8_t sector_index = handle_to_sector_index(hdev); 00152 FLASH_EraseInitTypeDef ei; 00153 uint32_t error = 0; 00154 00155 DPRINTF("FLASH_Erase_Page %d"DCRLF, PAGE_NO(sector_index)); 00156 HAL_FLASH_Unlock(); 00157 00158 ei.TypeErase = FLASH_TYPEERASE_PAGES; 00159 #if defined(STM32L431xx) || defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L442xx) || defined(STM32L443xx) ||\ 00160 defined(STM32L451xx) || defined(STM32L452xx) || defined(STM32L462xx) 00161 ei.Banks = FLASH_BANK_1;//bank1 only 00162 #else 00163 ei.Banks = FLASH_BANK_2; 00164 #endif 00165 ei.Page = PAGE_NO(secotr_index); //top page 00166 ei.NbPages = N_PAGE_SPEC; //number of page 00167 HAL_StatusTypeDef ret = HAL_FLASHEx_Erase(&ei, &error); 00168 00169 HAL_FLASH_Lock(); 00170 DPRINTF("FLASH_Erase_Page ret=%d, page=%d, n=%d\r\n", ret, ei.Page, ei.NbPages); 00171 } 00172 00173 uint64_t SOF_dev_read_dword(SOF_DevHandle_t hdev, uint32_t offset_addr) 00174 { 00175 uint8_t sector_index = handle_to_sector_index(hdev); 00176 uint32_t src = PAGE_ADDR(sector_index) + offset_addr; 00177 uint64_t ret = *(volatile uint64_t*)src; 00178 return ret; 00179 } 00180 00181 int SOF_dev_write_word(SOF_DevHandle_t hdev, uint32_t offset_addr, uint32_t data) 00182 { 00183 uint8_t sector_index = handle_to_sector_index(hdev); 00184 uint32_t dst = PAGE_ADDR(sector_index) + offset_addr; 00185 DPRINTF("SOF_dev_write_word dst=%08X ofs=%d, ", dst, offset_addr); 00186 // +0 +4 +8 00187 // +------+------+ 00188 // |DWORDH|DWORDL| 00189 // +------+------+ 00190 if(offset_addr % 8 == 0){//address 8 multiple 00191 _data64w |= data; 00192 _offset_addr_w = offset_addr; 00193 DPRINTF("data=%08X\r\n", data); 00194 return 0;//next waiting 00195 } else if(offset_addr % 4 == 0){//address 4 multiple 00196 _data64w |= ((uint64_t)data << 32); 00197 dst = PAGE_ADDR(sector_index) + _offset_addr_w; 00198 DPRINTF("data=%08X\r\n", data); 00199 } 00200 00201 DASSERT((offset_addr % sizeof(uint32_t)) == 0);//required address 4 multiple 00202 HAL_FLASH_Unlock(); 00203 00204 if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, dst, _data64w) != HAL_OK) { 00205 DPRINTF("FLASH_ProgramWord failed: %#x"DCRLF, dst); 00206 HAL_FLASH_Lock(); 00207 return -1; 00208 } 00209 00210 HAL_FLASH_Lock(); 00211 00212 /*--- read back ---*/ 00213 if (_data64w != SOF_dev_read_dword(hdev, _offset_addr_w)) { 00214 DPRINTF("addr=%X %#04X %#04X"DCRLF, dst, data, SOF_dev_read_dword(hdev, _offset_addr_w)); 00215 return -1; 00216 } 00217 00218 _data64w = 0;//finish 00219 _offset_addr_w = -1;//finish 00220 00221 return 0; 00222 } 00223 00224 uint32_t SOF_dev_read_word(SOF_DevHandle_t hdev, uint32_t offset_addr) 00225 { 00226 uint8_t sector_index = handle_to_sector_index(hdev); 00227 uint32_t src = PAGE_ADDR(sector_index) + offset_addr; 00228 DASSERT((offset_addr % sizeof(uint32_t)) == 0);//required address 4 multiple 00229 00230 uint32_t ret = *(volatile uint32_t*)src; 00231 DPRINTF("SOF_dev_read_word src=%08X, ret=%08X\r\n", src, ret); 00232 return ret; 00233 } 00234 00235 int SOF_dev_write_byte(SOF_DevHandle_t hdev, uint32_t offset_addr, uint8_t data) 00236 { 00237 uint8_t sector_index = handle_to_sector_index(hdev); 00238 uint32_t dst = PAGE_ADDR(sector_index) + offset_addr; 00239 DPRINTF("SOF_dev_write_byte dst=%08X ofs=%d, ", dst, offset_addr); 00240 // +0 +1 +2 +3 +4 +8 00241 // +------+------+------+------+---- +------+ 00242 // |BYTE1 |BYTE2 |BYTE3 |BYTE4 | |BYTE8 | 00243 // +------+------+------+------+---- +------+ 00244 if(offset_addr % 8 == 0){//address 4 multiple 00245 _data64b |= ((uint64_t)data << (64-64)); 00246 _offset_addr_b = offset_addr; 00247 DPRINTF("data=%02X\r\n", data); 00248 return 0;//next waiting 00249 } else if(offset_addr % 8 == 1){ 00250 _data64b |= ((uint64_t)data << (64-56)); 00251 DPRINTF("data=%02X\r\n", data); 00252 return 0; 00253 } else if(offset_addr % 8 == 2){ 00254 _data64b |= ((uint64_t)data << (64-48)); 00255 DPRINTF("data=%02X\r\n", data); 00256 return 0; 00257 } else if(offset_addr % 8 == 3){ 00258 _data64b |= ((uint64_t)data << (64-40)); 00259 DPRINTF("data=%02X\r\n", data); 00260 return 0; 00261 } else if(offset_addr % 8 == 4){ 00262 _data64b |= ((uint64_t)data << (64-32)); 00263 DPRINTF("data=%02X\r\n", data); 00264 return 0; 00265 } else if(offset_addr % 8 == 5){ 00266 _data64b |= ((uint64_t)data << (64-24)); 00267 DPRINTF("data=%02X\r\n", data); 00268 return 0; 00269 } else if(offset_addr % 8 == 6){ 00270 _data64b |= ((uint64_t)data << (64-16)); 00271 DPRINTF("data=%02X\r\n", data); 00272 return 0; 00273 } else if(offset_addr % 8 == 7){ 00274 _data64b |= ((uint64_t)data << (64-8)); 00275 dst = PAGE_ADDR(sector_index) + _offset_addr_b; 00276 DPRINTF("data=%02X\r\n", data); 00277 } 00278 00279 HAL_FLASH_Unlock(); 00280 00281 if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, dst, _data64b) != HAL_OK) { 00282 DPRINTF("FLASH_ProgramByte failed: %#x"DCRLF, dst); 00283 HAL_FLASH_Lock(); 00284 return -1; 00285 } 00286 00287 HAL_FLASH_Lock(); 00288 00289 /*--- read back ---*/ 00290 if (_data64b != SOF_dev_read_dword(hdev, _offset_addr_b)) { 00291 DPRINTF("addr=%X %#04X %#04X"DCRLF, dst, data, SOF_dev_read_dword(hdev, _offset_addr_b)); 00292 return -1; 00293 } 00294 00295 _data64b = 0;//finish 00296 _offset_addr_b = -1;//finish 00297 00298 return 0; 00299 } 00300 00301 uint8_t SOF_dev_read_byte(SOF_DevHandle_t hdev, uint32_t offset_addr) 00302 { 00303 uint8_t sector_index = handle_to_sector_index(hdev); 00304 uint32_t src = PAGE_ADDR(sector_index) + offset_addr; 00305 uint8_t ret = *(volatile uint8_t*)src; 00306 DPRINTF("SOF_dev_read_byte src=%08X, ret=%02X\r\n", src, ret); 00307 return ret; 00308 } 00309 00310 00311
Generated on Fri Nov 18 2022 07:19:36 by
1.7.2