flash_sam3.c
Go to the documentation of this file.
00001 00040 #include "flash_sam3.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/cm3.h> 00057 00058 #include <drv/timer.h> 00059 #include <drv/flash.h> 00060 00061 #include <string.h> 00062 00063 00064 struct FlashHardware 00065 { 00066 uint8_t status; 00067 }; 00068 00069 00077 RAM_FUNC NOINLINE static void write_page_bank(uint32_t page) 00078 { 00079 // Send the 'write page' command 00080 EEFC0_FCR = EEFC_FCR_FKEY | EFC_FCR_FCMD_EWP | EEFC_FCR_FARG(page); 00081 00082 // Wait for the end of command 00083 while(!(EEFC0_FSR & BV(EEFC_FSR_FRDY))) 00084 { 00085 //NOP; 00086 } 00087 } 00088 00089 #if FLASH_BANKS_NUM > 1 00090 RAM_FUNC NOINLINE static void write_page_bank1(uint32_t page) 00091 { 00092 // Send the 'write page' command 00093 EEFC1_FCR = EEFC_FCR_FKEY | EFC_FCR_FCMD_EWP | EEFC_FCR_FARG(page); 00094 00095 // Wait for the end of command 00096 while(!(EEFC1_FSR & BV(EEFC_FSR_FRDY))) 00097 { 00098 //NOP; 00099 } 00100 } 00101 #endif 00102 00103 00110 INLINE void flash_sendWRcmd(uint32_t page) 00111 { 00112 cpu_flags_t flags; 00113 00114 #if FLASH_BANKS_NUM > 1 00115 if (page >= FLASH_PAGES_FOR_BANK) 00116 { 00117 page &= 0x3FF; 00118 LOG_INFO("Writing page %ld on bank 1\n", page); 00119 00120 IRQ_SAVE_DISABLE(flags); 00121 write_page_bank1(page); 00122 IRQ_RESTORE(flags); 00123 } 00124 else 00125 #endif 00126 { 00127 LOG_INFO("Writing page %ld on bank 0\n", page); 00128 00129 IRQ_SAVE_DISABLE(flags); 00130 write_page_bank(page); 00131 IRQ_RESTORE(flags); 00132 } 00133 00134 00135 LOG_INFO("Done\n"); 00136 } 00137 00138 static size_t sam3_flash_readDirect(struct KBlock *blk, block_idx_t idx, void *buf, size_t offset, size_t size) 00139 { 00140 memcpy(buf, (void *)(idx * blk->blk_size + FLASH_BASE + offset), size); 00141 return size; 00142 } 00143 00144 static size_t sam3_flash_writeDirect(struct KBlock *blk, block_idx_t idx, const void *_buf, size_t offset, size_t size) 00145 { 00146 ASSERT(offset == 0); 00147 ASSERT(size == blk->blk_size); 00148 00149 uint32_t *addr = (uint32_t *)(idx * blk->blk_size + FLASH_BASE); 00150 const uint8_t *buf = (const uint8_t *)_buf; 00151 00152 while (size) 00153 { 00154 uint32_t data = (*(buf + 3) << 24) | 00155 (*(buf + 2) << 16) | 00156 (*(buf + 1) << 8) | 00157 *buf; 00158 *addr = data; 00159 00160 size -= 4; 00161 buf += 4; 00162 addr++; 00163 } 00164 00165 flash_sendWRcmd(idx); 00166 00167 Flash *fls = FLASH_CAST(blk); 00168 uint32_t status = (uint32_t)&EEFC0_FSR; 00169 #if FLASH_BANKS_NUM > 1 00170 if (idx > FLASH_PAGES_FOR_BANK) 00171 { 00172 status = (uint32_t)&EEFC1_FSR; 00173 } 00174 #endif 00175 00176 if(status & BV(EEFC_FSR_FCMDE)) 00177 { 00178 fls->hw->status |= FLASH_WR_ERR; 00179 LOG_ERR("flash not erased..\n"); 00180 return 0; 00181 } 00182 00183 if(status & BV(EEFC_FSR_FLOCKE)) 00184 { 00185 fls->hw->status |= FLASH_WR_PROTECT; 00186 LOG_ERR("wr protect..\n"); 00187 return 0; 00188 } 00189 00190 return blk->blk_size; 00191 } 00192 00193 00194 static int sam3_flash_error(struct KBlock *blk) 00195 { 00196 Flash *fls = FLASH_CAST(blk); 00197 return fls->hw->status; 00198 } 00199 00200 static void sam3_flash_clearerror(struct KBlock *blk) 00201 { 00202 Flash *fls = FLASH_CAST(blk); 00203 fls->hw->status = 0; 00204 } 00205 00206 static const KBlockVTable flash_sam3_buffered_vt = 00207 { 00208 .readDirect = sam3_flash_readDirect, 00209 .writeDirect = sam3_flash_writeDirect, 00210 00211 .readBuf = kblock_swReadBuf, 00212 .writeBuf = kblock_swWriteBuf, 00213 .load = kblock_swLoad, 00214 .store = kblock_swStore, 00215 00216 .error = sam3_flash_error, 00217 .clearerr = sam3_flash_clearerror, 00218 }; 00219 00220 static const KBlockVTable flash_sam3_unbuffered_vt = 00221 { 00222 .readDirect = sam3_flash_readDirect, 00223 .writeDirect = sam3_flash_writeDirect, 00224 00225 .error = sam3_flash_error, 00226 .clearerr = sam3_flash_clearerror, 00227 }; 00228 00229 static struct FlashHardware flash_sam3_hw; 00230 static uint8_t flash_buf[FLASH_PAGE_SIZE_BYTES]; 00231 00232 static void common_init(Flash *fls) 00233 { 00234 memset(fls, 0, sizeof(*fls)); 00235 DB(fls->blk.priv.type = KBT_FLASH); 00236 00237 fls->hw = &flash_sam3_hw; 00238 00239 fls->blk.blk_size = FLASH_PAGE_SIZE_BYTES; 00240 fls->blk.blk_cnt = FLASH_MEM_SIZE / FLASH_PAGE_SIZE_BYTES; 00241 } 00242 00243 void flash_hw_init(Flash *fls, UNUSED_ARG(int, flags)) 00244 { 00245 common_init(fls); 00246 fls->blk.priv.vt = &flash_sam3_buffered_vt; 00247 fls->blk.priv.flags |= KB_BUFFERED | KB_PARTIAL_WRITE; 00248 fls->blk.priv.buf = flash_buf; 00249 00250 /* Load the first block in the cache */ 00251 memcpy(fls->blk.priv.buf, (void *)(FLASH_BASE), fls->blk.blk_size); 00252 } 00253 00254 void flash_hw_initUnbuffered(Flash *fls, UNUSED_ARG(int, flags)) 00255 { 00256 common_init(fls); 00257 fls->blk.priv.vt = &flash_sam3_unbuffered_vt; 00258 } 00259
![(please configure the [header_logo] section in trac.ini)](/chrome/site/bertos_logo.png)