bug in flashwriting routines
Tue Apr 22 18:18:23 UTC 2008
Hi,
I think there is a timing bug in the openpicc storage-routines in
trunk/openpicc/application/env.c. On my openpicc this bug caused a reset via
watchdog every time I called store_env. The data would be stored but the
flash_cmd_wait() function would never return. The at91sam7s256 datasheet states
that for normal flashoperations the 'Flash Microsecond Cycle Number' must be set
to the number of master clock cycles in 1.5 microseconds.
env_init() sets this field to the number of clock cycles in 1 microsecond. This
is only correct when writing Lock bits, General Purpose NVM bit and Security bits.
Additionaly I think (also according to the datasheet on page 130) there has to
be a call to flash_cmd_wait() before the call to is_page_locked().
Please find attached a patch to hopefully fix this problems.
regards,
Johannes
--
Johannes Schlumberger Department of Computer Science IV
Martensstrasse 1 D-91058 Erlangen Germany University of Erlangen-Nuremberg
http://wwwcip.informatik.uni-erlangen.de/~spjsschl
-------------- next part --------------
--- application/env.c.orig 2008-04-21 14:26:52.000000000 +0200
+++ application/env.c 2008-04-21 14:31:46.000000000 +0200
@@ -43,6 +43,7 @@
#define ENV_FLASH ((unsigned int *)AT91C_IFLASH + AT91C_IFLASH_SIZE - ENVIRONMENT_SIZE)
TEnvironmentBlock env;
+static unsigned int fmcn;
static inline unsigned short RAMFUNC page_from_ramaddr(const void *addr)
{
@@ -66,6 +67,7 @@
static inline void RAMFUNC unlock_page(unsigned short page)
{
page &= 0x3ff;
+ AT91F_MC_EFC_CfgModeReg(AT91C_BASE_MC, fmcn << 16 | AT91C_MC_FWS_3FWS);
AT91F_MC_EFC_PerformCmd(AT91C_BASE_MC, AT91C_MC_FCMD_UNLOCK |
AT91C_MC_CORRECT_KEY | (page << 8));
flash_cmd_wait();
@@ -74,10 +76,15 @@
static inline void RAMFUNC flash_page(const void *addr)
{
unsigned short page = page_from_ramaddr(addr) & 0x3ff;
+ unsigned int fmcnscale = fmcn * 1.5;
+
+ flash_cmd_wait();
if (is_page_locked(page))
unlock_page(page);
+ AT91F_MC_EFC_CfgModeReg(AT91C_BASE_MC, fmcnscale << 16 |
+ AT91C_MC_FWS_3FWS);
AT91F_MC_EFC_PerformCmd(AT91C_BASE_MC, AT91C_MC_FCMD_START_PROG |
AT91C_MC_CORRECT_KEY | (page << 8));
flash_cmd_wait();
@@ -143,7 +150,5 @@
void env_init(void)
{
- unsigned int fmcn = AT91F_MC_EFC_ComputeFMCN(MCK);
-
- AT91F_MC_EFC_CfgModeReg(AT91C_BASE_MC, fmcn << 16 | AT91C_MC_FWS_3FWS);
+ fmcn = AT91F_MC_EFC_ComputeFMCN(MCK);
}
More information about the openpcd-devel
mailing list