|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
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"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 |
BCD-calendar Realtime Clock driver implementation.
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):
Definition in file ra8_rtc.c.
| 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.
| enum ra8_rtc_bcd_t : uint8_t |
| enum ra8_rtc_byte_mask_t : uint8_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.
| enum ra8_rtc_mask_t : uint8_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. |
| 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. |
| enum ra8_rtc_year_t : uint16_t |
| Enumerator | |
|---|---|
| k_ra8_rtc_year_base | Base year for ra8_rtc_datetime_t. |
|
static |
Internal helper.
See implementation.
| [in] | bcd | See implementation. |
| k_ra8_ok | Operation succeeded. |
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().
|
static |
Internal helper.
See implementation.
| [in] | bin | See implementation. |
| k_ra8_ok | Operation succeeded. |
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().
|
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.
| [in] | src | Count source to enable (sub-clock or LOCO). |
| k_ra8_ok | Oscillator running (stop bit reads 0). |
| k_ra8_err_hw_init_failed | Stop bit still set after the enable write. |
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().
|
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).
| [in] | reg | Register pointer to poll. |
| [in] | mask | Bits to mask before comparing. |
| [in] | expect | Expected masked value. |
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().
|
nodiscard |
Attach a callback for the RTC alarm / periodic event.
Definition at line 520 of file ra8_rtc.c.
References k_ra8_ok, and s_rtc_state.
|
nodiscard |
Clear RCR1 IRQ enable bits.
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().
|
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):
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.
| [in] | src | Count source to bring up and select (k_ra8_rtc_clk_subclock or k_ra8_rtc_clk_loco). |
| k_ra8_ok | Count source running, selected, RTC reset. |
| k_ra8_err_invalid_arg | src is not a valid ra8_rtc_clk_src_t. |
| k_ra8_err_hw_init_failed | The selected oscillator did not leave its stop state (stop bit still set after enable). |
src and the RTC has been software-reset with its prescaler stopped (RCR2.START = 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().
|
nodiscard |
Tear down the RTC (stop counter + disable IRQs).
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.
| 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.
Definition at line 527 of file ra8_rtc.c.
References k_ra8_rtc_irq_all, ra8_rtc(), and s_rtc_state.
|
nodiscard |
Stop the RTC counter for low-power mode.
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.
|
nodiscard |
Restart the RTC counter from stop.
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.
|
nodiscard |
Read the calendar registers.
| [out] | out | Receive buffer. |
Definition at line 385 of file ra8_rtc.c.
References ra8_rtc_datetime_t::day, ra8_rtc_datetime_t::hour, internal_bcd_to_bin(), k_ra8_ok, k_ra8_rtc_year_base, ra8_rtc_datetime_t::minute, ra8_rtc_datetime_t::month, RA8_CHECK_NULL_PTR, ra8_rtc(), r_rtc_regs_t::RDAYCNT, r_rtc_regs_t::RHRCNT, r_rtc_regs_t::RMINCNT, r_rtc_regs_t::RMONCNT, r_rtc_regs_t::RSECCNT, r_rtc_regs_t::RWKCNT, r_rtc_regs_t::RYRCNT, s_tag, ra8_rtc_datetime_t::second, ra8_rtc_datetime_t::weekday, and ra8_rtc_datetime_t::year.
Referenced by main().
|
nodiscard |
Read RCR1 IRQ enable bits.
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().
|
nodiscard |
Start the RTC in 24-hour calendar mode.
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().
|
nodiscard |
Write the calendar registers.
| [in] | dt | Date/time to install (BCD-encoded internally). |
Definition at line 343 of file ra8_rtc.c.
References ra8_rtc_datetime_t::day, ra8_rtc_datetime_t::hour, internal_bin_to_bcd(), internal_wait_bit(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_rcr2_bit_start, k_ra8_rtc_year_base, ra8_rtc_datetime_t::minute, ra8_rtc_datetime_t::month, RA8_CHECK_NULL_PTR, ra8_log_info_val, ra8_rtc(), r_rtc_regs_t::RCR2, r_rtc_regs_t::RDAYCNT, r_rtc_regs_t::RHRCNT, r_rtc_regs_t::RMINCNT, r_rtc_regs_t::RMONCNT, r_rtc_regs_t::RSECCNT, r_rtc_regs_t::RWKCNT, r_rtc_regs_t::RYRCNT, s_tag, ra8_rtc_datetime_t::second, ra8_rtc_datetime_t::weekday, and ra8_rtc_datetime_t::year.
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().
|
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.
| [in] | alarm | See header. |
| k_ra8_ok | Alarm written. |
| k_ra8_err_null_ptr | alarm is NULL. |
| k_ra8_err_invalid_arg | Out-of-range hour/min/sec. |
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().
|
nodiscard |
Enable one or more RTC IRQ sources via RCR1.
Definition at line 498 of file ra8_rtc.c.
References k_ra8_ok, k_ra8_rtc_irq_all, ra8_rtc(), and r_rtc_regs_t::RCR1.
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().
|
static |
Definition at line 484 of file ra8_rtc.c.
Referenced by ra8_rtc_attach_handler(), ra8_rtc_deinit(), and ra8_rtc_dispatch().