From f21e08aa9f22d873e938cd3f021c3fc33d06d286 Mon Sep 17 00:00:00 2001 From: meri Date: Tue, 10 Apr 2007 17:34:53 +0000 Subject: moved flash code to seperate file git-svn-id: https://svn.openpcd.org:2342/trunk@294 6dc7ffe9-61d6-0310-9af1-9938baff3ed1 --- firmware/Makefile | 5 ++-- firmware/Makefile.dfu | 2 +- firmware/src/dfu/dfu.c | 4 +-- firmware/src/os/flash.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++ firmware/src/os/flash.h | 5 ++++ 5 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 firmware/src/os/flash.c create mode 100644 firmware/src/os/flash.h diff --git a/firmware/Makefile b/firmware/Makefile index f18fa80..d3d02ef 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -34,7 +34,7 @@ # - 19. Apr. 2006 - option FLASH_TOOL (default lpc21isp); variable IMGEXT (mth) # - 19. Mai. 2006 - USE_THUMB_MODE switch, ROM_RUN->RUN_FROM_ROM RAM_RUN->RUN_FROM_RAM -LIBRFID_DIR:=../../librfid/ +LIBRFID_DIR:=../librfid/ FLASH_TOOL = AT91FLASH #FLASH_TOOL = UVISION @@ -91,7 +91,8 @@ SRCARM += src/os/pcd_enumerate.c src/os/fifo.c src/os/dbgu.c \ src/os/main.c src/os/syscalls.c src/os/usb_handler.c \ src/os/usb_benchmark.c src/os/tc_cdiv.c src/os/pit.c \ src/os/pwm.c src/os/pio_irq.c src/os/usbcmd_generic.c \ - src/os/wdt.c src/os/blinkcode.c src/os/system_irq.c + src/os/wdt.c src/os/blinkcode.c src/os/system_irq.c \ + src/os/flash.c ifeq ($(BOARD), PCD) # PCD support code diff --git a/firmware/Makefile.dfu b/firmware/Makefile.dfu index 3bec426..c526fc2 100644 --- a/firmware/Makefile.dfu +++ b/firmware/Makefile.dfu @@ -79,7 +79,7 @@ SRC = # use file-extension c for "c-only"-files SRCARM = src/start/Cstartup_SAM7.c lib/lib_AT91SAM7.c \ - src/dfu/dfu.c src/dfu/dbgu.c src/dfu/flash.c + src/dfu/dfu.c src/dfu/dbgu.c src/os/flash.c # List C++ source files here. # use file-extension cpp for C++-files (use extension .cpp) diff --git a/firmware/src/dfu/dfu.c b/firmware/src/dfu/dfu.c index 20778bd..58062a0 100644 --- a/firmware/src/dfu/dfu.c +++ b/firmware/src/dfu/dfu.c @@ -30,7 +30,7 @@ #include #include -#include +#include #include #include "../openpcd.h" @@ -234,7 +234,7 @@ static int __dfufunc handle_dnload(u_int16_t val, u_int16_t len) dfu_state = DFU_STATE_dfuMANIFEST_SYNC; return RET_ZLP; } - if (ptr + len > (u_int8_t *) AT91C_IFLASH + AT91C_IFLASH_SIZE) { + if (ptr + len >= (u_int8_t *) AT91C_IFLASH + AT91C_IFLASH_SIZE - ENVIRONMENT_SIZE ) { DEBUGP("end of write exceeds flash end "); dfu_state = DFU_STATE_dfuERROR; dfu_status = DFU_STATUS_errADDRESS; diff --git a/firmware/src/os/flash.c b/firmware/src/os/flash.c new file mode 100644 index 0000000..c729ff8 --- /dev/null +++ b/firmware/src/os/flash.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include + +#define EFCS_CMD_WRITE_PAGE 0x1 +#define EFCS_CMD_SET_LOCK_BIT 0x2 +#define EFCS_CMD_WRITE_PAGE_LOCK 0x3 +#define EFCS_CMD_CLEAR_LOCK 0x4 +#define EFCS_CMD_ERASE_ALL 0x8 +#define EFCS_CMD_SET_NVM_BIT 0xb +#define EFCS_CMD_CLEAR_NVM_BIT 0xd +#define EFCS_CMD_SET_SECURITY_BIT 0xf + +static u_int16_t page_from_ramaddr(const void *addr) +{ + u_int32_t ramaddr = (u_int32_t) addr; + ramaddr -= (u_int32_t) AT91C_IFLASH; + return ((ramaddr >> AT91C_IFLASH_PAGE_SHIFT)); +} +#define PAGES_PER_LOCKREGION (AT91C_IFLASH_LOCK_REGION_SIZE>>AT91C_IFLASH_PAGE_SHIFT) +#define IS_FIRST_PAGE_OF_LOCKREGION(x) ((x % PAGES_PER_LOCKREGION) == 0) +#define LOCKREGION_FROM_PAGE(x) (x / PAGES_PER_LOCKREGION) + +static int is_page_locked(u_int16_t page) +{ + u_int16_t lockregion = LOCKREGION_FROM_PAGE(page); + + return (AT91C_BASE_MC->MC_FSR & (lockregion << 16)); +} + +static void unlock_page(u_int16_t page) +{ + page &= 0x3ff; + AT91F_MC_EFC_PerformCmd(AT91C_BASE_MC, AT91C_MC_FCMD_UNLOCK | + AT91C_MC_CORRECT_KEY | (page << 8)); +} + +void flash_page(u_int8_t *addr) +{ + u_int16_t page = page_from_ramaddr(addr) & 0x3ff; + u_int32_t fsr = AT91F_MC_EFC_GetStatus(AT91C_BASE_MC); + DEBUGP("flash_page(0x%x=%u) ", addr, page); + + if (is_page_locked(page)) { + DEBUGP("unlocking "); + unlock_page(page); + } + + if (!(fsr & AT91C_MC_FRDY)) { + DEBUGP("NOT_FLASHING "); + return; + } + + DEBUGP("performing start_prog "); + + AT91F_MC_EFC_PerformCmd(AT91C_BASE_MC, AT91C_MC_FCMD_START_PROG | + AT91C_MC_CORRECT_KEY | (page << 8)); +} + +void flash_init(void) +{ + unsigned int fmcn = AT91F_MC_EFC_ComputeFMCN(MCK); + + AT91F_MC_EFC_CfgModeReg(AT91C_BASE_MC, (fmcn&0xff) << 16 | + AT91C_MC_FWS_3FWS); +} diff --git a/firmware/src/os/flash.h b/firmware/src/os/flash.h new file mode 100644 index 0000000..b812714 --- /dev/null +++ b/firmware/src/os/flash.h @@ -0,0 +1,5 @@ +#ifndef _FLASH_H +#define _FLASH_H +extern void flash_page(u_int8_t *addr); +extern void flash_init(void); +#endif -- cgit v1.2.3