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
This commit is contained in:
parent
b37eb1dd6e
commit
3e3d4d2bff
139
drv/rtc.c
Normal file
139
drv/rtc.c
Normal 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
43
drv/rtc.h
Normal 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_
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user