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