diff --git a/drv/bkp.c b/drv/bkp.c new file mode 100644 index 0000000..5c2f4ec --- /dev/null +++ b/drv/bkp.c @@ -0,0 +1,125 @@ +/** @file bkp.c + * Module handling the Backup (BKP) domain functionalities. + * + */ + +//--includes-------------------------------------------------------------------- + +#include "bkp.h" +#include "bkp_regs.h" +#include "rcc.h" +#include "nvic.h" + + +//--local definitions----------------------------------------------------------- + +uint32_t compute_prescaler(uint32_t period_ms, enum BkpRtcClockSrc clock_src); + + +//--local variables------------------------------------------------------------- + +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; + +static BkpRtcCallback rtc_callback; + + +//--public functions------------------------------------------------------------ + +void bkp_configure_rtc(uint32_t period_ms, enum BkpRtcClockSrc clock_src, + enum BkpRtcIrq irq_mask, uint32_t alarm_tick, BkpRtcCallback callback) +{ + rcc_enable(RCC_AHB_NONE, RCC_APB1_BKP, RCC_APB2_NONE); + + //start RTC + rcc_regs->BDCR.RTCSEL = clock_src + 1; + rcc_regs->BDCR.RTCEN = 1; + + //compute prescaler + uint32_t prescaler = compute_prescaler(period_ms, clock_src); + + //wait for registers to synchronize + rtc_regs->CRL.RSF = 0; + while (rtc_regs->CRL.RSF != 1) {} + //wait for last operation to finish + while (rtc_regs->CRL.RTOFF != 1) {} + + //enable core configuration + rtc_regs->CRL.CNF = 1; + + //configure core registers + rtc_regs->PRLH.PRL = prescaler >> 16; + rtc_regs->PRLL.PRL = prescaler; + rtc_regs->ALRH.RTC_ALR = alarm_tick >> 16; + rtc_regs->ALRL.RTC_ALR = alarm_tick; + + //apply irq config + rtc_regs->CRH.word |= irq_mask & 0x7; + + //disable/apply core configuration + rtc_regs->CRL.CNF = 0; + + //wait for last operation to finish + while (rtc_regs->CRL.RTOFF != 1) {} + + if (callback) { + rtc_callback = callback; + nvic_enable(NVIC_IRQ_RTC); + } +} + +uint32_t bkp_read_rtc(void) +{ + //wait for core registers to be synchronized, immediate most of the time + while (rtc_regs->CRL.RSF != 1) {} + + uint32_t time = rtc_regs->CNTH.RTC_CNT << 16; + time |= rtc_regs->CNTL.RTC_CNT << 0; + + return time; +} + +void bkp_reset(void) +{ + rcc_regs->BDCR.BDRST = 1; + rcc_regs->BDCR.BDRST = 0; +} + + +//--local functions------------------------------------------------------------- + +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 + break; + case BKP_RTC_CLOCK_SRC_LSI: + prescaler = 40000000; //40khz + break; + case BKP_RTC_CLOCK_SRC_HSE: + prescaler = 62500000; //8Mhz / 128 + break; + default: + return 0; + } + + return prescaler / period_ms; +} + + +//--ISRs------------------------------------------------------------------------ + +void hdr_rtc(void) +{ + nvic_clear_pending(NVIC_IRQ_RTC); + + //copy and clear and pass along src flags + enum BkpRtcIrq src = rtc_regs->CRL.word & 0x7; + rtc_regs->CRL.word &= ~(0x7); + rtc_callback(src); +} + diff --git a/drv/bkp.h b/drv/bkp.h new file mode 100644 index 0000000..f7e9c0f --- /dev/null +++ b/drv/bkp.h @@ -0,0 +1,47 @@ +/** @file bkp.h + * Module handling the Backup (BKP) domain functionalities. + * + */ + +#ifndef _BKP_H_ +#define _BKP_H_ + +//--includes-------------------------------------------------------------------- + +#include "stdint.h" + + +//--type definitions------------------------------------------------------------ + +enum BkpRtcClockSrc { + BKP_RTC_CLOCK_SRC_LSE = 0x0, + BKP_RTC_CLOCK_SRC_LSI = 0x1, + BKP_RTC_CLOCK_SRC_HSE = 0x2, +}; + +enum BkpRtcIrq { + BKP_RTC_IRQ_NONE = 0, + BKP_RTC_IRQ_SECOND = 0x1 << 0, + BKP_RTC_IRQ_ALARM = 0x1 << 1, + BKP_RTC_IRQ_OVERFLOW = 0x1 << 2, +}; + +typedef void (*BkpRtcCallback)(enum BkpRtcIrq src); + + +//--functions------------------------------------------------------------------- + +void bkp_configure_rtc(uint32_t period_ms, enum BkpRtcClockSrc clock_src, + enum BkpRtcIrq irq_mask, uint32_t alarm_tick, BkpRtcCallback callback); +uint32_t bkp_read_rtc(void); + +void bkp_reset(void); + +//unimplemented functions +void bkp_configure_tamper(); +void bkp_calibrate_lsi(void); +void bkp_configure_lse(bool enable); + + +#endif //_BKP_H_ + diff --git a/drv/rtc_regs.h b/drv/bkp_regs.h similarity index 59% rename from drv/rtc_regs.h rename to drv/bkp_regs.h index de83d87..8a3b6c7 100644 --- a/drv/rtc_regs.h +++ b/drv/bkp_regs.h @@ -1,13 +1,13 @@ -/** @file rtc_regs.h - * Module defining the Real-Time Clock (RTC) registers. +/** @file bkp_regs.h + * Module defining the Backup (bkp) domain registers. * - * Mainly made to be used by the rtc module. It is recommanded to go through + * Mainly made to be used by the bkp module. It is recommanded to go through * the functions provided by that module instead of directly using the registers * defined here. */ -#ifndef _RTC_REGS_H_ -#define _RTC_REGS_H_ +#ifndef _BKP_REGS_H_ +#define _BKP_REGS_H_ //--includes-------------------------------------------------------------------- @@ -16,8 +16,79 @@ //--type definitions------------------------------------------------------------ +#define BKP_BASE_ADDRESS 0x40006C00 +#define RCC_BASE_ADDRESS 0x40021020 #define RTC_BASE_ADDRESS 0x40002800 +union BKP_DR { + struct { + uint32_t D:16; + uint32_t reserved1:16; + }; + uint32_t word; +}; + +union BKP_RTCCR { + struct { + uint32_t CAL:7; + uint32_t CCO:1; + uint32_t ASOE:1; + uint32_t ASOS:1; + uint32_t reserved1:22; + }; + uint32_t word; +}; + +union BKP_CR { + struct { + uint32_t TPE:1; + uint32_t TPAL:1; + uint32_t reserved1:30; + }; + uint32_t word; +}; + +union BKP_CSR { + struct { + uint32_t CTE:1; + uint32_t CTI:1; + uint32_t TPIE:1; + uint32_t reserved1:5; + uint32_t TEF:1; + uint32_t TIF:1; + uint32_t reserved2:22; + }; + uint32_t word; +}; + +struct BKP { + union BKP_DR DR[20]; + union BKP_RTCCR RTCCR; + union BKP_CR CR; + union BKP_CSR CSR; +}; + + +union RCC_BDCR { + struct { + uint32_t LSEON:1; + uint32_t LSERDY:1; + uint32_t LSEBYP:1; + uint32_t reserved1:5; + uint32_t RTCSEL:2; + uint32_t reserved2:5; + uint32_t RTCEN:1; + uint32_t BDRST:1; + uint32_t reserved3:15; + }; + uint32_t word; +}; + +struct RCC { + union RCC_BDCR BDCR; +}; + + union RTC_CRH { struct { uint32_t SECIE:1; @@ -121,5 +192,5 @@ struct RTC { //--functions------------------------------------------------------------------- -#endif //_RTC_REGS_H_ +#endif //_BKP_REGS_H_ diff --git a/drv/rcc.c b/drv/rcc.c index c229c45..4369a79 100644 --- a/drv/rcc.c +++ b/drv/rcc.c @@ -70,12 +70,6 @@ void rcc_configure_lsi(bool enable) } } -void rcc_configure_rtc(bool enable, enum RccRtcClockSrc clock_src) -{ - regs->BDCR.RTCSEL = clock_src; - regs->BDCR.RTCEN = enable; -} - void rcc_enable(enum RccAhb ahb_mask, enum RccApb1 apb1_mask, enum RccApb2 apb2_mask) { diff --git a/drv/rcc.h b/drv/rcc.h index b437ecb..9d1e9d4 100644 --- a/drv/rcc.h +++ b/drv/rcc.h @@ -125,8 +125,6 @@ void rcc_configure(enum RccPreset preset); */ void rcc_configure_lsi(bool enable); -void rcc_configure_rtc(bool enable, enum RccRtcClockSrc clock_src); - /** * Enables peripherals on the different buses. The enums values can used as * masks to enable multiple peripherals at the same time. Invalid values will be diff --git a/drv/rcc_regs.h b/drv/rcc_regs.h index 47a9612..7e36f7a 100644 --- a/drv/rcc_regs.h +++ b/drv/rcc_regs.h @@ -225,21 +225,6 @@ union RCC_APB1ENR { uint32_t word; }; -union RCC_BDCR { - struct { - uint32_t LSEON:1; - uint32_t LSERDY:1; - uint32_t LSEBYP:1; - uint32_t reserved1:5; - uint32_t RTCSEL:2; - uint32_t reserved2:5; - uint32_t RTCEN:1; - uint32_t BDRST:1; - uint32_t reserved3:15; - }; - uint32_t word; -}; - union RCC_CSR { struct { uint32_t LSION:1; @@ -266,7 +251,7 @@ struct RCC { union RCC_AHBENR AHBENR; union RCC_APB2ENR APB2ENR; union RCC_APB1ENR APB1ENR; - union RCC_BDCR BDCR; + uint32_t reserved1; union RCC_CSR CSR; }; diff --git a/drv/rtc.c b/drv/rtc.c deleted file mode 100644 index fe5ddd1..0000000 --- a/drv/rtc.c +++ /dev/null @@ -1,139 +0,0 @@ -//--includes-------------------------------------------------------------------- - -#include "rtc.h" -#include "rtc_regs.h" -#include "rcc.h" -#include "pwr.h" -#include "nvic.h" - - -//--local definitions----------------------------------------------------------- - -//--local variables------------------------------------------------------------- - -static volatile struct RTC* regs = (struct RTC*)RTC_BASE_ADDRESS; -static RtcCallback rtc_callback; - - -//--public functions------------------------------------------------------------ - -void rtc_configure(uint32_t period_ms, enum RtcClockSrc clock_src, - enum RtcIrq irq_mask, uint32_t alarm_tick, RtcCallback callback) -{ - pwr_configure_bkp_write(true); - //start RTC - rcc_configure_rtc(true, clock_src + 1); - - //rtc_reset(); - rcc_enable(RCC_AHB_NONE, RCC_APB1_BKP, RCC_APB2_NONE); - //rcc_configure_rtc(false, RCC_RTC_CLOCK_SRC_NONE); - - //compute prescaler - uint32_t prescaler = 0; - switch (clock_src) { - case RTC_CLOCK_SRC_LSE: - prescaler = 32768000; //32.768kHz - break; - case RTC_CLOCK_SRC_LSI: - prescaler = 40000000; //40khz - break; - case RTC_CLOCK_SRC_HSE: - prescaler = 62500000; //8Mhz / 128 - break; - default: - return; - } - prescaler /= period_ms; - - //wait for registers to synchronize - regs->CRL.RSF = 0; - while (regs->CRL.RSF != 1) {} - //wait for last operation to finish - while (regs->CRL.RTOFF != 1) {} - - //enable core configuration - regs->CRL.CNF = 1; - - //configure core registers - regs->PRLH.PRL = prescaler >> 16; - regs->PRLL.PRL = prescaler; - regs->ALRH.RTC_ALR = alarm_tick >> 16; - regs->ALRL.RTC_ALR = alarm_tick; - - //apply irq config - regs->CRH.word |= irq_mask & 0x7; - - //disable/apply core configuration - regs->CRL.CNF = 0; - - //wait for last operation to finish - while (regs->CRL.RTOFF != 1) {} - - pwr_configure_bkp_write(false); - - if (callback) { - rtc_callback = callback; - nvic_enable(NVIC_IRQ_RTC); - } -} - -void rtc_reset(void) -{ - nvic_disable(NVIC_IRQ_RTC); - pwr_configure_bkp_write(true); - rcc_enable(RCC_AHB_NONE, RCC_APB1_BKP, RCC_APB2_NONE); - - //wait for registers to synchronize - regs->CRL.RSF = 0; - //while (regs->CRL.RSF != 1) {} - //wait for last operation to finish - while (regs->CRL.RTOFF != 1) {} - - //clear config registers - regs->CRH.word &= ~0x7; - regs->CRL.word &= ~0xf; - - //enable core configuration - regs->CRL.CNF = 1; - - //reset core registers. DIV register can be ignore since it is reset on any - //changes of the other 2 - regs->PRLH.PRL = 0x0; - regs->PRLL.PRL = 0x8000; - regs->CNTH.RTC_CNT = 0x0; - regs->CNTL.RTC_CNT = 0x0; - - //disable/apply core configuration - regs->CRL.CNF = 0; - - //wait for last operation to finish - while (regs->CRL.RTOFF != 1) {} - - rcc_configure_rtc(false, RCC_RTC_CLOCK_SRC_NONE); - rcc_disable(RCC_AHB_NONE, RCC_APB1_BKP, RCC_APB2_NONE); - pwr_configure_bkp_write(false); -} - -uint32_t stk_read_s(void) -{ - //wait for core registers to be synchronized, immediate most of the time - while (regs->CRL.RSF != 1) {} - - uint32_t time = regs->CNTH.RTC_CNT << 16; - time |= regs->CNTL.RTC_CNT << 0; - - return time; -} - - -//--local functions------------------------------------------------------------- - -void hdr_rtc(void) -{ - nvic_clear_pending(NVIC_IRQ_RTC); - - //copy and clear and pass along src flags - enum RtcIrq src = regs->CRL.word & 0x7; - regs->CRL.word &= ~(0x7); - rtc_callback(src); -} diff --git a/drv/rtc.h b/drv/rtc.h deleted file mode 100644 index ff161f4..0000000 --- a/drv/rtc.h +++ /dev/null @@ -1,43 +0,0 @@ -/** @file rtc.h - * Module handling the Real-Time Clock (RTC). - * - */ - -#ifndef _RTC_H_ -#define _RTC_H_ - -//--includes-------------------------------------------------------------------- - -#include "stdint.h" - - -//--type definitions------------------------------------------------------------ - -enum RtcClockSrc { - RTC_CLOCK_SRC_LSE = 0x0, - RTC_CLOCK_SRC_LSI = 0x1, - RTC_CLOCK_SRC_HSE = 0x2, -}; - -enum RtcIrq { - RTC_IRQ_NONE = 0, - RTC_IRQ_SECOND = 0x1 << 0, - RTC_IRQ_ALARM = 0x1 << 1, - RTC_IRQ_OVERFLOW = 0x1 << 2, -}; - -typedef void (*RtcCallback)(enum RtcIrq src); - - -//--functions------------------------------------------------------------------- - -void rtc_configure(uint32_t period_ms, enum RtcClockSrc clock_src, - enum RtcIrq irq_mask, uint32_t alarm_tick, RtcCallback callback); - -void rtc_reset(void); - -uint32_t stk_read_s(void); - - -#endif //_RTC_H_ -