Compare commits
3 Commits
93f1b5a992
...
edb59d7e6b
| Author | SHA1 | Date | |
|---|---|---|---|
| edb59d7e6b | |||
| d7da7618e3 | |||
| 3cbc836fe5 |
214
drv/tim.c
Normal file
214
drv/tim.c
Normal file
@ -0,0 +1,214 @@
|
||||
/** @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 = 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);
|
||||
}
|
||||
|
||||
163
drv/tim.h
Normal file
163
drv/tim.h
Normal file
@ -0,0 +1,163 @@
|
||||
/** @file tim.h
|
||||
* Module handling general purpose and advances TIMers
|
||||
*/
|
||||
|
||||
#ifndef _TIM_H_
|
||||
#define _TIM_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
enum TimPeriph {
|
||||
TIM_PERIPH_1,
|
||||
TIM_PERIPH_2,
|
||||
TIM_PERIPH_3,
|
||||
TIM_PERIPH_4,
|
||||
};
|
||||
|
||||
enum TimChannel {
|
||||
TIM_CHANNEL_1,
|
||||
TIM_CHANNEL_2,
|
||||
TIM_CHANNEL_3,
|
||||
TIM_CHANNEL_4,
|
||||
};
|
||||
|
||||
enum TimConfig {
|
||||
TIM_CONFIG_DISABLE_UPDATES = (0x1 << 1),
|
||||
TIM_CONFIG_LIMIT_UPDATE_SRC = (0x1 << 2),
|
||||
TIM_CONFIG_CONTINUOUS = (0x0 << 3),
|
||||
TIM_CONFIG_ONE_SHOT = (0x1 << 3),
|
||||
TIM_CONFIG_DIR_UP = (0x0 << 4),
|
||||
TIM_CONFIG_DIR_DOWN = (0x1 << 4),
|
||||
TIM_CONFIG_CENTER_ALIGNED_1 = (0x1 << 5),
|
||||
TIM_CONFIG_CENTER_ALIGNED_2 = (0x2 << 5),
|
||||
TIM_CONFIG_CENTER_ALIGNED_3 = (0x3 << 5),
|
||||
TIM_CONFIG_BUFFERED_ARR = (0x1 << 7),
|
||||
TIM_CONFIG_FILTER_CLOCK_DIV_1 = (0x0 << 8),
|
||||
TIM_CONFIG_FILTER_CLOCK_DIV_2 = (0x1 << 8),
|
||||
TIM_CONFIG_FILTER_CLOCK_DIV_4 = (0x2 << 8),
|
||||
TIM_CONFIG_DMA_ON_CC_EVENT = (0x0 << 19),
|
||||
TIM_CONFIG_DMA_ON_UPDATE = (0x1 << 19),
|
||||
TIM_CONFIG_XOR_TI1 = (0x1 << 23),
|
||||
};
|
||||
|
||||
enum TimMasterConfig {
|
||||
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),
|
||||
|
||||
};
|
||||
|
||||
enum TimSlaveConfig {
|
||||
TIM_SLAVE_CONFIG_MODE_ENCODER_1 = (0x1 << 0),
|
||||
TIM_SLAVE_CONFIG_MODE_ENCODER_2 = (0x2 << 0),
|
||||
TIM_SLAVE_CONFIG_MODE_ENCODER_3 = (0x3 << 0),
|
||||
TIM_SLAVE_CONFIG_MODE_RESET = (0x4 << 0),
|
||||
TIM_SLAVE_CONFIG_MODE_GATED = (0x5 << 0),
|
||||
TIM_SLAVE_CONFIG_MODE_TRIGGER = (0x6 << 0),
|
||||
TIM_SLAVE_CONFIG_MODE_EXT_CLK = (0x7 << 0),
|
||||
TIM_SLAVE_CONFIG_TRIG_INTERNAL_1 = (0x0 << 4),
|
||||
TIM_SLAVE_CONFIG_TRIG_INTERNAL_2 = (0x1 << 4),
|
||||
TIM_SLAVE_CONFIG_TRIG_INTERNAL_3 = (0x2 << 4),
|
||||
TIM_SLAVE_CONFIG_TRIG_INTERNAL_4 = (0x3 << 4),
|
||||
TIM_SLAVE_CONFIG_TRIG_EDGE_DETECT = (0x4 << 4),
|
||||
TIM_SLAVE_CONFIG_TRIG_FILTERED_1 = (0x5 << 4),
|
||||
TIM_SLAVE_CONFIG_TRIG_FILTERED_2 = (0x6 << 4),
|
||||
TIM_SLAVE_CONFIG_TRIG_EXT = (0x7 << 4),
|
||||
};
|
||||
|
||||
enum TimExtConfig {
|
||||
TIM_EXT_CONFIG_FILTER_1 = (0x1 << 8),
|
||||
TIM_EXT_CONFIG_FILTER_2 = (0x2 << 8),
|
||||
TIM_EXT_CONFIG_FILTER_3 = (0x3 << 8),
|
||||
TIM_EXT_CONFIG_FILTER_4 = (0x4 << 8),
|
||||
TIM_EXT_CONFIG_FILTER_5 = (0x5 << 8),
|
||||
TIM_EXT_CONFIG_FILTER_6 = (0x6 << 8),
|
||||
TIM_EXT_CONFIG_FILTER_7 = (0x7 << 8),
|
||||
TIM_EXT_CONFIG_FILTER_8 = (0x8 << 8),
|
||||
TIM_EXT_CONFIG_FILTER_9 = (0x9 << 8),
|
||||
TIM_EXT_CONFIG_FILTER_10 = (0xA << 8),
|
||||
TIM_EXT_CONFIG_FILTER_11 = (0xB << 8),
|
||||
TIM_EXT_CONFIG_FILTER_12 = (0xC << 8),
|
||||
TIM_EXT_CONFIG_FILTER_13 = (0xD << 8),
|
||||
TIM_EXT_CONFIG_FILTER_14 = (0xE << 8),
|
||||
TIM_EXT_CONFIG_FILTER_15 = (0xF << 8),
|
||||
TIM_EXT_CONFIG_PRESCALER_DIV_1 = (0x0 << 12),
|
||||
TIM_EXT_CONFIG_PRESCALER_DIV_2 = (0x1 << 12),
|
||||
TIM_EXT_CONFIG_PRESCALER_DIV_4 = (0x2 << 12),
|
||||
TIM_EXT_CONFIG_PRESCALER_DIV_8 = (0x3 << 12),
|
||||
TIM_EXT_CONFIG_USE_AS_CLK = (0x3 << 14),
|
||||
TIM_EXT_CONFIG_INVERT = (0x3 << 15),
|
||||
};
|
||||
|
||||
enum TimOutputConfig {
|
||||
TIM_OUTPUT_CONFIG_FAST_MODE = (0x1 << 2),
|
||||
TIM_OUTPUT_CONFIG_PRELOAD_EN = (0x1 << 3),
|
||||
TIM_OUTPUT_CONFIG_MODE_FROZEN = (0x0 << 4),
|
||||
TIM_OUTPUT_CONFIG_MODE_ACTIVE = (0x1 << 4),
|
||||
TIM_OUTPUT_CONFIG_MODE_INACTIVE = (0x2 << 4),
|
||||
TIM_OUTPUT_CONFIG_MODE_TOGGLE = (0x3 << 4),
|
||||
TIM_OUTPUT_CONFIG_MODE_FORCE_ACTIVE = (0x4 << 4),
|
||||
TIM_OUTPUT_CONFIG_MODE_FORCE_INACTIVE = (0x5 << 4),
|
||||
TIM_OUTPUT_CONFIG_MODE_PWM_1 = (0x6 << 4),
|
||||
TIM_OUTPUT_CONFIG_MODE_PWM_2 = (0x7 << 4),
|
||||
TIM_OUTPUT_CONFIG_CLEAR_ON_EXT_TRIG = (0x1 << 7),
|
||||
};
|
||||
|
||||
enum TimIntputConfig {
|
||||
TIM_INPUT_CONFIG_ALTERNATE_TRIGGER = (0x2 << 0),
|
||||
TIM_INPUT_CONFIG_INTERNAL_TRIGGER = (0x3 << 0),
|
||||
TIM_INPUT_CONFIG_PRESCALER_1 = (0x0 << 2),
|
||||
TIM_INPUT_CONFIG_PRESCALER_2 = (0x1 << 2),
|
||||
TIM_INPUT_CONFIG_PRESCALER_4 = (0x2 << 2),
|
||||
TIM_INPUT_CONFIG_PRESCALER_8 = (0x3 << 2),
|
||||
};
|
||||
|
||||
enum TimIRQSource {
|
||||
TIM_IRQ_SOURCE_TRIGGER,
|
||||
TIM_IRQ_SOURCE_UPDATE,
|
||||
};
|
||||
|
||||
typedef void (*TimCallback)(enum TimIRQSource src);
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
|
||||
void tim_configure_master(enum TimPeriph periph, enum TimConfig config_mask,
|
||||
enum TimMasterConfig master_config_mask, TimCallback callback);
|
||||
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);
|
||||
|
||||
uint16_t tim_get_auto_reload(enum TimPeriph periph);
|
||||
uint16_t tim_get_prescaler(enum TimPeriph periph);
|
||||
uint16_t tim_get_counter(enum TimPeriph periph);
|
||||
|
||||
void tim_configure_output_channel(enum TimPeriph periph,
|
||||
enum TimChannel channel_mask, enum TimOutputConfig config_mask,
|
||||
uint16_t value);
|
||||
void tim_configure_input_channel(enum TimPeriph periph,
|
||||
enum TimChannel channel_mask, enum TimInputConfig config_mask,
|
||||
uint16_t value);
|
||||
void tim_configure_ext_trigger(enum TimPeriph periph,
|
||||
enum TimExtConfig ext_config_mask);
|
||||
|
||||
#endif //_TIM_H_
|
||||
|
||||
Loading…
Reference in New Issue
Block a user