184 lines
4.0 KiB
C
184 lines
4.0 KiB
C
/** @file tim.c
|
|
* Module handling general purpose and advances TIMers
|
|
*/
|
|
|
|
//--includes--------------------------------------------------------------------
|
|
|
|
#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 = 0;
|
|
|
|
enum NvicIrq irq = 0;
|
|
switch (periph) {
|
|
case TIM_PERIPH_1:
|
|
irq = NVIC_IRQ_TIM1_UP;
|
|
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;
|
|
while (regs[periph]->sr.UIF == 0) {}
|
|
regs[periph]->sr.UIF = 0;
|
|
|
|
if (callback != nullptr) {
|
|
regs[periph]->dier.UIE = 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_up(void)
|
|
{
|
|
nvic_clear_pending(NVIC_IRQ_TIM1_UP);
|
|
|
|
enum TimIRQSource src = computeIRQSource(TIM_PERIPH_1);
|
|
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);
|
|
}
|
|
|