cancel
Showing results for 
Search instead for 
Did you mean: 

STR73x - Flash Erase/Write Data Abort

mikegoulet9
Associate II
Posted on November 28, 2008 at 21:54

STR73x - Flash Erase/Write Data Abort

8 REPLIES 8
mikegoulet9
Associate II
Posted on December 14, 2006 at 18:30

Hello,

I cannot get the STR73x 'flash' sample application to run without causing processor exceptions.

I am using IAR EW 4.0 with the ST731FV2 (256K flash).

Out of the box, the sample program starts out by erasing sector 1 and then writes 256 4-byte words to flash address 0x2000 (using ST's 73x_flash library API functions). The error seems to vary - sometimes the exception occurs during erase, other times it occurs during write. Sometimes the error is PREFETCH-ABORT, other times it is UNDEFINED-INSTRUCTION, other times it is SW-EXCEPTION - I've not been able to figure out exactly what causes what!

At one point, I was actually able to get the entire thing to run if I single-stepped through (though I have not been able to repeat that), but if I ran without stepping, the program would crash as described above.

My first concern is that it is physically writing to address 0x80002000 and my program size is about 5K, located presumabely at 0x80000000. But ST wrote this program, and that would be a glaring mistake, so obviously there is something about how the program is located in flash that I don't understand.

I tried erasing/writing to all the sectors in the device: 0-7 and all cause the crash condition.

What am I doing wrong? Is there related errata?

Thanks,

-Mike

BTW, here are relavent snippets from both the main program and the ST 73x_flash file.

*********************************************************************

*********************** main.c **************************************

*********************************************************************

...

typedef enum { FAIL = 0, PASS = !FAIL } Status;

#define BufferSize 256

#define AddrToWriteTo 0x2000

#define AddrToReadFrom 0x2000

...

u32 Index;

u32 SRC_Buffer[BufferSize], DST_Buffer[BufferSize];

Status TransferStatus;

...

Status Buffercmp(u32* pBuffer, u32* pBuffer1, u16 BufferLength);

void main()

{

#ifdef DEBUG

debug();

#endif

/* fill in the SRC_Buffer */

for(Index = 0; Index < BufferSize; Index++)

{

SRC_Buffer[Index] = Index;

}

/* deinitialize Flash registers */

FLASH_DeInit();

/* erase Flash sector1 */

FLASH_SectorErase(FLASH_Sector1);

/* write the SRC_Buffer contents to the Flash starting from address 0x2000 */

FLASH_BlockWrite((u32)&SRC_Buffer, AddrToWriteTo, BufferSize);

/* read the first 256 words from Flash sector1 and store them in DST_Buffer */

FLASH_BlockRead(AddrToReadFrom, (u32)&DST_Buffer, BufferSize);

/* check if the written data is correct --------------------------------------*/

TransferStatus = Buffercmp(DST_Buffer, SRC_Buffer, BufferSize);

/* TransferStatus = PASS, if the written data is correct */

/* TransferStatus = FAIL, if the written data is corrupted */

while(1);

}

*********************************************************************

*********************** 73x_flash.c *********************************

*********************************************************************

void FLASH_DeInit(void)

{

/* reset Flash control registers */

FLASHR->CR0 = 0x00000000;

FLASHR->CR1 = 0x00000000;

/* reset Flash data registers */

FLASHR->DR0 = 0xFFFFFFFF;

FLASHR->DR1 = 0xFFFFFFFF;

/* reset Flash address register */

FLASHR->AR = 0x00000000;

/* reset Flash error register */

FLASHR->ER = 0x00000000;

}

void FLASH_WordWrite(u32 DestAddr, u32 Data)

{

/* wait for the end of last task */

FLASH_WaitForLastTask();

/* set the WPG bit in CR0 register */

FLASHR->CR0 |= FLASH_WPG;

/* load the destination address in AR register */

FLASHR->AR = DestAddr;

/* load the data to be programmed in DR0 register */

FLASHR->DR0 = Data;

/* set the start bit WMS in CR0 register to start Write operation */

FLASHR->CR0 |= FLASH_WMS;

}

void FLASH_DWordWrite(u32 DestAddr, u32 Data0, u32 Data1)

{

/* wait for the end of last task */

FLASH_WaitForLastTask();

/* set the DWPG bit in CR0 register */

FLASHR->CR0 |= FLASH_DWPG;

/* load the destination address in AR register */

FLASHR->AR = DestAddr;

/* load the first word to be programmed in DR0 register */

FLASHR->DR0 = Data0;

/* load the second word to be programmed in DR1 register */

FLASHR->DR1 = Data1;

/* set the start bit WMS in CR0 register to start Write operation */

FLASHR->CR0 |= FLASH_WMS;

}

void FLASH_BlockWrite(u32 SourceAddr, u32 DestAddr, u32 NbrWordToWrite)

{

... This is just a bunch of word/dwordWrite calls

}

void FLASH_SectorErase(u8 FLASH_Sector)

{

/* wait for the end of last task */

FLASH_WaitForLastTask();

/* set the SER bit in CR0 register */

FLASHR->CR0 |= FLASH_SER;

/* select the sectors to be erased in the CR1 register */

FLASHR->CR1 |= FLASH_Sector;

/* set the start bit WMS in CR0 register */

FLASHR->CR0 |= FLASH_WMS;

}

static void FLASH_WaitForLastTask(void)

{

/* wait until the Flash controller acknowledges the end of the last

operation resetting the BSY0 and LOCK bits in the CR0 register */

while((FLASHR->CR0 & FLASH_FLAG_LOCKBSY0) != RESET);

}

javida14
Associate II
Posted on December 15, 2006 at 17:52

Hi,

I'm using the STR730 Hitech board and Keil. I have no problems flashing the board and executing code right out of the box.

mikegoulet9
Associate II
Posted on December 18, 2006 at 13:04

Zouhair, Javi,

Thanks for your help. It seems you are saying that my program must run out of RAM in order to write/erase Flash, which means my program must be less than 16K, correct?

-Mike

mikegoulet9
Associate II
Posted on December 18, 2006 at 13:35

OK, so I want to use the IAR '__ramfunc' qualifier to locate the code in RAM. I did this and I'm up and running! I can read, write, and erase sectors that my code does not reside in.

Again, thanks for your hints.

-Mike

Incidentally, if anyone wants to figure this out using GCC, I found the following at

http://www.embeddedrelated.com/groups/AT91SAM/show/1358.php

.

When using GCC, this IAR keyword does not work.

For a similar effect with GCC, use the __attribute__ compiler

instruction to construct a the following define:

#define RAMFUNC __attribute__ ((long_call, section (''.ramsection'')))

Then, when you declare a function you can instructthe linker to place

the code in RAM:

void foo() RAMFUNC;

void foo()

{

......... your code ...........

}

Also, in your linker map you need to indicate where .ramsection resides:

.data : AT (_etext)

{

_data =3D . ;

KEEP(*(.vectram)) /* added by mthomas */=09

*(.data)

SORT(CONSTRUCTORS)

. =3D ALIGN(4);

*(.ramsection) /* here your ramsection will be located */

} >DATA

. =3D ALIGN(4);

When you remove all RAMFUNC keywords, not much more wil happen than that

the linker will place your code in the default section (flash or sram,

depends on your linker map.

Placing code in SRAM has the benefit of speed. For example, putting your

interrupt handlers there is a good idea.

mikegoulet9
Associate II
Posted on December 18, 2006 at 16:55

Zouhair,

It turns out I am still experiencing problems writing to flash. What I have done is use IAR's intrinsic '__ramfunc' mechanism to locate my flash-erase/write functions to RAM, but my program is still crashing. So it appears that I am still doing flash-reads while performing the flash-erase or flash-write. But why??? I have declared ALL functions in the call stack as '__ramfunc'. I'm starting to think that the processor pipeline is the culprit!

BTW, I do poll for the completion of the flash operations (write & erase) BEFORE exiting the __ramfunc functions.

Any thoughts? I cannot run my program from RAM because it is larger than 16K.

-Mike

mikegoulet9
Associate II
Posted on December 19, 2006 at 09:46

Zouhair, I did exactly as you describe, but it was still crashing. The problem was a timer interrupt running out of flash! This explains the inconsistent mode of failure. Once I disabled interrupts prior to performing the flash write/erase, it worked fine. Actually, I had called IAR to inquire how '__ramfunc' really works (it works exactly as advertised), and it was one of their support engineers who suggested that interrupts could be the problem.

I think that the ST 'flash' example program should be expanded to atleast provide a readme explaining some of the pitfalls of flash-IAP. Simply locating your program in RAM is not a good solution for many. Though I will admit that if I had RTM more carefully, I could have avoided all these problems!

Thanks,

-Mike

mcu_guy
Associate
Posted on August 06, 2008 at 19:16

I am working through the same troubles right now. I am trying to write to flash on an STR731 micro using the Keil uVision environment. My program resides in BANK0 and I am trying to write to flash BANK5. I keep getting exception errors. Does anyone have a solution (or hints) that works with the Keil Tools?

Thanks. :)

ali2
Associate
Posted on November 28, 2008 at 21:54

I am having the same problem. I am running EVERYTHING out of RAM. I have disable interrupts and the code still gets lost while programming. The only think that seems to work is if I single-step through the code!

Can anyone help?

Thanks