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
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>
00053 #include <cpu/types.h>
00054
00055 #include <string.h>
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
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