flash_at91.c
Go to the documentation of this file.00001
00040 #include "flash_at91.h"
00041
00042 #include "cfg/cfg_flash_at91.h"
00043 #include <cfg/macros.h>
00044
00045 #include "hw/hw_boot.h"
00046
00047
00048 #define LOG_LEVEL CONFIG_FLASH_AT91_LOG_LEVEL
00049 #define LOG_FORMAT CONFIG_FLASH_AT91_LOG_FORMAT
00050 #include <cfg/log.h>
00051
00052
00053 #include <cpu/irq.h>
00054 #include <cpu/attr.h>
00055 #include <cpu/power.h>
00056
00057 #include <kern/kfile.h>
00058
00059 #include <io/arm.h>
00060
00061 #include <drv/timer.h>
00062 #include <drv/flash.h>
00063
00064 #include <string.h>
00065
00066
00067
00068
00069 RAM_FUNC static bool flash_at91_isReady(void)
00070 {
00071 return (MC_FSR & BV(MC_FRDY));
00072 }
00073
00079 RAM_FUNC static void flash_at91_sendWRcmd(uint32_t page)
00080 {
00081 cpu_flags_t flags;
00082
00083
00084 while(!flash_at91_isReady())
00085 {
00086 cpu_relax();
00087 }
00088
00089 IRQ_SAVE_DISABLE(flags);
00090
00091
00092 MC_FCR = MC_KEY | MC_FCMD_WP | (MC_PAGEN_MASK & (page << 8));
00093
00094
00095 while(!flash_at91_isReady())
00096 {
00097 cpu_relax();
00098 }
00099
00100 IRQ_RESTORE(flags);
00101 }
00102
00107 RAM_FUNC static int flash_at91_getStatus(struct KFile *_fd)
00108 {
00109 (void)_fd;
00110
00111
00112
00113
00114
00115
00116 if(MC_FSR & BV(MC_LOCKE))
00117 return -1;
00118
00119
00120
00121
00122
00123 if(MC_FSR & BV(MC_PROGE))
00124 return -2;
00125
00126 return 0;
00127 }
00128
00129
00134 RAM_FUNC static void flash_at91_flush(Flash *fd)
00135 {
00136 if (fd->page_dirty)
00137 {
00138
00139 page_addr_t *addr = (page_addr_t *)((fd->curr_page * FLASH_PAGE_SIZE_BYTES) + FLASH_BASE);
00140
00141
00142 for (page_addr_t page_addr = 0; page_addr < FLASH_PAGE_SIZE_BYTES; page_addr += 4)
00143 {
00144 uint32_t data;
00145 memcpy(&data, &fd->page_buf[page_addr], sizeof(data));
00146 *addr = data;
00147 addr++;
00148 }
00149
00150
00151 flash_at91_sendWRcmd(fd->curr_page);
00152 }
00153 }
00154
00161 static int flash_at91_kfileFlush(struct KFile *_fd)
00162 {
00163 Flash *fd = FLASH_CAST(_fd);
00164 flash_at91_flush(fd);
00165 return 0;
00166 }
00167
00168
00173 static void flash_at91_loadPage(Flash *fd, page_t page)
00174 {
00175 if (page != fd->curr_page)
00176 {
00177 flash_at91_flush(fd);
00178
00179 memcpy(fd->page_buf, (const char *)((page * FLASH_PAGE_SIZE_BYTES) + FLASH_BASE), FLASH_PAGE_SIZE_BYTES);
00180 fd->curr_page = page;
00181 LOG_INFO("Loaded page %lu\n", fd->curr_page);
00182 }
00183 }
00184
00185
00191 static size_t flash_at91_write(struct KFile *_fd, const void *_buf, size_t size)
00192 {
00193 Flash *fd = FLASH_CAST(_fd);
00194 const uint8_t *buf =(const uint8_t *)_buf;
00195
00196 page_t page;
00197 page_addr_t page_addr;
00198 size_t total_write = 0;
00199
00200 size = MIN((kfile_off_t)size, (kfile_off_t)(fd->fd.size - (fd->fd.seek_pos - FLASH_BASE)));
00201
00202 LOG_INFO("Writing at pos[%lu]\n", fd->fd.seek_pos);
00203 while (size)
00204 {
00205 page = (fd->fd.seek_pos - FLASH_BASE) / FLASH_PAGE_SIZE_BYTES;
00206 page_addr = (fd->fd.seek_pos - FLASH_BASE) % FLASH_PAGE_SIZE_BYTES;
00207
00208 flash_at91_loadPage(fd, page);
00209
00210 size_t wr_len = MIN(size, (size_t)(FLASH_PAGE_SIZE_BYTES - page_addr));
00211
00212 memcpy(fd->page_buf + page_addr, buf, wr_len);
00213 fd->page_dirty = true;
00214
00215 buf += wr_len;
00216 fd->fd.seek_pos += wr_len;
00217 size -= wr_len;
00218 total_write += wr_len;
00219 }
00220 LOG_INFO("written %u bytes\n", total_write);
00221 return total_write;
00222 }
00223
00227 static int flash_at91_close(struct KFile *_fd)
00228 {
00229 Flash *fd = FLASH_CAST(_fd);
00230 flash_at91_flush(fd);
00231 LOG_INFO("Flash file closed\n");
00232
00233 return 0;
00234 }
00235
00241 static void flash_at91_open(struct Flash *fd)
00242 {
00243 fd->fd.size = FLASH_BASE + FLASH_MEM_SIZE;
00244 fd->fd.seek_pos = FLASH_BASE + FLASH_BOOT_SIZE;
00245 fd->curr_page = (fd->fd.seek_pos - FLASH_BASE) / FLASH_PAGE_SIZE_BYTES;
00246
00247 memcpy(fd->page_buf, (const char *)((fd->curr_page * FLASH_PAGE_SIZE_BYTES) + FLASH_BASE), FLASH_PAGE_SIZE_BYTES);
00248
00249 fd->page_dirty = false;
00250 LOG_INFO("Flash file opened\n");
00251 }
00252
00253
00258 static kfile_off_t flash_at91_seek(struct KFile *_fd, kfile_off_t offset, KSeekMode whence)
00259 {
00260 Flash *fd = FLASH_CAST(_fd);
00261 kfile_off_t seek_pos;
00262
00263 switch (whence)
00264 {
00265
00266 case KSM_SEEK_SET:
00267 seek_pos = FLASH_BASE + FLASH_BOOT_SIZE;
00268 break;
00269 case KSM_SEEK_END:
00270 seek_pos = fd->fd.size;
00271 break;
00272 case KSM_SEEK_CUR:
00273 seek_pos = fd->fd.seek_pos;
00274 break;
00275 default:
00276 ASSERT(0);
00277 return EOF;
00278 break;
00279 }
00280
00281 #if LOG_LEVEL >= LOG_LVL_INFO
00282
00283 if (seek_pos + offset > fd->fd.size)
00284 LOG_INFO("seek outside EOF\n");
00285 #endif
00286
00287 fd->fd.seek_pos = seek_pos + offset;
00288
00289 return fd->fd.seek_pos - (FLASH_BASE + FLASH_BOOT_SIZE);
00290 }
00291
00295 static struct KFile *flash_at91_reopen(struct KFile *_fd)
00296 {
00297 Flash *fd = FLASH_CAST(_fd);
00298 flash_at91_close(_fd);
00299 flash_at91_open(fd);
00300
00301 return _fd;
00302 }
00303
00308 static size_t flash_at91_read(struct KFile *_fd, void *_buf, size_t size)
00309 {
00310 Flash *fd = FLASH_CAST(_fd);
00311 uint8_t *buf =(uint8_t *)_buf;
00312
00313 size = MIN((kfile_off_t)size, fd->fd.size - fd->fd.seek_pos);
00314
00315 LOG_INFO("Reading at pos[%lu]\n", fd->fd.seek_pos);
00316
00317
00318 flash_at91_flush(fd);
00319
00320 uint32_t *addr = (uint32_t *)fd->fd.seek_pos;
00321 memcpy(buf, (uint8_t *)addr, size);
00322
00323 fd->fd.seek_pos += size;
00324
00325 LOG_INFO("Read %u bytes\n", size);
00326 return size;
00327 }
00328
00329
00334 void flash_hw_init(struct Flash *fd)
00335 {
00336 memset(fd, 0, sizeof(*fd));
00337 DB(fd->fd._type = KFT_FLASH);
00338
00339
00340 fd->fd.reopen = flash_at91_reopen;
00341 fd->fd.close = flash_at91_close;
00342 fd->fd.write = flash_at91_write;
00343 fd->fd.read = flash_at91_read;
00344 fd->fd.seek = flash_at91_seek;
00345 fd->fd.error = flash_at91_getStatus;
00346 fd->fd.flush = flash_at91_kfileFlush;
00347
00348 flash_at91_open(fd);
00349
00350 uint32_t fmcn;
00351 uint32_t fws = 0;
00352
00353
00354
00355
00356
00357
00358
00359 fmcn = (CPU_FREQ/1000000ul) + (CPU_FREQ/2000000ul) + 1;
00360
00361
00362 if (fmcn > 0xFF)
00363 fmcn = 0xFF;
00364
00365
00366 if (CPU_FREQ <= 33333ul)
00367 fmcn = 0;
00368
00369
00370 if (CPU_FREQ > 30000000ul)
00371 {
00372 fws = 1;
00373 }
00374
00375
00376 MC_FMR = fmcn << 16 | fws << 8;
00377
00378 }