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

On-chip Temperature Sensor (TSN) driver implementation. More...

#include "ra8_tsn.h"
#include <stdint.h>
#include "ra8_adc.h"
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_hw_intrinsics.h"
#include "ra8_log.h"
#include "ra8_mstp.h"
#include "ra8_tsn_regs.h"
Include dependency graph for ra8_tsn.c:

Go to the source code of this file.

Enumerations

enum  ra8_tsn_internal_t : uint16_t {
  k_ra8_tsn_min_stab_us = 30U ,
  k_ra8_tsn_busy_loops_per_us = 1000U
}
 Driver-internal magic values. More...

Functions

static void internal_busy_wait_us (uint16_t usec)
 Coarse software busy-wait used during init.
static ra8_err_t internal_validate_cfg (const ra8_tsn_config_t *cfg)
 Validate the high/low reference temperatures in a config.
ra8_err_t ra8_tsn_init (const ra8_tsn_config_t *cfg)
 Power on the TSN block and enable its ADC output path.
ra8_err_t ra8_tsn_deinit (void)
 Tear down the TSN block.
ra8_err_t ra8_tsn_read_raw (uint16_t raw, uint16_t *out_code)
 Pass through a raw ADC sample of the TSN channel.
ra8_err_t ra8_tsn_convert_to_milli_c (uint16_t raw_code, int32_t *out_milli_c)
 Convert a raw 12-bit TSN code to milli-degrees-Celsius.
ra8_err_t ra8_tsn_read_die_temp_milli_c (int32_t *out_milli_c)
 Read the die temperature end-to-end through the HAL.
ra8_err_t ra8_tsn_get_status (uint8_t *out_tscr)
 Read TSCR (TSEN + TSOE bits).
ra8_err_t ra8_tsn_clear_status (void)
 Clear TSCR (drive both TSEN and TSOE low).
ra8_err_t ra8_tsn_enter_stop (void)
 Re-assert MSTPD22 to clock-gate the TSN block.
ra8_err_t ra8_tsn_exit_stop (void)
 Clear MSTPD22 to re-power the TSN block.

Variables

static const char * s_tag = "TSN"
static bool s_ra8_tsn_initialized
 Tracks whether ra8_tsn_init has run successfully.
static int16_t s_ra8_tsn_high_ref_degc = k_ra8_tsn_cal_temp_high_125
 Cached high-side calibration temperature.
static int16_t s_ra8_tsn_low_ref_degc = k_ra8_tsn_cal_temp_low_n40
 Cached low-side calibration temperature (always -40).

Detailed Description

On-chip Temperature Sensor (TSN) driver implementation.

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

Owns TSCR (HUM Ch 55.2.1 p 3498) and the two-point calibration math (HUM Ch 55.3.1 p 3499-3500). Does not touch the ADC – callers must drive the ADC themselves; adc.c exposes the channel-select path (HUM Ch 53 "16-bit A/D Converter").

Definition in file ra8_tsn.c.

Enumeration Type Documentation

◆ ra8_tsn_internal_t

enum ra8_tsn_internal_t : uint16_t

Driver-internal magic values.

  • k_ra8_tsn_min_stab_us matches HUM Figure 55.2 (p 3502) tTSTBL = 30 us; ra8_tsn_init rejects shorter waits.
  • k_ra8_tsn_busy_loops_per_us is a worst-case lower bound on the empty-loop count needed to absorb 1 us at the Cortex-M85 1 GHz ceiling. Real hardware will spin-wait longer; the driver only needs the floor to be safe.
Enumerator
k_ra8_tsn_min_stab_us 

tTSTBL spec floor.

k_ra8_tsn_busy_loops_per_us 

Conservative spin count.

Definition at line 45 of file ra8_tsn.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 currently expose a microsecond busy-wait helper; ra8_delay_ms() is the only timed primitive and its 1 ms granularity vastly overshoots the 30 us tTSTBL floor. For a one-shot path that runs only at init it is acceptable to burn an empty loop. The loop body calls ra8_hw_nop, which is a real nop on the target (so the compiler cannot optimise the spin away) and a host no-op through the ra8_hw_intrinsics seam, which is fine because the host has no timing requirement.

Parameters
[in]usecMicroseconds to spin (>= k_ra8_tsn_min_stab_us).
Precondition
usec >= 1.
Caller has IRQs masked (otherwise the wait stretches but never shortens, which is harmless).
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 101 of file ra8_tsn.c.

References k_ra8_tsn_busy_loops_per_us, and ra8_hw_nop().

Referenced by ra8_tsn_init().

◆ internal_validate_cfg()

ra8_err_t internal_validate_cfg ( const ra8_tsn_config_t * cfg)
static

Validate the high/low reference temperatures in a config.

Parameters
[in]cfgCaller-supplied descriptor (must be non-null).
Returns
k_ra8_ok if the trim selection is one of the RA8D2-supported pairs, else k_ra8_err_invalid_arg.
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 129 of file ra8_tsn.c.

References ra8_tsn_config_t::high_ref_degc, k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_tsn_cal_temp_high_105, k_ra8_tsn_cal_temp_high_125, k_ra8_tsn_cal_temp_low_n40, k_ra8_tsn_min_stab_us, ra8_tsn_config_t::low_ref_degc, and ra8_tsn_config_t::stab_us.

Referenced by ra8_tsn_init().

◆ ra8_tsn_clear_status()

ra8_err_t ra8_tsn_clear_status ( void )
nodiscard

Clear TSCR (drive both TSEN and TSOE low).

Returns
ra8_err_t Status code.
Return values
k_ra8_okAlways.
Precondition
TSN module-stop is cleared so the write actually lands.
Caller has accepted that this stops the sensor immediately.
Postcondition
TSCR == 0.
Sensor output is no longer driven onto the ADC mux.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 283 of file ra8_tsn.c.

References k_ra8_ok, ra8_tsn(), and r_tsn_ctrl_regs_t::TSCR.

◆ ra8_tsn_convert_to_milli_c()

ra8_err_t ra8_tsn_convert_to_milli_c ( uint16_t raw_code,
int32_t * out_milli_c )
nodiscard

Convert a raw 12-bit TSN code to milli-degrees-Celsius.

Two-point trim conversion (HUM Ch 55.3.1 p 3499-3500):

v1_uv = AVCC_uV * CAL_HI / 4096 v2_uv = AVCC_uV * CAL_LO / 4096 vs_uv = AVCC_uV * raw / 4096 T_mC = ((vs_uv - v1_uv) * (T1 - T2) * 1000) / (v1_uv - v2_uv)

  • T1 * 1000

Everything stays in 64-bit signed integer arithmetic so the driver can run on the Cortex-M85 without pulling in libm.

Parameters
[in]raw_code12-bit ADC code from ra8_tsn_read_raw.
[out]out_milli_cTemperature in milli-degC (+25000 = 25 degC).
Returns
ra8_err_t Status code.
Return values
k_ra8_okConversion succeeded.
k_ra8_err_null_ptrout_milli_c was nullptr.
k_ra8_err_invalid_statera8_tsn_init has not run, or the calibration words are 0 (would divide by zero).
Precondition
ra8_tsn_init has been called.
raw_code <= 0x0FFF.
Postcondition
*out_milli_c populated when the call returns k_ra8_ok.
No peripheral registers were written.
Note
Thread safety: re-entrant – reads MMIO only.
See also
ra8_tsn_read_raw
Since
0.1.0

Definition at line 214 of file ra8_tsn.c.

References k_ra8_err_invalid_state, k_ra8_ok, k_ra8_tscdr_data_mask, k_ra8_tsn_adc_avcc_uv, k_ra8_tsn_adc_full_scale, k_ra8_tsn_uv_per_mv, RA8_CHECK_NULL_PTR, ra8_tsn_cal(), s_ra8_tsn_high_ref_degc, s_ra8_tsn_initialized, s_ra8_tsn_low_ref_degc, s_tag, r_tsn_cal_regs_t::TSCDR, and r_tsn_cal_regs_t::TSCDR2.

Referenced by ra8_tsn_read_die_temp_milli_c().

◆ ra8_tsn_deinit()

ra8_err_t ra8_tsn_deinit ( void )
nodiscard

Tear down the TSN block.

Clears TSCR.TSOE then TSCR.TSEN (HUM Figure 55.2 p 3502 reverse sequence) and then re-asserts MSTPD22 via ra8_mstp_disable.

Returns
ra8_err_t Status code.
Return values
k_ra8_okSensor stopped and module-stop reasserted.
OtherForwarded from ra8_mstp_disable.
Precondition
Caller has previously called ra8_tsn_init.
No outstanding ADC conversion targeting the TSN channel.
Postcondition
TSCR.TSEN = 0 and TSCR.TSOE = 0.
MSTPD22 is set (block clock-gated).
Note
Thread safety: not thread-safe.
See also
ra8_tsn_init
Since
0.1.0

Definition at line 180 of file ra8_tsn.c.

References k_ra8_mstp_tsn, k_ra8_ok, k_ra8_tscr_mask_tsen, ra8_mstp_disable(), ra8_tsn(), s_ra8_tsn_initialized, and r_tsn_ctrl_regs_t::TSCR.

◆ ra8_tsn_enter_stop()

ra8_err_t ra8_tsn_enter_stop ( void )
nodiscard

Re-assert MSTPD22 to clock-gate the TSN block.

Returns
ra8_err_t Status code.
Return values
k_ra8_okModule-stop bit asserted.
OtherForwarded from ra8_mstp_disable.
Precondition
Caller has stopped any in-flight ADC conversion that targets the TSN channel.
ra8_mstp_init has been called.
Postcondition
MSTPD22 = 1.
Subsequent TSCR reads return 0 until ra8_tsn_exit_stop.
Note
Thread safety: not thread-safe.
See also
ra8_tsn_exit_stop
Since
0.1.0

Definition at line 291 of file ra8_tsn.c.

References k_ra8_mstp_tsn, and ra8_mstp_disable().

◆ ra8_tsn_exit_stop()

ra8_err_t ra8_tsn_exit_stop ( void )
nodiscard

Clear MSTPD22 to re-power the TSN block.

Returns
ra8_err_t Status code.
Return values
k_ra8_okModule-stop bit cleared.
OtherForwarded from ra8_mstp_enable.
Precondition
ra8_mstp_init has been called.
Caller will re-run the TSEN / tTSTBL / TSOE sequence before reading any new conversion.
Postcondition
MSTPD22 = 0.
TSCR is back to its reset value (0).
Note
Thread safety: not thread-safe.
See also
ra8_tsn_enter_stop
Since
0.1.0

Definition at line 297 of file ra8_tsn.c.

References k_ra8_mstp_tsn, and ra8_mstp_enable().

◆ ra8_tsn_get_status()

ra8_err_t ra8_tsn_get_status ( uint8_t * out_tscr)
nodiscard

Read TSCR (TSEN + TSOE bits).

Parameters
[out]out_tscrReceives the current TSCR value (only k_ra8_tscr_mask_all bits are valid).
Returns
ra8_err_t Status code.
Return values
k_ra8_ok*out_tscr populated.
k_ra8_err_null_ptrout_tscr was nullptr.
Precondition
TSN module-stop is cleared (otherwise the read returns 0).
out_tscr is non-null.
Postcondition
No registers were written.
*out_tscr populated when the call returns k_ra8_ok.
Note
Thread safety: re-entrant.
Since
0.1.0

Definition at line 274 of file ra8_tsn.c.

References k_ra8_ok, k_ra8_tscr_mask_all, RA8_CHECK_NULL_PTR, ra8_tsn(), s_tag, and r_tsn_ctrl_regs_t::TSCR.

◆ ra8_tsn_init()

ra8_err_t ra8_tsn_init ( const ra8_tsn_config_t * cfg)
nodiscard

Power on the TSN block and enable its ADC output path.

Algorithm (HUM Figure 55.2 p 3502 condensed for the case where TEMPRCR.TSNKEEP is left at its reset value):

  1. Validate cfg and the configured stabilisation delay.
  2. Clear MSTPD22 via ra8_mstp_enable(k_ra8_mstp_tsn) (HUM Ch 11.2.9 p 449).
  3. Set TSCR.TSEN = 1 to start the sensor.
  4. Busy-wait cfg->stab_us microseconds (>= 30 us per the HUM tTSTBL spec).
  5. Set TSCR.TSOE = 1 to route the sensor output to the ADC16H input mux. The ADC itself is not touched here – driving the ADC channel select stays the caller's job (see libs/ra8_hal/src/adc.c and the ADC chapter, HUM Ch 53).
Parameters
[in]cfgNon-null configuration descriptor.
Returns
ra8_err_t Status code.
Return values
k_ra8_okSensor enabled and routed to the ADC.
k_ra8_err_null_ptrcfg was nullptr.
k_ra8_err_invalid_argcfg->stab_us below the 30 us floor or calibration temperatures invalid.
OtherForwarded from ra8_mstp_enable.
Precondition
IRQs masked or single-threaded init context.
ra8_mstp_init has been called.
AVCC0 / VREFH0 are stable (3.3 V).
Postcondition
TSCR.TSEN = 1 and TSCR.TSOE = 1.
The 30 us reference-voltage stabilisation has elapsed.
Note
Thread safety: not thread-safe; call once during init.
The driver does not start an ADC conversion. Callers must drive the ADC themselves.
Example:
const ra8_tsn_config_t cfg = {
.high_ref_degc = k_ra8_tsn_cal_temp_high_125,
.low_ref_degc = k_ra8_tsn_cal_temp_low_n40,
.stab_us = 30,
};
(void)ra8_tsn_init(&cfg);
ra8_err_t ra8_tsn_init(const ra8_tsn_config_t *cfg)
Power on the TSN block and enable its ADC output path.
Definition ra8_tsn.c:149
@ k_ra8_tsn_cal_temp_high_125
125 degC Tj_max parts.
Definition ra8_tsn.h:99
@ k_ra8_tsn_cal_temp_low_n40
Always -40 degC on RA8D2.
Definition ra8_tsn.h:101
Configuration descriptor for ra8_tsn_init.
Definition ra8_tsn.h:121
See also
ra8_tsn_deinit
ra8_tsn_read_raw
ra8_tsn_convert_to_milli_c
Since
0.1.0

Definition at line 149 of file ra8_tsn.c.

References ra8_tsn_config_t::high_ref_degc, internal_busy_wait_us(), internal_validate_cfg(), k_ra8_mstp_tsn, k_ra8_ok, k_ra8_tscr_mask_tsen, k_ra8_tscr_mask_tsoe, ra8_tsn_config_t::low_ref_degc, RA8_CHECK_NULL_PTR, ra8_log_info, ra8_mstp_enable(), RA8_RETURN_ON_ERROR, ra8_tsn(), s_ra8_tsn_high_ref_degc, s_ra8_tsn_initialized, s_ra8_tsn_low_ref_degc, s_tag, ra8_tsn_config_t::stab_us, and r_tsn_ctrl_regs_t::TSCR.

Referenced by adc_diag_arm().

◆ ra8_tsn_read_die_temp_milli_c()

ra8_err_t ra8_tsn_read_die_temp_milli_c ( int32_t * out_milli_c)
nodiscard

Read the die temperature end-to-end through the HAL.

Closes the loop that ra8_tsn_read_raw deliberately leaves to the caller: it drives the ADC16H temperature-sensor channel (CNVCS = 0x64, HUM Ch 53.2.3.1 Table p 3335) via ra8_adc_read_internal_channel, masks the raw 12-bit code through ra8_tsn_read_raw, then runs the two-point trim conversion (ra8_tsn_convert_to_milli_c). The result register for the temperature channel is ADEXDR4 (HUM Ch 53.2.13.2 p 3391); that routing lives in adc.c.

Parameters
[out]out_milli_cTemperature in milli-degC (+25000 = 25 degC).
Returns
ra8_err_t Status code.
Return values
k_ra8_okTemperature read and converted.
k_ra8_err_null_ptrout_milli_c was nullptr.
k_ra8_err_invalid_statera8_tsn_init has not run, or the calibration words are unprogrammed.
k_ra8_err_hw_timeoutThe ADC conversion never completed.
k_ra8_err_out_of_rangeThe temperature ADEXDR slot was unmapped.
Precondition
ra8_tsn_init has routed the sensor to the ADC mux (TSCR.TSOE).
ra8_adc_init has powered and clocked the ADC16H.
Postcondition
*out_milli_c populated when the call returns k_ra8_ok.
No TSN registers were written (only the ADC was driven).
Note
Thread safety: not thread-safe; serialise with other ADC use.
See also
ra8_tsn_convert_to_milli_c
ra8_tsn_read_raw
Since
0.1.0

Definition at line 249 of file ra8_tsn.c.

References k_ra8_adc_chan_temperature, k_ra8_err_invalid_state, ra8_adc_read_internal_channel(), RA8_CHECK_NULL_PTR, RA8_RETURN_ON_ERROR, ra8_tsn_convert_to_milli_c(), ra8_tsn_read_raw(), s_ra8_tsn_initialized, and s_tag.

Referenced by adc_diag_run_cycle().

◆ ra8_tsn_read_raw()

ra8_err_t ra8_tsn_read_raw ( uint16_t raw,
uint16_t * out_code )
nodiscard

Pass through a raw ADC sample of the TSN channel.

The TSN block has no result register of its own – the conversion code lives in the ADC's data register. The caller arms the ADC (see ra8_adc.h and ADC chapter HUM Ch 53), reads the raw 12-bit code, and hands it here. This function masks the value down to the documented 12-bit width and returns it via out_code. It exists so that future callers can be retargeted at a different conversion path (for example the high-resolution accumulator) without changing their call sites.

Parameters
[in]rawRaw ADC code as read from the ADC's data register. Only the lower 12 bits are observed (HUM Ch 55.2.2 p 3498-3499: calibration codes are 12-bit, so live samples are too).
[out]out_codeReceives the masked 12-bit code.
Returns
ra8_err_t Status code.
Return values
k_ra8_okCode stored in *out_code.
k_ra8_err_null_ptrout_code was nullptr.
k_ra8_err_invalid_stateTSCR.TSEN is 0 (sensor not started).
Precondition
ra8_tsn_init has been called.
Caller already obtained the raw ADC code.
Postcondition
*out_code <= 0x0FFF.
No registers were written.
Note
Thread safety: not thread-safe.
See also
ra8_tsn_convert_to_milli_c
Since
0.1.0

Definition at line 202 of file ra8_tsn.c.

References k_ra8_err_invalid_state, k_ra8_ok, k_ra8_tscdr_data_mask, RA8_CHECK_NULL_PTR, s_ra8_tsn_initialized, and s_tag.

Referenced by ra8_tsn_read_die_temp_milli_c().

Variable Documentation

◆ s_ra8_tsn_high_ref_degc

int16_t s_ra8_tsn_high_ref_degc = k_ra8_tsn_cal_temp_high_125
static

Cached high-side calibration temperature.

Populated from ra8_tsn_config_t::high_ref_degc so ra8_tsn_convert_to_milli_c can run without a config pointer. Defaults to 125 until init has run.

Definition at line 67 of file ra8_tsn.c.

Referenced by ra8_tsn_convert_to_milli_c(), and ra8_tsn_init().

◆ s_ra8_tsn_initialized

bool s_ra8_tsn_initialized
static

Tracks whether ra8_tsn_init has run successfully.

Note
Read by ra8_tsn_read_raw / ra8_tsn_convert_to_milli_c to refuse work before init.

Definition at line 57 of file ra8_tsn.c.

Referenced by ra8_tsn_convert_to_milli_c(), ra8_tsn_deinit(), ra8_tsn_init(), ra8_tsn_read_die_temp_milli_c(), and ra8_tsn_read_raw().

◆ s_ra8_tsn_low_ref_degc

int16_t s_ra8_tsn_low_ref_degc = k_ra8_tsn_cal_temp_low_n40
static

Cached low-side calibration temperature (always -40).

Definition at line 73 of file ra8_tsn.c.

Referenced by ra8_tsn_convert_to_milli_c(), and ra8_tsn_init().

◆ s_tag

const char* s_tag = "TSN"
static

Definition at line 31 of file ra8_tsn.c.