Compare commits

...

9 Commits

8 changed files with 112 additions and 54 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,38 @@ 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;
}
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
*/
@ -85,6 +99,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 +107,13 @@ uint32_t bkp_read_rtc(void);
*/
void bkp_reset(void);
void bkp_write_data(enum BkpData data_index, uint16_t data);
uint16_t bkp_read_data(enum BkpData data_index);
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

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

View File

@ -47,13 +47,12 @@ void tim_configure_master(enum TimPeriph periph, enum TimConfig config_mask,
callbacks[periph] = callback;
regs[periph]->dier.TIE = 1;
regs[periph]->dier.UIE = 1;
regs[periph]->dier.UIE = 0;
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;
irq = NVIC_IRQ_TIM1_UP;
break;
case TIM_PERIPH_2:
irq = NVIC_IRQ_TIM2;
@ -71,6 +70,12 @@ void tim_configure_master(enum TimPeriph periph, enum TimConfig config_mask,
//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;
}
}
@ -144,49 +149,13 @@ static enum TimIRQSource computeIRQSource(enum TimPeriph periph)
//--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)
{

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,