flash_at91.c
Go to the documentation of this file.
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 reg32_t *fcr, *fsr; 00079 00080 #if CPU_ARM_AT91SAM7S512 || CPU_ARM_AT91SAM7X512 00081 if (page >= (FLASH_MEM_SIZE / FLASH_PAGE_SIZE_BYTES / 2)) 00082 { 00083 fcr = &MC_FCR1; 00084 fsr = &MC_FSR1; 00085 page &= 0x3FF; 00086 } 00087 else 00088 #endif 00089 { 00090 fcr = &MC_FCR; 00091 fsr = &MC_FSR; 00092 } 00093 00094 // Send the 'write page' command 00095 *fcr = MC_KEY | MC_FCMD_WP | (MC_PAGEN_MASK & (page << 8)); 00096 00097 // Wait for the end of command 00098 while(!(*fsr & BV(MC_FRDY))) 00099 { 00100 //NOP; 00101 } 00102 } 00103 00104 00111 INLINE void flash_sendWRcmd(uint32_t page) 00112 { 00113 cpu_flags_t flags; 00114 00115 LOG_INFO("Writing page %ld...\n", page); 00116 00117 IRQ_SAVE_DISABLE(flags); 00118 write_page(page); 00119 00120 IRQ_RESTORE(flags); 00121 LOG_INFO("Done\n"); 00122 } 00123 00128 static bool flash_getStatus(struct KBlock *blk) 00129 { 00130 Flash *fls = FLASH_CAST(blk); 00131 /* 00132 * This bit is set to one if an invalid command and/or a bad keywords was/were 00133 * written in the Flash Command Register. 00134 */ 00135 if(MC_FSR & BV(MC_PROGE)) 00136 { 00137 fls->hw->status |= FLASH_WR_ERR; 00138 LOG_ERR("flash not erased..\n"); 00139 return false; 00140 } 00141 00142 /* 00143 * This bit is set to one if we programming of at least one locked lock 00144 * region. 00145 */ 00146 if(MC_FSR & BV(MC_LOCKE)) 00147 { 00148 fls->hw->status |= FLASH_WR_PROTECT; 00149 LOG_ERR("wr protect..\n"); 00150 return false; 00151 } 00152 #if CPU_ARM_AT91SAM7X512 || CPU_ARM_AT91SAM7S512 00153 /* Check also EFC1 for larger devices */ 00154 if(MC_FSR1 & BV(MC_PROGE)) 00155 { 00156 fls->hw->status |= FLASH_WR_ERR; 00157 LOG_ERR("flash not erased..\n"); 00158 return false; 00159 } 00160 00161 if(MC_FSR1 & BV(MC_LOCKE)) 00162 { 00163 fls->hw->status |= FLASH_WR_PROTECT; 00164 LOG_ERR("wr protect..\n"); 00165 return false; 00166 } 00167 00168 #endif 00169 00170 return true; 00171 } 00172 00173 static size_t at91_flash_readDirect(struct KBlock *blk, block_idx_t idx, void *buf, size_t offset, size_t size) 00174 { 00175 memcpy(buf, (void *)(idx * blk->blk_size + FLASH_BASE + offset), size); 00176 return size; 00177 } 00178 00179 static size_t at91_flash_writeDirect(struct KBlock *blk, block_idx_t idx, const void *_buf, size_t offset, size_t size) 00180 { 00181 ASSERT(offset == 0); 00182 ASSERT(size == blk->blk_size); 00183 00184 uint32_t *addr = (uint32_t *)(idx * blk->blk_size + FLASH_BASE); 00185 const uint8_t *buf = (const uint8_t *)_buf; 00186 00187 while (size) 00188 { 00189 uint32_t data = (*(buf + 3) << 24) | 00190 (*(buf + 2) << 16) | 00191 (*(buf + 1) << 8) | 00192 *buf; 00193 *addr = data; 00194 00195 size -= 4; 00196 buf += 4; 00197 addr++; 00198 } 00199 00200 flash_sendWRcmd(idx); 00201 00202 if (!flash_getStatus(blk)) 00203 return 0; 00204 00205 return blk->blk_size; 00206 } 00207 00208 00209 static int at91_flash_error(struct KBlock *blk) 00210 { 00211 Flash *fls = FLASH_CAST(blk); 00212 return fls->hw->status; 00213 } 00214 00215 static void at91_flash_clearerror(struct KBlock *blk) 00216 { 00217 Flash *fls = FLASH_CAST(blk); 00218 fls->hw->status = 0; 00219 } 00220 00221 static const KBlockVTable flash_at91_buffered_vt = 00222 { 00223 .readDirect = at91_flash_readDirect, 00224 .writeDirect = at91_flash_writeDirect, 00225 00226 .readBuf = kblock_swReadBuf, 00227 .writeBuf = kblock_swWriteBuf, 00228 .load = kblock_swLoad, 00229 .store = kblock_swStore, 00230 00231 .error = at91_flash_error, 00232 .clearerr = at91_flash_clearerror, 00233 }; 00234 00235 static const KBlockVTable flash_at91_unbuffered_vt = 00236 { 00237 .readDirect = at91_flash_readDirect, 00238 .writeDirect = at91_flash_writeDirect, 00239 00240 .error = at91_flash_error, 00241 .clearerr = at91_flash_clearerror, 00242 }; 00243 00244 static struct FlashHardware flash_at91_hw; 00245 static uint8_t flash_buf[FLASH_PAGE_SIZE_BYTES]; 00246 00247 static void common_init(Flash *fls) 00248 { 00249 memset(fls, 0, sizeof(*fls)); 00250 DB(fls->blk.priv.type = KBT_FLASH); 00251 00252 fls->hw = &flash_at91_hw; 00253 00254 fls->blk.blk_size = FLASH_PAGE_SIZE_BYTES; 00255 fls->blk.blk_cnt = FLASH_MEM_SIZE / FLASH_PAGE_SIZE_BYTES; 00256 } 00257 00258 void flash_hw_init(Flash *fls, UNUSED_ARG(int, flags)) 00259 { 00260 common_init(fls); 00261 fls->blk.priv.vt = &flash_at91_buffered_vt; 00262 fls->blk.priv.flags |= KB_BUFFERED | KB_PARTIAL_WRITE; 00263 fls->blk.priv.buf = flash_buf; 00264 00265 /* Load the first block in the cache */ 00266 memcpy(fls->blk.priv.buf, (void *)(FLASH_BASE), fls->blk.blk_size); 00267 } 00268 00269 void flash_hw_initUnbuffered(Flash *fls, UNUSED_ARG(int, flags)) 00270 { 00271 common_init(fls); 00272 fls->blk.priv.vt = &flash_at91_unbuffered_vt; 00273 } 00274
![(please configure the [header_logo] section in trac.ini)](/chrome/site/bertos_logo.png)