After some study, trial and error, I created a simple project for a NXP LPC1768, to test its timer interrupt. This project contains only startup_LPC17xx.s, system_LPC17xx.c, C-main.c, and timer.c.
C-main.c:
#include "lpc17xx.h" #include "timer.h" extern uint32_t SystemFrequency; int main(void) { SystemInit(); Timer_Init_n_Enable( LPC_TIM0, (SystemFrequency/8-1) ); NVIC_EnableIRQ(TIMER0_IRQn); /* LED Init */ LPC_GPIO2->FIODIR |= 0x000000FF; /* P2.0 to P2.7 LEDs defined as output */ while(1); }
timer.c:
#include "lpc17xx.h" #include "timer.h" void TIMER0_IRQHandler(void) { LPC_TIM0->IR = (1u<<0); // Reset the MR0 Interrupt; Writing a zero has no effect. LPC_GPIO2->FIOPIN ^= (1<<7); // Toggle LED. } void Timer_Init_n_Enable( LPC_TIM_TypeDef * TimerX, uint32_t TimerInterval ) { TimerX->MR0 = TimerInterval; TimerX->MCR |= (1u<<0) | (1u<<1); // Interrupt and Reset on MR0 TimerX->TCR |= (1u<<0); // Enable Timer Counter and Prescale Counter }
This project seemed to work.
But if I change the timer.c to:
void TIMER0_IRQHandler(void) { LPC_GPIO2->FIOPIN ^= (1<<7); // Toggle LED. LPC_TIM0->IR = (1u<<0); // Reset the MR0 Interrupt; Writing a zero has no effect. }
It doesn't work.
If I change the timer.c to:
void TIMER0_IRQHandler(void) { LPC_GPIO2->FIOPIN ^= (1<<7); // Toggle LED. LPC_TIM0->IR = (1u<<0); // Reset the MR0 Interrupt; Writing a zero has no effect. NVIC_ClearPendingIRQ(TIMER0_IRQn); }
It seemed to works.
I guess that, it doesn't work because I clear the LPC_TIM0->IR interrupt flag too late, so the NVIC generates a pending interrupt for LPC_TIM0->IR.
I don't have a LPC23xx now, so I can't verify my guess. I guess that, it will still work:
void Timer0Handler(void) __irq { FIO2PIN ^= (1<<7); // Toggle LED. T0IR = 1; /* Clear Interrupt Flag */ VICVectAddr = 0; /* Acknowledge Interrupt */ }
I think it is usual that, programmer needs to do something to identify which kind of interrupt was triggered, before clear the interrupt flag.
So, if my understanding is correct, how do I know that, I did NOT clear the interrupt flag too late within an ISR?
It is quite frustrated that, I can't even handle a simple timer interrupt properly. Maybe my understanding has never been correct.
Hi John,
Quite likely the issue here is that the ISR ends before the bus cycle for accessing the interrupt flag has completed. Just spending a bit more time in the ISR and clearing the flag as early as possible should help. You might also try if a synchronization barrier (DSB) after clearing the flag helps. Pulse interrupts also help but might not always be available.
Regards Marcus http://www.doulos.com/arm/
That would be a possibilty that NXP would need to answer - it has nothing specifically to do with Keil.
It might also be specific to NXP's implementation - so that ST's examples would not be applicable...
"It might also be specific to NXP's implementation - so that ST's examples would not be applicable..."
I don't think so. I don't think NXP have any options open to them in this case, given the integration of the NVIC in the core.
But the help function in the ST example may represent extra clock cycles explaining the problem with the NXP chip and inlined acknowledge of the timer flag directly before the return.
"I don't think so. I don't think NXP have any options open to them in this case, given the integration of the NVIC in the core."
You may well be right; but NXP would be the ones to confirm it - rather than Keil.
Or, perhaps, the core documentation from ARM.
Or The Definitive Guide to the ARM Cortex-M3 by Joseph Yiu - see: http://www.keil.com/books/armbooks.asp
Or it might be an interaction between the NVIC and the Timer (which is NXP-specific)...?
When I said "It doesn't work", I mean "LED doesn't toggle."
LPC1768 has been released to the market for quite a long time, and I did check the errata, it did not mention anything about Timer or "bus cycle for accessing the interrupt flag".
Base on your replies, I guess that, my understanding is not that incorrect, and though I can "clear the interrupt flag first", but "just toggle a LED" before "clear the interrupt flag" should be fine. Am I right?
The LPC1768 MCU I am evaluating, is a '-' Initial device revision MCU. I think that, the symptom I observed, is quite easy to reproduce. I don't know how to contact NXP, and will not try to contact NXP at the moment. I need to pass the trial period first.
RTC doesn't work, Strange Timer behavior, sounds like I am a quite lousy programmer.
Many thanks for your kind help.
Is your RTC powered? It is in a separate power domain.
When you only use one interrupt source from a device and that source have limited interrupt repeat time, then it doesn't matter where you acknowledge the interrupt source.
If the interrupt source can have short spans between interrupts, then you should acknowledge the interrupt source as soon as possible so the bit is ready to latch next interrupt from that source.
I think my RTC is powered. It has the main power, and also a battery. I found out that, even it has the main power, it still needs a battery.
[3] The RTC typically fails when Vi(VBAT) drops below 1.6 V.
The Errata did not provide enough information about RTC problem, my google search tell me that, "The Real Time Clock (RTC) does not work reliably within the temperature specification." (from Errata) means, most RTC on the '-' revision LPC1768 will NOT work.
Your first point of contact should be your Distributor.
Don't NXP have forums any more?
"I did check the errata"
It may not be an erratum - it might be "expected behaviour".
"RTC doesn't work, Strange Timer behavior, sounds like I am a quite lousy programmer."
Don't be so hard on yourself.
Like many things, it's common to have a number of problems and questions when you start working with a new processor. It's all part of the learning curve - at least that's my experience.
The NXP forum might be worth a try, but the one I look at has plenty of questions and precious few answers.
Try here:
http://forums.nxp.com/
Indeed it is!
And it is the role of a good technical Distributor to support you through the learning curve.
All the manufacturers (including NXP) are pushing their Cortex offerings hard at the moment, so there are lots of training opportunities - many free!
For example, see: http://www.keil.com/events/
I think the RTC problems are only related to the temperature span - but alas, NXP don't want to give any information about what the safe temperature span is. I have been looking at replacing 23xx with 17xx but avoided it because of the RTC issue.
> I did check the errata, it did not mention anything about Timer or "bus cycle for > accessing the interrupt flag".
As Andrew noted before, the reason is that this wouldn't be an erratum. It is a feature inherent in the architecture. I'll spare you the details, but simply put, Cortex-M3 has two independent bus interfaces for instructions and data respectively. Your memory access is using the data port (and waits for the APB bus cycle to finish), while the instruction port keeps fetching more code which gets executed. The ISR return might execute before the data bus access has completed, so NVIC thinks that the (still) active IRQ was a new one.
-- Marcus
void TIMER0_IRQHandler(void) { LPC_TIM0->IR = (1u<<0); LPC_GPIO2->FIOPIN ^= (1<<7); //=> LPC_TIM0->IR cleared already. } //===========================================> The ISR return.
void TIMER0_IRQHandler(void) { LPC_GPIO2->FIOPIN ^= (1<<7); //=> instruction port: done. LPC_TIM0->IR = (1u<<0); //=> instruction port: done; data port: not yet, LPC_TIM0->IR not cleared. } //===========================================> The ISR return. //===========================================> NVIC works on next Interrupt Handling. //===========================================> NVIC gets a LPC_TIM0->IR flag.
void TIMER0_IRQHandler(void) { LPC_GPIO2->FIOPIN ^= (1<<7); LPC_TIM0->IR = (1u<<0); NVIC_ClearPendingIRQ(TIMER0_IRQn);//=> LPC_TIM0->IR cleared already. } //===========================================> The ISR return.
Many thanks to Marcus.
I guess, If I am really trying to identify the interrupt source first, then clear the related interrupt flag right after, this symptom will not occur. Because before the ISR returns, all the interrupt flag updating has been done already.
I just joined the new company around two months. The trial period of new employee is generally three months. Somehow I can not get any available hardware for my development. (Just like in my ex-company.) So my supervisor let me use my private evaluation board, which I bought from eBay/ruten last year for personal study purpose. My supervisor asked me to do some basic practices like Key-Input and De-bounce, RTC based Date/Time Displaying. Actually most people here, don't know anything about ARM. I was told that, if I prefer ARM and I can handle ARM, I can use ARM for new projects; but it is quite doubtable. And in the Taiwanese culture, it is not wise to do something unusual, or ask for outside training of new technology, when you are the new guy.
RTC doesn't work, Strange Timer behavior, sounds like you are a quite lousy programmer.
MCU/Embedded System is very platform dependent; Yes, I know.
Good luck with the new job then.