Initializes an SD card handle and performs the full SPI-mode power-up sequence.
434 {
436 uint8_t free_index;
437
442 "sd_init_handle: subsys not initialized"
443 );
444
446 }
447
452 "sd_init_handle: subsystem out of memory space"
453 );
454
456 }
457
458 if(!sd_cfg) {
462 "sd_init_handle: invalid argument"
463 );
465 }
466
467 bool found = false;
468
469 for(uint32_t i = 0; i < CONFIG_SD_MAX_OBJECTS; i++) {
471 free_index = i;
472 found = true;
473 break;
474 }
475 }
476
477 if(!found)
479
486
492
499
506
507
516
524
525
526 uint32_t spi_pclk = 0;
527
530 }
533 }
534
535 uint32_t spi_pclk_cpy = spi_pclk;
536 uint32_t div_factor = 2;
537 while(div_factor <= 256) {
538 spi_pclk = spi_pclk / div_factor;
539
540 if(spi_pclk >= 100000 && spi_pclk <= 400000) {
541 break;
542 }
543
544 spi_pclk = spi_pclk_cpy;
545 div_factor *= 2;
546 }
547
548 switch (div_factor) {
557 }
558
560
565 );
566
579
581
583
584
585 DELAY(CONFIG_SD_HW_INIT_WAIT_TIME);
586
587
589
590
592
593 uint8_t dummy_tx = 0xFF;
594 for(uint8_t i = 0; i < 10; i++) {
596 }
597
599
600
605 "sd_init_handle: failed to enter idle state, deinitializing handle"
606 );
607
609
611 }
612
613
614 bool match = false;
615 bool no_response = false;
616
621 "sd_init_handle: failed to get SD card type, deinitializing handle"
622 );
623
625
627 }
628
629
630 if(match) {
635 "sd_init_handle: failed to initiate initialization of SD Ver.2, deinitializing handle"
636 );
637
639
641 }
642
647 "sd_init_handle: failed to obtain SD Ver 2. information, deinitializing handle"
648 );
649
651 }
652 }
653
654 else if(no_response) {
656
659 }
660
663
667 "sd_init_handle: unknown card, deinitializing handle"
668 );
669
671
673 }
674
675 else {
677 }
678 }
679
680 else {
683 "sd_init_handle: unknown card, deinitializing handle"
684 );
685
687
689 }
690 }
691
697 "sd_init_handle: failed to initialize, deinitializing handle"
698 );
699
701
703 }
704 }
705
707
711 "sd_init_handle: sd handle %s initialized",
713 );
714
715
717
719
720
722
724}
int str_cpy(char *str_to, const char *str_from, uint32_t len)
Copies a null-terminated string into a destination buffer.
uint32_t get_str_len(char const *str)
Returns the length of a string, excluding the null terminator.
#define DELAY(ms)
Blocking delay using the system tick counter.
@ ERR_INITIALIZATION_FAILURE
ERR_te io_init_handle(IO_CFG_ts *io_cfg, IO_HANDLE_ts **io_handle_o)
Initializes and registers an IO handle.
ERR_te io_start_subsys(void)
Starts the IO subsystem.
ERR_te io_init_subsys(void)
Initializes the IO subsystem.
struct io_handle_s IO_HANDLE_ts
Opaque handle representing an IO instance.
#define LOG_CRITICAL(subsys, lvl, fmt,...)
static ERR_te sd_cease_comms(SD_HANDLE_ts *sd_handle, bool deinit)
Raises CS, sends two dummy bytes, and disables SPI. Optionally deinitializes the handle.
static ERR_te sd_app_send_op_cond(SD_HANDLE_ts *sd_handle, uint32_t arg)
Issues ACMD41 to initiate SD card initialization (SD Ver.2 and Ver.1).
static ERR_te sd_read_ocr(SD_HANDLE_ts *sd_handle)
Reads the OCR register via CMD58 and stores power-up status, addressing mode, and voltage range.
static ERR_te sd_go_idle_state(SD_HANDLE_ts *sd_handle)
Issues CMD0 to reset the SD card into idle (SPI) mode.
static ERR_te sd_send_op_cond(SD_HANDLE_ts *sd_handle)
Issues CMD1 to initiate MMC Ver.3 card initialization.
static ERR_te sd_set_blocklen(SD_HANDLE_ts *sd_handle)
Issues CMD16 to set the block length to 512 bytes for byte-addressed cards.
static ERR_te sd_read_csd(SD_HANDLE_ts *sd_handle)
Issues CMD9 to read the CSD register and stores capacity information in the handle.
static ERR_te sd_send_if_cond(SD_HANDLE_ts *sd_handle, bool *match_o, bool *no_resp_o)
Issues CMD8 to determine whether the card is SD Ver.2 or older.
void gpio_write(GPIO_REGDEF_ts *gpio_port, uint8_t gpio_pin, PIN_STATUS_te pin_status)
Drives a GPIO output pin high or low.
void gpio_init(GPIO_CFG_ts *gpio_cfg)
Initializes a GPIO pin according to the given configuration.
@ GPIO_MODE_ALTERNATE_FUNCTION
uint32_t rcc_get_apb2_clk(void)
Returns the current APB2 (high-speed) peripheral bus clock frequency in Hz.
uint32_t rcc_get_apb1_clk(void)
Returns the current APB1 (low-speed) peripheral bus clock frequency in Hz.
void spi_send(SPI_REGDEF_ts *spi_instance, uint8_t *tx_buffer, uint32_t len)
Blocking SPI transmit. Sends len bytes from tx_buffer.
void spi_init(SPI_CFG_ts *spi_cfg)
Initializes the SPI peripheral with the given configuration.
void spi_set_comm(SPI_REGDEF_ts *spi_instance, EN_STATUS_te en_status)
Enables or disables the SPI peripheral (SPE bit).
void spi_set_pclk_div(SPI_REGDEF_ts *spi_instance, SPI_MASTER_SCLK_SPEED_te pclk_div)
Changes the SPI master clock speed divisor at runtime.
@ SPI_CLOCK_PHASE_FIRST_TRANSITION
@ SPI_DATA_FRAME_FORMATE_8_BIT
@ SPI_SLAVE_SELECT_MODE_SW
@ SPI_MASTER_SCLK_SPEED_PCLK_DIV_8
@ SPI_MASTER_SCLK_SPEED_PCLK_DIV_2
@ SPI_MASTER_SCLK_SPEED_PCLK_DIV_16
@ SPI_MASTER_SCLK_SPEED_PCLK_DIV_4
@ SPI_MASTER_SCLK_SPEED_PCLK_DIV_256
@ SPI_MASTER_SCLK_SPEED_PCLK_DIV_32
@ SPI_MASTER_SCLK_SPEED_PCLK_DIV_128
@ SPI_MASTER_SCLK_SPEED_PCLK_DIV_64
@ SPI_CLOCK_POLARITY_0_IDLE
Configuration structure for initializing a GPIO pin.
GPIO_ALTERNATE_FUNCTION_te alternate_function
Configuration structure for initializing an IO handle.
char name[CONFIG_IO_MAX_NAME_LEN]
GPIO_CFG_ts * gpio_handle
GPIO_REGDEF_ts * miso_gpio_port
GPIO_PIN_te sclk_gpio_pin
GPIO_REGDEF_ts * mosi_gpio_port
char name[CONFIG_SD_MAX_NAME_LEN]
GPIO_REGDEF_ts * cs_gpio_port
SPI_REGDEF_ts * spi_instance
GPIO_PIN_te mosi_gpio_pin
GPIO_ALTERNATE_FUNCTION_te gpio_alternate_function
GPIO_REGDEF_ts * sclk_gpio_port
GPIO_PIN_te miso_gpio_pin
Configuration structure for initializing an SPI peripheral.
SPI_CLOCK_POLARITY_te clock_polarity
SPI_SLAVE_SELECT_MODE_te slave_select_mode
SPI_MASTER_SCLK_SPEED_te master_sclk_speed
SPI_DATA_FRAME_FORMAT_te data_frame_format
SPI_CLOCK_PHASE_te clock_phase
SPI_BIT_FIRST_te bit_first