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

SD/MMC Host Interface (SDHI) driver scaffold. More...

#include <stdint.h>
#include "ra8_err.h"
Include dependency graph for ra8_sdhi.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef void(* ra8_sdhi_event_fn_t) (void *ctx, uint8_t instance, uint32_t status_mask)
 SDHI event callback.

Enumerations

enum  ra8_sdhi_bus_width_t : uint8_t {
  k_ra8_sdhi_bus_width_unset = 0U ,
  k_ra8_sdhi_bus_width_1bit = 1U ,
  k_ra8_sdhi_bus_width_4bit = 4U ,
  k_ra8_sdhi_bus_width_8bit = 8U
}
 SD data-bus width accepted by ra8_sdhi_set_bus_width. More...

Functions

ra8_err_t ra8_sdhi_init (uint8_t instance)
 Initialise an SDHI instance.
ra8_err_t ra8_sdhi_send_command (uint8_t instance, uint32_t cmd, uint32_t arg, uint32_t *out_rsp)
 Issue a single SD command and read the 4-word response.
ra8_err_t ra8_sdhi_set_clock (uint8_t instance, uint32_t divider)
 Set the SD bus clock divider (SD_CLK_CTRL).
ra8_err_t ra8_sdhi_set_bus_width (uint8_t instance, ra8_sdhi_bus_width_t width)
 Program the host-side SD data-bus width (SD_OPTION.WIDTH / WIDTH8).
ra8_err_t ra8_sdhi_set_bus_width_4bit (uint8_t instance, uint16_t rca)
 Negotiate a 4-bit data bus with the card via CMD55 + ACMD6.
ra8_err_t ra8_sdhi_set_bus_width_8bit (uint8_t instance)
 Negotiate an 8-bit data bus with an eMMC device via CMD6 SWITCH.
ra8_err_t ra8_sdhi_deinit (uint8_t instance)
 Tear down an SDHI instance.
ra8_err_t ra8_sdhi_get_status (uint8_t instance, uint32_t *out_mask)
 Read the SD_INFO1 status register.
ra8_err_t ra8_sdhi_clear_status (uint8_t instance, uint32_t mask)
 Clear SD_INFO1 status bits via write-0-to-clear.
ra8_err_t ra8_sdhi_attach_handler (ra8_sdhi_event_fn_t fn, void *ctx)
 Attach an SDHI event callback (shared across instances).
void ra8_sdhi_dispatch (uint8_t instance)
 Dispatch an SDHI event – snapshot status + fire callback.
ra8_err_t ra8_sdhi_enter_stop (uint8_t instance)
 Put an SDHI instance into MSTP-gated stop.
ra8_err_t ra8_sdhi_exit_stop (uint8_t instance)
 Exit MSTP-gated stop.
ra8_err_t ra8_sdhi_read_block (uint8_t instance, uint32_t lba, uint8_t *buf, uint32_t block_count)
 Read one or more 512-byte SD blocks via the SD_BUF0 FIFO.
ra8_err_t ra8_sdhi_write_block (uint8_t instance, uint32_t lba, const uint8_t *buf, uint32_t block_count)
 Write one or more 512-byte SD blocks via the SD_BUF0 FIFO.
ra8_err_t ra8_sdhi_attach_dma (uint8_t instance, uint8_t enable)
 Enable or disable DMAC-driven SDHI transfers.

Detailed Description

SD/MMC Host Interface (SDHI) driver scaffold.

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

introduces a minimal SDHI driver scaffold covering the lifecycle + status + IRQ + power-transition surface, the polled command + block-transfer engine, and bus-width negotiation. The default bus width is the conservative 1-bit mode; callers widen an SD card to 4-bit only after it acknowledges ACMD6 (SET_BUS_WIDTH), or an eMMC device to 8-bit after it acknowledges CMD6 (SWITCH).

API surface:

Definition in file ra8_sdhi.h.

Typedef Documentation

◆ ra8_sdhi_event_fn_t

typedef void(* ra8_sdhi_event_fn_t) (void *ctx, uint8_t instance, uint32_t status_mask)

SDHI event callback.

Definition at line 48 of file ra8_sdhi.h.

Enumeration Type Documentation

◆ ra8_sdhi_bus_width_t

enum ra8_sdhi_bus_width_t : uint8_t

SD data-bus width accepted by ra8_sdhi_set_bus_width.

The numeric values equal the physical lane count so callers read as intent. They map onto the SD_OPTION.WIDTH / WIDTH8 bit pair via the HUM Ch 47.2.16 truth table (1-bit: WIDTH=1,WIDTH8=0; 4-bit: WIDTH=0,WIDTH8=0; 8-bit: WIDTH=0,WIDTH8=1).

Invariant
Only these three values are valid; any other is rejected with k_ra8_err_invalid_arg.
See also
ra8_sdhi_set_bus_width()
ra8_sdhi_set_bus_width_4bit()
Enumerator
k_ra8_sdhi_bus_width_unset 

Unset: leave the bus at its power-on width.

k_ra8_sdhi_bus_width_1bit 

Single data lane (power-on safe default).

k_ra8_sdhi_bus_width_4bit 

Four data lanes (SD default-speed wide).

k_ra8_sdhi_bus_width_8bit 

Eight data lanes (eMMC only).

Definition at line 66 of file ra8_sdhi.h.

Function Documentation

◆ ra8_sdhi_attach_dma()

ra8_err_t ra8_sdhi_attach_dma ( uint8_t instance,
uint8_t enable )
nodiscard

Enable or disable DMAC-driven SDHI transfers.

Toggles SD_DMAEN.DMAEN and the SD_INFO2_MASK BREM/BWEM bits in lock-step the way FSP r_sdhi_transfer_read / r_sdhi_transfer_write do. With DMA enabled the polled BRE / BWE wait in the read/write helpers above must be replaced by an external transfer primitive that targets SD_BUF0; this function is the toggle point.

Parameters
[in]instanceSDHI instance.
[in]enableNon-zero to enable DMA, 0 to fall back to PIO.
Return values
k_ra8_okSuccess.
k_ra8_err_null_ptrinstance invalid.
Precondition
ra8_sdhi_init has been called for instance.
Postcondition
SD_DMAEN reflects enable.
Note
The DMAC channel itself must be wired up by the caller via ra8_dmac before any transfer is started.
Since
0.1.0

Definition at line 726 of file ra8_sdhi.c.

References k_ra8_ok, k_ra8_sdhi_dmaen_set, k_ra8_sdhi_info2_brem_bwem, RA8_CHECK_NULL_PTR, ra8_sdhi(), s_tag, r_sdhi_regs_t::SD_DMAEN, and r_sdhi_regs_t::SD_INFO2_MASK.

◆ ra8_sdhi_attach_handler()

ra8_err_t ra8_sdhi_attach_handler ( ra8_sdhi_event_fn_t fn,
void * ctx )
nodiscard

Attach an SDHI event callback (shared across instances).

Since
0.1.0

Definition at line 357 of file ra8_sdhi.c.

References k_ra8_ok, s_sdhi_ctx, and s_sdhi_fn.

◆ ra8_sdhi_clear_status()

ra8_err_t ra8_sdhi_clear_status ( uint8_t instance,
uint32_t mask )
nodiscard

Clear SD_INFO1 status bits via write-0-to-clear.

Since
0.1.0

Definition at line 345 of file ra8_sdhi.c.

References k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_sdhi(), s_tag, and r_sdhi_regs_t::SD_INFO1.

◆ ra8_sdhi_deinit()

◆ ra8_sdhi_dispatch()

void ra8_sdhi_dispatch ( uint8_t instance)

Dispatch an SDHI event – snapshot status + fire callback.

Called from the SDHI access / DMA-end / SDIO ISR (HUM Ch 50 "SD/MMC Host Interface (SDHI)", p 2655) to snapshot SD_INFO1 / SD_INFO2 and invoke the registered handler. Spurious IRQs and out-of-range instance values are silently ignored.

Parameters
[in]instanceSDHI instance index (0 or 1).
Precondition
Called from ISR context or a host-test driver.
instance < 2.
Postcondition
Stored callback (if any) has been invoked exactly once.
Status latch is left for the caller to clear via ra8_sdhi_clear_status.
Note
Not thread-safe; pair with NVIC masking.
Since
0.1.0

Definition at line 365 of file ra8_sdhi.c.

References ra8_sdhi(), s_sdhi_ctx, s_sdhi_fn, and r_sdhi_regs_t::SD_INFO1.

◆ ra8_sdhi_enter_stop()

ra8_err_t ra8_sdhi_enter_stop ( uint8_t instance)
nodiscard

Put an SDHI instance into MSTP-gated stop.

Since
0.1.0

Definition at line 381 of file ra8_sdhi.c.

References k_ra8_err_invalid_arg, k_ra8_sdhi_instance_count, ra8_mstp_disable(), and s_sdhi_mstp_table.

◆ ra8_sdhi_exit_stop()

ra8_err_t ra8_sdhi_exit_stop ( uint8_t instance)
nodiscard

Exit MSTP-gated stop.

Since
0.1.0

Definition at line 389 of file ra8_sdhi.c.

References k_ra8_err_invalid_arg, k_ra8_sdhi_instance_count, ra8_mstp_enable(), and s_sdhi_mstp_table.

◆ ra8_sdhi_get_status()

ra8_err_t ra8_sdhi_get_status ( uint8_t instance,
uint32_t * out_mask )
nodiscard

Read the SD_INFO1 status register.

Since
0.1.0

Definition at line 335 of file ra8_sdhi.c.

References k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_sdhi(), s_tag, and r_sdhi_regs_t::SD_INFO1.

◆ ra8_sdhi_init()

◆ ra8_sdhi_read_block()

ra8_err_t ra8_sdhi_read_block ( uint8_t instance,
uint32_t lba,
uint8_t * buf,
uint32_t block_count )
nodiscard

Read one or more 512-byte SD blocks via the SD_BUF0 FIFO.

Polled (PIO-style) block-read primitive. Mirrors FSP R_SDHI_Read -> r_sdhi_read_write_common (file r_sdhi.c, lines 450..490 and 1383..1405) without the DMA/DTC machinery: the driver loads SD_SECCNT / SD_SIZE, kicks the READ_SINGLE_BLOCK (CMD17) or READ_MULTIPLE_BLOCK (CMD18) command, waits for SD_INFO1.RSPEND, then drains 512 bytes per block from SD_BUF0 in 4-byte words while polling SD_INFO2.BRE.

Algorithm:

  1. Validate buf non-NULL and block_count > 0
  2. Write SD_STOP = SECCNT_ENABLE (multi-block only)
  3. Write SD_SECCNT = block_count
  4. Write SD_SIZE = 512 (block size)
  5. Write SD_ARG = lba (sector address)
  6. Write SD_CMD = CMD17 (single) or CMD18 (multi)
  7. Poll SD_INFO1.RSPEND for command-response complete
  8. For each of block_count * 128 words: poll SD_INFO2.BRE, copy SD_BUF0 -> buf
  9. For multi-block: issue CMD12 STOP_TRANSMISSION
  10. Clear SD_INFO1 / SD_INFO2 flags
Parameters
[in]instanceSDHI instance (0 or 1).
[in]lbaLogical block address (sector number).
[out]bufDestination buffer; must hold at least block_count * 512 bytes.
[in]block_countNumber of 512-byte blocks to read; must be > 0.
Return values
k_ra8_okSuccess.
k_ra8_err_null_ptrbuf was NULL or instance invalid.
k_ra8_err_invalid_argblock_count was 0.
k_ra8_err_hw_timeoutRSPEND or BRE poll exceeded the spin budget.
Precondition
Card has been initialized through CMD0..ACMD41 + CMD2/3/7 by the consumer.
ra8_sdhi_init has been called for instance.
Postcondition
On success buf[0..block_count*512] holds card data.
SD_INFO1.RSPEND and SD_INFO2 BRE bits are cleared.
Note
Blocking, polled implementation; not safe to call from an ISR.
Since
0.1.0

Definition at line 677 of file ra8_sdhi.c.

References internal_sdhi_drain(), internal_sdhi_finish_xfer(), internal_sdhi_send(), internal_sdhi_setup_xfer(), k_ra8_err_invalid_arg, k_ra8_sdhi_cmd_read_multi_block, k_ra8_sdhi_cmd_read_single_block, k_ra8_sdhi_words_per_block, RA8_CHECK_NULL_PTR, RA8_RETURN_ON_ERROR, ra8_sdhi(), and s_tag.

Referenced by ra8_sdcard_read_blocks().

◆ ra8_sdhi_send_command()

ra8_err_t ra8_sdhi_send_command ( uint8_t instance,
uint32_t cmd,
uint32_t arg,
uint32_t * out_rsp )
nodiscard

Issue a single SD command and read the 4-word response.

polling primitive. Loads SD_ARG with arg, writes cmd to SD_CMD, polls SD_INFO1.RSPEND for completion, and copies SD_RSP10/32/54/76 into out_rsp[0..3]. The caller encodes the SD command index + response type in cmd.

Parameters
[in]instanceSDHI instance.
[in]cmdPre-encoded SD_CMD register value.
[in]arg32-bit command argument (zero-extended).
[out]out_rsp4-word response buffer; may be NULL if the command type returns no response.
Since
0.1.0

Definition at line 184 of file ra8_sdhi.c.

References k_ra8_err_hw_timeout, k_ra8_ok, k_ra8_sdhi_cmd_spin, k_ra8_sdhi_info1_rspend_mask, RA8_CHECK_NULL_PTR, ra8_sdhi(), s_tag, r_sdhi_regs_t::SD_ARG, r_sdhi_regs_t::SD_CMD, r_sdhi_regs_t::SD_INFO1, r_sdhi_regs_t::SD_RSP10, r_sdhi_regs_t::SD_RSP32, r_sdhi_regs_t::SD_RSP54, and r_sdhi_regs_t::SD_RSP76.

Referenced by internal_run_acmd41(), internal_sdcard_identify(), internal_sdcard_publish_and_select(), internal_sdcard_publish_rca(), ra8_sdhi_set_bus_width_4bit(), and ra8_sdhi_set_bus_width_8bit().

◆ ra8_sdhi_set_bus_width()

ra8_err_t ra8_sdhi_set_bus_width ( uint8_t instance,
ra8_sdhi_bus_width_t width )
nodiscard

Program the host-side SD data-bus width (SD_OPTION.WIDTH / WIDTH8).

Low-level, host-only setter: it flips the SD_OPTION.WIDTH (bit 15) and WIDTH8 (bit 13) bits per the HUM Ch 47.2.16 truth table while preserving the TOP / CTOP / TOUTMASK timeout fields with a read-modify-write. It does NOT touch the card – the card's own bus width must already match (negotiate it with ra8_sdhi_set_bus_width_4bit first), otherwise transfers corrupt.

Parameters
[in]instanceSDHI instance (0 or 1).
[in]widthDesired width: k_ra8_sdhi_bus_width_1bit, k_ra8_sdhi_bus_width_4bit, or k_ra8_sdhi_bus_width_8bit.
Returns
ra8_err_t error code.
Return values
k_ra8_okSD_OPTION updated to the requested width.
k_ra8_err_null_ptrinstance out of range.
k_ra8_err_invalid_argwidth not one of the three valid widths.
Precondition
ra8_sdhi_init has been called for instance.
The card has been moved to width on its side (or is in 1-bit).
Postcondition
On success SD_OPTION.WIDTH / WIDTH8 reflect width.
Timeout fields (TOP / CTOP / TOUTMASK) are unchanged.
Note
Not thread-safe; serialize with the rest of the SDHI command path.
Warning
Widening the host before the card corrupts every transfer.
See also
ra8_sdhi_set_bus_width_4bit() Negotiate the card side via ACMD6.
Since
0.1.0

Definition at line 239 of file ra8_sdhi.c.

References k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_sdhi_bus_width_1bit, k_ra8_sdhi_bus_width_4bit, k_ra8_sdhi_bus_width_8bit, k_ra8_sdhi_option_width8_bit, k_ra8_sdhi_option_width_bit, k_ra8_sdhi_option_width_mask, RA8_CHECK_NULL_PTR, ra8_sdhi(), s_tag, and r_sdhi_regs_t::SD_OPTION.

Referenced by ra8_sdhi_set_bus_width_4bit(), and ra8_sdhi_set_bus_width_8bit().

◆ ra8_sdhi_set_bus_width_4bit()

ra8_err_t ra8_sdhi_set_bus_width_4bit ( uint8_t instance,
uint16_t rca )
nodiscard

Negotiate a 4-bit data bus with the card via CMD55 + ACMD6.

Runs the SD application-command handshake that switches an SD card from its power-on 1-bit bus to 4-bit, then widens the host side to match. The sequence is:

  1. CMD55 APP_CMD (arg = rca << 16) – prefix the next command as an application command. The R1 response must echo APP_CMD.
  2. ACMD6 SET_BUS_WIDTH (arg = 0b10) – request 4-bit on the card. The R1 response must carry no error/violation bits.
  3. On a clean acknowledgement, call ra8_sdhi_set_bus_width with k_ra8_sdhi_bus_width_4bit so the host SD_OPTION follows.

If the card declines (missing APP_CMD echo or any R1 error bit) the host is left in 1-bit mode and k_ra8_err_not_supported is returned – the conservative default is preserved.

Parameters
[in]instanceSDHI instance (0 or 1).
[in]rcaCard relative address published by CMD3.
Returns
ra8_err_t error code.
Return values
k_ra8_okCard and host both switched to 4-bit.
k_ra8_err_null_ptrinstance out of range.
k_ra8_err_hw_timeoutCMD55 or ACMD6 RSPEND never asserted.
k_ra8_err_not_supportedCard declined ACMD6; host stays 1-bit.
Precondition
Card is in TRAN state (CMD7 selected) with a known rca.
ra8_sdhi_init has been called for instance.
Postcondition
On success the card and host are both 4-bit.
On failure the host bus width is unchanged (1-bit).
Note
Blocking, polled; not safe to call from an ISR.
See also
ra8_sdhi_set_bus_width() Host-only width setter this drives.
Since
0.1.0

Definition at line 269 of file ra8_sdhi.c.

References k_ra8_err_not_supported, k_ra8_sdhi_acmd6_arg_4bit, k_ra8_sdhi_bus_width_4bit, k_ra8_sdhi_cmd_app_cmd, k_ra8_sdhi_cmd_set_bus_width, k_ra8_sdhi_r1_app_cmd_mask, k_ra8_sdhi_r1_error_mask, k_ra8_sdhi_rca_arg_shift, RA8_CHECK_NULL_PTR, RA8_RETURN_ON_ERROR, ra8_sdhi(), ra8_sdhi_send_command(), ra8_sdhi_set_bus_width(), and s_tag.

Referenced by internal_sdcard_negotiate_width().

◆ ra8_sdhi_set_bus_width_8bit()

ra8_err_t ra8_sdhi_set_bus_width_8bit ( uint8_t instance)
nodiscard

Negotiate an 8-bit data bus with an eMMC device via CMD6 SWITCH.

The 8-bit data bus is an eMMC-only capability (SD cards top out at the 4-bit ACMD6 path). Unlike ACMD6 this uses the native JEDEC CMD6 SWITCH command – no CMD55 application prefix – to write the EXT_CSD BUS_WIDTH byte (index 183) with value 2 (8-bit SDR). The sequence is:

  1. CMD6 SWITCH (arg = k_ra8_sdhi_cmd6_arg_8bit) – request the EXT_CSD BUS_WIDTH write. The R1b response must carry no error or status-violation bits (k_ra8_sdhi_r1_error_mask).
  2. On a clean acknowledgement, call ra8_sdhi_set_bus_width with k_ra8_sdhi_bus_width_8bit so the host SD_OPTION follows.

If the device declines (any R1 error bit) the host is left at its current width and k_ra8_err_not_supported is returned – an SD card, which cannot do 8-bit, lands here and stays narrow.

Parameters
[in]instanceSDHI instance (0 or 1).
Returns
ra8_err_t error code.
Return values
k_ra8_okDevice and host both switched to 8-bit.
k_ra8_err_null_ptrinstance out of range.
k_ra8_err_hw_timeoutCMD6 RSPEND never asserted.
k_ra8_err_not_supportedDevice declined CMD6; host width unchanged.
Precondition
The device is an eMMC in TRAN state (CMD7 selected).
ra8_sdhi_init has been called for instance.
Postcondition
On success the device and host are both 8-bit.
On failure the host bus width is unchanged.
Note
Blocking, polled; not safe to call from an ISR.
See also
ra8_sdhi_set_bus_width_4bit() The SD ACMD6 4-bit counterpart.
ra8_sdhi_set_bus_width() Host-only width setter this drives.
Since
0.1.0

Definition at line 307 of file ra8_sdhi.c.

References k_ra8_err_not_supported, k_ra8_sdhi_bus_width_8bit, k_ra8_sdhi_cmd6_arg_8bit, k_ra8_sdhi_cmd_emmc_switch, k_ra8_sdhi_r1_error_mask, RA8_CHECK_NULL_PTR, RA8_RETURN_ON_ERROR, ra8_sdhi(), ra8_sdhi_send_command(), ra8_sdhi_set_bus_width(), and s_tag.

◆ ra8_sdhi_set_clock()

ra8_err_t ra8_sdhi_set_clock ( uint8_t instance,
uint32_t divider )
nodiscard

Set the SD bus clock divider (SD_CLK_CTRL).

Since
0.1.0

Definition at line 223 of file ra8_sdhi.c.

References k_ra8_ok, k_ra8_sdhi_clk_ctrl_clkctrlen_mask, k_ra8_sdhi_clk_ctrl_clken_mask, k_ra8_sdhi_clk_ctrl_setting_mask, RA8_CHECK_NULL_PTR, ra8_sdhi(), s_tag, and r_sdhi_regs_t::SD_CLK_CTRL.

Referenced by ra8_sdcard_init().

◆ ra8_sdhi_write_block()

ra8_err_t ra8_sdhi_write_block ( uint8_t instance,
uint32_t lba,
const uint8_t * buf,
uint32_t block_count )
nodiscard

Write one or more 512-byte SD blocks via the SD_BUF0 FIFO.

Polled (PIO-style) block-write primitive. Mirrors FSP R_SDHI_Write -> r_sdhi_read_write_common (file r_sdhi.c, lines 509..554 and 1383..1405) without the DMA/DTC machinery: the driver loads SD_SECCNT / SD_SIZE, kicks the WRITE_SINGLE_BLOCK (CMD24) or WRITE_MULTIPLE_BLOCK (CMD25) command, waits for SD_INFO1.RSPEND, then pushes 512 bytes per block into SD_BUF0 in 4-byte words while polling SD_INFO2.BWE.

Parameters
[in]instanceSDHI instance (0 or 1).
[in]lbaLogical block address (sector number).
[in]bufSource buffer; must hold at least block_count * 512 bytes.
[in]block_countNumber of 512-byte blocks to write; must be > 0.
Return values
k_ra8_okSuccess.
k_ra8_err_null_ptrbuf was NULL or instance invalid.
k_ra8_err_invalid_argblock_count was 0.
k_ra8_err_hw_timeoutRSPEND or BWE poll exceeded the spin budget.
Precondition
Card has been initialized through CMD0..ACMD41 + CMD2/3/7 by the consumer.
Card is not write-protected (caller responsibility).
Postcondition
On success the requested block range has been pushed into the SDHI FIFO.
For multi-block writes a CMD12 STOP_TRANSMISSION has been issued.
Note
Blocking, polled implementation; not safe to call from an ISR.
Since
0.1.0

Definition at line 702 of file ra8_sdhi.c.

References internal_sdhi_fill(), internal_sdhi_finish_xfer(), internal_sdhi_send(), internal_sdhi_setup_xfer(), k_ra8_err_invalid_arg, k_ra8_sdhi_cmd_write_multi_block, k_ra8_sdhi_cmd_write_single_block, k_ra8_sdhi_words_per_block, RA8_CHECK_NULL_PTR, RA8_RETURN_ON_ERROR, ra8_sdhi(), and s_tag.

Referenced by ra8_sdcard_write_blocks().