Compare commits

..

17 Commits

Author SHA1 Message Date
daf5920814 Merge pull request 'tim' (#6) from tim into dev
Reviewed-on: https://git.steins7.ovh/Steins7/stm32f1xx_HBL/pulls/6
2024-11-03 12:07:39 +00:00
70e6cd2d19 Replace wfi by wfe for faster wakeup time 2024-11-03 13:01:12 +01:00
3303bf6435 Document RTC calibration functions 2024-11-03 13:00:46 +01:00
ec9f5f85fb Remove debug statement left in the code 2024-10-21 17:13:03 +02:00
bd15878cb5 Add missing variable name to dma's function 2024-10-21 17:07:02 +02:00
5ddcf4b15e Fix dual LF at the end of debug lines 2024-10-21 17:05:49 +02:00
05e3397d95 Implement rtc's LSI calibration 2024-10-21 17:05:26 +02:00
ae9cdc3582 Fix majors bugs in tim module 2024-10-21 17:04:45 +02:00
a0dadf166d Fix rcc's timer frequency being 10x too low 2024-10-21 17:03:03 +02:00
a1028b29b8 Fix bkp regs missing a field 2024-10-21 17:02:16 +02:00
449ec77f9f Implement backup domain's data registers access 2024-09-01 22:43:14 +02:00
92085aabb0 Fix rtc prescaler computation 2024-09-01 19:32:38 +02:00
6ab59f1545 Add timer clocks to rcc's clock frequencies 2024-08-30 22:23:24 +02:00
edb59d7e6b 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
2024-08-28 23:11:18 +02:00
d7da7618e3 Define tim's first API iteration
This API is subject to changes and lacks DMA management
2024-08-28 22:06:20 +02:00
3cbc836fe5 Setup tim's module backbone 2024-08-07 21:37:44 +02:00
93f1b5a992 Define tim module's registers 2024-08-04 23:18:38 +02:00
12 changed files with 929 additions and 19 deletions

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -106,6 +106,7 @@ struct RccClocks {
uint32_t ahb_freq;
uint32_t apb1_freq;
uint32_t apb2_freq;
uint32_t tim_freq;
};

183
drv/tim.c Normal file
View File

@ -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);
}

163
drv/tim.h Normal file
View 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_

455
drv/tim_regs.h Normal file
View File

@ -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_

View File

@ -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,

View File

@ -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);