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

PWM Delay Generation Circuit (PDG) driver implementation. More...

#include "ra8_pdg.h"
#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_gpt_regs.h"
#include "ra8_hw_intrinsics.h"
#include "ra8_log.h"
#include "ra8_mstp.h"
#include "ra8_pdg_regs.h"
Include dependency graph for ra8_pdg.c:

Go to the source code of this file.

Enumerations

enum  ra8_pdg_internal_t : uint16_t {
  k_ra8_pdg_channel_mask_all = 0x000FU ,
  k_ra8_pdg_dll_lock_us = 20U ,
  k_ra8_pdg_busy_loops_per_us = 1000U ,
  k_ra8_pdg_post_reset_loops = 32U ,
  k_ra8_pdg_ns_per_sec_kilo = 1000U
}
 Driver-internal magic values (no magic numbers in functions). More...
enum  ra8_pdg_gtwp_key_t : uint32_t {
  k_ra8_pdg_gtwp_unlock = 0xA500U ,
  k_ra8_pdg_gtwp_lock = 0xA501U
}
 GPT GTWP write-protect key values (mirrors FSP). More...
enum  ra8_pdg_constraint_t : uint32_t {
  k_ra8_pdg_constraint_low_thresh = 2U ,
  k_ra8_pdg_constraint_high_pad = 2U
}
 Numeric thresholds in HUM Ch 23.4.2 Table 23.4. More...
enum  ra8_pdg_write_interval_t : uint32_t {
  k_ra8_pdg_pclka_mult = 6U ,
  k_ra8_pdg_gptclk_mult = 4U
}
 Multipliers in the HUM Ch 23.4.3 (p 1163) interval formula. More...
enum  ra8_pdg_unit_t : uint32_t { k_ra8_pdg_ns_per_sec = 1000000000UL }
 Units used by internal_freq_to_period_ns. More...

Functions

static bool internal_pdg_is_initialized (void)
 Probe live PDG registers to decide whether ra8_pdg_init has run successfully.
static void internal_busy_wait_us (uint16_t usec)
 Coarse software busy-wait used during init.
static void internal_wait_5_gtclk (void)
 Spin >= 5 GTCLK cycles after releasing DLYRST (HUM Fig 23.2).
static bool internal_frange_ok (ra8_pdg_frange_t f)
 Validate the FRANGE encoding.
static ra8_err_t internal_validate_cfg (const ra8_pdg_config_t *cfg)
 Validate a user-supplied PDG configuration.
static volatile uint16_t * internal_dly_cell (uint8_t channel, ra8_pdg_pin_t pin, ra8_pdg_edge_t edge)
 Compute a pointer to the right delay register cell.
static ra8_err_t internal_validate_slot (uint8_t channel, ra8_pdg_pin_t pin, ra8_pdg_edge_t edge, uint8_t code)
 Validate a (channel, pin, edge, code) tuple.
static uint32_t internal_freq_to_period_ns (uint32_t hz)
 Convert a frequency in Hz to a period in nanoseconds.
static void internal_program_dll (const ra8_pdg_config_t *cfg, ra8_pdg_frange_t frange_use)
 Run the six-step DLL bring-up sequence from HUM Fig 23.2.
ra8_err_t ra8_pdg_init (const ra8_pdg_config_t *cfg)
 Initialise the PDG block per HUM Figure 23.2 (p 1160).
ra8_err_t ra8_pdg_deinit (void)
 Tear down the PDG block (reset + module-stop).
ra8_err_t ra8_pdg_set_delay (uint8_t channel, ra8_pdg_pin_t pin, ra8_pdg_edge_t edge, uint8_t code)
 Set the per-edge fine delay for one PDG channel/pin/edge.
ra8_err_t ra8_pdg_get_delay (uint8_t channel, ra8_pdg_pin_t pin, ra8_pdg_edge_t edge, uint8_t *out_code)
 Read back the last-programmed delay code.
ra8_err_t ra8_pdg_set_delay_batch (const ra8_pdg_delay_entry_t *entries, uint8_t count)
 Atomically program a batch of (channel, pin, edge, code) delay updates.
ra8_err_t ra8_pdg_delay_ns_to_code (uint32_t delay_ns, uint32_t gptclk_hz, ra8_pdg_frange_t frange, uint8_t *out_code)
 Convert a desired pin-to-pin delay (in nanoseconds) to a DLY[6:0] code given a measured GPTCLK frequency.
ra8_err_t ra8_pdg_exit_stop (uint8_t channel)
 Power up one PDG channel (clear the GTDLYCR2.DLYENn bit).
ra8_err_t ra8_pdg_enter_stop (uint8_t channel)
 Power down one PDG channel (set GTDLYCR2.DLYENn).
ra8_err_t ra8_pdg_channel_bypass_set (uint8_t channel, uint8_t bypass)
 Set or clear the bypass bit for a channel.
ra8_err_t ra8_pdg_pin_disable (uint8_t channel, ra8_pdg_pin_t pin)
 Force a single A or B pin's delay to zero (per-pin disable) without touching the channel-level bypass / power bits.
ra8_err_t ra8_pdg_get_status (uint16_t *out)
 Read GTDLYCR packed into a status mask.
ra8_err_t ra8_pdg_get_status_full (ra8_pdg_status_full_t *out)
 Read a fully-decoded snapshot of GTDLYCR + GTDLYCR2.
ra8_err_t ra8_pdg_clear_status (uint16_t mask)
 Clear the soft-reset bit (DLYRST -> 0) and re-enable the DLL.
ra8_err_t ra8_pdg_attach_handler (ra8_pdg_event_fn_t fn, void *ctx)
 Attach an asynchronous PDG event callback.
void ra8_pdg_dispatch (void)
 Fire the registered handler.
ra8_err_t ra8_pdg_capture_start (const ra8_pdg_delay_entry_t *buf, uint8_t len)
 Stage a buffer of ra8_pdg_delay_entry_t records and arm them.
ra8_err_t ra8_pdg_capture_stop (void)
 Cancel any pending buffered apply and clear the completion latch.
ra8_err_t ra8_pdg_pick_frange (uint32_t gptclk_hz, ra8_pdg_frange_t *out)
 Auto-pick a FRANGE value from a measured GPTCLK frequency.
ra8_err_t ra8_pdg_set_frange (ra8_pdg_frange_t new_frange)
 Switch FRANGE at runtime, re-running the DLL re-lock sequence with the new band.
ra8_err_t ra8_pdg_bind_gpt_channel (uint8_t channel)
 Bind PDG channel n to its host GPT32n channel.
ra8_err_t ra8_pdg_unbind_gpt_channel (uint8_t channel)
 Reverse ra8_pdg_bind_gpt_channel, restoring write-protect.
ra8_err_t ra8_pdg_check_constraints (ra8_pdg_wave_mode_t mode, ra8_pdg_count_dir_t dir, uint32_t compare_match, uint32_t gtpr)
 Check Table 23.4 constraints before writing a delay register.
ra8_err_t ra8_pdg_required_write_ns (uint32_t pclka_hz, uint32_t gptclk_hz, uint32_t *out_ns)
 Compute the minimum register-write interval (HUM 23.4.3 p 1163).

Variables

static const char * s_tag = "PDG"
static ra8_pdg_event_fn_t s_pdg_event_fn
 Most recent callback registered by ra8_pdg_attach_handler.
static void * s_pdg_event_ctx
 Opaque pointer forwarded to s_pdg_event_fn.
static bool s_pdg_capture_in_flight
 Set true between ra8_pdg_capture_start and the callback fire.

Detailed Description

PWM Delay Generation Circuit (PDG) driver implementation.

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

Drives the PDG block per HUM Ch 23 (p 1152-1163). The driver exposes init/deinit, per-edge delay programming, batch programming, per-channel + per-pin power transition, status snapshot, runtime FRANGE switch with proper DLL re-lock, GPT0/1/2/3 binding helpers, compare-match-window constraint validation (HUM Ch 23.4.2 p 1162), register-write-interval helpers (HUM Ch 23.4.3 p 1163), and an event-callback hook.

The PDG sits between GPT320..GPT323 and the GTIOC0..GTIOC3 pads (HUM Figure 23.1 p 1153). Higher GPT channels (4..9) bypass the PDG entirely and the driver therefore caps the channel index at k_ra8_pdg_channel_count = 4.

State Machine

Definition in file ra8_pdg.c.

Enumeration Type Documentation

◆ ra8_pdg_constraint_t

enum ra8_pdg_constraint_t : uint32_t

Numeric thresholds in HUM Ch 23.4.2 Table 23.4.

Enumerator
k_ra8_pdg_constraint_low_thresh 

"<= 2" boundary.

k_ra8_pdg_constraint_high_pad 

"GTPR - 2" boundary pad.

Definition at line 107 of file ra8_pdg.c.

◆ ra8_pdg_gtwp_key_t

enum ra8_pdg_gtwp_key_t : uint32_t

GPT GTWP write-protect key values (mirrors FSP).

The upper byte holds the 0xA5 password; the LSB is the actual WP bit. 0xA500 = unlock (WP cleared), 0xA501 = lock.

Enumerator
k_ra8_pdg_gtwp_unlock 

Unlock GTWP (WP = 0).

k_ra8_pdg_gtwp_lock 

Re-lock GTWP (WP = 1).

Definition at line 97 of file ra8_pdg.c.

◆ ra8_pdg_internal_t

enum ra8_pdg_internal_t : uint16_t

Driver-internal magic values (no magic numbers in functions).

  • k_ra8_pdg_channel_mask_all is a 4-bit mask covering channels 0..3 – used to validate the user's cfg->channel_mask.
  • k_ra8_pdg_dll_lock_us matches the >= 20 us DLL-lock wait in HUM Figure 23.2 p 1160. The host-test build pads the spin with the ra8_hw_intrinsics no-op so it costs nothing.
  • k_ra8_pdg_busy_loops_per_us is a conservative lower bound on the loop count needed to absorb one microsecond at the Cortex-M85 1 GHz ceiling.
Enumerator
k_ra8_pdg_channel_mask_all 

Bits 0..3 – 4 channels.

k_ra8_pdg_dll_lock_us 

HUM Fig 23.2 wait.

k_ra8_pdg_busy_loops_per_us 

Conservative spin floor.

k_ra8_pdg_post_reset_loops 

>= 5 GTCLK cycles.

k_ra8_pdg_ns_per_sec_kilo 

Used in MHz->ns math.

Definition at line 80 of file ra8_pdg.c.

◆ ra8_pdg_unit_t

enum ra8_pdg_unit_t : uint32_t

Units used by internal_freq_to_period_ns.

Enumerator
k_ra8_pdg_ns_per_sec 

1 second in ns.

Definition at line 126 of file ra8_pdg.c.

◆ ra8_pdg_write_interval_t

enum ra8_pdg_write_interval_t : uint32_t

Multipliers in the HUM Ch 23.4.3 (p 1163) interval formula.

Enumerator
k_ra8_pdg_pclka_mult 

Period_of_PCLKA x 6.

k_ra8_pdg_gptclk_mult 

Period_of_GPTCLK x 4.

Definition at line 117 of file ra8_pdg.c.

Function Documentation

◆ internal_busy_wait_us()

void internal_busy_wait_us ( uint16_t usec)
static

Coarse software busy-wait used during init.

The HAL does not expose a microsecond busy-wait helper; the loop pads each iteration with ra8_hw_nop, which is a real nop on the target and a host no-op through the ra8_hw_intrinsics seam (the host has no timing requirement to meet).

Parameters
[in]usecMicroseconds to spin.
Precondition
usec >= 1.
Caller has IRQs masked (otherwise the wait stretches).
Postcondition
Approximately usec microseconds have elapsed.
Note
Re-entrant; touches no globals or MMIO.
Postcondition
Caller-visible state matches the documented contract.
Since
0.1.0

Definition at line 201 of file ra8_pdg.c.

References k_ra8_pdg_busy_loops_per_us, ra8_hw_nop(), and RA8_INTERNAL.

Referenced by internal_program_dll(), and ra8_pdg_set_frange().

◆ internal_dly_cell()

volatile uint16_t * internal_dly_cell ( uint8_t channel,
ra8_pdg_pin_t pin,
ra8_pdg_edge_t edge )
inlinestatic

Compute a pointer to the right delay register cell.

Centralises the (channel, pin, edge) -> register pointer math so the various write/read entry points share one decoder. Callers MUST have already validated the indices.

Definition at line 308 of file ra8_pdg.c.

References r_pdg_dly_pair_t::A, r_pdg_dly_pair_t::B, r_pdg_regs_t::GTDLYF, r_pdg_regs_t::GTDLYR, k_ra8_pdg_edge_rising, k_ra8_pdg_pin_a, pin, and ra8_pdg().

Referenced by ra8_pdg_get_delay(), ra8_pdg_pin_disable(), ra8_pdg_set_delay(), and ra8_pdg_set_delay_batch().

◆ internal_frange_ok()

bool internal_frange_ok ( ra8_pdg_frange_t f)
static

Validate the FRANGE encoding.

Returns
true if f is a legal FRANGE value (HUM 23.2.1 p 1154).

See implementation.

Parameters
[in]fSee implementation.
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 247 of file ra8_pdg.c.

References k_ra8_pdg_frange_155_300_mhz, k_ra8_pdg_frange_80_160_mhz, and RA8_INTERNAL.

Referenced by internal_validate_cfg(), ra8_pdg_delay_ns_to_code(), and ra8_pdg_set_frange().

◆ internal_freq_to_period_ns()

uint32_t internal_freq_to_period_ns ( uint32_t hz)
static

Convert a frequency in Hz to a period in nanoseconds.

Parameters
[in]hzFrequency in Hz, must be > 0.
Returns
Period in ns.

See implementation.

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 368 of file ra8_pdg.c.

References k_ra8_pdg_ns_per_sec, and RA8_INTERNAL.

Referenced by ra8_pdg_required_write_ns().

◆ internal_pdg_is_initialized()

bool internal_pdg_is_initialized ( void )
static

Probe live PDG registers to decide whether ra8_pdg_init has run successfully.

The PDG block is "initialized" when ra8_pdg_init has driven the DLL into the locked / running state, i.e. GTDLYCR.DLLEN == 1 and GTDLYCR.DLYRST == 0 (HUM Ch 23.2.1 p 1154). Reading the register directly avoids stale-static-flag bugs across host-test resets that wipe the fake MMIO without touching driver-side TU statics.

Returns
true when DLLEN is asserted and DLYRST is cleared.
Precondition
Module clock is reachable (caller did not unmap the PDG region).
Postcondition
No side effects.
Note
Re-entrant; reads two MMIO bits and derives a Boolean.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Since
0.1.0

Definition at line 153 of file ra8_pdg.c.

References r_pdg_regs_t::GTDLYCR, k_ra8_pdg_gtdlycr_mask_dllen, k_ra8_pdg_gtdlycr_mask_dlyrst, RA8_INTERNAL, and ra8_pdg().

Referenced by ra8_pdg_bind_gpt_channel(), ra8_pdg_channel_bypass_set(), ra8_pdg_pin_disable(), ra8_pdg_set_delay(), ra8_pdg_set_delay_batch(), and ra8_pdg_set_frange().

◆ internal_program_dll()

void internal_program_dll ( const ra8_pdg_config_t * cfg,
ra8_pdg_frange_t frange_use )
static

Run the six-step DLL bring-up sequence from HUM Fig 23.2.

HUM Ch 23.3.1 "Adjustments to the Timing of Rising and Falling Edges" p 1159 describes the exact sequence: latch FRANGE, enable DLL, wait >= 20 us for lock, release DLYRST, wait >= 5 GTCLK cycles, then turn off bypass for the channels selected by cfg->channel_mask.

Parameters
[in]cfgValidated config.
[in]frange_useFinal FRANGE band (post auto-tune resolution).
Precondition
Module clock is ungated (caller has already taken care of MSTP).
Postcondition
DLL is locked, requested channels active, others in bypass.
Note
Internal helper, not thread-safe.
Precondition
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Since
0.1.0

Definition at line 400 of file ra8_pdg.c.

References ra8_pdg_config_t::channel_mask, r_pdg_regs_t::GTDLYCR, r_pdg_regs_t::GTDLYCR2, internal_busy_wait_us(), internal_wait_5_gtclk(), k_ra8_pdg_dll_lock_us, k_ra8_pdg_gtdlycr2_shift_dlybs, k_ra8_pdg_gtdlycr_mask_dllen, k_ra8_pdg_gtdlycr_mask_dlyrst, k_ra8_pdg_gtdlycr_shift_frange, RA8_INTERNAL, and ra8_pdg().

Referenced by ra8_pdg_init().

◆ internal_validate_cfg()

ra8_err_t internal_validate_cfg ( const ra8_pdg_config_t * cfg)
static

Validate a user-supplied PDG configuration.

Parameters
[in]cfgCaller-supplied descriptor (must be non-null).
Returns
k_ra8_ok if the FRANGE / channel_mask combination is legal, else k_ra8_err_invalid_arg / k_ra8_err_out_of_range.
Precondition
cfg is non-null.
cfg lives in readable memory.
Postcondition
No side effects.

See implementation.

Return values
k_ra8_okOperation succeeded.
Postcondition
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 277 of file ra8_pdg.c.

References ra8_pdg_config_t::auto_tune, ra8_pdg_config_t::channel_mask, ra8_pdg_config_t::frange, ra8_pdg_config_t::gptclk_hz, internal_frange_ok(), k_ra8_err_invalid_arg, k_ra8_err_out_of_range, k_ra8_ok, k_ra8_pdg_channel_mask_all, k_ra8_pdg_freq_high_max_hz, k_ra8_pdg_freq_low_min_hz, and RA8_INTERNAL.

Referenced by ra8_pdg_init().

◆ internal_validate_slot()

ra8_err_t internal_validate_slot ( uint8_t channel,
ra8_pdg_pin_t pin,
ra8_pdg_edge_t edge,
uint8_t code )
static

Validate a (channel, pin, edge, code) tuple.

See implementation.

Parameters
[in]channelSee implementation.
[in]pinSee implementation.
[in]edgeSee implementation.
[in]codeSee 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 336 of file ra8_pdg.c.

References k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_pdg_channel_count, k_ra8_pdg_dly_max, k_ra8_pdg_edge_falling, k_ra8_pdg_edge_rising, k_ra8_pdg_pin_a, k_ra8_pdg_pin_b, and pin.

Referenced by ra8_pdg_get_delay(), ra8_pdg_set_delay(), and ra8_pdg_set_delay_batch().

◆ internal_wait_5_gtclk()

void internal_wait_5_gtclk ( void )
static

Spin >= 5 GTCLK cycles after releasing DLYRST (HUM Fig 23.2).

Precondition
Caller has IRQs masked.
Postcondition
At least 5 GTCLK cycles have elapsed.

See implementation.

Precondition
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 222 of file ra8_pdg.c.

References k_ra8_pdg_post_reset_loops, ra8_hw_nop(), and RA8_INTERNAL.

Referenced by internal_program_dll(), and ra8_pdg_set_frange().

◆ ra8_pdg_attach_handler()

ra8_err_t ra8_pdg_attach_handler ( ra8_pdg_event_fn_t fn,
void * ctx )
nodiscard

Attach an asynchronous PDG event callback.

The PDG itself does not raise an NVIC vector – this hook is available for higher-level code that wants to forward GPT compare-match events (e.g. "delay updated") through a single registration point.

Parameters
[in]fnCallback invoked from ra8_pdg_dispatch.
[in]ctxForwarded to fn.
Returns
k_ra8_ok – the registration cannot fail.
Precondition
None.
Postcondition
Subsequent ra8_pdg_dispatch calls invoke fn.
Since
0.1.0

Definition at line 707 of file ra8_pdg.c.

References k_ra8_ok, s_pdg_event_ctx, and s_pdg_event_fn.

◆ ra8_pdg_bind_gpt_channel()

ra8_err_t ra8_pdg_bind_gpt_channel ( uint8_t channel)
nodiscard

Bind PDG channel n to its host GPT32n channel.

HUM Ch 23.2.3 (p 1156) requires that GTWP write-protect is cleared on the matching GPT channel before the PDG delay registers can be written. This helper performs that GTWP unlock (and stores the prior value so the caller can re-arm protection later via ra8_pdg_unbind_gpt_channel).

Parameters
[in]channel0..3 (GPT320..GPT323).
Returns
ra8_err_t error code.
Return values
k_ra8_okGTWP cleared, binding active.
k_ra8_err_invalid_argchannel out of range.
Precondition
PDG init has run.
Postcondition
GPT32n.GTWP write-protect bits cleared.
Subsequent ra8_pdg_set_delay writes are accepted.
Since
0.1.0

Definition at line 839 of file ra8_pdg.c.

References r_gpt_channel_regs_t::GTWP, internal_pdg_is_initialized(), k_ra8_err_hw_unmapped, k_ra8_err_invalid_arg, k_ra8_err_not_initialized, k_ra8_ok, k_ra8_pdg_channel_count, k_ra8_pdg_gtwp_unlock, and ra8_gpt().

◆ ra8_pdg_capture_start()

ra8_err_t ra8_pdg_capture_start ( const ra8_pdg_delay_entry_t * buf,
uint8_t len )
nodiscard

Stage a buffer of ra8_pdg_delay_entry_t records and arm them.

The PDG itself does not "capture" data – this entry-point exists so the camera/data-capture orchestrator can stream a buffer of fine-delay updates through the same *_capture_start(buf, len) shape that the VIN / CEU drivers expose. Each ra8_pdg_delay_entry_t in buf is forwarded to ra8_pdg_set_delay_batch after a NULL / range check, and the registered completion callback (see ra8_pdg_attach_handler) fires via ra8_pdg_dispatch once all entries land.

Parameters
[in]bufPointer to an array of ra8_pdg_delay_entry_t records.
[in]lenElement count (must be > 0 and <= k_ra8_pdg_slot_count).
Returns
ra8_err_t
Return values
k_ra8_okEntries staged + dispatch fired.
k_ra8_err_null_ptrbuf was NULL.
k_ra8_err_invalid_arglen out of range or bad entry.
k_ra8_err_not_initializedPDG init has not run.
Precondition
PDG init has run.
buf is non-NULL and points to len valid entries.
Postcondition
All entries are written to their PDG temporary registers.
The registered completion callback fires once.
Note
Not thread-safe.
See also
ra8_pdg_set_delay_batch
ra8_pdg_capture_stop
Since
0.1.0

Definition at line 738 of file ra8_pdg.c.

References k_ra8_err_invalid_arg, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_pdg_dispatch(), ra8_pdg_set_delay_batch(), s_pdg_capture_in_flight, and s_tag.

◆ ra8_pdg_capture_stop()

ra8_err_t ra8_pdg_capture_stop ( void )
nodiscard

Cancel any pending buffered apply and clear the completion latch.

Mirrors the VIN / CEU *_capture_stop shape. Implementation simply clears the internal "in flight" flag so a subsequent ra8_pdg_dispatch does not double-fire the callback.

Returns
ra8_err_t
Return values
k_ra8_okAlways.
Precondition
PDG init has run.
Postcondition
Pending in-flight latch is cleared.
Note
Not thread-safe.
See also
ra8_pdg_capture_start
Since
0.1.0

Definition at line 754 of file ra8_pdg.c.

References k_ra8_ok, and s_pdg_capture_in_flight.

◆ ra8_pdg_channel_bypass_set()

ra8_err_t ra8_pdg_channel_bypass_set ( uint8_t channel,
uint8_t bypass )
nodiscard

Set or clear the bypass bit for a channel.

HUM Ch 23.2.2 (p 1155) describes the DLYBSn bit: 1 = delay applied, 0 = bypass. ra8_pdg_init already sets the bit for every channel in cfg->channel_mask; this helper exists so a caller can flip the bypass on the fly without a full re-init.

Parameters
[in]channel0..3.
[in]bypassNon-zero sets bypass-off (delay applied); zero sets bypass-on (delay skipped).
Returns
ra8_err_t error code.
Precondition
PDG init has run.
Postcondition
DLYBSn matches bypass.
Since
0.1.0

Definition at line 616 of file ra8_pdg.c.

References r_pdg_regs_t::GTDLYCR2, internal_pdg_is_initialized(), k_ra8_err_invalid_arg, k_ra8_err_not_initialized, k_ra8_ok, k_ra8_pdg_channel_count, k_ra8_pdg_gtdlycr2_shift_dlybs, and ra8_pdg().

◆ ra8_pdg_check_constraints()

ra8_err_t ra8_pdg_check_constraints ( ra8_pdg_wave_mode_t mode,
ra8_pdg_count_dir_t dir,
uint32_t compare_match,
uint32_t gtpr )
nodiscard

Check Table 23.4 constraints before writing a delay register.

HUM Ch 23.4.2 Table 23.4 (p 1162) forbids changing a delay register while the host GPT is in a "no write" window:

mode direction compare-match value forbidden
Saw Up >= GTPR - 2
Saw Down <= 2
Triangle Down <= 2
Parameters
[in]modeSaw vs triangle.
[in]dirCounter direction.
[in]compare_matchCurrent GTCCRx (= compare match value).
[in]gtprGPT period register value.
Returns
ra8_err_t error code.
Return values
k_ra8_okSafe to write the delay register.
k_ra8_err_invalid_stateInside the forbidden window.
Precondition
None.
Postcondition
No side effects.
Since
0.1.0

Definition at line 881 of file ra8_pdg.c.

References k_ra8_err_invalid_arg, k_ra8_err_invalid_state, k_ra8_ok, k_ra8_pdg_constraint_high_pad, k_ra8_pdg_constraint_low_thresh, k_ra8_pdg_dir_down, k_ra8_pdg_dir_up, k_ra8_pdg_wave_saw, and k_ra8_pdg_wave_triangle.

◆ ra8_pdg_clear_status()

ra8_err_t ra8_pdg_clear_status ( uint16_t mask)
nodiscard

Clear the soft-reset bit (DLYRST -> 0) and re-enable the DLL.

Used to re-arm the block after a controlled park via ra8_pdg_enter_stop. The "status mask" is in fact the GTDLYCR register so this call only writes back the bit that the caller provided – DLYRST is forced low.

Parameters
[in]maskCaller-supplied bits to clear in GTDLYCR. Only k_ra8_pdg_status_in_reset is meaningful today.
Returns
ra8_err_t error code.
Precondition
PDG init has run.
Postcondition
GTDLYCR.DLYRST = 0 if mask includes k_ra8_pdg_status_in_reset.
Since
0.1.0

Definition at line 696 of file ra8_pdg.c.

References r_pdg_regs_t::GTDLYCR, k_ra8_ok, k_ra8_pdg_gtdlycr_mask_dlyrst, k_ra8_pdg_status_in_reset, and ra8_pdg().

◆ ra8_pdg_deinit()

ra8_err_t ra8_pdg_deinit ( void )
nodiscard

Tear down the PDG block (reset + module-stop).

Returns
ra8_err_t error code.
Return values
k_ra8_okBlock parked back in module-stop with all channels disabled.
Precondition
PDG was previously initialized (otherwise a no-op).
Postcondition
GTDLYCR.DLLEN = 0 and DLYRST = 1.
GTDLYCR2 = 0 (every channel bypassed and powered down).
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 464 of file ra8_pdg.c.

References r_pdg_dly_pair_t::A, r_pdg_dly_pair_t::B, r_pdg_regs_t::GTDLYCR, r_pdg_regs_t::GTDLYCR2, r_pdg_regs_t::GTDLYF, r_pdg_regs_t::GTDLYR, k_ra8_mstp_pdg, k_ra8_ok, k_ra8_pdg_channel_count, k_ra8_pdg_gtdlycr_mask_dlyrst, ra8_mstp_disable(), and ra8_pdg().

◆ ra8_pdg_delay_ns_to_code()

ra8_err_t ra8_pdg_delay_ns_to_code ( uint32_t delay_ns,
uint32_t gptclk_hz,
ra8_pdg_frange_t frange,
uint8_t * out_code )
nodiscard

Convert a desired pin-to-pin delay (in nanoseconds) to a DLY[6:0] code given a measured GPTCLK frequency.

Uses the divider table from HUM Ch 23.2.3..23.2.6 (p 1156-1158): 1/128 step at k_ra8_pdg_frange_80_160_mhz, 1/64 step at k_ra8_pdg_frange_155_300_mhz. The result is rounded to the nearest representable code and clamped to [0, 0x7F].

Parameters
[in]delay_nsDesired delay in nanoseconds.
[in]gptclk_hzGPTCLK frequency in Hz (must be > 0).
[in]frangeThe FRANGE band currently programmed.
[out]out_codeReceives the closest DLY[6:0] code.
Returns
ra8_err_t error code.
Return values
k_ra8_okCode computed.
k_ra8_err_null_ptrout_code is NULL.
k_ra8_err_invalid_arggptclk_hz is zero or frange out of range.
Precondition
out_code non-null, gptclk_hz > 0.
Postcondition
*out_code <= 0x7F.
Since
0.1.0

Definition at line 554 of file ra8_pdg.c.

References internal_frange_ok(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_pdg_dly_div_high, k_ra8_pdg_dly_div_low, k_ra8_pdg_dly_max, k_ra8_pdg_frange_80_160_mhz, k_ra8_pdg_ns_per_sec, RA8_CHECK_NULL_PTR, and s_tag.

◆ ra8_pdg_dispatch()

void ra8_pdg_dispatch ( void )

Fire the registered handler.

Test / ELC entry point.

Since
0.1.0

See implementation.

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.

Definition at line 715 of file ra8_pdg.c.

References s_pdg_event_ctx, and s_pdg_event_fn.

Referenced by ra8_pdg_capture_start().

◆ ra8_pdg_enter_stop()

ra8_err_t ra8_pdg_enter_stop ( uint8_t channel)
nodiscard

Power down one PDG channel (set GTDLYCR2.DLYENn).

Parameters
[in]channel0..3.
Returns
ra8_err_t error code.
Precondition
channel < 4.
Postcondition
Channel channel is power-off; its outputs revert to the undelayed GPT signal.
Since
0.1.0

Definition at line 603 of file ra8_pdg.c.

References r_pdg_regs_t::GTDLYCR2, k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_pdg_channel_count, k_ra8_pdg_gtdlycr2_shift_dlyen, and ra8_pdg().

◆ ra8_pdg_exit_stop()

ra8_err_t ra8_pdg_exit_stop ( uint8_t channel)
nodiscard

Power up one PDG channel (clear the GTDLYCR2.DLYENn bit).

Parameters
[in]channel0..3.
Returns
ra8_err_t error code.
Precondition
PDG init has run.
Postcondition
Channel channel is power-on (HUM 23.2.2 p 1155 – DLYEN is inverted, 0 = enabled).
Since
0.1.0

Definition at line 589 of file ra8_pdg.c.

References r_pdg_regs_t::GTDLYCR2, k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_pdg_channel_count, k_ra8_pdg_gtdlycr2_shift_dlyen, and ra8_pdg().

◆ ra8_pdg_get_delay()

ra8_err_t ra8_pdg_get_delay ( uint8_t channel,
ra8_pdg_pin_t pin,
ra8_pdg_edge_t edge,
uint8_t * out_code )
nodiscard

Read back the last-programmed delay code.

Parameters
[in]channelPDG channel (0..3).
[in]pink_ra8_pdg_pin_a / k_ra8_pdg_pin_b.
[in]edgek_ra8_pdg_edge_rising / k_ra8_pdg_edge_falling.
[out]out_codeReceives the DLY[6:0] code last written.
Returns
ra8_err_t error code.
Precondition
out_code is non-null.
channel < 4.
Postcondition
*out_code is in 0..0x7F.
Note
Reads the live register, not the temporary buffer.
Since
0.1.0

Definition at line 512 of file ra8_pdg.c.

References internal_dly_cell(), internal_validate_slot(), k_ra8_ok, k_ra8_pdg_dly_mask, pin, RA8_CHECK_NULL_PTR, RA8_RETURN_ON_ERROR, and s_tag.

Referenced by internal_pdg_demo_sample().

◆ ra8_pdg_get_status()

ra8_err_t ra8_pdg_get_status ( uint16_t * out)
nodiscard

Read GTDLYCR packed into a status mask.

Parameters
[out]outReceives a bitmask of ra8_pdg_status_t bits.
Returns
ra8_err_t error code.
Precondition
out is non-null.
Postcondition
*out reflects the live GTDLYCR (DLLEN, DLYRST, FRANGE).
Since
0.1.0

Definition at line 663 of file ra8_pdg.c.

References r_pdg_regs_t::GTDLYCR, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_pdg(), and s_tag.

◆ ra8_pdg_get_status_full()

ra8_err_t ra8_pdg_get_status_full ( ra8_pdg_status_full_t * out)
nodiscard

Read a fully-decoded snapshot of GTDLYCR + GTDLYCR2.

Parameters
[out]outNon-null structure to fill in.
Returns
ra8_err_t error code.
Return values
k_ra8_okSnapshot stored.
k_ra8_err_null_ptrout is NULL.
Precondition
out non-null.
Postcondition
Every field in *out reflects the live registers at call time (DLLEN, DLYRST, FRANGE, DLYBSn, DLYENn).
Since
0.1.0

Definition at line 672 of file ra8_pdg.c.

References ra8_pdg_status_full_t::dll_enabled, ra8_pdg_status_full_t::frange, r_pdg_regs_t::GTDLYCR, r_pdg_regs_t::GTDLYCR2, ra8_pdg_status_full_t::in_reset, k_ra8_ok, k_ra8_pdg_channel_count, k_ra8_pdg_gtdlycr2_shift_dlybs, k_ra8_pdg_gtdlycr2_shift_dlyen, k_ra8_pdg_gtdlycr_mask_dllen, k_ra8_pdg_gtdlycr_mask_dlyrst, k_ra8_pdg_gtdlycr_mask_frange, k_ra8_pdg_gtdlycr_shift_frange, ra8_pdg_status_full_t::per_channel_bypass_off, ra8_pdg_status_full_t::per_channel_powered, RA8_CHECK_NULL_PTR, ra8_pdg(), ra8_pdg_status_full_t::raw_gtdlycr, ra8_pdg_status_full_t::raw_gtdlycr2, and s_tag.

Referenced by internal_pdg_demo_sample().

◆ ra8_pdg_init()

ra8_err_t ra8_pdg_init ( const ra8_pdg_config_t * cfg)
nodiscard

Initialise the PDG block per HUM Figure 23.2 (p 1160).

Clears the PDG module-stop bit (MSTPD6 per HUM Ch 23.4.1 p 1162), holds the circuit in reset, programs FRANGE (or auto-derives it from cfg->gptclk_hz when cfg->auto_tune == 1), enables the DLL, waits for lock, releases reset, and turns off bypass for the channels listed in cfg->channel_mask.

Parameters
[in]cfgNon-NULL driver descriptor.
Returns
ra8_err_t error code.
Return values
k_ra8_okInit complete.
k_ra8_err_null_ptrcfg was NULL.
k_ra8_err_invalid_argcfg->frange out of range or cfg->channel_mask selects bits outside [0..3] or auto-tune saw gptclk_hz == 0.
k_ra8_err_out_of_rangeAuto-tune saw gptclk_hz outside the 80..300 MHz range allowed by HUM Ch 23.2.1 p 1154.
k_ra8_err_hw_init_failedMSTP failed to release the block.
Precondition
IRQs masked or single-threaded init context.
ra8_mstp_init has been called.
Postcondition
GTDLYCR.DLLEN = 1 and DLYRST = 0.
GTDLYCR2.DLYBSn = 1 for every n in cfg->channel_mask.
Note
Thread safety: not thread-safe.
See also
ra8_gpt.h
ra8_pdg_set_frange Switch FRANGE at runtime without deinit.
Since
0.1.0

Definition at line 438 of file ra8_pdg.c.

References ra8_pdg_config_t::auto_tune, ra8_pdg_config_t::frange, ra8_pdg_config_t::gptclk_hz, internal_program_dll(), internal_validate_cfg(), k_ra8_mstp_pdg, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_log_info, ra8_mstp_enable(), ra8_pdg_pick_frange(), RA8_RETURN_ON_ERROR, and s_tag.

Referenced by internal_pdg_demo_configure().

◆ ra8_pdg_pick_frange()

ra8_err_t ra8_pdg_pick_frange ( uint32_t gptclk_hz,
ra8_pdg_frange_t * out )
nodiscard

Auto-pick a FRANGE value from a measured GPTCLK frequency.

Implements the band-selection table of HUM Ch 23.2.1 (p 1154):

The two ranges overlap between 155 and 160 MHz; this helper picks the lower band when the input falls in the overlap because that gives the finer 1/128 step.

Parameters
[in]gptclk_hzGPTCLK in Hz (>0). 80..300 MHz inclusive.
[out]outReceives the chosen ra8_pdg_frange_t.
Returns
ra8_err_t error code.
Return values
k_ra8_okBand selected.
k_ra8_err_null_ptrout is NULL.
k_ra8_err_invalid_arggptclk_hz is 0.
k_ra8_err_out_of_rangegptclk_hz outside [80 MHz, 300 MHz].
Since
0.1.0

Definition at line 765 of file ra8_pdg.c.

References k_ra8_err_invalid_arg, k_ra8_err_out_of_range, k_ra8_ok, k_ra8_pdg_frange_155_300_mhz, k_ra8_pdg_frange_80_160_mhz, k_ra8_pdg_freq_high_max_hz, k_ra8_pdg_freq_low_min_hz, k_ra8_pdg_freq_overlap_top, RA8_CHECK_NULL_PTR, and s_tag.

Referenced by ra8_pdg_init().

◆ ra8_pdg_pin_disable()

ra8_err_t ra8_pdg_pin_disable ( uint8_t channel,
ra8_pdg_pin_t pin )
nodiscard

Force a single A or B pin's delay to zero (per-pin disable) without touching the channel-level bypass / power bits.

The HUM lets DLYBSn / DLYENn be flipped per channel; per-pin disable is achieved by writing 0x00 into the pin's two delay cells (rising + falling). ra8_pdg_pin_disable does that, and ra8_pdg_pin_enable restores caller-supplied codes.

Parameters
[in]channel0..3.
[in]pink_ra8_pdg_pin_a or k_ra8_pdg_pin_b.
Returns
ra8_err_t error code.
Precondition
PDG init has run.
Postcondition
Both rising and falling delay cells of the chosen pin = 0.
Since
0.1.0

Definition at line 637 of file ra8_pdg.c.

References internal_dly_cell(), internal_pdg_is_initialized(), k_ra8_err_invalid_arg, k_ra8_err_not_initialized, k_ra8_ok, k_ra8_pdg_channel_count, k_ra8_pdg_edge_falling, k_ra8_pdg_edge_rising, k_ra8_pdg_pin_a, k_ra8_pdg_pin_b, and pin.

◆ ra8_pdg_required_write_ns()

ra8_err_t ra8_pdg_required_write_ns ( uint32_t pclka_hz,
uint32_t gptclk_hz,
uint32_t * out_ns )
nodiscard

Compute the minimum register-write interval (HUM 23.4.3 p 1163).

Write_Interval [ns] = Period_of_PCLKA [ns] x 6

  • Period_of_GPTCLK [ns] x 4

Used by callers that issue back-to-back writes to the same delay register to size their software pacing.

Parameters
[in]pclka_hzPCLKA frequency in Hz (>0).
[in]gptclk_hzGPTCLK frequency in Hz (>0).
[out]out_nsReceives the required interval, in ns.
Returns
ra8_err_t error code.
Precondition
Both clocks > 0; out_ns non-null.
Postcondition
*out_ns >= 0.
Since
0.1.0

Definition at line 921 of file ra8_pdg.c.

References internal_freq_to_period_ns(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_pdg_gptclk_mult, k_ra8_pdg_pclka_mult, RA8_CHECK_NULL_PTR, and s_tag.

◆ ra8_pdg_set_delay()

ra8_err_t ra8_pdg_set_delay ( uint8_t channel,
ra8_pdg_pin_t pin,
ra8_pdg_edge_t edge,
uint8_t code )
nodiscard

Set the per-edge fine delay for one PDG channel/pin/edge.

Parameters
[in]channelPDG channel (0..3, mapped to GPT320..GPT323).
[in]pink_ra8_pdg_pin_a (GTIOCnA) or k_ra8_pdg_pin_b (GTIOCnB).
[in]edgek_ra8_pdg_edge_rising or k_ra8_pdg_edge_falling.
[in]codeDLY[6:0] code, 0..0x7F. 0 disables the delay on this edge; the meaning of non-zero codes depends on the FRANGE bit currently programmed in GTDLYCR (HUM Ch 23.2.3..23.2.6 p 1156-1158).
Returns
ra8_err_t error code.
Return values
k_ra8_okCode written.
k_ra8_err_invalid_argChannel >= 4, pin/edge invalid, or code > 0x7F.
k_ra8_err_not_initializedPDG init has not run.
Precondition
PDG is out of reset (GTDLYCR.DLYRST == 0).
Caller is not currently inside the GPT compare-match window where writes are disallowed (HUM Ch 23.4.2 p 1162, Table 23.4) – use ra8_pdg_check_constraints first.
Postcondition
The temporary register holds code; it propagates to the live delay on the next GPT overflow / underflow / trough (HUM Ch 23.3.2 p 1161).
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 494 of file ra8_pdg.c.

References internal_dly_cell(), internal_pdg_is_initialized(), internal_validate_slot(), k_ra8_err_not_initialized, k_ra8_ok, k_ra8_pdg_dly_mask, pin, RA8_RETURN_ON_ERROR, and s_tag.

Referenced by internal_pdg_demo_configure().

◆ ra8_pdg_set_delay_batch()

ra8_err_t ra8_pdg_set_delay_batch ( const ra8_pdg_delay_entry_t * entries,
uint8_t count )
nodiscard

Atomically program a batch of (channel, pin, edge, code) delay updates.

Walks entries and applies each one with IRQs nominally masked (host-test build is single-threaded). All writes land in the PDG temporary registers in the same critical section, so the next GPT overflow / underflow / trough applies them as one coherent set. This is the multi-edge atomic batch entry-point called for in HUM Ch 23.3.2 (p 1161).

Parameters
[in]entriesPointer to count entries.
[in]countNumber of entries (must be > 0 and <= k_ra8_pdg_slot_count).
Returns
ra8_err_t error code.
Return values
k_ra8_okAll entries written.
k_ra8_err_null_ptrentries is NULL.
k_ra8_err_invalid_argCount out of range or any entry contains a bad channel / pin / edge / code.
k_ra8_err_not_initializedPDG init has not run.
Precondition
entries non-null and points to count valid entries.
PDG is out of reset.
Postcondition
Every entry's delay code is in the corresponding temporary register; it propagates on next overflow.
Since
0.1.0

Definition at line 525 of file ra8_pdg.c.

References internal_dly_cell(), internal_pdg_is_initialized(), internal_validate_slot(), k_ra8_err_invalid_arg, k_ra8_err_not_initialized, k_ra8_ok, k_ra8_pdg_dly_mask, k_ra8_pdg_slot_count, pin, RA8_CHECK_NULL_PTR, and s_tag.

Referenced by ra8_pdg_capture_start().

◆ ra8_pdg_set_frange()

ra8_err_t ra8_pdg_set_frange ( ra8_pdg_frange_t new_frange)
nodiscard

Switch FRANGE at runtime, re-running the DLL re-lock sequence with the new band.

HUM Ch 23.2.1 (p 1154): "Set the FRANGE[1:0] bits only when the DLLEN bit is 0." This routine therefore performs:

  1. Save current DLYBSn / DLYENn from GTDLYCR2.
  2. Drop DLLEN to 0, raise DLYRST to 1.
  3. Write the new FRANGE bits.
  4. Re-enable DLLEN, wait 20 us for lock.
  5. Lower DLYRST.
  6. Restore the saved GTDLYCR2 bits.
Parameters
[in]new_frangeThe new FRANGE encoding.
Returns
ra8_err_t error code.
Return values
k_ra8_okSwitch complete.
k_ra8_err_invalid_argnew_frange not a legal band.
k_ra8_err_not_initializedPDG init has not run.
Precondition
PDG init has run.
Postcondition
GTDLYCR.FRANGE == new_frange, DLLEN = 1, DLYRST = 0.
GTDLYCR2 contents preserved across the call.
Since
0.1.0

Definition at line 787 of file ra8_pdg.c.

References r_pdg_regs_t::GTDLYCR, r_pdg_regs_t::GTDLYCR2, internal_busy_wait_us(), internal_frange_ok(), internal_pdg_is_initialized(), internal_wait_5_gtclk(), k_ra8_err_invalid_arg, k_ra8_err_not_initialized, k_ra8_ok, k_ra8_pdg_dll_lock_us, k_ra8_pdg_gtdlycr_mask_dllen, k_ra8_pdg_gtdlycr_mask_dlyrst, k_ra8_pdg_gtdlycr_shift_frange, and ra8_pdg().

◆ ra8_pdg_unbind_gpt_channel()

ra8_err_t ra8_pdg_unbind_gpt_channel ( uint8_t channel)
nodiscard

Reverse ra8_pdg_bind_gpt_channel, restoring write-protect.

Parameters
[in]channel0..3.
Returns
ra8_err_t error code.
Precondition
channel < 4.
Postcondition
GPT32n.GTWP write-protect re-armed.
Since
0.1.0

Definition at line 860 of file ra8_pdg.c.

References r_gpt_channel_regs_t::GTWP, k_ra8_err_hw_unmapped, k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_pdg_channel_count, k_ra8_pdg_gtwp_lock, and ra8_gpt().

Variable Documentation

◆ s_pdg_capture_in_flight

bool s_pdg_capture_in_flight
static

Set true between ra8_pdg_capture_start and the callback fire.

Note
Cleared by ra8_pdg_capture_stop and after the callback fires.
Since
0.1.0

Definition at line 736 of file ra8_pdg.c.

Referenced by ra8_pdg_capture_start(), and ra8_pdg_capture_stop().

◆ s_pdg_event_ctx

void* s_pdg_event_ctx
static

Opaque pointer forwarded to s_pdg_event_fn.

Definition at line 179 of file ra8_pdg.c.

Referenced by ra8_pdg_attach_handler(), and ra8_pdg_dispatch().

◆ s_pdg_event_fn

ra8_pdg_event_fn_t s_pdg_event_fn
static

Most recent callback registered by ra8_pdg_attach_handler.

Warning
Not protected against concurrent re-registration – the public API documents that the driver is single-threaded.

Definition at line 173 of file ra8_pdg.c.

Referenced by ra8_pdg_attach_handler(), and ra8_pdg_dispatch().

◆ s_tag

const char* s_tag = "PDG"
static

Definition at line 64 of file ra8_pdg.c.