From 16f211c13b4aee73b29b4ba3ff1ea7c40acc356e Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Wed, 29 Jan 2020 14:59:30 +0100 Subject: [PATCH 1/4] HardwareTimer: Remove some superfluous empty lines --- cores/arduino/HardwareTimer.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/cores/arduino/HardwareTimer.h b/cores/arduino/HardwareTimer.h index c02e47e587..ef2c43ab3d 100644 --- a/cores/arduino/HardwareTimer.h +++ b/cores/arduino/HardwareTimer.h @@ -112,7 +112,6 @@ class HardwareTimer { void setPWM(uint32_t channel, PinName pin, uint32_t frequency, uint32_t dutycycle, void (*PeriodCallback)(HardwareTimer *) = NULL, void (*CompareCallback)(HardwareTimer *) = NULL); // Set all in one command freq in HZ, Duty in percentage. Including both interrup. void setPWM(uint32_t channel, uint32_t pin, uint32_t frequency, uint32_t dutycycle, void (*PeriodCallback)(HardwareTimer *) = NULL, void (*CompareCallback)(HardwareTimer *) = NULL); - void setCount(uint32_t val, TimerFormat_t format = TICK_FORMAT); // set timer counter to value 'val' depending on format provided uint32_t getCount(TimerFormat_t format = TICK_FORMAT); // return current counter value of timer depending on format provided @@ -120,7 +119,6 @@ class HardwareTimer { void setMode(uint32_t channel, TimerModes_t mode, uint32_t pin); uint32_t getCaptureCompare(uint32_t channel, TimerCompareFormat_t format = TICK_COMPARE_FORMAT); // return Capture/Compare register value of specified channel depending on format provided - void setCaptureCompare(uint32_t channel, uint32_t compare, TimerCompareFormat_t format = TICK_COMPARE_FORMAT); // set Compare register value of specified channel depending on format provided void setInterruptPriority(uint32_t preemptPriority, uint32_t subPriority); // set interrupt priority @@ -139,7 +137,6 @@ class HardwareTimer { // Refresh() is usefull while timer is running after some registers update void refresh(void); // Generate update event to force all registers (Autoreload, prescaler, compare) to be taken into account - uint32_t getTimerClkFreq(); // return timer clock frequency in Hz. static void captureCompareCallback(TIM_HandleTypeDef *htim); // Generic Caputre and Compare callback which will call user callback @@ -168,4 +165,4 @@ extern timer_index_t get_timer_index(TIM_TypeDef *htim); #endif /* __cplusplus */ #endif // HAL_TIM_MODULE_ENABLED && !HAL_TIM_MODULE_ONLY -#endif // HARDWARETIMER_H_ \ No newline at end of file +#endif // HARDWARETIMER_H_ From 65d37f1fb049a186c138fc354a57d01974616ff6 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Wed, 29 Jan 2020 15:14:59 +0100 Subject: [PATCH 2/4] HardwareTimer: Allow setting preload enable bits --- cores/arduino/HardwareTimer.cpp | 22 ++++++++++++++++++++++ cores/arduino/HardwareTimer.h | 2 ++ 2 files changed, 24 insertions(+) diff --git a/cores/arduino/HardwareTimer.cpp b/cores/arduino/HardwareTimer.cpp index 7477eea9de..c6c8624942 100644 --- a/cores/arduino/HardwareTimer.cpp +++ b/cores/arduino/HardwareTimer.cpp @@ -677,6 +677,28 @@ void HardwareTimer::setMode(uint32_t channel, TimerModes_t mode, PinName pin) } } +/** + * @brief Enable or disable preloading for overflow value + * When disabled, changes to the overflow value take effect + * immediately. When enabled, the value takes effect only at + * the next update event (typically the next overflow). + * + * Note that the capture/compare register has its own preload + * enable bit, which is independent and enabled in PWM modes + * and disabled otherwise. If you need more control of that + * bit, you can use the HAL functions directly. + * @param value: true to enable preloading, false to disable + * @retval None + */ +void HardwareTimer::setPreloadEnable(bool value) +{ + if (value) { + LL_TIM_EnableARRPreload(_timerObj.handle.Instance); + } else { + LL_TIM_DisableARRPreload(_timerObj.handle.Instance); + } +} + /** * @brief Set channel Capture/Compare register * @param channel: Arduino channel [1..4] diff --git a/cores/arduino/HardwareTimer.h b/cores/arduino/HardwareTimer.h index ef2c43ab3d..30532b4f74 100644 --- a/cores/arduino/HardwareTimer.h +++ b/cores/arduino/HardwareTimer.h @@ -118,6 +118,8 @@ class HardwareTimer { void setMode(uint32_t channel, TimerModes_t mode, PinName pin = NC); // Configure timer channel with specified mode on specified pin if available void setMode(uint32_t channel, TimerModes_t mode, uint32_t pin); + void setPreloadEnable(bool value); // Configure overflow preload enable setting + uint32_t getCaptureCompare(uint32_t channel, TimerCompareFormat_t format = TICK_COMPARE_FORMAT); // return Capture/Compare register value of specified channel depending on format provided void setCaptureCompare(uint32_t channel, uint32_t compare, TimerCompareFormat_t format = TICK_COMPARE_FORMAT); // set Compare register value of specified channel depending on format provided From 010876828007fee5d797633e82f04f6ff27bdc47 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 30 Jan 2020 16:58:23 +0100 Subject: [PATCH 3/4] HardwareTimer: Enable preload for ARR/overflow register This changes the default for preload (i.e. delay updating the overflow value until an update event such as timer overflow) to enabled, since this is will probably make the timer output behave as expected as much as possible (e.g. you cannot make it "skip" an overflow and run it all the way up to 0xffff by lowering the overflow value). --- cores/arduino/HardwareTimer.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/cores/arduino/HardwareTimer.cpp b/cores/arduino/HardwareTimer.cpp index c6c8624942..2b22b3d473 100644 --- a/cores/arduino/HardwareTimer.cpp +++ b/cores/arduino/HardwareTimer.cpp @@ -93,7 +93,7 @@ HardwareTimer::HardwareTimer(TIM_TypeDef *instance) #if defined(TIM_RCR_REP) _timerObj.handle.Init.RepetitionCounter = 0; #endif - _timerObj.handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; + _timerObj.handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; HAL_TIM_Base_Init(&(_timerObj.handle)); } @@ -442,6 +442,11 @@ uint32_t HardwareTimer::getOverflow(TimerFormat_t format) /** * @brief Set overflow (rollover) + * + * Note that by default, the new value will not be applied + * immediately, but become effective at the next update event + * (usually the next timer overflow). See setPreloadEnable() + * for controlling this behaviour. * @param overflow: depend on format parameter * @param format of overflow parameter. If ommited default format is Tick * TICK_FORMAT: overflow is the number of tick for overflow @@ -680,8 +685,9 @@ void HardwareTimer::setMode(uint32_t channel, TimerModes_t mode, PinName pin) /** * @brief Enable or disable preloading for overflow value * When disabled, changes to the overflow value take effect - * immediately. When enabled, the value takes effect only at - * the next update event (typically the next overflow). + * immediately. When enabled (the default), the value takes + * effect only at the next update event (typically the next + * overflow). * * Note that the capture/compare register has its own preload * enable bit, which is independent and enabled in PWM modes From e761507bd0df66b00eff1bd68ca587b14367e43a Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 30 Jan 2020 17:05:01 +0100 Subject: [PATCH 4/4] HardwareTimer: Expose some helper methods These methods allow access to some of the more low-level values and are useful to implement some more advanced usecases, where the HAL is also directly accessed. --- cores/arduino/HardwareTimer.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/cores/arduino/HardwareTimer.h b/cores/arduino/HardwareTimer.h index 30532b4f74..695f64b21b 100644 --- a/cores/arduino/HardwareTimer.h +++ b/cores/arduino/HardwareTimer.h @@ -146,11 +146,6 @@ class HardwareTimer { // The following function(s) are available for more advanced timer options TIM_HandleTypeDef *getHandle(); // return the handle address for HAL related configuration - - private: - TimerModes_t _ChannelMode[TIMER_CHANNELS]; - timerObj_t _timerObj; - void (*callbacks[1 + TIMER_CHANNELS])(HardwareTimer *); //Callbacks: 0 for update, 1-4 for channels. (channel5/channel6, if any, doesn't have interrupt) int getChannel(uint32_t channel); int getLLChannel(uint32_t channel); int getIT(uint32_t channel); @@ -158,6 +153,10 @@ class HardwareTimer { #if defined(TIM_CCER_CC1NE) bool isComplementaryChannel[TIMER_CHANNELS]; #endif + private: + TimerModes_t _ChannelMode[TIMER_CHANNELS]; + timerObj_t _timerObj; + void (*callbacks[1 + TIMER_CHANNELS])(HardwareTimer *); //Callbacks: 0 for update, 1-4 for channels. (channel5/channel6, if any, doesn't have interrupt) }; extern timerObj_t *HardwareTimer_Handle[TIMER_NUM];