BeRTOS
flash_lm3s.c
Go to the documentation of this file.
00001 
00038 #include "flash_lm3s.h"
00039 #include "cfg/cfg_emb_flash.h"
00040 
00041 // Define log settings for cfg/log.h
00042 #define LOG_LEVEL    CONFIG_FLASH_EMB_LOG_LEVEL
00043 #define LOG_FORMAT   CONFIG_FLASH_EMB_LOG_FORMAT
00044 #include <cfg/log.h>
00045 #include <cfg/macros.h>
00046 
00047 #include <io/kblock.h>
00048 
00049 #include <drv/timer.h>
00050 #include <drv/flash.h>
00051 
00052 #include <cpu/power.h> /* cpu_relax() */
00053 #include <cpu/types.h>
00054 
00055 #include <string.h> /* memcpy() */
00056 
00057 struct FlashHardware
00058 {
00059     int status;
00060 };
00061 
00062 static bool flash_wait(struct KBlock *blk, uint32_t event)
00063 {
00064     Flash *fls = FLASH_CAST(blk);
00065     ticks_t start = timer_clock();
00066     while (true)
00067     {
00068         if (!(FLASH_FMC_R & event))
00069             break;
00070 
00071         if (FLASH_FCRIS_R & FLASH_FCRIS_ARIS)
00072         {
00073             fls->hw->status |= FLASH_WR_PROTECT;
00074             LOG_ERR("wr protect..\n");
00075             return false;
00076         }
00077 
00078         if (timer_clock() - start > ms_to_ticks(CONFIG_FLASH_WR_TIMEOUT))
00079         {
00080             fls->hw->status |= FLASH_WR_TIMEOUT;
00081             LOG_ERR("Timeout..\n");
00082             return false;
00083         }
00084 
00085         cpu_relax();
00086     }
00087 
00088     return true;
00089 }
00090 
00091 static int lm3s_erasePage(struct KBlock *blk, uint32_t addr)
00092 {
00093     FLASH_FCMISC_R = FLASH_FCMISC_AMISC;
00094 
00095     FLASH_FMA_R = (volatile uint32_t)addr;
00096     FLASH_FMC_R = FLASH_FMC_WRKEY | FLASH_FMC_ERASE;
00097 
00098     return flash_wait(blk, FLASH_FMC_ERASE);
00099 }
00100 
00101 static int lm3s_writeWord(struct KBlock *blk, uint32_t addr, uint32_t data)
00102 {
00103     FLASH_FCMISC_R = FLASH_FCMISC_AMISC;
00104 
00105     FLASH_FMA_R = (volatile uint32_t)addr;
00106     FLASH_FMD_R = (volatile uint32_t)data;
00107     FLASH_FMC_R = FLASH_FMC_WRKEY | FLASH_FMC_WRITE;
00108 
00109     return flash_wait(blk, FLASH_FMC_WRITE);
00110 }
00111 
00112 static size_t lm3s_flash_readDirect(struct KBlock *blk, block_idx_t idx, void *buf, size_t offset, size_t size)
00113 {
00114     memcpy(buf, (void *)(idx * blk->blk_size + offset), size);
00115     return size;
00116 }
00117 
00118 static size_t lm3s_flash_writeDirect(struct KBlock *blk, block_idx_t idx, const void *_buf, size_t offset, size_t size)
00119 {
00120     (void)offset;
00121     ASSERT(offset == 0);
00122     ASSERT(size == blk->blk_size);
00123 
00124     if (!lm3s_erasePage(blk, (idx * blk->blk_size)))
00125         return 0;
00126 
00127     uint32_t addr = idx * blk->blk_size;
00128     const uint8_t *buf = (const uint8_t *)_buf;
00129 
00130     while (size)
00131     {
00132         uint32_t data = (*(buf + 3) << 24) |
00133                         (*(buf + 2) << 16) |
00134                         (*(buf + 1) << 8)  |
00135                         *buf;
00136 
00137         if (!lm3s_writeWord(blk, addr, data))
00138             return 0;
00139 
00140         size -= 4;
00141         buf += 4;
00142         addr += 4;
00143     }
00144 
00145     return blk->blk_size;
00146 }
00147 
00148 static int lm3s_flash_error(struct KBlock *blk)
00149 {
00150     Flash *fls = FLASH_CAST(blk);
00151     return fls->hw->status;
00152 }
00153 
00154 static void lm3s_flash_clearerror(struct KBlock *blk)
00155 {
00156     Flash *fls = FLASH_CAST(blk);
00157     fls->hw->status = 0;
00158 }
00159 
00160 static const KBlockVTable flash_lm3s_buffered_vt =
00161 {
00162     .readDirect = lm3s_flash_readDirect,
00163     .writeDirect = lm3s_flash_writeDirect,
00164 
00165     .readBuf = kblock_swReadBuf,
00166     .writeBuf = kblock_swWriteBuf,
00167     .load = kblock_swLoad,
00168     .store = kblock_swStore,
00169 
00170     .close = kblock_swClose,
00171 
00172     .error = lm3s_flash_error,
00173     .clearerr = lm3s_flash_clearerror,
00174 };
00175 
00176 static const KBlockVTable flash_lm3s_unbuffered_vt =
00177 {
00178     .readDirect = lm3s_flash_readDirect,
00179     .writeDirect = lm3s_flash_writeDirect,
00180 
00181     .close = kblock_swClose,
00182 
00183     .error = lm3s_flash_error,
00184     .clearerr = lm3s_flash_clearerror,
00185 };
00186 
00187 static struct FlashHardware flash_lm3s_hw;
00188 static uint8_t flash_buf[FLASH_PAGE_SIZE];
00189 
00190 static void common_init(Flash *fls)
00191 {
00192     memset(fls, 0, sizeof(*fls));
00193     DB(fls->blk.priv.type = KBT_FLASH);
00194 
00195     FLASH_USECRL_R = CPU_FREQ / 1000000 - 1;
00196 
00197     fls->hw = &flash_lm3s_hw;
00198 
00199     fls->blk.blk_size = FLASH_PAGE_SIZE;
00200     fls->blk.blk_cnt =  FLASH_SIZE / FLASH_PAGE_SIZE;
00201 }
00202 
00203 
00204 void flash_hw_init(Flash *fls, UNUSED_ARG(int, flags))
00205 {
00206     common_init(fls);
00207     fls->blk.priv.vt = &flash_lm3s_buffered_vt;
00208     fls->blk.priv.flags |= KB_BUFFERED | KB_PARTIAL_WRITE;
00209     fls->blk.priv.buf = flash_buf;
00210 
00211     /* Load the first block in the cache */
00212     void *flash_start = 0x0;
00213     memcpy(fls->blk.priv.buf, flash_start, fls->blk.blk_size);
00214 }
00215 
00216 void flash_hw_initUnbuffered(Flash *fls, UNUSED_ARG(int, flags))
00217 {
00218     common_init(fls);
00219     fls->blk.priv.vt = &flash_lm3s_unbuffered_vt;
00220 }
00221 
00222 
00223