Timer test

This commit is contained in:
Ea-r-th
2026-03-11 00:31:40 -07:00
parent 43bdee4406
commit 5b0819a300
7 changed files with 134 additions and 36 deletions

View File

@@ -82,6 +82,7 @@ ${CPU_PARAMETERS}
-Wextra -Wextra
-Wpedantic -Wpedantic
-Wno-unused-parameter -Wno-unused-parameter
-Wno-unused-function
$<$<COMPILE_LANGUAGE:CXX>: $<$<COMPILE_LANGUAGE:CXX>:
-Wno-volatile -Wno-volatile
-Wsuggest-override> -Wsuggest-override>

View File

@@ -42,8 +42,13 @@ enum class SHAL_Result{
//Currently configures systick to count down in microseconds //Currently configures systick to count down in microseconds
inline uint32_t ticks = 0;
void systick_init(); void systick_init();
extern "C" void SysTick_Handler();
static uint32_t millis();
//Max of 16ms, use SHAL_delay_ms for longer delay //Max of 16ms, use SHAL_delay_ms for longer delay
void SHAL_delay_us(uint32_t us); 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 return false; // timeout
} }
#define SHAL_set_bits(reg, size, bits, offset) \ #define SHAL_set_bits(reg, size, bits, offset) \
do { \ do { \
if ((reg) != NULL) { \ if ((reg) != NULL) { \

View File

@@ -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}; 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; 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, SHAL_TIM_Control_Register_1 res = {nullptr, TIM_CR1_CEN_Msk,
TIM_CR1_UDIS, TIM_CR1_UDIS,
@@ -107,7 +107,7 @@ static inline SHAL_TIM_Control_Register_1 getTimerControlRegister1(Timer_Key key
return res; 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}; 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; 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}; SHAL_TIM_Event_Generation_Register res = {nullptr, TIM_EGR_UG};
@@ -127,7 +127,7 @@ static inline SHAL_TIM_Event_Generation_Register getTimerEventGenerationRegister
return res; 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, SHAL_TIM_Break_Dead_Time_Register res = {nullptr,
TIM_BDTR_DTG_Pos, TIM_BDTR_DTG_Pos,
@@ -145,7 +145,7 @@ static inline SHAL_TIM_Break_Dead_Time_Register getTimerBreakDeadTimeRegister(Ti
return res; 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}; SHAL_TIM_Prescaler_Register res = {nullptr, 1UL << 15};
@@ -155,7 +155,7 @@ static inline SHAL_TIM_Prescaler_Register getTimerPrescalerRegister(Timer_Key ke
return res; 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}; 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; return res;
} }
static inline SHAL_TIM_Capture_Compare_Register getTimerCaptureCompareRegister(Timer_Key key, SHAL_Timer_Channel channel){ static SHAL_TIM_Capture_Compare_Register getTimerCaptureCompareRegister(Timer_Key key, SHAL_Timer_Channel channel){
auto channel_num = static_cast<uint8_t>(channel); const auto channel_num = static_cast<uint8_t>(channel);
volatile TIM_TypeDef* tim = TIM_INFO_TABLE[static_cast<uint8_t>(key)].timer; volatile TIM_TypeDef* tim = TIM_INFO_TABLE[static_cast<uint8_t>(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::CH3: return {&tim->CCR3,0};
case SHAL_Timer_Channel::CH4: return {&tim->CCR4,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<uint8_t>(channel);
uint8_t channel_stride = 3; const auto output_enable = TIM_CCER_CC1E << (channel_stride * (channel_num - 1));
auto channel_num = static_cast<uint8_t>(channel); const auto output_polarity = TIM_CCER_CC1P << (channel_stride * channel_num);
const auto output_complimentary_enable = TIM_CCER_CC1NE << (channel_stride * channel_num);
auto output_enable = TIM_CCER_CC1E << (channel_stride * (channel_num - 1)); const auto output_complimentary_polarity = TIM_CCER_CC1NP << (channel_stride * channel_num);
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);
SHAL_TIM_Capture_Compare_Enable_Register res = {nullptr, SHAL_TIM_Capture_Compare_Enable_Register res = {nullptr,
output_enable, output_enable,
@@ -203,7 +204,7 @@ static inline SHAL_TIM_Capture_Compare_Enable_Register getTimerCaptureCompareEna
return res; 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 = { SHAL_TIM_Output_Capture_Compare_Mode_Register res = {
nullptr, nullptr,
TIM_CCMR1_CC1S_Pos, //Channel 1 Capture/Compare selection 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<uint8_t>(key)].timer; volatile TIM_TypeDef* tim = TIM_INFO_TABLE[static_cast<uint8_t>(key)].timer;
uint8_t num_tim_channels = TIM_INFO_TABLE[static_cast<uint8_t>(key)].numChannels; const uint8_t num_tim_channels = TIM_INFO_TABLE[static_cast<uint8_t>(key)].numChannels;
volatile uint32_t* reg = nullptr; volatile uint32_t* reg = nullptr;
uint8_t channelNum = static_cast<uint32_t>(channel); const auto channelNum = static_cast<uint32_t>(channel);
assert(num_tim_channels >= channelNum); //Assert that we don't access undefined memory trying to initialize a non-existent channel assert(num_tim_channels >= channelNum); //Assert that we don't access undefined memory trying to initialize a non-existent channel

View File

@@ -23,6 +23,17 @@ public:
/// \param autoReload The number of timer counts before the count is reset and IRQ is called /// \param autoReload The number of timer counts before the count is reset and IRQ is called
void init(uint16_t prescaler, uint16_t autoReload); 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 //Starts the counter
void start(); void start();
@@ -30,10 +41,10 @@ public:
void stop(); void stop();
//Set prescaler value //Set prescaler value
void setPrescaler(uint16_t presc); void setPrescaler(uint16_t presc) const;
//Set auto reload register //Set auto reload register
void setARR(uint16_t arr); void setARR(uint16_t arr) const;
//Enable interrupts //Enable interrupts
void enableInterrupt(); 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 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); 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 //Set TIMER_KEY IRQ callback function
void setCallbackFunc(TimerCallback callback){ void setCallbackFunc(TimerCallback callback) const {
registerTimerCallback(m_key, callback); registerTimerCallback(m_key, callback);
} }

View File

@@ -16,6 +16,13 @@ void systick_init(){
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk; 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){ void SHAL_delay_us(uint32_t us){
uint32_t ticks = us * (SystemCoreClock / 1000000U); uint32_t ticks = us * (SystemCoreClock / 1000000U);

View File

@@ -40,13 +40,16 @@ void Timer::stop() {
SHAL_clear_bitmask(rcc_reg.reg,rcc_reg.enable_mask); SHAL_clear_bitmask(rcc_reg.reg,rcc_reg.enable_mask);
} }
void Timer::setPrescaler(uint16_t presc) { void Timer::setPrescaler(const uint16_t presc) const {
getTimerRegister(m_key)->PSC = presc; auto prescalerReg = getTimerPrescalerRegister(m_key);
SHAL_set_bits(prescalerReg.reg,16,presc,0);
} }
void Timer::setARR(uint16_t arr) { void Timer::setARR(const uint16_t arr) const {
getTimerRegister(m_key)->ARR = arr; auto autoReloadReg = getTimerAutoReloadRegister(m_key);
}
SHAL_set_bits(autoReloadReg.reg,16,arr,0);}
void Timer::enableInterrupt() { void Timer::enableInterrupt() {
getTimerRegister(m_key)->DIER |= TIM_DIER_UIE; getTimerRegister(m_key)->DIER |= TIM_DIER_UIE;
@@ -62,6 +65,28 @@ void Timer::init(uint16_t prescaler, uint16_t autoReload) {
setARR(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) { void Timer::setOutputCompareMode(SHAL_Timer_Channel channel, SHAL_TIM_Output_Compare_Mode outputCompareMode) {
auto channelNum = static_cast<uint8_t>(channel); auto channelNum = static_cast<uint8_t>(channel);

View File

@@ -1,6 +1,26 @@
#include <cstdio> #include <cstdio>
#include "SHAL.h" #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() { int main() {
SHAL_init(); SHAL_init();
@@ -9,11 +29,41 @@ int main() {
PIN(A8).setAlternateFunction(GPIO_Alternate_Function::AF2); 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.init(48,100);
SHAL_TIM1.setOutputCompareMode(SHAL_Timer_Channel::CH1,SHAL_TIM_Output_Compare_Mode::PWMMode1); SHAL_TIM1.configurePWM(SHAL_Timer_Channel::CH1, 4800, 100, 20);
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.start(); 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);
}
} }