From a61b5fa4769f0776e33391e4d9ce75904fa620dd Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Mon, 4 Nov 2019 10:58:38 +0100 Subject: [PATCH 1/3] [Timer] Move get_timer_obj() from cpp to c This will allow to customize IRQ priority Signed-off-by: Frederic Pillon --- cores/arduino/HardwareTimer.cpp | 152 +++++++++++++++----------------- cores/arduino/HardwareTimer.h | 14 +-- cores/arduino/stm32/timer.c | 9 ++ cores/arduino/stm32/timer.h | 10 +++ 4 files changed, 92 insertions(+), 93 deletions(-) diff --git a/cores/arduino/HardwareTimer.cpp b/cores/arduino/HardwareTimer.cpp index 1ac21b8a37..f3f499c1cc 100644 --- a/cores/arduino/HardwareTimer.cpp +++ b/cores/arduino/HardwareTimer.cpp @@ -33,7 +33,7 @@ #define MAX_RELOAD ((1 << 16) - 1) // Currently even 32b timers are used as 16b to have generic behavior /* Private Variables */ -HardwareTimerObj_t *HardwareTimer_Handle[TIMER_NUM] = {NULL}; +timerObj_t *HardwareTimer_Handle[TIMER_NUM] = {NULL}; IRQn_Type getTimerUpIrq(TIM_TypeDef *tim); IRQn_Type getTimerCCIrq(TIM_TypeDef *tim); @@ -50,25 +50,25 @@ HardwareTimer::HardwareTimer(TIM_TypeDef *instance) Error_Handler(); } - HardwareTimer_Handle[index] = &_HardwareTimerObj; + HardwareTimer_Handle[index] = &_timerObj; - _HardwareTimerObj.handle.Instance = instance; - _HardwareTimerObj.handle.Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED; - _HardwareTimerObj.handle.hdma[0] = NULL; - _HardwareTimerObj.handle.hdma[1] = NULL; - _HardwareTimerObj.handle.hdma[2] = NULL; - _HardwareTimerObj.handle.hdma[3] = NULL; - _HardwareTimerObj.handle.hdma[4] = NULL; - _HardwareTimerObj.handle.hdma[5] = NULL; - _HardwareTimerObj.handle.hdma[6] = NULL; - _HardwareTimerObj.handle.Lock = HAL_UNLOCKED; - _HardwareTimerObj.handle.State = HAL_TIM_STATE_RESET; + _timerObj.handle.Instance = instance; + _timerObj.handle.Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED; + _timerObj.handle.hdma[0] = NULL; + _timerObj.handle.hdma[1] = NULL; + _timerObj.handle.hdma[2] = NULL; + _timerObj.handle.hdma[3] = NULL; + _timerObj.handle.hdma[4] = NULL; + _timerObj.handle.hdma[5] = NULL; + _timerObj.handle.hdma[6] = NULL; + _timerObj.handle.Lock = HAL_UNLOCKED; + _timerObj.handle.State = HAL_TIM_STATE_RESET; - _HardwareTimerObj.handle.Instance = instance; - _HardwareTimerObj.__this = (void *)this; + _timerObj.handle.Instance = instance; + _timerObj.__this = (void *)this; // Enable Timer clock - enableTimerClock(&(_HardwareTimerObj.handle)); + enableTimerClock(&(_timerObj.handle)); // Configure HAL structure for all channels for (int i = 0; i < TIMER_CHANNELS; i++) { @@ -103,7 +103,7 @@ HardwareTimer::HardwareTimer(TIM_TypeDef *instance) */ void HardwareTimer::pause() { - HAL_TIM_Base_Stop_IT(&(_HardwareTimerObj.handle)); + HAL_TIM_Base_Stop_IT(&(_timerObj.handle)); } /** @@ -113,19 +113,19 @@ void HardwareTimer::pause() */ void HardwareTimer::resume(void) { - _HardwareTimerObj.handle.Init.CounterMode = TIM_COUNTERMODE_UP; - _HardwareTimerObj.handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + _timerObj.handle.Init.CounterMode = TIM_COUNTERMODE_UP; + _timerObj.handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; #if defined(TIM_RCR_REP) - _HardwareTimerObj.handle.Init.RepetitionCounter = 0; + _timerObj.handle.Init.RepetitionCounter = 0; #endif - _HardwareTimerObj.handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; - HAL_TIM_Base_Init(&(_HardwareTimerObj.handle)); + _timerObj.handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; + HAL_TIM_Base_Init(&(_timerObj.handle)); // Start timer with IT if required if (callbacks[0] != NULL) { - HAL_TIM_Base_Start_IT(&(_HardwareTimerObj.handle)); + HAL_TIM_Base_Start_IT(&(_timerObj.handle)); } else { - HAL_TIM_Base_Start(&(_HardwareTimerObj.handle)); + HAL_TIM_Base_Start(&(_timerObj.handle)); } resumeChannel(1); @@ -175,58 +175,58 @@ void HardwareTimer::resumeChannel(uint32_t channel) } if (IS_TIM_PWM_MODE(_channelOC[channel - 1].OCMode)) { - HAL_TIM_PWM_ConfigChannel(&(_HardwareTimerObj.handle), &_channelOC[channel - 1], timChannel); + HAL_TIM_PWM_ConfigChannel(&(_timerObj.handle), &_channelOC[channel - 1], timChannel); if ((channel < (TIMER_CHANNELS + 1)) && (callbacks[channel] != NULL)) { // Only channel 1..4 can have interruption #if defined(TIM_CCER_CC1NE) if (isComplementaryChannel[channel]) { - HAL_TIMEx_PWMN_Start_IT(&(_HardwareTimerObj.handle), timChannel); + HAL_TIMEx_PWMN_Start_IT(&(_timerObj.handle), timChannel); } else #endif { - HAL_TIM_PWM_Start_IT(&(_HardwareTimerObj.handle), timChannel); + HAL_TIM_PWM_Start_IT(&(_timerObj.handle), timChannel); } } else { #if defined(TIM_CCER_CC1NE) if (isComplementaryChannel[channel]) { - HAL_TIMEx_PWMN_Start(&(_HardwareTimerObj.handle), timChannel); + HAL_TIMEx_PWMN_Start(&(_timerObj.handle), timChannel); } else #endif { - HAL_TIM_PWM_Start(&(_HardwareTimerObj.handle), timChannel); + HAL_TIM_PWM_Start(&(_timerObj.handle), timChannel); } } } else if (IS_TIM_OC_MODE(_channelOC[channel - 1].OCMode)) { - HAL_TIM_OC_ConfigChannel(&(_HardwareTimerObj.handle), &_channelOC[channel - 1], timChannel); + HAL_TIM_OC_ConfigChannel(&(_timerObj.handle), &_channelOC[channel - 1], timChannel); if ((channel < (TIMER_CHANNELS + 1)) && (callbacks[channel] != NULL)) { // Only channel 1..4 can have interruption #if defined(TIM_CCER_CC1NE) if (isComplementaryChannel[channel]) { - HAL_TIMEx_OCN_Start_IT(&(_HardwareTimerObj.handle), timChannel); + HAL_TIMEx_OCN_Start_IT(&(_timerObj.handle), timChannel); } else #endif { - HAL_TIM_OC_Start_IT(&(_HardwareTimerObj.handle), timChannel); + HAL_TIM_OC_Start_IT(&(_timerObj.handle), timChannel); } } else { #if defined(TIM_CCER_CC1NE) if (isComplementaryChannel[channel]) { - HAL_TIMEx_OCN_Start(&(_HardwareTimerObj.handle), timChannel); + HAL_TIMEx_OCN_Start(&(_timerObj.handle), timChannel); } else #endif { - HAL_TIM_OC_Start(&(_HardwareTimerObj.handle), timChannel); + HAL_TIM_OC_Start(&(_timerObj.handle), timChannel); } } } else if (_channelIC[channel - 1].ICPolarity != TIMER_NOT_USED) { - HAL_TIM_IC_ConfigChannel(&(_HardwareTimerObj.handle), &_channelIC[channel - 1], timChannel); + HAL_TIM_IC_ConfigChannel(&(_timerObj.handle), &_channelIC[channel - 1], timChannel); if (callbacks[channel] != NULL) { - HAL_TIM_IC_Start_IT(&(_HardwareTimerObj.handle), timChannel); + HAL_TIM_IC_Start_IT(&(_timerObj.handle), timChannel); } else { - HAL_TIM_IC_Start(&(_HardwareTimerObj.handle), timChannel); + HAL_TIM_IC_Start(&(_timerObj.handle), timChannel); } } } @@ -239,7 +239,7 @@ void HardwareTimer::resumeChannel(uint32_t channel) uint32_t HardwareTimer::getPrescaleFactor() { // Hardware register correspond to prescaler-1. Example PSC register value 0 means divided by 1 - return (_HardwareTimerObj.handle.Init.Prescaler + 1); + return (_timerObj.handle.Init.Prescaler + 1); } /** @@ -250,8 +250,8 @@ uint32_t HardwareTimer::getPrescaleFactor() void HardwareTimer::setPrescaleFactor(uint32_t prescaler) { // Hardware register correspond to prescaler-1. Example PSC register value 0 means divided by 1 - __HAL_TIM_SET_PRESCALER(&_HardwareTimerObj.handle, prescaler - 1); - _HardwareTimerObj.handle.Init.Prescaler = prescaler - 1; + __HAL_TIM_SET_PRESCALER(&_timerObj.handle, prescaler - 1); + _timerObj.handle.Init.Prescaler = prescaler - 1; } /** @@ -265,8 +265,8 @@ void HardwareTimer::setPrescaleFactor(uint32_t prescaler) uint32_t HardwareTimer::getOverflow(TimerFormat_t format) { // Hardware register correspond to period count-1. Example ARR register value 9 means period of 10 timer cycle - uint32_t ARR_RegisterValue = __HAL_TIM_GET_AUTORELOAD(&(_HardwareTimerObj.handle)); - uint32_t Prescalerfactor = _HardwareTimerObj.handle.Instance->PSC + 1; + uint32_t ARR_RegisterValue = __HAL_TIM_GET_AUTORELOAD(&(_timerObj.handle)); + uint32_t Prescalerfactor = _timerObj.handle.Instance->PSC + 1; uint32_t return_value; switch (format) { case MICROSEC_FORMAT: @@ -302,15 +302,15 @@ void HardwareTimer::setOverflow(uint32_t overflow, TimerFormat_t format) case MICROSEC_FORMAT: period_cyc = overflow * (getTimerClkFreq() / 1000000); Prescalerfactor = (period_cyc / 0x10000) + 1; - __HAL_TIM_SET_PRESCALER(&_HardwareTimerObj.handle, Prescalerfactor - 1); - _HardwareTimerObj.handle.Init.Prescaler = Prescalerfactor - 1; + __HAL_TIM_SET_PRESCALER(&_timerObj.handle, Prescalerfactor - 1); + _timerObj.handle.Init.Prescaler = Prescalerfactor - 1; ARR_RegisterValue = (period_cyc / Prescalerfactor) - 1; break; case HERTZ_FORMAT: period_cyc = getTimerClkFreq() / overflow; Prescalerfactor = (period_cyc / 0x10000) + 1; - __HAL_TIM_SET_PRESCALER(&_HardwareTimerObj.handle, Prescalerfactor - 1); - _HardwareTimerObj.handle.Init.Prescaler = Prescalerfactor - 1; + __HAL_TIM_SET_PRESCALER(&_timerObj.handle, Prescalerfactor - 1); + _timerObj.handle.Init.Prescaler = Prescalerfactor - 1; ARR_RegisterValue = (period_cyc / Prescalerfactor) - 1; break; case TICK_FORMAT: @@ -319,8 +319,8 @@ void HardwareTimer::setOverflow(uint32_t overflow, TimerFormat_t format) break; } - __HAL_TIM_SET_AUTORELOAD(&_HardwareTimerObj.handle, ARR_RegisterValue); - _HardwareTimerObj.handle.Init.Period = ARR_RegisterValue; + __HAL_TIM_SET_AUTORELOAD(&_timerObj.handle, ARR_RegisterValue); + _timerObj.handle.Init.Period = ARR_RegisterValue; } /** @@ -333,8 +333,8 @@ void HardwareTimer::setOverflow(uint32_t overflow, TimerFormat_t format) */ uint32_t HardwareTimer::getCount(TimerFormat_t format) { - uint32_t CNT_RegisterValue = __HAL_TIM_GET_COUNTER(&(_HardwareTimerObj.handle)); - uint32_t Prescalerfactor = _HardwareTimerObj.handle.Instance->PSC + 1; + uint32_t CNT_RegisterValue = __HAL_TIM_GET_COUNTER(&(_timerObj.handle)); + uint32_t Prescalerfactor = _timerObj.handle.Instance->PSC + 1; uint32_t return_value; switch (format) { case MICROSEC_FORMAT: @@ -363,7 +363,7 @@ uint32_t HardwareTimer::getCount(TimerFormat_t format) void HardwareTimer::setCount(uint32_t counter, TimerFormat_t format) { uint32_t CNT_RegisterValue; - uint32_t Prescalerfactor = _HardwareTimerObj.handle.Instance->PSC + 1; + uint32_t Prescalerfactor = _timerObj.handle.Instance->PSC + 1; switch (format) { case MICROSEC_FORMAT: CNT_RegisterValue = ((counter * (getTimerClkFreq() / 1000000)) / Prescalerfactor) - 1 ; @@ -376,7 +376,7 @@ void HardwareTimer::setCount(uint32_t counter, TimerFormat_t format) CNT_RegisterValue = counter - 1; break; } - __HAL_TIM_SET_COUNTER(&(_HardwareTimerObj.handle), CNT_RegisterValue); + __HAL_TIM_SET_COUNTER(&(_timerObj.handle), CNT_RegisterValue); } /** @@ -519,7 +519,7 @@ void HardwareTimer::setMode(uint32_t channel, TimerModes_t mode, PinName pin) void HardwareTimer::setCaptureCompare(uint32_t channel, uint32_t compare, TimerCompareFormat_t format) { int timChannel = getChannel(channel); - uint32_t Prescalerfactor = _HardwareTimerObj.handle.Instance->PSC + 1; + uint32_t Prescalerfactor = _timerObj.handle.Instance->PSC + 1; uint32_t CCR_RegisterValue; if (timChannel == -1) { @@ -534,13 +534,13 @@ void HardwareTimer::setCaptureCompare(uint32_t channel, uint32_t compare, TimerC CCR_RegisterValue = (getTimerClkFreq() / (compare * Prescalerfactor)) - 1; break; case PERCENT_COMPARE_FORMAT: - CCR_RegisterValue = ((__HAL_TIM_GET_AUTORELOAD(&(_HardwareTimerObj.handle)) + 1) * compare) / 100; + CCR_RegisterValue = ((__HAL_TIM_GET_AUTORELOAD(&(_timerObj.handle)) + 1) * compare) / 100; break; case RESOLUTION_8B_COMPARE_FORMAT: - CCR_RegisterValue = ((__HAL_TIM_GET_AUTORELOAD(&(_HardwareTimerObj.handle)) + 1) * compare) / 255 ; + CCR_RegisterValue = ((__HAL_TIM_GET_AUTORELOAD(&(_timerObj.handle)) + 1) * compare) / 255 ; break; case RESOLUTION_12B_COMPARE_FORMAT: - CCR_RegisterValue = ((__HAL_TIM_GET_AUTORELOAD(&(_HardwareTimerObj.handle)) + 1) * compare) / 4095 ; + CCR_RegisterValue = ((__HAL_TIM_GET_AUTORELOAD(&(_timerObj.handle)) + 1) * compare) / 4095 ; break; case TICK_COMPARE_FORMAT: default : @@ -548,7 +548,7 @@ void HardwareTimer::setCaptureCompare(uint32_t channel, uint32_t compare, TimerC break; } - __HAL_TIM_SET_COMPARE(&(_HardwareTimerObj.handle), timChannel, CCR_RegisterValue); + __HAL_TIM_SET_COMPARE(&(_timerObj.handle), timChannel, CCR_RegisterValue); _channelOC[channel - 1].Pulse = CCR_RegisterValue; } @@ -564,8 +564,8 @@ void HardwareTimer::setCaptureCompare(uint32_t channel, uint32_t compare, TimerC uint32_t HardwareTimer::getCaptureCompare(uint32_t channel, TimerCompareFormat_t format) { int timChannel = getChannel(channel); - uint32_t CCR_RegisterValue = __HAL_TIM_GET_COMPARE(&(_HardwareTimerObj.handle), timChannel); - uint32_t Prescalerfactor = _HardwareTimerObj.handle.Instance->PSC + 1; + uint32_t CCR_RegisterValue = __HAL_TIM_GET_COMPARE(&(_timerObj.handle), timChannel); + uint32_t Prescalerfactor = _timerObj.handle.Instance->PSC + 1; uint32_t return_value; if (timChannel == -1) { @@ -580,13 +580,13 @@ uint32_t HardwareTimer::getCaptureCompare(uint32_t channel, TimerCompareFormat_ return_value = (uint32_t)(getTimerClkFreq() / (CCR_RegisterValue * Prescalerfactor)); break; case PERCENT_COMPARE_FORMAT: - return_value = (CCR_RegisterValue * 100) / __HAL_TIM_GET_AUTORELOAD(&(_HardwareTimerObj.handle)); + return_value = (CCR_RegisterValue * 100) / __HAL_TIM_GET_AUTORELOAD(&(_timerObj.handle)); break; case RESOLUTION_8B_COMPARE_FORMAT: - return_value = (CCR_RegisterValue * 255) / __HAL_TIM_GET_AUTORELOAD(&(_HardwareTimerObj.handle)); + return_value = (CCR_RegisterValue * 255) / __HAL_TIM_GET_AUTORELOAD(&(_timerObj.handle)); break; case RESOLUTION_12B_COMPARE_FORMAT: - return_value = (CCR_RegisterValue * 4095) / __HAL_TIM_GET_AUTORELOAD(&(_HardwareTimerObj.handle)); + return_value = (CCR_RegisterValue * 4095) / __HAL_TIM_GET_AUTORELOAD(&(_timerObj.handle)); break; case TICK_COMPARE_FORMAT: default : @@ -694,7 +694,7 @@ void HardwareTimer::detachInterrupt(uint32_t channel) */ void HardwareTimer::refresh() { - HAL_TIM_GenerateEvent(&(_HardwareTimerObj.handle), TIM_EVENTSOURCE_UPDATE); + HAL_TIM_GenerateEvent(&(_timerObj.handle), TIM_EVENTSOURCE_UPDATE); } /** @@ -708,7 +708,7 @@ void HardwareTimer::updateCallback(TIM_HandleTypeDef *htim) Error_Handler(); } - HardwareTimerObj_t *obj = get_timer_obj(htim); + timerObj_t *obj = get_timer_obj(htim); HardwareTimer *HT = (HardwareTimer *)(obj->__this); if (HT->callbacks[0] != NULL) { @@ -749,7 +749,7 @@ void HardwareTimer::captureCompareCallback(TIM_HandleTypeDef *htim) return; } - HardwareTimerObj_t *obj = get_timer_obj(htim); + timerObj_t *obj = get_timer_obj(htim); HardwareTimer *HT = (HardwareTimer *)(obj->__this); if (HT->callbacks[channel] != NULL) { @@ -763,10 +763,10 @@ void HardwareTimer::captureCompareCallback(TIM_HandleTypeDef *htim) */ HardwareTimer::~HardwareTimer() { - uint32_t index = get_timer_index(_HardwareTimerObj.handle.Instance); - disableTimerClock(&(_HardwareTimerObj.handle)); + uint32_t index = get_timer_index(_timerObj.handle.Instance); + disableTimerClock(&(_timerObj.handle)); HardwareTimer_Handle[index] = NULL; - _HardwareTimerObj.__this = NULL; + _timerObj.__this = NULL; } /** @@ -904,7 +904,7 @@ uint32_t HardwareTimer::getTimerClkFreq() /* Get clock configuration */ HAL_RCC_GetClockConfig(&clkconfig, &pFLatency); - switch (getTimerClkSrc(_HardwareTimerObj.handle.Instance)) { + switch (getTimerClkSrc(_timerObj.handle.Instance)) { case 1: uwAPBxPrescaler = clkconfig.APB1CLKDivider; uwTimclock = HAL_RCC_GetPCLK1Freq(); @@ -1015,16 +1015,6 @@ uint32_t HardwareTimer::getTimerClkFreq() return uwTimclock; } -/* Aim of the function is to get _HardwareTimerObj_s pointer using htim pointer */ -/* Highly inspired from magical linux kernel's "container_of" */ -/* (which was not directly used since not compatible with IAR toolchain) */ -HardwareTimerObj_t *get_timer_obj(TIM_HandleTypeDef *htim) -{ - HardwareTimerObj_t *obj; - obj = (HardwareTimerObj_t *)((char *)htim - offsetof(HardwareTimerObj_t, handle)); - return (obj); -} - /** * @brief This function will reset the timer * @param obj : Hardware timer instance ex: Timer6, ... @@ -1032,8 +1022,8 @@ HardwareTimerObj_t *get_timer_obj(TIM_HandleTypeDef *htim) */ void HardwareTimer::timerHandleDeinit() { - HAL_TIM_Base_Stop_IT(&(_HardwareTimerObj.handle)); - HAL_TIM_Base_DeInit(&(_HardwareTimerObj.handle)); + HAL_TIM_Base_Stop_IT(&(_timerObj.handle)); + HAL_TIM_Base_DeInit(&(_timerObj.handle)); } /******************************************************************************/ diff --git a/cores/arduino/HardwareTimer.h b/cores/arduino/HardwareTimer.h index 45036bb4f2..d09bcfa4a4 100644 --- a/cores/arduino/HardwareTimer.h +++ b/cores/arduino/HardwareTimer.h @@ -74,14 +74,6 @@ typedef enum { RESOLUTION_12B_COMPARE_FORMAT // used for Dutycycle: [0.. 4095] } TimerCompareFormat_t; -// This structure is used to be able to get HardwareTimer instance (C++ class) -// from handler (C structure) specially for interrupt management -typedef struct { - // Those 2 first fields must remain in this order at the beginning of the structure - void *__this; - TIM_HandleTypeDef handle; -} HardwareTimerObj_t; - #ifdef __cplusplus /* Class --------------------------------------------------------*/ @@ -135,7 +127,7 @@ class HardwareTimer { private: TIM_OC_InitTypeDef _channelOC[TIMER_CHANNELS]; TIM_IC_InitTypeDef _channelIC[TIMER_CHANNELS]; - HardwareTimerObj_t _HardwareTimerObj; + 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); @@ -145,9 +137,7 @@ class HardwareTimer { #endif }; -HardwareTimerObj_t *get_timer_obj(TIM_HandleTypeDef *htim); - -extern HardwareTimerObj_t *HardwareTimer_Handle[TIMER_NUM]; +extern timerObj_t *HardwareTimer_Handle[TIMER_NUM]; extern timer_index_t get_timer_index(TIM_TypeDef *htim); diff --git a/cores/arduino/stm32/timer.c b/cores/arduino/stm32/timer.c index b79c6ec9cb..de1a6c0d3d 100644 --- a/cores/arduino/stm32/timer.c +++ b/cores/arduino/stm32/timer.c @@ -20,6 +20,15 @@ extern "C" { #ifdef HAL_TIM_MODULE_ENABLED /* Private Functions */ +/* Aim of the function is to get _timerObj pointer using htim pointer */ +/* Highly inspired from magical linux kernel's "container_of" */ +/* (which was not directly used since not compatible with IAR toolchain) */ +timerObj_t *get_timer_obj(TIM_HandleTypeDef *htim) +{ + timerObj_t *obj; + obj = (timerObj_t *)((char *)htim - offsetof(timerObj_t, handle)); + return (obj); +} /** * @brief TIMER Initialization - clock init and nvic init diff --git a/cores/arduino/stm32/timer.h b/cores/arduino/stm32/timer.h index 31d5270f35..ae8d2563f1 100644 --- a/cores/arduino/stm32/timer.h +++ b/cores/arduino/stm32/timer.h @@ -231,7 +231,17 @@ typedef enum { UNKNOWN_TIMER = 0XFFFF } timer_index_t; + +// This structure is used to be able to get HardwareTimer instance (C++ class) +// from handler (C structure) specially for interrupt management +typedef struct { + // Those 2 first fields must remain in this order at the beginning of the structure + void *__this; + TIM_HandleTypeDef handle; +} timerObj_t; + /* Exported functions ------------------------------------------------------- */ +timerObj_t *get_timer_obj(TIM_HandleTypeDef *htim); void enableTimerClock(TIM_HandleTypeDef *htim); void disableTimerClock(TIM_HandleTypeDef *htim); From a3ddf3ad6e2becc11b8a1963ebece4d050e0aaea Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Mon, 4 Nov 2019 11:14:11 +0100 Subject: [PATCH 2/3] [Timer] Add function to set interrupt priority Signed-off-by: Frederic Pillon --- cores/arduino/HardwareTimer.cpp | 15 +++++++++++++++ cores/arduino/HardwareTimer.h | 2 ++ cores/arduino/stm32/timer.c | 10 ++++++---- cores/arduino/stm32/timer.h | 2 ++ 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/cores/arduino/HardwareTimer.cpp b/cores/arduino/HardwareTimer.cpp index f3f499c1cc..081ad5dae4 100644 --- a/cores/arduino/HardwareTimer.cpp +++ b/cores/arduino/HardwareTimer.cpp @@ -66,6 +66,8 @@ HardwareTimer::HardwareTimer(TIM_TypeDef *instance) _timerObj.handle.Instance = instance; _timerObj.__this = (void *)this; + _timerObj.preemptPriority = TIM_IRQ_PRIO; + _timerObj.subPriority = TIM_IRQ_SUBPRIO; // Enable Timer clock enableTimerClock(&(_timerObj.handle)); @@ -638,6 +640,19 @@ void HardwareTimer::setPWM(uint32_t channel, PinName pin, uint32_t frequency, ui resume(); } +/** + * @brief Set the priority of the interrupt + * @note Must be call before resume() + * @param preemptPriority: the pre-emption priority for the IRQn channel + * @param subPriority: the subpriority level for the IRQ channel. + * @retval None + */ +void HardwareTimer::setInterruptPriority(uint32_t preemptPriority, uint32_t subPriority) +{ + _timerObj.preemptPriority = preemptPriority; + _timerObj.subPriority = subPriority; +} + /** * @brief Attach interrupt callback on update (rollover) event * @param callback: interrupt callback diff --git a/cores/arduino/HardwareTimer.h b/cores/arduino/HardwareTimer.h index d09bcfa4a4..ce3e0cc1ac 100644 --- a/cores/arduino/HardwareTimer.h +++ b/cores/arduino/HardwareTimer.h @@ -105,6 +105,8 @@ class HardwareTimer { 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 + //Add interrupt to period update void attachInterrupt(void (*handler)(HardwareTimer *)); // Attach interrupt callback which will be called upon update event (timer rollover) void detachInterrupt(); // remove interrupt callback which was attached to update event diff --git a/cores/arduino/stm32/timer.c b/cores/arduino/stm32/timer.c index de1a6c0d3d..066ee04d70 100644 --- a/cores/arduino/stm32/timer.c +++ b/cores/arduino/stm32/timer.c @@ -37,15 +37,16 @@ timerObj_t *get_timer_obj(TIM_HandleTypeDef *htim) */ void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim_base) { + timerObj_t *obj = get_timer_obj(htim_base); enableTimerClock(htim_base); // configure Update interrupt - HAL_NVIC_SetPriority(getTimerUpIrq(htim_base->Instance), TIM_IRQ_PRIO, TIM_IRQ_SUBPRIO); + HAL_NVIC_SetPriority(getTimerUpIrq(htim_base->Instance), obj->preemptPriority, obj->subPriority); HAL_NVIC_EnableIRQ(getTimerUpIrq(htim_base->Instance)); if (getTimerCCIrq(htim_base->Instance) != getTimerUpIrq(htim_base->Instance)) { // configure Capture Compare interrupt - HAL_NVIC_SetPriority(getTimerCCIrq(htim_base->Instance), TIM_IRQ_PRIO, TIM_IRQ_SUBPRIO); + HAL_NVIC_SetPriority(getTimerCCIrq(htim_base->Instance), obj->preemptPriority, obj->subPriority); HAL_NVIC_EnableIRQ(getTimerCCIrq(htim_base->Instance)); } } @@ -69,15 +70,16 @@ void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim_base) */ void HAL_TIM_OC_MspInit(TIM_HandleTypeDef *htim) { + timerObj_t *obj = get_timer_obj(htim); enableTimerClock(htim); // configure Update interrupt - HAL_NVIC_SetPriority(getTimerUpIrq(htim->Instance), TIM_IRQ_PRIO, TIM_IRQ_SUBPRIO); + HAL_NVIC_SetPriority(getTimerUpIrq(htim->Instance), obj->preemptPriority, obj->subPriority); HAL_NVIC_EnableIRQ(getTimerUpIrq(htim->Instance)); if (getTimerCCIrq(htim->Instance) != getTimerUpIrq(htim->Instance)) { // configure Capture Compare interrupt - HAL_NVIC_SetPriority(getTimerCCIrq(htim->Instance), TIM_IRQ_PRIO, TIM_IRQ_SUBPRIO); + HAL_NVIC_SetPriority(getTimerCCIrq(htim->Instance), obj->preemptPriority, obj->subPriority); HAL_NVIC_EnableIRQ(getTimerCCIrq(htim->Instance)); } } diff --git a/cores/arduino/stm32/timer.h b/cores/arduino/stm32/timer.h index ae8d2563f1..3f8b8abb11 100644 --- a/cores/arduino/stm32/timer.h +++ b/cores/arduino/stm32/timer.h @@ -238,6 +238,8 @@ typedef struct { // Those 2 first fields must remain in this order at the beginning of the structure void *__this; TIM_HandleTypeDef handle; + uint32_t preemptPriority; + uint32_t subPriority; } timerObj_t; /* Exported functions ------------------------------------------------------- */ From 402818f4f7e3e08015ae252d09a31323ecc76d87 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Mon, 4 Nov 2019 11:48:55 +0100 Subject: [PATCH 3/3] [SoftwareSerial] Add function to set interrupt priority Fixes #751 Signed-off-by: Frederic Pillon --- libraries/SoftwareSerial/src/SoftwareSerial.cpp | 5 +++++ libraries/SoftwareSerial/src/SoftwareSerial.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.cpp b/libraries/SoftwareSerial/src/SoftwareSerial.cpp index 9ba9dbb731..ebf9fe70e6 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.cpp +++ b/libraries/SoftwareSerial/src/SoftwareSerial.cpp @@ -419,3 +419,8 @@ int SoftwareSerial::peek() // Read from "head" return _receive_buffer[_receive_buffer_head]; } + +void SoftwareSerial::setInterruptPriority(uint32_t preemptPriority, uint32_t subPriority) +{ + timer.setInterruptPriority(preemptPriority, subPriority); +} \ No newline at end of file diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.h b/libraries/SoftwareSerial/src/SoftwareSerial.h index 7ec0aee188..6e9eb8fef4 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.h +++ b/libraries/SoftwareSerial/src/SoftwareSerial.h @@ -118,6 +118,8 @@ class SoftwareSerial : public Stream { return true; } + static void setInterruptPriority(uint32_t preemptPriority, uint32_t subPriority); + using Print::write; };