|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
SD card driver implementation – SD Physical Layer state machine. More...
#include "ra8_sdcard.h"#include <stdint.h>#include "ra8_attributes.h"#include "ra8_check.h"#include "ra8_err.h"#include "ra8_log.h"#include "ra8_sdhi.h"Go to the source code of this file.
Data Structures | |
| struct | ra8_sdcard_state_t |
| Internal per-driver state. More... | |
Functions | |
| static ra8_err_t | internal_run_acmd41 (uint8_t instance, uint32_t *out_ocr) |
| static ra8_err_t | internal_decode_csd (const uint32_t *rsp, uint32_t *out_blocks) |
| Decode a CSD response (v1 or v2) into a capacity-in-blocks count. | |
| static ra8_err_t | internal_sdcard_identify (uint8_t instance) |
| Drive CMD0 + CMD8 to take the card from power-on into idle. | |
| static ra8_err_t | internal_sdcard_publish_rca (uint8_t instance, uint16_t *out_rca) |
| Run CMD2 + CMD3 so the card publishes its relative address. | |
| static ra8_err_t | internal_sdcard_publish_and_select (uint8_t instance, uint16_t *out_rca, uint32_t *out_blocks) |
| Publish the RCA, decode the CSD, and put the card in TRAN. | |
| static ra8_sdcard_card_type_t | internal_classify (uint8_t high_capacity, uint32_t blocks) |
| Classify card type from OCR.CCS and decoded block count. | |
| static void | internal_sdcard_negotiate_width (uint8_t instance, ra8_sdhi_bus_width_t width, uint16_t rca) |
| Negotiate the requested SD data-bus width after card selection. | |
| static ra8_err_t | internal_sdcard_card_online (uint8_t instance, uint16_t *out_rca, uint32_t *out_blocks, uint8_t *out_high_capacity) |
| Take an identified SDHI card from power-on to TRAN state. | |
| ra8_err_t | ra8_sdcard_init (const ra8_sdcard_cfg_t *cfg) |
| Bring up the SDHI block and perform full SD card initialization. | |
| static uint32_t | internal_to_card_address (uint32_t lba) |
| Translate a logical block address into the SD on-card argument. | |
| ra8_err_t | ra8_sdcard_read_blocks (uint32_t lba, uint8_t *buf, uint32_t count) |
| Read count 512-byte blocks starting at lba. | |
| ra8_err_t | ra8_sdcard_write_blocks (uint32_t lba, const uint8_t *buf, uint32_t count) |
| Write count 512-byte blocks starting at lba. | |
| ra8_err_t | ra8_sdcard_get_capacity (uint32_t *out_blocks) |
| Return card capacity in 512-byte blocks. | |
| ra8_err_t | ra8_sdcard_get_type (ra8_sdcard_card_type_t *out_type) |
| Return the detected card type (SDSC / SDHC / SDXC). | |
| ra8_err_t | ra8_sdcard_deinit (void) |
| Tear down the card driver and release the SDHI block. | |
Variables | |
| static const char * | s_tag = "SDCARD" |
| Module log tag. | |
| static ra8_sdcard_state_t | s_sdcard |
| Module-private state. | |
SD card driver implementation – SD Physical Layer state machine.
Implements the SD Physical Layer initialization sequence on top of the lower-level ra8_sdhi register driver:
CMD0 -> CMD8 -> ACMD41 (loop) -> CMD2 -> CMD3 -> CMD9 -> CMD7
After the card is parked in TRAN state the bus clock is bumped from the 400 kHz identification rate to 25 MHz default-speed by way of ra8_sdhi_set_clock. Block I/O calls fall through to the polled ra8_sdhi_read_block / ra8_sdhi_write_block primitives.
The CSD register is decoded for both v1 (SDSC byte-addressed) and v2 (SDHC/SDXC block-addressed) layouts. Capacity is normalized to 512-byte blocks regardless of card class so callers always speak in sector counts.
Every SDHI register access cites HUM Ch 47 "SD/MMC Host Interface (SDHI)" (HUM pages 3122-3179). SD command numbers and response formats follow the SD Physical Layer Specification v6.00 – HUM Ch 47.1 "Overview" pins SDHI to that document directly.
Definition in file ra8_sdcard.c.
| enum ra8_sdcard_cmd_t : uint8_t |
SD Physical Layer command indices used by ra8_sdcard_init.
Matches the SD Physical Layer Specification v6.00, Table 4-24 "Card commands". Values are bare command indices; SDHI infers the response type and data direction from the index for the standard commands used here.
Definition at line 73 of file ra8_sdcard.c.
| enum ra8_sdcard_csd_t : uint32_t |
CSD register decoding constants.
SD CSD layout (Section 5.3 of the Physical Layer Spec):
The SDHI hardware drops the 8-bit CRC and 1-bit end bit, so what shows up in out_rsp[0..3] is bits [127:8] left-shifted by 8. The decoder below expects that 120-bit format – matching FSP r_sdhi_csd_extract.
| Enumerator | |
|---|---|
| k_ra8_sdcard_csd_v2_blocks_per_unit | 512 KiB / 512 B |
| k_ra8_sdcard_sdhc_threshold_blocks | 2 GiB / 512 B = SDXC boundary |
Definition at line 123 of file ra8_sdcard.c.
| enum ra8_sdcard_proto_t : uint32_t |
SD protocol-level constants.
Magic numbers from the SD Physical Layer Specification v6.00. The CMD8 check-pattern is fixed at 0xAA and the voltage-supplied field is set to b0001 ("2.7-3.6 V") – the only voltage range the host supports.
Definition at line 94 of file ra8_sdcard.c.
| enum sd_csd_field_t : uint32_t |
SD CSD register field masks, shifts and block size.
Definition at line 47 of file ra8_sdcard.c.
|
static |
Classify card type from OCR.CCS and decoded block count.
SDA marketing tiers: SDSC < 2 GiB (byte-addressed), SDHC up to 32 GiB, SDXC above. The exact cutover is fuzzy; treat anything above a generous 32 GB as SDXC and the rest as SDHC.
| [in] | high_capacity | Non-zero if OCR.CCS = 1. |
| [in] | blocks | Capacity in 512-byte blocks. |
| k_ra8_sdcard_type_sdsc | high_capacity == 0 (byte-addressed card). |
| k_ra8_sdcard_type_sdhc | high_capacity != 0 and blocks <= 32 GiB threshold. |
| k_ra8_sdcard_type_sdxc | high_capacity != 0 and blocks > 32 GiB threshold. |
Definition at line 434 of file ra8_sdcard.c.
References k_ra8_sdcard_sdhc_threshold_blocks, k_ra8_sdcard_type_sdhc, k_ra8_sdcard_type_sdsc, and k_ra8_sdcard_type_sdxc.
Referenced by ra8_sdcard_init().
|
static |
Decode a CSD response (v1 or v2) into a capacity-in-blocks count.
| [in] | rsp | CSD register contents from CMD9 (rsp[0..3]). |
| [out] | out_blocks | Receives the 512-byte block count. |
The SDHI hardware strips the CRC + end bit, so each rsp word holds the 32-bit CSD slice already shifted to the standard layout. rsp[3] carries the high 32 bits; CSD_STRUCTURE sits at rsp[3][31:30].
| 0 | Success or default value. |
Definition at line 212 of file ra8_sdcard.c.
References k_ra8_err_hw_init_failed, k_ra8_ok, k_ra8_sdcard_csd_v2_blocks_per_unit, k_sd_block_size_bytes, k_sd_csd_struct_shift, k_sd_csize_mult_mask, k_sd_csize_mult_shift, k_sd_csize_v1_lo_mask, k_sd_csize_v1_lo_shift, k_sd_csize_v1_mask, k_sd_csize_v1_shift, k_sd_csize_v2_lo_mask, k_sd_csize_v2_mask, k_sd_csize_v2_mid_mask, k_sd_read_bl_mask, RA8_CHECK_NULL_PTR, and s_tag.
Referenced by internal_sdcard_publish_and_select().
|
static |
Definition at line 151 of file ra8_sdcard.c.
References k_ra8_err_hw_init_failed, k_ra8_ok, k_ra8_sdcard_acmd41_hcs, k_ra8_sdcard_acmd41_send_op_cond, k_ra8_sdcard_acmd41_voltage_win, k_ra8_sdcard_cmd55_app_cmd, k_ra8_sdcard_init_retry_max, k_ra8_sdcard_ocr_busy_done_mask, RA8_CHECK_NULL_PTR, ra8_sdhi_send_command(), and s_tag.
Referenced by internal_sdcard_card_online().
|
static |
Take an identified SDHI card from power-on to TRAN state.
Brings up the SDHI module, then runs the SD Physical Layer chain: CMD0/CMD8 identification, the ACMD41 op-cond loop (capturing OCR.CCS), then CMD2/CMD3/CMD9/CMD7 to publish the RCA, decode the CSD, and select the card. On any failure after the module came up the SDHI module is deinit'd, so the caller simply propagates the error.
| [in] | instance | SDHI instance index. |
| [out] | out_rca | Receives the published relative address. |
| [out] | out_blocks | Receives capacity in 512-byte blocks. |
| [out] | out_high_capacity | Receives 1 when OCR.CCS = 1 (SDHC/SDXC). |
| k_ra8_ok | Card parked in TRAN, outputs valid. |
| k_ra8_err_hw_init_failed | Identification / CSD decode failed. |
Definition at line 512 of file ra8_sdcard.c.
References internal_run_acmd41(), internal_sdcard_identify(), internal_sdcard_publish_and_select(), k_ra8_ok, k_ra8_sdcard_ocr_ccs_mask, RA8_RETURN_ON_ERROR, ra8_sdhi_deinit(), ra8_sdhi_init(), and s_tag.
Referenced by ra8_sdcard_init().
|
static |
Drive CMD0 + CMD8 to take the card from power-on into idle.
HUM Ch 47.2.1 SD_CMD command sequence. CMD0 has no response but still drives the RSPEND handshake; CMD8 echoes the low 12 bits of the argument back through R7. Mismatch indicates a v1 (no-CMD8) card or no card present.
| [in] | instance | SDHI instance index. |
| k_ra8_ok | Identification echo matched. |
| k_ra8_err_hw_init_failed | CMD8 pattern mismatch. |
Definition at line 275 of file ra8_sdcard.c.
References k_ra8_err_hw_init_failed, k_ra8_ok, k_ra8_sdcard_cmd0_go_idle, k_ra8_sdcard_cmd8_pattern, k_ra8_sdcard_cmd8_pattern_mask, k_ra8_sdcard_cmd8_send_if_cond, RA8_RETURN_ON_ERROR, ra8_sdhi_send_command(), and s_tag.
Referenced by internal_sdcard_card_online().
|
static |
Negotiate the requested SD data-bus width after card selection.
Only the SD 4-bit path is negotiable from the SD-card driver; 1-bit needs no action and any other request (including the eMMC-only 8-bit width) is treated as "stay 1-bit". Widening is a best-effort optimization: the card was already identified and selected at 1-bit, so ANY ACMD6 failure (a card that declines, or a bus timeout) simply falls back to the proven 1-bit mode and is logged – it never fails ra8_sdcard_init, which is why this returns void.
| [in] | instance | SDHI instance index. |
| [in] | width | Requested bus width from ra8_sdcard_cfg_t. |
| [in] | rca | Card relative address published by CMD3. |
Definition at line 471 of file ra8_sdcard.c.
References k_ra8_ok, k_ra8_sdhi_bus_width_4bit, ra8_log_info_val, ra8_sdhi_set_bus_width_4bit(), and s_tag.
Referenced by ra8_sdcard_init().
|
static |
Publish the RCA, decode the CSD, and put the card in TRAN.
HUM Ch 47.2.5 response registers / SD Physical Layer Spec Section 4.7. Delegates CMD2/CMD3 to internal_sdcard_publish_rca, then runs CMD9 (CSD) and CMD7 with the published RCA to move the card into TRAN.
| [in] | instance | SDHI instance index. |
| [out] | out_rca | Receives the card's relative address. |
| [out] | out_blocks | Receives capacity in 512-byte blocks. |
| k_ra8_ok | Card parked in TRAN. |
| k_ra8_err_hw_init_failed | CSD decode rejected the layout. |
Definition at line 376 of file ra8_sdcard.c.
References internal_decode_csd(), internal_sdcard_publish_rca(), k_ra8_ok, k_ra8_sdcard_cmd7_select_card, k_ra8_sdcard_cmd9_send_csd, RA8_RETURN_ON_ERROR, ra8_sdhi_send_command(), and s_tag.
Referenced by internal_sdcard_card_online().
|
static |
Run CMD2 + CMD3 so the card publishes its relative address.
SD Physical Layer Spec Section 4.2.2 identification flow: CMD2 ALL_SEND_CID broadcasts the 136-bit CID (which this host does not decode), then CMD3 SEND_RELATIVE_ADDR asks the card to publish the 16-bit RCA in rsp[0][31:16].
| [in] | instance | SDHI instance index. |
| [out] | out_rca | Receives the card-published relative address. |
| k_ra8_ok | RCA published and captured. |
Definition at line 327 of file ra8_sdcard.c.
References k_ra8_ok, k_ra8_sdcard_cmd2_all_send_cid, k_ra8_sdcard_cmd3_send_rca, k_sd_rca_mask, RA8_RETURN_ON_ERROR, ra8_sdhi_send_command(), and s_tag.
Referenced by internal_sdcard_publish_and_select().
|
static |
Translate a logical block address into the SD on-card argument.
SDSC cards expect a byte address, SDHC/SDXC cards expect a block index. The host always speaks in block indices; this helper applies the byte-multiplication where it is needed.
| [in] | lba | Logical block address. |
| 0 | Success or default value. |
Definition at line 604 of file ra8_sdcard.c.
References k_ra8_sdcard_type_sdsc, k_sd_block_size_bytes, and s_sdcard.
Referenced by ra8_sdcard_read_blocks(), and ra8_sdcard_write_blocks().
|
nodiscard |
Tear down the card driver and release the SDHI block.
Resets the internal protocol state (capacity, RCA, type) and calls ra8_sdhi_deinit on the underlying instance. After this call ra8_sdcard_init may be invoked again.
| k_ra8_ok | Success (or already-deinit no-op). |
| k_ra8_err_invalid_state | SDHI deinit failed. |
Definition at line 664 of file ra8_sdcard.c.
References k_ra8_err_invalid_state, k_ra8_ok, k_ra8_sdcard_type_unknown, ra8_sdhi_deinit(), and s_sdcard.
|
nodiscard |
Return card capacity in 512-byte blocks.
| [out] | out_blocks | Receives the block count; non-NULL. |
| k_ra8_ok | Success. |
| k_ra8_err_null_ptr | out_blocks was NULL. |
| k_ra8_err_invalid_state | Card never initialized. |
Definition at line 644 of file ra8_sdcard.c.
References k_ra8_err_invalid_state, k_ra8_ok, RA8_CHECK_NULL_PTR, s_sdcard, and s_tag.
Referenced by internal_sdhi_get_caps(), and sdhi_card_check_capacity().
|
nodiscard |
Return the detected card type (SDSC / SDHC / SDXC).
| [out] | out_type | Receives the card type; non-NULL. |
| k_ra8_ok | Success. |
| k_ra8_err_null_ptr | out_type was NULL. |
| k_ra8_err_invalid_state | Card never initialized. |
Definition at line 654 of file ra8_sdcard.c.
References k_ra8_err_invalid_state, k_ra8_ok, RA8_CHECK_NULL_PTR, s_sdcard, and s_tag.
|
nodiscard |
Bring up the SDHI block and perform full SD card initialization.
Runs the standard SD Physical Layer init sequence:
ra8_sdhi_set_clock to 25 MHz default-speed
On success the internal state holds card type, RCA, and capacity in 512-byte blocks, and the SDHI block is ready for read_blocks / write_blocks traffic.
| [in] | cfg | Non-NULL configuration with a valid SDHI instance. |
| k_ra8_ok | Card initialized, ready for I/O. |
| k_ra8_err_null_ptr | cfg was NULL. |
| k_ra8_err_invalid_arg | cfg->instance out of range. |
| k_ra8_err_invalid_state | Already initialized (call ra8_sdcard_deinit first). |
| k_ra8_err_hw_timeout | A command never produced RSPEND. |
| k_ra8_err_hw_init_failed | CMD8 echo / ACMD41 pattern mismatch. |
Definition at line 544 of file ra8_sdcard.c.
References ra8_sdcard_cfg_t::bus_width, ra8_sdcard_cfg_t::instance, internal_classify(), internal_sdcard_card_online(), internal_sdcard_negotiate_width(), k_ra8_err_invalid_state, k_ra8_ok, k_ra8_sdcard_default_clk_div, RA8_CHECK_NULL_PTR, ra8_log_info_val, RA8_RETURN_ON_ERROR, ra8_sdhi_set_clock(), s_sdcard, and s_tag.
Referenced by internal_sdcard_thread_entry(), sdhi_card_init_or_halt(), and sdhi_demo_init_card_or_halt().
|
nodiscard |
Read count 512-byte blocks starting at lba.
Thin pass-through to ra8_sdhi_read_block once the card has been initialized. The lba argument is the logical block address as understood by the card – which means block address for SDHC/SDXC and byte address for SDSC. ra8_sdcard translates the SDSC case internally (lba * 512) so callers always pass block indices.
| [in] | lba | Logical block address (sector number). |
| [out] | buf | Destination buffer; must hold count * 512 bytes. |
| [in] | count | Number of 512-byte blocks; must be > 0. |
| k_ra8_ok | Success. |
| k_ra8_err_null_ptr | buf was NULL. |
| k_ra8_err_invalid_arg | count was 0. |
| k_ra8_err_invalid_state | Card never initialized. |
| k_ra8_err_out_of_range | lba + count exceeds card capacity. |
Definition at line 612 of file ra8_sdcard.c.
References internal_to_card_address(), k_ra8_err_invalid_arg, k_ra8_err_invalid_state, k_ra8_err_out_of_range, RA8_CHECK_NULL_PTR, ra8_sdhi_read_block(), s_sdcard, and s_tag.
Referenced by internal_sdcard_one_pass(), internal_sdhi_read(), and sdhi_card_block_roundtrip().
|
nodiscard |
Write count 512-byte blocks starting at lba.
Thin pass-through to ra8_sdhi_write_block. Same SDSC byte-address translation as ra8_sdcard_read_blocks. The driver does not perform pre-erase (ACMD23) or busy-poll the card after writes; the caller is expected to layer those on top if required.
| [in] | lba | Logical block address. |
| [in] | buf | Source buffer; must hold count * 512 bytes. |
| [in] | count | Number of 512-byte blocks; must be > 0. |
Definition at line 628 of file ra8_sdcard.c.
References internal_to_card_address(), k_ra8_err_invalid_arg, k_ra8_err_invalid_state, k_ra8_err_out_of_range, RA8_CHECK_NULL_PTR, ra8_sdhi_write_block(), s_sdcard, and s_tag.
Referenced by internal_sdhi_write(), and sdhi_card_block_roundtrip().
|
static |
Module-private state.
Definition at line 147 of file ra8_sdcard.c.
Referenced by internal_to_card_address(), ra8_sdcard_deinit(), ra8_sdcard_get_capacity(), ra8_sdcard_get_type(), ra8_sdcard_init(), ra8_sdcard_read_blocks(), and ra8_sdcard_write_blocks().
|
static |
Module log tag.
Definition at line 44 of file ra8_sdcard.c.