switch stm32 scheduling to use PWM driver (#1983)
* move to folder * extract hardware part of microsecond_timer * dead ST forum link * de-volatile * simulator build * guard * switch stm32 to pwm timer * comments * f7 mcuconf * simulator * guard * warning * header, cleanup * constant * less magic Co-authored-by: Matthew Kennedy <makenne@microsoft.com>
This commit is contained in:
parent
64fdfba435
commit
8ad2080df7
|
@ -179,7 +179,7 @@
|
|||
#define STM32_GPT_USE_TIM2 FALSE
|
||||
#define STM32_GPT_USE_TIM3 FALSE
|
||||
#define STM32_GPT_USE_TIM4 FALSE
|
||||
#define STM32_GPT_USE_TIM5 TRUE
|
||||
#define STM32_GPT_USE_TIM5 FALSE
|
||||
#define STM32_GPT_USE_TIM6 TRUE
|
||||
#define STM32_GPT_USE_TIM7 FALSE
|
||||
#define STM32_GPT_USE_TIM8 FALSE
|
||||
|
@ -191,7 +191,7 @@
|
|||
#define STM32_GPT_TIM2_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM3_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM4_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM5_IRQ_PRIORITY PRECISE_SCHEDULING_TIMER_PRIORITY
|
||||
#define STM32_GPT_TIM5_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM6_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM7_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM8_IRQ_PRIORITY 7
|
||||
|
@ -273,14 +273,14 @@
|
|||
#define STM32_PWM_USE_TIM2 FALSE
|
||||
#define STM32_PWM_USE_TIM3 FALSE
|
||||
#define STM32_PWM_USE_TIM4 TRUE
|
||||
#define STM32_PWM_USE_TIM5 FALSE
|
||||
#define STM32_PWM_USE_TIM5 TRUE
|
||||
#define STM32_PWM_USE_TIM8 TRUE
|
||||
#define STM32_PWM_USE_TIM9 FALSE
|
||||
#define STM32_PWM_TIM1_IRQ_PRIORITY 7
|
||||
#define STM32_PWM_TIM2_IRQ_PRIORITY 7
|
||||
#define STM32_PWM_TIM3_IRQ_PRIORITY 7
|
||||
#define STM32_PWM_TIM4_IRQ_PRIORITY 7
|
||||
#define STM32_PWM_TIM5_IRQ_PRIORITY 7
|
||||
#define STM32_PWM_TIM5_IRQ_PRIORITY PRECISE_SCHEDULING_TIMER_PRIORITY
|
||||
#define STM32_PWM_TIM8_IRQ_PRIORITY 7
|
||||
#define STM32_PWM_TIM9_IRQ_PRIORITY 7
|
||||
|
||||
|
|
|
@ -200,7 +200,7 @@
|
|||
#define STM32_GPT_USE_TIM2 FALSE
|
||||
#define STM32_GPT_USE_TIM3 FALSE
|
||||
#define STM32_GPT_USE_TIM4 FALSE
|
||||
#define STM32_GPT_USE_TIM5 TRUE
|
||||
#define STM32_GPT_USE_TIM5 FALSE
|
||||
#define STM32_GPT_USE_TIM6 TRUE
|
||||
#define STM32_GPT_USE_TIM7 FALSE
|
||||
#define STM32_GPT_USE_TIM8 FALSE
|
||||
|
@ -212,7 +212,7 @@
|
|||
#define STM32_GPT_TIM2_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM3_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM4_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM5_IRQ_PRIORITY PRECISE_SCHEDULING_TIMER_PRIORITY
|
||||
#define STM32_GPT_TIM5_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM6_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM7_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM8_IRQ_PRIORITY 7
|
||||
|
@ -284,14 +284,14 @@
|
|||
#define STM32_PWM_USE_TIM2 FALSE
|
||||
#define STM32_PWM_USE_TIM3 FALSE
|
||||
#define STM32_PWM_USE_TIM4 TRUE
|
||||
#define STM32_PWM_USE_TIM5 FALSE
|
||||
#define STM32_PWM_USE_TIM5 TRUE
|
||||
#define STM32_PWM_USE_TIM8 TRUE
|
||||
#define STM32_PWM_USE_TIM9 FALSE
|
||||
#define STM32_PWM_TIM1_IRQ_PRIORITY 7
|
||||
#define STM32_PWM_TIM2_IRQ_PRIORITY 7
|
||||
#define STM32_PWM_TIM3_IRQ_PRIORITY 7
|
||||
#define STM32_PWM_TIM4_IRQ_PRIORITY 7
|
||||
#define STM32_PWM_TIM5_IRQ_PRIORITY 7
|
||||
#define STM32_PWM_TIM5_IRQ_PRIORITY PRECISE_SCHEDULING_TIMER_PRIORITY
|
||||
#define STM32_PWM_TIM8_IRQ_PRIORITY 7
|
||||
#define STM32_PWM_TIM9_IRQ_PRIORITY 7
|
||||
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/**
|
||||
* @file microsecond_timer_stm32.cpp
|
||||
*
|
||||
* A single upcounting timer (currently TIM5) is used as a single timebase both for time
|
||||
* measurement and event scheduling. This helps reduce jitter by not making another time
|
||||
* measurement at the time of scheduling.
|
||||
*
|
||||
* This implementation only works on stm32 because it sets hardware registers directly.
|
||||
* ChibiOS doesn't support using timers in output compare mode, only PMW, so we have to
|
||||
* manually configure the timer in outupt compare mode.
|
||||
*
|
||||
* @date Dec 1, 2020
|
||||
* @author Matthew Kennedy, (c) 2012-2020
|
||||
*/
|
||||
|
||||
#include "global.h"
|
||||
|
||||
#if EFI_PROD_CODE && HAL_USE_PWM
|
||||
|
||||
#include "port_microsecond_timer.h"
|
||||
|
||||
void portSetHardwareSchedulerTimer(efitick_t nowNt, efitick_t setTimeNt) {
|
||||
// This implementation doesn't need the current time, only the target time
|
||||
UNUSED(nowNt);
|
||||
|
||||
pwm_lld_enable_channel(&SCHEDULER_PWM_DEVICE, 0, setTimeNt);
|
||||
pwmEnableChannelNotificationI(&SCHEDULER_PWM_DEVICE, 0);
|
||||
}
|
||||
|
||||
static void hwTimerCallback(PWMDriver*) {
|
||||
pwmDisableChannelNotificationI(&SCHEDULER_PWM_DEVICE, 0);
|
||||
portMicrosecondTimerCallback();
|
||||
}
|
||||
|
||||
static constexpr PWMConfig timerConfig = {
|
||||
SCHEDULER_TIMER_FREQ,
|
||||
UINT32_MAX, // timer period = 2^32 counts
|
||||
nullptr, // No update callback
|
||||
{
|
||||
{PWM_OUTPUT_DISABLED, hwTimerCallback}, // Channel 0 = timer callback, others unused
|
||||
{PWM_OUTPUT_DISABLED, nullptr},
|
||||
{PWM_OUTPUT_DISABLED, nullptr},
|
||||
{PWM_OUTPUT_DISABLED, nullptr}
|
||||
},
|
||||
0, // CR1
|
||||
0 // CR2
|
||||
};
|
||||
|
||||
void portInitMicrosecondTimer() {
|
||||
pwmStart(&SCHEDULER_PWM_DEVICE, &timerConfig);
|
||||
|
||||
// ChibiOS doesn't let you configure timers in output compare mode, only PWM mode.
|
||||
// We want to be able to set the compare register without waiting for an update event
|
||||
// (which would take 358 seconds at 12mhz timer speed), so we have to use normal upcounting
|
||||
// output compare mode instead.
|
||||
SCHEDULER_TIMER_DEVICE->CCMR1 = STM32_TIM_CCMR1_OC1M(1);
|
||||
}
|
||||
|
||||
uint32_t getTimeNowLowerNt() {
|
||||
// Using the same timer for measurement and scheduling improves
|
||||
// precision and reduces jitter.
|
||||
return SCHEDULER_TIMER_DEVICE->CNT;
|
||||
}
|
||||
|
||||
#endif // EFI_PROD_CODE
|
|
@ -10,11 +10,14 @@
|
|||
|
||||
#include "device_mpu_util.h"
|
||||
|
||||
// 168 ticks in microsecond in case of 168MHz 407
|
||||
#define US_TO_NT_MULTIPLIER (CORE_CLOCK / 1000000)
|
||||
// 12mhz was chosen because it's the GCD of (168, 180, 216), the three speeds of STM32 currently supported
|
||||
// https://www.wolframalpha.com/input/?i=common+factors+of+168+180+216
|
||||
#define US_TO_NT_MULTIPLIER (12)
|
||||
|
||||
// Scheduler queue GPT device - use TIM5
|
||||
#define GPTDEVICE GPTD5
|
||||
// Scheduler queue timer - use TIM5
|
||||
#define SCHEDULER_PWM_DEVICE PWMD5
|
||||
#define SCHEDULER_TIMER_DEVICE TIM5
|
||||
#define SCHEDULER_TIMER_FREQ (US_TO_NT_MULTIPLIER * 1'000'000)
|
||||
|
||||
typedef enum {
|
||||
BOR_Level_None = OB_BOR_OFF, // 0x0C=12 Supply voltage ranges from 1.62 to 2.10 V
|
||||
|
|
|
@ -6,7 +6,7 @@ HW_LAYER_EMS_CPP += \
|
|||
$(PROJECT_DIR)/hw_layer/ports/stm32/stm32_pins.cpp \
|
||||
$(PROJECT_DIR)/hw_layer/ports/stm32/stm32_common.cpp \
|
||||
$(PROJECT_DIR)/hw_layer/ports/stm32/backup_ram.cpp \
|
||||
$(PROJECT_DIR)/hw_layer/microsecond_timer/microsecond_timer_gpt.cpp \
|
||||
$(PROJECT_DIR)/hw_layer/ports/stm32/microsecond_timer_stm32.cpp \
|
||||
|
||||
RUSEFIASM = $(PROJECT_DIR)/hw_layer/ports/stm32/rusEfiStartup.S
|
||||
|
||||
|
|
|
@ -7,11 +7,16 @@
|
|||
|
||||
#include "global.h"
|
||||
#include "framework.h"
|
||||
#include "efitime.h"
|
||||
|
||||
efitick_t getTimeNowNt(void) {
|
||||
return getTimeNowUs() * US_TO_NT_MULTIPLIER;
|
||||
}
|
||||
|
||||
uint32_t getTimeNowLowerNt(void) {
|
||||
return getTimeNowNt();
|
||||
}
|
||||
|
||||
efitimeus_t getTimeNowUs(void) {
|
||||
return chVTGetSystemTimeX() * (1000000 / CH_CFG_ST_FREQUENCY);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue