summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/Makefile5
-rw-r--r--firmware/Makefile.dfu2
-rw-r--r--firmware/src/dfu/dfu.c4
-rw-r--r--firmware/src/os/flash.c68
-rw-r--r--firmware/src/os/flash.h5
5 files changed, 79 insertions, 5 deletions
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 <dfu/dfu.h>
#include <dfu/dbgu.h>
-#include <dfu/flash.h>
+#include <os/flash.h>
#include <os/pcd_enumerate.h>
#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 <sys/types.h>
+#include <lib_AT91SAM7.h>
+#include <AT91SAM7.h>
+#include <dfu/dbgu.h>
+#include <board.h>
+
+#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
personal git repositories of Harald Welte. Your mileage may vary