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