Validate basic use case for tim 2 to 4

tim 2, 3 and 4 work as expected in continuous upcounting with IRQ. tim 1
doesn't seem to work at all (no IRQ), though the issue as not be found
yet
This commit is contained in:
Steins7 2024-08-28 23:11:18 +02:00
parent d7da7618e3
commit edb59d7e6b
2 changed files with 214 additions and 9 deletions

196
drv/tim.c
View File

@ -6,13 +6,209 @@
#include "tim.h"
#include "tim_regs.h"
#include "nvic.h"
#include "../srv/error.h"
//--local definitions-----------------------------------------------------------
static volatile struct TIM* regs[] = {
(struct TIM*)TIM1_BASE_ADDRESS,
(struct TIM*)TIM2_BASE_ADDRESS,
(struct TIM*)TIM3_BASE_ADDRESS,
(struct TIM*)TIM4_BASE_ADDRESS,
};
static enum TimIRQSource computeIRQSource(enum TimPeriph periph);
//--local variables-------------------------------------------------------------
static TimCallback callbacks[4];
//--public functions------------------------------------------------------------
void tim_configure_master(enum TimPeriph periph, enum TimConfig config_mask,
enum TimMasterConfig master_config_mask, TimCallback callback)
{
error_assert(periph <= TIM_PERIPH_4);
//apply config mask directly while masking reserved areas. Masking is
//important here since advanced timer may have additionnal config bits
regs[periph]->cr1.word |= config_mask & 0x3FF;
regs[periph]->cr2.word |= (config_mask >> 16) & 0x88;
regs[periph]->cr2.word |= master_config_mask & 0x70;
//if callback specified, configure IRQ
if (callback != nullptr) {
callbacks[periph] = callback;
regs[periph]->dier.TIE = 1;
regs[periph]->dier.UIE = 1;
enum NvicIrq irq = 0;
switch (periph) {
case TIM_PERIPH_1:
irq = NVIC_IRQ_TIM1_BRK | NVIC_IRQ_TIM1_UP
| NVIC_IRQ_TIM1_TRG_COM | NVIC_IRQ_TIM1_CC;
break;
case TIM_PERIPH_2:
irq = NVIC_IRQ_TIM2;
break;
case TIM_PERIPH_3:
irq = NVIC_IRQ_TIM3;
break;
case TIM_PERIPH_4:
irq = NVIC_IRQ_TIM4;
break;
}
nvic_enable(irq);
}
//trigger update to force application of the config
regs[periph]->egr.UG = 1;
}
void tim_start(enum TimPeriph periph)
{
error_assert(periph <= TIM_PERIPH_4);
regs[periph]->cr1.CEN = 1;
}
void tim_stop(enum TimPeriph periph)
{
error_assert(periph <= TIM_PERIPH_4);
regs[periph]->cr1.CEN = 0;
}
void tim_update(enum TimPeriph periph)
{
error_assert(periph <= TIM_PERIPH_4);
regs[periph]->egr.UG = 1;
}
void tim_set_auto_reload(enum TimPeriph periph, uint16_t auto_reload)
{
error_assert(periph <= TIM_PERIPH_4);
regs[periph]->arr.ARR = auto_reload;
}
void tim_set_prescaler(enum TimPeriph periph, uint16_t prescaler)
{
error_assert(periph <= TIM_PERIPH_4);
regs[periph]->psc.PSC = prescaler;
}
void tim_set_counter(enum TimPeriph periph, uint16_t counter)
{
error_assert(periph <= TIM_PERIPH_4);
regs[periph]->cnt.CNT = counter;
}
uint16_t tim_get_auto_reload(enum TimPeriph periph)
{
error_assert(periph <= TIM_PERIPH_4);
return regs[periph]->arr.ARR;
}
uint16_t tim_get_prescaler(enum TimPeriph periph)
{
error_assert(periph <= TIM_PERIPH_4);
return regs[periph]->psc.PSC;
}
uint16_t tim_get_counter(enum TimPeriph periph)
{
error_assert(periph <= TIM_PERIPH_4);
return regs[periph]->cnt.CNT;
}
//--local functions-------------------------------------------------------------
static enum TimIRQSource computeIRQSource(enum TimPeriph periph)
{
enum TimIRQSource src =
(TIM_IRQ_SOURCE_TRIGGER & regs[periph]->sr.TIF)
| (TIM_IRQ_SOURCE_UPDATE & regs[periph]->sr.UIF);
regs[periph]->sr.TIF = 0;
regs[periph]->sr.UIF = 0;
return src;
}
//--ISRs------------------------------------------------------------------------
void hdr_tim1_brk(void)
{
nvic_clear_pending(NVIC_IRQ_TIM1_BRK);
enum TimIRQSource src = computeIRQSource(TIM_PERIPH_1);
if (callbacks[TIM_PERIPH_1] != nullptr) {
callbacks[TIM_PERIPH_1](src);
}
}
void hdr_tim1_up(void)
{
nvic_clear_pending(NVIC_IRQ_TIM1_UP);
enum TimIRQSource src = computeIRQSource(TIM_PERIPH_1);
if (callbacks[TIM_PERIPH_1] != nullptr) {
callbacks[TIM_PERIPH_1](src);
}
}
void hdr_tim1_trg_com(void)
{
nvic_clear_pending(NVIC_IRQ_TIM1_TRG_COM);
enum TimIRQSource src = computeIRQSource(TIM_PERIPH_1);
if (callbacks[TIM_PERIPH_1] != nullptr) {
callbacks[TIM_PERIPH_1](src);
}
}
void hdr_tim1_cc(void)
{
nvic_clear_pending(NVIC_IRQ_TIM1_CC);
enum TimIRQSource src = computeIRQSource(TIM_PERIPH_1);
if (callbacks[TIM_PERIPH_1] != nullptr) {
callbacks[TIM_PERIPH_1](src);
}
}
void hdr_tim2(void)
{
nvic_clear_pending(NVIC_IRQ_TIM2);
enum TimIRQSource src = computeIRQSource(TIM_PERIPH_2);
callbacks[TIM_PERIPH_2](src);
}
void hdr_tim3(void)
{
nvic_clear_pending(NVIC_IRQ_TIM3);
enum TimIRQSource src = computeIRQSource(TIM_PERIPH_3);
callbacks[TIM_PERIPH_3](src);
}
void hdr_tim4(void)
{
nvic_clear_pending(NVIC_IRQ_TIM4);
enum TimIRQSource src = computeIRQSource(TIM_PERIPH_4);
callbacks[TIM_PERIPH_4](src);
}

View File

@ -46,14 +46,14 @@ enum TimConfig {
};
enum TimMasterConfig {
TIM_MASTER_CONFIG_MODE_RESET = (0x0 << 20),
TIM_MASTER_CONFIG_MODE_ENABLE = (0x1 << 20),
TIM_MASTER_CONFIG_MODE_UPDATE = (0x2 << 20),
TIM_MASTER_CONFIG_MODE_COMP_PULSE = (0x3 << 20),
TIM_MASTER_CONFIG_MODE_COMP_1 = (0x4 << 20),
TIM_MASTER_CONFIG_MODE_COMP_2 = (0x5 << 20),
TIM_MASTER_CONFIG_MODE_COMP_3 = (0x6 << 20),
TIM_MASTER_CONFIG_MODE_COMP_4 = (0x7 << 20),
TIM_MASTER_CONFIG_MODE_RESET = (0x0 << 4),
TIM_MASTER_CONFIG_MODE_ENABLE = (0x1 << 4),
TIM_MASTER_CONFIG_MODE_UPDATE = (0x2 << 4),
TIM_MASTER_CONFIG_MODE_COMP_PULSE = (0x3 << 4),
TIM_MASTER_CONFIG_MODE_COMP_1 = (0x4 << 4),
TIM_MASTER_CONFIG_MODE_COMP_2 = (0x5 << 4),
TIM_MASTER_CONFIG_MODE_COMP_3 = (0x6 << 4),
TIM_MASTER_CONFIG_MODE_COMP_4 = (0x7 << 4),
};
@ -122,7 +122,12 @@ enum TimIntputConfig {
TIM_INPUT_CONFIG_PRESCALER_8 = (0x3 << 2),
};
typedef void (*TimCallback)(void);
enum TimIRQSource {
TIM_IRQ_SOURCE_TRIGGER,
TIM_IRQ_SOURCE_UPDATE,
};
typedef void (*TimCallback)(enum TimIRQSource src);
//--functions-------------------------------------------------------------------
@ -133,6 +138,10 @@ void tim_configure_master(enum TimPeriph periph, enum TimConfig config_mask,
void tim_configure_slave(enum TimPeriph periph, enum TimConfig config_mask,
enum TimSlaveConfig slave_config_mask, TimCallback callback);
void tim_start(enum TimPeriph periph);
void tim_stop(enum TimPeriph periph);
void tim_update(enum TimPeriph periph);
void tim_set_auto_reload(enum TimPeriph periph, uint16_t auto_reload);
void tim_set_prescaler(enum TimPeriph periph, uint16_t prescaler);
void tim_set_counter(enum TimPeriph periph, uint16_t counter);