Compare commits

...

4 Commits

Author SHA1 Message Date
004b0b9a76 Implement RTC module's basic functionnalities
FUnctions need a cleanup and some details need be ironned, like the
clock management since the whole backup domain must be reset to
configure them
2024-07-27 16:39:49 +02:00
b37eb1dd6e Add RTC configuration to RCC module 2024-07-27 14:17:58 +02:00
0b483c535b Ensure PWR is enabled before configuration 2024-07-27 14:15:55 +02:00
a02bcecaec Implement RTC module's registers 2024-07-16 22:21:05 +02:00
6 changed files with 333 additions and 1 deletions

View File

@ -11,6 +11,7 @@
#include "pwr.h"
#include "pwr_regs.h"
#include "scb.h"
#include "rcc.h"
//--local definitions-----------------------------------------------------------
@ -30,19 +31,28 @@ void pwr_sleep(void)
void pwr_stop(enum PwrWakeupSpeed speed)
{
rcc_enable(RCC_AHB_NONE, RCC_APB1_PWR, RCC_APB2_NONE);
scb_configure_deepsleep(true);
regs->CR.PDDS = 0;
regs->CR.LPDS = speed;
__asm("wfi");
rcc_configure(RCC_PRESET_SPEED);
}
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");
rcc_configure(RCC_PRESET_SPEED);
}
void pwr_configure_bkp_write(bool enable)
{
rcc_enable(RCC_AHB_NONE, RCC_APB1_PWR, RCC_APB2_NONE);
regs->CR.DBP = enable;
}
//--local functions-------------------------------------------------------------

View File

@ -66,10 +66,16 @@ void rcc_configure_lsi(bool enable)
//ensure LSI is enabled
if (enable) {
while (regs->CSR.LSIRDY != 0x1);
while (regs->CSR.LSIRDY != 0x1) {}
}
}
void rcc_configure_rtc(bool enable, enum RccRtcClockSrc clock_src)
{
regs->BDCR.RTCSEL = 0x2;
regs->BDCR.RTCEN = enable;
}
void rcc_enable(enum RccAhb ahb_mask, enum RccApb1 apb1_mask,
enum RccApb2 apb2_mask)
{

View File

@ -95,6 +95,13 @@ enum RccApb2 {
RCC_APB2_TIM11 = (0x1 << 21),
};
enum RccRtcClockSrc {
RCC_RTC_CLOCK_SRC_NONE = 0x0,
RCC_RTC_CLOCK_SRC_LSE = 0x1,
RCC_RTC_CLOCK_SRC_LSI = 0x2,
RCC_RTC_CLOCK_SRC_HSE = 0x3,
};
struct RccClocks {
uint32_t ahb_freq;
uint32_t apb1_freq;
@ -118,6 +125,8 @@ 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

139
drv/rtc.c Normal file
View File

@ -0,0 +1,139 @@
//--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 Normal file
View File

@ -0,0 +1,43 @@
/** @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_

125
drv/rtc_regs.h Normal file
View File

@ -0,0 +1,125 @@
/** @file rtc_regs.h
* Module defining the Real-Time Clock (RTC) registers.
*
* Mainly made to be used by the rtc 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_
//--includes--------------------------------------------------------------------
#include "stdint.h"
//--type definitions------------------------------------------------------------
#define RTC_BASE_ADDRESS 0x40002800
union RTC_CRH {
struct {
uint32_t SECIE:1;
uint32_t ALRIE:1;
uint32_t OWIE:1;
uint32_t reserved1:29;
};
uint32_t word;
};
union RTC_CRL {
struct {
uint32_t SECF:1;
uint32_t ALRF:1;
uint32_t OWF:1;
uint32_t RSF:1;
uint32_t CNF:1;
uint32_t RTOFF:1;
uint32_t reserved1:26;
};
uint32_t word;
};
union RTC_PRLH {
struct {
uint32_t PRL:4;
uint32_t reserved1:28;
};
uint32_t word;
};
union RTC_PRLL {
struct {
uint32_t PRL:16;
uint32_t reserved1:16;
};
uint32_t word;
};
union RTC_DIVH {
struct {
uint32_t RTC_DIV:4;
uint32_t reserved1:28;
};
uint32_t word;
};
union RTC_DIVL {
struct {
uint32_t RTC_DIV:16;
uint32_t reserved1:16;
};
uint32_t word;
};
union RTC_CNTH {
struct {
uint32_t RTC_CNT:16;
uint32_t reserved1:16;
};
uint32_t word;
};
union RTC_CNTL {
struct {
uint32_t RTC_CNT:16;
uint32_t reserved1:16;
};
uint32_t word;
};
union RTC_ALRH {
struct {
uint32_t RTC_ALR:16;
uint32_t reserved1:16;
};
uint32_t word;
};
union RTC_ALRL {
struct {
uint32_t RTC_ALR:16;
uint32_t reserved1:16;
};
uint32_t word;
};
struct RTC {
union RTC_CRH CRH;
union RTC_CRL CRL;
union RTC_PRLH PRLH;
union RTC_PRLL PRLL;
union RTC_DIVH DIVH;
union RTC_DIVL DIVL;
union RTC_CNTH CNTH;
union RTC_CNTL CNTL;
union RTC_ALRH ALRH;
union RTC_ALRL ALRL;
};
//--functions-------------------------------------------------------------------
#endif //_RTC_REGS_H_