EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Setting AT91SAM7x Flash GPNVM bits

Started by kama...@ronan.com September 29, 2010
Hello, Im not an expert in embedded coding and am in somewhat of a hurry to get a brownout detection project out of the way and have been stuck trying to set and clear the General-purpose NVM bits in the embedded flash controller.
The processor Im using is the AT91SAM7x256. I need to be able to set and clear the GPNVM bits 0 and 1 as I desire. However I was once able to set the bits and now am not able to clear the bits. The process I follow is given below.

1. Set the Flash Microsecond Cycle Number in MC_FMR register which is the Number of Master Clock Cycles in one uS.
2. Check EFC_FSR to see if GPNVM bits 0 and 1 are set and clear bit 1 while setting bit 0.
3. Check the Error bits, the FREADY bit and the GPNVM bits in MC_FSR to see if the bits were set propperly without error.

For some reason, if I follow step one above everything goes haywire and nothing seems to work, including reading from the flash registers. And I cannot seem to set or clear these bits. Hopefully someone can help me out.

Heres part of my code:

/* Get the master clock frequency */
MasterClk_freq = BSP_CPU_ClkFreq()/1000000;

//Set the Flash Microsecon cycle number
AT91C_BASE_EFC0->EFC_FMR = (MasterClk_freq << 16);

//Set the GPNVM bits in the EFC_FCR Register which will enable BOD and BOD Resets
//First the Set_GPNVM command must be called in order to set these bits
if(!(AT91C_BASE_EFC0->EFC_FSR & AT91C_MC_GPNVM0))
AT91C_BASE_EFC0->EFC_FCR = AT91C_MC_FCMD_SET_GP_NVM |AT91C_MC_GPNVM0|AT91C_MC_KEY ;
//Wait for FREADY signal
while(!(AT91C_BASE_EFC0->EFC_FSR & AT91C_MC_FRDY));

if((AT91C_BASE_EFC0->EFC_FSR & AT91C_MC_GPNVM1))
AT91C_BASE_EFC0->EFC_FCR = AT91C_MC_FCMD_CLR_GP_NVM |AT91C_MC_GPNVM1|AT91C_MC_KEY ;

while(!(AT91C_BASE_EFC0->EFC_FSR & AT91C_MC_FRDY));

//Read the Ready and Error bits in the Flash register, to see if GPNVM bits were set properly
status = AT91C_BASE_EFC0->EFC_FSR & (AT91C_MC_FRDY|AT91C_MC_PROGE|AT91C_MC_LOCKE |AT91C_MC_GPNVM0|AT91C_MC_GPNVM1|AT91C_MC_SECURITY
);
Hello, I have been trying to develop a brownout detector on the
AT91SAM7x256 processor and am having problems setting the GPNVM bit 0 and
clearing the GPNVM bit 1 on the Embedded Flash Controller. Every time I
attempt to set these bits the system hangs or goes into loops around each
Set or Clear Command, sometimes the FREADY bit doesn't go high. I was at one
time able to set both GPNVM bits 1 and 0, however I am now unable to clear
GPNVM bit 1 now. In order to enable a brownout triggered interrupt, I need
to clear GPNVM bit 1.

The process I follow to set/clear these bits is given below.

1. Set the Flash Microsecond Cycle Number in MC_FMR register which is
the Number of Master Clock Cycles in one uS.

In our case, the master clock is 48 MHz therefore the number we feed the
FMCN is 48. The following command handles this.
MasterClk_freq = BSP_CPU_ClkFreq()/1000000;
AT91C_BASE_EFC0->EFC_FMR = (MasterClk_freq << 16);

2. Check EFC_FSR to see if GPNVM bits 0 and 1 are set and clear bit 1 while
setting bit 0.

if(!(AT91C_BASE_EFC0->EFC_FSR & AT91C_MC_GPNVM0))
AT91C_BASE_EFC0->EFC_FCR = AT91C_MC_FCMD_SET_GP_NVM
|AT91C_MC_GPNVM0|AT91C_MC_KEY ;

while(!(AT91C_BASE_EFC0->EFC_FSR & AT91C_MC_FRDY)); //Wait for FREADY
signal

if((AT91C_BASE_EFC0->EFC_FSR & AT91C_MC_GPNVM1))
AT91C_BASE_EFC0->EFC_FCR = AT91C_MC_FCMD_CLR_GP_NVM
|AT91C_MC_GPNVM1|AT91C_MC_KEY ;

while(!(AT91C_BASE_EFC0->EFC_FSR & AT91C_MC_FRDY));

3. Check the Error bits, the FREADY bit and the GPNVM bits in MC_FSR to see
if the bits were set properly without error.

status = AT91C_BASE_EFC0->EFC_FSR &
(AT91C_MC_FRDY|AT91C_MC_PROGE|AT91C_MC_LOCKE
|AT91C_MC_GPNVM0|AT91C_MC_GPNVM1|AT91C_MC_SECURITY
);

I hope you are able to help. Please let me know if anything needs further
clarification.
Haven't done that sort of this ion a long time, but you are running that
code from RAM aren't you ?
Unless there's something very different about SAM7X, or controlling
those bits doesn't affect read access of the relevant Flash array... but
else, your code must be in RAM. (use .fast)

HTH
On Thu, 2010-09-30 at 13:24 -0700, Kamal wrote:
>
> Hello, I have been trying to develop a brownout detector on the
> AT91SAM7x256 processor and am having problems setting the GPNVM bit 0
> and clearing the GPNVM bit 1 on the Embedded Flash Controller. Every
> time I attempt to set these bits the system hangs or goes into loops
> around each Set or Clear Command, sometimes the FREADY bit doesn’t go
> high. I was at one time able to set both GPNVM bits 1 and 0, however I
> am now unable to clear GPNVM bit 1 now. In order to enable a brownout
> triggered interrupt, I need to clear GPNVM bit 1.
>
>
>
> The process I follow to set/clear these bits is given below.
>
>
>
> 1. Set the Flash Microsecond Cycle Number in MC_FMR register
> which is the Number of Master Clock Cycles in one uS.
>
> In our case, the master clock is 48 MHz therefore the number we feed
> the FMCN is 48. The following command handles this.
> MasterClk_freq = BSP_CPU_ClkFreq()/1000000;
> AT91C_BASE_EFC0->EFC_FMR = (MasterClk_freq << 16);
>
>
> 2. Check EFC_FSR to see if GPNVM bits 0 and 1 are set and clear bit 1
> while setting bit 0.
>
>
>
> if(!(AT91C_BASE_EFC0->EFC_FSR & AT91C_MC_GPNVM0))
> AT91C_BASE_EFC0->EFC_FCR = AT91C_MC_FCMD_SET_GP_NVM |AT91C_MC_GPNVM0|
> AT91C_MC_KEY ;
>
> while(!(AT91C_BASE_EFC0->EFC_FSR & AT91C_MC_FRDY)); //Wait for
> FREADY signal
>
> if((AT91C_BASE_EFC0->EFC_FSR & AT91C_MC_GPNVM1))
> AT91C_BASE_EFC0->EFC_FCR = AT91C_MC_FCMD_CLR_GP_NVM |AT91C_MC_GPNVM1|
> AT91C_MC_KEY ;
>
> while(!(AT91C_BASE_EFC0->EFC_FSR & AT91C_MC_FRDY));
>
>
> 3. Check the Error bits, the FREADY bit and the GPNVM bits in MC_FSR
> to see if the bits were set properly without error.
>
> status = AT91C_BASE_EFC0->EFC_FSR & (AT91C_MC_FRDY|AT91C_MC_PROGE|
> AT91C_MC_LOCKE |AT91C_MC_GPNVM0|AT91C_MC_GPNVM1|AT91C_MC_SECURITY
> );

--
Best regards,
Kris

Hello, thanks for your reply. Yes I am running this from RAM, and according
to what I have understood by the data sheet, it is possible to run it this
way. I have made one change to my Flash Microsecond cycle counter code and
that is adding (EFC) 2 cycles for Read, 3 for Write operations command to
it. With this addition, the code doesn't seem to hang up or cause any loops,
however the bits are still not getting set or cleared as I want them to.
Hope someone can help.

Here is the new code for step 1 below.

// Flas Microsecond cycle number

AT91C_BASE_EFC0->EFC_FMR = ((AT91C_MC_FMCN)&(48 <<16)) |
AT91C_MC_FWS_1FWS ;

Thank you,

Kamal

_____

From: A... [mailto:A...] On Behalf Of
Microbit_Ubuntu
Sent: Thursday, September 30, 2010 2:30 PM
To: A...
Subject: Re: [AT91SAM] Setting AT91SAM7x Flash GPNVM bits

Haven't done that sort of this ion a long time, but you are running that
code from RAM aren't you ?
Unless there's something very different about SAM7X, or controlling
those bits doesn't affect read access of the relevant Flash array... but
else, your code must be in RAM. (use .fast)

HTH

On Thu, 2010-09-30 at 13:24 -0700, Kamal wrote:
>
> Hello, I have been trying to develop a brownout detector on the
> AT91SAM7x256 processor and am having problems setting the GPNVM bit 0
> and clearing the GPNVM bit 1 on the Embedded Flash Controller. Every
> time I attempt to set these bits the system hangs or goes into loops
> around each Set or Clear Command, sometimes the FREADY bit doesn't go
> high. I was at one time able to set both GPNVM bits 1 and 0, however I
> am now unable to clear GPNVM bit 1 now. In order to enable a brownout
> triggered interrupt, I need to clear GPNVM bit 1.
>
> The process I follow to set/clear these bits is given below.
>
> 1. Set the Flash Microsecond Cycle Number in MC_FMR register
> which is the Number of Master Clock Cycles in one uS.
>
> In our case, the master clock is 48 MHz therefore the number we feed
> the FMCN is 48. The following command handles this.
> MasterClk_freq = BSP_CPU_ClkFreq()/1000000;
> AT91C_BASE_EFC0->EFC_FMR = (MasterClk_freq << 16);
> 2. Check EFC_FSR to see if GPNVM bits 0 and 1 are set and clear bit 1
> while setting bit 0.
>
> if(!(AT91C_BASE_EFC0->EFC_FSR & AT91C_MC_GPNVM0))
> AT91C_BASE_EFC0->EFC_FCR = AT91C_MC_FCMD_SET_GP_NVM |AT91C_MC_GPNVM0|
> AT91C_MC_KEY ;
>
> while(!(AT91C_BASE_EFC0->EFC_FSR & AT91C_MC_FRDY)); //Wait for
> FREADY signal
>
> if((AT91C_BASE_EFC0->EFC_FSR & AT91C_MC_GPNVM1))
> AT91C_BASE_EFC0->EFC_FCR = AT91C_MC_FCMD_CLR_GP_NVM |AT91C_MC_GPNVM1|
> AT91C_MC_KEY ;
>
> while(!(AT91C_BASE_EFC0->EFC_FSR & AT91C_MC_FRDY));
> 3. Check the Error bits, the FREADY bit and the GPNVM bits in MC_FSR
> to see if the bits were set properly without error.
>
> status = AT91C_BASE_EFC0->EFC_FSR & (AT91C_MC_FRDY|AT91C_MC_PROGE|
> AT91C_MC_LOCKE |AT91C_MC_GPNVM0|AT91C_MC_GPNVM1|AT91C_MC_SECURITY
> );

--
Best regards,
Kris
FWIW, this is what I do to set the security bit on a AT91SAM7X512. Hope it helps.

- Nick
AT91C_BASE_EFC0->EFC_FMR = (unsigned int)((FMCN_PLL_1_0_US << 16) | AT91C_MC_FWS_1FWS); //setup flash mode register (1.0us)
while (!(AT91C_BASE_EFC0->EFC_FSR & AT91C_MC_FRDY)); //wait for flash to become ready
setSecurityBit(); //call to RAM routine - does not return

__attribute__ ((long_call, section(".ramcode"))) void setSecurityBit() {
AT91C_BASE_EFC0->EFC_FCR = (unsigned int)((0x5A << 24) | AT91C_MC_FCMD_SET_SECURITY); //program security bit
while (!(AT91C_BASE_EFC0->EFC_FSR & AT91C_MC_FRDY)); //wait for flash write to complete
AT91C_BASE_RSTC->RSTC_RCR = (unsigned int)((0xA5 << 24) | AT91C_RSTC_PROCRST | AT91C_RSTC_PERRST | AT91C_RSTC_EXTRST); //reset the processor and the peripherals
}


The 2024 Embedded Online Conference