ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
adc_selfdiag.c
Go to the documentation of this file.
1
25
26#include <stdint.h>
27
28#include "adc_internal.h"
29#include "ra8_adc.h"
30#include "ra8_adc_b_regs.h"
31#include "ra8_attributes.h"
32#include "ra8_check.h"
33#include "ra8_err.h"
34#include "ra8_log.h"
35
36static const char* s_tag = "ADC";
37
38/* The public ra8_adc_internal_chan_t values must mirror the register-header
39 * CNVCS codes so ra8_adc_b_adexdr_index_for_chan() maps them correctly. */
40static_assert((uint8_t)k_ra8_adc_chan_temperature == (uint8_t)k_ra8_adc_b_chan_temperature,
41 "temperature CNVCS code drift between ra8_adc.h and ra8_adc_b_regs.h");
42static_assert((uint8_t)k_ra8_adc_chan_int_ref_volt == (uint8_t)k_ra8_adc_b_chan_int_ref_volt,
43 "internal-Vref CNVCS code drift between ra8_adc.h and ra8_adc_b_regs.h");
44
55typedef enum : uint8_t {
59
72
86typedef enum : int32_t {
89
109 uint32_t* out_diagval)
110{
111 switch (mode) {
113 *out_diagval = (uint32_t)k_ra8_adsgdcr_diag_mode1;
114 return true;
116 *out_diagval = (uint32_t)k_ra8_adsgdcr_diag_mode2;
117 return true;
119 *out_diagval = (uint32_t)k_ra8_adsgdcr_diag_mode3;
120 return true;
121 default:
122 return false;
123 }
124}
125
144{
145 switch (mode) {
147 return (int32_t)k_ra8_adc_selfdiag_expect_mode2;
149 return (int32_t)k_ra8_adc_selfdiag_expect_mode3;
151 default:
152 return (int32_t)k_ra8_adc_selfdiag_expect_mode1;
153 }
154}
155
174{
175 return (diff <= (int32_t)k_ra8_adc_selfdiag_tol_lsb) &&
176 (diff >= -(int32_t)k_ra8_adc_selfdiag_tol_lsb);
177}
178
200
217RA8_INTERNAL static void
218internal_program_ext_channel(uint8_t vch, uint8_t physical_ch, uint8_t group, bool differential)
219{
220 volatile uint32_t* reg = ra8_adc_b_adchcr(vch);
221 if (reg == nullptr) {
222 return;
223 }
224 const uint32_t cnvcs =
225 ((uint32_t)physical_ch << (uint32_t)k_ra8_adchcr_bit_cnvcs) & k_ra8_adchcr_mask_cnvcs;
226 const uint32_t sgsel =
227 ((uint32_t)group << (uint32_t)k_ra8_adchcr_bit_sgsel) & k_ra8_adchcr_mask_sgsel;
228 const uint32_t ainmd =
229 differential ? (((uint32_t)1UL << (uint32_t)k_ra8_adchcr_bit_ainmd) & k_ra8_adchcr_mask_ainmd)
230 : 0UL;
231 /* HUM Ch 53.2.3.1 "ADCHCRn : A/D Conversion Channel Configuration Register n" p 3335 */
232 *reg = (cnvcs | sgsel | ainmd);
233}
234
250RA8_INTERNAL static void internal_set_data_format(uint8_t vch, uint8_t adprc, uint8_t signsel)
251{
252 volatile uint32_t* reg = ra8_adc_b_addopcrc(vch);
253 if (reg == nullptr) {
254 return;
255 }
256 const uint32_t adprc_field =
257 ((uint32_t)adprc << (uint32_t)k_ra8_addopcrc_bit_adprc) & k_ra8_addopcrc_mask_adprc;
258 const uint32_t sign_field =
259 ((uint32_t)signsel << (uint32_t)k_ra8_addopcrc_bit_signsel) & k_ra8_addopcrc_mask_signsel;
260 /* HUM Ch 53.2.3.4 "ADDOPCRCn : A/D Conversion Data Operation Control C Register n" p 3339 */
261 const uint32_t cleared = *reg & ~(k_ra8_addopcrc_mask_adprc | k_ra8_addopcrc_mask_signsel);
262 *reg = (cleared | adprc_field | sign_field);
263}
264
284{
285 volatile uint32_t* adstr = ra8_adc_b_adstr(group);
286 if (adstr == nullptr) {
288 }
289 /* HUM Ch 53 "16-bit A/D Converter (ADC16H)" p 3308 */
290 *adstr = k_ra8_adstr_mask_adst;
291 /* HUM Ch 53 "16-bit A/D Converter (ADC16H)" p 3308 */
292 for (uint32_t i = 0U; i < k_ra8_adc_busy_wait_limit; ++i) {
293 if ((*ra8_adc_b_adsr() & k_ra8_adsr_mask_adact0) == 0U) {
294 return k_ra8_ok;
295 }
296 }
298}
299
324{
327 (uint8_t)k_ra8_adc_diag_group,
328 true);
332
333 /* HUM Ch 53 "16-bit A/D Converter (ADC16H)" p 3308 */
334 *ra8_adc_b_adsger() |= (uint32_t)(1UL << (uint32_t)k_ra8_adc_diag_group);
335
336 /* HUM Ch 53.2.4.1 "ADSGDCRn : Scan Group Diagnosis Function Control Register n" p 3340 */
337 volatile uint32_t* sgdcr = ra8_adc_b_adsgdcr((uint8_t)k_ra8_adc_diag_group);
338 *sgdcr = (*sgdcr & ~k_ra8_adsgdcr_mask_diagval) |
339 ((diagval << (uint32_t)k_ra8_adsgdcr_bit_diagval) & k_ra8_adsgdcr_mask_diagval);
340
342
343 /* Always return DIAGVAL to off so later normal scans on this group are
344 * not stuck in diagnosis mode (HUM Ch 53.2.4.1 p 3340). */
345 /* HUM Ch 53.2.4.1 "ADSGDCRn : Scan Group Diagnosis Function Control Register n" p 3340 */
346 *sgdcr = *sgdcr & ~k_ra8_adsgdcr_mask_diagval;
347
348 return run_err;
349}
350
351ra8_err_t ra8_adc_self_diagnose(ra8_adc_selfdiag_mode_t mode, uint16_t* out_code, bool* out_pass)
352{
353 RA8_CHECK_NULL_PTR(out_code, s_tag, "out_code must not be nullptr");
354 RA8_CHECK_NULL_PTR(out_pass, s_tag, "out_pass must not be nullptr");
355 *out_code = 0U;
356 *out_pass = false;
357
358 uint32_t diagval = 0U;
359 if (!internal_diagval_for_mode(mode, &diagval)) {
361 }
362
363 const ra8_err_t run_err = internal_selfdiag_run(diagval);
364 RA8_RETURN_ON_ERROR(run_err, s_tag, "self_diagnose: conversion");
365
366 /* HUM Ch 53.2.13.2 "ADEXDRn : A/D Extended Analog Data Register n" p 3391 */
367 const uint32_t exd =
369 const uint16_t data = (uint16_t)(exd & k_ra8_adexdr_mask_data);
370 const bool err_flag = (exd & k_ra8_adexdr_mask_err) != 0U;
371
372 const int32_t actual = (int32_t)(int16_t)data; /* signed format (SIGNSEL=0). */
373 const int32_t expected = internal_selfdiag_expected(mode);
374 const bool in_band = internal_selfdiag_in_band(actual - expected);
375
376 *out_code = data;
377 *out_pass = (!err_flag) && in_band;
378 return k_ra8_ok;
379}
380
382{
383 RA8_CHECK_NULL_PTR(out_raw, s_tag, "out_raw must not be nullptr");
384 *out_raw = 0U;
387 }
388
389 /* Single-ended, 12-bit unsigned so the code lines up with the 12-bit
390 * scale used by the TSN two-point calibration (HUM Ch 55.2.2 p 3498). */
392 (uint8_t)chan,
393 (uint8_t)k_ra8_adc_diag_group,
394 false);
398
399 /* HUM Ch 53 "16-bit A/D Converter (ADC16H)" p 3308 */
400 *ra8_adc_b_adsger() |= (uint32_t)(1UL << (uint32_t)k_ra8_adc_diag_group);
401
403 /* GCOVR_EXCL_BR_START -- HW convert timing */
404 RA8_RETURN_ON_ERROR(run_err, s_tag, "read_internal: conversion");
405 /* GCOVR_EXCL_BR_STOP */
406
407 const uint8_t idx = ra8_adc_b_adexdr_index_for_chan((uint8_t)chan);
408 volatile const uint32_t* exd = ra8_adc_b_adexdr(idx);
409 if (exd == nullptr) {
411 }
412 /* HUM Ch 53.2.13.2 "ADEXDRn : A/D Extended Analog Data Register n" p 3391 */
413 *out_raw = (uint16_t)(*exd & k_ra8_adexdr_mask_data);
414 return k_ra8_ok;
415}
Cross-TU constants shared by the ADC_B driver split.
@ k_ra8_adc_busy_wait_limit
ADSR.ADACT busy-poll budget.
static int32_t internal_selfdiag_expected(ra8_adc_selfdiag_mode_t mode)
Ideal signed self-diagnosis result for a mode.
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.
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.
ra8_adc_diag_slot_t
Dedicated virtual-channel / scan-group used for diagnostic reads.
@ k_ra8_adc_diag_group
Dedicated scan group for diagnostic reads.
@ k_ra8_adc_diag_vchan
Dedicated ADCHCR slot for diagnostic reads.
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.
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_adc_selfdiag_expect_t
Ideal 16-bit signed self-diagnosis result per mode.
@ k_ra8_adc_selfdiag_expect_mode1
0x0000.
@ k_ra8_adc_selfdiag_expect_mode3
0x7FFF.
@ k_ra8_adc_selfdiag_expect_mode2
0x8000.
static bool internal_selfdiag_in_band(int32_t diff)
Test whether a signed deviation is inside the tolerance band.
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.
ra8_adc_selfdiag_tol_t
Allowed absolute deviation from the ideal self-diagnosis result.
@ k_ra8_adc_selfdiag_tol_lsb
+/- LSB tolerance about the ideal.
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.
Full-featured ADC_B driver.
ra8_adc_internal_chan_t
Internal / extended-analog channels readable through the HAL.
Definition ra8_adc.h:535
@ k_ra8_adc_chan_temperature
On-chip die-temperature sensor.
Definition ra8_adc.h:536
@ k_ra8_adc_chan_int_ref_volt
Internal reference voltage.
Definition ra8_adc.h:537
ra8_adc_selfdiag_mode_t
ADC_B built-in self-diagnosis modes (HUM Ch 53.3.11 p 3411-3414).
Definition ra8_adc.h:516
@ k_ra8_adc_selfdiag_mode_3
Positive full-scale.
Definition ra8_adc.h:519
@ k_ra8_adc_selfdiag_mode_2
Negative full-scale.
Definition ra8_adc.h:518
@ k_ra8_adc_selfdiag_mode_1
Zero-differential reference.
Definition ra8_adc.h:517
ADC16H (16-bit SAR) register layout for the Renesas RA8D2 / RA8P1.
@ k_ra8_adc_b_chan_int_ref_volt
Internal reference voltage.
@ k_ra8_adc_b_chan_selfdiag_adc0
Self-diagnosis A/D unit 0.
@ k_ra8_adc_b_chan_temperature
On-chip temperature sensor.
@ k_ra8_adexdr_mask_data
DATA[15:0] conversion result.
@ k_ra8_adexdr_mask_err
ERR conversion-error flag.
@ k_ra8_addopcrc_adprc_12bit
12-bit data.
@ k_ra8_addopcrc_adprc_16bit
16-bit data.
static volatile uint32_t * ra8_adc_b_addopcrc(uint8_t ch)
Pointer to the per-virtual-channel ADDOPCRC[n] register.
@ k_ra8_adchcr_mask_cnvcs
[14:8]
@ k_ra8_adchcr_mask_ainmd
[15]
@ k_ra8_adchcr_mask_sgsel
[4:0]
@ k_ra8_adsgdcr_mask_diagval
DIAGVAL[2:0].
@ k_ra8_adchcr_bit_sgsel
Scan group selection.
@ k_ra8_adchcr_bit_ainmd
Analog input mode (single/diff).
@ k_ra8_adchcr_bit_cnvcs
Physical channel selection.
@ k_ra8_adsgdcr_bit_diagval
Self-diagnosis mode select [2:0].
@ k_ra8_adsgdcr_diag_mode3
Mode 3: positive FS (0x7FFF).
@ k_ra8_adsgdcr_diag_mode2
Mode 2: negative FS (0x8000).
@ k_ra8_adsgdcr_diag_mode1
Mode 1: zero differential (0x0000).
@ k_ra8_addopcrc_mask_signsel
SIGNSEL.
@ k_ra8_addopcrc_mask_adprc
ADPRC[1:0].
static volatile uint32_t * ra8_adc_b_adstr(uint8_t group)
Pointer to the per-scan-group ADSTR[n] register.
static uint8_t ra8_adc_b_adexdr_index_for_chan(uint8_t cnvcs)
Map a CNVCS extended-channel code to its ADEXDR index.
@ k_ra8_adstr_mask_adst
RA8 adstr mask adst.
static volatile uint32_t * ra8_adc_b_adchcr(uint8_t ch)
Pointer to the per-virtual-channel ADCHCR register.
@ k_ra8_adsr_mask_adact0
RA8 adsr mask adact0.
@ k_ra8_addopcrc_signsel_unsigned
Unsigned data format.
@ k_ra8_addopcrc_signsel_signed
Signed data format.
@ k_ra8_adc_b_ext_chan_base
ADEXDR index n = CNVCS - this.
@ k_ra8_addopcrc_bit_signsel
Signed/unsigned select [20].
@ k_ra8_addopcrc_bit_adprc
Data-format select [17:16].
static volatile uint32_t * ra8_adc_b_adexdr(uint8_t n)
Pointer to the ADEXDR[n] extended-analog result register.
static volatile uint32_t * ra8_adc_b_adsgdcr(uint8_t group)
Pointer to the per-scan-group ADSGDCR[n] register (self-diagnosis).
static volatile uint32_t * ra8_adc_b_adsger(void)
Pointer to the 32-bit ADSGER register (scan-group enable).
static volatile uint32_t * ra8_adc_b_adsr(void)
Pointer to the 32-bit ADSR register (status).
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_RETURN_ON_ERROR(err, tag, message)
Early return on error, propagating the code upward.
Definition ra8_check.h:184
#define RA8_CHECK_NULL_PTR(ptr, tag, message)
Reject nullptr pointer, returning k_ra8_err_null_ptr.
Definition ra8_check.h:243
Error Code Definitions for ra8-firmware.
@ k_ra8_err_out_of_range
Sensor or peripheral output out of valid range.
Definition ra8_err.h:337
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_err_hw_timeout
Hardware timed out waiting for a flag or handshake.
Definition ra8_err.h:304
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Lightweight Logging Interface for ra8-firmware.