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

Low Power Asynchronous General Purpose Timer driver. More...

#include "ra8_agt.h"
#include <stdint.h>
#include "ra8_agt_regs.h"
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_log.h"
#include "ra8_mstp.h"
Include dependency graph for ra8_agt.c:

Go to the source code of this file.

Enumerations

enum  ra8_agt_mstp_limit_t : uint8_t { k_ra8_agt_mstp_id_count = 2U }
 Number of AGT channels that have dedicated MSTPD bits. More...
enum  ra8_agt_cascade_split_t : uint32_t {
  k_ra8_agt_cascade_lo_mask = 0xFFFFU ,
  k_ra8_agt_cascade_hi_shift = 16U
}
 Shift / mask used to split the cascade 32-bit reload. More...

Functions

static ra8_err_t internal_agt_mstp_acquire (uint8_t channel)
 Acquire the per-channel AGT MSTP reference exactly once (issue #68).
static ra8_err_t internal_agt_mstp_release (uint8_t channel)
 Release the per-channel AGT MSTP reference if held (issue #68).
ra8_err_t ra8_agt_start_free_run (uint8_t channel, uint16_t reload)
 Start an AGT channel in free-running mode.
ra8_err_t ra8_agt_stop (uint8_t channel)
 Stop an AGT channel.
ra8_err_t ra8_agt_deinit (uint8_t channel)
 Tear down one AGT channel.
ra8_err_t ra8_agt_set_reload (uint8_t channel, uint16_t reload)
 Change the AGT reload value at runtime.
ra8_err_t ra8_agt_get_status (uint8_t channel, uint8_t *out_mask)
 Read the AGTCR status register.
ra8_err_t ra8_agt_attach_handler (ra8_agt_event_fn_t fn, void *ctx)
 Attach an AGT event callback (shared across channels).
void ra8_agt_dispatch (uint8_t channel)
 Dispatch an AGT event to the registered shared callback.
ra8_err_t ra8_agt_enter_stop (uint8_t channel)
 Put one AGT channel into MSTP-gated stop.
ra8_err_t ra8_agt_exit_stop (uint8_t channel)
 Exit MSTP-gated stop for one AGT channel.
static uint8_t internal_agt_pulse_agtioc_value (ra8_agt_output_polarity_t polarity)
 Translate the pulse-mode polarity enum into an AGTIOC mask.
static uint8_t internal_agt_pulse_agtcmsr_value (ra8_agt_pulse_compare_t compare)
 Build the AGTCMSR mask for a chosen compare-match output.
static void internal_agt_pulse_program_compare (volatile r_agt_regs_t *reg, ra8_agt_pulse_compare_t compare, uint16_t duty)
 Programme the AGTCMA / AGTCMB compare register for pulse mode.
static ra8_err_t internal_agt_pulse_validate_cfg (const ra8_agt_pulse_cfg_t *cfg)
 Validate the enum members of a pulse-output config block.
static void internal_agt_pulse_program_registers (volatile r_agt_regs_t *reg, const ra8_agt_pulse_cfg_t *cfg)
 Write the AGT mode / I/O / compare-match registers for pulse output.
ra8_err_t ra8_agt_start_pulse_output (uint8_t channel, const ra8_agt_pulse_cfg_t *cfg)
 Arm one AGT channel in pulse-output / output-compare mode.
static ra8_err_t internal_agt_cascade_clock_to_tck (ra8_agt_cascade_clk_t clock, uint8_t *out_tck)
 Translate the cascade clock enum into an AGTMR1.TCK encoding.
static void internal_agt_cascade_arm_half (volatile r_agt_regs_t *reg, uint8_t tmr1, uint16_t reload)
 Reset and arm one cascade half in plain timer mode.
static ra8_err_t internal_agt_cascade_mstp_enable_both (void)
 Power on both halves of the cascade pair.
static void internal_agt_cascade_program_and_start (volatile r_agt_regs_t *lo, volatile r_agt_regs_t *hi, uint32_t reload32, uint8_t tck_lo)
 Programme both AGT halves and start them in cascade order.
static void internal_agt_cascade_install_callback (const ra8_agt_cascade_cfg_t *cfg)
 Install the optional cascade-completion callback.
static ra8_err_t internal_agt_cascade_resolve_halves (volatile r_agt_regs_t **out_lo, volatile r_agt_regs_t **out_hi)
 Fetch and validate both AGT register windows for cascade.
ra8_err_t ra8_agt_start_cascade (const ra8_agt_cascade_cfg_t *cfg)
 Cascade AGT0 and AGT1 into a 32-bit virtual down-counter.

Variables

static const char * s_tag = "AGT"
static const ra8_mstp_t s_agt_mstp_table [k_ra8_agt_mstp_id_count]
 Channel-index -> MSTP id lookup for AGT0 / AGT1.
static bool s_agt_mstp_held [k_ra8_agt_mstp_id_count]
 Per-channel "this driver holds the MSTP reference" latch (AGT0/AGT1).
static ra8_agt_event_fn_t s_agt_fn
static void * s_agt_ctx

Detailed Description

Low Power Asynchronous General Purpose Timer driver.

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

driver for the RA8D2 AGT block (10 channels total; only AGT0 / AGT1 have dedicated MSTPD bits, the rest share the sub-clock path). Programmes an AGT channel as a free-running 16-bit down-counter clocked from PCLKB. Used as a coarse tick source on boards where SysTick is not desirable. Every register access carries a HUM Ch 24 citation.

Definition in file ra8_agt.c.

Enumeration Type Documentation

◆ ra8_agt_cascade_split_t

enum ra8_agt_cascade_split_t : uint32_t

Shift / mask used to split the cascade 32-bit reload.

Enumerator
k_ra8_agt_cascade_lo_mask 

RA8 AGT cascade lo mask.

k_ra8_agt_cascade_hi_shift 

RA8 AGT cascade hi shift.

Definition at line 770 of file ra8_agt.c.

◆ ra8_agt_mstp_limit_t

enum ra8_agt_mstp_limit_t : uint8_t

Number of AGT channels that have dedicated MSTPD bits.

HUM Ch 11.2.9 p 448 only lists MSTPD4 / MSTPD5 for AGT1 / AGT0. The chip lays out 10 AGT channels total but only the first two are ref-counted through ra8_mstp; additional channels inherit their clock from the shared LOCO / sub-clock path.

Enumerator
k_ra8_agt_mstp_id_count 

RA8 AGT mstp ID count.

Definition at line 43 of file ra8_agt.c.

Function Documentation

◆ internal_agt_cascade_arm_half()

void internal_agt_cascade_arm_half ( volatile r_agt_regs_t * reg,
uint8_t tmr1,
uint16_t reload )
static

Reset and arm one cascade half in plain timer mode.

Writes AGTCR=0 (stop), AGTMR1=tmr1 (timer mode + TCK encoding), AGTMR2=0 (no CKS divide), AGT=reload, then leaves TSTART low so the caller can start both halves in the correct order.

Parameters
[in,out]regAGT channel window (non-NULL).
[in]tmr1Packed AGTMR1 byte (TMOD timer-mode + TCK).
[in]reload16-bit counter reload value.
Precondition
reg points at a valid AGT channel window.
tmr1 encodes TMOD = timer-mode plus a valid TCK value.
Postcondition
AGT counter is loaded with reload.
Counter is still stopped (AGTCR.TSTART = 0).
Note
Not thread-safe; ISR-unsafe (touches MMIO).
Since
0.1.0

Definition at line 750 of file ra8_agt.c.

References r_agt_regs_t::AGT, r_agt_regs_t::AGTCMSR, r_agt_regs_t::AGTCR, r_agt_regs_t::AGTIOC, r_agt_regs_t::AGTMR1, and r_agt_regs_t::AGTMR2.

Referenced by internal_agt_cascade_program_and_start().

◆ internal_agt_cascade_clock_to_tck()

ra8_err_t internal_agt_cascade_clock_to_tck ( ra8_agt_cascade_clk_t clock,
uint8_t * out_tck )
static

Translate the cascade clock enum into an AGTMR1.TCK encoding.

Maps ra8_agt_cascade_clk_t onto the AGTMR1.TCK[2:0] bit field (HUM Ch 24.2.5 p 1168). Only the three PCLKB-derived options are supported – AGT1 always uses TCK=101b (AGT0 underflow) so its source does not come from this helper.

Parameters
[in]clockCascade clock-source enum value.
[out]out_tckReceives the bit-shifted TCK encoding.
Returns
ra8_err_t error code.
Return values
k_ra8_ok*out_tck holds the encoded TCK value.
k_ra8_err_invalid_argclock was out of range.
Precondition
out_tck non-NULL.
Caller will consume *out_tck only on a k_ra8_ok return.
Postcondition
*out_tck is unchanged when the function returns non-OK.
No global state is touched.
Note
Not thread-safe; pure mapping helper.
Since
0.1.0

Definition at line 710 of file ra8_agt.c.

References k_ra8_agt_agtmr1_tck_pclkb, k_ra8_agt_agtmr1_tck_pclkb_div2, k_ra8_agt_agtmr1_tck_pclkb_div8, k_ra8_agt_cascade_clk_pclkb, k_ra8_agt_cascade_clk_pclkb_div2, k_ra8_agt_cascade_clk_pclkb_div8, k_ra8_err_invalid_arg, k_ra8_ok, and RA8_INTERNAL.

Referenced by ra8_agt_start_cascade().

◆ internal_agt_cascade_install_callback()

void internal_agt_cascade_install_callback ( const ra8_agt_cascade_cfg_t * cfg)
static

Install the optional cascade-completion callback.

Copies cfg->on_underflow and cfg->ctx into the global AGT dispatch slot when cfg->on_underflow is non-NULL. NULL is treated as "leave the previously-installed handler in place" so cascade callers do not stomp on a sibling AGT-channel attach.

Parameters
[in]cfgCascade configuration block (non-NULL).
Precondition
cfg is non-NULL.
IRQs masked or single-threaded init context.
Postcondition
When cfg->on_underflow != nullptr the global slot is overwritten.
When cfg->on_underflow == nullptr the slot is unchanged.
Note
Not thread-safe; shared module-static slot.
Since
0.1.0

Definition at line 878 of file ra8_agt.c.

References ra8_agt_cascade_cfg_t::ctx, ra8_agt_cascade_cfg_t::on_underflow, RA8_INTERNAL, s_agt_ctx, and s_agt_fn.

Referenced by ra8_agt_start_cascade().

◆ internal_agt_cascade_mstp_enable_both()

ra8_err_t internal_agt_cascade_mstp_enable_both ( void )
static

Power on both halves of the cascade pair.

Reference-counts the MSTP bits for AGT0 and AGT1 in order so the peripheral clock arrives before any register write touches them (HUM Ch 11.2.9 "MSTPCRD : Module Stop Control Register D" p 448).

Returns
ra8_err_t error code.
Return values
k_ra8_okBoth MSTP bits are ref-incremented.
k_ra8_err_hw_timeoutra8_mstp_enable read-back failed.
Precondition
IRQs masked or init context.
ra8_mstp_init has been called previously.
Postcondition
Both MSTP bits are now ref-incremented on success.
Caller releases via ra8_agt_deinit per channel.
Note
Not thread-safe; MSTP refcount table is shared with other drivers.
Since
0.1.0

Definition at line 797 of file ra8_agt.c.

References internal_agt_mstp_acquire(), k_ra8_agt_cascade_hi_channel, k_ra8_agt_cascade_lo_channel, k_ra8_ok, RA8_INTERNAL, RA8_RETURN_ON_ERROR, and s_tag.

Referenced by ra8_agt_start_cascade().

◆ internal_agt_cascade_program_and_start()

void internal_agt_cascade_program_and_start ( volatile r_agt_regs_t * lo,
volatile r_agt_regs_t * hi,
uint32_t reload32,
uint8_t tck_lo )
static

Programme both AGT halves and start them in cascade order.

Splits reload32 into the two 16-bit reload values, configures AGT0 in plain timer mode and AGT1 with TCK=101b (AGT0 underflow), then sets TSTART on AGT1 first and AGT0 second so AGT1 is ready to sample on the first cycle (HUM Ch 24.2.5 p 1168 note 6).

Parameters
[in,out]loAGT0 channel window.
[in,out]hiAGT1 channel window.
[in]reload3232-bit virtual reload value.
[in]tck_loPre-encoded AGTMR1 TCK byte for the AGT0 half.
Precondition
Both MSTP bits are enabled.
tck_lo encodes the AGTMR1 TCK field for the AGT0 half.
Postcondition
Both AGTCR.TSTART = 1; cascade is live.
AGT1 begins counting on the first AGT0 underflow.
Note
Not thread-safe; ISR-unsafe (touches MMIO).
Since
0.1.0

Definition at line 831 of file ra8_agt.c.

References r_agt_regs_t::AGTCR, internal_agt_cascade_arm_half(), k_ra8_agt_agtcr_tstart_msk, k_ra8_agt_agtmr1_tck_agt0_underflow, k_ra8_agt_agtmr1_tmod_timer, k_ra8_agt_cascade_hi_shift, k_ra8_agt_cascade_lo_mask, and RA8_INTERNAL.

Referenced by ra8_agt_start_cascade().

◆ internal_agt_cascade_resolve_halves()

ra8_err_t internal_agt_cascade_resolve_halves ( volatile r_agt_regs_t ** out_lo,
volatile r_agt_regs_t ** out_hi )
static

Fetch and validate both AGT register windows for cascade.

Cascade only works on the AGT0 / AGT1 pair (HUM Ch 24.1 Table 24.1 p 1164). This helper resolves the two channel pointers and rejects any host where the fake window is missing.

Parameters
[out]out_loReceives the AGT0 channel window pointer.
[out]out_hiReceives the AGT1 channel window pointer.
Returns
ra8_err_t error code.
Return values
k_ra8_okBoth pointers populated.
k_ra8_err_null_ptrra8_agt(0) or ra8_agt(1) returned NULL.
Precondition
out_lo / out_hi non-NULL.
Caller will inspect the return value.
Postcondition
On OK return both *out_lo and *out_hi are non-NULL.
No MMIO is touched.
Note
Not thread-safe; pure resolver.
Since
0.1.0

Definition at line 910 of file ra8_agt.c.

References k_ra8_agt_cascade_hi_channel, k_ra8_agt_cascade_lo_channel, k_ra8_ok, ra8_agt(), RA8_CHECK_NULL_PTR, RA8_INTERNAL, and s_tag.

Referenced by ra8_agt_start_cascade().

◆ internal_agt_mstp_acquire()

ra8_err_t internal_agt_mstp_acquire ( uint8_t channel)
static

Acquire the per-channel AGT MSTP reference exactly once (issue #68).

Idempotent: enables the AGT0/AGT1 module stop reference only when the channel does not already hold it, so a periodic re-arm (stop + start every underflow) never leaks a fresh ra8_mstp_enable reference. Channels 2..9 have no dedicated MSTP bit and are a no-op. Early returns keep every decision a single relational test (no compound boolean).

Parameters
[in]channelAGT channel index (0..9).
Returns
ra8_err_t outcome.
Return values
k_ra8_okReference held (already, or newly acquired), or channel has no dedicated MSTP bit.
k_ra8_err_hw_timeoutra8_mstp_enable read-back failed (target).
Precondition
IRQs masked or single-threaded init context.
channel is a valid AGT channel.
Postcondition
On k_ra8_ok for channels 0/1, s_agt_mstp_held[channel] is true.
No module-stop write is issued when the reference is already held.
Note
Not thread-safe.
Since
0.1.0

Definition at line 98 of file ra8_agt.c.

References k_ra8_agt_mstp_id_count, k_ra8_ok, RA8_INTERNAL, ra8_mstp_enable(), s_agt_mstp_held, and s_agt_mstp_table.

Referenced by internal_agt_cascade_mstp_enable_both(), ra8_agt_exit_stop(), ra8_agt_start_free_run(), and ra8_agt_start_pulse_output().

◆ internal_agt_mstp_release()

ra8_err_t internal_agt_mstp_release ( uint8_t channel)
static

Release the per-channel AGT MSTP reference if held (issue #68).

Mirror of internal_agt_mstp_acquire: drops the AGT0/AGT1 module-stop reference only when the channel currently holds it, so a stop after a never-acquired start (or a double release) cannot underflow the ra8_mstp refcount. Channels 2..9 are a no-op. Early returns keep every decision single-condition.

Parameters
[in]channelAGT channel index (0..9).
Returns
ra8_err_t outcome.
Return values
k_ra8_okReference released, or nothing was held.
k_ra8_err_invalid_statera8_mstp_disable underflow (defensive).
Precondition
IRQs masked or single-threaded init context.
channel is a valid AGT channel.
Postcondition
On k_ra8_ok for channels 0/1, s_agt_mstp_held[channel] is false.
No module-stop write is issued when no reference is held.
Note
Not thread-safe.
Since
0.1.0

Definition at line 138 of file ra8_agt.c.

References k_ra8_agt_mstp_id_count, k_ra8_ok, RA8_INTERNAL, ra8_mstp_disable(), s_agt_mstp_held, and s_agt_mstp_table.

Referenced by ra8_agt_deinit(), and ra8_agt_enter_stop().

◆ internal_agt_pulse_agtcmsr_value()

uint8_t internal_agt_pulse_agtcmsr_value ( ra8_agt_pulse_compare_t compare)
static

Build the AGTCMSR mask for a chosen compare-match output.

HUM Ch 24.2.9 "AGTCMSR" p 1172. Enables compare-match A or B with the matching pin-output enable and "start-high / normal" polarity. compare = none returns zero so the caller leaves the register cleared.

Parameters
[in]compareOne of k_ra8_agt_pulse_compare_none, k_ra8_agt_pulse_compare_a, or k_ra8_agt_pulse_compare_b.
Returns
uint8_t bit-mask suitable for direct write to AGTCMSR.
Return values
0x00none (no compare-match output armed).
0x03compare A (TCMEA | TOEA).
0x30compare B (TCMEB | TOEB).
Precondition
compare is one of the three enumerators.
Caller will use the result only as an AGTCMSR value.
Postcondition
Returned byte has either none / A-side / B-side bits set.
No global state is touched.
Note
Not thread-safe; pure ALU helper.
Since
0.1.0

Definition at line 497 of file ra8_agt.c.

References k_ra8_agt_agtcmsr_tcmea_msk, k_ra8_agt_agtcmsr_tcmeb_msk, k_ra8_agt_agtcmsr_toea_msk, k_ra8_agt_agtcmsr_toeb_msk, k_ra8_agt_pulse_compare_a, k_ra8_agt_pulse_compare_b, and RA8_INTERNAL.

Referenced by internal_agt_pulse_program_registers().

◆ internal_agt_pulse_agtioc_value()

uint8_t internal_agt_pulse_agtioc_value ( ra8_agt_output_polarity_t polarity)
static

Translate the pulse-mode polarity enum into an AGTIOC mask.

HUM Ch 24.2.7 "AGTIOC : AGT I/O Control Register" p 1170 + Table 24.3 p 1171 ("Pulse output mode": TEDGSEL=0 -> start high, TEDGSEL=1 -> start low). Always returns TOE = 1 so the AGTOn pin is enabled when pulse mode is armed.

Parameters
[in]polarityOne of k_ra8_agt_output_polarity_active_high or k_ra8_agt_output_polarity_active_low.
Returns
uint8_t bit-mask suitable for direct write to AGTIOC.
Return values
0x04active-low (TOE only, TEDGSEL cleared).
0x05active-high (TOE | TEDGSEL).
Precondition
polarity is one of the two enumerators.
Caller will use the result only as an AGTIOC value.
Postcondition
Returned byte has TOE set (bit 2).
No global state is touched.
Note
Not thread-safe; pure ALU helper.
Since
0.1.0

Definition at line 461 of file ra8_agt.c.

References k_ra8_agt_agtioc_tedgsel_msk, k_ra8_agt_agtioc_toe_msk, k_ra8_agt_output_polarity_active_high, and RA8_INTERNAL.

Referenced by internal_agt_pulse_program_registers().

◆ internal_agt_pulse_program_compare()

void internal_agt_pulse_program_compare ( volatile r_agt_regs_t * reg,
ra8_agt_pulse_compare_t compare,
uint16_t duty )
static

Programme the AGTCMA / AGTCMB compare register for pulse mode.

HUM Ch 24.2.2 "AGTCMA : AGT Compare Match A Register" p 1166 and HUM Ch 24.2.3 "AGTCMB : AGT Compare Match B Register" p 1166. The unselected register is parked at 0xFFFF as per the spec note.

Parameters
[in,out]regAGT channel window (non-NULL).
[in]compareCompare-match selector (see enum).
[in]duty16-bit duty value loaded into the selected compare register; the unselected register is loaded with 0xFFFF (parked).
Precondition
reg points at a valid AGT channel window.
compare is one of the three enumerators.
Postcondition
AGTCMA holds duty when compare == A, else 0xFFFF.
AGTCMB holds duty when compare == B, else 0xFFFF.
Note
Not thread-safe; ISR-unsafe (touches MMIO).
Since
0.1.0

Definition at line 531 of file ra8_agt.c.

References r_agt_regs_t::AGTCMA, r_agt_regs_t::AGTCMB, k_ra8_agt_compare_parked_value, k_ra8_agt_pulse_compare_a, k_ra8_agt_pulse_compare_b, and RA8_INTERNAL.

Referenced by internal_agt_pulse_program_registers().

◆ internal_agt_pulse_program_registers()

void internal_agt_pulse_program_registers ( volatile r_agt_regs_t * reg,
const ra8_agt_pulse_cfg_t * cfg )
static

Write the AGT mode / I/O / compare-match registers for pulse output.

Programmes everything except AGTCR.TSTART (the caller flips that last). Each register write is preceded by a HUM citation comment.

Parameters
[in,out]regAGT channel window (non-NULL).
[in]cfgValidated pulse-output configuration.
Precondition
reg points at a valid AGT channel window.
cfg has already been validated by internal_agt_pulse_validate_cfg.
Postcondition
AGT is loaded with the period, compare-match regs hold duty or 0xFFFF.
Counter is still stopped (AGTCR.TSTART = 0).
Note
Not thread-safe; ISR-unsafe (touches MMIO).
Since
0.1.0

Definition at line 600 of file ra8_agt.c.

References r_agt_regs_t::AGT, r_agt_regs_t::AGTCMSR, r_agt_regs_t::AGTCR, r_agt_regs_t::AGTIOC, r_agt_regs_t::AGTMR1, r_agt_regs_t::AGTMR2, ra8_agt_pulse_cfg_t::compare, ra8_agt_pulse_cfg_t::duty, internal_agt_pulse_agtcmsr_value(), internal_agt_pulse_agtioc_value(), internal_agt_pulse_program_compare(), k_ra8_agt_agtmr1_tmod_pulse_output, ra8_agt_pulse_cfg_t::period, ra8_agt_pulse_cfg_t::polarity, and RA8_INTERNAL.

Referenced by ra8_agt_start_pulse_output().

◆ internal_agt_pulse_validate_cfg()

ra8_err_t internal_agt_pulse_validate_cfg ( const ra8_agt_pulse_cfg_t * cfg)
static

Validate the enum members of a pulse-output config block.

The two pulse-mode enums (compare and polarity) are passed by the caller and so must be sanity-checked before being mapped onto register-mask values. mode is informational and is checked at the polling layer in the demo, not here.

Parameters
[in]cfgConfiguration block (caller has already null-checked).
Returns
ra8_err_t error code.
Return values
k_ra8_okBoth enum fields hold a documented value.
k_ra8_err_invalid_argcompare or polarity out of range.
Precondition
cfg is non-NULL.
Caller will inspect the return value.
Postcondition
No global or MMIO state is touched.
Returns OK only when both enum fields hold a documented value.
Note
Not thread-safe; pure validator.
Since
0.1.0

Definition at line 566 of file ra8_agt.c.

References ra8_agt_pulse_cfg_t::compare, k_ra8_agt_output_polarity_active_high, k_ra8_agt_output_polarity_active_low, k_ra8_agt_pulse_compare_a, k_ra8_agt_pulse_compare_b, k_ra8_agt_pulse_compare_none, k_ra8_err_invalid_arg, k_ra8_ok, ra8_agt_pulse_cfg_t::polarity, and RA8_INTERNAL.

Referenced by ra8_agt_start_pulse_output().

◆ ra8_agt_attach_handler()

ra8_err_t ra8_agt_attach_handler ( ra8_agt_event_fn_t fn,
void * ctx )
nodiscard

Attach an AGT event callback (shared across channels).

Stores fn / ctx in module-static storage. The same handler fires for every AGT channel that is dispatched through ra8_agt_dispatch; the dispatcher passes the channel index back to the handler so multi-channel callers can route on it.

Parameters
[in]fnCallback (NULL clears the slot).
[in]ctxOpaque pointer passed back to fn.
Returns
ra8_err_t error code.
Return values
k_ra8_okSlot updated.
Precondition
IRQs masked or single-threaded init context.
Caller is happy to share the single global slot with other AGT users.
Postcondition
Subsequent ra8_agt_dispatch calls invoke fn(ctx, ch).
Previous callback (if any) is overwritten.
Note
Not thread-safe.
Since
0.1.0

Definition at line 324 of file ra8_agt.c.

References k_ra8_ok, s_agt_ctx, and s_agt_fn.

◆ ra8_agt_deinit()

ra8_err_t ra8_agt_deinit ( uint8_t channel)
nodiscard

Tear down one AGT channel.

Clears AGTCR (HUM Ch 24.2.4 "AGTCR : AGT Control Register", p 1167) so the counter stops, then drops the matching MSTP reference for AGT0 / AGT1. Channels 2..9 share the LOCO / sub-clock path, so no MSTP work is required for them.

Parameters
[in]channelAGT channel index (0..9).
Returns
ra8_err_t error code.
Return values
k_ra8_okChannel stopped, MSTP released.
k_ra8_err_invalid_argchannel >= 10 (no register window).
k_ra8_err_invalid_statera8_mstp_disable underflow.
Precondition
IRQs masked or single-threaded init context.
ra8_agt_start_free_run (or sibling start) was previously called for channel.
Postcondition
AGTCR for the channel reads as 0 (counter stopped).
MSTP reference for AGT0/AGT1 has been decremented when the channel index falls inside the dedicated MSTP window.
Note
Not thread-safe.
Since
0.1.0

Definition at line 221 of file ra8_agt.c.

References r_agt_regs_t::AGTCR, internal_agt_mstp_release(), ra8_agt(), RA8_CHECK_NULL_PTR, and s_tag.

◆ ra8_agt_dispatch()

void ra8_agt_dispatch ( uint8_t channel)

Dispatch an AGT event to the registered shared callback.

Dispatch an AGT event – fire callback.

Called from the AGT compare-match / underflow ISR (HUM Ch 24 "Asynchronous General Purpose Timer", p 1167). Silently no-ops when channel is out of range or no handler is attached.

Parameters
[in]channelAGT channel (0..9) whose ISR fired.
Precondition
Called from ISR context or a host-test driver.
channel < 10.
Postcondition
Stored callback (if any) has been invoked exactly once.
No AGT register state is mutated.
Note
Not thread-safe.
Since
0.1.0

Definition at line 351 of file ra8_agt.c.

References ra8_agt(), s_agt_ctx, and s_agt_fn.

◆ ra8_agt_enter_stop()

ra8_err_t ra8_agt_enter_stop ( uint8_t channel)
nodiscard

Put one AGT channel into MSTP-gated stop.

Put one channel into MSTP-gated stop.

Clears AGTCR (HUM Ch 24.2.4 "AGTCR : AGT Control Register", p 1167) so the counter halts, then for AGT0 / AGT1 drops the dedicated MSTPD bit (HUM Ch 11.2.9 "MSTPCRD", p 448) so the peripheral clock can gate.

Parameters
[in]channelAGT channel index (0..9).
Returns
ra8_err_t error code.
Return values
k_ra8_okChannel halted, MSTP gated.
k_ra8_err_invalid_argchannel >= 10.
k_ra8_err_invalid_statera8_mstp_disable underflow on the shared MSTP id.
Precondition
IRQs masked or single-threaded init context.
Channel was previously started via ra8_agt_start_free_run.
Postcondition
AGTCR for the channel reads as 0.
For AGT0/AGT1 the MSTPCRD bit has been ref-decremented.
Note
Not thread-safe.
Since
0.1.0

Definition at line 389 of file ra8_agt.c.

References r_agt_regs_t::AGTCR, internal_agt_mstp_release(), ra8_agt(), RA8_CHECK_NULL_PTR, and s_tag.

◆ ra8_agt_exit_stop()

ra8_err_t ra8_agt_exit_stop ( uint8_t channel)
nodiscard

Exit MSTP-gated stop for one AGT channel.

Exit MSTP-gated stop.

Re-asserts the MSTP reference for AGT0 / AGT1 (HUM Ch 11.2.9 "MSTPCRD", p 448) so the channel sees its peripheral clock again. Channels 2..9 share the LOCO / sub-clock path and become a no-op here. The caller is expected to reissue a start request next.

Parameters
[in]channelAGT channel index (0..9).
Returns
ra8_err_t error code.
Return values
k_ra8_okMSTP re-enabled (or no-op for shared).
k_ra8_err_invalid_argchannel >= 10.
k_ra8_err_hw_timeoutra8_mstp_enable read-back failure.
Precondition
IRQs masked or single-threaded init context.
Channel was previously placed in stop via ra8_agt_enter_stop.
Postcondition
For AGT0/AGT1 the matching MSTPCRD bit has been ref-incremented.
Channel is ready to be restarted.
Note
Not thread-safe.
Since
0.1.0

Definition at line 423 of file ra8_agt.c.

References internal_agt_mstp_acquire(), k_ra8_err_invalid_arg, and ra8_agt().

◆ ra8_agt_get_status()

ra8_err_t ra8_agt_get_status ( uint8_t channel,
uint8_t * out_mask )
nodiscard

Read the AGTCR status register.

Returns the raw 8-bit AGTCR value (HUM Ch 24.2.4 "AGTCR : AGT Control Register", p 1167) so callers can inspect the TSTART / TCSTF / TUNDF / TEDGF flags without leaking the register layout.

Parameters
[in]channelAGT channel index (0..9).
[out]out_maskReceives the AGTCR snapshot.
Returns
ra8_err_t error code.
Return values
k_ra8_okStatus read into *out_mask.
k_ra8_err_null_ptrout_mask was NULL.
k_ra8_err_invalid_argchannel >= 10.
Precondition
out_mask non-NULL.
Caller has previously powered or started the channel.
Postcondition
*out_mask reflects live AGTCR contents.
No AGT register state is mutated.
Note
Not thread-safe.
Since
0.1.0

Definition at line 289 of file ra8_agt.c.

References r_agt_regs_t::AGTCR, k_ra8_ok, ra8_agt(), RA8_CHECK_NULL_PTR, and s_tag.

Referenced by main().

◆ ra8_agt_set_reload()

ra8_err_t ra8_agt_set_reload ( uint8_t channel,
uint16_t reload )
nodiscard

Change the AGT reload value at runtime.

Writes reload into the AGT counter register (HUM Ch 24.2.1 "AGT : AGT Counter", p 1165). Valid only on a stopped channel or while the counter has just been refreshed.

Parameters
[in]channelAGT channel index (0..9).
[in]reload16-bit reload value.
Returns
ra8_err_t error code.
Return values
k_ra8_okCounter rewritten.
k_ra8_err_invalid_argchannel >= 10.
Precondition
IRQs masked or single-threaded init context.
ra8_agt_start_free_run was previously called for channel or the channel has been initialized by a sibling driver.
Postcondition
Counter holds reload.
Channel state (running / stopped) is unchanged.
Note
Not thread-safe.
Since
0.1.0

Definition at line 255 of file ra8_agt.c.

References r_agt_regs_t::AGT, k_ra8_ok, ra8_agt(), RA8_CHECK_NULL_PTR, and s_tag.

◆ ra8_agt_start_cascade()

ra8_err_t ra8_agt_start_cascade ( const ra8_agt_cascade_cfg_t * cfg)
nodiscard

Cascade AGT0 and AGT1 into a 32-bit virtual down-counter.

Implementation of the public API declared in ra8_agt.h. Validates the clock enum, ref-counts the AGT0 / AGT1 MSTP bits, splits the 32-bit reload into two 16-bit halves, programmes both channels in timer mode (AGT1 with TCK=101b "AGT0 underflow", HUM Ch 24.2.5 p 1168 note 6), then starts AGT1 first so it samples the very first AGT0 underflow.

Parameters
[in]cfgCascade configuration block; must not be NULL.
Returns
ra8_err_t error code.
Return values
k_ra8_okAGT0 + AGT1 armed as a 32-bit cascade.
k_ra8_err_null_ptrcfg NULL or AGT0/AGT1 window missing.
k_ra8_err_invalid_argcfg->clock enum out of range.
k_ra8_err_hw_timeoutMSTP enable read-back failed.
Precondition
IRQs masked or single-threaded init context.
Caller has not separately armed AGT0 or AGT1.
Postcondition
AGT0.AGTCR.TSTART = 1; AGT1.AGTCR.TSTART = 1.
Global handler slot points at cfg->on_underflow if non-NULL.
Note
Not thread-safe; pair with IRQ masking.
Since
0.1.0

Definition at line 949 of file ra8_agt.c.

References ra8_agt_cascade_cfg_t::clock, internal_agt_cascade_clock_to_tck(), internal_agt_cascade_install_callback(), internal_agt_cascade_mstp_enable_both(), internal_agt_cascade_program_and_start(), internal_agt_cascade_resolve_halves(), k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_log_info_val, RA8_RETURN_ON_ERROR, ra8_agt_cascade_cfg_t::reload32, and s_tag.

Referenced by internal_arm().

◆ ra8_agt_start_free_run()

ra8_err_t ra8_agt_start_free_run ( uint8_t channel,
uint16_t reload )
nodiscard

Start an AGT channel in free-running mode.

Parameters
[in]channelAGT channel (0..9).
[in]reload16-bit reload value (counter starts here and counts down toward zero).
Returns
ra8_err_t error code.
Since
0.1.0

Definition at line 151 of file ra8_agt.c.

References r_agt_regs_t::AGT, r_agt_regs_t::AGTCR, r_agt_regs_t::AGTMR1, r_agt_regs_t::AGTMR2, internal_agt_mstp_acquire(), k_ra8_ok, ra8_agt(), RA8_CHECK_NULL_PTR, ra8_log_info_val, RA8_RETURN_ON_ERROR, and s_tag.

Referenced by internal_agt_periodic_arm().

◆ ra8_agt_start_pulse_output()

ra8_err_t ra8_agt_start_pulse_output ( uint8_t channel,
const ra8_agt_pulse_cfg_t * cfg )
nodiscard

Arm one AGT channel in pulse-output / output-compare mode.

Start an AGT channel in pulse-output / output-compare mode.

Implementation of the public API declared in ra8_agt.h. Validates the config, ref-counts the MSTP bit for AGT0 / AGT1, programmes the mode + I/O + compare-match registers, then sets AGTCR.TSTART to 1. HUM Ch 24.3.4 "Pulse Output Mode" p 1177 is the spec reference; per-register citations sit on each write below.

Parameters
[in]channelAGT channel (0..9).
[in]cfgConfiguration block; must not be NULL.
Returns
ra8_err_t error code.
Return values
k_ra8_okChannel armed, AGTOn pin toggling.
k_ra8_err_null_ptrcfg NULL or channel >= 10.
k_ra8_err_invalid_argcfg->compare / cfg->polarity enum out of range.
Precondition
IRQs masked or single-threaded init context.
Pin function-select has already routed AGTOn etc.
Postcondition
AGTCR.TSTART reads 1 (counter running).
AGTMR1.TMOD reads 001b (pulse-output mode).
Note
Not thread-safe; pair with IRQ masking.
Since
0.1.0

Definition at line 649 of file ra8_agt.c.

References r_agt_regs_t::AGTCR, internal_agt_mstp_acquire(), internal_agt_pulse_program_registers(), internal_agt_pulse_validate_cfg(), k_ra8_agt_agtcr_tstart_msk, k_ra8_ok, ra8_agt_pulse_cfg_t::mode, ra8_agt(), RA8_CHECK_NULL_PTR, ra8_log_info_val, RA8_RETURN_ON_ERROR, and s_tag.

Referenced by internal_arm().

◆ ra8_agt_stop()

ra8_err_t ra8_agt_stop ( uint8_t channel)
nodiscard

Stop an AGT channel.

Parameters
[in]channelAGT channel (0..9).
Returns
ra8_err_t error code.
Since
0.1.0

Definition at line 177 of file ra8_agt.c.

References r_agt_regs_t::AGTCR, k_ra8_ok, ra8_agt(), RA8_CHECK_NULL_PTR, and s_tag.

Referenced by main().

Variable Documentation

◆ s_agt_ctx

void* s_agt_ctx
static

◆ s_agt_fn

◆ s_agt_mstp_held

bool s_agt_mstp_held[k_ra8_agt_mstp_id_count]
static

Per-channel "this driver holds the MSTP reference" latch (AGT0/AGT1).

AGT0/AGT1 must hold exactly ONE ra8_mstp_enable reference for the life of the channel, not one per (re)start. A free-run periodic demo re-arms every underflow via ra8_agt_stop + ra8_agt_start_free_run; without this latch each restart took a fresh MSTP reference, leaking the uint8_t refcount in ra8_mstp.c until it saturated at 255 and the 256th start returned k_ra8_err_invalid_state (issue #68 – "AGT free-run demos fault after exactly 255 periods"). The latch makes the MSTP acquire idempotent: a start only enables when the channel is not already held, and only deinit / enter-stop release it.

Definition at line 71 of file ra8_agt.c.

Referenced by internal_agt_mstp_acquire(), and internal_agt_mstp_release().

◆ s_agt_mstp_table

const ra8_mstp_t s_agt_mstp_table[k_ra8_agt_mstp_id_count]
static
Initial value:
= {
}
@ k_ra8_mstp_agt0
MSTPD5 AGT0.
@ k_ra8_mstp_agt1
MSTPD4 AGT1.

Channel-index -> MSTP id lookup for AGT0 / AGT1.

Definition at line 51 of file ra8_agt.c.

Referenced by internal_agt_mstp_acquire(), and internal_agt_mstp_release().

◆ s_tag

const char* s_tag = "AGT"
static

Definition at line 31 of file ra8_agt.c.