This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

TIMER1 compare not triggered for CC=0x00

I am using a TIMER1 compare event to generate an interrupt. Generally the code all works fine, but I have noticed some strange behaviour when loading the CC register with 0x00. If the timer is allowed to run freely and overflow, then it is possible to generate a compare event when the timer rolls-over to 0. No problem there. But then I tried to limit the maximum timer count using;

NRF_TIMER1->SHORTS |= TIMER_SHORTS_COMPARE2_CLEAR_Enabled << TIMER_SHORTS_COMPARE2_CLEAR_Pos;
NRF_TIMER1->CC[2] = T1_TICKS_MAX;

My understanding is that this should cause the timer to reset to zero when it hits the value in CC2 (T1_TICKS_MAX). However, when I do this I no longer get any compare events generated for CC=0x00. Any other CC value less than or equal to T1_TICKS_MAX works fine.

This seems a bit unexpected to me. Is this normal behaviour? Or do I perhaps have a bug in my code somewhere?

  • Thanks for the suggestion to change the timer max count to 0xFD (or 0xFFFD in 16-bit mode). I think this would solve the problem for that particular compare channel (CC1). However, I am also using other compare channels (eg CC2) at the same time for different tasks. In my code the TIMER1 resources are shared by two different independent modules. If I change the max timer roll over value it will inadvertently affect both COMPARE events - not just the one that required the compare event at 0x00. I don't think this solution is going to work for me.

    I am actually using 16-bit mode, not 8-bit mode. I may have made some typos when giving register values. Where I said 0xFE I actually meant 0xFFFE. 0xFF should have been 0xFFFF, etc. Sorry for the confusion.

  • when you change the roll over value, you need to fix all compare channels like you change CC1 value from 0 to 1, you need to increase CC2 by 1 (with modulo). This should be enough for your case. If i am not wrong, then you are designing a real time scheduler, which accepts scheduling request and then add offset to the compare channel. Adding 1 to fix the jitter should not cause problem. when you fix the roll over value from 0XFFFD to 0XFFFE, you should decrement 1 from other compare channels

  • I see what you mean. Thanks for the suggestion. But I think there are a couple of issues that will complicate this solution.

    First, it requires me to update multiple register values while the timer is running. In an ideal implementation all the CC registers (including ones that are used for scheduling and to set the roll-over value) would be updated atomically, within a single clock cycle. But in reality I can't achieve this and some registers will be updated before others. If I decrease the roll-over CC register before increasing (with modulo) the scheduler CC register then I run the risk of missing the compare event. If I update the registers in the reverse order then I run the risk of getting two compare events.

  • Second, if I decrease my timer roll-over value to 0xFFFD then at some point I must increase it back to 0xFFFE. If I don't, then my roll-over value will continue to decrease each time I try to schedule a compare for 0x0000. Eventually my roll-over value will reach 0. Granted, this will only occur after many hours of running. But it is still a problem nonetheless.

  • for your first comment, yes these complications occur when you have to update multiple registers. When you are updating a particular CC register, does it makes sense to disable the event, modify and enable. But i see your point, and the fact is all these corner cases add complexity to the logic and not all of them can be solved atomically. for your second comment, yes, like i mentioned you should set back the rollover value when the addition of offset and then % does not give 0.

Related