Skip to content

Feat stm32 synctimers #374

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 6 commits into from
Feb 5, 2024
Merged
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
196 changes: 175 additions & 21 deletions src/drivers/hardware_specific/stm32/stm32_mcu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@

#if defined(_STM32_DEF_)

#define SIMPLEFOC_STM32_DEBUG
#pragma message("")
#pragma message("SimpleFOC: compiling for STM32")
#pragma message("")


//#define SIMPLEFOC_STM32_DEBUG

#ifdef SIMPLEFOC_STM32_DEBUG
void printTimerCombination(int numPins, PinMap* timers[], int score);
int getTimerNumber(int timerIndex);
Expand Down Expand Up @@ -204,25 +203,112 @@ void _stopTimers(HardwareTimer **timers_to_stop, int timer_num)
}
}

// align the timers to end the init
void _startTimers(HardwareTimer **timers_to_start, int timer_num)
{
// TODO - sart each timer only once
// sart timers
for (int i=0; i < timer_num; i++) {
if(timers_to_start[i] == NP) return;
timers_to_start[i]->resume();
#ifdef SIMPLEFOC_STM32_DEBUG
SIMPLEFOC_DEBUG("STM32-DRV: Starting timer ", getTimerNumber(get_timer_index(timers_to_start[i]->getHandle()->Instance)));
#endif
}

#if defined(STM32G4xx)
// function finds the appropriate timer source trigger for the master/slave timer combination
// returns -1 if no trigger source is found
// currently supports the master timers to be from TIM1 to TIM4 and TIM8
int _getInternalSourceTrigger(HardwareTimer* master, HardwareTimer* slave) { // put master and slave in temp variables to avoid arrows
TIM_TypeDef *TIM_master = master->getHandle()->Instance;
#if defined(TIM1) && defined(LL_TIM_TS_ITR0)
if (TIM_master == TIM1) return LL_TIM_TS_ITR0;// return TIM_TS_ITR0;
#endif
#if defined(TIM2) && defined(LL_TIM_TS_ITR1)
else if (TIM_master == TIM2) return LL_TIM_TS_ITR1;//return TIM_TS_ITR1;
#endif
#if defined(TIM3) && defined(LL_TIM_TS_ITR2)
else if (TIM_master == TIM3) return LL_TIM_TS_ITR2;//return TIM_TS_ITR2;
#endif
#if defined(TIM4) && defined(LL_TIM_TS_ITR3)
else if (TIM_master == TIM4) return LL_TIM_TS_ITR3;//return TIM_TS_ITR3;
#endif
#if defined(TIM5) && defined(LL_TIM_TS_ITR4)
else if (TIM_master == TIM5) return LL_TIM_TS_ITR4;//return TIM_TS_ITR4;
#endif
#if defined(TIM8) && defined(LL_TIM_TS_ITR5)
else if (TIM_master == TIM8) return LL_TIM_TS_ITR5;//return TIM_TS_ITR5;
#endif
return -1;
}
#elif defined(STM32F4xx) || defined(STM32F1xx) || defined(STM32L4xx)

// function finds the appropriate timer source trigger for the master/slave timer combination
// returns -1 if no trigger source is found
// currently supports the master timers to be from TIM1 to TIM4 and TIM8
int _getInternalSourceTrigger(HardwareTimer* master, HardwareTimer* slave) {
// put master and slave in temp variables to avoid arrows
TIM_TypeDef *TIM_master = master->getHandle()->Instance;
TIM_TypeDef *TIM_slave = slave->getHandle()->Instance;
#if defined(TIM1) && defined(LL_TIM_TS_ITR0)
if (TIM_master == TIM1){
if(TIM_slave == TIM2 || TIM_slave == TIM3 || TIM_slave == TIM4) return LL_TIM_TS_ITR0;
#if defined(TIM8)
else if(TIM_slave == TIM8) return LL_TIM_TS_ITR0;
#endif
}
#endif
#if defined(TIM2) && defined(LL_TIM_TS_ITR1)
else if (TIM_master == TIM2){
if(TIM_slave == TIM1 || TIM_slave == TIM3 || TIM_slave == TIM4) return LL_TIM_TS_ITR1;
#if defined(TIM8)
else if(TIM_slave == TIM8) return LL_TIM_TS_ITR1;
#endif
#if defined(TIM5)
else if(TIM_slave == TIM5) return LL_TIM_TS_ITR0;
#endif
}
#endif
#if defined(TIM3) && defined(LL_TIM_TS_ITR2)
else if (TIM_master == TIM3){
if(TIM_slave== TIM1 || TIM_slave == TIM2 || TIM_slave == TIM4) return LL_TIM_TS_ITR2;
#if defined(TIM5)
else if(TIM_slave == TIM5) return LL_TIM_TS_ITR1;
#endif
}
#endif
#if defined(TIM4) && defined(LL_TIM_TS_ITR3)
else if (TIM_master == TIM4){
if(TIM_slave == TIM1 || TIM_slave == TIM2 || TIM_slave == TIM3) return LL_TIM_TS_ITR3;
#if defined(TIM8)
else if(TIM_slave == TIM8) return LL_TIM_TS_ITR2;
#endif
#if defined(TIM5)
else if(TIM_slave == TIM5) return LL_TIM_TS_ITR1;
#endif
}
#endif
#if defined(TIM5)
else if (TIM_master == TIM5){
#if !defined(STM32L4xx) // only difference between F4,F1 and L4
if(TIM_slave == TIM1) return LL_TIM_TS_ITR0;
else if(TIM_slave == TIM3) return LL_TIM_TS_ITR2;
#endif
#if defined(TIM8)
if(TIM_slave == TIM8) return LL_TIM_TS_ITR3;
#endif
}
#endif
#if defined(TIM8)
else if (TIM_master == TIM8){
if(TIM_slave==TIM2) return LL_TIM_TS_ITR1;
else if(TIM_slave ==TIM4 || TIM_slave ==TIM5) return LL_TIM_TS_ITR3;
}
#endif
return -1; // combination not supported
}
#else
// Alignment not supported for this architecture
int _getInternalSourceTrigger(HardwareTimer* master, HardwareTimer* slave) {
return -1;
}
#endif


void _alignTimersNew() {
int numTimers = 0;
HardwareTimer *timers[numTimerPinsUsed];

// reset timer counters
// find the timers used
for (int i=0; i<numTimerPinsUsed; i++) {
uint32_t index = get_timer_index((TIM_TypeDef*)timerPinsUsed[i]->peripheral);
HardwareTimer *timer = (HardwareTimer *)(HardwareTimer_Handle[index]->__this);
Expand All @@ -237,6 +323,62 @@ void _alignTimersNew() {
timers[numTimers++] = timer;
}

#ifdef SIMPLEFOC_STM32_DEBUG
SIMPLEFOC_DEBUG("STM32-DRV: Syncronising timers! Timer no. ", numTimers);
#endif

// see if there is more then 1 timers used for the pwm
// if yes, try to align timers
if(numTimers > 1){
// find the master timer
int16_t master_index = -1;
int triggerEvent = -1;
for (int i=0; i<numTimers; i++) {
// check if timer can be master
if(IS_TIM_MASTER_INSTANCE(timers[i]->getHandle()->Instance)) {
// check if timer already configured in TRGO update mode (used for ADC triggering)
// in that case we should not change its TRGO configuration
if(timers[i]->getHandle()->Instance->CR2 & LL_TIM_TRGO_UPDATE) continue;
// check if the timer has the supported internal trigger for other timers
for (int slave_i=0; slave_i<numTimers; slave_i++) {
if (i==slave_i) continue; // skip self
// check if it has the supported internal trigger
triggerEvent = _getInternalSourceTrigger(timers[i],timers[slave_i]);
if(triggerEvent == -1) break; // not supported keep searching
}
if(triggerEvent == -1) continue; // cannot be master, keep searching
// otherwise the master has been found, remember the index
master_index = i; // found the master timer
break;
}
}


// if no master timer found do not perform alignment
if (master_index == -1) {
#ifdef SIMPLEFOC_STM32_DEBUG
SIMPLEFOC_DEBUG("STM32-DRV: ERR: No master timer found, cannot align timers!");
#endif
}else{
#ifdef SIMPLEFOC_STM32_DEBUG
SIMPLEFOC_DEBUG("STM32-DRV: Aligning PWM to master timer: ", getTimerNumber(get_timer_index(timers[master_index]->getHandle()->Instance)));
#endif
// make the master timer generate ITRGx event
// if it was already configured in slave mode
LL_TIM_SetSlaveMode(timers[master_index]->getHandle()->Instance, LL_TIM_SLAVEMODE_DISABLED );
// Configure the master timer to send a trigger signal on enable
LL_TIM_SetTriggerOutput(timers[master_index]->getHandle()->Instance, LL_TIM_TRGO_ENABLE);
// configure other timers to get the input trigger from the master timer
for (int slave_index=0; slave_index < numTimers; slave_index++) {
if (slave_index == master_index)
continue;
// Configure the slave timer to be triggered by the master enable signal
LL_TIM_SetTriggerInput(timers[slave_index]->getHandle()->Instance, _getInternalSourceTrigger(timers[master_index], timers[slave_index]));
LL_TIM_SetSlaveMode(timers[slave_index]->getHandle()->Instance, LL_TIM_SLAVEMODE_TRIGGER);
}
}
}

// enable timer clock
for (int i=0; i<numTimers; i++) {
timers[i]->pause();
Expand All @@ -254,6 +396,20 @@ void _alignTimersNew() {



// align the timers to end the init
void _startTimers(HardwareTimer **timers_to_start, int timer_num)
{
// // TODO - start each timer only once
// // start timers
// for (int i=0; i < timer_num; i++) {
// if(timers_to_start[i] == NP) return;
// timers_to_start[i]->resume();
// #ifdef SIMPLEFOC_STM32_DEBUG
// SIMPLEFOC_DEBUG("STM32-DRV: Starting timer ", getTimerNumber(get_timer_index(timers_to_start[i]->getHandle()->Instance)));
// #endif
// }
_alignTimersNew();
}


// configure hardware 6pwm for a complementary pair of channels
Expand Down Expand Up @@ -540,7 +696,7 @@ void* _configure1PWM(long pwm_frequency, const int pinA) {
return (STM32DriverParams*)SIMPLEFOC_DRIVER_INIT_FAILED;

HardwareTimer* HT1 = _initPinPWM(pwm_frequency, pinTimers[0]);\
// allign the timers
// align the timers
_alignTimersNew();

uint32_t channel1 = STM_PIN_CHANNEL(pinTimers[0]->function);
Expand Down Expand Up @@ -598,6 +754,8 @@ void* _configure2PWM(long pwm_frequency, const int pinA, const int pinB) {



TIM_MasterConfigTypeDef sMasterConfig;
TIM_SlaveConfigTypeDef sSlaveConfig;

// function setting the high pwm frequency to the supplied pins
// - BLDC motor - 3PWM setting
Expand All @@ -620,7 +778,7 @@ void* _configure3PWM(long pwm_frequency,const int pinA, const int pinB, const in
HardwareTimer* HT1 = _initPinPWM(pwm_frequency, pinTimers[0]);
HardwareTimer* HT2 = _initPinPWM(pwm_frequency, pinTimers[1]);
HardwareTimer* HT3 = _initPinPWM(pwm_frequency, pinTimers[2]);

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 @@ -945,8 +1103,4 @@ void printTimerCombination(int numPins, PinMap* timers[], int score) {

#endif





#endif