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
This commit is contained in:
parent
3e3d4d2bff
commit
507f1e6863
125
drv/bkp.c
Normal file
125
drv/bkp.c
Normal file
@ -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);
|
||||
}
|
||||
|
||||
47
drv/bkp.h
Normal file
47
drv/bkp.h
Normal file
@ -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_
|
||||
|
||||
@ -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_
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
|
||||
139
drv/rtc.c
139
drv/rtc.c
@ -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);
|
||||
}
|
||||
43
drv/rtc.h
43
drv/rtc.h
@ -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_
|
||||
|
||||
Loading…
Reference in New Issue
Block a user