flash_stm32.c
Go to the documentation of this file.00001
00038 #include "flash_stm32.h"
00039
00040 #include "cfg/cfg_emb_flash.h"
00041
00042
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
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
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
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 }