2023-09-10 06:44 PM
Hi everyone, I meet a problem and I'm not sure it's MCU issue or I program not proper.
I meet this issue both on the STM8 and STM32 MCUs.
I enable TIM_2 Ch1 as input to capture the signal and TIM_2 Ch2 as output to do the compare function.
void init_TIM_2
{
RCC.APB1ENR.bit.TIM2EN = 1;
..
TIM2.CCMR1.bit.Inmode.IC1S = 1;
TIM2.CCMR1.bit.Inmode.IC1PSC = 0;
TIM2.CCER.bit.CC1P = 0;
TIM2.CCER.bit.CC1E = 1;
..
TIM2.CCMR1.bit.Outmode.OC2S = 0;
TIM2.CCER.bit.CC2E = 1;
TIM2.DIER.bit.CC2IE = 1;
..
}
Also I enable the global interrupt with the NVIC module. So the interrupt is working.
And what I do in the interrupt just set a new compare value and toggle an GPIO pin.
void TIM2_ISR(void)
{
if (TIM2.SR.bit.CC2IF)
{
int p = TIM2_CCR;
int new_val = 0;
..
// Calculate a new compare value
// Toggle the GPIO pin
..
TIM2.CCR = p + new_val;
TIM2.SR.bit.CC2IF = 0;
}
}
I found it will miss the compare value sometime.
I trace the CCR value and timer counter value of TIM2, the CCR value should be greater than the counter value in normal case. But I found it's not triggered the ISR and the counter just exceed the CCR value sometimes.
If I program not proper, please have some advise for me. Thank you!
The actual data trace list as below:
TIM2 CCR value | TIM2 counter value | Notes |
21735563 | 21729923 | |
21735563 | 21735024 | |
21735563 | 21740124 | The counter val > CCR and no interrupt event |
21735563 | 21745225 |
Solved! Go to Solution.
2023-09-12 02:07 AM
TIM2.SR.bit.CC1IF = 0;
This is exactly what I was talking about above:
> Doesn't this lead to RMW? That might clear inadvertently other flags in the TIMx_SR register, too.
Read the linked article. Don't use bitfields to clear status register, that results in RMW even if it looks elegant; write directly to TIMx_SR. I don't know how did you define TIM2, but using the "normal" CMSIS-mandated device header, you would be adviced not to write
TIM2->SR &= ~TIM_SR_CC1IF;
but rather
TIM2->SR = ~TIM_SR_CC1IF;
JW
2023-09-11 12:12 AM
Hello @Joey_Duh
I suggest you to double check and debug your code step by step to localise the problem. Also, I suggest you to verify the interrupt priority of timer2, if it's very low it may have some problems from Time to time as you mentioned.
Best regards.
II
2023-09-11 01:32 AM
Hi Issamos,
Thanks for your reply.
I checked my interrupt config and the priority I set whatever it's high or low the symptom is the same.
What I do to debug this issue is to record the timer compare value(CCR) and timer counter value(CNT) as I mentioned. The GPIO should not keep low or keep high because I make GPIO toggle when interrupt triggered.
I think the compare ISR must be triggered if the compare value is set greater than the current CNT.
But it seems not, so I still confused.
Many thanks.
Joey
2023-09-11 01:43 AM
Try to debug using break points everywhere it seems to be source of issue.
Best regards.
II
2023-09-11 02:27 AM - edited 2023-09-11 02:28 AM
What programming language is this?
TIM2.SR.bit.CC2IF = 0;
Doesn't this lead to RMW? That might clear inadvertently other flags in the TIMx_SR register, too.
Post the entire ISR content. I am not interested in how do you calculate the new CCRx value, but whether there are or are not other TIM registers' changes.
> trace the CCR value and timer counter value of TIM2
How?
Does the GPIO pin toggle properly, or what exactly are you observing on it?
JW
2023-09-11 02:59 AM
> What programming language is this?
TIM2.SR.bit.CC2IF = 0;
Jan has a point here.
Have you built your own struct called "TIM2"?
If yes, then this might be okay, but irritating for everybody else, because in the STM32 header files "TIM2" is a pointer, with the registers in a timer typedef struct, so that you can access the registers like:
TIM2->CR = ...;
2023-09-11 08:19 PM
@Issamos The timer compare ISR triggered is worked, but not worked everytime. That's why I record the timer register value in background but not using break point. Also the break point would pause the program and the ISR cannot stop in my design even 1 times.
@waclawek.jan @LCE I have my own TIM2 struct and the CC2IF is one bit of the Timer status register which means the content of the counter TIM2_CNT has matched the content of the TIM2_CCR2
register.
And actually what I post is the entire ISR content. GPIO toggle properly if the ISR actually triggered. And runs a few minutes or seconds it just a line because the ISR not triggered. I record the timer register value in the background because I need to make sure if the counter is lower than the CCR value.
2023-09-11 11:38 PM
How and where do you handle the capture in channel 1?
JW
2023-09-12 12:22 AM
@waclawek.jan I handle the capture in the background.
void get_capture_val(void)
{
if (TIM2.SR.bit.CC1IF == 1)
{
// ..
// Handle the capture value
// ..
TIM2.SR.bit.CC1IF = 0;
}
}
2023-09-12 02:07 AM
TIM2.SR.bit.CC1IF = 0;
This is exactly what I was talking about above:
> Doesn't this lead to RMW? That might clear inadvertently other flags in the TIMx_SR register, too.
Read the linked article. Don't use bitfields to clear status register, that results in RMW even if it looks elegant; write directly to TIMx_SR. I don't know how did you define TIM2, but using the "normal" CMSIS-mandated device header, you would be adviced not to write
TIM2->SR &= ~TIM_SR_CC1IF;
but rather
TIM2->SR = ~TIM_SR_CC1IF;
JW