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

OSPI / xSPI manual-command engine + JEDEC NOR-flash operations. More...

#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_hw_err.h"
#include "ra8_ospi_regs.h"
#include "ra8_xspi.h"
#include "ra8_xspi_internal.h"
Include dependency graph for ra8_xspi_flash.c:

Go to the source code of this file.

Enumerations

enum  xspi_mask_t : uint32_t { k_xspi_byte_mask = 0xFFUL }
 Low-byte mask for status/JEDEC-id extraction. More...
enum  ra8_spi_flash_op_t : uint8_t {
  k_ra8_spi_flash_op_write_enable = 0x06U ,
  k_ra8_spi_flash_op_page_program = 0x02U ,
  k_ra8_spi_flash_op_read_status = 0x05U ,
  k_ra8_spi_flash_op_read_id = 0x9FU ,
  k_ra8_spi_flash_op_read = 0x03U ,
  k_ra8_spi_flash_op_erase_sector = 0x20U
}
 Standard JEDEC NOR-flash command opcodes used by this driver. More...
enum  ra8_flash_status_bit_t : uint8_t {
  k_ra8_flash_status_bit_wip = 0U ,
  k_ra8_flash_status_bit_wel = 1U
}
 Bit positions in the SPI flash Status Register. More...
enum  ra8_xspi_addr_space_t : uint32_t { k_ra8_xspi_addr_space_3byte = 0x1000000UL }
 Reachable flash address space for the 3-byte JEDEC commands. More...
enum  ra8_xspi_cdt_limits_t : uint8_t { k_ra8_xspi_cdt_max_data_bytes = 8U }
 Per-transaction byte-size limits encodable in CDT. More...
enum  ra8_spi_flash_resp_bytes_t : uint8_t {
  k_ra8_xspi_resp_bytes_status = 1U ,
  k_ra8_xspi_resp_bytes_jedec = 3U
}
 Per-opcode response-byte counts for read-direction commands. More...

Functions

static uint32_t internal_make_cdt (uint8_t opcode, uint8_t cmd_bytes, uint8_t addr_bytes, uint8_t data_bytes, uint8_t is_write)
 Encode a manual-command CDT word (opcode + size/type fields).
static ra8_err_t internal_flash_range_check (uint32_t flash_addr, uint32_t len)
 Validate a [flash_addr, flash_addr + len) window against the 3-byte JEDEC address space.
static ra8_err_t internal_wait_command_done (volatile r_xspi_regs_t *reg)
 Wait for a manual XSPI command to retire, then clear its status bits.
ra8_err_t priv_ra8_xspi_kick_command (volatile r_xspi_regs_t *reg)
 Kick a prepared manual-command transfer by raising TRREQ.
ra8_err_t priv_ra8_xspi_issue_simple_opcode (volatile r_xspi_regs_t *reg, uint8_t opcode)
 Build CDBUF[0] for a 1-byte opcode with no address / no data.
static ra8_err_t internal_issue_read_opcode (volatile r_xspi_regs_t *reg, uint8_t opcode, uint8_t resp_bytes)
 Issue a 1-byte opcode that returns 1..8 response data bytes.
static void internal_build_chunk_header (volatile r_xspi_regs_t *reg, uint8_t opcode, uint32_t addr, uint8_t data_bytes, uint8_t is_write)
 Build CDBUF[0] for a single CDD0/CDD1 chunk of an opcode + addr.
static ra8_err_t internal_flash_read_chunk (volatile r_xspi_regs_t *reg, uint32_t flash_addr, uint8_t *buf, uint32_t chunk)
 Read one manual-command slot (<= 8 bytes) from flash into buf.
ra8_err_t ra8_xspi_flash_read (uint8_t instance, uint32_t flash_addr, uint8_t *buf, uint32_t len)
 Read len bytes from external flash into buf.
static ra8_err_t internal_flash_stage_program (volatile r_xspi_regs_t *reg, uint32_t flash_addr, uint32_t len)
 Stage WREN + page-program header (CDT + CDA only) without kicking.
static ra8_err_t internal_poll_wip_clear (uint8_t instance)
 Poll the SPI-flash Status Register until Write-In-Progress clears.
static void internal_xspi_stage_payload (volatile r_xspi_regs_t *reg, const uint8_t *data, uint32_t len)
 Stage the page-program payload into CDBUF[CDD0] / CDBUF[CDD1].
static ra8_err_t internal_flash_program_chunk (volatile r_xspi_regs_t *reg, uint8_t instance, uint32_t flash_addr, const uint8_t *data, uint32_t chunk)
 Program one page-program slot (<= 8 bytes) at flash_addr.
ra8_err_t ra8_xspi_flash_program (uint8_t instance, uint32_t flash_addr, const uint8_t *data, uint32_t len)
 Program (write) len bytes at flash_addr.
ra8_err_t ra8_xspi_flash_erase_sector (uint8_t instance, uint32_t flash_addr)
 Erase the 4 KiB sector containing flash_addr.
ra8_err_t ra8_xspi_flash_read_status (uint8_t instance, uint8_t *out_status)
 Read the flash Status Register (opcode 0x05).
ra8_err_t ra8_xspi_flash_read_id (uint8_t instance, uint32_t *out_id)
 Read the JEDEC ID (opcode 0x9F), returning 24 bits in a uint32_t.

Variables

static const char * s_tag = "XSPI"
 Logging tag for this driver.

Detailed Description

OSPI / xSPI manual-command engine + JEDEC NOR-flash operations.

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

Sibling translation unit of ra8_xspi.c (split out for file size). Owns the xSPI manual-command engine – the CDT/CDBUF builders, the INTS.CMDCMP poll, and the CDCTL0.TRREQ kick – and the JEDEC SPI NOR-flash operations layered on top of it:

The two manual-command primitives priv_ra8_xspi_kick_command() and priv_ra8_xspi_issue_simple_opcode() are exported via ra8_xspi_internal.h because the lifecycle surface in ra8_xspi.c (suspend / resume / software-reset) reuses them.

Every build runs the identical register sequence. On the host the CMDCMP poll consults the ra8_fake_mmio seam (tests/mocks/src/ra8_fake_mmio.c) so a unit test can model the peripheral: the register-level NOR-flash model in tests/mocks/src/ra8_fake_xspi_flash.c services each TRREQ kick on the driver's own poll thread, and fault tests arm the seam to drive the timeout legs (#238). Every register access carries a HUM Ch 44 "Octal Serial Peripheral Interface (OSPI)" p 2986 citation comment for the cite checker.

Since
0.1.0

Definition in file ra8_xspi_flash.c.

Enumeration Type Documentation

◆ ra8_flash_status_bit_t

enum ra8_flash_status_bit_t : uint8_t

Bit positions in the SPI flash Status Register.

Enumerator
k_ra8_flash_status_bit_wip 

Write-In-Progress (busy).

k_ra8_flash_status_bit_wel 

Write Enable Latch.

Definition at line 75 of file ra8_xspi_flash.c.

◆ ra8_spi_flash_op_t

enum ra8_spi_flash_op_t : uint8_t

Standard JEDEC NOR-flash command opcodes used by this driver.

Enumerator
k_ra8_spi_flash_op_write_enable 

0x06 WREN.

k_ra8_spi_flash_op_page_program 

0x02 page program.

k_ra8_spi_flash_op_read_status 

0x05 read status reg.

k_ra8_spi_flash_op_read_id 

0x9F JEDEC ID read.

k_ra8_spi_flash_op_read 

0x03 normal read.

k_ra8_spi_flash_op_erase_sector 

0x20 sector erase.

Definition at line 62 of file ra8_xspi_flash.c.

◆ ra8_spi_flash_resp_bytes_t

Per-opcode response-byte counts for read-direction commands.

The xSPI manual-command engine drives DATASIZE clocks on the bus after the opcode (and address, if any) so the device can stream its response bytes into CDD0/CDD1. For 0x05 RDSR the device sends 1 byte; for 0x9F RDID it sends the JEDEC triplet (3 bytes). With DATASIZE=0 the controller never clocks the response phase and CDD0 stays at whatever it held before the transfer – which is why an earlier version of this driver always read WIP=0 and tripped LevelX into believing erases had completed instantly. IS25LX512M datasheet Ch 8.6 (RDSR) + Ch 8.13 (RDID).

Enumerator
k_ra8_xspi_resp_bytes_status 

RDSR returns 1 status byte.

k_ra8_xspi_resp_bytes_jedec 

RDID returns MFR+TYPE+CAP.

Definition at line 171 of file ra8_xspi_flash.c.

◆ ra8_xspi_addr_space_t

enum ra8_xspi_addr_space_t : uint32_t

Reachable flash address space for the 3-byte JEDEC commands.

Every read / program / erase this driver issues encodes its address phase as ADDSIZE=3 (24 bits on the wire), so a flash_addr at or beyond 2^24 cannot be transmitted – the controller would silently truncate it to the low 24 bits and the command would land on the wrong sector. The public operations validate the whole [flash_addr, flash_addr + len) window against this bound up front and reject the call instead.

Enumerator
k_ra8_xspi_addr_space_3byte 

2^24: 3-byte address limit.

Definition at line 93 of file ra8_xspi_flash.c.

◆ ra8_xspi_cdt_limits_t

enum ra8_xspi_cdt_limits_t : uint8_t

Per-transaction byte-size limits encodable in CDT.

Enumerator
k_ra8_xspi_cdt_max_data_bytes 

CDD0 + CDD1 = 8 bytes per slot.

Definition at line 101 of file ra8_xspi_flash.c.

◆ xspi_mask_t

enum xspi_mask_t : uint32_t

Low-byte mask for status/JEDEC-id extraction.

Enumerator
k_xspi_byte_mask 

XSPI byte mask.

Definition at line 54 of file ra8_xspi_flash.c.

Function Documentation

◆ internal_build_chunk_header()

void internal_build_chunk_header ( volatile r_xspi_regs_t * reg,
uint8_t opcode,
uint32_t addr,
uint8_t data_bytes,
uint8_t is_write )
static

Build CDBUF[0] for a single CDD0/CDD1 chunk of an opcode + addr.

Used by the read path (TRTYPE=read) and by the program path (TRTYPE=write) to programme the per-chunk header. Address phase is fixed at 3 bytes for the JEDEC opcodes in use; data_bytes is 0..8 (one slot's worth). FSP equivalent: the body of r_ospi_b_direct_transfer that builds cdtbuf0.

Parameters
[in]regSee declaration: volatile r_xspi_regs_t* reg.
[in]opcodeSee declaration: uint8_t opcode.
[in]addrSee declaration: uint32_t addr.
[in]data_bytesSee declaration: uint8_t data_bytes.
[in]is_writeSee declaration: uint8_t is_write.
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 361 of file ra8_xspi_flash.c.

References r_xspi_regs_t::CDBUF, internal_make_cdt(), k_ra8_xspi_cdbuf_idx_addr, k_ra8_xspi_cdbuf_idx_cdt, k_ra8_xspi_cdt_addsize_3, and k_ra8_xspi_cdt_cmdsize_1.

Referenced by internal_flash_read_chunk(), internal_flash_stage_program(), and ra8_xspi_flash_erase_sector().

◆ internal_flash_program_chunk()

ra8_err_t internal_flash_program_chunk ( volatile r_xspi_regs_t * reg,
uint8_t instance,
uint32_t flash_addr,
const uint8_t * data,
uint32_t chunk )
static

Program one page-program slot (<= 8 bytes) at flash_addr.

Runs the full WREN -> 0x02 page-program -> WIP-poll sequence for a single manual-command slot of chunk bytes:

  1. internal_flash_stage_program writes WREN, builds the PP command header in CDT/CDA, and returns without asserting TRREQ.
  2. internal_xspi_stage_payload packs data[] into CDBUF[CDD0/CDD1].
  3. priv_ra8_xspi_kick_command asserts CDCTL0.TRREQ and polls CMDCMP.
  4. internal_poll_wip_clear issues 0x05 RDSR until WIP=0.

chunk must be <= k_ra8_xspi_cdt_max_data_bytes (8) and must not cross a k_ra8_xspi_page_len (256-byte) NOR page boundary; the ra8_xspi_flash_program loop enforces both before calling.

Parameters
[in]regxSPI register block (already gated open).
[in]instancexSPI instance index (for the RDSR WIP poll).
[in]flash_addrDestination flash byte address for this chunk.
[in]dataSource bytes (chunk of them).
[in]chunkByte count for this transfer (1..8).
Returns
ra8_err_t outcome of the chunk program.
Return values
k_ra8_okChunk programmed and WIP cleared.
k_ra8_err_hw_timeoutWREN or PP never retired (CMDCMP timeout).
k_ra8_err_timeoutWIP never cleared after the program.
Precondition
reg != nullptr and data != nullptr.
chunk is in [1..8] and stays within one 256-byte page.
Postcondition
On success chunk bytes are persisted at flash_addr.
On success the flash WIP bit is clear (controller idle).
Note
Not thread-safe; caller serialises bus access.
Since
0.1.0

Definition at line 665 of file ra8_xspi_flash.c.

References internal_flash_stage_program(), internal_poll_wip_clear(), internal_xspi_stage_payload(), k_ra8_ok, and priv_ra8_xspi_kick_command().

Referenced by ra8_xspi_flash_program().

◆ internal_flash_range_check()

ra8_err_t internal_flash_range_check ( uint32_t flash_addr,
uint32_t len )
static

Validate a [flash_addr, flash_addr + len) window against the 3-byte JEDEC address space.

Two single-condition checks (no compound decision): the start address must lie inside the 2^24-byte window ADDSIZE=3 can encode, and the transfer must not run past its end. The subtraction form of the second check cannot overflow because the first check already bounded flash_addr. Rejecting here prevents the controller from silently truncating the address to 24 bits on the wire and landing the command on the wrong sector.

Parameters
[in]flash_addrFirst flash byte address of the transfer.
[in]lenTransfer length in bytes (0 allowed for erase).
Returns
ra8_err_t Error code.
Return values
k_ra8_okThe whole window is 3-byte addressable.
k_ra8_err_invalid_argThe window starts or ends past 2^24.
Precondition
len was already bounded by the caller (<= k_ra8_xspi_max_xfer).
The caller passes the transfer's true byte extent.
Postcondition
No state is modified (pure comparison).
The return reflects only the addressability comparison.
Note
Thread-safe (pure comparison).
Since
0.1.0

Definition at line 205 of file ra8_xspi_flash.c.

References k_ra8_err_invalid_arg, k_ra8_ok, and k_ra8_xspi_addr_space_3byte.

Referenced by ra8_xspi_flash_erase_sector(), ra8_xspi_flash_program(), and ra8_xspi_flash_read().

◆ internal_flash_read_chunk()

ra8_err_t internal_flash_read_chunk ( volatile r_xspi_regs_t * reg,
uint32_t flash_addr,
uint8_t * buf,
uint32_t chunk )
static

Read one manual-command slot (<= 8 bytes) from flash into buf.

Issues a single JEDEC 0x03 read of chunk bytes at flash_addr and copies the CDBUF data words (CDD0 = bytes 0..3, CDD1 = bytes 4..7) into buf. chunk must be <= k_ra8_xspi_cdt_max_data_bytes (8) because the manual-command engine only carries 8 data bytes per transfer; ra8_xspi_flash_read loops this helper to cover arbitrary lengths.

Parameters
[in]regxSPI register block (already gated open).
[in]flash_addrSource flash byte address for this chunk.
[out]bufDestination buffer for chunk bytes.
[in]chunkByte count for this transfer (1..8).
Returns
ra8_err_t outcome of the chunk read.
Return values
k_ra8_okChunk read and copied.
k_ra8_err_hw_timeoutCMDCMP timeout from the read command.
Precondition
reg != nullptr and buf != nullptr.
chunk is in [1..8].
Postcondition
On success buf[0..chunk-1] holds the flash data.
No state outside buf and the CDBUF slot is modified.
Note
Not thread-safe; caller serialises bus access.
Since
0.1.0

Definition at line 406 of file ra8_xspi_flash.c.

References r_xspi_regs_t::CDBUF, internal_build_chunk_header(), k_ra8_ok, k_ra8_spi_flash_op_read, k_ra8_xspi_cdbuf_idx_data0, k_ra8_xspi_cdbuf_idx_data1, k_ra8_xspi_cdt_trtype_read, and priv_ra8_xspi_kick_command().

Referenced by ra8_xspi_flash_read().

◆ internal_flash_stage_program()

ra8_err_t internal_flash_stage_program ( volatile r_xspi_regs_t * reg,
uint32_t flash_addr,
uint32_t len )
static

Stage WREN + page-program header (CDT + CDA only) without kicking.

Splits the previous "WREN -> build PP header -> KICK" helper so the caller can load the outgoing payload into CDBUF[CDD0] / CDBUF[CDD1] BEFORE TRREQ is asserted. The earlier code asserted TRREQ here and only loaded CDD0/CDD1 afterwards, which clocked the stale CDBUF contents (zeros, or whatever the previous read response left behind) onto the bus instead of the caller's data. That bug surfaced as: (a) flash_journal's first round-trip "passing" purely because CDD0/CDD1 happened to be zero (matching counter=0) while every subsequent counter mismatched, (b) the threadx_levelx_demo panicking inside lx_nor_flash_format because LevelX's free-bit metadata reads back as the previous transfer's status byte instead of the bit-pattern it just wrote, and (c) the threadx_fs_levelx_demo surfacing lx_nor_flash_format failed for the same reason – every LevelX sector-header write to the on-board MX25xxx flash dropped its payload, so LevelX saw zero usable sectors.

HUM Ch 44 "Octal Serial Peripheral Interface (OSPI)" p 2986 documents the manual-command flow as "fill CDBUF, then set CDCTL0.TRREQ"; FSP r_ospi_b_direct_transfer (r_ospi_b.c line ~1311) writes the data words into CDBUF before TRREQ on every PP transfer.

Parameters
[in]regxSPI register block (already gated open).
[in]flash_addrDestination flash byte address.
[in]lenBytes to program in this chunk (1..8).
Returns
ra8_err_t outcome of the WREN sub-command.
Return values
k_ra8_okWREN dispatched and CMDCMP cleared.
otherUnderlying CMDCMP timeout from WREN.
Precondition
reg != nullptr and the xSPI MSTP gate is open.
len has been clamped by the caller to [1..8].
Postcondition
On success the controller has accepted WREN and the PP CDT/CDA words are staged in CDBUF slot 0 awaiting TRREQ.
CDBUF[CDD0]/CDBUF[CDD1] are intentionally NOT touched here so the caller can load the payload before kicking.
Note
Not thread-safe; caller serialises bus access.
Since
0.1.0

Definition at line 508 of file ra8_xspi_flash.c.

References internal_build_chunk_header(), k_ra8_ok, k_ra8_spi_flash_op_page_program, k_ra8_spi_flash_op_write_enable, k_ra8_xspi_cdt_max_data_bytes, k_ra8_xspi_cdt_trtype_write, and priv_ra8_xspi_issue_simple_opcode().

Referenced by internal_flash_program_chunk().

◆ internal_issue_read_opcode()

ra8_err_t internal_issue_read_opcode ( volatile r_xspi_regs_t * reg,
uint8_t opcode,
uint8_t resp_bytes )
static

Issue a 1-byte opcode that returns 1..8 response data bytes.

Used by RDSR (0x05) / RDID (0x9F): no address phase, but we MUST tell the controller how many response bytes to clock in via DATASIZE. Caller reads the response out of CDBUF[CDD0/CDD1] after CMDCMP. HUM Ch 44 p 2986; IS25LX512M datasheet Ch 8.6 + 8.13.

Parameters
[in]regxSPI register block.
[in]opcodeJEDEC opcode (0x05 or 0x9F).
[in]resp_bytes1..8 response bytes to clock into CDBUF.
Returns
k_ra8_ok on success or the underlying CMDCMP timeout.
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 324 of file ra8_xspi_flash.c.

References r_xspi_regs_t::CDBUF, internal_make_cdt(), k_ra8_xspi_cdbuf_idx_addr, k_ra8_xspi_cdbuf_idx_cdt, k_ra8_xspi_cdbuf_idx_data0, k_ra8_xspi_cdbuf_idx_data1, k_ra8_xspi_cdt_addsize_0, k_ra8_xspi_cdt_cmdsize_1, k_ra8_xspi_cdt_trtype_read, and priv_ra8_xspi_kick_command().

Referenced by ra8_xspi_flash_read_id(), and ra8_xspi_flash_read_status().

◆ internal_make_cdt()

uint32_t internal_make_cdt ( uint8_t opcode,
uint8_t cmd_bytes,
uint8_t addr_bytes,
uint8_t data_bytes,
uint8_t is_write )
static

Encode a manual-command CDT word (opcode + size/type fields).

Mirrors FSP r_ospi_b_direct_transfer (line ~1311 of r_ospi_b.c): builds the CDBUF[0].CDT word from CMDSIZE/ADDSIZE/DATASIZE/TRTYPE plus the JEDEC opcode at bits [31..16]. Latency is fixed at zero for the simple JEDEC opcodes this driver issues. HUM Ch 44 p 2986.

Parameters
[in]opcodeSee declaration: uint8_t opcode.
[in]cmd_bytesSee declaration: uint8_t cmd_bytes.
[in]addr_bytesSee declaration: uint8_t addr_bytes.
[in]data_bytesSee declaration: uint8_t data_bytes.
[in]is_writeSee declaration: uint8_t is_write.
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 130 of file ra8_xspi_flash.c.

References k_ra8_xspi_cdt_mask_addsize, k_ra8_xspi_cdt_mask_cmd, k_ra8_xspi_cdt_mask_cmdsize, k_ra8_xspi_cdt_mask_datasize, k_ra8_xspi_cdt_mask_trtype, k_ra8_xspi_cdt_pos_addsize, k_ra8_xspi_cdt_pos_cmd, k_ra8_xspi_cdt_pos_cmdsize, k_ra8_xspi_cdt_pos_datasize, and k_ra8_xspi_cdt_pos_trtype.

Referenced by internal_build_chunk_header(), internal_issue_read_opcode(), and priv_ra8_xspi_issue_simple_opcode().

◆ internal_poll_wip_clear()

ra8_err_t internal_poll_wip_clear ( uint8_t instance)
static

Poll the SPI-flash Status Register until Write-In-Progress clears.

Issues RDSR (via ra8_xspi_flash_read_status) in a statically-bounded loop until the WIP bit reads 0 or the program-timeout budget is exhausted. The status byte comes from the real RDSR response in CDD0 on every build; on the host the tests/mocks/src/ra8_fake_xspi_flash.c model answers it, holding WIP asserted for as many polls as the test configured so the loop's continuation and timeout legs are reachable.

Parameters
[in]instanceXSPI flash instance index passed to ra8_xspi_flash_read_status.
Returns
ra8_err_t Error code.
Return values
k_ra8_okWIP cleared within the timeout budget.
k_ra8_err_timeoutWIP stayed set for the full budget.
otherra8_xspi_flash_read_status reported a read fault.
Precondition
instance identifies an opened XSPI flash.
A write or erase command was just issued (WIP may be set).
Postcondition
On k_ra8_ok the device is idle (WIP == 0).
No register is written beyond the RDSR commands themselves.
Note
Not thread-safe; the XSPI program path is single-owner.
Since
0.1.0

Definition at line 559 of file ra8_xspi_flash.c.

References k_ra8_err_timeout, k_ra8_flash_program_timeout_us, k_ra8_flash_status_bit_wip, k_ra8_ok, and ra8_xspi_flash_read_status().

Referenced by internal_flash_program_chunk(), and ra8_xspi_flash_erase_sector().

◆ internal_wait_command_done()

ra8_err_t internal_wait_command_done ( volatile r_xspi_regs_t * reg)
static

Wait for a manual XSPI command to retire, then clear its status bits.

Bounded poll of the XSPI INTS register for the CMDCMP (command complete) flag. On the host build each poll iteration consults the ra8_fake_mmio seam (the i2c / i3c / sdhi status-poll pattern): the tests/mocks/src/ra8_fake_xspi_flash.c model services the pending TRREQ kick synchronously inside the consult and the loop then observes the CMDCMP flag the model raised, while a fault test arms the seam on INTS to force the timeout / continuation legs. On completion it clears every pending status bit via INTC = INTS, mirroring FSP r_ospi_b_direct_transfer.

Parameters
[in,out]regXSPI register block; INTS is polled and INTC written.
Returns
ra8_err_t Error code.
Return values
k_ra8_okCMDCMP was observed and the retired status bits cleared.
k_ra8_err_hw_timeoutCMDCMP never asserted within the spin budget.
Precondition
reg is a valid, powered XSPI register block.
A manual command was just issued (CDCTL0.TRREQ set).
Postcondition
On success every retired INTS status bit is cleared.
On failure the register state is left unchanged.
Note
Not thread-safe; the XSPI manual-command path is single-owner.
Since
0.1.0

Definition at line 246 of file ra8_xspi_flash.c.

References r_xspi_regs_t::INTC, r_xspi_regs_t::INTS, k_ra8_err_hw_timeout, k_ra8_ok, k_ra8_xspi_cmd_spin, and k_ra8_xspi_ints_mask_cmdcmp.

Referenced by priv_ra8_xspi_kick_command().

◆ internal_xspi_stage_payload()

void internal_xspi_stage_payload ( volatile r_xspi_regs_t * reg,
const uint8_t * data,
uint32_t len )
static

Stage the page-program payload into CDBUF[CDD0] / CDBUF[CDD1].

HUM Ch 44 "Octal Serial Peripheral Interface (OSPI)" p 2986 + FSP r_ospi_b_direct_transfer document the manual-command flow as "fill CDBUF, then set CDCTL0.TRREQ". The prior implementation issued the WREN + 0x02 page-program header and asserted TRREQ BEFORE staging the caller's bytes; the controller therefore clocked out whatever stale words were left in CDD0/CDD1 from the previous transfer. Splitting the staging step into this helper lets ra8_xspi_flash_program write the real payload first and only then kick the transaction.

Parameters
[in]regxSPI register block (already gated open by the caller).
[in]dataCaller bytes. Must be non-NULL; len bytes are read.
[in]lenNumber of bytes to stage, in [1..8] (manual- command CDBUF capacity).
Precondition
reg != nullptr and the xSPI MSTPCR gate has been opened.
data != nullptr and len is clamped to [1..8].
Postcondition
CDBUF[CDD0] holds bytes data[0..min(3,len)] packed little-endian.
CDBUF[CDD1] holds bytes data[4..len-1] (or zero if len <= 4).
Note
Not thread-safe; caller serialises bus access.
Since
0.1.0

Definition at line 608 of file ra8_xspi_flash.c.

References r_xspi_regs_t::CDBUF, k_ra8_xspi_cdbuf_idx_data0, and k_ra8_xspi_cdbuf_idx_data1.

Referenced by internal_flash_program_chunk().

◆ priv_ra8_xspi_issue_simple_opcode()

ra8_err_t priv_ra8_xspi_issue_simple_opcode ( volatile r_xspi_regs_t * reg,
uint8_t opcode )

Build CDBUF[0] for a 1-byte opcode with no address / no data.

Defined in ra8_xspi_flash.c. Populates CDBUF slot 0 per FSP r_ospi_b_direct_transfer (CDT carries opcode + size encoding, CDA/CDD0/CDD1 zeroed) and kicks the transfer. Promoted to TU-external linkage so the lifecycle surface in ra8_xspi.c (suspend / resume) can reuse it. HUM Ch 44 p 2986.

Parameters
[in]regxSPI register block (already gated open by the caller).
[in]opcodeJEDEC opcode to issue (no address, no payload).
Returns
ra8_err_t outcome.
Return values
k_ra8_okCommand dispatched and CMDCMP cleared.
k_ra8_err_hw_timeoutUnderlying CMDCMP timeout.
Precondition
reg != nullptr and the xSPI MSTP gate is open.
The controller is idle (no manual command in flight).
Postcondition
On success the opcode has been clocked out and CMDCMP cleared.
No flash address or payload words are transmitted.
Note
Not thread-safe; the caller must serialise concurrent access.
Since
0.1.0

Definition at line 279 of file ra8_xspi_flash.c.

References r_xspi_regs_t::CDBUF, internal_make_cdt(), k_ra8_xspi_cdbuf_idx_addr, k_ra8_xspi_cdbuf_idx_cdt, k_ra8_xspi_cdbuf_idx_data0, k_ra8_xspi_cdbuf_idx_data1, k_ra8_xspi_cdt_addsize_0, k_ra8_xspi_cdt_cmdsize_1, k_ra8_xspi_cdt_trtype_read, and priv_ra8_xspi_kick_command().

Referenced by internal_flash_stage_program(), ra8_xspi_flash_erase_sector(), ra8_xspi_resume(), and ra8_xspi_suspend().

◆ priv_ra8_xspi_kick_command()

ra8_err_t priv_ra8_xspi_kick_command ( volatile r_xspi_regs_t * reg)

Kick a prepared manual-command transfer by raising TRREQ.

Defined in ra8_xspi_flash.c. FSP r_ospi_b_direct_transfer waits for any prior in-flight TRREQ to self-clear before pushing a new request, then sets TRREQ=1 and waits for it to self-clear again. We mirror the FSP "self-clear" semantics by polling INTS.CMDCMP. Promoted to TU-external linkage so the lifecycle surface in ra8_xspi.c (software-reset path) can reuse it. HUM Ch 44 p 2986.

Parameters
[in]regxSPI register block (already gated open by the caller).
Returns
ra8_err_t outcome.
Return values
k_ra8_okCMDCMP observed; transfer retired.
k_ra8_err_hw_timeoutCMDCMP never fired within the budget.
Precondition
reg != nullptr and the xSPI MSTP gate is open.
The CDBUF slot has been fully populated by the caller.
Postcondition
On success the controller is idle and INTS is cleared.
On timeout no further register state is modified.
Note
Not thread-safe; the caller must serialise concurrent access.
Since
0.1.0

Definition at line 272 of file ra8_xspi_flash.c.

References r_xspi_regs_t::CDCTL0, internal_wait_command_done(), and k_ra8_xspi_cdctl0_mask_trreq.

Referenced by internal_flash_program_chunk(), internal_flash_read_chunk(), internal_issue_read_opcode(), internal_issue_reset_opcode(), priv_ra8_xspi_issue_simple_opcode(), and ra8_xspi_flash_erase_sector().

◆ ra8_xspi_flash_erase_sector()

ra8_err_t ra8_xspi_flash_erase_sector ( uint8_t instance,
uint32_t flash_addr )
nodiscard

Erase the 4 KiB sector containing flash_addr.

Parameters
[in]instancexSPI instance.
[in]flash_addrAddress within the target sector (3-byte addressable).
Returns
k_ra8_ok on success.
k_ra8_err_null_ptr if instance is out of range.
k_ra8_err_invalid_arg if flash_addr exceeds the 2^24-byte window a 3-byte JEDEC address can reach.
k_ra8_err_hw_timeout if the WREN / SE command never retires.
k_ra8_err_timeout if WIP does not clear.
Since
0.1.0

Definition at line 724 of file ra8_xspi_flash.c.

References internal_build_chunk_header(), internal_flash_range_check(), internal_poll_wip_clear(), k_ra8_ok, k_ra8_spi_flash_op_erase_sector, k_ra8_spi_flash_op_write_enable, k_ra8_xspi_cdt_trtype_write, priv_ra8_xspi_issue_simple_opcode(), priv_ra8_xspi_kick_command(), RA8_CHECK_NULL_PTR, ra8_xspi(), and s_tag.

Referenced by flash_journal_round_trip(), internal_nor_block_erase(), internal_write_one_sector(), internal_xspi_erase(), ospirw_ospi_provision(), and selftest_ospi_write_pattern().

◆ ra8_xspi_flash_program()

ra8_err_t ra8_xspi_flash_program ( uint8_t instance,
uint32_t flash_addr,
const uint8_t * data,
uint32_t len )
nodiscard

Program (write) len bytes at flash_addr.

Sequence per chunk is: Write Enable -> Page Program -> Poll WIP, with chunks clamped to the 8-byte manual-command slot and to 256-byte NOR page boundaries. Every build drives the identical xSPI register sequence; host unit tests run it against the register-level NOR model in tests/mocks/src/ra8_fake_xspi_flash.c.

Parameters
[in]instancexSPI instance.
[in]flash_addrFlash offset (3-byte addressable).
[in]dataSource buffer.
[in]lenNumber of bytes to program.
Returns
k_ra8_ok on success.
k_ra8_err_null_ptr if data or instance is invalid.
k_ra8_err_invalid_arg if len == 0, len > k_ra8_xspi_max_xfer, or [flash_addr, flash_addr + len) exceeds the 2^24-byte window a 3-byte JEDEC address can reach.
k_ra8_err_hw_timeout if a WREN / PP command never retires.
k_ra8_err_timeout if the WIP bit never clears.
Since
0.1.0

Definition at line 685 of file ra8_xspi_flash.c.

References internal_flash_program_chunk(), internal_flash_range_check(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_xspi_cdt_max_data_bytes, k_ra8_xspi_max_xfer, k_ra8_xspi_page_len, RA8_CHECK_NULL_PTR, ra8_xspi(), and s_tag.

Referenced by flash_journal_round_trip(), internal_nor_write(), internal_xspi_program_chunked(), ospirw_msc_write(), and selftest_ospi_write_pattern().

◆ ra8_xspi_flash_read()

ra8_err_t ra8_xspi_flash_read ( uint8_t instance,
uint32_t flash_addr,
uint8_t * buf,
uint32_t len )
nodiscard

Read len bytes from external flash into buf.

Builds a standard 0x03 (1S-1S-1S) read command sequence in 8-byte manual-command chunks, kicks each via CDCTL0.TRREQ, polls INTS.CMDCMP for completion, and copies the CDD0/CDD1 response words into buf. Host unit tests exercise the identical sequence against the register-level NOR model in tests/mocks/src/ra8_fake_xspi_flash.c.

Parameters
[in]instancexSPI instance (0 or 1).
[in]flash_addrFlash offset to read from (3-byte addressable).
[out]bufDestination buffer. Must not be NULL.
[in]lenNumber of bytes to read.
Returns
k_ra8_ok on success.
k_ra8_err_null_ptr if buf is NULL or instance out of range.
k_ra8_err_invalid_arg if len == 0, len > k_ra8_xspi_max_xfer, or [flash_addr, flash_addr + len) exceeds the 2^24-byte window a 3-byte JEDEC address can reach.
k_ra8_err_hw_timeout if a read command never retires (CMDCMP).
Since
0.1.0

Definition at line 431 of file ra8_xspi_flash.c.

References internal_flash_range_check(), internal_flash_read_chunk(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_xspi_cdt_max_data_bytes, k_ra8_xspi_max_xfer, RA8_CHECK_NULL_PTR, ra8_xspi(), and s_tag.

Referenced by flash_journal_round_trip(), internal_nor_block_erased_verify(), internal_nor_read(), internal_xspi_read_chunked(), ospirw_msc_read(), ra8_nsc_xspi_read(), and selftest_fat_fill_sector().

◆ ra8_xspi_flash_read_id()

ra8_err_t ra8_xspi_flash_read_id ( uint8_t instance,
uint32_t * out_id )
nodiscard

Read the JEDEC ID (opcode 0x9F), returning 24 bits in a uint32_t.

The returned word packs the three JEDEC bytes as: (manufacturer << 16) | (mem_type << 8) | capacity. Compatible with Macronix MX25, Winbond W25, Renesas AT25, and ISSI IS25 parts.

Parameters
[in]instancexSPI instance.
[out]out_id24-bit JEDEC ID in a 32-bit word.
Returns
k_ra8_ok on success.
k_ra8_err_null_ptr if pointer is NULL or instance out of range.
Since
0.1.0

Definition at line 773 of file ra8_xspi_flash.c.

References r_xspi_regs_t::CDBUF, internal_issue_read_opcode(), k_ra8_ok, k_ra8_spi_flash_op_read_id, k_ra8_xspi_cdbuf_idx_data0, k_ra8_xspi_resp_bytes_jedec, k_xspi_byte_mask, RA8_CHECK_NULL_PTR, ra8_xspi(), and s_tag.

Referenced by flash_journal_setup_or_halt(), internal_probe_rdid(), ospirw_ospi_provision(), and selftest_ospi_provision().

◆ ra8_xspi_flash_read_status()

ra8_err_t ra8_xspi_flash_read_status ( uint8_t instance,
uint8_t * out_status )
nodiscard

Read the flash Status Register (opcode 0x05).

Parameters
[in]instancexSPI instance.
[out]out_statusStatus-register value (WIP is bit 0).
Returns
k_ra8_ok on success.
k_ra8_err_null_ptr if pointer is NULL or instance out of range.
Since
0.1.0

Definition at line 753 of file ra8_xspi_flash.c.

References r_xspi_regs_t::CDBUF, internal_issue_read_opcode(), k_ra8_ok, k_ra8_spi_flash_op_read_status, k_ra8_xspi_cdbuf_idx_data0, k_ra8_xspi_resp_bytes_status, k_xspi_byte_mask, RA8_CHECK_NULL_PTR, ra8_xspi(), and s_tag.

Referenced by internal_poll_wip_clear().

Variable Documentation

◆ s_tag

const char* s_tag = "XSPI"
static

Logging tag for this driver.

Definition at line 51 of file ra8_xspi_flash.c.