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

Full-featured SCI_B driver implementation. More...

#include "ra8_sci.h"
#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_hw_err.h"
#include "ra8_log.h"
#include "ra8_mstp.h"
#include "ra8_mstp_regs.h"
#include "ra8_register_guard.h"
#include "ra8_sci_internal.h"
#include "ra8_sci_regs.h"
Include dependency graph for ra8_sci.c:

Go to the source code of this file.

Enumerations

enum  ra8_sci_baud_calc_const_t : uint16_t {
  k_ra8_sci_baud_brr_max = 255U ,
  k_ra8_sci_baud_cks_max = 3U ,
  k_ra8_sci_baud_div_step = 4U ,
  k_ra8_sci_baud_n0_divisor = 32U
}
 Constants used by ra8_sci_baud_calculate. More...

Functions

static volatile r_sci_regs_tinternal_reg (uint8_t channel)
 Validate channel and return the register pointer.
static uint8_t internal_brr (uint32_t pclk_hz, uint32_t baud)
 Compute the 8-bit BRR value from a target baud and PCLKB.
static uint32_t internal_ccr1 (const ra8_sci_cfg_t *cfg)
 Build the CCR1 value for an async-UART config descriptor.
static uint32_t internal_ccr3 (const ra8_sci_cfg_t *cfg)
 Build the CCR3 value for an async-UART config descriptor.
static void internal_clear_csr_flags (volatile r_sci_regs_t *reg)
 Clear every stale CSR / FFCLR latch on a freshly-opened channel.
static ra8_err_t internal_wait_tx_end (volatile r_sci_regs_t *reg)
 Spin until CSR.TEND = 1 or the bounded budget runs out.
static uint32_t internal_ccr2 (const ra8_sci_cfg_t *cfg)
 Build the CCR2 value with BRR programmed.
static void internal_program_ccr_bank (volatile r_sci_regs_t *reg, const ra8_sci_cfg_t *cfg)
 Program CCR0..CCR4 + FCR for the requested UART config.
ra8_err_t ra8_sci_init (uint8_t channel, const ra8_sci_cfg_t *cfg)
 Initialise an SCI channel using the descriptor.
ra8_err_t ra8_sci_deinit (uint8_t channel)
 Tear down a channel – disable TX/RX, release MSTP.
ra8_err_t ra8_sci_putc_polling (uint8_t channel, uint8_t byte)
 Poll-send one byte (blocking, bounded by ra8_hw_err spin budget).
ra8_err_t ra8_sci_getc_polling (uint8_t channel, uint8_t *out_byte)
 Poll-receive one byte (blocking, bounded spin).
ra8_err_t ra8_sci_write_polling (uint8_t channel, const uint8_t *data, uint32_t len)
 Send len bytes by polling (convenience wrapper).
ra8_err_t ra8_sci_flush (uint8_t channel)
 Block until the channel's transmit shift register is empty.
ra8_err_t ra8_sci_attach_rx_handler (uint8_t channel, ra8_sci_rx_fn_t fn, void *ctx)
 Install the RX interrupt callback + context.
ra8_err_t ra8_sci_attach_tx_handler (uint8_t channel, ra8_sci_tx_fn_t fn, void *ctx)
 Install the TX interrupt callback + context.
ra8_err_t ra8_sci_get_errors (uint8_t channel, uint8_t *out_mask)
 Read the SSR error bits (ORER, FER, PER).
ra8_err_t ra8_sci_clear_errors (uint8_t channel)
 Clear the SSR error flags via write-zero.
ra8_err_t ra8_sci_set_baud (uint8_t channel, uint32_t baud, uint32_t pclk_hz)
 Change the baud rate without tearing down the channel.
ra8_err_t ra8_sci_enter_stop (uint8_t channel)
 Put the channel into MSTP-gated stop state.
ra8_err_t ra8_sci_exit_stop (uint8_t channel)
 Exit MSTP-gated stop state; the channel must be re-init'd.
ra8_err_t ra8_sci_baud_calculate (uint32_t baud, uint32_t pclk_hz, uint16_t *brr_out, uint8_t *clk_div_out)
 Pure-math conversion from a target baud rate to BRR + clock divider settings.
ra8_err_t ra8_sci_write (uint8_t channel, const uint8_t *data, uint32_t len)
 Arm an interrupt-driven TX of len bytes from data.
ra8_err_t ra8_sci_read (uint8_t channel, uint8_t *buf, uint32_t len)
 Arm an interrupt-driven RX of len bytes into buf.
ra8_err_t ra8_sci_abort (uint8_t channel, ra8_sci_dir_t direction)
 Cancel an in-flight async TX or RX.
ra8_err_t ra8_sci_read_stop (uint8_t channel, uint32_t *remaining)
 Stop an in-flight RX and report how many bytes were not yet consumed.
ra8_err_t ra8_sci_receive_suspend (uint8_t channel)
 Suspend reception by clearing CCR0.RE.
ra8_err_t ra8_sci_receive_resume (uint8_t channel)
 Resume reception by setting CCR0.RE.

Variables

static const char * s_tag = "SCI"
ra8_sci_state_t s_sci_state [k_ra8_sci_channel_count_val]
 Per-channel allocation + dispatch table.
static const ra8_mstp_t s_mstp_table [k_ra8_sci_channel_count_val]
 Channel-index -> MSTP id lookup.

Detailed Description

Full-featured SCI_B driver implementation.

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

SCI_B variant of the RA8D2 SCI peripheral (HUM Ch 38). See ra8_sci.h for the public API contract and ra8_sci_regs.h for the register layout. This file replaces the prior legacy-SCI driver stub (the legacy 8-bit-register variant is not present on RA8D2).

Asynchronous (UART) bring-up sequence implemented in ra8_sci_init:

  1. Open the per-channel MSTP gate.
  2. Clear CCR0 so TE/RE/TIE/RIE/TEIE are off before reconfiguring.
  3. Programme CCR1 (parity / inverter / break-data defaults).
  4. Programme CCR3 (mode = async, CHR = data length, STP = stop bits, MOD = 0 for async/multi-proc, MP/FM/DEN/CKE all clear so the channel uses the on-chip baud generator with no FIFO).
  5. Programme CCR2 with BRR computed from PCLKB and the requested baud (CKS = 0, BGDM = 0, ABCS = 0 – the standard 16x base clock path), MDDR left at reset (0xFF -> no modulation).
  6. Disable FIFO mode and Manchester / LIN / IIC satellite bits.
  7. Clear every CSR / FFCLR latch left over from a prior boot (mirrors FSP R_SCI_B_UART_Open lines 375 & 378).
  8. Set CCR0 = TE | RE.
Intentional FSP Gaps
The driver follows the FSP r_sci_b_uart reference closely but deliberately omits four steps that do not apply to our usage:
  • r_sci_b_uart.c (CCR0 IDSEL pre-seed). FSP pre-loads CCR0 with the IDSEL bit when the multi-processor bit is being turned on. IDSEL is only meaningful when CCR3.MP=1; this driver never enables multi-processor mode (see internal_ccr3 – MOD stays 000 / async and MP stays 0), so the bit is dead and we skip the extra write.
  • r_sci_b_uart.c (r_sci_b_uart_synchronization_delay_cfg). The FSP delay loop accounts for the synchronizer hop between SCICLK and PCLK when those clocks are sourced independently. In our async-UART configuration the on-chip baud generator is fed from PCLKB (CCR3.CKE = 00, CCR3.BPEN = 1 – see internal_ccr3), so SCICLK and PCLK are the same edge and FSP's own delay-count formula evaluates to zero. The wait is a no-op for us and is intentionally not ported.
  • r_sci_b_uart.c (SCI_B_UART_FCR_DEFAULT_VALUE = 0x1F1F0000). FSP seeds FCR with RTRG=31 / TTRG=31 even when FIFO mode is off. RTRG/TTRG are dead bits when CCR3.FM=0 (HUM Ch 38.2.11 p 2215, "valid only when FM = 1"); we keep FCR = 0 here since we never enable FIFO mode.
  • r_sci_b_uart.c (Close clears CCR3.FM before TE drop). FSP's Close path explicitly toggles FM off because there is a documented hang where TE -> 0 with FM=1 leaves CSR.TEND stuck at 0 and the peripheral wedged. Since this driver never sets FM=1, the workaround is unnecessary and ra8_sci_deinit writes CCR0=0 directly.

Definition in file ra8_sci.c.

Enumeration Type Documentation

◆ ra8_sci_baud_calc_const_t

enum ra8_sci_baud_calc_const_t : uint16_t

Constants used by ra8_sci_baud_calculate.

HUM Ch 38.2.7 "CCR2 : Common Control Register 2", p 2189 Table 38.7: the 16x base-clock formula divides PCLKB by 32 * 2^(2n) where n is the CKS divider (0..3). With n = 0 the divisor is 32; with n = 1 it is 128; with n = 2 it is 512; with n = 3 it is 2048. k_ra8_sci_baud_brr_max is the 8-bit ceiling for BRR.

Enumerator
k_ra8_sci_baud_brr_max 

BRR is 8 bits wide.

k_ra8_sci_baud_cks_max 

CKS field is 2 bits.

k_ra8_sci_baud_div_step 

Multiplier per CKS step.

k_ra8_sci_baud_n0_divisor 

32 * 2^(2*0).

Definition at line 709 of file ra8_sci.c.

Function Documentation

◆ internal_brr()

uint8_t internal_brr ( uint32_t pclk_hz,
uint32_t baud )
static

Compute the 8-bit BRR value from a target baud and PCLKB.

HUM Ch 38.2.7 "CCR2 : Common Control Register 2", p 2189 Table 38.7. For the default Asynchronous-mode 16x base-clock path (CCR2.BGDM = ABCS = ABCSE = ABCSE2 = 0, CCR3.CKE = 0, CCR2.CKS = 0 -> n = 0):

\[ N = \frac{TCLK}{64 \cdot 2^{(2n - 1)} \cdot B} - 1 = \frac{TCLK}{32 \cdot B} - 1 \]

Saturates at 0 if the requested baud is unreachable.

Parameters
[in]pclk_hzSee declaration: uint32_t pclk_hz.
[in]baudSee declaration: uint32_t baud.
Returns
ra8_err_t outcome (or scalar return value).
Return values
k_ra8_okOperation completed successfully.
otherNon-zero error code from the underlying operation.
Precondition
Module/state preconditions hold (see function body).
Module/state preconditions hold (see function body).
Postcondition
Documented side effects are visible on success.
Documented side effects are visible on success.
Note
Not thread-safe; the caller must serialise concurrent access.
Since
0.1.0

Definition at line 155 of file ra8_sci.c.

References k_ra8_sci_brr_async_divisor, and RA8_INTERNAL.

Referenced by internal_ccr2(), and ra8_sci_set_baud().

◆ internal_ccr1()

uint32_t internal_ccr1 ( const ra8_sci_cfg_t * cfg)
static

Build the CCR1 value for an async-UART config descriptor.

HUM Ch 38.2.6 "CCR1 : Common Control Register 1", p 2185. Always sets SPB2DT + SPB2IO so TXD idles HIGH while TE=0 – without those bits the line floats low and a host UART sees a permanent break, blocking the very first frame. FSP r_sci_b_uart does the same write unconditionally for async-UART configs. Parity is set per cfg->parity; the rest (CTSE/CTSPEN/TINV/RINV/SPLP/SHARPS/ NFEN) stay at their reset value.

Parameters
[in]cfgSee declaration: const ra8_sci_cfg_t* cfg.
Returns
ra8_err_t outcome (or scalar return value).
Return values
k_ra8_okOperation completed successfully.
otherNon-zero error code from the underlying operation.
Precondition
Module/state preconditions hold (see function body).
Module/state preconditions hold (see function body).
Postcondition
Documented side effects are visible on success.
Documented side effects are visible on success.
Note
Not thread-safe; the caller must serialise concurrent access.
Since
0.1.0

Definition at line 189 of file ra8_sci.c.

References k_ra8_sci_ccr1_bit_pe, k_ra8_sci_ccr1_bit_pm, k_ra8_sci_ccr1_bit_spb2dt, k_ra8_sci_ccr1_bit_spb2io, k_ra8_sci_parity_none, k_ra8_sci_parity_odd, ra8_sci_cfg_t::parity, and RA8_INTERNAL.

Referenced by internal_program_ccr_bank().

◆ internal_ccr2()

uint32_t internal_ccr2 ( const ra8_sci_cfg_t * cfg)
static

Build the CCR2 value with BRR programmed.

HUM Ch 38.2.7 "CCR2 : Common Control Register 2", p 2189. MDDR field reset value is 0xFF (modulation-disabled equivalent), so we keep it at 0xFF and program BRR[15:8] only. CKS = 0, BGDM = ABCS = ABCSE = ABCSE2 = 0 – the 16x base-clock path.

Parameters
[in]cfgSee declaration: const ra8_sci_cfg_t* cfg.
Returns
ra8_err_t outcome (or scalar return value).
Return values
k_ra8_okOperation completed successfully.
otherNon-zero error code from the underlying operation.
Precondition
Module/state preconditions hold (see function body).
Module/state preconditions hold (see function body).
Postcondition
Documented side effects are visible on success.
Documented side effects are visible on success.
Note
Not thread-safe; the caller must serialise concurrent access.
Since
0.1.0

Definition at line 340 of file ra8_sci.c.

References ra8_sci_cfg_t::baud, internal_brr(), k_ra8_sci_ccr2_shift_brr, k_ra8_sci_ccr2_shift_mddr, k_ra8_sci_mddr_default, ra8_sci_cfg_t::pclk_hz, and RA8_INTERNAL.

Referenced by internal_program_ccr_bank().

◆ internal_ccr3()

uint32_t internal_ccr3 ( const ra8_sci_cfg_t * cfg)
static

Build the CCR3 value for an async-UART config descriptor.

HUM Ch 38.2.8 "CCR3 : Common Control Register 3", p 2203. MOD = 000 (asynchronous), CHR = 8-bit / 7-bit, STP = 0/1 stop bit = 1 / 2 stop bits. CKE = 00 (on-chip baud generator). FM = 0 (non-FIFO). MP = 0 (single-processor). All other bits stay 0.

Parameters
[in]cfgSee declaration: const ra8_sci_cfg_t* cfg.
Returns
ra8_err_t outcome (or scalar return value).
Return values
k_ra8_okOperation completed successfully.
otherNon-zero error code from the underlying operation.
Precondition
Module/state preconditions hold (see function body).
Module/state preconditions hold (see function body).
Postcondition
Documented side effects are visible on success.
Documented side effects are visible on success.
Note
Not thread-safe; the caller must serialise concurrent access.
Since
0.1.0

Definition at line 219 of file ra8_sci.c.

References ra8_sci_cfg_t::data_bits, k_ra8_sci_ccr3_bit_bpen, k_ra8_sci_ccr3_bit_lsbf, k_ra8_sci_ccr3_bit_stp, k_ra8_sci_ccr3_chr_7bit, k_ra8_sci_ccr3_chr_8bit, k_ra8_sci_ccr3_shift_chr, k_ra8_sci_data_7, k_ra8_sci_stop_2, RA8_INTERNAL, and ra8_sci_cfg_t::stop_bits.

Referenced by internal_program_ccr_bank().

◆ internal_clear_csr_flags()

void internal_clear_csr_flags ( volatile r_sci_regs_t * reg)
static

Clear every stale CSR / FFCLR latch on a freshly-opened channel.

Mirrors FSP r_sci_b_uart.c (p_ctrl->p_reg->CFCLR = SCI_B_UART_CFCLR_DEFAULT) and r_sci_b_uart.c (p_ctrl->p_reg->FFCLR = SCI_B_UART_FFCLR_DEFAULT). Both clear registers are write-1-to-clear: writing the "all bits" mask drops every defined latch in a single store while leaving the reserved bits at 0. Without this step, residual flags from a prior boot (e.g. ORER set by a stray RX framing error) would surface as a spurious error the moment we re-enable RIE/TIE.

Parameters
[in]regSee declaration: volatile r_sci_regs_t* reg.
Precondition
Module/state preconditions hold (see function body).
Module/state preconditions hold (see function body).
Postcondition
Documented side effects are visible on success.
Documented side effects are visible on success.
Note
Not thread-safe; the caller must serialise concurrent access.
Since
0.1.0

Definition at line 274 of file ra8_sci.c.

References r_sci_regs_t::CFCLR, r_sci_regs_t::FFCLR, k_ra8_sci_cfclr_default, k_ra8_sci_ffclr_default, and RA8_INTERNAL.

Referenced by internal_program_ccr_bank().

◆ internal_program_ccr_bank()

void internal_program_ccr_bank ( volatile r_sci_regs_t * reg,
const ra8_sci_cfg_t * cfg )
static

Program CCR0..CCR4 + FCR for the requested UART config.

Performs the deterministic MMIO write sequence required between MSTP-enable and the final TE/RE strobe: CCR0=0 (disable), FCR=0 (non-FIFO), CCR1/CCR3/CCR2 from the cached helpers, CCR4=0, then the CFCLR / FFCLR latch clear. The write order is identical to FSP r_sci_b_uart.c.

Parameters
[in,out]regChannel register bank, non-NULL.
[in]cfgValidated UART configuration.
Precondition
Caller has enabled the module-stop clock for this channel.
reg is the canonical bank pointer for the active channel.
Postcondition
CCR0=0 (TX/RX still disabled until ra8_sci_init re-strobes it).
FCR=0, CCR1/CCR2/CCR3 programmed, CCR4 cleared, flags cleared.
Note
Not thread-safe; called once during init under IRQ-masked context.
Since
0.1.0

Definition at line 376 of file ra8_sci.c.

References r_sci_regs_t::CCR0, r_sci_regs_t::CCR1, r_sci_regs_t::CCR2, r_sci_regs_t::CCR3, r_sci_regs_t::CCR4, r_sci_regs_t::FCR, internal_ccr1(), internal_ccr2(), internal_ccr3(), internal_clear_csr_flags(), and RA8_INTERNAL.

Referenced by ra8_sci_init().

◆ internal_reg()

◆ internal_wait_tx_end()

ra8_err_t internal_wait_tx_end ( volatile r_sci_regs_t * reg)
static

Spin until CSR.TEND = 1 or the bounded budget runs out.

Mirrors FSP r_sci_b_uart.c and :809 (FSP_HARDWARE_REGISTER_WAIT(p_ctrl->p_reg->CSR_b.TEND, 1U)). TDRE (transmit data register empty) is asserted as soon as TDR is latched into the shift register, but the bits are not yet on the wire. TEND additionally waits for the shift register to drain. We use a bounded medium-budget spin so the call returns in finite time even if the line is wedged.

On the host (RA8_OFF_TARGET) the fake does not model the shift-register drain – *reg would never see TEND assert – so we short-circuit and return success.

Parameters
[in,out]regSee function signature.
Returns
Result code or value; see implementation.
Return values
0Success or default value.
Precondition
Module has been initialized.
Caller has validated arguments.
Postcondition
Side effects bounded to documented state.
State reflects operation result.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 312 of file ra8_sci.c.

References r_sci_regs_t::CSR, k_ra8_hw_budget_medium, k_ra8_sci_csr_bit_tend, ra8_hw_wait_flag_set32(), and RA8_INTERNAL.

Referenced by ra8_sci_flush(), and ra8_sci_write_polling().

◆ ra8_sci_abort()

ra8_err_t ra8_sci_abort ( uint8_t channel,
ra8_sci_dir_t direction )
nodiscard

Cancel an in-flight async TX or RX.

Mirrors FSP R_SCI_B_UART_Abort (r_sci_b_uart.c). When direction includes k_ra8_sci_dir_tx, CCR0.TIE / CCR0.TEIE are cleared and the per-channel TX state is zeroed. When direction includes k_ra8_sci_dir_rx, CCR0.RIE is cleared and the per-channel RX state is zeroed. k_ra8_sci_dir_both aborts both. CCR0.TE / RE are left alone – callers may still poll or arm a fresh transfer.

Parameters
[in]channelSCI channel (0..9).
[in]directionTX, RX, or both.
Returns
ra8_err_t error code.
Return values
k_ra8_okDirection(s) aborted.
k_ra8_err_invalid_argchannel > 9 or direction is not one of the three defined values.
Precondition
Channel previously initialized.
Postcondition
The selected direction(s) have IE bits cleared and the matching per-channel byte counter is zero.
Note
Thread safety: not thread-safe.
See also
ra8_sci_write
ra8_sci_read
Since
0.1.0

Definition at line 815 of file ra8_sci.c.

References r_sci_regs_t::CCR0, internal_reg(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_sci_ccr0_bit_rie, k_ra8_sci_ccr0_bit_teie, k_ra8_sci_ccr0_bit_tie, k_ra8_sci_dir_both, k_ra8_sci_dir_rx, k_ra8_sci_dir_tx, ra8_register_guard_enter(), ra8_register_guard_exit(), and s_sci_state.

◆ ra8_sci_attach_rx_handler()

ra8_err_t ra8_sci_attach_rx_handler ( uint8_t channel,
ra8_sci_rx_fn_t fn,
void * ctx )
nodiscard

Install the RX interrupt callback + context.

Parameters
[in]channelSCI channel.
[in]fnCallback fired on RDRF interrupt. Must not be NULL to enable; pass NULL to detach.
[in]ctxContext passed to the callback.
Returns
k_ra8_ok / k_ra8_err_invalid_arg.
Precondition
Channel previously initialized.
Postcondition
On success, SCR.RIE is set (if fn non-NULL).
Since
0.1.0

Definition at line 558 of file ra8_sci.c.

References r_sci_regs_t::CCR0, internal_reg(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_sci_ccr0_bit_rie, ra8_register_guard_enter(), ra8_register_guard_exit(), and s_sci_state.

Referenced by main().

◆ ra8_sci_attach_tx_handler()

ra8_err_t ra8_sci_attach_tx_handler ( uint8_t channel,
ra8_sci_tx_fn_t fn,
void * ctx )
nodiscard

Install the TX interrupt callback + context.

Parameters
[in]channelSCI channel.
[in]fnCallback fired on TDRE interrupt. Return true with the next byte or false to disable.
[in]ctxContext passed to the callback.
Returns
k_ra8_ok / k_ra8_err_invalid_arg.
Precondition
Channel previously initialized.
Postcondition
On success, SCR.TIE is set (if fn non-NULL).
Since
0.1.0

Definition at line 583 of file ra8_sci.c.

References r_sci_regs_t::CCR0, internal_reg(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_sci_ccr0_bit_tie, ra8_register_guard_enter(), ra8_register_guard_exit(), and s_sci_state.

◆ ra8_sci_baud_calculate()

ra8_err_t ra8_sci_baud_calculate ( uint32_t baud,
uint32_t pclk_hz,
uint16_t * brr_out,
uint8_t * clk_div_out )
nodiscard

Pure-math conversion from a target baud rate to BRR + clock divider settings.

Mirrors FSP R_SCI_B_UART_BaudCalculate (r_sci_b_uart.c) for the simple non-modulated 16x base-clock path. Implements the formula from HUM Ch 38.2.7 "CCR2 : Common Control Register 2", p 2189 Table 38.7:

N = TCLK / (64 * 2^(2n - 1) * B) - 1

with n = *clk_div_out chosen as the smallest CKS divider for which BRR fits in 8 bits. *brr_out receives the 8-bit BRR. Pure math only – this routine does not touch any hardware register. Use ra8_sci_set_baud to apply the result.

Parameters
[in]baudTarget baud rate in bps; must be > 0.
[in]pclk_hzPCLKB frequency in Hz; must be > 0.
[out]brr_outComputed BRR value (0..255).
[out]clk_div_outComputed CKS divider exponent (0..3).
Returns
ra8_err_t error code.
Return values
k_ra8_okBRR computed within hardware reach.
k_ra8_err_null_ptrbrr_out or clk_div_out is NULL.
k_ra8_err_invalid_argbaud or pclk_hz is zero, or the requested baud cannot be reached with any CKS divider (BRR > 255).
Precondition
brr_out and clk_div_out are non-NULL.
Postcondition
On success, the pair (*brr_out, *clk_div_out) yields an effective baud whose error vs. baud is < 5 percent for standard 9.6k/19.2k/57.6k/115.2k targets at typical PCLKB rates.
Note
Thread safety: pure function; safe to call concurrently.
See also
ra8_sci_set_baud
Since
0.1.0

Definition at line 717 of file ra8_sci.c.

References k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_sci_baud_brr_max, k_ra8_sci_baud_cks_max, k_ra8_sci_baud_div_step, k_ra8_sci_baud_n0_divisor, RA8_CHECK_NULL_PTR, and s_tag.

◆ ra8_sci_clear_errors()

ra8_err_t ra8_sci_clear_errors ( uint8_t channel)
nodiscard

Clear the SSR error flags via write-zero.

Parameters
[in]channelSCI channel.
Returns
k_ra8_ok / k_ra8_err_invalid_arg.
Precondition
IRQs masked or single-threaded init context.
Postcondition
ORER, FER, PER read back as 0.
Since
0.1.0

Definition at line 633 of file ra8_sci.c.

References r_sci_regs_t::CFCLR, internal_reg(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_sci_cfclr_bit_ferc, k_ra8_sci_cfclr_bit_orerc, and k_ra8_sci_cfclr_bit_perc.

Referenced by ra8_sci_dispatch_eri().

◆ ra8_sci_deinit()

ra8_err_t ra8_sci_deinit ( uint8_t channel)
nodiscard

Tear down a channel – disable TX/RX, release MSTP.

Parameters
[in]channelSCI channel number.
Returns
ra8_err_t error code.
Return values
k_ra8_okChannel released.
k_ra8_err_invalid_argchannel > 9.
Precondition
IRQs masked or single-threaded init context.
Caller previously called ra8_sci_init(channel).
Postcondition
TX/RX disabled; MSTP reference for the channel decremented.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 443 of file ra8_sci.c.

References r_sci_regs_t::CCR0, internal_reg(), k_ra8_err_invalid_arg, ra8_mstp_disable(), ra8_register_guard_enter(), ra8_register_guard_exit(), s_mstp_table, and s_sci_state.

◆ ra8_sci_enter_stop()

ra8_err_t ra8_sci_enter_stop ( uint8_t channel)
nodiscard

Put the channel into MSTP-gated stop state.

Parameters
[in]channelSCI channel.
Returns
k_ra8_ok / k_ra8_err_invalid_arg.
Precondition
IRQs masked or single-threaded context.
Postcondition
Channel is MSTP-gated.
Warning
Callers lose every register setting; pair with ra8_sci_exit_stop + re-init if reconfiguration is needed.
Since
0.1.0

Definition at line 677 of file ra8_sci.c.

References r_sci_regs_t::CCR0, internal_reg(), k_ra8_err_invalid_arg, ra8_mstp_disable(), and s_mstp_table.

◆ ra8_sci_exit_stop()

ra8_err_t ra8_sci_exit_stop ( uint8_t channel)
nodiscard

Exit MSTP-gated stop state; the channel must be re-init'd.

Parameters
[in]channelSCI channel.
Returns
k_ra8_ok / k_ra8_err_invalid_arg.
Precondition
Channel is currently MSTP-gated.
Postcondition
MSTP bit is cleared; caller must call ra8_sci_init to restore registers.
Since
0.1.0

Definition at line 688 of file ra8_sci.c.

References k_ra8_err_invalid_arg, k_ra8_sci_channel_max_index, ra8_mstp_enable(), and s_mstp_table.

◆ ra8_sci_flush()

ra8_err_t ra8_sci_flush ( uint8_t channel)
nodiscard

Block until the channel's transmit shift register is empty.

Spins on CSR.TEND (HUM Ch 38.2.17 "CSR : Common Status Register", p 2225). TEND asserts only after both TDR and the shift register are drained, so this call guarantees that every byte previously handed to the SCI has finished clocking out on the wire.

The intended use is before any panic / sleep / WFI sequence that would gate the SCI clock and silently lose in-flight bytes:

(void)ra8_sci_write_polling(k_demo_sci_channel, panic_msg, len);
(void)ra8_sci_flush(k_demo_sci_channel); // wait for the wire
panic_halt(); // safe to WFI now
ra8_err_t ra8_sci_write_polling(uint8_t channel, const uint8_t *data, uint32_t len)
Send len bytes by polling (convenience wrapper).
Definition ra8_sci.c:516
ra8_err_t ra8_sci_flush(uint8_t channel)
Block until the channel's transmit shift register is empty.
Definition ra8_sci.c:543

The wait is bounded by ra8_hw_wait_flag_set32 (medium budget – roughly 65k tight-loop iterations), so the call is guaranteed to return in finite time even if TXD is wedged. On the host (RA8_OFF_TARGET) the fake does not model the shift-register drain, so this routine returns k_ra8_ok without polling.

Parameters
[in]channelSCI channel (0..9).
Returns
ra8_err_t error code.
Return values
k_ra8_okTEND observed high (or fake stub).
k_ra8_err_invalid_argchannel > 9.
k_ra8_err_hw_timeoutSpin budget elapsed without TEND.
Precondition
Channel previously initialized via ra8_sci_init.
Postcondition
On success, the SCI transmit shift register is empty – safe to drop CCR0.TE, gate the MSTP clock, or execute WFI.
Note
Thread safety: not thread-safe with respect to ISR-driven TX on the same channel (the ISR may refill TDR mid-poll). Drain or abort the async TX first, then flush.
See also
ra8_sci_write_polling
ra8_sci_abort
Since
0.1.0

Definition at line 543 of file ra8_sci.c.

References internal_reg(), internal_wait_tx_end(), and k_ra8_err_invalid_arg.

Referenced by internal_uart_flush(), main(), and ra8_board_uart_console_flush().

◆ ra8_sci_get_errors()

ra8_err_t ra8_sci_get_errors ( uint8_t channel,
uint8_t * out_mask )
nodiscard

Read the SSR error bits (ORER, FER, PER).

Parameters
[in]channelSCI channel.
[out]out_maskOR of k_ra8_sci_err_* values.
Returns
k_ra8_ok / k_ra8_err_null_ptr / k_ra8_err_invalid_arg.
Precondition
out_mask non-NULL.
Postcondition
No hardware state is modified.
Since
0.1.0

Definition at line 609 of file ra8_sci.c.

References r_sci_regs_t::CSR, internal_reg(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_sci_csr_bit_fer, k_ra8_sci_csr_bit_orer, k_ra8_sci_csr_bit_per, k_ra8_sci_err_framing, k_ra8_sci_err_none, k_ra8_sci_err_overrun, k_ra8_sci_err_parity, RA8_CHECK_NULL_PTR, and s_tag.

◆ ra8_sci_getc_polling()

ra8_err_t ra8_sci_getc_polling ( uint8_t channel,
uint8_t * out_byte )
nodiscard

Poll-receive one byte (blocking, bounded spin).

Parameters
[in]channelSCI channel number.
[out]out_byteReceived byte on success.
Returns
k_ra8_ok / k_ra8_err_hw_timeout / k_ra8_err_null_ptr.
Precondition
out_byte non-NULL.
Channel previously initialized.
Postcondition
On success, one byte was drained from RDR.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 496 of file ra8_sci.c.

References r_sci_regs_t::CSR, internal_reg(), k_ra8_err_invalid_arg, k_ra8_hw_budget_medium, k_ra8_ok, k_ra8_sci_csr_bit_rdrf, k_ra8_sci_rdr_mask_data8, RA8_CHECK_NULL_PTR, ra8_hw_wait_flag_set32(), r_sci_regs_t::RDR, and s_tag.

Referenced by internal_lin_rx_buf(), modem_rx_byte(), ra8_board_uart_console_read(), ra8_nsc_sci_getc(), and ra8_sci_lin_read_response().

◆ ra8_sci_init()

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

Initialise an SCI channel using the descriptor.

Ungates the channel through ra8_mstp_enable, programs CCR1 / CCR2 (BRR + MDDR) / CCR3 (mode + framing) / CCR4 / FCR registers from cfg, then enables CCR0.TE + CCR0.RE. Errors before the final enable step leave the channel gated.

Parameters
[in]channelSCI channel number (0..9).
[in]cfgConfiguration descriptor.
Returns
ra8_err_t error code.
Return values
k_ra8_okChannel ready.
k_ra8_err_null_ptrcfg was NULL.
k_ra8_err_invalid_argchannel > 9 or cfg has bad field values.
k_ra8_err_hw_init_failedra8_mstp_enable failed.
Precondition
IRQs masked or single-threaded init context.
ra8_mstp_init has been called.
Postcondition
On success, the channel is clocked, configured, and ready to TX / RX.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 410 of file ra8_sci.c.

References r_sci_regs_t::CCR0, internal_program_ccr_bank(), internal_reg(), k_ra8_err_hw_init_failed, k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_sci_ccr0_bit_re, k_ra8_sci_ccr0_bit_te, RA8_CHECK_NULL_PTR, ra8_log_error_val, ra8_log_info_val, ra8_mstp_enable(), s_mstp_table, s_sci_state, and s_tag.

Referenced by blc_setup_or_halt(), demo_setup_or_halt(), internal_demo_setup_or_halt(), modem_setup_or_halt(), ra8_board_uart_console_init(), ra8_nsc_sci_init(), ra8_sci_lin_init(), and uart_irq_setup_or_halt().

◆ ra8_sci_putc_polling()

ra8_err_t ra8_sci_putc_polling ( uint8_t channel,
uint8_t byte )
nodiscard

Poll-send one byte (blocking, bounded by ra8_hw_err spin budget).

Parameters
[in]channelSCI channel number.
[in]byteByte to transmit.
Returns
k_ra8_ok / k_ra8_err_hw_timeout / k_ra8_err_invalid_arg.
Precondition
Channel previously initialized.
Postcondition
On success, the byte has been handed to the TX register.
Note
Thread safety: not thread-safe with respect to IRQ TX on the same channel.
Since
0.1.0

Definition at line 476 of file ra8_sci.c.

References r_sci_regs_t::CSR, internal_reg(), k_ra8_err_invalid_arg, k_ra8_hw_budget_medium, k_ra8_ok, k_ra8_sci_csr_bit_tdre, ra8_hw_wait_flag_set32(), and r_sci_regs_t::TDR.

Referenced by internal_lin_tx_buf(), modem_tx_byte(), ra8_nsc_sci_putc(), ra8_sci_lin_send_header(), ra8_sci_lin_send_response(), and ra8_sci_write_polling().

◆ ra8_sci_read()

ra8_err_t ra8_sci_read ( uint8_t channel,
uint8_t * buf,
uint32_t len )
nodiscard

Arm an interrupt-driven RX of len bytes into buf.

Mirrors FSP R_SCI_B_UART_Read (r_sci_b_uart.c): installs an internal byte-counting RX state machine, sets CCR0.RIE, and returns immediately. Each subsequent RXI copies the byte from RDR into buf[index++] and decrements remaining. When remaining reaches zero, RIE is cleared automatically. A previously-attached user RX callback is still invoked per byte.

Parameters
[in]channelSCI channel (0..9).
[out]bufDestination buffer; must stay live until the transfer drains or ra8_sci_read_stop is called.
[in]lenNumber of bytes to receive. Zero is a no-op.
Returns
ra8_err_t error code.
Return values
k_ra8_okTransfer armed.
k_ra8_err_null_ptrbuf is NULL with len > 0.
k_ra8_err_invalid_argchannel > 9 or channel not initialized.
k_ra8_err_busyA previous async RX is still draining.
Precondition
Channel previously initialized via ra8_sci_init.
buf non-NULL when len > 0.
Postcondition
On success, CCR0.RIE = 1 and the per-channel RX state holds buf / len / index = 0.
Note
Thread safety: not thread-safe.
See also
ra8_sci_read_stop
ra8_sci_abort
ra8_sci_dispatch_rxi
Since
0.1.0

Definition at line 781 of file ra8_sci.c.

References r_sci_regs_t::CCR0, internal_reg(), k_ra8_err_busy, k_ra8_err_invalid_arg, k_ra8_err_null_ptr, k_ra8_ok, k_ra8_sci_ccr0_bit_rie, ra8_register_guard_enter(), ra8_register_guard_exit(), and s_sci_state.

Referenced by main(), and uart_irq_rx_cb().

◆ ra8_sci_read_stop()

ra8_err_t ra8_sci_read_stop ( uint8_t channel,
uint32_t * remaining )
nodiscard

Stop an in-flight RX and report how many bytes were not yet consumed.

Mirrors FSP R_SCI_B_UART_ReadStop (r_sci_b_uart.c). Clears the per-channel RX byte counter, then writes the value that was just cleared into *remaining so the caller knows how much of the original len is still pending. Disarms RIE.

Parameters
[in]channelSCI channel (0..9).
[out]remainingBytes still pending at stop time. Set to 0 if no RX was active.
Returns
ra8_err_t error code.
Return values
k_ra8_okRX state cleared, *remaining updated.
k_ra8_err_null_ptrremaining is NULL.
k_ra8_err_invalid_argchannel > 9.
Precondition
remaining is non-NULL.
Channel previously initialized.
Postcondition
CCR0.RIE = 0 and the per-channel RX state is zeroed.
Note
Thread safety: not thread-safe.
See also
ra8_sci_read
Since
0.1.0

Definition at line 850 of file ra8_sci.c.

References r_sci_regs_t::CCR0, internal_reg(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_sci_ccr0_bit_rie, RA8_CHECK_NULL_PTR, ra8_register_guard_enter(), ra8_register_guard_exit(), s_sci_state, and s_tag.

◆ ra8_sci_receive_resume()

ra8_err_t ra8_sci_receive_resume ( uint8_t channel)
nodiscard

Resume reception by setting CCR0.RE.

Parameters
[in]channelSCI channel (0..9).
Returns
ra8_err_t error code.
Return values
k_ra8_okRX re-armed (CCR0.RE = 1).
k_ra8_err_invalid_argchannel > 9.
Precondition
Channel previously initialized.
Postcondition
CCR0.RE = 1.
Note
Thread safety: not thread-safe.
See also
ra8_sci_receive_suspend
Since
0.1.0

Definition at line 897 of file ra8_sci.c.

References r_sci_regs_t::CCR0, internal_reg(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_sci_ccr0_bit_re, ra8_register_guard_enter(), and ra8_register_guard_exit().

◆ ra8_sci_receive_suspend()

ra8_err_t ra8_sci_receive_suspend ( uint8_t channel)
nodiscard

Suspend reception by clearing CCR0.RE.

Mirrors FSP R_SCI_B_UART_ReceiveSuspend (r_sci_b_uart.c) but with a real implementation: FSP returns FSP_ERR_UNSUPPORTED for SCI_B because the hardware does not have a dedicated "RX-suspend" bit. We approximate it by dropping CCR0.RE – the receive shift register stops sampling RXD and RXI is silenced. ra8_sci_receive_resume re-asserts RE.

Parameters
[in]channelSCI channel (0..9).
Returns
ra8_err_t error code.
Return values
k_ra8_okRX paused (CCR0.RE = 0).
k_ra8_err_invalid_argchannel > 9.
Precondition
Channel previously initialized.
Postcondition
CCR0.RE = 0; bytes already in RDR remain readable.
Note
Thread safety: not thread-safe.
See also
ra8_sci_receive_resume
Since
0.1.0

Definition at line 878 of file ra8_sci.c.

References r_sci_regs_t::CCR0, internal_reg(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_sci_ccr0_bit_re, ra8_register_guard_enter(), and ra8_register_guard_exit().

◆ ra8_sci_set_baud()

ra8_err_t ra8_sci_set_baud ( uint8_t channel,
uint32_t baud,
uint32_t pclk_hz )
nodiscard

Change the baud rate without tearing down the channel.

Parameters
[in]channelSCI channel.
[in]baudNew target baud rate in bps.
[in]pclk_hzCurrent PCLKB frequency in Hz.
Returns
k_ra8_ok / k_ra8_err_invalid_arg.
Precondition
Channel initialized.
IRQs masked or single-threaded context.
Postcondition
BRR reflects the new divider.
Since
0.1.0

Definition at line 648 of file ra8_sci.c.

References r_sci_regs_t::CCR2, internal_brr(), internal_reg(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_sci_ccr2_mask_brr_field, k_ra8_sci_ccr2_shift_brr, ra8_register_guard_enter(), and ra8_register_guard_exit().

◆ ra8_sci_write()

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

Arm an interrupt-driven TX of len bytes from data.

Mirrors FSP R_SCI_B_UART_Write (r_sci_b_uart.c): installs an internal byte-counting state machine on the channel, sets CCR0.TIE, and returns immediately. Each subsequent TXI then shifts one byte out of TDR and decrements the remaining count; when the count reaches zero, TIE is cleared automatically. If a user TX callback was previously attached via ra8_sci_attach_tx_handler, it is still invoked once per byte (with *byte already populated from data[i]) so existing flow-control hooks keep working.

Parameters
[in]channelSCI channel (0..9).
[in]dataSource buffer; must stay live until the transfer drains or is aborted.
[in]lenNumber of bytes to send. Zero is a no-op.
Returns
ra8_err_t error code.
Return values
k_ra8_okTransfer armed.
k_ra8_err_null_ptrdata is NULL with len > 0.
k_ra8_err_invalid_argchannel > 9 or channel not initialized.
k_ra8_err_busyA previous async TX is still draining.
Precondition
Channel previously initialized via ra8_sci_init.
data non-NULL when len > 0.
Postcondition
On success, CCR0.TIE = 1 and the per-channel TX state holds data / len.
Note
Thread safety: not thread-safe; ISR contention is the caller's responsibility.
See also
ra8_sci_abort
ra8_sci_dispatch_txi
Since
0.1.0

Definition at line 747 of file ra8_sci.c.

References r_sci_regs_t::CCR0, internal_reg(), k_ra8_err_busy, k_ra8_err_invalid_arg, k_ra8_err_null_ptr, k_ra8_ok, k_ra8_sci_ccr0_bit_tie, ra8_register_guard_enter(), ra8_register_guard_exit(), and s_sci_state.

Referenced by uart_irq_rx_cb().

◆ ra8_sci_write_polling()

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

Send len bytes by polling (convenience wrapper).

Parameters
[in]channelSCI channel number.
[in]dataByte buffer.
[in]lenNumber of bytes.
Returns
k_ra8_ok or the first error the inner putc returned.
Precondition
data non-NULL unless len == 0.
Postcondition
On success, every byte has been handed to TDR.
Since
0.1.0

Definition at line 516 of file ra8_sci.c.

References internal_reg(), internal_wait_tx_end(), k_ra8_err_invalid_arg, k_ra8_err_null_ptr, k_ra8_ok, and ra8_sci_putc_polling().

Referenced by blc_print(), blc_print_hex(), internal_uart_write(), main(), and ra8_board_uart_console_write().

Variable Documentation

◆ s_mstp_table

const ra8_mstp_t s_mstp_table[k_ra8_sci_channel_count_val]
static
Initial value:
= {
}
@ k_ra8_mstp_sci2
MSTPB29 SCI2.
@ k_ra8_mstp_sci4
MSTPB27 SCI4.
@ k_ra8_mstp_sci7
MSTPB24 SCI7.
@ k_ra8_mstp_sci9
MSTPB22 SCI9.
@ k_ra8_mstp_sci0
MSTPB31 SCI0.
@ k_ra8_mstp_sci5
MSTPB26 SCI5.
@ k_ra8_mstp_sci1
MSTPB30 SCI1.
@ k_ra8_mstp_sci6
MSTPB25 SCI6.
@ k_ra8_mstp_sci8
MSTPB23 SCI8.
@ k_ra8_mstp_sci3
MSTPB28 SCI3.

Channel-index -> MSTP id lookup.

Definition at line 100 of file ra8_sci.c.

Referenced by ra8_sci_deinit(), ra8_sci_enter_stop(), ra8_sci_exit_stop(), ra8_sci_init(), ra8_sci_spi_deinit(), and ra8_sci_spi_init().

◆ s_sci_state

Per-channel allocation + dispatch table.

Per-channel allocation + dispatch table (defined in ra8_sci.c).

Canonical definition of the cross-TU dispatch table declared extern in ra8_sci_internal.h; ra8_sci_dma_isr.c reads and mutates the same storage from the ISR dispatch path.

The canonical storage lives in ra8_sci.c; ra8_sci_dma_isr.c references it through this extern declaration so the ISR dispatch path sees the same in-flight async TX/RX state the configuration path mutates.

Note
Not thread-safe by itself. Its async TX/RX fields are published and torn down by the mainline runtime APIs (ra8_sci_write / read / abort / read_stop / deinit / the attach_*_handler pair) from inside an ra8_register_guard PRIMASK critical section, and are also mutated from the TXI/RXI ISR dispatch path in ra8_sci_dma_isr.c. The critical section (cpsid i + a "memory" clobber) both serialises the read-modify-write against a same-core ISR and prevents the compiler from reordering the descriptor publish past the interrupt enable (#176 / T1-02). ra8_sci_init publishes the initial zeroed state during single-threaded bring-up, before the channel IRQ is armed.
Warning
Do not redefine; the single definition is owned by ra8_sci.c.
Since
0.1.0

Definition at line 94 of file ra8_sci.c.

Referenced by ra8_sci_abort(), ra8_sci_attach_rx_handler(), ra8_sci_attach_tx_handler(), ra8_sci_deinit(), ra8_sci_dispatch_rxi(), ra8_sci_dispatch_txi(), ra8_sci_init(), ra8_sci_read(), ra8_sci_read_stop(), and ra8_sci_write().

◆ s_tag

const char* s_tag = "SCI"
static

Definition at line 78 of file ra8_sci.c.