cancel
Showing results for 
Search instead for 
Did you mean: 

Dividing hardware timer in software

LMorr.3
Senior II

I have a hardware timer using its updateEvent interrupt to increment a ms_passed variable every 1 ms. I have a freeRTOS task reading ms_passed ( via TaskNotification ) in a while(1) loop to toggle a pin at a given time interval/tempo based on a variable BPM ( beats per minute ).

I would like to be able to divide 4 'clocks' in software based on the ms_passed ticks. I have implemented a rough solution based on a similar way of setting baud rates registers, ( integer and remainder registers ) and use no floating points, but I still get drift. If I run toggle 2 leds, they are in sync initially but end up out of sync with drift introduced after several minutes.

Does anyone know of an example i can look at in case this has already been done or have suggestions on the best approach?

Thanks!

6 REPLIES 6

Well NCO/DDS methods use an ADDER, basically you add a value to a 32-bit "phase accumulator" register, and the high order bit(s) can reflect the on/off state, or phase angle into a SINE ROM. Usually done in HW, usually clocked at high rates.

If it is walking off, you might need to add/subtract 1 from the value you're adding in. Generally pretty good at doing fractional rates that simple integer divider/counter methods fail at spectacularly.

Where are the TWO LEDs connected?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
gbm
Lead III

Whaty you are trying to do is in conflict with RTOS philosophy. That's what timing system was designed for. Use osDelayUntil() or RTOS timers.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice

Good info. for me to research, thanks. I'm currently using a DISCO F407 dev board and I'm just toggling LEDs when I trigger 2 of my clock divisions. ( GPIOD, GPIO_PIN_14 and GPIOD, GPIO_PIN_15 ) I plan replacing my LED toggles with a trigger to a hardware timer to generate a one-time-pulse. ( I have that part working well )

For my test, I set BPM to 65 and divide 2 clocks to run them both side-by-side to detect drift. One clock is divided by /1 and the second is divided /2 with the idea of seeing one LED toggle at half of the other's rate. This is where I'm seeing the drift after a few minutes.

Thanks for pointing this out, I will revisit using freeRTOS software timers, which is where I started. I thought they may not be accurate enough ( 1ms resolution ) but did not know about compensating for drift at the time.

I noticed a native freeRTOS vTaskDelayUntil() function. Should I use it instead of osDelayUntil()?

gbm
Lead III

It's roughly the same. I would recommend to stick to one RTOS interface; I believe CMSIS-RTOS2 is the way to go. Generally CMSIS osXxx calls are easier to use and more immune to simple mistakes than native FreeRTOS calls.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice