Timer test
This commit is contained in:
@@ -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>
|
||||||
|
|||||||
@@ -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) { \
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user