Content originally posted in LPCWare by 0xdeadbeef on Wed Apr 23 11:20:42 MST 2014
In a project I'm using a timer like this (my own code looks different due to macros etc, but functionally this should be identical):
LPC_TIM3->MR0 = 6000; // match at 6000 ticks
LPC_TIM3->IR = 1; // clear MR0 interrupt flag
LPC_TIM3->CTCR = 0; // timer mode
LPC_TIM3->MCR = 7; // interrupt on match, stop timer on match, reset timer on match
LPC_TIM3->TCR = 1; // enable timer
Note that in my real program, the write access to TCR to start the timer is done via DMA.
Furthermore, the interrupt request actually triggers another DMA transfer, so there is no interrupt handler and the interrupt request flag is never cleared.
Now while this seems to work exactly as expected, I have cases where I want to update the match register.
To do this in a safe way, I first disable the DMA transfer that could restart the timer. Then I want to make sure that the last match already happened by
waiting until the timer is stopped/reset (note that I can't use the interrupt flag as this is always set due to the absence of an interrupt service routine).
According to the manual, the enable bit in TCR should be erased and TC should be 0 after the match:
Stop on MR0: the TC and PC will be stopped and TCR[0] will be set to 0 if MR0 matches the TC.
Reset on MR0: the TC will be reset if MR0 matches it.
However when I try to poll for either ((TCR1 & 1) == 0) [timer was disabled] or (TC==0) [timer was reset], I'm stuck in an endless loop sooner or later.
If I break there, I can see that the TC==MR0==6000 and TCR=1. So the match occurred and TC is not changing anymore, but neither was the timer
reset nor was the enable bit erased - even though the timer is obviously stopped.
Only when I also erase the interrupt service flag inside my polling loop, the enable bit is really always erased.
Even then though, the TC is not (always) reset and I have to do it manually to avoid hangups.
I can't find any hint in the manual that there reset/stop is only correctly performed when the IR flag is reset or that the combination of STOP and RESET
doesn't work reliably. So is this a flaw or the way it should be???