ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_rtc.c File Reference

BCD-calendar Realtime Clock driver implementation. More...

#include "ra8_rtc.h"
#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_hw_err.h"
#include "ra8_log.h"
#include "ra8_register_protection.h"
#include "ra8_rtc_regs.h"
#include "ra8_system_regs.h"
#include "ra8_time.h"
Include dependency graph for ra8_rtc.c:

Go to the source code of this file.

Data Structures

struct  ra8_rtc_state_t

Enumerations

enum  ra8_rtc_bcd_t : uint8_t {
  k_ra8_bcd_digit_mask = 0x0FU ,
  k_ra8_bcd_digit_shift = 4U ,
  k_ra8_bcd_digit_base = 10U
}
enum  ra8_rtc_year_t : uint16_t { k_ra8_rtc_year_base = 2000U }
enum  ra8_rtc_wait_t : uint16_t { k_ra8_rtc_wait_iters = 10000U }
 Bounded-loop limits for register-change waits. More...
enum  ra8_rtc_byte_mask_t : uint8_t { k_ra8_rtc_byte_mask_all = 0xFFU }
enum  ra8_rtc_clk_wait_t : uint16_t {
  k_ra8_rtc_clk_stab_sub_ms = 1000U ,
  k_ra8_rtc_clk_stab_loco_ms = 5U ,
  k_ra8_rtc_clk_six_clocks_ms = 1U ,
  k_ra8_rtc_clk_reset_ms = 5U
}
 Fixed timed waits (ms) used while bringing up the count source. More...
enum  ra8_rtc_rfr_t : uint16_t {
  k_ra8_rtc_rfrh_cold = 0x0000U ,
  k_ra8_rtc_rfrl_32768 = 0x00FFU
}
 Prescaler frequency-register values for the LOCO count source. More...
enum  ra8_rtc_alarm_t : uint8_t {
  k_ra8_rtc_alarm_enb_bit = 7U ,
  k_ra8_rtc_alarm_max_hr = 23U ,
  k_ra8_rtc_alarm_max_min = 59U ,
  k_ra8_rtc_alarm_max_sec = 59U
}
 Bit positions / limits for the RxxAR alarm registers. More...
enum  ra8_rtc_mask_t : uint8_t { k_ra8_rtc_irq_all }
 Combined IRQ mask. More...

Functions

static uint8_t internal_bcd_to_bin (uint8_t bcd)
 Internal helper.
static uint8_t internal_bin_to_bcd (uint8_t bin)
 Internal helper.
static void internal_wait_bit (volatile const uint8_t *reg, uint8_t mask, uint8_t expect)
 Spin until (*reg & mask) == expect, up to k_ra8_rtc_wait_iters.
static ra8_err_t internal_start_count_source (ra8_rtc_clk_src_t src)
 Start and wait out the requested RTC count-source oscillator.
ra8_err_t ra8_rtc_clock_init (ra8_rtc_clk_src_t src)
 Bring up and select the RTC count source (HUM Fig 26.3).
ra8_err_t ra8_rtc_init (void)
 Start the RTC in 24-hour calendar mode.
ra8_err_t ra8_rtc_set (const ra8_rtc_datetime_t *dt)
 Write the calendar registers.
ra8_err_t ra8_rtc_get (ra8_rtc_datetime_t *out)
 Read the calendar registers.
ra8_err_t ra8_rtc_set_alarm (const ra8_rtc_datetime_t *alarm)
 Implementation of ra8_rtc_set_alarm().
ra8_err_t ra8_rtc_deinit (void)
 Tear down the RTC (stop counter + disable IRQs).
ra8_err_t ra8_rtc_set_irq_enable (uint8_t mask)
 Enable one or more RTC IRQ sources via RCR1.
ra8_err_t ra8_rtc_get_status (uint8_t *out_mask)
 Read RCR1 IRQ enable bits.
ra8_err_t ra8_rtc_clear_status (uint8_t mask)
 Clear RCR1 IRQ enable bits.
ra8_err_t ra8_rtc_attach_handler (ra8_rtc_event_fn_t fn, void *ctx)
 Attach a callback for the RTC alarm / periodic event.
void ra8_rtc_dispatch (void)
 Dispatch an RTC event – snapshot RCR1 + fire callback.
ra8_err_t ra8_rtc_enter_stop (void)
 Stop the RTC counter for low-power mode.
ra8_err_t ra8_rtc_exit_stop (void)
 Restart the RTC counter from stop.

Variables

static const char * s_tag = "RTC"
static ra8_rtc_state_t s_rtc_state

Detailed Description

BCD-calendar Realtime Clock driver implementation.

Tag
[Ring 3 / HAL] {World: S}

Hand-written RA8D2 RTC driver. Operates in 24-hour calendar mode, decodes BCD into ra8_rtc_datetime_t, and exposes the alarm / carry / periodic IRQ surface via the dispatch path.

Cross-verified against FSP r_rtc.c R_RTC_Open / CalendarTimeSet / CalendarTimeGet and FSP R_RTC_Type (BSP R7KA8D2KF_core0.h). Every register access carries a HUM Ch 26 citation – the chapter spans pages 1219..1255.

Key sequencing (FSP-aligned):

  • To write any count register the START bit must be cleared first; the driver waits with a bounded loop for the bit to actually fall and then re-asserts it after the writes.
  • HUM Ch 26.2.21: writes to RCR2.HR24 / CNTMD only take effect after the bit reads back the new value, so init polls those.

Definition in file ra8_rtc.c.

Enumeration Type Documentation

◆ ra8_rtc_alarm_t

enum ra8_rtc_alarm_t : uint8_t

Bit positions / limits for the RxxAR alarm registers.

HUM Ch 26.2.10..26.2.16 – each alarm register's bit 7 is the ENB (alarm enable) flag; the lower 7 bits hold the BCD value to match.

Enumerator
k_ra8_rtc_alarm_enb_bit 

RA8 rtc alarm enb bit.

k_ra8_rtc_alarm_max_hr 

RA8 rtc alarm maximum hr.

k_ra8_rtc_alarm_max_min 

RA8 rtc alarm maximum minimum.

k_ra8_rtc_alarm_max_sec 

RA8 rtc alarm maximum sec.

Definition at line 410 of file ra8_rtc.c.

◆ ra8_rtc_bcd_t

enum ra8_rtc_bcd_t : uint8_t
Enumerator
k_ra8_bcd_digit_mask 

RA8 bcd digit mask.

k_ra8_bcd_digit_shift 

RA8 bcd digit shift.

k_ra8_bcd_digit_base 

RA8 bcd digit base.

Definition at line 45 of file ra8_rtc.c.

◆ ra8_rtc_byte_mask_t

enum ra8_rtc_byte_mask_t : uint8_t
Enumerator
k_ra8_rtc_byte_mask_all 

Whole-byte mask for wait loops.

Definition at line 70 of file ra8_rtc.c.

◆ ra8_rtc_clk_wait_t

enum ra8_rtc_clk_wait_t : uint16_t

Fixed timed waits (ms) used while bringing up the count source.

Neither the sub-clock oscillator nor the LOCO exposes a hardware stabilization flag (OSCSF only covers MOSC / HOCO / PLL), so the count-source bring-up waits fixed times rather than polling a ready bit.

  • stab_sub_ms covers t_SUBOSCWT for the 32.768 kHz watch crystal.
  • stab_loco_ms covers the (much shorter) LOCO settle after LCSTP=0.
  • six_clocks_ms is >= 6 cycles of a 32.768 kHz source (~183 us).
  • reset_ms bounds the count-source-synchronized RTC software reset.
Enumerator
k_ra8_rtc_clk_stab_sub_ms 

Sub-clock crystal stabilization wait.

k_ra8_rtc_clk_stab_loco_ms 

LOCO settle wait.

k_ra8_rtc_clk_six_clocks_ms 

>= 6 clocks of the count source.

k_ra8_rtc_clk_reset_ms 

RTC software-reset settle wait.

Definition at line 167 of file ra8_rtc.c.

◆ ra8_rtc_mask_t

enum ra8_rtc_mask_t : uint8_t

Combined IRQ mask.

Enumerator
k_ra8_rtc_irq_all 

RA8 rtc IRQ all.

Definition at line 474 of file ra8_rtc.c.

◆ ra8_rtc_rfr_t

enum ra8_rtc_rfr_t : uint16_t

Prescaler frequency-register values for the LOCO count source.

When LOCO is the count source the prescaler divides it to a 128 Hz base, so RFRL must hold (LOCO_Hz / 128) - 1; for a 32.768 kHz LOCO that is 0x00FF, and RFRH must be cleared first after a cold start (HUM Ch 26.2.24 "RFRL" p 1236, Ch 26.2.25 "RFRH" p 1237).

Enumerator
k_ra8_rtc_rfrh_cold 

RFRH cleared before RFRL on cold start.

k_ra8_rtc_rfrl_32768 

(32768 / 128) - 1 for a 32.768 kHz LOCO.

Definition at line 184 of file ra8_rtc.c.

◆ ra8_rtc_wait_t

enum ra8_rtc_wait_t : uint16_t

Bounded-loop limits for register-change waits.

The RTC sub-clock is at most a few kHz, so a few thousand CPU spin-iterations is plenty (FSP uses FSP_HARDWARE_REGISTER_WAIT which itself spins with no upper bound). We pick an explicit ceiling here to satisfy NASA Rule 2 (bounded loops) and to fail loudly if the hardware never honours the write.

Enumerator
k_ra8_rtc_wait_iters 

RA8 rtc wait iters.

Definition at line 66 of file ra8_rtc.c.

◆ ra8_rtc_year_t

enum ra8_rtc_year_t : uint16_t
Enumerator
k_ra8_rtc_year_base 

Base year for ra8_rtc_datetime_t.

Definition at line 51 of file ra8_rtc.c.

Function Documentation

◆ internal_bcd_to_bin()

uint8_t internal_bcd_to_bin ( uint8_t bcd)
static

Internal helper.

See implementation.

Parameters
[in]bcdSee implementation.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 87 of file ra8_rtc.c.

References k_ra8_bcd_digit_base, k_ra8_bcd_digit_mask, k_ra8_bcd_digit_shift, and RA8_INTERNAL.

Referenced by ra8_rtc_get().

◆ internal_bin_to_bcd()

uint8_t internal_bin_to_bcd ( uint8_t bin)
static

Internal helper.

See implementation.

Parameters
[in]binSee implementation.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 107 of file ra8_rtc.c.

References k_ra8_bcd_digit_base, k_ra8_bcd_digit_shift, and RA8_INTERNAL.

Referenced by ra8_rtc_set(), and ra8_rtc_set_alarm().

◆ internal_start_count_source()

ra8_err_t internal_start_count_source ( ra8_rtc_clk_src_t src)
static

Start and wait out the requested RTC count-source oscillator.

Sub-clock path: write SOMCR drive (standard, matching the EK-RA8D2 watch crystal) while SOSC is stopped, clear SOSCCR.SOSTP, then wait t_SUBOSCWT. LOCO path: clear LOCOCR.LCSTP (the LOCO is normally already running) and let it settle. All three registers sit behind PRCR group 0, so the writes run inside an RA8_PROTECTED_WRITE window. The "other" bits of each register are documented read-as-0 / write-0, so each is written whole rather than read-modify-write.

Parameters
[in]srcCount source to enable (sub-clock or LOCO).
Returns
ra8_err_t outcome.
Return values
k_ra8_okOscillator running (stop bit reads 0).
k_ra8_err_hw_init_failedStop bit still set after the enable write.
Precondition
ra8_time_init() has run (blocks on ra8_delay_ms).
Single-threaded init context.
Postcondition
The selected oscillator's stop bit is clear.
PRCR is re-locked.
Note
Not thread-safe.
Since
0.1.0

Definition at line 215 of file ra8_rtc.c.

References k_ra8_err_hw_init_failed, k_ra8_lococr_lcstp_mask, k_ra8_ok, k_ra8_prcr_unlock_cgc, k_ra8_rtc_clk_loco, k_ra8_rtc_clk_stab_loco_ms, k_ra8_rtc_clk_stab_sub_ms, k_ra8_somcr_drv_standard, k_ra8_sosccr_sostp_mask, ra8_delay_ms(), RA8_INTERNAL, RA8_PROTECTED_WRITE, ra8_sys_lococr(), ra8_sys_somcr(), and ra8_sys_sosccr().

Referenced by ra8_rtc_clock_init().

◆ internal_wait_bit()

void internal_wait_bit ( volatile const uint8_t * reg,
uint8_t mask,
uint8_t expect )
static

Spin until (*reg & mask) == expect, up to k_ra8_rtc_wait_iters.

FSP uses FSP_HARDWARE_REGISTER_WAIT(...) which hard-loops with no time-out. We bound the loop instead so the driver still passes NASA Rule 2 even when the hardware never matches (test mock).

Parameters
[in]regRegister pointer to poll.
[in]maskBits to mask before comparing.
[in]expectExpected masked value.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 134 of file ra8_rtc.c.

References k_ra8_rtc_wait_iters.

Referenced by ra8_rtc_clock_init(), ra8_rtc_enter_stop(), ra8_rtc_exit_stop(), ra8_rtc_init(), and ra8_rtc_set().

◆ ra8_rtc_attach_handler()

ra8_err_t ra8_rtc_attach_handler ( ra8_rtc_event_fn_t fn,
void * ctx )
nodiscard

Attach a callback for the RTC alarm / periodic event.

Since
0.1.0

Definition at line 520 of file ra8_rtc.c.

References k_ra8_ok, and s_rtc_state.

◆ ra8_rtc_clear_status()

ra8_err_t ra8_rtc_clear_status ( uint8_t mask)
nodiscard

Clear RCR1 IRQ enable bits.

Since
0.1.0

Definition at line 513 of file ra8_rtc.c.

References k_ra8_ok, k_ra8_rtc_irq_all, ra8_rtc(), and r_rtc_regs_t::RCR1.

Referenced by main().

◆ ra8_rtc_clock_init()

ra8_err_t ra8_rtc_clock_init ( ra8_rtc_clk_src_t src)
nodiscard

Bring up and select the RTC count source (HUM Fig 26.3).

The RTC counter does not advance until a count clock is both running and selected. This routine performs the "Clock and Count Mode Setting Procedure" of HUM Ch 26.3.2 (Figure 26.3, p 1243):

  1. Start the requested count-source oscillator – for the sub-clock, set SOMCR drive then clear SOSCCR.SOSTP and wait the sub-clock stabilization time; for LOCO, clear LOCOCR.LCSTP. Oscillator control registers are gated by PRCR group 0 (CGC).
  2. Select the count source via RCR4.RCKSEL and supply at least six count-source clocks before proceeding.
  3. Stop the prescaler (RCR2.START = 0) and, when LOCO is selected, program the prescaler frequency register (RFRH = 0, RFRL = 0x00FF for 32.768 kHz) per HUM Ch 26.2.24 p 1236.
  4. Execute an RTC software reset (RCR2.RESET = 1) so the prescaler and count registers initialize against the live count source.

Call this once at power-on, BEFORE ra8_rtc_init(): it leaves the RTC stopped with its count source running and selected, ready for the 24-hour-calendar bring-up that ra8_rtc_init() finishes.

Parameters
[in]srcCount source to bring up and select (k_ra8_rtc_clk_subclock or k_ra8_rtc_clk_loco).
Returns
ra8_err_t outcome.
Return values
k_ra8_okCount source running, selected, RTC reset.
k_ra8_err_invalid_argsrc is not a valid ra8_rtc_clk_src_t.
k_ra8_err_hw_init_failedThe selected oscillator did not leave its stop state (stop bit still set after enable).
Precondition
ra8_time_init() has run (this routine blocks on ra8_delay_ms).
Single-threaded init context (mutates PRCR-gated CGC registers).
Postcondition
The selected oscillator's stop bit is clear (oscillator running).
RCR4.RCKSEL selects src and the RTC has been software-reset with its prescaler stopped (RCR2.START = 0).
Note
Not thread-safe.
See also
ra8_rtc_init()
Since
0.1.0

Definition at line 260 of file ra8_rtc.c.

References internal_start_count_source(), internal_wait_bit(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_rcr2_bit_reset, k_ra8_rcr2_bit_start, k_ra8_rtc_clk_loco, k_ra8_rtc_clk_reset_ms, k_ra8_rtc_clk_six_clocks_ms, k_ra8_rtc_rfrh_cold, k_ra8_rtc_rfrl_32768, ra8_delay_ms(), ra8_log_error, ra8_log_info_val, ra8_rtc(), r_rtc_regs_t::RCR2, r_rtc_regs_t::RCR4, r_rtc_regs_t::RFRH, r_rtc_regs_t::RFRL, and s_tag.

Referenced by internal_rtc_demo_setup_or_halt().

◆ ra8_rtc_deinit()

ra8_err_t ra8_rtc_deinit ( void )
nodiscard

Tear down the RTC (stop counter + disable IRQs).

Since
0.1.0

Definition at line 486 of file ra8_rtc.c.

References k_ra8_ok, ra8_rtc(), r_rtc_regs_t::RCR1, r_rtc_regs_t::RCR2, and s_rtc_state.

◆ ra8_rtc_dispatch()

void ra8_rtc_dispatch ( void )

Dispatch an RTC event – snapshot RCR1 + fire callback.

Reads RTC.RCR1 (HUM Ch 25.2.18 "RCR1 : RTC Control Register 1", p ~1097) to capture which interrupt flag (alarm AIE, carry CIE, or periodic PIE) is asserted, clears the captured bits, and invokes the handler installed via ra8_rtc_attach_handler() with the snapshot mask. Silently returns if no handler is installed.

Precondition
ra8_rtc_init() previously succeeded.
Called from ISR context or unit-test driver.
Postcondition
RCR1 interrupt-enable bits captured at entry are cleared.
Registered handler invoked at most once with the snapshot mask.
Note
Thread safety: ISR context only; not re-entrant.
Since
0.1.0

Definition at line 527 of file ra8_rtc.c.

References k_ra8_rtc_irq_all, ra8_rtc(), and s_rtc_state.

◆ ra8_rtc_enter_stop()

ra8_err_t ra8_rtc_enter_stop ( void )
nodiscard

Stop the RTC counter for low-power mode.

Since
0.1.0

Definition at line 537 of file ra8_rtc.c.

References internal_wait_bit(), k_ra8_ok, k_ra8_rcr2_bit_start, ra8_rtc(), and r_rtc_regs_t::RCR2.

◆ ra8_rtc_exit_stop()

ra8_err_t ra8_rtc_exit_stop ( void )
nodiscard

Restart the RTC counter from stop.

Since
0.1.0

Definition at line 546 of file ra8_rtc.c.

References internal_wait_bit(), k_ra8_ok, k_ra8_rcr2_bit_start, ra8_rtc(), and r_rtc_regs_t::RCR2.

◆ ra8_rtc_get()

◆ ra8_rtc_get_status()

ra8_err_t ra8_rtc_get_status ( uint8_t * out_mask)
nodiscard

Read RCR1 IRQ enable bits.

Since
0.1.0

Definition at line 506 of file ra8_rtc.c.

References k_ra8_ok, k_ra8_rtc_irq_all, RA8_CHECK_NULL_PTR, ra8_rtc(), and s_tag.

Referenced by main().

◆ ra8_rtc_init()

ra8_err_t ra8_rtc_init ( void )
nodiscard

Start the RTC in 24-hour calendar mode.

Returns
k_ra8_ok on success, k_ra8_err_hw_init_failed otherwise.
Note
The count source must already be running and selected. Call ra8_rtc_clock_init() first – this driver's counter does not advance otherwise.
Since
0.1.0

Definition at line 308 of file ra8_rtc.c.

References internal_wait_bit(), k_ra8_ok, k_ra8_rcr2_bit_cntmd, k_ra8_rcr2_bit_hr24, k_ra8_rcr2_bit_start, k_ra8_rtc_byte_mask_all, ra8_log_info, ra8_rtc(), r_rtc_regs_t::RCR1, r_rtc_regs_t::RCR2, and s_tag.

Referenced by internal_lpm_dpsby1_setup_or_halt(), internal_lpm_dpsby2_setup_or_halt(), internal_lpm_dpsby3_setup_or_halt(), internal_lpm_swstd_setup_or_halt(), and internal_rtc_demo_setup_or_halt().

◆ ra8_rtc_set()

◆ ra8_rtc_set_alarm()

ra8_err_t ra8_rtc_set_alarm ( const ra8_rtc_datetime_t * alarm)
nodiscard

Implementation of ra8_rtc_set_alarm().

Programme the alarm-match registers (hour/minute/second).

Writes the BCD-encoded second / minute / hour into RSECAR / RMINAR / RHRAR with their ENB bits set, and clears every other AR register's ENB so the alarm matches purely on time-of-day.

Parameters
[in]alarmSee header.
Returns
Result code.
Return values
k_ra8_okAlarm written.
k_ra8_err_null_ptralarm is NULL.
k_ra8_err_invalid_argOut-of-range hour/min/sec.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe.
Since
0.1.0

Definition at line 437 of file ra8_rtc.c.

References ra8_rtc_datetime_t::hour, internal_bin_to_bcd(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_rtc_alarm_enb_bit, k_ra8_rtc_alarm_max_hr, k_ra8_rtc_alarm_max_min, k_ra8_rtc_alarm_max_sec, ra8_rtc_datetime_t::minute, RA8_CHECK_NULL_PTR, ra8_rtc(), r_rtc_regs_t::RDAYAR, r_rtc_regs_t::RHRAR, r_rtc_regs_t::RMINAR, r_rtc_regs_t::RMONAR, r_rtc_regs_t::RSECAR, r_rtc_regs_t::RWKAR, r_rtc_regs_t::RYRAR, r_rtc_regs_t::RYRAREN, s_tag, and ra8_rtc_datetime_t::second.

Referenced by internal_lpm_dpsby1_arm_wake(), internal_lpm_dpsby2_arm_wake(), internal_lpm_dpsby3_arm_wake(), internal_lpm_swstd_arm_wake(), and internal_rtc_demo_arm_alarm().

◆ ra8_rtc_set_irq_enable()

ra8_err_t ra8_rtc_set_irq_enable ( uint8_t mask)
nodiscard

Variable Documentation

◆ s_rtc_state

ra8_rtc_state_t s_rtc_state
static

Definition at line 484 of file ra8_rtc.c.

Referenced by ra8_rtc_attach_handler(), ra8_rtc_deinit(), and ra8_rtc_dispatch().

◆ s_tag

const char* s_tag = "RTC"
static

Definition at line 43 of file ra8_rtc.c.