BeRTOS
|
00001 00038 #include "flash_stm32.h" 00039 00040 #include "cfg/cfg_emb_flash.h" 00041 00042 // Define log settings for cfg/log.h 00043 #define LOG_LEVEL CONFIG_FLASH_EMB_LOG_LEVEL 00044 #define LOG_FORMAT CONFIG_FLASH_EMB_LOG_FORMAT 00045 #include <cfg/log.h> 00046 00047 #include <drv/timer.h> 00048 #include <drv/flash.h> 00049 00050 #include <cpu/power.h> 00051 #include <cpu/detect.h> 00052 00053 #include <io/stm32.h> 00054 00055 #include <string.h> 00056 00057 #define EMB_FLASH ((struct stm32_flash*)FLASH_R_BASE) 00058 00059 struct FlashHardware 00060 { 00061 uint8_t status; 00062 }; 00063 00064 static bool flash_wait(struct KBlock *blk) 00065 { 00066 Flash *fls = FLASH_CAST(blk); 00067 ticks_t start = timer_clock(); 00068 while (true) 00069 { 00070 cpu_relax(); 00071 if (!(EMB_FLASH->SR & FLASH_FLAG_BSY)) 00072 break; 00073 00074 if (EMB_FLASH->SR & FLASH_FLAG_PGERR) 00075 { 00076 fls->hw->status |= FLASH_NOT_ERASED; 00077 LOG_ERR("flash not erased..\n"); 00078 return false; 00079 } 00080 00081 if (EMB_FLASH->SR & FLASH_FLAG_WRPRTERR) 00082 { 00083 fls->hw->status |= FLASH_WR_PROTECT; 00084 LOG_ERR("wr protect..\n"); 00085 return false; 00086 } 00087 00088 if (timer_clock() - start > ms_to_ticks(CONFIG_FLASH_WR_TIMEOUT)) 00089 { 00090 fls->hw->status |= FLASH_WR_TIMEOUT; 00091 LOG_ERR("Timeout..\n"); 00092 return false; 00093 } 00094 } 00095 00096 return true; 00097 } 00098 00099 static bool stm32_erasePage(struct KBlock *blk, uint32_t page_add) 00100 { 00101 00102 EMB_FLASH->CR |= CR_PER_SET; 00103 EMB_FLASH->AR = page_add; 00104 EMB_FLASH->CR |= CR_STRT_SET; 00105 00106 if (!flash_wait(blk)) 00107 return false; 00108 00109 EMB_FLASH->CR &= CR_PER_RESET; 00110 00111 return true; 00112 } 00113 00114 #if 0 00115 // not used for now 00116 static bool stm32_eraseAll(struct KBlock *blk) 00117 { 00118 EMB_FLASH->CR |= CR_MER_SET; 00119 EMB_FLASH->CR |= CR_STRT_SET; 00120 00121 if (!flash_wait(blk)) 00122 return false; 00123 00124 EMB_FLASH->CR &= CR_MER_RESET; 00125 00126 return true; 00127 } 00128 #endif 00129 00130 static int stm32_flash_error(struct KBlock *blk) 00131 { 00132 Flash *fls = FLASH_CAST(blk); 00133 return fls->hw->status; 00134 } 00135 00136 static void stm32_flash_clearerror(struct KBlock *blk) 00137 { 00138 Flash *fls = FLASH_CAST(blk); 00139 fls->hw->status = 0; 00140 } 00141 00142 static size_t stm32_flash_readDirect(struct KBlock *blk, block_idx_t idx, void *buf, size_t offset, size_t size) 00143 { 00144 memcpy(buf, (void *)(idx * blk->blk_size + offset), size); 00145 return size; 00146 } 00147 00148 00149 INLINE bool stm32_writeWord(struct KBlock *blk, uint32_t addr, uint16_t data) 00150 { 00151 ASSERT(!(addr % 2)); 00152 00153 EMB_FLASH->CR |= CR_PG_SET; 00154 00155 *(reg16_t *)addr = data; 00156 00157 if (!flash_wait(blk)) 00158 return false; 00159 00160 EMB_FLASH->CR &= CR_PG_RESET; 00161 00162 return true; 00163 } 00164 00165 static size_t stm32_flash_writeDirect(struct KBlock *blk, block_idx_t idx, const void *_buf, size_t offset, size_t size) 00166 { 00167 ASSERT(offset == 0); 00168 ASSERT(size == blk->blk_size); 00169 00170 if (!stm32_erasePage(blk, (idx * blk->blk_size))) 00171 return 0; 00172 00173 uint32_t addr = idx * blk->blk_size; 00174 const uint8_t *buf = (const uint8_t *)_buf; 00175 00176 while (size) 00177 { 00178 uint16_t data = (*(buf + 1) << 8) | *buf; 00179 if (!stm32_writeWord(blk, addr, data)) 00180 return 0; 00181 00182 buf += 2; 00183 size -= 2; 00184 addr += 2; 00185 } 00186 00187 return blk->blk_size; 00188 } 00189 00190 static const KBlockVTable flash_stm32_buffered_vt = 00191 { 00192 .readDirect = stm32_flash_readDirect, 00193 .writeDirect = stm32_flash_writeDirect, 00194 00195 .readBuf = kblock_swReadBuf, 00196 .writeBuf = kblock_swWriteBuf, 00197 .load = kblock_swLoad, 00198 .store = kblock_swStore, 00199 00200 .close = kblock_swClose, 00201 00202 .error = stm32_flash_error, 00203 .clearerr = stm32_flash_clearerror, 00204 }; 00205 00206 static const KBlockVTable flash_stm32_unbuffered_vt = 00207 { 00208 .readDirect = stm32_flash_readDirect, 00209 .writeDirect = stm32_flash_writeDirect, 00210 00211 .close = kblock_swClose, 00212 00213 .error = stm32_flash_error, 00214 .clearerr = stm32_flash_clearerror, 00215 }; 00216 00217 static struct FlashHardware flash_stm32_hw; 00218 static uint8_t flash_buf[FLASH_PAGE_SIZE]; 00219 00220 static void common_init(Flash *fls) 00221 { 00222 memset(fls, 0, sizeof(*fls)); 00223 DB(fls->blk.priv.type = KBT_FLASH); 00224 00225 fls->hw = &flash_stm32_hw; 00226 00227 fls->blk.blk_size = FLASH_PAGE_SIZE; 00228 fls->blk.blk_cnt = (F_SIZE * 1024) / FLASH_PAGE_SIZE; 00229 00230 /* Unlock flash memory for the FPEC Access */ 00231 EMB_FLASH->KEYR = FLASH_KEY1; 00232 EMB_FLASH->KEYR = FLASH_KEY2; 00233 } 00234 00235 00236 void flash_hw_init(Flash *fls, UNUSED_ARG(int, flags)) 00237 { 00238 common_init(fls); 00239 fls->blk.priv.vt = &flash_stm32_buffered_vt; 00240 fls->blk.priv.flags |= KB_BUFFERED | KB_PARTIAL_WRITE; 00241 fls->blk.priv.buf = flash_buf; 00242 00243 /* Load the first block in the cache */ 00244 void *flash_start = 0x0; 00245 memcpy(fls->blk.priv.buf, flash_start, fls->blk.blk_size); 00246 } 00247 00248 void flash_hw_initUnbuffered(Flash *fls, UNUSED_ARG(int, flags)) 00249 { 00250 common_init(fls); 00251 fls->blk.priv.vt = &flash_stm32_unbuffered_vt; 00252 }