51static const char*
s_tag =
"SDSPI";
59typedef enum : uint32_t {
73typedef enum : uint8_t {
94typedef enum : uint8_t {
107typedef enum : uint8_t {
128typedef enum : uint8_t {
146typedef enum : uint16_t {
174 if (data ==
nullptr) {
177 for (uint32_t i = 0U; i < len; i++) {
178 uint8_t
byte = data[i];
186 byte = (uint8_t)(
byte << 1U);
195 if (data ==
nullptr) {
198 for (uint32_t i = 0U; i < len; i++) {
204 crc = (uint16_t)(crc << 1U);
220 const uint8_t tx_buf[1] = {tx};
221 uint8_t rx_buf[1] = {};
238 for (uint32_t i = 0U; i < n; i++) {
379 uint8_t bytes[4] = {};
384 for (uint32_t i = 0U; i < 4U; i++) {
423 for (uint32_t i = 0U; i < max_polls; i++) {
454 const uint32_t c_size =
467 ((uint32_t)csd[7] << 2U) |
469 const uint8_t c_size_mult =
470 (uint8_t)((((uint8_t)csd[9] & 0x03U) << 1U) |
472 const uint32_t mult = (uint32_t)1U << ((uint32_t)c_size_mult + 2U);
473 const uint32_t block_len = (uint32_t)1U << (uint32_t)read_bl_len;
475 const uint64_t bytes = (uint64_t)(c_size + 1U) * (uint64_t)mult * (uint64_t)block_len;
490 if (transport ==
nullptr) {
493 if ((transport->set_clock ==
nullptr) || (transport->cs ==
nullptr) ||
494 (transport->xfer ==
nullptr)) {
695 uint8_t crc_bytes[2] = {};
700 if (*out_blocks == 0U) {
785 uint32_t blocks = 0U;
static const char * s_tag
Logging / check tag.
#define RA8_PRIV
Module-private helper: shared across TUs but only inside one library.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_RETURN_ON_ERROR(err, tag, message)
Early return on error, propagating the code upward.
Error Code Definitions for ra8-firmware.
@ k_ra8_err_hw_init_failed
Hardware peripheral failed to initialise.
@ k_ra8_err_invalid_arg
Invalid function argument.
@ k_ra8_err_hw_timeout
Hardware timed out waiting for a flag or handshake.
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
@ k_ra8_err_null_ptr
Pointer was NULL where a valid pointer was required.
@ k_ra8_err_protocol_error
Protocol-level error (e.g.
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
PSEL codes for peripheral pin routing on the RA8D2.
Lightweight Logging Interface for ra8-firmware.
High-level GPIO helpers on top of the PORT + PFS register layer.
SCI Simple-SPI controller-mode driver (polling, full-duplex).
sd_csd_field_t
SD CSD register field masks, shifts and block size.
@ k_sd_read_bl_mask
READ_BL_LEN (4-bit).
static ra8_err_t internal_read_csd(uint32_t *out_blocks)
sd_crc16_const_t
CRC16-CCITT polynomial and mask constants (SD spec PHY v9 section 4.5).
@ k_sd_crc16_poly
CRC16-CCITT polynomial.
@ k_sd_crc16_msb_test
Top bit of the 16-bit working CRC.
static ra8_err_t internal_read_r3_or_r7_tail(uint32_t *out_word)
sd_r1_bit_t
R1 response bit definitions (SD spec PHY v9 section 7.3.2.1).
@ k_sd_r1_parameter_error
SD r1 parameter error.
@ k_sd_r1_address_error
SD r1 address error.
@ k_sd_r1_sentinel
SD r1 sentinel.
@ k_sd_r1_com_crc_error
SD r1 com CRC error.
@ k_sd_r1_illegal_command
SD r1 illegal command.
@ k_sd_r1_erase_sequence_error
SD r1 erase sequence error.
@ k_sd_r1_erase_reset
SD r1 erase reset.
@ k_sd_r1_idle_state
SD r1 idle state.
ra8_err_t priv_sdmmc_spi_xfer_one(uint8_t tx, uint8_t *rx)
Shift out one byte and capture the response over the transport.
static ra8_err_t internal_read_ocr(bool *out_is_hc)
ra8_err_t priv_sdmmc_spi_send_acmd(sd_cmd_t acmd, uint32_t arg, uint8_t *out_r1)
Send an ACMD by prefixing it with CMD55 (APP_CMD).
static void internal_build_frame(sd_cmd_t cmd, uint32_t arg, uint8_t *out_frame)
static ra8_err_t internal_wake_card(void)
static ra8_err_t internal_send_cmd0(void)
sd_state_t g_sdmmc_spi_state
Single driver instance (the module's one external definition).
uint8_t ra8_sdmmc_spi_crc7(const uint8_t *data, uint32_t len)
Compute the SD-spec CRC7 over an arbitrary byte run.
sd_csd_layout_t
Selected CSD-byte indices and bit shifts (SD spec PHY v9 section 5).
@ k_sd_csd_v2_byte_csize_msb
SD csd v2 byte csize msb.
@ k_sd_csd_v2_byte_csize_mid
SD csd v2 byte csize mid.
@ k_sd_csd_byte_version
SD csd byte version.
@ k_sd_csd_v2_byte_csize_lsb
SD csd v2 byte csize lsb.
@ k_sd_csd_version_shift
SD csd version shift.
@ k_sd_csd_v2_blocks_shift
SD csd v2 blocks shift.
static ra8_err_t internal_probe_card(bool *out_is_v2, bool *out_is_hc)
ra8_err_t priv_sdmmc_spi_wait_not_busy(void)
Wait for the card to release the busy token (CIPO returns to 0xFF).
static ra8_err_t internal_read_r1(uint8_t *out_r1)
ra8_err_t priv_sdmmc_spi_cs_release(void)
Drive CS high after clocking one idle byte (SD spec section 7.2.4).
ra8_err_t priv_sdmmc_spi_send_idle(uint32_t n)
Shift n idle bytes (0xFF) and discard the response.
static ra8_err_t internal_set_block_len(void)
ra8_err_t priv_sdmmc_spi_send_command(sd_cmd_t cmd, uint32_t arg, uint8_t *out_r1)
Send a command frame and capture the R1 response byte.
ra8_err_t priv_sdmmc_spi_run_init_sequence(void)
Walk the full SD identification sequence and learn capacity / type.
ra8_err_t priv_sdmmc_spi_send_stop_transmission(uint8_t *out_r1)
Send CMD12 (STOP_TRANSMISSION) and capture its R1 response byte.
sd_crc7_const_t
CRC7 polynomial and mask constants (SD spec PHY v9 section 4.5).
@ k_sd_crc7_msb_test
Top bit of the 7-bit working CRC.
@ k_sd_crc7_register_mask
Mask the 7-bit working register.
@ k_sd_crc7_byte_msb
Top bit of an input byte.
@ k_sd_crc7_poly_low7
G(x) low 7 bits: 0b0001001.
static ra8_sdmmc_spi_card_type_t internal_classify_card(bool is_v2, bool is_hc)
ra8_err_t priv_sdmmc_spi_wait_not_busy_bounded(uint32_t max_polls)
Wait for the card to release busy (CIPO -> 0xFF), bounded by max_polls.
static ra8_err_t internal_acmd41_loop(bool is_v2)
@ k_sd_csize_msb_mask
CSD v2 C_SIZE MSB field (6-bit).
@ k_sd_cmd_frame_len
Command bytes preceding the CRC7.
@ k_sd_mult_lo_mask
C_SIZE_MULT low bit (byte 10).
@ k_sd_csize_lo_mask
CSD v1 C_SIZE low 2 bits (byte 8).
@ k_sd_mult_shift
C_SIZE_MULT low-bit shift.
@ k_sd_csize_shift
CSD v1 C_SIZE high-bits shift.
ra8_err_t priv_sdmmc_spi_validate_transport(const ra8_sdmmc_spi_transport_t *transport)
Validate the transport descriptor: every callback non-NULL.
ra8_err_t priv_sdmmc_spi_cs_assert(void)
Drive CS low and clock a single idle byte so CIPO is sampled.
static uint32_t internal_csd_to_blocks(const uint8_t *csd)
uint16_t ra8_sdmmc_spi_crc16(const uint8_t *data, uint32_t len)
Compute the SD-spec CRC16-CCITT over an arbitrary byte run.
sd_cmd_arg_idx_t
Byte indices inside a 6-byte SD command frame.
@ k_sd_frame_idx_crc
SD frame index CRC.
@ k_sd_frame_idx_arg_byte2
SD frame index arg byte2.
@ k_sd_frame_idx_arg_byte1
SD frame index arg byte1.
@ k_sd_frame_idx_arg_msb
SD frame index arg msb.
@ k_sd_frame_idx_arg_lsb
SD frame index arg lsb.
@ k_sd_frame_idx_cmd
SD frame index cmd.
static void internal_recover_stuck_card(void)
Best-effort recovery for a card stranded mid-write by an interrupted transaction (e....
ra8_err_t priv_sdmmc_spi_wait_data_token(void)
Poll for the data-start token (0xFE), bounded by a retry budget.
static ra8_err_t internal_send_cmd8(bool *out_is_v2)
SD card driver in SPI-mode (PMOD-attached cards).
@ k_ra8_sdmmc_spi_block_size
512-byte block (SD spec PHY v9 section 7.2.2).
@ k_ra8_sdmmc_spi_csd_response_len
CMD9 CSD register payload bytes.
@ k_ra8_sdmmc_spi_cmd_frame_bytes
1 cmd-byte + 4 arg-bytes + 1 CRC-byte.
ra8_sdmmc_spi_card_type_t
Detected SD card capacity / addressing class.
@ k_ra8_sdmmc_spi_type_sdhc
SDHC / SDXC v2.x (block-addressed).
@ k_ra8_sdmmc_spi_type_sdv2
SD v2.x SC (byte-addressed).
@ k_ra8_sdmmc_spi_type_sdv1
SD v1.x (byte-addressed).
Contracts for file-local SD protocol helpers.
Module-private cross-TU surface for the SPI-mode SD card driver.
@ k_sd_token_stop_multi
Multi-block stop.
@ k_sd_token_data_start_single
Single-block start.
@ k_sd_token_idle
Idle bus.
@ k_sd_max_busy_poll_bytes
Worst-case write timeout.
@ k_sd_crc7_cmd0_byte
SD crc7 cmd0 byte.
@ k_sd_max_recover_attempts
Re-flush + retry CMD0 before failing.
@ k_sd_cmd8_arg_check_pattern
SD cmd8 arg check pattern.
@ k_sd_ocr_ccs_bit
SD ocr ccs bit.
@ k_sd_max_r1_wait_bytes
R1 must appear within 8 bytes per spec; 2x slack.
@ k_sd_recover_idle_bytes
512 CS-released clocks drain busy + reset framing.
@ k_sd_max_data_token_polls
~500 ms at 100 us / poll.
@ k_sd_crc7_cmd8_byte
SD crc7 cmd8 byte.
@ k_sd_max_acmd41_attempts
1 s at 1 ms / attempt.
@ k_sd_init_dummy_clocks
80 clocks = 10 bytes of 0xFF (>=74 required).
@ k_sd_acmd41_arg_hcs
SD acmd41 arg hcs.
@ k_sd_recover_flush_bytes
>= 512 data + 2 CRC + token to flush a stuck write.
@ k_sd_mask_byte
Low 8 bits of a wider value.
@ k_sd_mask_12bit
CMD8 R7 echo voltage-range + check pattern.
sd_cmd_t
Wire-byte for every command used by this driver.
@ k_sd_cmd_set_blocklen
CMD16.
@ k_sd_acmd_sd_send_op_cond
ACMD41.
@ k_sd_cmd_stop_transmission
CMD12.
@ k_sd_cmd_send_if_cond
CMD8.
@ k_sd_cmd_read_ocr
CMD58.
@ k_sd_cmd_go_idle_state
CMD0.
@ k_sd_bit_three_byte
SD bit three byte.
@ k_sd_bit_byte
SD bit byte.
@ k_sd_bit_two_byte
SD bit two byte.
SPI_B controller driver (RA8D2 Type-B SPI peripheral).
Driver-to-bus binding (Dependency Inversion seam).
Cached protocol state held across the driver public API.