flyboy74 wrote: Fri May 08, 2020 7:53 am
I have changed my interrupt handler a little bit so that all the update code is inside the loop that tests TIM_SR_UIF bit and I don't reset this bit till the end of the handler that way it can't fire again till after exit.
Please test this update and see if your still get a dropped bit
https://github.com/OutOfTheBots/STM32_N ... ter/main.c
The good news is that with your modified interrupt routine the first bit does not get lost.
The bad news is that now, very occasionally, the first bit gets duplicated!
The other bad news, is that my explanation is a bit long...
Normally, let's say somewhere in the middle of generating the whole long stream of pulses, the execution of the interrupt routine is synchronised with the timer. That is, the interrupt routine always gets called just after the timer update event, when the count starts back at zero. The previous CCR value has just been latched, so it is then "safe" to set a new CCR value, without overlaying the previous value before it could get used, and you also have a (relatively) long time available to do this before the next update event. I'm mentioning CCR, same thing applies to ARR.
Things are different right at the start of the pulse stream kicked off in show_neopixels by turning on the UIE bit. The timer is already enabled at that point, and has been running, still generating update events which will have set the UIF flag. So, at soon as you clear UIE the interrupt will occur, and the interrupt routine will be called. It is not so much the fact that the interrupt routine gets called, but that this call to the interrupt routine is not synchronised with what is happening in the timer, it just depends on when you happen to call show_neopixels.
Usually, this does not cause a problem, but this is a sequence that might happen, with the original interrupt routine, which cleared UIF and then wrote to CCR1:
Interrupt occurs as soon as show_neopixels clears UIE.
Interrupt routine clears UIF.
Update event happens to occur now - this latches previously set CCR1 (0 for no pulse), and sets UIF again.
Interrupt routine sets CCR1 according to first data bit, to be latched at next update event.
As soon as interrupt routine exits, interrupt occurs again as UIF is set.
Interrupt routine clears UIF.
Interrupt routine sets CCR1 according to second data bit, overwriting the value for the first data bit, which has not been latched yet.
Result - first data bit is simply lost, pulse train starts with the second bit.
Now you changed the interrupt routine to write to CCR1 and then clear UIF. Imagine a sequence similar to that above, except now the first time the interrupt routine is called:
The update event happens to occur after CCR1 is updated with value for first bit, but before the UIF is cleared.
The update event latched the value for the first bit, and the pulse output has already gone high for the start of the first bit.
The interrupt routine clears UIF immediately after it was set.
Because UIF was cleared, at the time when the interrupt routine should have been called again to provide the value for the second bit, well, nothing happens (interrput not called).
However the timer is still running, and is quite happy to generate another pulse using the value for the first bit. Only when the timer is reusing the first CCR value for the second time, does the interrupt routine get called again, and it then continues as if nothing had happened.
Result - first bit gets duplicated.
My head hurts if I try to think what might happen if the update event happened between writing to CCR1 and ARR, and the zero and one bit ARR values were not the same.