diff --git a/drv/bkp.c b/drv/bkp.c index 69630b9..802af59 100644 --- a/drv/bkp.c +++ b/drv/bkp.c @@ -18,12 +18,14 @@ //--local definitions----------------------------------------------------------- -uint32_t compute_prescaler(uint32_t period_ms, enum BkpRtcClockSrc clock_src); +static uint32_t compute_prescaler(uint32_t period_ms, + enum BkpRtcClockSrc clock_src); +static void lsi_calib_callback(enum TimIRQSource src); //--local variables------------------------------------------------------------- -//static volatile struct BKP* bkp_regs = (struct BKP*)BKP_BASE_ADDRESS; +static volatile struct BKP* bkp_regs = (struct BKP*)BKP_BASE_ADDRESS; static volatile struct RCC* rcc_regs = (struct RCC*)RCC_BASE_ADDRESS; static volatile struct RTC* rtc_regs = (struct RTC*)RTC_BASE_ADDRESS; @@ -103,12 +105,62 @@ uint32_t bkp_read_rtc(void) return time; } +uint32_t bkp_read_rtc_div(void) +{ + //wait for core registers to be synchronized, immediate most of the time + while (rtc_regs->CRL.RSF != 1) {} + + uint32_t div = rtc_regs->DIVH.RTC_DIV << 16; + div |= rtc_regs->DIVL.RTC_DIV << 0; + + return div; +} + void bkp_reset(void) { rcc_regs->BDCR.BDRST = 1; rcc_regs->BDCR.BDRST = 0; } +void bkp_write_data(enum BkpData data_index, uint16_t data) +{ + bkp_regs->DR[data_index].D = data; +} + +uint16_t bkp_read_data(enum BkpData data_index) +{ + return bkp_regs->DR[data_index].D; +} + +void bkp_calibrate_lsi(enum TimPeriph timer) +{ + rcc_enable(RCC_AHB_NONE, RCC_APB1_BKP, RCC_APB2_NONE); + + //do not calibrate if already calibrated + if (bkp_read_data(BKP_DATA_LSI_CALIB) != 0) { + return; + } + + //configure timer to count 1s exactly + struct RccClocks clocks; + rcc_get_clocks(&clocks); + + tim_set_prescaler(timer, (clocks.tim_freq / 10000)); //10000 to avoid + //prescaler overflow + tim_set_auto_reload(timer, 10000); + tim_configure_master(timer, TIM_CONFIG_ONE_SHOT + | TIM_CONFIG_DIR_UP, TIM_MASTER_CONFIG_MODE_RESET, + lsi_calib_callback); + + //configure rtc to tick every 2s so the div value isn't reset during the + //timer's delay if the clock is too fast + bkp_configure_rtc(2000, BKP_RTC_CLOCK_SRC_LSI, BKP_RTC_IRQ_NONE, nullptr); + tim_start(timer); + + while (bkp_read_data(BKP_DATA_LSI_CALIB) == 0) {} + + //TODO reset timer +} //--local functions------------------------------------------------------------- @@ -116,25 +168,43 @@ void bkp_reset(void) * Computes the prescaler value based on the clock source and the required * period */ -uint32_t compute_prescaler(uint32_t period_ms, enum BkpRtcClockSrc clock_src) +static uint32_t compute_prescaler(uint32_t period_ms, + enum BkpRtcClockSrc clock_src) { uint32_t prescaler; switch (clock_src) { case BKP_RTC_CLOCK_SRC_LSE: - prescaler = 32768000; //32.768kHz + prescaler = 32768; //32.768kHz break; case BKP_RTC_CLOCK_SRC_LSI: - prescaler = 40000000; //40khz + prescaler = bkp_read_data(BKP_DATA_LSI_CALIB); + if (prescaler == 0) { + prescaler = 40000; //40khz + } break; case BKP_RTC_CLOCK_SRC_HSE: - prescaler = 62500000; //8Mhz / 128 + prescaler = 62500; //8Mhz / 128 break; default: return 0; } - return prescaler / period_ms; + return (period_ms * prescaler) / 1000; +} + +/** + * LSI callibration callback. Measures the LSI deviation from its theorical + * frequency using the RTC and stores the effective frequency for calibration + * purposes + */ +static void lsi_calib_callback(enum TimIRQSource src) +{ + if (src == TIM_IRQ_SOURCE_UPDATE) { + //div is decremented from 40kHz * programmed delay (in s) + uint32_t lsi_freq = (40000 * 2) - bkp_read_rtc_div(); + bkp_write_data(BKP_DATA_LSI_CALIB, lsi_freq); + } } diff --git a/drv/bkp.h b/drv/bkp.h index 28da3f8..b83541d 100644 --- a/drv/bkp.h +++ b/drv/bkp.h @@ -14,6 +14,7 @@ //--includes-------------------------------------------------------------------- #include "stdint.h" +#include "tim.h" //--type definitions------------------------------------------------------------ @@ -39,6 +40,19 @@ enum BkpRtcIrq { BKP_RTC_IRQ_OVERFLOW = 0x1 << 2, }; +enum BkpData { + BKP_DATA_LSI_CALIB, + BKP_DATA_1, + BKP_DATA_2, + BKP_DATA_3, + BKP_DATA_4, + BKP_DATA_5, + BKP_DATA_6, + BKP_DATA_7, + BKP_DATA_8, + BKP_DATA_9, +}; + /** * Prototype of the IRQ callbacks that the applicative code can provide */ @@ -56,7 +70,8 @@ typedef void (*BkpRtcCallback)(enum BkpRtcIrq src); * - LSE consumes the less energy and continues to run in standby mode, but * requires an extra oscillator circuit * - LSI consumes little but isn't very accurate and requires extra calibration - * (see bkp_callibrate_lsi) + * (see bkp_callibrate_lsi). The calibration value is automatically used if + * present when calling this function. * - HSE consumes the most. * WARNING : once configured, the clock source can only changed by reseting the * whole backup domain via bkp_reset() @@ -85,6 +100,7 @@ void bkp_set_rtc_alam(uint32_t offset); * Returns the current counter value of the RTC */ uint32_t bkp_read_rtc(void); +uint32_t bkp_read_rtc_div(void); /** * Resets the entire backup domain, composed of everything configured through @@ -92,9 +108,28 @@ uint32_t bkp_read_rtc(void); */ void bkp_reset(void); +/** + * Writes data to the specified backup domain index. The data will persist as + * long as VBAT is present + */ +void bkp_write_data(enum BkpData data_index, uint16_t data); + +/** + * Writes data from the specified backup domain data index. The data will + * persist as long as VBAT is present + */ +uint16_t bkp_read_data(enum BkpData data_index); + +/** + * Calibrate the LSI oscillator using the specified timer for accurate RTC + * timings and store the calibration value at backup domain index + * BKP_DATA_LSI_CALIB. This function has no effect if a calibration value is + * already present + */ +void bkp_calibrate_lsi(enum TimPeriph timer); + //unimplemented functions void bkp_configure_tamper(); -void bkp_calibrate_lsi(void); void bkp_configure_lse(bool enable); diff --git a/drv/bkp_regs.h b/drv/bkp_regs.h index 8a3b6c7..8101c15 100644 --- a/drv/bkp_regs.h +++ b/drv/bkp_regs.h @@ -62,6 +62,7 @@ union BKP_CSR { }; struct BKP { + uint32_t reserved1; union BKP_DR DR[20]; union BKP_RTCCR RTCCR; union BKP_CR CR; diff --git a/drv/dma.h b/drv/dma.h index 5367530..8ddcf33 100644 --- a/drv/dma.h +++ b/drv/dma.h @@ -96,7 +96,7 @@ enum DmaIRQSource { /** * Prototype of the IRQ callbacks that the applicative code can provide */ -typedef void (*DmaCallback)(enum DmaIRQSource, volatile void* param); +typedef void (*DmaCallback)(enum DmaIRQSource src, volatile void* param); /** * Generic struct used to share DAM configs between peripheral drivers and diff --git a/drv/pwr.c b/drv/pwr.c index 19f17f7..bf5fa2e 100644 --- a/drv/pwr.c +++ b/drv/pwr.c @@ -26,7 +26,7 @@ static volatile struct PWR* regs = (struct PWR*)PWR_BASE_ADDRESS; void pwr_sleep(void) { scb_configure_deepsleep(false); - __asm("wfi"); + __asm("wfe"); } void pwr_stop(enum PwrWakeupSpeed speed) @@ -35,7 +35,7 @@ void pwr_stop(enum PwrWakeupSpeed speed) scb_configure_deepsleep(true); regs->CR.PDDS = 0; regs->CR.LPDS = speed; - __asm("wfi"); + __asm("wfe"); rcc_configure(RCC_PRESET_SPEED); } @@ -44,7 +44,7 @@ void pwr_standby(void) rcc_enable(RCC_AHB_NONE, RCC_APB1_PWR, RCC_APB2_NONE); scb_configure_deepsleep(true); regs->CR.PDDS = 1; - __asm("wfi"); + __asm("wfe"); rcc_configure(RCC_PRESET_SPEED); } diff --git a/drv/rcc.c b/drv/rcc.c index 4369a79..f755b0a 100644 --- a/drv/rcc.c +++ b/drv/rcc.c @@ -94,17 +94,20 @@ void rcc_reset(enum RccApb1 apb1_mask, enum RccApb2 apb2_mask) void rcc_get_clocks(struct RccClocks* clocks) { + clocks->ahb_freq = 0; switch (current_preset) { case RCC_PRESET_DEFAULT: clocks->ahb_freq = 8000000; clocks->apb1_freq = 8000000; clocks->apb2_freq = 8000000; + clocks->tim_freq = 8000000; break; case RCC_PRESET_SPEED: clocks->ahb_freq = 72000000; clocks->apb1_freq = 36000000; clocks->apb2_freq = 72000000; + clocks->tim_freq = 72000000; break; default: //TODO hardfault diff --git a/drv/rcc.h b/drv/rcc.h index 9d1e9d4..51eacea 100644 --- a/drv/rcc.h +++ b/drv/rcc.h @@ -106,6 +106,7 @@ struct RccClocks { uint32_t ahb_freq; uint32_t apb1_freq; uint32_t apb2_freq; + uint32_t tim_freq; }; diff --git a/drv/tim.c b/drv/tim.c new file mode 100644 index 0000000..832a75b --- /dev/null +++ b/drv/tim.c @@ -0,0 +1,183 @@ +/** @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); +} + diff --git a/drv/tim.h b/drv/tim.h new file mode 100644 index 0000000..c10470f --- /dev/null +++ b/drv/tim.h @@ -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_ + diff --git a/drv/tim_regs.h b/drv/tim_regs.h new file mode 100644 index 0000000..a97f204 --- /dev/null +++ b/drv/tim_regs.h @@ -0,0 +1,455 @@ +/** @file tim_regs.h + * Module defining the TIMers registers. + * + * Mainly made to be used by the tim module. It is recommanded to go through + * the functions provided by that module instead of directly using the registers + * defined here. + */ + +#ifndef _TIM_REGS_H_ +#define _TIM_REGS_H_ + +//--includes-------------------------------------------------------------------- + +#include "stdint.h" + + +//--type definitions------------------------------------------------------------ + +#define TIM1_BASE_ADDRESS 0x40012C00 +#define TIM2_BASE_ADDRESS 0x40000000 +#define TIM3_BASE_ADDRESS 0x40000400 +#define TIM4_BASE_ADDRESS 0x40000800 + +union TIM_CR1 { + struct { + uint32_t CEN:1; + uint32_t UDIS:1; + uint32_t URS:1; + uint32_t OPM:1; + uint32_t DIR:1; + uint32_t CMS:2; + uint32_t ARPE:1; + uint32_t CKD:2; + uint32_t reserved1:22; + }; + uint32_t word; +}; + +union TIM_CR2 { + struct { + uint32_t reserved1:3; + uint32_t CCDS:1; + uint32_t MMS:3; + uint32_t TI1S:1; + uint32_t reserved2:24; + }; + uint32_t word; +}; + +union TIM_ADV_CR2 { + struct { + uint32_t CCPC:1; + uint32_t reserved1:1; + uint32_t CCUS:1; + uint32_t CCDS:1; + uint32_t MMS:3; + uint32_t TI1S:1; + uint32_t OI1S:1; + uint32_t OIS1N:1; + uint32_t OIS2:1; + uint32_t OIS2N:1; + uint32_t OIS3:1; + uint32_t OIS3N:1; + uint32_t OIS4:1; + uint32_t reserved2:17; + }; + uint32_t word; +}; + +union TIM_SMCR { + struct { + uint32_t SMS:3; + uint32_t reserved1:1; + uint32_t TS:3; + uint32_t MSM:1; + uint32_t ETF:4; + uint32_t ETPS:2; + uint32_t ECE:1; + uint32_t ETP:1; + uint32_t reserved2:16; + }; + uint32_t word; +}; + +union TIM_DIER { + struct { + uint32_t UIE:1; + uint32_t CC1IE:1; + uint32_t CC2IE:1; + uint32_t CC3IE:1; + uint32_t CC4IE:1; + uint32_t reserved1:1; + uint32_t TIE:1; + uint32_t reserved2:1; + uint32_t UDE:1; + uint32_t CC1DE:1; + uint32_t CC2DE:1; + uint32_t CC3DE:1; + uint32_t CC4DE:1; + uint32_t COMDE:1; + uint32_t TDE:1; + uint32_t reserved3:17; + }; + uint32_t word; +}; + +union TIM_ADV_DIER { + struct { + uint32_t UIE:1; + uint32_t CC1IE:1; + uint32_t CC2IE:1; + uint32_t CC3IE:1; + uint32_t CC4IE:1; + uint32_t COMIE:1; + uint32_t TIE:1; + uint32_t BIE:1; + uint32_t UDE:1; + uint32_t CC1DE:1; + uint32_t CC2DE:1; + uint32_t CC3DE:1; + uint32_t CC4DE:1; + uint32_t COMDE:1; + uint32_t TDE:1; + uint32_t reserved1:17; + }; + uint32_t word; +}; + + +union TIM_SR { + struct { + uint32_t UIF:1; + uint32_t CC1IF:1; + uint32_t CC2IF:1; + uint32_t CC3IF:1; + uint32_t CC4IF:1; + uint32_t reserved1:1; + uint32_t TIF:1; + uint32_t reserved2:2; + uint32_t CC1OF:1; + uint32_t CC2OF:1; + uint32_t CC3OF:1; + uint32_t CC4OF:1; + uint32_t reserved3:19; + }; + uint32_t word; +}; + +union TIM_ADV_SR { + struct { + uint32_t UIF:1; + uint32_t CC1IF:1; + uint32_t CC2IF:1; + uint32_t CC3IF:1; + uint32_t CC4IF:1; + uint32_t COMIF:1; + uint32_t TIF:1; + uint32_t BIF:1; + uint32_t reserved1:1; + uint32_t CC1OF:1; + uint32_t CC2OF:1; + uint32_t CC3OF:1; + uint32_t CC4OF:1; + uint32_t reserved2:19; + }; + uint32_t word; +}; + +union TIM_EGR { + struct { + uint32_t UG:1; + uint32_t CC1G:1; + uint32_t CC2G:1; + uint32_t CC3G:1; + uint32_t CC4G:1; + uint32_t reserved1:1; + uint32_t TG:1; + uint32_t reserved2:25; + }; + uint32_t word; +}; + +union TIM_ADV_EGR { + struct { + uint32_t UG:1; + uint32_t CC1G:1; + uint32_t CC2G:1; + uint32_t CC3G:1; + uint32_t CC4G:1; + uint32_t COMG:1; + uint32_t TG:1; + uint32_t BG:1; + uint32_t reserved1:24; + }; + uint32_t word; +}; + +union TIM_CCMR1_INPUT { + struct { + uint32_t CC1S:2; + uint32_t OC1FE:1; + uint32_t OC1PE:1; + uint32_t OC1M:3; + uint32_t OC1CE:1; + uint32_t CC2S:2; + uint32_t OC2FE:1; + uint32_t OC2PE:1; + uint32_t OC2M:3; + uint32_t OC2CE:1; + uint32_t reserved1:16; + }; + uint32_t word; +}; + +union TIM_CCMR1_OUTPUT { + struct { + uint32_t CC1S:2; + uint32_t IC1PSC:2; + uint32_t IC1F:4; + uint32_t CC2S:2; + uint32_t IC2PSC:2; + uint32_t IC2F:4; + uint32_t reserved1:16; + }; + uint32_t word; +}; + +union TIM_CCMR1 { + union TIM_CCMR1_INPUT input; + union TIM_CCMR1_OUTPUT output; +}; + +union TIM_CCMR2_INPUT { + struct { + uint32_t CC3S:2; + uint32_t OC3FE:1; + uint32_t OC3PE:1; + uint32_t OC3M:3; + uint32_t OC3CE:1; + uint32_t CC4S:2; + uint32_t OC4FE:1; + uint32_t OC4PE:1; + uint32_t OC4M:3; + uint32_t OC4CE:1; + uint32_t reserved1:16; + }; + uint32_t word; +}; + +union TIM_CCMR2_OUTPUT { + struct { + uint32_t CC3S:2; + uint32_t IC3PSC:2; + uint32_t IC3F:4; + uint32_t CC4S:2; + uint32_t IC4PSC:2; + uint32_t IC4F:4; + uint32_t reserved1:16; + }; + uint32_t word; +}; + +union TIM_CCMR2 { + union TIM_CCMR2_INPUT input; + union TIM_CCMR2_OUTPUT output; +}; + +union TIM_CCER { + struct { + uint32_t CC1E:1; + uint32_t CC1P:1; + uint32_t reserved1:2; + uint32_t CC2E:1; + uint32_t CC2P:1; + uint32_t reserved2:2; + uint32_t CC3E:1; + uint32_t CC3P:1; + uint32_t reserved3:2; + uint32_t CC4E:1; + uint32_t CC4P:1; + uint32_t reserved4:18; + }; + uint32_t word; +}; + +union TIM_ADV_CCER { + struct { + uint32_t CC1E:1; + uint32_t CC1P:1; + uint32_t CC1NE:1; + uint32_t CC1NP:1; + uint32_t CC2E:1; + uint32_t CC2P:1; + uint32_t CC2NE:1; + uint32_t CC2NP:1; + uint32_t CC3E:1; + uint32_t CC3P:1; + uint32_t CC3NE:1; + uint32_t CC3NP:1; + uint32_t CC4E:1; + uint32_t CC4P:1; + uint32_t CC4NE:1; + uint32_t CC4NP:1; + uint32_t reserved1:18; + }; + uint32_t word; +}; + +union TIM_CNT { + struct { + uint32_t CNT:16; + uint32_t reserved1:16; + }; + uint32_t word; +}; + +union TIM_PSC { + struct { + uint32_t PSC:16; + uint32_t reserved1:16; + }; + uint32_t word; +}; + +union TIM_ARR { + struct { + uint32_t ARR:16; + uint32_t reserved1:16; + }; + uint32_t word; +}; + +union TIM_ADV_RCR { + struct { + uint32_t REP:8; + uint32_t reserved1:24; + }; + uint32_t word; +}; + +union TIM_CCR1 { + struct { + uint32_t CCR1:16; + uint32_t reserved1:16; + }; + uint32_t word; +}; + +union TIM_CCR2 { + struct { + uint32_t CCR2:16; + uint32_t reserved1:16; + }; + uint32_t word; +}; + +union TIM_CCR3 { + struct { + uint32_t CCR3:16; + uint32_t reserved1:16; + }; + uint32_t word; +}; + +union TIM_CCR4 { + struct { + uint32_t CCR4:16; + uint32_t reserved1:16; + }; + uint32_t word; +}; + +union TIM_ADV_BDTR { + struct { + uint32_t DT:8; + uint32_t LOCK:2; + uint32_t OSSI:1; + uint32_t OSSR:1; + uint32_t BKE:1; + uint32_t BKP:1; + uint32_t AOE:1; + uint32_t MOE:1; + uint32_t reserved1:16; + }; + uint32_t word; +}; + +union TIM_DCR { + struct { + uint32_t DBA:5; + uint32_t reserved1:3; + uint32_t MBL:5; + uint32_t reserved2:19; + }; + uint32_t word; +}; + +union TIM_DMAR { + struct { + uint32_t DMAB; + }; + uint32_t word; +}; + +struct TIM { + union TIM_CR1 cr1; + union TIM_CR2 cr2; + union TIM_SMCR smcr; + union TIM_DIER dier; + union TIM_SR sr; + union TIM_EGR egr; + union TIM_CCMR1 ccmr1; + union TIM_CCMR2 ccmr2; + union TIM_CCER ccer; + union TIM_CNT cnt; + union TIM_PSC psc; + union TIM_ARR arr; + uint32_t reserved1; + union TIM_CCR1 ccr1; + union TIM_CCR2 ccr2; + union TIM_CCR3 ccr3; + union TIM_CCR4 ccr4; + uint32_t reserved2; + union TIM_DCR dcr; + union TIM_DMAR dmar; +}; + +struct TIM_ADV { + union TIM_CR1 cr1; + union TIM_ADV_CR2 cr2; + union TIM_SMCR smcr; + union TIM_ADV_DIER dier; + union TIM_ADV_SR sr; + union TIM_ADV_EGR egr; + union TIM_CCMR1 ccmr1; + union TIM_CCMR2 ccmr2; + union TIM_ADV_CCER ccer; + union TIM_CNT cnt; + union TIM_PSC psc; + union TIM_ARR arr; + union TIM_ADV_RCR rcr; + union TIM_CCR1 ccr1; + union TIM_CCR2 ccr2; + union TIM_CCR3 ccr3; + union TIM_CCR4 ccr4; + union TIM_ADV_BDTR bdtr; + union TIM_DCR dcr; + union TIM_DMAR dmar; +}; + + +//--functions------------------------------------------------------------------- + +#endif //_TIM_REGS_H_ + diff --git a/srv/debug.c b/srv/debug.c index 416880c..dcd1d21 100644 --- a/srv/debug.c +++ b/srv/debug.c @@ -38,11 +38,11 @@ void _debug_init(enum UsartPeriph usart, enum GpioPort tx_port, dma_mbuf_configure(&mbuf,usart_configure_tx_dma(usart), DMA_CONFIG_PRIO_LOW, tx_buffer, BUFFER_SIZE); - debug_trace("\n"); - debug_trace("------------------------------------------------------------------------------\n"); - debug_trace("starting debug software\n"); - debug_trace("compiled on " __DATE__ " at " __TIME__ "\n"); - debug_trace("------------------------------------------------------------------------------\n"); + debug_trace(""); + debug_trace("------------------------------------------------------------------------------"); + debug_trace("starting debug software"); + debug_trace("compiled on " __DATE__ " at " __TIME__); + debug_trace("------------------------------------------------------------------------------"); } void _debug_print(const char* restrict header, diff --git a/srv/task.c b/srv/task.c index 047fca1..9d3f53e 100644 --- a/srv/task.c +++ b/srv/task.c @@ -58,7 +58,6 @@ void task_start_scheduler(void) rcc_configure_lsi(true); pwr_configure_bkp_write(true); - bkp_reset(); bkp_configure_rtc(1000, BKP_RTC_CLOCK_SRC_LSI, BKP_RTC_IRQ_NONE, nullptr); pwr_configure_bkp_write(false); exti_configure(EXTI_LINE_RTC, EXTI_CONFIG_RISING_EDGE, callback_rtc);