EmbeddedRelated.com
Forums
Memfault Beyond the Launch

LPC2478 IAP Troubles

Started by mike_schwarzer March 11, 2010
Hi Guys,

I have some confusing troubles with IAP on an LPC2478.
I have written Routines for IAP Prepare, Erase, Write, ...
These Routines are working on all 4kB Sektors (0 .. 7 / 22 .. 27)
as acpected.
I use them to store some 'nearly' const Variables (eg. Touch Range)

Now i have started to write an Application Update Funktion, which
of course use also the 32kB Sectors.
But there I ran into a 'Prefetch Abort' Exeption, directly out
from IAP Erase Sector. Meaning my Code starts the Erase Function
(0x7FFFFFF1) and 'returns' at the 'Prefetch Abort' Vector.

Has someone any Idea, Hint, what the reason for that might be??

Prepare Sector look like:
#pragma location="IAP_PRG_ROM"
Int32U SysIAP_PrepareSec(Int32U Sec1Num, Int32U Sec2Num)
{
//---- Pren ob Sektor Nummern brauchbar
if(Sec2Num < Sec1Num)
{
return(IAP_STA_INVALD_PARAM);
}
//---- IAP Command Setup
_IAP_Command[0] = IAP_CMD_PrepareSec;
_IAP_Command[1] = Sec1Num;
_IAP_Command[2] = Sec2Num;
//---- Execute IAP
IAP_ENTRY(_IAP_Command, _IAP_Result);
//---- Return Result
return(_IAP_Result[0]);
}

Erase Sector:
#pragma location="IAP_PRG_ROM"
Int32U SysIAP_EraseSec(Int32U Sec1Num, Int32U Sec2Num)
{
//---- Pren ob Sektor Nummern brauchbar
if(Sec2Num < Sec1Num)
{
return(IAP_STA_INVALD_PARAM);
}
//---- IAP Command Setup
_IAP_Command[0] = IAP_CMD_PrepareSec;
_IAP_Command[1] = Sec1Num;
_IAP_Command[2] = Sec2Num;
//---- Execute IAP
IAP_ENTRY(_IAP_Command, _IAP_Result);
if(_IAP_Result[0] == IAP_STA_CMD_SUCCESS)
{
//---- IAP Command Setup
_IAP_Command[0] = IAP_CMD_EraseSec;
_IAP_Command[1] = Sec1Num;
_IAP_Command[2] = Sec2Num;
_IAP_Command[3] = CORE_FREQ / 1000;
//---- Execute IAP
IAP_ENTRY(_IAP_Command, _IAP_Result);
}
//---- Return Result
return(_IAP_Result[0]);
}

#pragma location="IAP_PRG_ROM"
Int32U SysIAP_WriteSec(Int32U iFlashAddr, Int32U iMemAddr, Int32U iSize)
{
//---- IAP Command Setup
_IAP_Command[0] = IAP_CMD_CopyRAMToFlash;
_IAP_Command[1] = iFlashAddr;
_IAP_Command[2] = iMemAddr;
_IAP_Command[3] = iSize;
_IAP_Command[4] = CORE_FREQ / 1000;
//---- Execute IAP
IAP_ENTRY(_IAP_Command, _IAP_Result);
//---- Return Result
return(_IAP_Result[0]);
}

CORE_FREQ is 72MHz, so CORE_FREQ/1000 is 72000kHz
The IAP_CMD Values are from User Manual and are corect working
with the small Sectors.
The '#pragma location="IAP_PRG_ROM"' Location is Sector 1 and 2,
which dont gets Updates.

The Application Code starts with Sector 3, the update works fine
until it reaches sector 8 (first 32kB) Sektor, there it ends up
with the 'Prefetch Abort', ....

Someone able to help me

mfg
Mike

An Engineer's Guide to the LPC2100 Series

--- In l..., "mike_schwarzer" wrote:
>
> Hi Guys,

> But there I ran into a 'Prefetch Abort' Exeption, directly out
> from IAP Erase Sector. Meaning my Code starts the Erase Function
> (0x7FFFFFF1) and 'returns' at the 'Prefetch Abort' Vector.
Hi Mike

Have you reserved 32 bytes at the top of RAM for use by the IAP?
If not the IAP execution may be corrupting stack and then a POP from the sub-routine may fail.

Regards

Mark

http://www.uTasker.com

Hi Mark,

> Hi Mike
>
> Have you reserved 32 bytes at the top of RAM for use by the IAP?
> If not the IAP execution may be corrupting stack and then a POP from the sub-routine may fail.
>
> Regards
>
> Mark

In the ICF I have defined the RAM as following:
define symbol __ICFEDIT_region_RAM_start__ = 0x40000040;
define symbol __ICFEDIT_region_RAM_end__ = 0x4000FFDF;
That should leave 64Bytes free at the beginning
and 32 Bytes at the end.
As these settings are working with the 4kB Sectors,
i think (hope) it should also work with the 32kB sectors

I use following sequenz to 'erase' the flash:
for(int iCnt = 3; iCnt < 22; iCnt ++)
{
//---- Erase Application Sector
if(SysIAP_EraseSec(iCnt, iCnt) != IAP_STA_CMD_SUCCESS)
{
while(1); // Erase Error
}
//---- Blank Check
if(SysIAP_BlankChkSec(iCnt, iCnt, &iError) != IAP_STA_CMD_SUCCESS)
{
while(1); // None Blank
}
}
When i cycle through that sequenz, sectors 3, 4, 5, 6, 7
get Erased (up to 0x7FFF)
When iCnt = 8 i can step through the complete loop, but
Sector 8 dont gets erased (IAR Memory View shows content as before
erase). But Blank Check says 'Success'
Some for Sector 9, Erase Sucess, Blank Check Success, but Content
as before.
Sector 10 (Last Application Sector) executes Erase Sucessfull.
Blank Checks ends up witch 'Prefetch Abort'.

mfg
mike

Hi Mark,

Additional Information:

The Loop has:
#pragma location="IAP_PRG_ROM"
#pragma optimize=none
So its in the 'protected' Region (Sector 1, 2) and all
optimiziation is turned off.

Also i have turned off all IRQ's:
iIrqState = __get_interrupt_state();
__disable_interrupt();

The IRQ Table itself is in Flash (0x0000 ....)

mfg
Mike

Hi Mark,

Next Confusing Issue.
Just for test, i have used sectors 11 upwards (just obove the
Application Prog. Space).
In that case everything works, erasing, blank check, writing.

So only some sectors (32kB) where the 'activ' Application
resides have troubles.
I would expect, that somewhere 'erased' Code would be used/called.
But if i single step though the loop i cant see any call/Adress
which is not in '#pragma location="IAP_PRG_ROM"'.
Can there be any 'hidden' Call, e.g. cstartup, or from IAR Debugger,
.... ???

mfg
Mike

--- In l..., "mike_schwarzer" wrote:

> I would expect, that somewhere 'erased' Code would be used/called.
> But if i single step though the loop i cant see any call/Adress
> which is not in '#pragma location="IAP_PRG_ROM"'.
> Can there be any 'hidden' Call, e.g. cstartup, or from IAR Debugger,
> .... ???

Hi Mike

I would set break points at the addresses 0xc and 0x18 [program abort and IRQ] (maybe not possible at the same time(?)).

When you get the program abort (it will break at 0x0c) you can see the offending address in LR (subtract 8 from it) - presumably it will be in one of your application areas which is being deleted at the time.

Maybe the IRQ masking is not working as expected - or maybe it is an FIQ which isn't masked by the call? Check the mask bits in the status register and set them off manually (using debugger) if in doubt.

When stepping, IAR will probably not allow interrupts to be called so there is probably a difference between stepping and running.

Regards

Mark

Mike,

as far as I understand you are executing out of the flash and try to
erase some other sectors of the flash. If you really attempt to do so, I
just wonder how this even works with some sectors. As far as I know (and
this is how I do) executing the routines doing the flash
erasing/programming should be located in RAM.

Best regards
Herbert

mike_schwarzer schrieb:
> Hi Mark,
>
> Next Confusing Issue.
> Just for test, i have used sectors 11 upwards (just obove the
> Application Prog. Space).
> In that case everything works, erasing, blank check, writing.
>
> So only some sectors (32kB) where the 'activ' Application
> resides have troubles.
> I would expect, that somewhere 'erased' Code would be used/called.
> But if i single step though the loop i cant see any call/Adress
> which is not in '#pragma location="IAP_PRG_ROM"'.
> Can there be any 'hidden' Call, e.g. cstartup, or from IAR Debugger,
> .... ???
>
> mfg
> Mike
>
--- In l..., groups@... wrote:
> just wonder how this even works with some sectors. As far as I know (and
> this is how I do) executing the routines doing the flash
> erasing/programming should be located in RAM.
>

Hi Herbert

Since the IAP routines are executed by the in-built program in an area at 0x7ffffff1 there is no reason to call this from RAM. The only thing that needs to be ensured is that the operation doesn't get interrupted by interrupts which could otherwise cause internal FLASH code to be executed during its operation.

Eg.
#define IAP_LOCATION (IAP)0x7ffffff1
// Thumb mode execution address of In-Application Programming routine
IAP iap_entry = IAP_LOCATION;
....
uDisable_Interrupt(); // protect FLASH routine from interrupts
iap_entry(command, result); // call the IAP routine
uEnable_Interrupt();
....
Regards

Mark

Hi Herbert,

> as far as I understand you are executing out of the flash and try to
> erase some other sectors of the flash. If you really attempt to do so, I
> just wonder how this even works with some sectors. As far as I know (and
> this is how I do) executing the routines doing the flash
> erasing/programming should be located in RAM.
>
> Best regards
> Herbert

The LPC2478 has the IAP Functions stored in some 'specal' ROM,
so there is no interference with normal Application Flash.

mfg
Mike

Hi, Mark

> Hi Mike
>
> I would set break points at the addresses 0xc and 0x18 [program abort and IRQ] (maybe not possible at the same time(?)).
>
> When you get the program abort (it will break at 0x0c) you can see the offending address in LR (subtract 8 from it) - presumably it will be in one of your application areas which is being deleted at the time.
>
> Maybe the IRQ masking is not working as expected - or maybe it is an FIQ which isn't masked by the call? Check the mask bits in the status register and set them off manually (using debugger) if in doubt.
>
> When stepping, IAR will probably not allow interrupts to be called so there is probably a difference between stepping and running.
>

It took some while to verify your sugestion's.
But as soon as i set a breakpoint, IAR Debugger runs in an error
condition (could not detect ARM Core, ....)
Which way that possible during a debug session, ....

Anything is doing as last description.

mfg
Mike


Memfault Beyond the Launch