BeRTOS
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     // 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