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

NSC veneers for the communications drivers. More...

#include "ra8_nsc_comms.h"
#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_i3c.h"
#include "ra8_nsc_veneer.h"
#include "ra8_sci.h"
#include "ra8_spi.h"
#include "ra8_usb.h"
Include dependency graph for ra8_nsc_comms.c:

Go to the source code of this file.

Functions

ra8_err_t ra8_nsc_sci_init (uint8_t channel, const ra8_sci_cfg_t *cfg)
 NSC veneer: bring up an SCI channel from Non-Secure code.
ra8_err_t ra8_nsc_sci_putc (uint8_t channel, uint8_t byte)
 NSC veneer: blocking single-byte SCI write.
ra8_err_t ra8_nsc_sci_getc (uint8_t channel, uint8_t *out_byte)
 NSC veneer: blocking single-byte SCI read.
ra8_err_t ra8_nsc_iic_init (uint8_t channel, const ra8_i3c_cfg_t *cfg)
 NSC veneer: bring up an IIC (I2C-B) channel from NS code.
ra8_err_t ra8_nsc_iic_write (uint8_t channel, uint8_t target_7b, const uint8_t *data, uint32_t len)
 NSC veneer: blocking I2C write to a 7-bit target.
ra8_err_t ra8_nsc_iic_read (uint8_t channel, uint8_t target_7b, uint8_t *out_buf, uint32_t len)
 NSC veneer: blocking I2C read from a 7-bit target.
ra8_err_t ra8_nsc_spi_init (uint8_t channel, const ra8_spi_cfg_t *cfg)
 NSC veneer: bring up an SPI controller channel from NS code.
ra8_err_t ra8_nsc_spi_xfer8 (uint8_t channel, uint8_t tx, uint8_t *rx)
 NSC veneer: full-duplex single-byte SPI exchange.
static uint8_t internal_spi_unit_bytes (ra8_spi_bit_width_t bit_width)
 Bytes-per-frame helper for the NSC SPI multi-byte veneers.
static bool internal_spi_byte_span (uint8_t bytes_per_unit, uint32_t len, uint32_t *out_span)
 Byte span of len frames at bytes_per_unit each, in 64-bit.
ra8_err_t ra8_nsc_spi_write (uint8_t channel, const void *tx, uint32_t len, ra8_spi_bit_width_t bit_width)
 NSC veneer: multi-frame TX-only polling SPI write.
ra8_err_t ra8_nsc_spi_read (uint8_t channel, void *rx, uint32_t len, ra8_spi_bit_width_t bit_width)
 NSC veneer: multi-frame RX-only polling SPI read.
ra8_err_t ra8_nsc_spi_write_read (uint32_t ch_bw, const void *tx, void *rx, uint32_t len)
 NSC veneer: multi-frame full-duplex polling SPI exchange.
ra8_err_t ra8_nsc_usb_init (ra8_usb_speed_t speed)
 NSC veneer: bring up the USB device controller.
ra8_err_t ra8_nsc_usb_attach (ra8_usb_speed_t speed, bool attached)
 NSC veneer: raise / drop the USB D+ pull-up.

Variables

static const char * s_tag = "NSCCOM"

Detailed Description

NSC veneers for the communications drivers.

Tag
[Ring 4 / NSC] {World: NSC}

retrofit. Each veneer validates pointer arguments (under TrustZone) then forwards to the secure-side Ring-3 driver primitive.

Definition in file ra8_nsc_comms.c.

Function Documentation

◆ internal_spi_byte_span()

bool internal_spi_byte_span ( uint8_t bytes_per_unit,
uint32_t len,
uint32_t * out_span )
static

Byte span of len frames at bytes_per_unit each, in 64-bit.

The SPI veneers must range-check the exact byte span a hostile Non-Secure caller's frame count spans before the secure driver touches it. Computing bytes_per_unit * len in 32-bit overflows for large len (e.g. len = 0x40000000 at width 32 wraps 4 GiB to 0), which would let the cmse_check_address_range argument truncate to a tiny span while the driver still transfers the full len – a hostile NS caller could shift secret Secure memory out over SPI. This computes the span in 64-bit and reports failure if it exceeds what the range check (a 32-bit length) can validate, so the veneer rejects rather than under-validating (T5-07).

Parameters
[in]bytes_per_unitBytes per frame (1, 2, or 4); non-zero.
[in]lenFrame count from the Non-Secure caller.
[out]out_spanReceives the byte span when the return is true. Must be non-NULL (every caller passes a stack slot).
Returns
Whether the span fits a 32-bit range-check length.
Return values
trueSpan computed and stored in *out_span.
falseThe span exceeds UINT32_MAX (would truncate the check).
Precondition
out_span is non-NULL.
bytes_per_unit is the validated 1/2/4 result of internal_spi_unit_bytes.
Postcondition
On false, *out_span is not written.
No hardware state is mutated.
Note
Static helper; pure function.
Since
0.1.0

Definition at line 398 of file ra8_nsc_comms.c.

Referenced by ra8_nsc_spi_read(), ra8_nsc_spi_write(), and ra8_nsc_spi_write_read().

◆ internal_spi_unit_bytes()

uint8_t internal_spi_unit_bytes ( ra8_spi_bit_width_t bit_width)
static

Bytes-per-frame helper for the NSC SPI multi-byte veneers.

Mirrors the bit-width -> byte mapping in ra8_spi_b.c so the veneer can size the NS-range check correctly. 0 signals an unsupported width (the underlying driver will then reject with k_ra8_err_invalid_arg).

Parameters
[in]bit_widthFrame width enum.
Returns
Bytes per frame: 1, 2, or 4.
Return values
0Unknown / unsupported width.
Precondition
bit_width is one of the documented enum values.
Postcondition
No state mutated.
Note
Static helper; pure function.
Since
0.1.0
Precondition
Module has been initialized.
Postcondition
Side effects bounded to documented state.

Definition at line 351 of file ra8_nsc_comms.c.

References k_ra8_spi_width_16, k_ra8_spi_width_32, and k_ra8_spi_width_8.

Referenced by ra8_nsc_spi_read(), ra8_nsc_spi_write(), and ra8_nsc_spi_write_read().

◆ ra8_nsc_iic_init()

ra8_err_t ra8_nsc_iic_init ( uint8_t channel,
const ra8_i3c_cfg_t * cfg )
nodiscard

NSC veneer: bring up an IIC (I2C-B) channel from NS code.

NSC veneer: bring up an IIC channel.

Validates the NS pointer to cfg then forwards to ra8_i3c_init.

Parameters
[in]channelIIC channel index.
[in]cfgCaller-supplied configuration in NS memory.
Returns
ra8_err_t outcome.
Return values
k_ra8_okChannel programmed.
k_ra8_err_null_ptrcfg was NULL.
k_ra8_err_invalid_argcfg not in NS region or channel bad.
Precondition
TrustZone substrate up.
cfg lies entirely within NS data region.
Postcondition
On success the IIC hardware is ready for I/O.
On failure no module state was mutated.
TrustZone:
NS->S boundary via cmse_nonsecure_entry. cfg is range-checked so a hostile NS pointer cannot leak secure-region bytes.
Note
Thread-safe: serialised by the secure IIC driver lock.
Since
0.1.0

Definition at line 167 of file ra8_nsc_comms.c.

References k_ra8_i3c_mode_i2c, ra8_i3c_cfg_t::mode, RA8_CHECK_NULL_PTR, ra8_i3c_init(), RA8_NSC_CHECK_NS_RANGE_R, RA8_NSC_VENEER, and s_tag.

◆ ra8_nsc_iic_read()

ra8_err_t ra8_nsc_iic_read ( uint8_t channel,
uint8_t target_7b,
uint8_t * out_buf,
uint32_t len )
nodiscard

NSC veneer: blocking I2C read from a 7-bit target.

Validates [out_buf, out_buf+len) lies in writable NS memory then forwards to ra8_i3c_read.

Parameters
[in]channelIIC channel index.
[in]target_7b7-bit peripheral address.
[out]out_bufNS destination buffer.
[in]lenByte count to read.
Returns
ra8_err_t outcome.
Return values
k_ra8_okBytes received into out_buf.
k_ra8_err_null_ptrout_buf was NULL.
k_ra8_err_invalid_argRange outside NS region.
Precondition
ra8_nsc_iic_init succeeded for channel.
[out_buf, out_buf+len) lies in NS data region.
Postcondition
On success out_buf holds len received bytes.
On failure out_buf content is undefined.
TrustZone:
NS->S boundary via cmse_nonsecure_entry. cmse_check_address_range guarantees the secure driver only writes to NS memory.
Note
Thread-safe: serialised by the secure IIC driver lock.
Since
0.1.0

Definition at line 244 of file ra8_nsc_comms.c.

References RA8_CHECK_NULL_PTR, ra8_i3c_read(), RA8_NSC_CHECK_NS_RANGE_RW, RA8_NSC_VENEER, and s_tag.

◆ ra8_nsc_iic_write()

ra8_err_t ra8_nsc_iic_write ( uint8_t channel,
uint8_t target_7b,
const uint8_t * data,
uint32_t len )
nodiscard

NSC veneer: blocking I2C write to a 7-bit target.

Validates [data, data+len) lies in NS memory then forwards to ra8_i3c_write.

Parameters
[in]channelIIC channel index.
[in]target_7b7-bit peripheral address.
[in]dataNS source buffer.
[in]lenByte count.
Returns
ra8_err_t outcome.
Return values
k_ra8_okBytes transmitted (or ACK-checked).
k_ra8_err_null_ptrdata was NULL.
k_ra8_err_invalid_argRange outside NS region or len bogus.
Precondition
ra8_nsc_iic_init succeeded for channel.
[data, data+len) lies in NS data region.
Postcondition
On success the bus completed a START-WRITE-STOP transaction.
On failure the bus has been released.
TrustZone:
NS->S boundary via cmse_nonsecure_entry. cmse_check_address_range rejects buffers that overlap secure memory before the secure driver reads them.
Note
Thread-safe: serialised by the secure IIC driver lock.
Since
0.1.0

Definition at line 206 of file ra8_nsc_comms.c.

References RA8_CHECK_NULL_PTR, ra8_i3c_write(), RA8_NSC_CHECK_NS_RANGE_R, RA8_NSC_VENEER, and s_tag.

◆ ra8_nsc_sci_getc()

ra8_err_t ra8_nsc_sci_getc ( uint8_t channel,
uint8_t * out_byte )
nodiscard

NSC veneer: blocking single-byte SCI read.

Validates out_byte is in the NS region and forwards to ra8_sci_getc_polling.

Parameters
[in]channelSCI channel index.
[out]out_byteDestination byte (in NS memory).
Returns
ra8_err_t outcome.
Return values
k_ra8_okOne byte stored at *out_byte.
k_ra8_err_null_ptrout_byte was NULL.
k_ra8_err_invalid_argPointer not in NS region.
Precondition
ra8_nsc_sci_init succeeded for channel.
out_byte lies in NS data region.
Postcondition
On success *out_byte reflects the received byte.
On failure *out_byte unchanged.
TrustZone:
Crosses NS->S via cmse_nonsecure_entry. out_byte is cmse_check_address_range-validated so the secure driver cannot be tricked into writing into secure memory.
Note
Thread-safe: serialised by the secure SCI driver lock.
Since
0.1.0

Definition at line 129 of file ra8_nsc_comms.c.

References RA8_CHECK_NULL_PTR, RA8_NSC_CHECK_NS_RANGE_RW, RA8_NSC_VENEER, ra8_sci_getc_polling(), and s_tag.

◆ ra8_nsc_sci_init()

ra8_err_t ra8_nsc_sci_init ( uint8_t channel,
const ra8_sci_cfg_t * cfg )
nodiscard

NSC veneer: bring up an SCI channel from Non-Secure code.

NSC veneer: bring up an SCI channel from NS code.

Validates cfg lies inside the NS region (TZ builds) and forwards to the secure ra8_sci_init driver.

Parameters
[in]channelSCI channel index (0..k_ra8_sci_channel_max-1).
[in]cfgCaller-supplied configuration in NS memory.
Returns
ra8_err_t outcome.
Return values
k_ra8_okChannel programmed and ready.
k_ra8_err_null_ptrcfg was NULL.
k_ra8_err_invalid_argcfg outside NS range or channel bad.
Precondition
TrustZone substrate has been initialized.
cfg lies entirely within the NS data region.
Postcondition
On success the SCI hardware is ready for I/O.
On failure no module state was mutated.
TrustZone:
Crosses the NS->S boundary via cmse_nonsecure_entry. The caller pointer is checked with cmse_check_address_range so a malicious NS pointer cannot trick the secure SCI driver into reading secure memory.
Note
Thread-safe: serialised by the secure SCI driver lock.
Since
0.1.0

Definition at line 65 of file ra8_nsc_comms.c.

References RA8_CHECK_NULL_PTR, RA8_NSC_CHECK_NS_RANGE_R, RA8_NSC_VENEER, ra8_sci_init(), and s_tag.

◆ ra8_nsc_sci_putc()

ra8_err_t ra8_nsc_sci_putc ( uint8_t channel,
uint8_t byte )
nodiscard

NSC veneer: blocking single-byte SCI write.

Forwards directly to ra8_sci_putc_polling; no pointer crosses the boundary so no NS-range check is needed.

Parameters
[in]channelSCI channel index.
[in]byteByte to transmit.
Returns
ra8_err_t outcome.
Return values
k_ra8_okByte queued for TX.
k_ra8_err_invalid_argBad channel index.
Precondition
ra8_nsc_sci_init succeeded for channel.
TrustZone substrate up.
Postcondition
On success one byte was transmitted.
On failure the bus state is unchanged.
TrustZone:
Crosses NS->S via cmse_nonsecure_entry. Scalar-only signature; nothing leaks across the boundary.
Note
Thread-safe: serialised by the secure SCI driver lock.
Since
0.1.0

Definition at line 97 of file ra8_nsc_comms.c.

References RA8_NSC_VENEER, and ra8_sci_putc_polling().

◆ ra8_nsc_spi_init()

ra8_err_t ra8_nsc_spi_init ( uint8_t channel,
const ra8_spi_cfg_t * cfg )
nodiscard

NSC veneer: bring up an SPI controller channel from NS code.

NSC veneer: bring up an SPI controller channel.

Validates the NS pointer to cfg then forwards to ra8_spi_init.

Parameters
[in]channelSPI channel index.
[in]cfgCaller-supplied configuration in NS memory.
Returns
ra8_err_t outcome.
Return values
k_ra8_okChannel programmed.
k_ra8_err_null_ptrcfg was NULL.
k_ra8_err_invalid_argcfg not in NS region or channel bad.
Precondition
TrustZone substrate up.
cfg lies in NS data region.
Postcondition
On success the SPI hardware is ready for transfers.
On failure no module state was mutated.
TrustZone:
NS->S boundary via cmse_nonsecure_entry. cfg is range-checked prior to the secure-side read.
Note
Thread-safe: serialised by the secure SPI driver lock.
Since
0.1.0

Definition at line 285 of file ra8_nsc_comms.c.

References RA8_CHECK_NULL_PTR, RA8_NSC_CHECK_NS_RANGE_R, RA8_NSC_VENEER, ra8_spi_init(), and s_tag.

◆ ra8_nsc_spi_read()

ra8_err_t ra8_nsc_spi_read ( uint8_t channel,
void * rx,
uint32_t len,
ra8_spi_bit_width_t bit_width )
nodiscard

NSC veneer: multi-frame RX-only polling SPI read.

Computes the byte span, range-checks rx in NS writable memory, then forwards to ra8_spi_read.

Parameters
[in]channelSPI channel index.
[out]rxNS destination buffer (may be NULL only if len == 0).
[in]lenFrame count.
[in]bit_widthFrame width (8/16/32).
Returns
ra8_err_t outcome.
Return values
k_ra8_okBytes received into rx.
k_ra8_err_null_ptrrx was NULL with non-zero len.
k_ra8_err_invalid_argRange outside NS region or bad width.
Precondition
ra8_nsc_spi_init succeeded for channel.
[rx, rx + bytes_per_frame*len) lies in NS writable memory.
Postcondition
On success rx holds len frames.
On failure rx content is undefined.
TrustZone:
NS->S boundary via cmse_nonsecure_entry. rx is range-checked so the secure driver cannot be tricked into writing into secure RAM.
Note
Thread-safe: serialised by the secure SPI driver lock.
Since
0.1.0

Definition at line 485 of file ra8_nsc_comms.c.

References internal_spi_byte_span(), internal_spi_unit_bytes(), k_ra8_err_invalid_arg, RA8_CHECK_NULL_PTR, RA8_NSC_CHECK_NS_RANGE_RW, RA8_NSC_VENEER, ra8_spi_read(), and s_tag.

◆ ra8_nsc_spi_write()

ra8_err_t ra8_nsc_spi_write ( uint8_t channel,
const void * tx,
uint32_t len,
ra8_spi_bit_width_t bit_width )
nodiscard

NSC veneer: multi-frame TX-only polling SPI write.

Computes bytes_per_frame * len, range-checks the source buffer in NS memory, then forwards to ra8_spi_write.

Parameters
[in]channelSPI channel index.
[in]txNS source buffer (may be NULL only if len == 0).
[in]lenFrame count.
[in]bit_widthFrame width (8/16/32).
Returns
ra8_err_t outcome.
Return values
k_ra8_okBytes shifted out.
k_ra8_err_null_ptrtx was NULL with non-zero len.
k_ra8_err_invalid_argRange outside NS region or bad width.
Precondition
ra8_nsc_spi_init succeeded for channel.
[tx, tx + bytes_per_frame*len) lies in NS memory.
Postcondition
On success len frames were transmitted.
On failure no module state was mutated.
TrustZone:
NS->S boundary via cmse_nonsecure_entry. The full byte range spanned by len frames is cmse_check_address_range-validated so the secure driver only reads NS memory.
Note
Thread-safe: serialised by the secure SPI driver lock.
Since
0.1.0

Definition at line 437 of file ra8_nsc_comms.c.

References internal_spi_byte_span(), internal_spi_unit_bytes(), k_ra8_err_invalid_arg, RA8_CHECK_NULL_PTR, RA8_NSC_CHECK_NS_RANGE_R, RA8_NSC_VENEER, ra8_spi_write(), and s_tag.

◆ ra8_nsc_spi_write_read()

ra8_err_t ra8_nsc_spi_write_read ( uint32_t ch_bw,
const void * tx,
void * rx,
uint32_t len )
nodiscard

NSC veneer: multi-frame full-duplex polling SPI exchange.

The veneer takes four register-sized arguments; pack channel and bit_width into ch_bw with ra8_nsc_spi_ch_bw().

TrustZone Safety:
  • Validates both buffer ranges are NS-accessible for the requested direction before forwarding.
Since
0.1.0

Definition at line 505 of file ra8_nsc_comms.c.

References internal_spi_byte_span(), internal_spi_unit_bytes(), k_ra8_err_invalid_arg, k_ra8_nsc_spi_bw_shift, k_ra8_nsc_spi_byte_msk, RA8_CHECK_NULL_PTR, RA8_NSC_CHECK_NS_RANGE_R, RA8_NSC_CHECK_NS_RANGE_RW, RA8_NSC_VENEER, ra8_spi_write_read(), and s_tag.

◆ ra8_nsc_spi_xfer8()

ra8_err_t ra8_nsc_spi_xfer8 ( uint8_t channel,
uint8_t tx,
uint8_t * rx )
nodiscard

NSC veneer: full-duplex single-byte SPI exchange.

Forwards to ra8_spi_xfer8. rx may be NULL (matches the legacy ra8_spi_xfer8 contract); when non-NULL it is range- checked.

Parameters
[in]channelSPI channel index.
[in]txByte to transmit.
[out]rxOptional NS destination for the received byte.
Returns
ra8_err_t outcome.
Return values
k_ra8_okExchange complete.
k_ra8_err_invalid_argrx non-NULL but outside NS region.
Precondition
ra8_nsc_spi_init succeeded for channel.
rx is NULL or in NS data region.
Postcondition
On success and rx non-NULL, *rx reflects the CIPO byte.
On failure the bus state is restored.
TrustZone:
NS->S boundary via cmse_nonsecure_entry. rx (when non-NULL) is cmse_check_address_range-validated.
Note
Thread-safe: serialised by the secure SPI driver lock.
Since
0.1.0

Definition at line 319 of file ra8_nsc_comms.c.

References RA8_NSC_CHECK_NS_RANGE_RW, RA8_NSC_VENEER, and ra8_spi_xfer8().

◆ ra8_nsc_usb_attach()

ra8_err_t ra8_nsc_usb_attach ( ra8_usb_speed_t speed,
bool attached )
nodiscard

NSC veneer: raise / drop the USB D+ pull-up.

NSC veneer: raise / drop USB D+ pull-up.

Forwards to ra8_usb_device_attach.

Parameters
[in]speedNegotiated USB speed enum.
[in]attachedTrue to assert pull-up, false to release.
Returns
ra8_err_t outcome.
Return values
k_ra8_okPull-up state set.
k_ra8_err_invalid_argUnknown speed.
Precondition
ra8_nsc_usb_init succeeded.
TrustZone substrate up.
Postcondition
On success the device is visible (or invisible) on the bus.
On failure the pull-up state is unchanged.
TrustZone:
NS->S boundary via cmse_nonsecure_entry. Scalar arguments only.
Note
Thread-safe: no.
Since
0.1.0

Definition at line 589 of file ra8_nsc_comms.c.

References RA8_NSC_VENEER, and ra8_usb_device_attach().

Referenced by internal_usb_audio_usb_or_halt().

◆ ra8_nsc_usb_init()

ra8_err_t ra8_nsc_usb_init ( ra8_usb_speed_t speed)
nodiscard

NSC veneer: bring up the USB device controller.

Forwards to ra8_usb_device_init. Scalar-only signature, so no NS-range check is needed.

Parameters
[in]speedNegotiated USB speed enum.
Returns
ra8_err_t outcome.
Return values
k_ra8_okUSB controller programmed.
k_ra8_err_invalid_argUnknown speed.
Precondition
TrustZone substrate up.
USB clock tree was enabled by ra8_nsc_periph_init.
Postcondition
On success the device controller is in the powered, detached state.
On failure no module state was mutated.
TrustZone:
NS->S boundary via cmse_nonsecure_entry. Scalar enum argument; nothing crosses the boundary that needs range-checking.
Note
Thread-safe: no – USB bring-up is single-threaded.
Since
0.1.0

Definition at line 561 of file ra8_nsc_comms.c.

References RA8_NSC_VENEER, and ra8_usb_device_init().

Variable Documentation

◆ s_tag

const char* s_tag = "NSCCOM"
static

Definition at line 30 of file ra8_nsc_comms.c.