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

ADC_B self-diagnosis + internal extended-analog channel reads. More...

#include <stdint.h>
#include "adc_internal.h"
#include "ra8_adc.h"
#include "ra8_adc_b_regs.h"
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_log.h"
Include dependency graph for adc_selfdiag.c:

Go to the source code of this file.

Enumerations

enum  ra8_adc_diag_slot_t : uint8_t {
  k_ra8_adc_diag_vchan = 23U ,
  k_ra8_adc_diag_group = 8U
}
 Dedicated virtual-channel / scan-group used for diagnostic reads. More...
enum  ra8_adc_selfdiag_expect_t : int32_t {
  k_ra8_adc_selfdiag_expect_mode1 = 0 ,
  k_ra8_adc_selfdiag_expect_mode2 = -32768 ,
  k_ra8_adc_selfdiag_expect_mode3 = 32767
}
 Ideal 16-bit signed self-diagnosis result per mode. More...
enum  ra8_adc_selfdiag_tol_t : int32_t { k_ra8_adc_selfdiag_tol_lsb = 256 }
 Allowed absolute deviation from the ideal self-diagnosis result. More...

Functions

static bool internal_diagval_for_mode (ra8_adc_selfdiag_mode_t mode, uint32_t *out_diagval)
 Translate a public self-diagnosis mode into the DIAGVAL code.
static int32_t internal_selfdiag_expected (ra8_adc_selfdiag_mode_t mode)
 Ideal signed self-diagnosis result for a mode.
static bool internal_selfdiag_in_band (int32_t diff)
 Test whether a signed deviation is inside the tolerance band.
static bool internal_is_supported_ext_chan (ra8_adc_internal_chan_t chan)
 Test whether a channel is a supported internal/extended source.
static void internal_program_ext_channel (uint8_t vch, uint8_t physical_ch, uint8_t group, bool differential)
 Program a dedicated ADCHCR slot for an extended-analog channel.
static void internal_set_data_format (uint8_t vch, uint8_t adprc, uint8_t signsel)
 Force the ADPRC data-format and SIGNSEL sign-format on a slot.
static ra8_err_t internal_start_and_wait (uint8_t group)
 Start a scan group and bounded-poll ADSR.ADACT0 to completion.
static ra8_err_t internal_selfdiag_run (uint32_t diagval)
 Arm the self-diagnosis channel, run one scan, and disarm DIAGVAL.
ra8_err_t ra8_adc_self_diagnose (ra8_adc_selfdiag_mode_t mode, uint16_t *out_code, bool *out_pass)
 Run an ADC_B built-in self-diagnosis pass on A/D unit 0.
ra8_err_t ra8_adc_read_internal_channel (ra8_adc_internal_chan_t chan, uint16_t *out_raw)
 Blocking single conversion of an internal / extended-analog channel.

Variables

static const char * s_tag = "ADC"

Detailed Description

ADC_B self-diagnosis + internal extended-analog channel reads.

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

Self-diagnosis + internal / extended-analog slice of the RA8D2 ADC_B HAL driver, split out of adc.c to keep every translation unit under the file-size budget.

Provides the SIL3 / DO-178C Level B periodic proof that the SAR core and reference are healthy (self-diagnosis modes 1/2/3, HUM Ch 53.3.11 p 3411-3414), plus the close-the-loop read of the on-chip temperature sensor / internal reference voltage from their ADEXDRn result registers (HUM Ch 53.2.13.2 p 3391).

The ADSR.ADACT0 conversion busy-poll budget is shared with adc.c via adc_internal.h.

Definition in file adc_selfdiag.c.

Enumeration Type Documentation

◆ ra8_adc_diag_slot_t

enum ra8_adc_diag_slot_t : uint8_t

Dedicated virtual-channel / scan-group used for diagnostic reads.

Internal-channel and self-diagnosis conversions are isolated onto a dedicated ADCHCR slot and scan group so they never collide with the legacy default-group polling path. The slot is the top ADCHCR index (no ADDR result slot is needed – results come from ADEXDR).

Enumerator
k_ra8_adc_diag_vchan 

Dedicated ADCHCR slot for diagnostic reads.

k_ra8_adc_diag_group 

Dedicated scan group for diagnostic reads.

Definition at line 55 of file adc_selfdiag.c.

◆ ra8_adc_selfdiag_expect_t

enum ra8_adc_selfdiag_expect_t : int32_t

Ideal 16-bit signed self-diagnosis result per mode.

HUM Table 53.19 (p 3412): mode 1 -> 0x0000, mode 2 -> 0x8000 (-32768), mode 3 -> 0x7FFF (+32767).

Enumerator
k_ra8_adc_selfdiag_expect_mode1 

0x0000.

k_ra8_adc_selfdiag_expect_mode2 

0x8000.

k_ra8_adc_selfdiag_expect_mode3 

0x7FFF.

Definition at line 67 of file adc_selfdiag.c.

◆ ra8_adc_selfdiag_tol_t

enum ra8_adc_selfdiag_tol_t : int32_t

Allowed absolute deviation from the ideal self-diagnosis result.

The self-diagnosis pass/fail band. A healthy SAR + reference lands on the ideal value within a few LSB (HUM Ch 53.3.11.2 p 3414); gross faults (stuck SAR, dead reference, wrong polarity) miss it by tens of thousands of LSB, so a loose band reliably separates pass from fail. TODO(confirm self-diagnosis accuracy band from HUM Ch 69 "Electrical Characteristics" – this gross-fault band is a placeholder until the exact A/D total-error spec is read).

Enumerator
k_ra8_adc_selfdiag_tol_lsb 

+/- LSB tolerance about the ideal.

Definition at line 86 of file adc_selfdiag.c.

Function Documentation

◆ internal_diagval_for_mode()

bool internal_diagval_for_mode ( ra8_adc_selfdiag_mode_t mode,
uint32_t * out_diagval )
static

Translate a public self-diagnosis mode into the DIAGVAL code.

Parameters
[in]modePublic self-diagnosis mode selector.
[out]out_diagvalReceives the ADSGDCRn.DIAGVAL[2:0] code.
Returns
True if mode is valid, false otherwise.
Return values
truemode is one of modes 1/2/3; out_diagval set to the DIAGVAL code.
falsemode is out of range; out_diagval left untouched.

Maps mode 1/2/3 onto DIAGVAL 0x4/0x5/0x6 (HUM Ch 53.2.4.1 p 3340). Leaves out_diagval untouched on the invalid path.

Precondition
out_diagval is non-null.
mode is sourced from ra8_adc_selfdiag_mode_t.
Postcondition
out_diagval is set only when the function returns true.
No registers are accessed.
Note
Re-entrant; touches no globals or MMIO.
Since
0.1.0

Definition at line 108 of file adc_selfdiag.c.

References k_ra8_adc_selfdiag_mode_1, k_ra8_adc_selfdiag_mode_2, k_ra8_adc_selfdiag_mode_3, k_ra8_adsgdcr_diag_mode1, k_ra8_adsgdcr_diag_mode2, k_ra8_adsgdcr_diag_mode3, and RA8_INTERNAL.

Referenced by ra8_adc_self_diagnose().

◆ internal_is_supported_ext_chan()

bool internal_is_supported_ext_chan ( ra8_adc_internal_chan_t chan)
static

Test whether a channel is a supported internal/extended source.

Parameters
[in]chanInternal-channel selector.
Returns
True iff chan is the temperature sensor or internal Vref.
Return values
truechan is the temperature sensor or the internal Vref channel.
falsechan is any other (unsupported) channel.

Compound decision: true for either the temperature sensor or the internal reference-voltage channel.

Precondition
chan is sourced from ra8_adc_internal_chan_t.
The set of supported channels matches the ADEXDR routing.
Postcondition
No side effects.
No registers are accessed.
Note
Re-entrant; touches no globals or MMIO.
Since
0.1.0

Definition at line 196 of file adc_selfdiag.c.

References k_ra8_adc_chan_int_ref_volt, k_ra8_adc_chan_temperature, and RA8_INTERNAL.

Referenced by ra8_adc_read_internal_channel().

◆ internal_program_ext_channel()

void internal_program_ext_channel ( uint8_t vch,
uint8_t physical_ch,
uint8_t group,
bool differential )
static

Program a dedicated ADCHCR slot for an extended-analog channel.

Parameters
[in]vchVirtual-channel (ADCHCR) slot index.
[in]physical_chCNVCS[6:0] code of the extended-analog source.
[in]groupScan-group membership.
[in]differentialTrue -> AINMD differential, false -> single-ended.

Writes SGSEL, CNVCS, and AINMD (HUM Ch 53.2.3.1 p 3335-3336).

Precondition
vch is a valid ADCHCR slot.
group is a valid scan group.
Postcondition
On a valid slot the ADCHCR fields match the arguments.
No write occurs when vch is out of range.
Note
Not thread-safe.
Since
0.1.0

Definition at line 218 of file adc_selfdiag.c.

References k_ra8_adchcr_bit_ainmd, k_ra8_adchcr_bit_cnvcs, k_ra8_adchcr_bit_sgsel, k_ra8_adchcr_mask_ainmd, k_ra8_adchcr_mask_cnvcs, k_ra8_adchcr_mask_sgsel, and ra8_adc_b_adchcr().

Referenced by internal_selfdiag_run(), and ra8_adc_read_internal_channel().

◆ internal_selfdiag_expected()

int32_t internal_selfdiag_expected ( ra8_adc_selfdiag_mode_t mode)
static

Ideal signed self-diagnosis result for a mode.

Parameters
[in]modeSelf-diagnosis mode (already validated).
Returns
Ideal 16-bit signed value (HUM Table 53.19 p 3412).
Return values
-32768mode is mode 2 (negative full-scale ideal).
32767mode is mode 3 (positive full-scale ideal).
0mode is mode 1 or any unlisted value (mid-scale ideal).

Mode 1 -> 0, mode 2 -> -32768, mode 3 -> +32767.

Precondition
mode is one of modes 1/2/3.
Caller validated mode via internal_diagval_for_mode.
Postcondition
Return value is in [-32768, +32767].
No registers are accessed.
Note
Re-entrant; touches no globals or MMIO.
Since
0.1.0

Definition at line 143 of file adc_selfdiag.c.

References k_ra8_adc_selfdiag_expect_mode1, k_ra8_adc_selfdiag_expect_mode2, k_ra8_adc_selfdiag_expect_mode3, k_ra8_adc_selfdiag_mode_1, k_ra8_adc_selfdiag_mode_2, k_ra8_adc_selfdiag_mode_3, and RA8_INTERNAL.

Referenced by ra8_adc_self_diagnose().

◆ internal_selfdiag_in_band()

bool internal_selfdiag_in_band ( int32_t diff)
static

Test whether a signed deviation is inside the tolerance band.

Parameters
[in]diffSigned (actual - expected) deviation in LSB.
Returns
True iff diff is within +/- k_ra8_adc_selfdiag_tol_lsb.
Return values
truediff lies within +/- k_ra8_adc_selfdiag_tol_lsb LSB.
falsediff exceeds the tolerance band on either edge.

Compound decision: true when diff lies within both the upper and lower edges of the symmetric tolerance band.

Precondition
diff was computed in int32_t to avoid 16-bit overflow.
The tolerance band is symmetric about zero.
Postcondition
No side effects.
Return value depends only on diff and the constant band.
Note
Re-entrant; touches no globals or MMIO.
Since
0.1.0

Definition at line 173 of file adc_selfdiag.c.

References k_ra8_adc_selfdiag_tol_lsb, and RA8_INTERNAL.

Referenced by ra8_adc_self_diagnose().

◆ internal_selfdiag_run()

ra8_err_t internal_selfdiag_run ( uint32_t diagval)
static

Arm the self-diagnosis channel, run one scan, and disarm DIAGVAL.

Parameters
[in]diagvalADSGDCRn.DIAGVAL[2:0] code for the requested mode.
Returns
k_ra8_ok when ADC0 goes idle, otherwise a forwarded error.
Return values
k_ra8_okThe diagnostic scan completed and ADC0 went idle.
k_ra8_err_out_of_rangeForwarded from internal_start_and_wait: bad group.
k_ra8_err_hw_timeoutForwarded from internal_start_and_wait: poll budget expired.

Maps the self-diagnosis channel (CNVCS = 0x60) onto the dedicated slot in differential, 16-bit signed format (HUM Ch 53.3.11.1 p 3412 + Notes p 3414), enables the dedicated scan group, writes DIAGVAL, kicks the scan, then clears DIAGVAL back to off so later normal scans on the group are not stuck in diagnosis mode (HUM Ch 53.2.4.1 p 3340).

Precondition
diagval is one of the valid DIAGVAL mode codes.
ra8_adc_init has powered and clocked the converter.
Postcondition
ADSGDCRn.DIAGVAL for the diagnostic group is back to 0.
The dedicated slot maps the self-diagnosis channel.
Note
Not thread-safe.
Since
0.1.0

Definition at line 323 of file adc_selfdiag.c.

References internal_program_ext_channel(), internal_set_data_format(), internal_start_and_wait(), k_ra8_adc_b_chan_selfdiag_adc0, k_ra8_adc_diag_group, k_ra8_adc_diag_vchan, k_ra8_addopcrc_adprc_16bit, k_ra8_addopcrc_signsel_signed, k_ra8_adsgdcr_bit_diagval, k_ra8_adsgdcr_mask_diagval, ra8_adc_b_adsgdcr(), ra8_adc_b_adsger(), and RA8_INTERNAL.

Referenced by ra8_adc_self_diagnose().

◆ internal_set_data_format()

void internal_set_data_format ( uint8_t vch,
uint8_t adprc,
uint8_t signsel )
static

Force the ADPRC data-format and SIGNSEL sign-format on a slot.

Parameters
[in]vchVirtual-channel (ADDOPCRC) slot index.
[in]adprcADPRC[1:0] data-format code.
[in]signselSIGNSEL sign-format code.

Read-modify-writes ADDOPCRCn (HUM Ch 53.2.3.4 p 3339).

Precondition
vch is a valid ADDOPCRC slot.
adprc / signsel are sourced from their register enums.
Postcondition
On a valid slot the ADPRC + SIGNSEL fields match the arguments.
No write occurs when vch is out of range.
Note
Not thread-safe.
Since
0.1.0

Definition at line 250 of file adc_selfdiag.c.

References k_ra8_addopcrc_bit_adprc, k_ra8_addopcrc_bit_signsel, k_ra8_addopcrc_mask_adprc, k_ra8_addopcrc_mask_signsel, ra8_adc_b_addopcrc(), and RA8_INTERNAL.

Referenced by internal_selfdiag_run(), and ra8_adc_read_internal_channel().

◆ internal_start_and_wait()

ra8_err_t internal_start_and_wait ( uint8_t group)
static

Start a scan group and bounded-poll ADSR.ADACT0 to completion.

Parameters
[in]groupScan-group index to kick.
Returns
k_ra8_ok when ADC0 goes idle, k_ra8_err_out_of_range for a bad group, or k_ra8_err_hw_timeout if the poll budget expires.
Return values
k_ra8_okADSR.ADACT0 cleared within the poll budget.
k_ra8_err_out_of_rangegroup has no ADSTR register (bad index).
k_ra8_err_hw_timeoutADACT0 stayed set until the poll budget expired.

Kicks ADSTR[group], then polls ADSR.ADACT0 (HUM Ch 53 p 3308).

Precondition
group has been enabled in ADSGER.
A virtual channel maps to group.
Postcondition
ADSTR[group].ADST has been asserted.
Returns only after ADACT0 clears or the budget expires.
Note
Not thread-safe.
Since
0.1.0

Definition at line 283 of file adc_selfdiag.c.

References k_ra8_adc_busy_wait_limit, k_ra8_adsr_mask_adact0, k_ra8_adstr_mask_adst, k_ra8_err_hw_timeout, k_ra8_err_out_of_range, k_ra8_ok, ra8_adc_b_adsr(), ra8_adc_b_adstr(), and RA8_INTERNAL.

Referenced by internal_selfdiag_run(), and ra8_adc_read_internal_channel().

◆ ra8_adc_read_internal_channel()

ra8_err_t ra8_adc_read_internal_channel ( ra8_adc_internal_chan_t chan,
uint16_t * out_raw )
nodiscard

Blocking single conversion of an internal / extended-analog channel.

Maps chan (e.g. temperature sensor CNVCS = 0x64) onto a dedicated virtual channel in single-ended mode, forces the 12-bit unsigned data format, starts the dedicated scan group, polls ADSR.ADACT0, and reads the 12-bit code from the matching ADEXDRn register (n = CNVCS - 0x60, HUM Ch 53.2.13.2 p 3391).

Parameters
[in]chanInternal channel selector.
[out]out_rawReceives the masked conversion code.
Returns
ra8_err_t Status code.
Return values
k_ra8_okConversion read into out_raw.
k_ra8_err_null_ptrout_raw is nullptr.
k_ra8_err_invalid_argchan is not a supported internal channel.
k_ra8_err_hw_timeoutADSR.ADACT0 never cleared.
k_ra8_err_out_of_rangeThe mapped ADEXDR slot does not exist.
Precondition
ra8_adc_init has been called.
For the temperature channel, ra8_tsn_init has routed the sensor to the ADC mux (TSCR.TSOE).
Postcondition
out_raw == 0 on every error path.
No scan-group state other than the dedicated diagnostic group is modified.
Note
Not thread-safe.
See also
ra8_adc_internal_chan_t
Since
0.1.0

Definition at line 381 of file adc_selfdiag.c.

References internal_is_supported_ext_chan(), internal_program_ext_channel(), internal_set_data_format(), internal_start_and_wait(), k_ra8_adc_diag_group, k_ra8_adc_diag_vchan, k_ra8_addopcrc_adprc_12bit, k_ra8_addopcrc_signsel_unsigned, k_ra8_adexdr_mask_data, k_ra8_err_invalid_arg, k_ra8_err_out_of_range, k_ra8_ok, ra8_adc_b_adexdr(), ra8_adc_b_adexdr_index_for_chan(), ra8_adc_b_adsger(), RA8_CHECK_NULL_PTR, RA8_RETURN_ON_ERROR, and s_tag.

Referenced by adc_diag_run_cycle(), and ra8_tsn_read_die_temp_milli_c().

◆ ra8_adc_self_diagnose()

ra8_err_t ra8_adc_self_diagnose ( ra8_adc_selfdiag_mode_t mode,
uint16_t * out_code,
bool * out_pass )
nodiscard

Run an ADC_B built-in self-diagnosis pass on A/D unit 0.

Implements the HUM Ch 53.3.11.1 procedure (p 3412):

  1. Map the self-diagnosis channel (CNVCS = 0x60) onto a dedicated virtual channel in differential input mode (HUM Ch 53.2.3.1 p 3335-3336).
  2. Force the 16-bit signed data format on that channel via ADDOPCRC (ADPRC = 0, SIGNSEL = 0) as required by HUM Ch 53.3.11.3 p 3414.
  3. Set ADSGDCRn.DIAGVAL[2:0] for the dedicated scan group to the requested mode (HUM Ch 53.2.4.1 p 3340).
  4. Start the scan group, poll ADSR.ADACT0, and read the result from ADEXDR0.DATA[15:0] plus its ERR flag (HUM Ch 53.2.13.2 p 3391).
  5. Compare the signed result against the mode's ideal value (Table 53.19 p 3412) within a gross-fault tolerance band and clear DIAGVAL back to off so later normal scans are unaffected.
Parameters
[in]modeSelf-diagnosis mode (1 / 2 / 3).
[out]out_codeRaw 16-bit ADEXDR0 result code (signed value).
[out]out_passTrue iff ERR == 0 and the result is within the expected-value tolerance band.
Returns
ra8_err_t Status code.
Return values
k_ra8_okDiagnosis ran (inspect out_pass).
k_ra8_err_null_ptrout_code or out_pass is nullptr.
k_ra8_err_invalid_argmode is not 1 / 2 / 3.
k_ra8_err_hw_timeoutADSR.ADACT0 never cleared.
Precondition
ra8_adc_init (or ra8_adc_init_configured) has been called.
IRQs masked or single-threaded so no other scan races the group.
Postcondition
ADSGDCRn.DIAGVAL for the dedicated diagnostic group is back to 0.
out_code and out_pass are written on every k_ra8_ok return.
Note
Not thread-safe; serialise with normal conversions.
Tolerance band is a gross-fault detector; tighten it to the HUM Ch 69 accuracy spec for production sign-off.
See also
ra8_adc_selfdiag_mode_t
Since
0.1.0

Definition at line 351 of file adc_selfdiag.c.

References internal_diagval_for_mode(), internal_selfdiag_expected(), internal_selfdiag_in_band(), internal_selfdiag_run(), k_ra8_adc_b_chan_selfdiag_adc0, k_ra8_adc_b_ext_chan_base, k_ra8_adexdr_mask_data, k_ra8_adexdr_mask_err, k_ra8_err_invalid_arg, k_ra8_ok, ra8_adc_b_adexdr(), RA8_CHECK_NULL_PTR, RA8_RETURN_ON_ERROR, and s_tag.

Referenced by adc_diag_run_cycle().

Variable Documentation

◆ s_tag

const char* s_tag = "ADC"
static

Definition at line 36 of file adc_selfdiag.c.