BeRTOS
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 // 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 }