From 507f1e68635f702eb79f825e5c09c542bea4f760 Mon Sep 17 00:00:00 2001 From: Steins7 Date: Sat, 27 Jul 2024 20:07:36 +0200 Subject: [PATCH] Move rtc control to new BKP module RCC's BCDR register has been moved to the BKP module since it is part of the backup circuit and thus also aboeys some restrictions access-wise --- drv/bkp.c | 125 +++++++++++++++++++++++++++++ drv/bkp.h | 47 +++++++++++ drv/{rtc_regs.h => bkp_regs.h} | 83 ++++++++++++++++++-- drv/rcc.c | 6 -- drv/rcc.h | 2 - drv/rcc_regs.h | 17 +--- drv/rtc.c | 139 --------------------------------- drv/rtc.h | 43 ---------- 8 files changed, 250 insertions(+), 212 deletions(-) create mode 100644 drv/bkp.c create mode 100644 drv/bkp.h rename drv/{rtc_regs.h => bkp_regs.h} (59%) delete mode 100644 drv/rtc.c delete mode 100644 drv/rtc.h 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_ -