From 5b0819a3009793aa23414cece95be1acb1dc21b8 Mon Sep 17 00:00:00 2001 From: Ea-r-th <39779954+Ea-r-th@users.noreply.github.com> Date: Wed, 11 Mar 2026 00:31:40 -0700 Subject: [PATCH] Timer test --- CMakeLists.txt | 1 + SHAL/Include/Core/SHAL_CORE.h | 7 +++ .../Timer/Reg/SHAL_TIM_REG_F072xB.h | 41 ++++++------- SHAL/Include/Peripheral/Timer/SHAL_TIM.h | 21 ++++--- SHAL/Src/STM32F0xx/Core/SHAL_CORE.cpp | 7 +++ .../STM32F0xx/Peripheral/Timer/SHAL_TIM.cpp | 35 +++++++++-- SHAL/Src/main.cpp | 58 +++++++++++++++++-- 7 files changed, 134 insertions(+), 36 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c197e0..3ccf443 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,6 +82,7 @@ ${CPU_PARAMETERS} -Wextra -Wpedantic -Wno-unused-parameter +-Wno-unused-function $<$: -Wno-volatile -Wsuggest-override> diff --git a/SHAL/Include/Core/SHAL_CORE.h b/SHAL/Include/Core/SHAL_CORE.h index e93ec45..c05b67d 100644 --- a/SHAL/Include/Core/SHAL_CORE.h +++ b/SHAL/Include/Core/SHAL_CORE.h @@ -42,8 +42,13 @@ enum class SHAL_Result{ //Currently configures systick to count down in microseconds +inline uint32_t ticks = 0; void systick_init(); +extern "C" void SysTick_Handler(); + +static uint32_t millis(); + //Max of 16ms, use SHAL_delay_ms for longer delay void SHAL_delay_us(uint32_t us); @@ -71,6 +76,8 @@ bool SHAL_wait_for_condition_ms(Condition cond, uint32_t timeout_ms) { return false; // timeout } + + #define SHAL_set_bits(reg, size, bits, offset) \ do { \ if ((reg) != NULL) { \ diff --git a/SHAL/Include/Peripheral/Timer/Reg/SHAL_TIM_REG_F072xB.h b/SHAL/Include/Peripheral/Timer/Reg/SHAL_TIM_REG_F072xB.h index ad680bc..443f150 100644 --- a/SHAL/Include/Peripheral/Timer/Reg/SHAL_TIM_REG_F072xB.h +++ b/SHAL/Include/Peripheral/Timer/Reg/SHAL_TIM_REG_F072xB.h @@ -83,7 +83,7 @@ static SHAL_TIM_RCC_Register getTimerRCC(Timer_Key t) { } -static inline SHAL_TIM_Status_Register getTimerStatusRegister(Timer_Key key){ +static SHAL_TIM_Status_Register getTimerStatusRegister(Timer_Key key){ SHAL_TIM_Status_Register res = {nullptr, TIM_SR_UIF}; @@ -93,7 +93,7 @@ static inline SHAL_TIM_Status_Register getTimerStatusRegister(Timer_Key key){ return res; } -static inline SHAL_TIM_Control_Register_1 getTimerControlRegister1(Timer_Key key){ +static SHAL_TIM_Control_Register_1 getTimerControlRegister1(Timer_Key key){ SHAL_TIM_Control_Register_1 res = {nullptr, TIM_CR1_CEN_Msk, TIM_CR1_UDIS, @@ -107,7 +107,7 @@ static inline SHAL_TIM_Control_Register_1 getTimerControlRegister1(Timer_Key key return res; } -static inline SHAL_TIM_DMA_Interrupt_Enable_Register getTimerDMAInterruptEnableRegister(Timer_Key key){ +static SHAL_TIM_DMA_Interrupt_Enable_Register getTimerDMAInterruptEnableRegister(Timer_Key key){ SHAL_TIM_DMA_Interrupt_Enable_Register res = {nullptr, TIM_DIER_UIE}; @@ -117,7 +117,7 @@ static inline SHAL_TIM_DMA_Interrupt_Enable_Register getTimerDMAInterruptEnableR return res; } -static inline SHAL_TIM_Event_Generation_Register getTimerEventGenerationRegister(Timer_Key key){ +static SHAL_TIM_Event_Generation_Register getTimerEventGenerationRegister(Timer_Key key){ SHAL_TIM_Event_Generation_Register res = {nullptr, TIM_EGR_UG}; @@ -127,7 +127,7 @@ static inline SHAL_TIM_Event_Generation_Register getTimerEventGenerationRegister return res; } -static inline SHAL_TIM_Break_Dead_Time_Register getTimerBreakDeadTimeRegister(Timer_Key key) { +static SHAL_TIM_Break_Dead_Time_Register getTimerBreakDeadTimeRegister(Timer_Key key) { SHAL_TIM_Break_Dead_Time_Register res = {nullptr, TIM_BDTR_DTG_Pos, @@ -145,7 +145,7 @@ static inline SHAL_TIM_Break_Dead_Time_Register getTimerBreakDeadTimeRegister(Ti return res; } -static inline SHAL_TIM_Prescaler_Register getTimerPrescalerRegister(Timer_Key key){ +static SHAL_TIM_Prescaler_Register getTimerPrescalerRegister(Timer_Key key){ SHAL_TIM_Prescaler_Register res = {nullptr, 1UL << 15}; @@ -155,7 +155,7 @@ static inline SHAL_TIM_Prescaler_Register getTimerPrescalerRegister(Timer_Key ke return res; } -static inline SHAL_TIM_Auto_Reload_Register getTimerAutoReloadRegister(Timer_Key key){ +static SHAL_TIM_Auto_Reload_Register getTimerAutoReloadRegister(Timer_Key key){ SHAL_TIM_Auto_Reload_Register res = {nullptr, 1UL << 15}; @@ -165,8 +165,8 @@ static inline SHAL_TIM_Auto_Reload_Register getTimerAutoReloadRegister(Timer_Key return res; } -static inline SHAL_TIM_Capture_Compare_Register getTimerCaptureCompareRegister(Timer_Key key, SHAL_Timer_Channel channel){ - auto channel_num = static_cast(channel); +static SHAL_TIM_Capture_Compare_Register getTimerCaptureCompareRegister(Timer_Key key, SHAL_Timer_Channel channel){ + const auto channel_num = static_cast(channel); volatile TIM_TypeDef* tim = TIM_INFO_TABLE[static_cast(key)].timer; @@ -178,17 +178,18 @@ static inline SHAL_TIM_Capture_Compare_Register getTimerCaptureCompareRegister(T case SHAL_Timer_Channel::CH3: return {&tim->CCR3,0}; case SHAL_Timer_Channel::CH4: return {&tim->CCR4,0}; } + __builtin_unreachable(); + } -static inline SHAL_TIM_Capture_Compare_Enable_Register getTimerCaptureCompareEnableRegister(Timer_Key key, SHAL_Timer_Channel channel){ +static SHAL_TIM_Capture_Compare_Enable_Register getTimerCaptureCompareEnableRegister(Timer_Key key, SHAL_Timer_Channel channel){ + constexpr uint8_t channel_stride = 3; + const auto channel_num = static_cast(channel); - uint8_t channel_stride = 3; - auto channel_num = static_cast(channel); - - auto output_enable = TIM_CCER_CC1E << (channel_stride * (channel_num - 1)); - auto output_polarity = TIM_CCER_CC1P << (channel_stride * channel_num); - auto output_complimentary_enable = TIM_CCER_CC1NE << (channel_stride * channel_num); - auto output_complimentary_polarity = TIM_CCER_CC1NP << (channel_stride * channel_num); + const auto output_enable = TIM_CCER_CC1E << (channel_stride * (channel_num - 1)); + const auto output_polarity = TIM_CCER_CC1P << (channel_stride * channel_num); + const auto output_complimentary_enable = TIM_CCER_CC1NE << (channel_stride * channel_num); + const auto output_complimentary_polarity = TIM_CCER_CC1NP << (channel_stride * channel_num); SHAL_TIM_Capture_Compare_Enable_Register res = {nullptr, output_enable, @@ -203,7 +204,7 @@ static inline SHAL_TIM_Capture_Compare_Enable_Register getTimerCaptureCompareEna return res; } -static inline SHAL_TIM_Output_Capture_Compare_Mode_Register getTimerOutputCaptureCompareModeRegister(Timer_Key key, SHAL_Timer_Channel channel) { +static SHAL_TIM_Output_Capture_Compare_Mode_Register getTimerOutputCaptureCompareModeRegister(Timer_Key key, SHAL_Timer_Channel channel) { SHAL_TIM_Output_Capture_Compare_Mode_Register res = { nullptr, TIM_CCMR1_CC1S_Pos, //Channel 1 Capture/Compare selection @@ -219,11 +220,11 @@ static inline SHAL_TIM_Output_Capture_Compare_Mode_Register getTimerOutputCaptur }; volatile TIM_TypeDef* tim = TIM_INFO_TABLE[static_cast(key)].timer; - uint8_t num_tim_channels = TIM_INFO_TABLE[static_cast(key)].numChannels; + const uint8_t num_tim_channels = TIM_INFO_TABLE[static_cast(key)].numChannels; volatile uint32_t* reg = nullptr; - uint8_t channelNum = static_cast(channel); + const auto channelNum = static_cast(channel); assert(num_tim_channels >= channelNum); //Assert that we don't access undefined memory trying to initialize a non-existent channel diff --git a/SHAL/Include/Peripheral/Timer/SHAL_TIM.h b/SHAL/Include/Peripheral/Timer/SHAL_TIM.h index 76c18d6..79379ff 100644 --- a/SHAL/Include/Peripheral/Timer/SHAL_TIM.h +++ b/SHAL/Include/Peripheral/Timer/SHAL_TIM.h @@ -23,6 +23,17 @@ public: /// \param autoReload The number of timer counts before the count is reset and IRQ is called void init(uint16_t prescaler, uint16_t autoReload); + /// Simple function to set a timer in basic PWM mode + /// @param channel Channel to output on + /// @param prescaler Divider from sysclock + /// @param autoReload Counter value to reset at + /// @param captureCompareThreshold PWM trigger value (duty cycle = this / autoReload) + void configurePWM(SHAL_Timer_Channel channel, uint16_t prescaler, uint16_t autoReload, uint16_t captureCompareThreshold); + + + + void configureOneshot(SHAL_Timer_Channel channel, uint16_t prescaler, uint16_t autoReload, uint16_t captureCompareThreshold); + //Starts the counter void start(); @@ -30,10 +41,10 @@ public: void stop(); //Set prescaler value - void setPrescaler(uint16_t presc); + void setPrescaler(uint16_t presc) const; //Set auto reload register - void setARR(uint16_t arr); + void setARR(uint16_t arr) const; //Enable interrupts void enableInterrupt(); @@ -43,12 +54,8 @@ public: void enableChannel(SHAL_Timer_Channel channel, SHAL_Timer_Channel_Main_Output_Mode mainOutputMode, SHAL_Timer_Channel_Complimentary_Output_Mode complimentaryOutputMode); void setOutputCompareMode(SHAL_Timer_Channel channel, SHAL_TIM_Output_Compare_Mode outputCompareMode); - /// Set the duty cycle for PWM - /// \param dutyCycle 10 * percentage (e.g. 500 = 50%) - void setPWMDutyCycle(uint32_t dutyCycle); - //Set TIMER_KEY IRQ callback function - void setCallbackFunc(TimerCallback callback){ + void setCallbackFunc(TimerCallback callback) const { registerTimerCallback(m_key, callback); } diff --git a/SHAL/Src/STM32F0xx/Core/SHAL_CORE.cpp b/SHAL/Src/STM32F0xx/Core/SHAL_CORE.cpp index 8f46a8f..d625dfb 100644 --- a/SHAL/Src/STM32F0xx/Core/SHAL_CORE.cpp +++ b/SHAL/Src/STM32F0xx/Core/SHAL_CORE.cpp @@ -16,6 +16,13 @@ void systick_init(){ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk; } +extern "C" void SysTick_Handler() { + ticks++; +} + +static uint32_t millis(); + + void SHAL_delay_us(uint32_t us){ uint32_t ticks = us * (SystemCoreClock / 1000000U); diff --git a/SHAL/Src/STM32F0xx/Peripheral/Timer/SHAL_TIM.cpp b/SHAL/Src/STM32F0xx/Peripheral/Timer/SHAL_TIM.cpp index 567c638..618ac48 100644 --- a/SHAL/Src/STM32F0xx/Peripheral/Timer/SHAL_TIM.cpp +++ b/SHAL/Src/STM32F0xx/Peripheral/Timer/SHAL_TIM.cpp @@ -40,13 +40,16 @@ void Timer::stop() { SHAL_clear_bitmask(rcc_reg.reg,rcc_reg.enable_mask); } -void Timer::setPrescaler(uint16_t presc) { - getTimerRegister(m_key)->PSC = presc; +void Timer::setPrescaler(const uint16_t presc) const { + auto prescalerReg = getTimerPrescalerRegister(m_key); + + SHAL_set_bits(prescalerReg.reg,16,presc,0); } -void Timer::setARR(uint16_t arr) { - getTimerRegister(m_key)->ARR = arr; -} +void Timer::setARR(const uint16_t arr) const { + auto autoReloadReg = getTimerAutoReloadRegister(m_key); + + SHAL_set_bits(autoReloadReg.reg,16,arr,0);} void Timer::enableInterrupt() { getTimerRegister(m_key)->DIER |= TIM_DIER_UIE; @@ -62,6 +65,28 @@ void Timer::init(uint16_t prescaler, uint16_t autoReload) { setARR(autoReload); } +void Timer::configurePWM(SHAL_Timer_Channel channel, uint16_t prescaler, uint16_t autoReload, uint16_t captureCompareThreshold) { + + setPrescaler(prescaler); + setARR(autoReload); + + setOutputCompareMode(channel, SHAL_TIM_Output_Compare_Mode::PWMMode1); + enableChannel(channel,SHAL_Timer_Channel_Main_Output_Mode::Polarity_Normal,SHAL_Timer_Channel_Complimentary_Output_Mode::Disabled); + + setCaptureCompareValue(channel, captureCompareThreshold); +} + +void Timer::configureOneshot(SHAL_Timer_Channel channel, uint16_t prescaler, uint16_t autoReload, uint16_t captureCompareThreshold) { + + setPrescaler(prescaler); + setARR(autoReload); + + setOutputCompareMode(channel, SHAL_TIM_Output_Compare_Mode::Toggle); + enableChannel(channel,SHAL_Timer_Channel_Main_Output_Mode::Polarity_Normal,SHAL_Timer_Channel_Complimentary_Output_Mode::Disabled); + + setCaptureCompareValue(channel, captureCompareThreshold); +} + void Timer::setOutputCompareMode(SHAL_Timer_Channel channel, SHAL_TIM_Output_Compare_Mode outputCompareMode) { auto channelNum = static_cast(channel); diff --git a/SHAL/Src/main.cpp b/SHAL/Src/main.cpp index 58c9e98..792ea88 100644 --- a/SHAL/Src/main.cpp +++ b/SHAL/Src/main.cpp @@ -1,6 +1,26 @@ #include #include "SHAL.h" +#define SER PIN(B10) +#define RCLK PIN(B9) +#define SRCLK PIN(B8) + +void scanOutputs(uint8_t num_outputs) { + + for (size_t i = 0; i < num_outputs + 1; i++) { + if (i == 0) { + SER.setHigh(); + } + else { + SER.setLow(); + } + RCLK.setHigh(); + SRCLK.setHigh(); + RCLK.setLow(); + SRCLK.setLow(); + } +} + int main() { SHAL_init(); @@ -9,11 +29,41 @@ int main() { PIN(A8).setAlternateFunction(GPIO_Alternate_Function::AF2); - RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; + RCC->AHBENR |= RCC_AHBENR_GPIOAEN; + + SER.setPinMode(PinMode::OUTPUT_MODE); + RCLK.setPinMode(PinMode::OUTPUT_MODE); + SRCLK.setPinMode(PinMode::OUTPUT_MODE); SHAL_TIM1.init(48,100); - SHAL_TIM1.setOutputCompareMode(SHAL_Timer_Channel::CH1,SHAL_TIM_Output_Compare_Mode::PWMMode1); - SHAL_TIM1.enableChannel(SHAL_Timer_Channel::CH1,SHAL_Timer_Channel_Main_Output_Mode::Polarity_Reversed,SHAL_Timer_Channel_Complimentary_Output_Mode::Disabled); - SHAL_TIM1.setCaptureCompareValue(SHAL_Timer_Channel::CH1, 5); + SHAL_TIM1.configurePWM(SHAL_Timer_Channel::CH1, 4800, 100, 20); SHAL_TIM1.start(); + + SER.setLow(); + RCLK.setLow(); + SRCLK.setLow(); + + uint8_t numDisplays = 6; + uint8_t count = 0; + + while (true) { + + if (count == 0) { + SER.setLow(); + } + else { + SER.setHigh(); + } + + count++; + + RCLK.setHigh(); + SRCLK.setHigh(); + RCLK.setLow(); + SRCLK.setLow(); + if (count == numDisplays) { + count = 0; + } + SHAL_delay_us(50); + } }