Enabling and disabling CCR interrupts on a running timer.
Hello all.
I am trying to set up a continuously running timer to use to set of interrupts at specific counts of the timer. So the user of this thing would say "setAlarm(n)" and at timer=n an interrupt goes off. But I also want interrupts for the ccr to be off when no alarm is set.
The end use case is a bit more complicated, I try to use the 32bit timer to emulate a 64bit timer and use the overflow interrupt to increment an "extra" 32 bit word. So the ISR is a bit complicated.
The ISR currently looks like this:
uint32_t hw = counter_high_word;
if (tim->SR & 0x1 ) { /* This indicates and update event (overflow?) */
/* TODO: Not 100% certain this is definitely an overflow. Couldn't it
be other "events"? */
uint32_t sr = tim->SR;
sr &= 0x1 & STM32_TIM_DIER_IRQ_MASK;
tim->SR = ~sr; /* clear update event flag */
counter_high_word++;
if (alarm.active) {
if (counter_high_word == alarm.alarm_time >> 32) {
tim->CCR[0] = (uint32_t)alarm.alarm_time;
tim->DIER |= 0x2; /* activate interrupt on ccr channel 1 */
}
}
}
if (tim->SR & 0x2) {
uint32_t low_word;
uint32_t high_word;
Time time;
uint32_t sr = tim->SR;
sr &= 0x2 & STM32_TIM_DIER_IRQ_MASK;
tim->SR = ~sr; /* clear ccr event flag */
tim->DIER &= ~0x2; /* disable interrupt on ccr channel 1 */
low_word = tim->CNT;
time = hw;
time <<= 32;
time |= low_word;
svm_msg_t msg;
msg.sender_id = SYS_TIME_SENDER_ID;
msg.timestamp = time;
msg.data = 0xDEADBEEF;
msg.msg_type = 0;
osalSysLockFromISR();
interop->send_message(interop, msg); /* check for error */
osalSysUnlockFromISR();
alarm.active = false;
}
There are some parts of this that uses mailboxes from chibios. But this is inconsequential to the issue, i believe.
The ISR has two different modes. Either there was an overflow and we we increment the "high word", then we check if there is an alarm set in the next 32bit low-word window. if you put that low word into CCR and activate interrupts.
The code that sets an alarm looks like this.
high_word = counter_high_word;
if (high_word == alarm.alarm_time >> 32) {
tim->CCR[0] = absolute; /* low 32 bits */
tim->DIER |= 0x2; /* enable interrups on CCR[0] */
} else {
tim->DIER &= ~0x2;
}if the alarm is within the current 32 bit low-word window. write the low word to CCR and activate interrupts for that CCR. if the alarm is not in the window, then interrupts for CCR is disabled.
I cannot seem to get the disabling of the CCR interrupt to work. Do you need to do something to make that piece of configuration stick. I do not want to stop the timer or restart it or anything like that. The timer should be free running that is essential to the application.
So what I want to learn is, if I do tim->DIER &= ~0x2 should interrupts be immediately disabled? or is there need for some kind of memory barrier or some other means of telling the TIM to make this configuration "stick". Or am I totally confused about enabling and disabling interrupts on CCR at all.
Thank you all and have a great day!
