at91sam7 flash timing bug

Hi,

the flash timing of an at91sam7 is incorrectly set (written to the read-only FSR instead of to the FMR, zero wait-states regardless of clock speed).

This only hurts when the target runs faster than the default 32kHz CPU clock.

The patch below fixes this.

Cheers

Anders

Fix the timing calculations and write the result to the correct register.

Signed-off-by: Anders Larsen <al@alarsen.net>
---
 src/flash/at91sam7.c |   10 ++++++----
 1 files changed, 6 insertions(+), 4 deletions(-)

Index: b/src/flash/at91sam7.c
===================================================================
--- a/src/flash/at91sam7.c
+++ b/src/flash/at91sam7.c
@@ -206,7 +206,7 @@ void at91sam7_read_clock_info(flash_bank
 /* Setup the timimg registers for nvbits or normal flash */
 void at91sam7_set_flash_mode(flash_bank_t *bank,int mode)
 {
-	u32 fmcn, fmr;
+	u32 fmr, fmcn = 0, fws = 0;
 	at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv;
 	target_t *target = at91sam7_info->target;
 	
@@ -220,12 +220,14 @@ void at91sam7_set_flash_mode(flash_bank_
 			fmcn = (at91sam7_info->mck_freq/666666ul)+1;
 
 		/* Only allow fmcn=0 if clock period is > 30 us. */
-		if (at91sam7_info->mck_freq <= 33333)
+		if (at91sam7_info->mck_freq <= 33333333ul)
 			fmcn = 0;
+		else
+			fws = 1;
 
 		DEBUG("fmcn: %i", fmcn); 
-		fmr = fmcn<<16;
-		target->type->write_memory(target, MC_FSR, 4, 1, (u8 *)&fmr);
+		fmr = fmcn << 16 | fws << 8;
+		target->type->write_memory(target, MC_FMR, 4, 1, (u8 *)&fmr);
 	}
 	at91sam7_info->flashmode = mode;		
 }

Hello Anders,

sorry I didn’t reply sooner (I’ve receieved your mails, just didn’t have time to answer yet).

I’ll add both patches to the next svn revision, thanks a lot.

Regards,

Dominic

Hi Dominic,

no problem - I just wanted to publish the bug (and the fix) before somebody else got bitten.

Cheers

Anders

Hello Anders and thanks.

Strange that this obvious error survived so long, I have actually used the code to flash an AT91SAM7S running from both 12MHz crystal and the 48MHz PLL for USB and it has worked.

I think the patch needs another fix, since the condition for settng FMCN to 0 is 30uS clock cycle = 33kHz, but the condition for allowing FWS = 0 is a frequency of 30 MHz.

So your code works correctly if the clock is above 33MHz and below 33kHz

(working copy)
--- /home/lundin/delad/arbete/animatronics/arm7/openocd/trunk/src/flash/at91sam7.c      (revision 92)
+++ /home/lundin/delad/arbete/animatronics/arm7/openocd/trunk/src/flash/at91sam7.c     @@ -220,10 +220,11 @@
                      /* main clocks in 1.5uS */
                      fmcn = (at91sam7_info->mck_freq/666666ul)+1;
 
-              /* Only allow fmcn=0 if clock period is > 30 us. */
-              if (at91sam7_info->mck_freq <= 33333333ul)
+              /* Only allow fmcn=0 if clock period is > 30 us = 33kHz. */
+              if (at91sam7_info->mck_freq <= 33333ul)
                      fmcn = 0;
-              else
+              /* Only allow fws=0 if clock frequency is < 30 MHz. */
+              if (at91sam7_info->mck_freq > 30000000ul)
                      fws = 1;
 
               DEBUG("fmcn: %i", fmcn);

Greetings

Magnus

Hello Magnus,

oops - you’re right, my patch was incorrect wrt FMCN :oops:

Could the reason you haven’t experienced problems with 48MHz possibly be that your own code has set FMR correctly?

Cheers

Anders