BeRTOS
|
00001 00040 #include "flash_at91.h" 00041 00042 #include "cfg/cfg_emb_flash.h" 00043 #include <cfg/macros.h> 00044 00045 // Define log settings for cfg/log.h 00046 #define LOG_LEVEL CONFIG_FLASH_EMB_LOG_LEVEL 00047 #define LOG_FORMAT CONFIG_FLASH_EMB_LOG_FORMAT 00048 #include <cfg/log.h> 00049 00050 #include <cpu/irq.h> 00051 #include <cpu/attr.h> 00052 #include <cpu/power.h> 00053 00054 #include <io/kfile.h> 00055 #include <io/kblock.h> 00056 #include <io/arm.h> 00057 00058 #include <drv/timer.h> 00059 #include <drv/flash.h> 00060 00061 #include <string.h> 00062 00063 struct FlashHardware 00064 { 00065 uint8_t status; 00066 }; 00067 00068 00076 RAM_FUNC NOINLINE static void write_page(uint32_t page) 00077 { 00078 // Send the 'write page' command 00079 MC_FCR = MC_KEY | MC_FCMD_WP | (MC_PAGEN_MASK & (page << 8)); 00080 00081 // Wait for the end of command 00082 while(!(MC_FSR & BV(MC_FRDY))) 00083 { 00084 //NOP; 00085 } 00086 } 00087 00088 00095 INLINE void flash_sendWRcmd(uint32_t page) 00096 { 00097 cpu_flags_t flags; 00098 00099 LOG_INFO("Writing page %ld...\n", page); 00100 00101 IRQ_SAVE_DISABLE(flags); 00102 write_page(page); 00103 00104 IRQ_RESTORE(flags); 00105 LOG_INFO("Done\n"); 00106 } 00107 00112 static bool flash_getStatus(struct KBlock *blk) 00113 { 00114 Flash *fls = FLASH_CAST(blk); 00115 /* 00116 * This bit is set to one if an invalid command and/or a bad keywords was/were 00117 * written in the Flash Command Register. 00118 */ 00119 if(MC_FSR & BV(MC_PROGE)) 00120 { 00121 fls->hw->status |= FLASH_WR_ERR; 00122 LOG_ERR("flash not erased..\n"); 00123 return false; 00124 } 00125 00126 /* 00127 * This bit is set to one if we programming of at least one locked lock 00128 * region. 00129 */ 00130 if(MC_FSR & BV(MC_LOCKE)) 00131 { 00132 fls->hw->status |= FLASH_WR_PROTECT; 00133 LOG_ERR("wr protect..\n"); 00134 return false; 00135 } 00136 00137 return true; 00138 } 00139 00140 static size_t at91_flash_readDirect(struct KBlock *blk, block_idx_t idx, void *buf, size_t offset, size_t size) 00141 { 00142 memcpy(buf, (void *)(idx * blk->blk_size + FLASH_BASE + offset), size); 00143 return size; 00144 } 00145 00146 static size_t at91_flash_writeDirect(struct KBlock *blk, block_idx_t idx, const void *_buf, size_t offset, size_t size) 00147 { 00148 ASSERT(offset == 0); 00149 ASSERT(size == blk->blk_size); 00150 00151 uint32_t *addr = (uint32_t *)(idx * blk->blk_size + FLASH_BASE); 00152 const uint8_t *buf = (const uint8_t *)_buf; 00153 00154 while (size) 00155 { 00156 uint32_t data = (*(buf + 3) << 24) | 00157 (*(buf + 2) << 16) | 00158 (*(buf + 1) << 8) | 00159 *buf; 00160 *addr = data; 00161 00162 size -= 4; 00163 buf += 4; 00164 addr++; 00165 } 00166 00167 flash_sendWRcmd(idx); 00168 00169 if (!flash_getStatus(blk)) 00170 return 0; 00171 00172 return blk->blk_size; 00173 } 00174 00175 00176 static int at91_flash_error(struct KBlock *blk) 00177 { 00178 Flash *fls = FLASH_CAST(blk); 00179 return fls->hw->status; 00180 } 00181 00182 static void at91_flash_clearerror(struct KBlock *blk) 00183 { 00184 Flash *fls = FLASH_CAST(blk); 00185 fls->hw->status = 0; 00186 } 00187 00188 static const KBlockVTable flash_at91_buffered_vt = 00189 { 00190 .readDirect = at91_flash_readDirect, 00191 .writeDirect = at91_flash_writeDirect, 00192 00193 .readBuf = kblock_swReadBuf, 00194 .writeBuf = kblock_swWriteBuf, 00195 .load = kblock_swLoad, 00196 .store = kblock_swStore, 00197 00198 .error = at91_flash_error, 00199 .clearerr = at91_flash_clearerror, 00200 }; 00201 00202 static const KBlockVTable flash_at91_unbuffered_vt = 00203 { 00204 .readDirect = at91_flash_readDirect, 00205 .writeDirect = at91_flash_writeDirect, 00206 00207 .error = at91_flash_error, 00208 .clearerr = at91_flash_clearerror, 00209 }; 00210 00211 static struct FlashHardware flash_at91_hw; 00212 static uint8_t flash_buf[FLASH_PAGE_SIZE_BYTES]; 00213 00214 static void common_init(Flash *fls) 00215 { 00216 memset(fls, 0, sizeof(*fls)); 00217 DB(fls->blk.priv.type = KBT_FLASH); 00218 00219 fls->hw = &flash_at91_hw; 00220 00221 fls->blk.blk_size = FLASH_PAGE_SIZE_BYTES; 00222 fls->blk.blk_cnt = FLASH_MEM_SIZE / FLASH_PAGE_SIZE_BYTES; 00223 } 00224 00225 void flash_hw_init(Flash *fls, UNUSED_ARG(int, flags)) 00226 { 00227 common_init(fls); 00228 fls->blk.priv.vt = &flash_at91_buffered_vt; 00229 fls->blk.priv.flags |= KB_BUFFERED | KB_PARTIAL_WRITE; 00230 fls->blk.priv.buf = flash_buf; 00231 00232 /* Load the first block in the cache */ 00233 memcpy(fls->blk.priv.buf, (void *)(FLASH_BASE), fls->blk.blk_size); 00234 } 00235 00236 void flash_hw_initUnbuffered(Flash *fls, UNUSED_ARG(int, flags)) 00237 { 00238 common_init(fls); 00239 fls->blk.priv.vt = &flash_at91_unbuffered_vt; 00240 } 00241