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

SD-card-over-SPI device model for ra8_emulator (attached to SPI_B). More...

#include "board_periph_sd.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "board_console.h"
#include "board_periph_sd_internal.h"
Include dependency graph for board_periph_sd.c:

Go to the source code of this file.

Enumerations

enum  sd_console_t : uint32_t {
  k_sd_console_line_cap = 48U ,
  k_sd_console_rd_every = 16U
}
 Console-tap sizing for SD-over-SPI block summaries. More...
enum  board_sd_cmd_idx_t : uint8_t {
  k_sd_idx_cmd0 = 0U ,
  k_sd_idx_cmd8 = 8U ,
  k_sd_idx_cmd9 = 9U ,
  k_sd_idx_cmd12 = 12U ,
  k_sd_idx_cmd16 = 16U ,
  k_sd_idx_cmd17 = 17U ,
  k_sd_idx_cmd18 = 18U ,
  k_sd_idx_cmd24 = 24U ,
  k_sd_idx_cmd25 = 25U ,
  k_sd_idx_cmd32 = 32U ,
  k_sd_idx_cmd33 = 33U ,
  k_sd_idx_cmd38 = 38U ,
  k_sd_idx_acmd41 = 41U ,
  k_sd_idx_cmd55 = 55U ,
  k_sd_idx_cmd58 = 58U
}
 SD SPI command indices answered by the model (low 6 bits of byte 0). More...

Functions

static uint16_t internal_board_sd_crc16 (const uint8_t *data, uint32_t len)
 CRC16-CCITT (poly 0x1021, init 0) over a buffer.
static bool internal_board_sd_fill_block (const board_sd_state_t *c, uint64_t off, uint8_t *blk)
 Copy one 512-byte block out of the backing image (zero past the end).
static void internal_board_sd_stage_block (board_sd_state_t *c, const uint8_t *payload, uint32_t len)
 Stage the R1 + data-token + payload + CRC16 reply for a block read.
static void internal_board_sd_begin_read (board_sd_state_t *c, uint8_t idx, uint32_t arg)
 Accept a CMD17/CMD18 block-read command and stage the first block.
static void internal_board_sd_read_stream_next (board_sd_state_t *c)
 Stage the next block of an open CMD18 stream (token + payload + CRC).
static void internal_board_sd_stop_read (board_sd_state_t *c, uint8_t r1)
 Answer CMD12 STOP_TRANSMISSION and close any open CMD18 stream.
static void internal_board_sd_begin_write (board_sd_state_t *c, uint8_t idx, uint32_t arg, uint8_t r1)
 Accept a CMD24/CMD25 block-write command and arm the data phase.
static void internal_sd_write_token (board_sd_state_t *c, uint8_t tx)
 Handle a byte while the model waits for a write data token.
static void internal_sd_write_data (board_sd_state_t *c, uint8_t tx)
 Absorb one payload byte of a write block.
static void internal_sd_write_crc (board_sd_state_t *c)
 Swallow the two block-CRC bytes, then acknowledge the block.
static uint8_t internal_board_sd_write_byte (board_sd_state_t *c, uint8_t tx)
 Feed one host byte into an in-flight block write; return the CIPO byte.
static void internal_board_sd_cmd_send_csd (board_sd_state_t *c)
 Stage the 16-byte CSD v2.0 data block for a CMD9 (SEND_CSD) reply.
static bool internal_board_sd_dispatch_ident (board_sd_state_t *c, uint8_t idx, uint8_t r1)
 Handle the identification / configuration commands (CMD0/8/55/58/16).
static void internal_board_sd_cmd_erase_bound (board_sd_state_t *c, uint32_t *bound, uint32_t arg, uint8_t r1)
 Record one bound of the CMD32/CMD33 erase range and acknowledge it.
static void internal_board_sd_cmd_erase (board_sd_state_t *c, uint8_t r1)
 Zero the latched [start, end] block range – CMD38 (ERASE).
static void internal_board_sd_dispatch_data (board_sd_state_t *c, uint8_t idx, uint32_t arg, uint8_t r1)
 Handle the data-transfer and erase commands (CMD9/17/18/12/24/25/32/33/38).
static void internal_board_sd_process_cmd (board_sd_state_t *c)
 Build the response for a completed 6-byte command frame.
uint8_t board_sd_exchange (uint8_t tx)
 Exchange one full-duplex SPI byte with the modelled card.
bool board_sd_read_block (uint32_t lba, uint8_t *dst)
 Copy one 512-byte block straight out of the backing image.
bool board_sd_write_block (uint32_t lba, const uint8_t *src)
 Copy one 512-byte block straight into the backing image.
void board_sd_reset (void)
 Reset the card's command / response framing to power-on.

Variables

static uint32_t s_sd_spi_block_reads
 Count of SD-over-SPI data blocks staged for read this run.
board_sd_state_t g_board_sd = {.image_fd = -1}
 The single modelled SD card (declared in board_periph_sd_internal.h).

Detailed Description

SD-card-over-SPI device model for ra8_emulator (attached to SPI_B).

Implements a high-capacity (SDHC) SD card running in SPI mode, backed by a host image file. The card answers the SD SPI command set the firmware's ra8_sdmmc_spi driver issues during bring-up and block I/O:

  • CMD0 GO_IDLE_STATE -> R1 = 0x01
  • CMD8 SEND_IF_COND -> R7 (R1 + 0x000001AA echo)
  • CMD55 + ACMD41 -> R1 = 0x00 (card ready)
  • CMD58 READ_OCR -> R3 (R1 + OCR with CCS=1 = SDHC)
  • CMD9 SEND_CSD -> R1 + 0xFE + 16-byte CSD v2.0 + CRC16
  • CMD17 READ_SINGLE_BLOCK -> R1 + 0xFE + 512 data bytes + CRC16
  • CMD18 READ_MULTIPLE_BLOCK -> as CMD17, then keeps streaming successive blocks until CMD12 STOP_TRANSMISSION
  • CMD12 STOP_TRANSMISSION -> stuff byte + R1 (ends a CMD18 stream)

Commands self-frame off the 01xxxxxx lead bits, so the model needs no chip-select wiring. The command-framing approach is verified end to end against the real driver by the in-file seed model of apps/shared_libs/reflow/tests/src/test_ra8_sdmmc_card_reflow.c (single-block reads); the CMD18/CMD12 stream and the write paths are exercised against the same wire framing by the driver's own host tests (tests/storage/src/test_ra8_sdmmc_spi.c).

Since
0.1.0

Definition in file board_periph_sd.c.

Enumeration Type Documentation

◆ board_sd_cmd_idx_t

enum board_sd_cmd_idx_t : uint8_t

SD SPI command indices answered by the model (low 6 bits of byte 0).

Enumerator
k_sd_idx_cmd0 

GO_IDLE_STATE.

k_sd_idx_cmd8 

SEND_IF_COND.

k_sd_idx_cmd9 

SEND_CSD.

k_sd_idx_cmd12 

STOP_TRANSMISSION.

k_sd_idx_cmd16 

SET_BLOCKLEN.

k_sd_idx_cmd17 

READ_SINGLE.

k_sd_idx_cmd18 

READ_MULTIPLE.

k_sd_idx_cmd24 

WRITE_SINGLE.

k_sd_idx_cmd25 

WRITE_MULTIPLE.

k_sd_idx_cmd32 

ERASE_WR_BLK_START.

k_sd_idx_cmd33 

ERASE_WR_BLK_END.

k_sd_idx_cmd38 

ERASE.

k_sd_idx_acmd41 

SD_SEND_OP_COND.

k_sd_idx_cmd55 

APP_CMD.

k_sd_idx_cmd58 

READ_OCR.

Definition at line 62 of file board_periph_sd.c.

◆ sd_console_t

enum sd_console_t : uint32_t

Console-tap sizing for SD-over-SPI block summaries.

Enumerator
k_sd_console_line_cap 

Max chars in an "SDSPI .. .." line.

k_sd_console_rd_every 

Push 1 read line per N blocks (anti-flood).

Definition at line 43 of file board_periph_sd.c.

Function Documentation

◆ board_sd_exchange()

uint8_t board_sd_exchange ( uint8_t tx)

Exchange one full-duplex SPI byte with the modelled card.

Drives the SD SPI-mode state machine: command bytes are framed and answered with the matching R1/R3/R7 + data-token + block stream.

Parameters
[in]txByte clocked out by the host (host-out).
Returns
The byte the card drives back (card-out); 0xFF when idle.
Return values
255Bus idle / no response pending.
Precondition
A card is attached (board_sd_attached is true).
None.
Postcondition
The model's command / response state may advance.
Reads leave storage unchanged; accepted write/erase commands update it.
Note
Not thread-safe.
Since
0.1.0

Definition at line 708 of file board_periph_sd.c.

References g_board_sd, internal_board_sd_process_cmd(), internal_board_sd_read_stream_next(), internal_board_sd_write_byte(), k_sd_cmd_len, k_sd_cmd_mask, k_sd_cmd_start, k_sd_idle, and k_sd_wr_idle.

Referenced by internal_sci_reg_write(), and internal_spi_spdr_write().

◆ board_sd_read_block()

bool board_sd_read_block ( uint32_t lba,
uint8_t * dst )

Copy one 512-byte block straight out of the backing image.

The byte-identical data CMD17 would stream back, served in a single call so ra8_emulator's --fast-sd block-read hook can fill the firmware's sector buffer without clocking 512 individual SPI byte-exchanges through MMIO. Uses the same SDHC block-addressing (lba * 512) as the modelled CMD17 path, so the bytes delivered are exactly those the full protocol would produce.

Parameters
[in]lbaLogical block address (SDHC block units).
[out]dstDestination for 512 bytes; must hold at least 512 bytes.
Returns
true if a card is attached, lba is in range, and the exact read succeeds.
Return values
falseNo card is attached, the block is out of range, or backend I/O failed.
Precondition
dst is non-null and sized for >= 512 bytes.
A card image is attached (board_sd_attached is true).
Postcondition
On true, dst holds the block; the backing image is unmodified.
On false, dst is left unchanged.
Note
Not thread-safe.
Since
0.1.0

Definition at line 741 of file board_periph_sd.c.

References g_board_sd, internal_board_sd_fill_block(), k_sd_block, and memcpy().

Referenced by internal_on_sdmmc_read_block(), and internal_sdhi_load_block().

◆ board_sd_reset()

void board_sd_reset ( void )

Reset the card's command / response framing to power-on.

Clears the in-flight command collector and pending response; the attached image and learned ready state are preserved.

Returns
None.
Precondition
None.
None.
Postcondition
Framing state is cleared; any attached image stays attached.
No host I/O is performed.
Note
Not thread-safe.
Since
0.1.0

Definition at line 775 of file board_periph_sd.c.

References g_board_sd, and k_sd_wr_idle.

Referenced by internal_spi_reset().

◆ board_sd_write_block()

bool board_sd_write_block ( uint32_t lba,
const uint8_t * src )

Copy one 512-byte block straight into the backing image.

The write-side mirror of board_sd_read_block: stores the byte-identical data a CMD24 single-block write would land, served in a single call so the native-SDHI block model can commit the firmware's sector buffer without clocking 128 individual SD_BUF0 FIFO words. Uses the same SDHC block-addressing (lba * 512) as the modelled CMD24 path, so the bytes stored are exactly those the full protocol would write.

Parameters
[in]lbaLogical block address (SDHC block units).
[in]srcSource of 512 bytes; must hold at least 512 bytes.
Returns
true if a card is attached, a full block fits, and the exact write succeeds.
Return values
falseNo card is attached, the block is out of range, or backend I/O failed.
Precondition
src is non-null and sized for >= 512 bytes.
A card image is attached (board_sd_attached is true).
Postcondition
On true, the block at lba holds src.
On validation failure the backing image is unchanged.
On host-I/O failure the return value is false; a short positioned write may have made the progress reported internally by the raw-I/O seam.
Note
Not thread-safe.
Since
0.1.0

Definition at line 759 of file board_periph_sd.c.

References g_board_sd, k_sd_block, and priv_board_sd_storage_write().

Referenced by internal_sdhi_buf_write().

◆ internal_board_sd_begin_read()

void internal_board_sd_begin_read ( board_sd_state_t * c,
uint8_t idx,
uint32_t arg )
static

Accept a CMD17/CMD18 block-read command and stage the first block.

Stages the R1 + data-token + payload + CRC16 reply for the block at arg (SDHC addresses by block). A CMD18 additionally opens the multi-block read stream: board_sd_exchange keeps staging successive blocks (token + payload + CRC, no R1) until CMD12 STOP_TRANSMISSION closes it.

Parameters
[in,out]cCard state.
[in]idxCommand index (CMD17 single or CMD18 multi).
[in]argBlock address argument.
Returns
None.
Precondition
c is non-null and a card image is attached.
idx is k_sd_idx_cmd17 or k_sd_idx_cmd18.
Postcondition
c->resp holds the first block reply; c->rd_off points past it.
c->rd_multi is true iff the command was CMD18.
Note
Not thread-safe.
Since
0.1.0

Definition at line 208 of file board_periph_sd.c.

References internal_board_sd_fill_block(), internal_board_sd_stage_block(), k_sd_block, k_sd_idx_cmd18, k_sd_r1_param_err, board_sd_state_t::rd_multi, board_sd_state_t::rd_off, board_sd_state_t::resp, and board_sd_state_t::resp_len.

Referenced by internal_board_sd_dispatch_data().

◆ internal_board_sd_begin_write()

void internal_board_sd_begin_write ( board_sd_state_t * c,
uint8_t idx,
uint32_t arg,
uint8_t r1 )
static

Accept a CMD24/CMD25 block-write command and arm the data phase.

Replies R1 (ready) and enters k_sd_wr_token, where board_sd_exchange collects the host's data token + 512 payload bytes + CRC into the backing image (the read side, CMD17, then serves them back). SDHC addresses by block, so the argument is scaled to a byte offset.

Parameters
[in,out]cCard state.
[in]idxCommand index (CMD24 single or CMD25 multi).
[in]argBlock address argument.
[in]r1R1 status byte to return (ready/idle).
Returns
None.
Precondition
c is non-null and a writable image is attached.
idx is k_sd_idx_cmd24 or k_sd_idx_cmd25.
Postcondition
c->resp holds R1; the write sub-state is armed.
The backing image is unchanged until the data phase runs.
Note
Not thread-safe.
Since
0.1.0

Definition at line 304 of file board_periph_sd.c.

References board_console_push(), k_board_console_ch_sd, k_sd_block, k_sd_console_line_cap, k_sd_idx_cmd25, k_sd_wr_token, board_sd_state_t::resp, board_sd_state_t::resp_len, board_sd_state_t::wr_cnt, board_sd_state_t::wr_multi, board_sd_state_t::wr_off, and board_sd_state_t::wr_phase.

Referenced by internal_board_sd_dispatch_data().

◆ internal_board_sd_cmd_erase()

void internal_board_sd_cmd_erase ( board_sd_state_t * c,
uint8_t r1 )
static

Zero the latched [start, end] block range – CMD38 (ERASE).

Models a zero-erase card: the range latched by CMD32/CMD33 is cleared in the backing image. An inverted range (end < start) erases nothing, and the span is clamped to the image length so a range past the end of a short image is truncated rather than writing out of bounds.

Parameters
[in,out]cCard state holding the latched erase bounds and the image.
[in]r1R1 status byte to answer with.
Precondition
c is non-null with a backing image attached.
c->erase_start / c->erase_end were latched by CMD32 / CMD33.
Postcondition
Blocks in the clamped range read back as zero.
c->resp holds a one-byte R1 reply.
Note
Not thread-safe.
Since
0.1.0

Definition at line 599 of file board_periph_sd.c.

References board_sd_state_t::erase_end, board_sd_state_t::erase_start, board_sd_state_t::image_len, k_sd_block, k_sd_r1_param_err, priv_board_sd_storage_zero(), RA8_INTERNAL, board_sd_state_t::resp, and board_sd_state_t::resp_len.

Referenced by internal_board_sd_dispatch_data().

◆ internal_board_sd_cmd_erase_bound()

void internal_board_sd_cmd_erase_bound ( board_sd_state_t * c,
uint32_t * bound,
uint32_t arg,
uint8_t r1 )
static

Record one bound of the CMD32/CMD33 erase range and acknowledge it.

CMD32 (ERASE_WR_BLK_START) and CMD33 (ERASE_WR_BLK_END) differ only in which bound they latch, so both land here with bound aimed at the field to set. Neither touches the backing image – the erase itself happens on CMD38.

Parameters
[in,out]cCard state whose response buffer is staged.
[out]boundc->erase_start or c->erase_end, the bound to latch.
[in]argCommand argument: an SDHC block number.
[in]r1R1 status byte to answer with.
Precondition
c and bound are non-null.
bound points into c (the caller picks the field).
Postcondition
*bound holds arg.
c->resp holds a one-byte R1 reply.
Note
Not thread-safe.
Since
0.1.0

Definition at line 574 of file board_periph_sd.c.

References board_sd_state_t::resp, and board_sd_state_t::resp_len.

Referenced by internal_board_sd_dispatch_data().

◆ internal_board_sd_cmd_send_csd()

void internal_board_sd_cmd_send_csd ( board_sd_state_t * c)
static

Stage the 16-byte CSD v2.0 data block for a CMD9 (SEND_CSD) reply.

Builds a CSD version 2.0 register whose capacity field (C_SIZE, the 22-bit value in bytes 7..9) is derived from the attached image so --sd / --sd-new present their real size to the firmware instead of a fixed 8 MiB. CSD v2.0 capacity is (C_SIZE + 1) * 512 KiB; a card smaller than one 512 KiB unit falls back to the fixed k_sd_csd_csize. Hands the block to internal_board_sd_stage_block() for streaming. Extracted verbatim from the CMD9 arm of internal_board_sd_process_cmd().

Parameters
[in,out]cCard state whose response buffer receives the CSD block.
Returns
None.
Precondition
c is non-null with a staging response buffer.
c->image_len reflects the attached card size.
Postcondition
c->resp / c->resp_len hold the staged 16-byte CSD block.
The backing image is not modified.
Note
Not thread-safe.
Since
0.1.0

Definition at line 476 of file board_periph_sd.c.

References board_sd_state_t::image_len, internal_board_sd_stage_block(), k_sd_arg_sh1, k_sd_byte_bits, k_sd_byte_mask, k_sd_csd_csize, k_sd_csd_csize_b7, k_sd_csd_csize_b8, k_sd_csd_len, k_sd_csd_off, k_sd_csd_unit, k_sd_csd_v2, k_sd_csize_b7_mask, memset(), and RA8_INTERNAL.

Referenced by internal_board_sd_dispatch_data().

◆ internal_board_sd_crc16()

uint16_t internal_board_sd_crc16 ( const uint8_t * data,
uint32_t len )
static

CRC16-CCITT (poly 0x1021, init 0) over a buffer.

Matches the firmware driver's ra8_sdmmc_spi_crc16 so the card's data-block CRCs validate.

Parameters
[in]dataBytes to checksum.
[in]lenNumber of bytes.
Returns
The 16-bit CRC.
Return values
0Empty input.
Precondition
data is non-null when len > 0.
None.
Postcondition
No state is modified (pure).
No state is modified (pure).
Note
Pure function.
Since
0.1.0

Definition at line 100 of file board_periph_sd.c.

References k_sd_byte_bits, k_sd_crc_msb, k_sd_crc_poly, and RA8_INTERNAL.

Referenced by internal_board_sd_stage_block().

◆ internal_board_sd_dispatch_data()

void internal_board_sd_dispatch_data ( board_sd_state_t * c,
uint8_t idx,
uint32_t arg,
uint8_t r1 )
static

Handle the data-transfer and erase commands (CMD9/17/18/12/24/25/32/33/38).

Dispatches the block read/write, stop, and erase commands, plus the CMD9 CSD reply (via internal_board_sd_cmd_send_csd()). Any unrecognised index falls to the default R1 reply. Extracted verbatim from the corresponding arms of internal_board_sd_process_cmd(); called only after internal_board_sd_dispatch_ident() declines the frame.

Parameters
[in,out]cCard state whose response / stream is updated.
[in]idx6-bit command index already masked from the frame.
[in]arg32-bit big-endian argument decoded from the frame.
[in]r1Pre-computed R1 status byte (idle vs ready).
Returns
None.
Precondition
c is non-null with a staging response buffer.
internal_board_sd_dispatch_ident() already declined idx.
Postcondition
c->resp / c->resp_len (and any read/write stream state) describe the reply.
The backing image is modified only for the erase (CMD38) command.
Note
Not thread-safe.
Since
0.1.0

Definition at line 638 of file board_periph_sd.c.

References board_sd_state_t::erase_end, board_sd_state_t::erase_start, internal_board_sd_begin_read(), internal_board_sd_begin_write(), internal_board_sd_cmd_erase(), internal_board_sd_cmd_erase_bound(), internal_board_sd_cmd_send_csd(), internal_board_sd_stop_read(), k_sd_idx_cmd12, k_sd_idx_cmd17, k_sd_idx_cmd18, k_sd_idx_cmd24, k_sd_idx_cmd25, k_sd_idx_cmd32, k_sd_idx_cmd33, k_sd_idx_cmd38, k_sd_idx_cmd9, board_sd_state_t::resp, and board_sd_state_t::resp_len.

Referenced by internal_board_sd_process_cmd().

◆ internal_board_sd_dispatch_ident()

bool internal_board_sd_dispatch_ident ( board_sd_state_t * c,
uint8_t idx,
uint8_t r1 )
static

Handle the identification / configuration commands (CMD0/8/55/58/16).

Builds the fixed R1/R3/R7 responses for the card-identification and block-len commands. Returns whether idx was one of these so the caller can fall through to the data-transfer dispatch otherwise. Extracted verbatim from the corresponding arms of internal_board_sd_process_cmd().

Parameters
[in,out]cCard state whose response buffer is populated.
[in]idx6-bit command index already masked from the frame.
[in]r1Pre-computed R1 status byte (idle vs ready).
Returns
Whether the command was recognised and handled here.
Return values
trueidx was an identification/config command; c->resp is set.
falseidx is not handled here; caller must dispatch elsewhere.
Precondition
c is non-null with a staging response buffer.
idx is the masked command index of a complete frame.
Postcondition
On true, c->resp / c->resp_len describe the reply.
On false, c->resp / c->resp_len are left unchanged.
Note
Not thread-safe.
Since
0.1.0

Definition at line 516 of file board_periph_sd.c.

References board_sd_state_t::app_cmd, k_sd_cmd8_echo, k_sd_idle, k_sd_idx_cmd0, k_sd_idx_cmd16, k_sd_idx_cmd55, k_sd_idx_cmd58, k_sd_idx_cmd8, k_sd_ocr_pwrccs, k_sd_ocr_volt, k_sd_r1_idle, k_sd_r1_ready, k_sd_r7_len, board_sd_state_t::resp, and board_sd_state_t::resp_len.

Referenced by internal_board_sd_process_cmd().

◆ internal_board_sd_fill_block()

bool internal_board_sd_fill_block ( const board_sd_state_t * c,
uint64_t off,
uint8_t * blk )
static

Copy one 512-byte block out of the backing image (zero past the end).

The shared payload fetch for CMD17, CMD18, and the CMD18 stream continuation: bytes beyond the image end read back as zero, matching the public board_sd_read_block accessor.

Parameters
[in]cCard state carrying the backing image.
[in]offByte offset of the block inside the image.
[out]blkDestination for exactly 512 bytes.
Returns
Whether the positioned backend read succeeded.
Return values
trueThe requested in-range bytes were read and the tail zero-filled.
falseThe sparse backend read failed.
Precondition
c and blk are non-null.
A backing image is attached (or every byte reads back zero).
Postcondition
blk holds the image bytes at off, zero-filled past the image end.
No card state is modified.
Note
Not thread-safe.
Since
0.1.0

Definition at line 137 of file board_periph_sd.c.

References board_sd_state_t::image_len, k_sd_block, memset(), and priv_board_sd_storage_read().

Referenced by board_sd_read_block(), internal_board_sd_begin_read(), and internal_board_sd_read_stream_next().

◆ internal_board_sd_process_cmd()

void internal_board_sd_process_cmd ( board_sd_state_t * c)
static

Build the response for a completed 6-byte command frame.

Parameters
[in,out]cCard state holding the collected command.
Returns
None.
Precondition
c is non-null and c->cmd holds a full frame.
A card image is attached.
Postcondition
c->resp / c->resp_len describe the reply; c->resp_pos reset.
The backing image is not modified.
Note
Not thread-safe.
Since
0.1.0

Build the response for a completed 6-byte command frame; this step is contained within the board periph SD model and uses bounded caller or module-owned storage.

Definition at line 684 of file board_periph_sd.c.

References board_sd_state_t::app_cmd, board_sd_state_t::cmd, internal_board_sd_dispatch_data(), internal_board_sd_dispatch_ident(), k_sd_arg_sh0, k_sd_arg_sh1, k_sd_byte_bits, k_sd_idx_acmd41, k_sd_idx_mask, k_sd_r1_idle, k_sd_r1_ready, RA8_INTERNAL, board_sd_state_t::ready, board_sd_state_t::resp, board_sd_state_t::resp_len, and board_sd_state_t::resp_pos.

Referenced by board_sd_exchange().

◆ internal_board_sd_read_stream_next()

void internal_board_sd_read_stream_next ( board_sd_state_t * c)
static

Stage the next block of an open CMD18 stream (token + payload + CRC).

Mid-stream blocks carry no R1 – the card just emits the next data-start token once the block is ready. Reuses internal_board_sd_stage_block for the framing and skips its leading R1 slot by starting the drain at the token. Advances the stream offset by one block.

Parameters
[in,out]cCard state with an open CMD18 stream.
Returns
None.
Precondition
c->rd_multi is true (a CMD18 stream is open).
A card image is attached (reads past its end yield zeros).
Postcondition
c->resp holds token + payload + CRC with c->resp_pos at the token.
c->rd_off advanced by one block.
Note
Not thread-safe.
Since
0.1.0

Definition at line 240 of file board_periph_sd.c.

References internal_board_sd_fill_block(), internal_board_sd_stage_block(), k_sd_block, k_sd_read_error, RA8_INTERNAL, board_sd_state_t::rd_multi, board_sd_state_t::rd_off, board_sd_state_t::resp, board_sd_state_t::resp_len, and board_sd_state_t::resp_pos.

Referenced by board_sd_exchange().

◆ internal_board_sd_stage_block()

void internal_board_sd_stage_block ( board_sd_state_t * c,
const uint8_t * payload,
uint32_t len )
static

Stage the R1 + data-token + payload + CRC16 reply for a block read.

Parameters
[in,out]cCard state.
[in]payloadSource bytes.
[in]lenPayload length (16 for CSD, 512 for a data block).
Returns
None.
Precondition
c and payload are non-null and len + 4 <= k_sd_resp_cap.
None.
Postcondition
c->resp holds R1, token, payload, and the two CRC bytes.
c->resp_len is set; c->resp_pos is left for the caller.
Note
Not thread-safe.
Since
0.1.0

Stage the r1 + data-token + payload + crc16 reply for a block read; this step is contained within the board periph SD model and uses bounded caller or module-owned storage.

Definition at line 164 of file board_periph_sd.c.

References board_console_push(), internal_board_sd_crc16(), k_board_console_ch_sd, k_sd_byte_bits, k_sd_byte_mask, k_sd_console_line_cap, k_sd_console_rd_every, k_sd_r1_ready, k_sd_tok_data, memcpy(), board_sd_state_t::resp, board_sd_state_t::resp_len, and s_sd_spi_block_reads.

Referenced by internal_board_sd_begin_read(), internal_board_sd_cmd_send_csd(), and internal_board_sd_read_stream_next().

◆ internal_board_sd_stop_read()

void internal_board_sd_stop_read ( board_sd_state_t * c,
uint8_t r1 )
static

Answer CMD12 STOP_TRANSMISSION and close any open CMD18 stream.

Stages the CMD12 reply the ra8_sdmmc_spi driver expects: one stuff byte (the undefined tail of the cut-off stream, which the driver discards before polling R1), the R1 status, one busy byte, then not-busy. Real cards hold CIPO low briefly after CMD12; a single busy byte models that.

Parameters
[in,out]cCard state.
[in]r1R1 status byte to return (ready/idle).
Returns
None.
Precondition
c is non-null.
c->resp_pos / c->resp_len were reset by the caller.
Postcondition
c->rd_multi is false (any open stream is closed).
c->resp holds stuff byte + R1 + busy + not-busy.
Note
Not thread-safe.
Since
0.1.0

Definition at line 273 of file board_periph_sd.c.

References k_sd_busy, k_sd_idle, RA8_INTERNAL, board_sd_state_t::rd_multi, board_sd_state_t::resp, and board_sd_state_t::resp_len.

Referenced by internal_board_sd_dispatch_data().

◆ internal_board_sd_write_byte()

uint8_t internal_board_sd_write_byte ( board_sd_state_t * c,
uint8_t tx )
static

Feed one host byte into an in-flight block write; return the CIPO byte.

Drives the SD SPI write handshake (SD PHY v9 7.3.3): skip idle bytes until the data-start token (0xFE single / 0xFC multi), capture 512 payload bytes into the backing image, swallow the 2 CRC bytes, then stage the data-response token (0x05 accepted) + one busy byte + done. A CMD25 multi-write advances to the next block and re-arms the token wait; the stop-tran token (0xFD) ends it. ra8_emulator has no real program delay, so a single busy byte suffices.

Parameters
[in,out]cCard state (must be mid-write).
[in]txByte clocked out by the host.
Returns
The byte the card presents on CIPO (always idle here; the staged data-response is drained by board_sd_exchange next).
Return values
0xFFBus idle while collecting the data phase.
Precondition
c->wr_phase != k_sd_wr_idle.
A writable backing image is attached.
Postcondition
A complete payload is committed to the sparse backend in one exact write.
On block completion the data-response token is staged in c->resp.
Note
Not thread-safe.
Since
0.1.0

Definition at line 443 of file board_periph_sd.c.

References internal_sd_write_crc(), internal_sd_write_data(), internal_sd_write_token(), k_sd_idle, k_sd_wr_data, k_sd_wr_token, RA8_INTERNAL, and board_sd_state_t::wr_phase.

Referenced by board_sd_exchange().

◆ internal_sd_write_crc()

void internal_sd_write_crc ( board_sd_state_t * c)
static

Swallow the two block-CRC bytes, then acknowledge the block.

The model does not verify the CRC (the firmware sends a valid one and no test injects a bad one). After both bytes it queues accept-busy-idle, and for a multi-block write re-arms the token phase at the next block offset.

Parameters
[in,out]cCard state.
Precondition
c is non-NULL and c->wr_phase is k_sd_wr_crc.
Postcondition
After the second CRC byte a three-byte response is queued.
A multi-block write returns to the token phase, a single one to idle.
Note
Not thread-safe; the emulator is single-threaded host-side.
Precondition
The call executes on the emulator's single owning thread.
Since
0.1.0

Definition at line 399 of file board_periph_sd.c.

References k_sd_block, k_sd_busy, k_sd_crc_len, k_sd_data_accept, k_sd_data_error, k_sd_idle, k_sd_wr_idle, k_sd_wr_token, priv_board_sd_storage_write(), RA8_INTERNAL, board_sd_state_t::resp, board_sd_state_t::resp_len, board_sd_state_t::resp_pos, board_sd_state_t::wr_block, board_sd_state_t::wr_cnt, board_sd_state_t::wr_multi, board_sd_state_t::wr_off, and board_sd_state_t::wr_phase.

Referenced by internal_board_sd_write_byte().

◆ internal_sd_write_data()

void internal_sd_write_data ( board_sd_state_t * c,
uint8_t tx )
static

Absorb one payload byte of a write block.

Parameters
[in,out]cCard state.
[in]txByte the host clocked out.
Precondition
c is non-NULL and c->wr_phase is k_sd_wr_data.
c->image_fd owns the writable sparse backend when attached.
Postcondition
Writes landing past the image end are dropped, never out of bounds.
The phase advances to CRC once a full block has been taken.
Note
Not thread-safe; the emulator is single-threaded host-side.

Absorb one payload byte of a write block; this step is contained within the board periph SD model and uses bounded caller or module-owned storage.

Since
0.1.0

Definition at line 369 of file board_periph_sd.c.

References k_sd_block, k_sd_wr_crc, RA8_INTERNAL, board_sd_state_t::wr_block, board_sd_state_t::wr_cnt, and board_sd_state_t::wr_phase.

Referenced by internal_board_sd_write_byte().

◆ internal_sd_write_token()

void internal_sd_write_token ( board_sd_state_t * c,
uint8_t tx )
static

Handle a byte while the model waits for a write data token.

A data token opens the payload phase; the stop-tran token ends a multi-block write and queues the busy-then-idle response the host polls. Anything else is ignored, matching a real card waiting for a token.

Parameters
[in,out]cCard state.
[in]txByte the host clocked out.
Precondition
c is non-NULL and c->wr_phase is k_sd_wr_token.
Postcondition
The phase advances to data, returns to idle, or stays put.
Any queued response is non-empty with resp_pos reset to 0.
Note
Not thread-safe; the emulator is single-threaded host-side.
Precondition
The call executes on the emulator's single owning thread.
Since
0.1.0

Definition at line 337 of file board_periph_sd.c.

References k_sd_busy, k_sd_idle, k_sd_tok_data, k_sd_tok_stop, k_sd_tok_wmulti, k_sd_wr_data, k_sd_wr_idle, RA8_INTERNAL, board_sd_state_t::resp, board_sd_state_t::resp_len, board_sd_state_t::resp_pos, board_sd_state_t::wr_cnt, board_sd_state_t::wr_multi, and board_sd_state_t::wr_phase.

Referenced by internal_board_sd_write_byte().

Variable Documentation

◆ g_board_sd

◆ s_sd_spi_block_reads

uint32_t s_sd_spi_block_reads
static

Count of SD-over-SPI data blocks staged for read this run.

Drives the console SD tab's read-tap rate limit so a book-sized multi-block read does not flood the ring (one line per N blocks).

Note
Not thread-safe; ra8_emulator is single-threaded.
Since
0.1.0

Definition at line 56 of file board_periph_sd.c.

Referenced by internal_board_sd_stage_block().