Skip to content

Set STM32 timer prescaler based on timer clock frequency #388

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 43 additions & 2 deletions src/drivers/hardware_specific/stm32/stm32_mcu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,15 @@ PinMap* timerPinsUsed[SIMPLEFOC_STM32_MAX_PINTIMERSUSED];



bool _getPwmState(void* params) {
// assume timers are synchronized and that there's at least one timer
HardwareTimer* pHT = ((STM32DriverParams*)params)->timers[0];
TIM_HandleTypeDef* htim = pHT->getHandle();

bool dir = __HAL_TIM_IS_TIM_COUNTING_DOWN(htim);

return dir;
}


// setting pwm to hardware pin - instead analogWrite()
Expand Down Expand Up @@ -230,7 +238,7 @@ int _getInternalSourceTrigger(HardwareTimer* master, HardwareTimer* slave) { //
#endif
return -1;
}
#elif defined(STM32F4xx) || defined(STM32F1xx) || defined(STM32L4xx)
#elif defined(STM32F4xx) || defined(STM32F1xx) || defined(STM32L4xx) || defined(STM32F7xx)

// function finds the appropriate timer source trigger for the master/slave timer combination
// returns -1 if no trigger source is found
Expand Down Expand Up @@ -303,6 +311,30 @@ int _getInternalSourceTrigger(HardwareTimer* master, HardwareTimer* slave) {
}
#endif

void syncTimerFrequency(long pwm_frequency, HardwareTimer *timers[], uint8_t num_timers) {
uint32_t max_frequency = 0;
uint32_t min_frequency = UINT32_MAX;
for (size_t i=0; i<num_timers; i++) {
uint32_t freq = timers[i]->getTimerClkFreq();
if (freq > max_frequency) {
max_frequency = freq;
} else if (freq < min_frequency) {
min_frequency = freq;
}
}
if (max_frequency==min_frequency) return;
uint32_t overflow_value = min_frequency/pwm_frequency;
for (size_t i=0; i<num_timers; i++) {
uint32_t prescale_factor = timers[i]->getTimerClkFreq()/min_frequency;
#ifdef SIMPLEFOC_DEBUG
SIMPLEFOC_DEBUG("STM32-DRV: Setting prescale to ", (float)prescale_factor);
SIMPLEFOC_DEBUG("STM32-DRV: Setting Overflow to ", (float)overflow_value);
#endif
timers[i]->setPrescaleFactor(prescale_factor);
timers[i]->setOverflow(overflow_value,TICK_FORMAT);
timers[i]->refresh();
}
}

void _alignTimersNew() {
int numTimers = 0;
Expand Down Expand Up @@ -382,7 +414,7 @@ void _alignTimersNew() {
// enable timer clock
for (int i=0; i<numTimers; i++) {
timers[i]->pause();
//timers[i]->refresh();
// timers[i]->refresh();
#ifdef SIMPLEFOC_STM32_DEBUG
SIMPLEFOC_DEBUG("STM32-DRV: Restarting timer ", getTimerNumber(get_timer_index(timers[i]->getHandle()->Instance)));
#endif
Expand Down Expand Up @@ -735,6 +767,8 @@ void* _configure2PWM(long pwm_frequency, const int pinA, const int pinB) {

HardwareTimer* HT1 = _initPinPWM(pwm_frequency, pinTimers[0]);
HardwareTimer* HT2 = _initPinPWM(pwm_frequency, pinTimers[1]);
HardwareTimer *timers[2] = {HT1, HT2};
syncTimerFrequency(pwm_frequency, timers, 2);
// allign the timers
_alignPWMTimers(HT1, HT2, HT2);

Expand Down Expand Up @@ -779,6 +813,9 @@ void* _configure3PWM(long pwm_frequency,const int pinA, const int pinB, const in
HardwareTimer* HT2 = _initPinPWM(pwm_frequency, pinTimers[1]);
HardwareTimer* HT3 = _initPinPWM(pwm_frequency, pinTimers[2]);

HardwareTimer *timers[3] = {HT1, HT2, HT3};
syncTimerFrequency(pwm_frequency, timers, 3);

uint32_t channel1 = STM_PIN_CHANNEL(pinTimers[0]->function);
uint32_t channel2 = STM_PIN_CHANNEL(pinTimers[1]->function);
uint32_t channel3 = STM_PIN_CHANNEL(pinTimers[2]->function);
Expand Down Expand Up @@ -821,6 +858,8 @@ void* _configure4PWM(long pwm_frequency,const int pinA, const int pinB, const in
HardwareTimer* HT2 = _initPinPWM(pwm_frequency, pinTimers[1]);
HardwareTimer* HT3 = _initPinPWM(pwm_frequency, pinTimers[2]);
HardwareTimer* HT4 = _initPinPWM(pwm_frequency, pinTimers[3]);
HardwareTimer *timers[4] = {HT1, HT2, HT3, HT4};
syncTimerFrequency(pwm_frequency, timers, 4);
// allign the timers
_alignPWMTimers(HT1, HT2, HT3, HT4);

Expand Down Expand Up @@ -918,6 +957,8 @@ void* _configure6PWM(long pwm_frequency, float dead_zone, const int pinA_h, cons
HardwareTimer* HT4 = _initPinPWMLow(pwm_frequency, pinTimers[3]);
HardwareTimer* HT5 = _initPinPWMHigh(pwm_frequency, pinTimers[4]);
HardwareTimer* HT6 = _initPinPWMLow(pwm_frequency, pinTimers[5]);
HardwareTimer *timers[6] = {HT1, HT2, HT3, HT4, HT5, HT6};
syncTimerFrequency(pwm_frequency, timers, 6);
uint32_t channel1 = STM_PIN_CHANNEL(pinTimers[0]->function);
uint32_t channel2 = STM_PIN_CHANNEL(pinTimers[1]->function);
uint32_t channel3 = STM_PIN_CHANNEL(pinTimers[2]->function);
Expand Down
3 changes: 3 additions & 0 deletions src/drivers/hardware_specific/stm32/stm32_mcu.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,8 @@ typedef struct STM32DriverParams {
void _stopTimers(HardwareTimer **timers_to_stop, int timer_num=6);
void _startTimers(HardwareTimer **timers_to_start, int timer_num=6);

// timer query functions
bool _getPwmState(void* params);

#endif
#endif