Skip to content

Commit

Permalink
Merge pull request #2294 from fpistm/HT_comp
Browse files Browse the repository at this point in the history
feat(HardwareTimer): support regular and complementary channels
  • Loading branch information
fpistm authored Mar 7, 2024
2 parents 7f5d45e + 9dfb520 commit cd7bdbb
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 82 deletions.
7 changes: 4 additions & 3 deletions cores/arduino/HardwareTimer.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,11 @@ class HardwareTimer {
int getLLChannel(uint32_t channel);
int getIT(uint32_t channel);
int getAssociatedChannel(uint32_t channel);
#if defined(TIM_CCER_CC1NE)
bool isComplementaryChannel[TIMER_CHANNELS];
#endif

private:
// Store for each channel if regular, complementary or both are used
// High part for complementary (COMPLEMENTARY_CHAN_MASK), low part for regular (REGULAR_CHAN_MASK)
uint8_t __ChannelsUsed[TIMER_CHANNELS];
TimerModes_t _ChannelMode[TIMER_CHANNELS];
timerObj_t _timerObj;
callback_function_t callbacks[1 + TIMER_CHANNELS]; //Callbacks: 0 for update, 1-4 for channels. (channel5/channel6, if any, doesn't have interrupt)
Expand Down
120 changes: 41 additions & 79 deletions libraries/SrcWrapper/src/HardwareTimer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
/* Private Defines */
#define PIN_NOT_USED 0xFF
#define MAX_RELOAD ((1 << 16) - 1) // Currently even 32b timers are used as 16b to have generic behavior
#define REGULAR_CHAN_MASK 0x01
#define COMPLEMENTARY_CHAN_MASK 0x10

/* Private Variables */
timerObj_t *HardwareTimer_Handle[TIMER_NUM] = {NULL};
Expand Down Expand Up @@ -73,9 +75,6 @@ HardwareTimer::HardwareTimer(TIM_TypeDef *instance)
void HardwareTimer::setup(TIM_TypeDef *instance)
{
uint32_t index = get_timer_index(instance);
if (index == UNKNOWN_TIMER) {
Error_Handler();
}

// Already initialized?
if (_timerObj.handle.Instance) {
Expand Down Expand Up @@ -111,9 +110,7 @@ void HardwareTimer::setup(TIM_TypeDef *instance)

// Initialize channel mode and complementary
for (int i = 0; i < TIMER_CHANNELS; i++) {
#if defined(TIM_CCER_CC1NE)
isComplementaryChannel[i] = false;
#endif
__ChannelsUsed[i] = 0x00;
_ChannelMode[i] = TIMER_DISABLED;
}

Expand Down Expand Up @@ -174,14 +171,7 @@ void HardwareTimer::pauseChannel(uint32_t channel)

int timAssociatedInputChannel;
int LLChannel = getLLChannel(channel);
if (LLChannel == -1) {
Error_Handler();
}

int interrupt = getIT(channel);
if (interrupt == -1) {
Error_Handler();
}

// Disable channel and corresponding interrupt
__HAL_TIM_DISABLE_IT(&(_timerObj.handle), interrupt);
Expand All @@ -190,11 +180,11 @@ void HardwareTimer::pauseChannel(uint32_t channel)
/* Starting from G4, new Channel state implementation prevents to restart a channel,
if the channel has not been explicitly be stopped with HAL interface */
#if defined(TIM_CHANNEL_N_STATE_SET)
if (isComplementaryChannel[channel - 1]) {
if (__ChannelsUsed[channel - 1] & COMPLEMENTARY_CHAN_MASK) {
TIM_CHANNEL_N_STATE_SET(&(_timerObj.handle), getChannel(channel), HAL_TIM_CHANNEL_STATE_READY);
} else
}
#endif
{
if (__ChannelsUsed[channel - 1] & REGULAR_CHAN_MASK) {
TIM_CHANNEL_STATE_SET(&(_timerObj.handle), getChannel(channel), HAL_TIM_CHANNEL_STATE_READY);
}
#endif
Expand Down Expand Up @@ -234,11 +224,11 @@ void HardwareTimer::resume(void)
/**
* @brief Convert arduino channel into HAL channel
* @param Arduino channel [1..4]
* @retval HAL channel. return -1 if arduino channel is invalid
* @retval HAL channel. Error handler called if arduino channel is invalid
*/
int HardwareTimer::getChannel(uint32_t channel)
{
uint32_t return_value;
int return_value = -1;

switch (channel) {
case 1:
Expand All @@ -254,21 +244,22 @@ int HardwareTimer::getChannel(uint32_t channel)
return_value = TIM_CHANNEL_4;
break;
default:
return_value = -1;
Error_Handler();
}
return return_value;
}

/**
* @brief Convert arduino channel into LL channel
* @brief Convert arduino channel into LL channels used (regular and/or complementary)
* @param Arduino channel [1..4]
* @retval LL channel. return -1 if arduino channel is invalid
* @retval LL channel. Error handler called if arduino channel is invalid
*/
int HardwareTimer::getLLChannel(uint32_t channel)
{
uint32_t return_value;
int return_value = 0;

#if defined(TIM_CCER_CC1NE)
if (isComplementaryChannel[channel - 1]) {
if (__ChannelsUsed[channel - 1] & COMPLEMENTARY_CHAN_MASK) {
// Complementary channel
switch (channel) {
case 1:
Expand All @@ -288,38 +279,41 @@ int HardwareTimer::getLLChannel(uint32_t channel)
default:
return_value = -1;
}
} else
}
#endif
{
if ((return_value != -1) && (__ChannelsUsed[channel - 1] & REGULAR_CHAN_MASK)) {
// Regular channel not complementary
switch (channel) {
case 1:
return_value = LL_TIM_CHANNEL_CH1;
return_value |= LL_TIM_CHANNEL_CH1;
break;
case 2:
return_value = LL_TIM_CHANNEL_CH2;
return_value |= LL_TIM_CHANNEL_CH2;
break;
case 3:
return_value = LL_TIM_CHANNEL_CH3;
return_value |= LL_TIM_CHANNEL_CH3;
break;
case 4:
return_value = LL_TIM_CHANNEL_CH4;
return_value |= LL_TIM_CHANNEL_CH4;
break;
default:
return_value = -1;
}
}
if (return_value == -1) {
Error_Handler();
}
return return_value;
}

/**
* @brief Convert arduino channel into HAL Interrupt ID
* @param Arduino channel [1..4]
* @retval HAL channel. return -1 if arduino channel is invalid
* @retval HAL channel. Error handler called if arduino channel is invalid
*/
int HardwareTimer::getIT(uint32_t channel)
{
uint32_t return_value;
int return_value = -1;

switch (channel) {
case 1:
Expand All @@ -335,7 +329,7 @@ int HardwareTimer::getIT(uint32_t channel)
return_value = TIM_IT_CC4;
break;
default:
return_value = -1;
Error_Handler();
}
return return_value;
}
Expand Down Expand Up @@ -377,19 +371,7 @@ void HardwareTimer::resumeChannel(uint32_t channel)
{
int timChannel = getChannel(channel);
int timAssociatedInputChannel;
if (timChannel == -1) {
Error_Handler();
}

int interrupt = getIT(channel);
if (interrupt == -1) {
Error_Handler();
}

int LLChannel = getLLChannel(channel);
if (LLChannel == -1) {
Error_Handler();
}

// Clear flag and enable IT
if (callbacks[channel]) {
Expand All @@ -401,11 +383,11 @@ void HardwareTimer::resumeChannel(uint32_t channel)
case TIMER_OUTPUT_COMPARE_PWM1:
case TIMER_OUTPUT_COMPARE_PWM2: {
#if defined(TIM_CCER_CC1NE)
if (isComplementaryChannel[channel - 1]) {
if (__ChannelsUsed[channel - 1] & COMPLEMENTARY_CHAN_MASK) {
HAL_TIMEx_PWMN_Start(&(_timerObj.handle), timChannel);
} else
}
#endif
{
if (__ChannelsUsed[channel - 1] & REGULAR_CHAN_MASK) {
HAL_TIM_PWM_Start(&(_timerObj.handle), timChannel);
}
}
Expand All @@ -416,11 +398,11 @@ void HardwareTimer::resumeChannel(uint32_t channel)
case TIMER_OUTPUT_COMPARE_FORCED_ACTIVE:
case TIMER_OUTPUT_COMPARE_FORCED_INACTIVE: {
#if defined(TIM_CCER_CC1NE)
if (isComplementaryChannel[channel - 1]) {
if (__ChannelsUsed[channel - 1] & COMPLEMENTARY_CHAN_MASK) {
HAL_TIMEx_OCN_Start(&(_timerObj.handle), timChannel);
} else
}
#endif
{
if (__ChannelsUsed[channel - 1] & REGULAR_CHAN_MASK) {
HAL_TIM_OC_Start(&(_timerObj.handle), timChannel);
}
}
Expand Down Expand Up @@ -642,10 +624,6 @@ void HardwareTimer::setMode(uint32_t channel, TimerModes_t mode, PinName pin, Ch
TIM_OC_InitTypeDef channelOC;
TIM_IC_InitTypeDef channelIC;

if (timChannel == -1) {
Error_Handler();
}

/* Configure some default values. Maybe overwritten later */
channelOC.OCMode = TIMER_NOT_USED;
channelOC.Pulse = __HAL_TIM_GET_COMPARE(&(_timerObj.handle), timChannel); // keep same value already written in hardware register
Expand Down Expand Up @@ -724,13 +702,18 @@ void HardwareTimer::setMode(uint32_t channel, TimerModes_t mode, PinName pin, Ch
HAL_TIM_IC_ConfigChannel(&(_timerObj.handle), &channelIC, timChannel);
break;
case TIMER_INPUT_FREQ_DUTY_MEASUREMENT:
// Check if regular channel
if (STM_PIN_INVERTED(pinmap_function(pin, PinMap_TIM))) {
Error_Handler();
}
// Configure 1st channel
channelIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
channelIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
HAL_TIM_IC_ConfigChannel(&(_timerObj.handle), &channelIC, timChannel);

// Identify and configure 2nd associated channel
timAssociatedInputChannel = getAssociatedChannel(channel);
__ChannelsUsed[timAssociatedInputChannel - 1] |= REGULAR_CHAN_MASK;
_ChannelMode[timAssociatedInputChannel - 1] = mode;
channelIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;
channelIC.ICSelection = TIM_ICSELECTION_INDIRECTTI;
Expand Down Expand Up @@ -759,9 +742,7 @@ void HardwareTimer::setMode(uint32_t channel, TimerModes_t mode, PinName pin, Ch
Error_Handler();
}

#if defined(TIM_CCER_CC1NE)
isComplementaryChannel[channel - 1] = STM_PIN_INVERTED(pinmap_function(pin, PinMap_TIM));
#endif
__ChannelsUsed[channel - 1] |= (STM_PIN_INVERTED(pinmap_function(pin, PinMap_TIM))) ? COMPLEMENTARY_CHAN_MASK : REGULAR_CHAN_MASK;
}
}

Expand Down Expand Up @@ -818,10 +799,6 @@ void HardwareTimer::setCaptureCompare(uint32_t channel, uint32_t compare, TimerC
uint32_t Prescalerfactor = LL_TIM_GetPrescaler(_timerObj.handle.Instance) + 1;
uint32_t CCR_RegisterValue;

if (timChannel == -1) {
Error_Handler();
}

switch (format) {
case MICROSEC_COMPARE_FORMAT:
CCR_RegisterValue = ((compare * (getTimerClkFreq() / 1000000)) / Prescalerfactor);
Expand Down Expand Up @@ -885,10 +862,6 @@ uint32_t HardwareTimer::getCaptureCompare(uint32_t channel, TimerCompareFormat_
uint32_t Prescalerfactor = LL_TIM_GetPrescaler(_timerObj.handle.Instance) + 1;
uint32_t return_value;

if (timChannel == -1) {
Error_Handler();
}

switch (format) {
case MICROSEC_COMPARE_FORMAT:
return_value = (uint32_t)((CCR_RegisterValue * Prescalerfactor * 1000000.0) / getTimerClkFreq());
Expand Down Expand Up @@ -1026,9 +999,6 @@ void HardwareTimer::detachInterrupt()
void HardwareTimer::attachInterrupt(uint32_t channel, callback_function_t callback)
{
int interrupt = getIT(channel);
if (interrupt == -1) {
Error_Handler();
}

if ((channel == 0) || (channel > (TIMER_CHANNELS + 1))) {
Error_Handler(); // only channel 1..4 have an interrupt
Expand All @@ -1055,9 +1025,6 @@ void HardwareTimer::attachInterrupt(uint32_t channel, callback_function_t callba
void HardwareTimer::detachInterrupt(uint32_t channel)
{
int interrupt = getIT(channel);
if (interrupt == -1) {
Error_Handler();
}

if ((channel == 0) || (channel > (TIMER_CHANNELS + 1))) {
Error_Handler(); // only channel 1..4 have an interrupt
Expand Down Expand Up @@ -1194,14 +1161,6 @@ bool HardwareTimer::isRunningChannel(uint32_t channel)
int interrupt = getIT(channel);
bool ret;

if (LLChannel == -1) {
Error_Handler();
}

if (interrupt == -1) {
Error_Handler();
}

// channel is running if: timer is running, and either output channel is
// enabled or interrupt is set
ret = LL_TIM_CC_IsEnabledChannel(_timerObj.handle.Instance, LLChannel)
Expand Down Expand Up @@ -1361,6 +1320,9 @@ timer_index_t get_timer_index(TIM_TypeDef *instance)
index = TIMER22_INDEX;
}
#endif
if (index == UNKNOWN_TIMER) {
Error_Handler();
}
return index;
}

Expand Down

0 comments on commit cd7bdbb

Please sign in to comment.