EmbeddedRelated.com
Forums
Memfault Beyond the Launch

SAM7S256 crashes when trying to write program flash

Started by Tobias Weber May 30, 2006
Hi list, hi Atmel fans,

I am quite new to this list, as well as to ARM7. I spend the last years programming several controllers but mostly AVR from tiny15 to mega128. Currently I am developing some simpe USB device using an AT91SAM7256 for the first time. It is used as connector between USB and a proprietary RF data link. The basic program is already working fine.

Now the last issue that I have to implement is a flash upgrade feature that I thought first should be quite simple to do. But since days I'm stuck with a particular problem.

My basic problem is, that when debugging step by step, everthing works fine (just to mention: debugging with JTAG on ARM is a pleasure generally). BUT when running it with F5 straight from the start or from within (all code located in RAM) then it crashes with a data abort exception. As I understood these exception do only take place when I try accessing a mem location that is within invalid mem range (those 3,5gb mentioned in the Atmel Manual). Or maybe when accessing flash that is just being programmed ? This shouldnt be the case when everything is located in RAM and RAM is properly mapped to 0x0 ?

My Setup: AT91SAM7S-EK, IAR EWARM 4.31A, SAM-ICE USB J-Link. (RF-module is not sending, while flashing)

I would be very thankful if someone would have an idea or a hint what could go wrong in my code.
Regards,
Tobias

----- program details -------

The whole flash update function is declared as __ramfunc.

First, I disable all interrupts with the IAR intrinsic function __disable_interrupt(); Watchdog has never been activated.

Then I configure the flash controller:
AT91C_BASE_MC->MC_FMR = ((AT91C_MC_FMCN)&(72 <<16)) | AT91C_MC_FWS_1FWS | AT91C_MC_NEBP;

then I erase the whole flash

// erase flash
//* set the Flash controller base address
AT91PS_MC ptMC = AT91C_BASE_MC;
//* Write the Erase All command
ptMC->MC_FCR = AT91C_MC_CORRECT_KEY | AT91C_MC_FCMD_ERASE_ALL ;
//* Wait the end of command
AT91F_Flash_Ready();
// check if properly erased
if(!AT91F_Flash_Check_Erase((u32*)AT91C_IFLASH, AT91C_IFLASH_SIZE)) {
LED_RED_ON; //error, does never occur
LED_GREEN_ON;
while(true) {}
}

That always works fine, but the following code crashes with a data abort exception:

pul = (u32*)AT91C_IFLASH;

//go through the pages
for(j = 0; j < _FU_FLASH_SIZE/AT91C_IFLASH_PAGE_SIZE; j++ ) {
//flash one page
//pul = (u32*)AT91C_IFLASH;
for(i = 0; i < AT91C_IFLASH_PAGE_SIZE/4; i++) {
*pul++ = *pDataIn++;
}
//* Write the write page command
AT91C_BASE_MC->MC_FCR = AT91C_MC_CORRECT_KEY | AT91C_MC_FCMD_START_PROG | (AT91C_MC_PAGEN & (j <<8)) ;
//* Wait the end of command
while ((status & AT91C_MC_FRDY) != AT91C_MC_FRDY ) {
status = AT91C_BASE_MC->MC_FSR;
}

//* Check the result
if ( (status & ( AT91C_MC_PROGE | AT91C_MC_LOCKE )) != 0 ) {
LED_RED_ON; //error
LED_GREEN_ON;
while(true) {}
}
}

After programming 2 pages correctly (which could be found out while watching flash at 0x100000) the dabtvec is called. If I step further, more pages are programmed correctly, but as soon as I RUN the ARM goes to dabtvec.

The registers after exception:
r13_abt is 0x0
r14_abt is 0x00001F7C

compiled code:

pul = (u32*)AT91C_IFLASH;
00001F50 E3A01940 MOV R1, #0x100000
for(j = 0; j < _FU_FLASH_SIZE/AT91C_IFLASH_PAGE_SIZE; j++ ) {
00001F54 E3A00000 MOV R0, #0x0
00001F58 EA000000 B 0x001F60
for(j = 0; j < _FU_FLASH_SIZE/AT91C_IFLASH_PAGE_SIZE; j++ ) {
00001F5C E2900001 ADDS R0, R0, #0x1
for(j = 0; j < _FU_FLASH_SIZE/AT91C_IFLASH_PAGE_SIZE; j++ ) {
00001F60 E3500040 CMP R0, #0x40
00001F64 2A000023 BCS 0x001FF8
for(i = 0; i < AT91C_IFLASH_PAGE_SIZE/4; i++) {
00001F68 E3A07000 MOV R7, #0x0
00001F6C EA000004 B 0x001F84
*pul++ = *pDataIn++;
00001F70 E5952000 LDR R2, [R5, #+0]
00001F74 E5812000 STR R2, [R1, #+0]
00001F78 E2955004 ADDS R5, R5, #0x4
00001F7C E2911004 ADDS R1, R1, #0x4
for(i = 0; i < AT91C_IFLASH_PAGE_SIZE/4; i++) {
00001F80 E2977001 ADDS R7, R7, #0x1
for(i = 0; i < AT91C_IFLASH_PAGE_SIZE/4; i++) {
00001F84 E3570040 CMP R7, #0x40
00001F88 3AFFFFF8 BCC 0x001F70
AT91C_BASE_MC->MC_FCR = AT91C_MC_CORRECT_KEY | AT91C_MC_FCMD_START_PROG | (AT91C_MC_PAGEN & (j <<8)) ;
00001F8C E3E0209B MVN R2, #0x9B
00001F90 E3A03BC0 MOV R3, #0x30000
00001F94 E3833CFF ORR R3, R3, #0xFF00
00001F98 E0133400 ANDS R3, R3, R0, LSL #8
00001F9C E3A07001 MOV R7, #0x1
00001FA0 E387745A ORR R7, R7, #0x5A000000
00001FA4 E1973003 ORRS R3, R7, R3
00001FA8 E5823000 STR R3, [R2, #+0]
00001FAC EA000001 B 0x001FB8
status = AT91C_BASE_MC->MC_FSR;
00001FB0 E3E02097 MVN R2, #0x97
00001FB4 E5924000 LDR R4, [R2, #+0]
Tobias,

Have you tried running out of Flash? I don't bother running out of RAM at
all, after all the end application will run in Flash, won't it? You'll need
to set up a Flash configuration (Project->Edit Configurations->New) which
can be confusing but there ought to be an example project with a Flash
configuration already set up for a 256.

Chip

_____

From: A... [mailto:A...] On Behalf Of
Tobias Weber
Sent: Tuesday, May 30, 2006 8:16 AM
To: A...
Subject: [AT91SAM] SAM7S256 crashes when trying to write program flash

Hi list, hi Atmel fans,

I am quite new to this list, as well as to ARM7. I spend the last years
programming several controllers but mostly AVR from tiny15 to mega128.
Currently I am developing some simpe USB device using an AT91SAM7256 for the
first time. It is used as connector between USB and a proprietary RF data
link. The basic program is already working fine.

Now the last issue that I have to implement is a flash upgrade feature that
I thought first should be quite simple to do. But since days I'm stuck with
a particular problem.

My basic problem is, that when debugging step by step, everthing works fine
(just to mention: debugging with JTAG on ARM is a pleasure generally). BUT
when running it with F5 straight from the start or from within (all code
located in RAM) then it crashes with a data abort exception. As I understood
these exception do only take place when I try accessing a mem location that
is within invalid mem range (those 3,5gb mentioned in the Atmel Manual). Or
maybe when accessing flash that is just being programmed ? This shouldnt be
the case when everything is located in RAM and RAM is properly mapped to 0x0
?

My Setup: AT91SAM7S-EK, IAR EWARM 4.31A, SAM-ICE USB J-Link. (RF-module is
not sending, while flashing)

I would be very thankful if someone would have an idea or a hint what could
go wrong in my code.

Regards,

Tobias

----- program details -------

The whole flash update function is declared as __ramfunc.

First, I disable all interrupts with the IAR intrinsic function
__disable_interrupt(); Watchdog has never been activated.

Then I configure the flash controller:

AT91C_BASE_MC->MC_FMR = ((AT91C_MC_FMCN)&(72 <<16)) |
AT91C_MC_FWS_1FWS | AT91C_MC_NEBP;

then I erase the whole flash

// erase flash
//* set the Flash controller base address
AT91PS_MC ptMC = AT91C_BASE_MC;
//* Write the Erase All command
ptMC->MC_FCR = AT91C_MC_CORRECT_KEY | AT91C_MC_FCMD_ERASE_ALL ;
//* Wait the end of command
AT91F_Flash_Ready();
// check if properly erased
if(!AT91F_Flash_Check_Erase((u32*)AT91C_IFLASH, AT91C_IFLASH_SIZE)) {
LED_RED_ON; //error, does never occur
LED_GREEN_ON;
while(true) {}
}

That always works fine, but the following code crashes with a data abort
exception:

pul = (u32*)AT91C_IFLASH;

//go through the pages
for(j = 0; j < _FU_FLASH_SIZE/AT91C_IFLASH_PAGE_SIZE; j++ ) {
//flash one page
//pul = (u32*)AT91C_IFLASH;
for(i = 0; i < AT91C_IFLASH_PAGE_SIZE/4; i++) {
*pul++ = *pDataIn++;
}
//* Write the write page command
AT91C_BASE_MC->MC_FCR = AT91C_MC_CORRECT_KEY | AT91C_MC_FCMD_START_PROG
| (AT91C_MC_PAGEN & (j <<8)) ;
//* Wait the end of command
while ((status & AT91C_MC_FRDY) != AT91C_MC_FRDY ) {
status = AT91C_BASE_MC->MC_FSR;
}

//* Check the result
if ( (status & ( AT91C_MC_PROGE | AT91C_MC_LOCKE )) != 0 ) {
LED_RED_ON; //error
LED_GREEN_ON;
while(true) {}
}
}

After programming 2 pages correctly (which could be found out while watching
flash at 0x100000) the dabtvec is called. If I step further, more pages are
programmed correctly, but as soon as I RUN the ARM goes to dabtvec.

The registers after exception:

r13_abt is 0x0

r14_abt is 0x00001F7C

compiled code:

pul = (u32*)AT91C_IFLASH;
00001F50 E3A01940 MOV R1, #0x100000
for(j = 0; j < _FU_FLASH_SIZE/AT91C_IFLASH_PAGE_SIZE; j++ ) {
00001F54 E3A00000 MOV R0, #0x0
00001F58 EA000000 B 0x001F60
for(j = 0; j < _FU_FLASH_SIZE/AT91C_IFLASH_PAGE_SIZE; j++ ) {
00001F5C E2900001 ADDS R0, R0, #0x1
for(j = 0; j < _FU_FLASH_SIZE/AT91C_IFLASH_PAGE_SIZE; j++ ) {
00001F60 E3500040 CMP R0, #0x40
00001F64 2A000023 BCS 0x001FF8
for(i = 0; i < AT91C_IFLASH_PAGE_SIZE/4; i++) {
00001F68 E3A07000 MOV R7, #0x0
00001F6C EA000004 B 0x001F84
*pul++ = *pDataIn++;
00001F70 E5952000 LDR R2, [R5, #+0]
00001F74 E5812000 STR R2, [R1, #+0]
00001F78 E2955004 ADDS R5, R5, #0x4
00001F7C E2911004 ADDS R1, R1, #0x4
for(i = 0; i < AT91C_IFLASH_PAGE_SIZE/4; i++) {
00001F80 E2977001 ADDS R7, R7, #0x1
for(i = 0; i < AT91C_IFLASH_PAGE_SIZE/4; i++) {
00001F84 E3570040 CMP R7, #0x40
00001F88 3AFFFFF8 BCC 0x001F70
AT91C_BASE_MC->MC_FCR = AT91C_MC_CORRECT_KEY | AT91C_MC_FCMD_START_PROG
| (AT91C_MC_PAGEN & (j <<8)) ;
00001F8C E3E0209B MVN R2, #0x9B
00001F90 E3A03BC0 MOV R3, #0x30000
00001F94 E3833CFF ORR R3, R3, #0xFF00
00001F98 E0133400 ANDS R3, R3, R0, LSL #8
00001F9C E3A07001 MOV R7, #0x1
00001FA0 E387745A ORR R7, R7, #0x5A000000
00001FA4 E1973003 ORRS R3, R7, R3
00001FA8 E5823000 STR R3, [R2, #+0]
00001FAC EA000001 B 0x001FB8
status = AT91C_BASE_MC->MC_FSR;
00001FB0 E3E02097 MVN R2, #0x97
00001FB4 E5924000 LDR R4, [R2, #+0]

SPONSORED LINKS
Microcontrollers
=Cpu+chip&w3=Arms&w4elopment+tool&w5=Microprocessor&c=5&s&.sig=JL1WKF
1vUqEgZhFSvLcTwQ>

Cpu
p&w3=Arms&w4elopment+tool&w5=Microprocessor&c=5&s&.sig=J2LJ4JioN5vEM0
428aODAg> chip

Arms
=Arms&w4elopment+tool&w5=Microprocessor&c=5&s&.sig=yPOxLkzDXn5eqYeA1w
MVCQ>
Development
=Cpu+chip&w3=Arms&w4elopment+tool&w5=Microprocessor&c=5&s&.sig=lhbODg
5ptVr7u61IFQfZXQ> tool

Microprocessor
pu+chip&w3=Arms&w4elopment+tool&w5=Microprocessor&c=5&s&.sig=CHIRUROY
ao456Telb69zdA>

_____

> Terms of Service.

_____
Hi Chip,

Yes it will finally run out of flash and yes I tried to run it there as
well -> it is absolutley the same effect. The only difference is that it
is a bit slower due to the wait state when running from flash.

Tobias
Chip Burns schrieb:
>
> Tobias,
>
>
>
> Have you tried running out of Flash? I don't bother running out of
> RAM at all, after all the end application will run in Flash, won't
> it? You'll need to set up a Flash configuration (Project->Edit
> Configurations->New) which can be confusing but there ought to be an
> example project with a Flash configuration already set up for a 256.
>
>
>
> Chip
>
Hi Magnus,

Thanks for the hint. I've checked the 4-byte alignment. But it seems fine.
pDataIn and pul are unsigned long * (I defined that u32*) and the buffer
where pDataIn is derived from is an u32 array. I checked the register that
keeps the pointer while executing and both are xxx0 - xxx4 - xxx8 -
xxxC -xxx0 and that is obvious proper 4 byte alignment to me. I'll keep
searching...

Tobias

----- Original Message -----
From: "Magnus Larsson"
To: "Tobias Weber"
Sent: Tuesday, May 30, 2006 10:17 PM
Subject: Re: [AT91SAM] SAM7S256 crashes when trying to write program flash
>
> On May 30, 2006, at 5:16 PM, Tobias Weber wrote:
>
>>
>> Hi list, hi Atmel fans,
>> for(i = 0; i < AT91C_IFLASH_PAGE_SIZE/4; i++) {
>> *pul++ = *pDataIn++;
>> }
> Are your sure the pDataIn is aligned to a 4 byte boundry? I had crash due
> that reason..
>
> You cannot cast a u8 pointer to a u32 pointer (a restriction in ARM and
> some other architectures) unless you know its aligned to a 4 byte
> boundry, you have to do some shift and or stuff unless you know its
> aligned
>
> If this is not the problem ignore this message ... :)
> /mla

Hello Tobias

Since it works when you run the code step by step, the likely problem
is that the flash programming has not finished when you start flashing
the next page.

Perhaps the problem is in the status check

> //* Wait the end of command
> while ((status & AT91C_MC_FRDY) != AT91C_MC_FRDY ) {
> status = AT91C_BASE_MC->MC_FSR;
> }
>

When you test the AT91C_MC_FRDY flag you only update the status
variable if the status flag is not set, so you will be reusing
the value from the previous check if the flash is erased.

So maybe you should try:

//* Wait the end of command
do
{
status = AT91C_BASE_MC->MC_FSR;
}
while ((status & AT91C_MC_FRDY) != AT91C_MC_FRDY );

This will update the status flag before testing its value.

If the data abort is actually generated by the flash controller,
this can explain why the abort is at a location where oly register
access is performed

Regards,
Magnus

Hello Magnus,

Many thanks for that hint. That was the solution ! I took this snipplet directly from Flash-Example that came with the AT91SAM7S-EK and never realy thought about it really. There we go: I tried the example and it does also not work correctly! So Atmel, please fix your flash example ;)

>If the data abort is actually generated by the flash controller,
>this can explain why the abort is at a location where oly register
>access is performed

Absoltley correct. That is why it occured during simple register access and not at a mem store/load.

Regards
Tobias
>Hello Tobias
>
>Since it works when you run the code step by step, the likely problem
>is that the flash programming has not finished when you start flashing
>the next page.
...
>This will update the status flag before testing its value.
>If the data abort is actually generated by the flash controller,
>this can explain why the abort is at a location where oly register
>access is performed
>
>Regards,
>Magnus

----- Original Message -----
From: Tobias Weber
To: Magnus Larsson
Cc: A...
Sent: Wednesday, May 31, 2006 11:33 AM
Subject: Re: [AT91SAM] SAM7S256 crashes when trying to write program flash
Hi Magnus,

Thanks for the hint. I've checked the 4-byte alignment. But it seems fine.
pDataIn and pul are unsigned long * (I defined that u32*) and the buffer
where pDataIn is derived from is an u32 array. I checked the register that
keeps the pointer while executing and both are xxx0 - xxx4 - xxx8 -
xxxC -xxx0 and that is obvious proper 4 byte alignment to me. I'll keep
searching...

Tobias

----- Original Message -----
From: "Magnus Larsson"
To: "Tobias Weber"
Sent: Tuesday, May 30, 2006 10:17 PM
Subject: Re: [AT91SAM] SAM7S256 crashes when trying to write program flash
>
> On May 30, 2006, at 5:16 PM, Tobias Weber wrote:
>
>>
>> Hi list, hi Atmel fans,
>>
>>
>> for(i = 0; i < AT91C_IFLASH_PAGE_SIZE/4; i++) {
>> *pul++ = *pDataIn++;
>> }
>>
>>
> Are your sure the pDataIn is aligned to a 4 byte boundry? I had crash due
> that reason..
>
> You cannot cast a u8 pointer to a u32 pointer (a restriction in ARM and
> some other architectures) unless you know its aligned to a 4 byte
> boundry, you have to do some shift and or stuff unless you know its
> aligned
>
> If this is not the problem ignore this message ... :)
>
>
> /mla

SPONSORED LINKS Microcontrollers Cpu chip Arms
Development tool Microprocessor
------
YAHOO! GROUPS LINKS

a..
------

Memfault Beyond the Launch