Cant run code from Flash MCF52xx

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Cant run code from Flash MCF52xx

832 Views
DaveTonyCook
Contributor IV

Hi,

I have found that the code programmed into the internal FLASH of the MCF5216 processor will not run when the code footprint exceeds a specific flash block boundary.

 

The project runs without problem until I increase the executable code size past the 0x40000 mark. The processor will run if I run up to the call and then step over, then continue.  The processor throws an exception if it executes at full speed.

 

I set the project up to have a file named bloat.c and added code until the .text section grew past the 0x00040000.  The code added did nothing eg foo_n(1); where void foo1(int x){switch(x){case 0:break;...so on}} and repeat 'ad nauseum'. Adding calls at 75 bytes/call until my app reached the required address to show up the issue.

'

512k flash part

CW 6.4

Code generation details:

Far code

Far data

compact memory model

 

I have double checked my LCF and it appearers to be without fault.

 

I set up two examples:

1. Below is the function check_memory() which makes a call to subroutine strcmp(). The address’s shown have been recorded from the .map file and show that the call made by the check_memory() is made across the flash block boundary of 0x0004_0000. This code throws an exception. The exception makes no sense. Please see stack frame below

 

Address in FLASH

Function name Called

Source Module

Memory Section

0000_3000

 

 

 

0001_EF5C

 

 

 

0004_006C

an_other_function()

.

.

.

check_memory()

.

.

.

strcmp()

 

an_other_module.c

.

.

.

  1. utility.c
...C_4i_CF_MSL.a
.text....text .text

2. below shows the function check_memory() which makes a call to subroutine strcmp(). The address’s shown have been recorded from the .map file and shows that the call made by check_memory() does not make the call across the flash block boundary of 0x0004_0000. This code runs correctly.

 

Address in FLASHFunction name CalledSource ModuleMemory Section
0000_3000 0001_EF54 0003_FFF0an_other_function()...check_memory()...strcmp()an_other_module.c...
  1. utility.c

.

.

.

C_4i_CF_MSL.a

.text

.

.

.

.text

 

 

 

.text

 

Below is the ‘exception stack frame’ contents just after the exception has been generated by the processor.  The stack frame has been recorded from the stack frame contents captured during a debug cycle and reports the following information:

 

Stack frame

General Description

Value

Description under fault

Format

Records any long word stack pointer misalignment

0x04

?

Fault status

Fault code generated by processor

0x0F

Unsupported on V2 core

Vector

Identifies exception type

251

User interrupt

Program counter

Value just before fault

0x70001F40

Garbage (doesn’t exist)

 

Interestingly enough there is also a call to the sin() library routine that is located at > 0x0004_0000 and this does not cause an exception. I might hazard a guess that it has something to do with operations on memory?

 

Any help greatly received

 

Regards

 

David Cook

Labels (1)
Tags (1)
0 Kudos
5 Replies

530 Views
TomE
Specialist II

> MCF5216


512k of FLASH from 0x00000000 to 0x0008000. So the problem is happening at the boundary between the first and second 256k parts. That must mean something.

> bloat.c

It should make testing easier if you put the upper half of your test code in a "named section" (probably with a pragma of some sort) and then change the linker file to put that where you want it. You'll then be able to position that section at different addresses like 0x3FFFe, 0x40000, 0x40002, 0x40004 and so on to try and decode what the problem is.

> Adding calls at 75 bytes/call

That has to be an even number. The ColdFire can't execute on odd boundaries. Function addresses are normally rounded up to the next 4-byte boundary, and sometimes to a 16-byte boundary.

> Below is the ‘exception stack frame’ contents


Don't decode it. Please capture the raw and complete stack frame (with the value of the stack pointer) on an instruction before the crash and then again after. There might be multiple stack frames from multiple exceptions, and the previous ones might give more information. Since the CPU is crashing and then entering the debugger, it may not be giving you the correct frame information as the entry into the debugger may not have been "clean".


Suggestions.

First, you may have a faulty part with hard or soft errors in its FLASH. Try another part.


Check that all of the Power Supplies and Grounds are connected, noise free, bypassed and at the proper voltage.

Read the Errata and make sure you don't have a very old part with a datecode prior to XXX0327.

Make sure your code isn't in violation of SECF005. There must be a "NOP" after all writes to CACR.

Check the value of FLASHBAR against the manual.

The CPU seems to be reading a bad value from the FLASH when it crosses that boundary. It may have been programmed/written wrong, so you should dump the Flash and compare the function that fails with the HEX or BIN file.

Fill the FLASH with data patterns (all zeros, all ones, alternating bits) and verify that it reads back OK. Your problem looks like it might be a "stuck bit" that only causes a problem when an instruction is in the right location to be corrupted "just so".

Make sure the Programmer has been told how fast your CPU clock is. When programming the FLASH it has to set CFMCLKD up to generate a valid clock. If this is out of spec the FLASH may be programmed badly and may be returning bad values as a result (it may be "half-programmed").

If the FLASH looks OK when read from the debugger, write some code to read it to RAM and then compare with the expected values.

If you're running with the Cache enabled, see if running with it off changes anything (single reads versus cache-line-fill burst-reads). Try invalidating the Cache before your test and see if it changes. Try all combinations of CACR[DISD] and CACR[DISI]. Run with the Cache Off on the FLASH but test with CACR[CEIB] on and off. Ditto CACR[DBWE] just in case.

Check the values written to CACR, ACR0 and ACR1. Are you mapping the Flash with one of the ACRs? Is it masking all or half of the Flash? Try changing the ACR to only map the upper or lower half and see if the symptoms change.

Change the CPU speed. Make it faster and slower and see if that changes anything. Make sure you don't have any interrupts or DMA enabled as that will complicate things. Make sure the Watchdog is disabled.

Assuming none of the above helped, I suspect the CPU is fetching a bad instruction and then jumping somewhere stupid. It then gets an exception. If there's no proper exception handler it will keep getting errors until if finally gets a fatal error, or runs into something the debugger has trapped ,or bombed the stack. By that time it has had so many faults it has wiped out any information that may help you. So you want to stop it ASAP. So you should add interrupt vectors for *ALL* interrupts (so that all 255 of them are covered). Point them to a small handler and put a breakpoint in there. That may stop it sooner. Fill the stack with a known patters so you can see where the CPU has been.

If all else fails, program a PIT or DMA timer to give an IPL7 interrupt. Then use it as a "timed breakpoint". Start it in your code that is "heading for the boundary" and try to set the timer to get an interrupt exactly on the first instruction that it goes crazy on. The Stack Frame will show the PC where it was interrupted.

Tom

0 Kudos

530 Views
DaveTonyCook
Contributor IV

>MCF5216

>512k of FLASH from 0x00000000 to 0x0008000. So the problem is happening at the boundary between the first and second 256k parts. That must mean something.

So it seems, however this is not always the case, eg sin() is called and it resides in the upper 256k and executes okay. Also if the instruction is executed in single step mode it runs fine ie run to problem, single step instruction, then execute at full speed. works fine.

> bloat.c

>It should make testing easier if you put the upper half of your test code in a "named section" (probably with a pragma of some sort) and then change the linker file to put that where you want it. You'll then be able to position that

>section at different addresses like 0x3FFFe, 0x40000, 0x40002, 0x40004 and so on to try and decode what the problem is.

Will try this.

> Adding calls at 75 bytes/call

>That has to be an even number. The ColdFire can't execute on odd boundaries. Function addresses are normally rounded up to the next 4-byte boundary, and sometimes to a 16-byte boundary.

Sorry, the function is 75hex (116) Bytes.

> Below is the ‘exception stack frame’ contents

> Don't decode it. Please capture the raw and complete stack frame (with the value of the stack pointer) on an instruction before the crash and then again after. There might be multiple stack frames from multiple exceptions, and the previous

> ones might give more information. Since the CPU is crashing and then entering the debugger, it may not be giving you the correct frame information as the entry into the debugger may not have been "clean".

Will do this, although I dont know how to achieve this as it crashes inside the lib function.


>Suggestions.

>First, you may have a faulty part with hard or soft errors in its FLASH. Try another part.

Tried parts from different batches. Same problem.

>Check that all of the Power Supplies and Grounds are connected, noise free, bypassed and at the proper voltage.

Will do this today

>Read the Errata and make sure you don't have a very old part with a datecode prior to XXX0327.

Already ruled this out. Date code on our devices is XXX1122

>Make sure your code isn't in violation of SECF005. There must be a "NOP" after all writes to CACR.

We don't use cash. Cash is off.

>Check the value of FLASHBAR against the manual.

From mcf5282_lo.s

Initialize FLASHBAR: locate internal Flash and validate it Initialize RAMBAR0: This is the FLASHBAR  Leaving bit 6 in the FLASHBAR register cleared can cause corrupted fetches from the device's internal flash so set bit 6 here. see chip errata SEC004

move.l#(___FLASH_START + 0x161),d0

movec d0,RAMBAR0

From mcf5282_lo.s.list

0x00000010: 203c00000161                        move.l       #(___FLASH_START + 0x161),d0

0x00000016: 4e7b0c04                            movec        d0,RAMBAR0      

From manual

0xC04 Flash Base Address Register 0

>The CPU seems to be reading a bad value from the FLASH when it crosses that boundary. It may have been programmed/written wrong, so you should dump the Flash and compare the function that fails with the HEX or BIN file.

This is done when the flash programmer performs a verify, does it not? (integral flash programmer supplied with CW 6.4)

>Fill the FLASH with data patterns (all zeros, all ones, alternating bits) and verify that it reads back OK. Your problem looks like it might be a "stuck bit" that only causes a problem when an instruction is in the right location to be >corrupted "just so".

Not done yet.

>Make sure the Programmer has been told how fast your CPU clock is. When programming the FLASH it has to set CFMCLKD up to generate a valid clock. If this is out of spec the FLASH may be programmed badly and may be >returning bad values as a result (it may be "half-programmed").

If this was the case why would it only effect code written to the upper 256k, Also I would not be able to single step the instruction without it crashing, however I will check it.

>If the FLASH looks OK when read from the debugger, write some code to read it to RAM and then compare with the expected values.

Not done yet

>If you're running with the Cache enabled, see if running with it off changes anything (single reads versus cache-line-fill burst-reads). Try invalidating the Cache before your test and see if it changes. Try all combinations of >CACR[DISD] and CACR[DISI]. Run with the Cache Off on the FLASH but test with CACR[CEIB] on and off. Ditto CACR[DBWE] just in case.

Not using Cashe

>Check the values written to CACR, ACR0 and ACR1. Are you mapping the Flash with one of the ACRs? Is it masking all or half of the Flash? Try changing the ACR to only map the upper or lower half and see if the symptoms >change.

We don't use cache

>Change the CPU speed. Make it faster and slower and see if that changes anything. Make sure you don't have any interrupts or DMA enabled as that will complicate things. Make sure the Watchdog is disabled.

Not done yet

>Assuming none of the above helped, I suspect the CPU is fetching a bad instruction and then jumping somewhere stupid. It then gets an exception. If there's no proper exception handler it will keep getting errors until if finally gets >a fatal error, or runs into something the debugger has trapped ,or bombed the stack. By that time it has had so many faults it has wiped out any information that may help you. So you want to stop it ASAP. So you should add >interrupt vectors for *ALL* interrupts (so that all 255 of them are covered). Point them to a small handler and put a breakpoint in there. That may stop it sooner. Fill the stack with a known patters so you can see where the CPU >has been.

I already trap all exception and have implemented just as described above. However initialising stack to a set pattern is a good tip thanks

>If all else fails, program a PIT or DMA timer to give an IPL7 interrupt. Then use it as a "timed breakpoint". Start it in your code that is "heading for the boundary" and try to set the timer to get an interrupt exactly on the first >instruction that it goes crazy on. The Stack Frame will show the PC where it was interrupted.

Will try this as a last it resort

Thanks for the advice. It will take some time for me to get round to all the suggestions. I'm going to start with a simple base project to see if I can replicate issue on a simpler app. and take it from there.  I will update this post with my findings.

Dave

0 Kudos

530 Views
TomE
Specialist II

Also, fill the rest of Flash with an illegal opcode, so if it manages a bad jump within the Flash it will stop dead/ There is a designated "ILLEGAL" opcode for this purpose. Just fill unused Flash with 0x4AFC.

Tom

0 Kudos

530 Views
DaveTonyCook
Contributor IV

Solved this issue.. The flash programming algorithm had not been followed.  I inherited the code so didn't look too carefully at the implementation as it had been running okay until the code crossed the 256k boundary, and the behaviour I was observing didn't appear to be helpful however the problem was that whilst the CBEIF bit was being checked the CCIF bit wasn't.  The result is that if your running from flash then you will run into difficultly if the device has not finished programming!! Simple in the end

0 Kudos

530 Views
TomE
Specialist II

> single step instruction, then execute at full speed. works fine.


It is something to do with the pattern of reading. It may be related to prefetching. Some CPUs have problems with code at the very end of a block of memory if the CPU speculatively prefetches "off the end" and into memory that doesn't exist. This is unlikely to be happening to you as you're running in the MIDDLE of a block of memory and not at the end. There could be a timing problem inside the Flash though. It may be built of two blocks of 256k, and something may go wrong when the two blocks are accessed with exactly the right/wrong timing.


>> please capture the raw and complete stack frame

> Will do this, although I dont know how to achieve this as it crashes inside the lib function.

The debugger should show you the value of the stack pointer and should also allow you to examine a block of memory. You want the value of the stack pointer before you make the code "run" over where it crashes, and then the value after it has crashed. Then print the memory contents from the first value down to (and beyond) the second one. Then you manually decode the stack. I've done this a lot.

> We don't use cash. Cash is off.

So turn the CACHE on and see if the problem changes. With the cache on the CPU should be performing complete cache-line-fill reads, reading 16 bytes at a time. This may avoid whatever memory cycles are causing the problem with the Flash.

There may be a design fault, but nobody else will have ever seen it because NOBODY runs code on these CPUs with the cache off. I'm kidding (slightly), but this may be related to the problem. This chip only runs at up to 80MHz and the Flash can almost keep up with that (it performs "interleaving and speculative reads"), so the cache doesn't make that much difference, but on the chip I work on (MCF5329) running at 240MHz with an 80MHz bus clock and slow FLASH it makes a huge difference, especially as the Flash and SDRAM give a lot of wait states on the 80MHz clock.

I would also suggest ENABLING the Cache, but then setting it so that all caching is DISABLED. Yes, the cache can be enabled, but for no address regions. Then enable "Cache enable non-cacheable instruction bursting" and see if the problem goes away as that should read the Flash with different memory cycles.

Here's another thing. If it is getting intermittent read errors in a bit and you can't cause this by reading the Flash as data, then if you enable the Program and Data cache you might be able to run the code over the bad fetch and have it crash. If you can recover/trap the crash, then read back the same memory locations, the COPIED values will be read from the cache. That would allow you to see the bad value that the CPU fetched then, and not the value that you can read from the Flash now. That might show a difference. This is of course relies on getting a lot of things right.

It would be very nice to track this down to the root cause, but if you can find a workaround it allows you to ship products.

>> >Make sure the Programmer has been told how fast your CPU clock is.

> If this was the case why would it only effect code written to the upper 256k,

Flash is internally Analog and not Digital. It is possible to "half program" a cell so that it is very close to the decision margin and can read high or low depending on noise and other cycles in the chip.

Tom

0 Kudos