Yesterday I've opened a thread about a system crash after the execution of an IRQ routine. After many tests I've isolated the problem and symplified the context in which it happens.
Now the problem I see is the following.
I've only an IRQ routine linked to CPU timer 0. It should be invoked every 1 ms. However after the first call the CPU switches to DATA ABORT mode.
I configure LPC2378 (rev. B) with 72 MHz clock and MAM fully enabled (the problem is present olaso with MAM partially enabled). The source code is the following
/************************************************* ** INITIALISING FUNCTION **************************************************/ void ini_base_timer(void){ PCONP |= (1 << 1); /* power up timer 0 */ T0TCR = 0; /* disable timer 0 */ PCLKSEL0 |= 0x00000004; /* timer 0 clock = PCLOCK */ T0IR = 0x11; /* reset irq flag */ T0CTCR = 0; T0PR = 8; /* prescaler */ T0MR0 = 7999; /* match register 0 */ /* configuration vectored interrupt */ VICIntEnClr |= (1 << 4); /* irq disabling */ VICIntSelect &= ~(1 << 4);/* IRQ interrupt */ VICVectPriority4 = 8; /* priority */ VICVectAddr4 = (UINT32)&irq_base_timer; /* ISR */ VICIntEnable |= (1 << 4);/* irq enabling*/ T0MCR |= 0x03; /* irq enabling and TC reset on match register 0 value */ T0TCR = 0x01; /* start timer */ } /* end ini_base_timer */ /************************************************* ** IRQ FUNCTION (ISR) ** global variables: ** long sd[32]; // global array ** unsigned char buffer_rx_fw[512]; // global array **************************************************/ void __IRQ__ irq_base_timer(void){ UINT32 cont; FIO4SET = 0x01; /* set GPOUTPUT 4.0 */ T0IR = 1; /* irq flag reset */ for(cont = 0; cont < 2; cont++){ if(sd[31] == cont){ sd[30]++; if(sd[30] == buffer_rx_fw[cont]) sd[28]++; } /* end if */ } /* end for */ FIO4CLR = 0x01; /* clear GPOUTPUT 4.0 */ VICVectAddr = 0; /* dummy write */ } /* end irq_base_timer */
In this condition the problem is deterministic in the sense that every time after the first execution of irq function, CPU switches to DATA ABORT mode (the system crashes!). If I execute code step-by-step in assembly mode I see that when micro exits from irq function the LR register contains the address of an instruction that causes DATA ABORT exception. I don't know how a simple IRQ routine can generate such terrible problem!
I'm using GCC compiler (ver. 4.0.3) with optimization level 1. If I put optimization level to 0 (zero) the system doesn't crash, however the assembly code produced is so redundant to degradate system performance too much!
Have you any suggestions?
Thank you,
Demis
Have you set up any IRQ stack?
Sure, I've configured all stacks. In particular for IRQ stack I've reserved 256 byte. Moreover, as I've explained in yesterday thread, I can check the maximum usage of each stack until system crashes and I see that each stack is used within its boundary.
It's a very very strange problem...
Don't start new threads to continue the discussion of an existing problem.
You haven't shown the definition of the sd variable, so we don't know if those assigns are to valid memory.
I apologize for having opened another thread on the same problem. I made this because I've simplified the problem so I've tought it would be better to present it in a new thread. Anyway, I'll never do it again, sorry.
I've shown the definition of sd variable in the comments of the irq function. I report it below
long sd[32];
Demis, Does your controller also crash when the ISR is emptied, hence contains only absolutely essential stuff?
No, if the irq is empty the system doesn't crash.
Yes, I did see the comment, but always prefer to se the actual code line where variables are declared.
Too often, comments and actually code does separate things.
Demis, Is your sd variable located at an exotic location in memory? what happens if you keep the loop but remove all referneces to sd? did you check your map file? are you using an RTOS with a memory manager? if not, did you check the address of sd just before writing to the momery pointed by it?
No, sd variable is located correctly at valid RAM address (I looked at map file more and more times to check possible address troubles...). However the crash happens even if I don't use sd inside the irq function. The only difference is that if I use the loop with sd the crash is deterministic, i.e. it happens every time at the end of the first execution of irq function. Otherwise it happens after a random number of irq executions.
I don't use any RTOS.
Demis, If I were you, I'd do the following: Create a new test project which does nothing but setting up the timer of your and handle the interrupts. Does it still crash? If so, then it is either your project settings, memory map, initialization code in main, etc. If not - well, then it is some kind of interaction with another part of the program. it is hard to tell from a distance.
Thanks for all your suggestions. I compiled the irq function in another file without any optimization (optimization level 0) and all seem to work well. My suspect is that there is a bug inside gcc compiler when it is used with optimization level equal to 1.
Regards,
See Errata for LPC2378. As it belongs to the same sub-family (LPC2364,LPC2366,LPC2368,LPC2378) I think you could be tasting one of the chip bugs. Especifically Core.1 problem. Try inserting a "NOP" instruction in between the 3 instructions before the last LDR instruction executed.
Thanks for your suggestion, however the Core.1 problem refers to code generated in Thumb state but I don't use it. So I don't think this is the cause of my problem.
If I execute code step-by-step in assembly mode I see that when micro exits from irq function the LR register contains the address of an instruction that causes DATA ABORT exception.
This "feature" of GCC bites more often than it ought to, but do not take my words in a blind faith, read those: tech.groups.yahoo.com/.../29435
Google is *your* friend, too: gcc.gnu.org/.../msg01563.html