We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hi.
I get the following error during runtime (after 8 sec run): "Non-aligned Access: ARM Instruction at 001042F8H, Memory Access at 00000001H Data Abort: ARM Instruction at 001042F8H, Memory Access at 00000001H"
The failing code contain debug code:
. . . unsigned int *dbgPinX, *dbgPin11 ... . . . if(ch & 0x01) { dbgPin11 = (unsigned int *)(pinsOledData+i); // for IO if (dbgPin11 > (unsigned int *)0x200000) dbgX=2; else dbgX=1; dbgPinX = dbgPin11; // THIS LINE CAUSE THE ERROR !!! ((pinsOledData+i)->pio)->PIO_SODR = (pinsOledData+i)->mask; } . . .
The statement in question is executed lots of times, but 8 sec after each program-start, this statement will fail (every run), with the above mentioned error-message !
If anyone can give me a clue, I'll apreciate that very much.
Regards Terje Bøhler
Have you made sure that:
dbgPin11 = (unsigned int *)(pinsOledData+i);
Results in a pointer that steps forward 4 bytes (sizeof unsigned int) for every increase of the variable "i"?
And by the way - have you made sure that "pinsOledData" isn't a NULL pointer?
If anyone can give me a clue,
Actually, your debugger already did. You just have to look at the writing on the wall a bit more closely. Does 00000001H really look like an address you should be trying to read a 32-bit integer from? Or anything at all, for that matter?
ARM7/ARM9 don't really like unaligned memory access, it's a classic reason ported code fails.
Even fewer processors likes NULL pointers.
Thank you all for comments! This problem seems more and more mysterious to me. The array of pointers are all assigned and properly initialised ("const ..."). I observed that the loopcounter for(i=0; i<8; i++) sometimes reached a value of 8 inside the loop! How can possibly a loop-couter exceeds its termination limit? This explains one type of error occuring: addressing element (pinsOledData+8) which don't exist. I have also seen the following error occuring:
... ((pinsOledData+i)->pio)->PIO_SODR = (pinsOledData+i)->mask; ... Fails for i=3, with the following output error-message: Non-aligned Access: ARM Instruction at 00104378H, Memory Access at 0000000DH Data Abort: ARM Instruction at 00104378H, Memory Access at 0000000DH
NOTE that PIO_SODR = 0x30 and all the 8 (0-7) pinsOledData[..] struct's are verified OK in const/ROM-segment (somwere above address 0x0100000). I got a feeling there is some strange timing-issues affecting (different) memory (segments). I then did the following test: Added some dummy time-consuming code immediate prior to the failing statement:
... dummy = 100; dummy = dummy/21; // TEB dummy added .. ((pinsOledData+i)->pio)->PIO_SODR = (pinsOledData+i)->mask; ...
... and then the error never occured !?
I will appreciate further comments on this matter. NOTE: I am running this code (written by others) on our own target via ULINK2 (and uV4).
Sounds like you suffer memory overwrites.
Timing shouldnt be an issue unless something is overclocked.
But bad pointers gives overwrites.
Have you followed your variable states? How long are they valid?
Hi Per. Sorry, but I did not understand your questions (new to ARM). Please clarify. Regards Terje
What part didn't you understand?
Any use of an uninitialized pointer means that the program may overwrite other memory regions that shouldn't be accessed - so more broken pointers can be created.
And any pointer to a 4-byte integer that hasn't an address that is 0, 4, 8, 12, 16, 20, ... will result in an unaligned access with your processor (it isn't so with all processors. Not even so with all ARM processors - a memory controller can solve an unaligned access by invisibly perform two accesses and a bit of shifting/masking).
Unless you are running the CPU core too fast, or you are running a memory (flash or RAM) too fast, then timing issues should not be able to result in problems with pointers. Every operation in your processor is performed synchronously, i.e. timed to a clock. So if something needs three clock ticks then the processor will wait three clock ticks for it to complete. But if the clock ticks have been redefined, so a 72MHz processor is initialized to run at 96MHz, then each tick will come too fast and bad things can happen. Same with external memory - an external memory chip might need 4 clock ticks when the clock is running at 72MHz. If that memory interface is instead configured to only wait 3 clock ticks then the memory will not be fast enough. Or if the clock frequency is configured to tick faster.
However - if your pointers are broken because they have been overwritten, or you have "overclocked" your processor or you just haven't correctly initialized them, you still need to debug your program. Step through the program and keep an eye open how far you can go before you see incorrect contents.
Problem solved. The code (which by the way was written by another programmer) was originally written under another IDE. I'm currently in the prosess of converting it to KEIL. So, here is the problem/solution: Originally written Interrup Service Routines (handlers) were by default named ISR_XXX. This would caused the local/old IDE's compiler to automatically treat it as an interrupt service routine, and add the required register bank switching at entry/exit. Under KEIL, another mechanism is used: Procedures are to be called XXX()__irq() to acheive register bank switching. So, the following happend: When the 1st interrupt occurred, at exit from the ISR, the registers contained "random values" (from the ISR) and hence, program failed ... simple as that ...
Regards Terje