8000 esp32s3: Implement sdioio by RetiredWizard · Pull Request #9641 · adafruit/circuitpython · GitHub
[go: up one dir, main page]

Skip to content

esp32s3: Implement sdioio #9641

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 24 additions & 9 deletions locale/circuitpython.pot
Original file line number Diff line number Diff line change
Expand Up @@ -661,12 +661,12 @@ msgid "Buffer length %d too big. It must be less than %d"
msgstr ""

#: ports/atmel-samd/common-hal/sdioio/SDCard.c
#: ports/cxd56/common-hal/sdioio/SDCard.c shared-module/sdcardio/SDCard.c
msgid "Buffer length must be a multiple of 512"
msgstr ""

#: ports/cxd56/common-hal/sdioio/SDCard.c
#: ports/espressif/common-hal/sdioio/SDCard.c
#: ports/stm/common-hal/sdioio/SDCard.c shared-bindings/floppyio/__init__.c
msgid "Buffer must be a multiple of 512 bytes"
#: shared-module/sdcardio/SDCard.c
#, c-format
msgid "Buffer must be a multiple of %d bytes"
msgstr ""

#: shared-bindings/_bleio/PacketBuffer.c
Expand Down Expand Up @@ -1183,11 +1183,13 @@ msgstr ""
msgid "Interrupted by output function"
msgstr ""

#: ports/espressif/common-hal/_bleio/Service.c
#: ports/espressif/common-hal/espulp/ULP.c
#: ports/espressif/common-hal/microcontroller/Processor.c
#: ports/mimxrt10xx/common-hal/audiobusio/__init__.c
#: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c
#: ports/raspberrypi/bindings/picodvi/Framebuffer.c
#: ports/raspberrypi/bindings/rp2pio/StateMachine.c
#: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c py/argcheck.c
#: shared-bindings/digitalio/DigitalInOut.c
#: shared-bindings/epaperdisplay/EPaperDisplay.c shared-bindings/pwmio/PWMOut.c
Expand Down Expand Up @@ -1307,6 +1309,7 @@ msgid "MAC address was invalid"
msgstr ""

#: ports/espressif/common-hal/_bleio/Characteristic.c
#: ports/espressif/common-hal/_bleio/Descriptor.c
msgid "MITM security not supported"
msgstr ""

Expand Down Expand Up @@ -1869,6 +1872,19 @@ msgstr ""
msgid "SDIO Init Error %d"
msgstr ""

#: ports/espressif/common-hal/sdioio/SDCard.c
#, c-format
msgid "SDIO Init Error %x"
msgstr ""

#: ports/espressif/common-hal/sdioio/SDCard.c
msgid "SDIO: cards have either 1 or 4 data lines"
msgstr ""

#: ports/espressif/common-hal/sdioio/SDCard.c
msgid "SDIO: requested frequency out of range"
msgstr ""

#: ports/espressif/common-hal/busio/SPI.c
msgid "SPI configuration failed"
msgstr ""
Expand Down Expand Up @@ -2242,14 +2258,12 @@ msgid "Update failed"
msgstr ""

#: ports/espressif/common-hal/_bleio/Characteristic.c
#: ports/espressif/common-hal/_bleio/Descriptor.c
#: ports/nordic/common-hal/_bleio/Characteristic.c
#: ports/nordic/common-hal/_bleio/Descriptor.c
msgid "Value length != required fixed length"
msgstr ""

#: ports/espressif/common-hal/_bleio/Characteristic.c
#: ports/espressif/common-hal/_bleio/Descriptor.c
#: ports/nordic/common-hal/_bleio/Characteristic.c
#: ports/nordic/common-hal/_bleio/Descriptor.c
msgid "Value length > max_length"
Expand Down Expand Up @@ -3098,7 +3112,8 @@ msgstr ""
msgid "function missing required positional argument #%d"
msgstr ""

#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/time/__init__.c
#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/_eve/__init__.c
#: shared-bindings/time/__init__.c
#, c-format
msgid "function takes %d positional arguments but %d were given"
msgstr ""
Expand Down Expand Up @@ -3250,7 +3265,7 @@ msgstr ""
msgid "input must be a dense ndarray"
msgstr ""

#: extmod/ulab/code/user/user.c
#: extmod/ulab/code/user/user.c shared-bindings/_eve/__init__.c
msgid "input must be an ndarray"
msgstr ""

Expand Down
2 changes: 1 addition & 1 deletion ports/atmel-samd/common-hal/sdioio/SDCard.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ static void check_for_deinit(sdioio_sdcard_obj_t *self) {

static void check_whole_block(mp_buffer_info_t *bufinfo) {
if (bufinfo->len % 512) {
mp_raise_ValueError(MP_ERROR_TEXT("Buffer length must be a multiple of 512"));
mp_raise_ValueError_varg(MP_ERROR_TEXT("Buffer must be a multiple of %d bytes"), 512);
}
}

Expand Down
2 changes: 1 addition & 1 deletion ports/cxd56/common-hal/sdioio/SDCard.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ uint32_t common_hal_sdioio_sdcard_get_count(sdioio_sdcard_obj_t *self) {

static void check_whole_block(mp_buffer_info_t *bufinfo) {
if (bufinfo->len % 512) {
mp_raise_ValueError(MP_ERROR_TEXT("Buffer length must be a multiple of 512"));
mp_raise_ValueError_varg(MP_ERROR_TEXT("Buffer must be a multiple of %d bytes"), 512);
}
}

Expand Down
2 changes: 1 addition & 1 deletion ports/espressif/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.16)
set(ENV{IDF_PATH} ${CMAKE_SOURCE_DIR}/esp-idf)

# The component list here determines what options we get in menuconfig and what the ninja file can build.
set(COMPONENTS bt driver esp_driver_dac esp_driver_gpio esp_driver_gptimer esp_driver_i2s esp_driver_ledc esp_driver_pcnt esp_driver_rmt esp_driver_spi esp_driver_tsens esp_driver_uart esp-tls esp_adc_cal esp_event esp_netif esp_psram esp_wifi esptool_py freertos log lwip main mbedtls mdns soc ulp usb wpa_supplicant esp-camera esp_lcd vfs esp_vfs_console)
set(COMPONENTS bt driver esp_driver_dac esp_driver_gpio esp_driver_gptimer esp_driver_i2s esp_driver_ledc esp_driver_pcnt esp_driver_rmt esp_driver_spi esp_driver_tsens esp_driver_uart esp-tls esp_adc_cal esp_event esp_netif esp_psram esp_wifi esptool_py freertos log lwip main mbedtls mdns soc ulp usb wpa_supplicant esp-camera esp_lcd vfs esp_vfs_console sdmmc)
set(EXTRA_COMPONENT_DIRS "esp-protocols/components/mdns" "esp-camera")

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
Expand Down
7 changes: 7 additions & 0 deletions ports/espressif/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ INC += \
-isystem esp-idf/components/esp_driver_ledc/include \
-isystem esp-idf/components/esp_driver_pcnt/include \
-isystem esp-idf/components/esp_driver_rmt/include \
-isystem esp-idf/components/esp_driver_sdio/include \
-isystem esp-idf/components/esp_driver_sdmmc/include \
-isystem esp-idf/components/esp_driver_spi/include \
-isystem esp-idf/components/esp_driver_tsens/include \
-isystem esp-idf/components/esp_driver_uart/include \
Expand Down Expand Up @@ -128,6 +130,8 @@ INC += \
-isystem esp-idf/components/mbedtls/port/include \
-isystem esp-idf/components/newlib/platform_include \
-isystem esp-idf/components/nvs_flash/include \
-isystem esp-idf/components/sdio/include \
-isystem esp-idf/components/sdmmc/include \
-isystem esp-idf/components/soc/include \
-isystem esp-idf/components/soc/$(IDF_TARGET)/include \
-isystem esp-idf/components/spi_flash/include \
Expand Down Expand Up @@ -660,6 +664,9 @@ endif
ifneq ($(CIRCUITPY_USB_DEVICE),0)
ESP_IDF_COMPONENTS_LINK += usb
endif
ifneq ($(CIRCUITPY_SDIOIO),0)
ESP_IDF_COMPONENTS_LINK += sdmmc esp_driver_sdmmc
endif

ESP_IDF_COMPONENTS_EXPANDED = $(foreach component, $(ESP_IDF_COMPONENTS_LINK), $(BUILD)/esp-idf/esp-idf/$(component)/lib$(component).a)

Expand Down
2 changes: 2 additions & 0 deletions ports/espressif/boards/makerfabs_tft7/mpconfigboard.mk
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ CIRCUITPY_ESP_PSRAM_FREQ = 80m

CIRCUITPY_DOTCLOCKFRAMEBUFFER = 1

CIRCUITPY_SDIOIO = 1

# To build with USB disabled allowing access to I2S pins
#CIRCUITPY_CREATOR_ID = 0x1A000000
#CIRCUITPY_CREATION_ID = 0x005381BF
Expand Down
7 changes: 3 additions & 4 deletions ports/espressif/boards/makerfabs_tft7/pins.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,9 @@ static const mp_rom_map_elem_t board_module_globals_table[] = {

// IO10 <> SD_CS is cut at factory (non-placed resistor position R34) and pulled up.
// Permanent SDIO 1-bit mode?
// Until SDIO 1-bit mode is support on Espressif ports these pins aren't useful
// { MP_ROM_QSTR(MP_QSTR_SDIO_CMD), MP_ROM_PTR(&pin_GPIO11) },
// { MP_ROM_QSTR(MP_QSTR_SDIO_D0), MP_ROM_PTR(&pin_GPIO13) },
// { MP_ROM_QSTR(MP_QSTR_SDIO_CLK), MP_ROM_PTR(&pin_GPIO12) },
{ MP_ROM_QSTR(MP_QSTR_SDIO_CMD), MP_ROM_PTR(&pin_GPIO11) },
{ MP_ROM_QSTR(MP_QSTR_SDIO_D0), MP_ROM_PTR(&pin_GPIO13) },
{ MP_ROM_QSTR(MP_QSTR_SDIO_CLK), MP_ROM_PTR(&pin_GPIO12) },

{ MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) },

Expand Down
223 changes: 223 additions & 0 deletions ports/espressif/common-hal/sdioio/SDCard.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2024 Jacob Rigby
//
// SPDX-License-Identifier: MIT

#include <stdbool.h>
#include "esp_err.h"

#include "driver/sdmmc_host.h"
#include "ports/espressif/esp-idf/components/sdmmc/include/sdmmc_cmd.h"

#include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/util.h"
#include "shared-bindings/sdioio/SDCard.h"
#include "py/mperrno.h"
#include "py/runtime.h"

#include "esp_log.h"
static const char *TAG = "SDCard.c";

static bool sdio_host_init = false;

static void common_hal_sdioio_sdcard_check_for_deinit(sdioio_sdcard_obj_t *self) {
if (common_hal_sdioio_sdcard_deinited(self)) {
raise_deinited_error();
}
}

static int check_pins(const mcu_pin_obj_t *clock, const mcu_pin_obj_t *command, const uint8_t num_data, const mcu_pin_obj_t **data) {
if (CONFIG_SOC_SDMMC_USE_GPIO_MATRIX) {
// ESP32-S3 and P4 can use any pin for any SDMMC func in either slot
// Default to SLOT_1 for SD cards
ESP_LOGI(TAG, "Using chip with CONFIG_SOC_SDMMC_USE_GPIO_MATRIX");
return SDMMC_HOST_SLOT_1;
}
if (command->number == GPIO_NUM_11 && clock->number == GPIO_NUM_6 && data[0]->number == GPIO_NUM_7) {
// Might be slot 0
if (num_data == 1 || (num_data == 4 && data[1]->number == GPIO_NUM_8 && data[2]->number == GPIO_NUM_9 && data[3]->number == GPIO_NUM_10)) {
return SDMMC_HOST_SLOT_0;
}
} else if (command->number == GPIO_NUM_15 && clock->number == GPIO_NUM_14 && data[0]->number == 2) {
// Might be slot 1
if (num_data == 1 || (num_data == 4 && data[1]->number == GPIO_NUM_4 && data[2]->number == GPIO_NUM_12 && data[3]->number == GPIO_NUM_13)) {
return SDMMC_HOST_SLOT_1;
}
}
return -1;
}

void common_hal_sdioio_sdcard_construct(sdioio_sdcard_obj_t *self,
const mcu_pin_obj_t *clock, const mcu_pin_obj_t *command,
uint8_t num_data, const mcu_pin_obj_t **data, uint32_t frequency) {
if (num_data != 4 && num_data != 1) {
mp_raise_ValueError(MP_ERROR_TEXT("SDIO: cards have either 1 or 4 data lines"));
}

self->num_data = num_data;
int sd_slot = check_pins(clock, command, num_data, data);
if (sd_slot != SDMMC_HOST_SLOT_0 && sd_slot != SDMMC_HOST_SLOT_1) {
// Bad pin combo
raise_ValueError_invalid_pins();
}

if (frequency > 40000000) {
// Higher than max 40Mhz frequency
mp_raise_ValueError(MP_ERROR_TEXT("SDIO: requested frequency out of range"));
}

ESP_LOGI(TAG, "Using slot %d", sd_slot);
self->slot = (uint8_t)sd_slot;
esp_err_t err = ESP_OK;

sdmmc_host_t host = SDMMC_HOST_DEFAULT();
host.max_freq_khz = frequency / 1000;

sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
slot_config.width = 1;
slot_config.clk = clock->number;
claim_pin(clock);
self->clock = clock->number;
slot_config.cmd = command->number;
claim_pin(command);
self->command = command->number;
slot_config.d0 = data[0]->number;
self->data[0] = data[0]->number;
claim_pin(data[0]);
if (num_data == 4) {
slot_config.width = 4;
slot_config.d1 = data[1]->number;
claim_pin(data[1]);
self->data[1] = data[1]->number;
slot_config.d2 = data[2]->number;
claim_pin(data[2]);
self->data[2] = data[2]->number;
slot_config.d3 = data[3]->number;
claim_pin(data[3]);
self->data[3] = data[3]->number;
}

ESP_LOGI(TAG, "slot_config:\nwidth: %d, clk: %d, cmd: %d\nd0: %d, d1: %d, d2: %d, d3: %d",
slot_config.width, slot_config.clk, slot_config.cmd,
slot_config.d0, slot_config.d1, slot_config.d2, slot_config.d3);

if (!sdio_host_init) {
err = sdmmc_host_init();
if (err != ESP_OK) {
mp_raise_OSError_msg_varg(MP_ERROR_TEXT("SDIO Init Error %x"), err);
}
// sdio_host_init = true;
}
err = sdmmc_host_init_slot(sd_slot, &slot_config);
if (err != ESP_OK) {
ESP_LOGW(TAG, "Failed to initialize SDMMC slot: %x", err);
mp_raise_OSError_msg_varg(MP_ERROR_TEXT("SDIO Init Error %x"), err);
}
// sdmmc_card_t card;
// self->card = malloc(sizeof(sdmmc_card_t));
err = sdmmc_card_init(&host, &self->card);
if (err != ESP_OK) {
ESP_LOGW(TAG, "Failed to initialize SDMMC card: %x", err);
mp_raise_OSError_msg_varg(MP_ERROR_TEXT("SDIO Init Error %x"), err);
}

common_hal_sdioio_sdcard_check_for_deinit(self);

ESP_LOGI(TAG, "Initialized SD card with ID %d:%d-%s",
self->card.cid.mfg_id, self->card.cid.oem_id, self->card.cid.name);

ESP_LOGI(TAG, "Number of sectors: %d with sector_size: %d",
self->card.csd.capacity, self->card.csd.sector_size);

self->frequency = self->card.real_freq_khz;
ESP_LOGI(TAG, "Real frequency is %lu", self->frequency);
self->capacity = self->card.csd.capacity; // Reported number of sectors
ESP_LOGI(TAG, "Reported capacity is %lu", self->capacity);

return;
}

uint32_t common_hal_sdioio_sdcard_get_count(sdioio_sdcard_obj_t *self) {
return self->capacity;
}

uint32_t common_hal_sdioio_sdcard_get_frequency(sdioio_sdcard_obj_t *self) {
return self->frequency;
}

uint8_t common_hal_sdioio_sdcard_get_width(sdioio_sdcard_obj_t *self) {
return self->num_data;
}

static void check_whole_block(mp_buffer_info_t *bufinfo, int sector_size) {
if (bufinfo->len % sector_size) {
mp_raise_ValueError_varg(MP_ERROR_TEXT("Buffer must be a multiple of %d bytes"), sector_size);
}
}

int common_hal_sdioio_sdcard_writeblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo) {
common_hal_sdioio_sdcard_check_for_deinit(self);
check_whole_block(bufinfo, self->card.csd.sector_size);
esp_err_t err;
ESP_LOGI(TAG, "in common_hal_sdioio_sdcard_writeblocks");
// err = sdmmc_io_write_blocks(&self->card, 1, start_block, bufinfo->buf, bufinfo->len);
err = sdmmc_write_sectors(&self->card, bufinfo->buf, start_block, bufinfo->len / self->card.csd.sector_size);
if (err != ESP_OK) {
ESP_LOGW(TAG, "Failed to write blocks with err 0x%X", err);
}
return 0;
}

int common_hal_sdioio_sdcard_readblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo) {
common_hal_sdioio_sdcard_check_for_deinit(self);
check_whole_block(bufinfo, self->card.csd.sector_size);
esp_err_t err;
ESP_LOGI(TAG, "in common_hal_sdioio_sdcard_readblocks");
// err = sdmmc_io_read_blocks(&self->card, 1, start_block, bufinfo->buf, bufinfo->len);
err = sdmmc_read_sectors(&self->card, bufinfo->buf, start_block, bufinfo->len / self->card.csd.sector_size);
if (err != ESP_OK) {
ESP_LOGW(TAG, "Failed to read blocks with err 0x%X", err);
}
return 0;
}

bool common_hal_sdioio_sdcard_configure(sdioio_sdcard_obj_t *self, uint32_t frequency, uint8_t bits) {
return true;
}

bool common_hal_sdioio_sdcard_deinited(sdioio_sdcard_obj_t *self) {
return self->command == COMMON_HAL_MCU_NO_PIN;
}

void common_hal_sdioio_sdcard_deinit(sdioio_sdcard_obj_t *self) {
if (common_hal_sdioio_sdcard_deinited(self)) {
return;
}
sdmmc_host_deinit();
reset_pin_number(self->command);
self->command = COMMON_HAL_MCU_NO_PIN;
reset_pin_number(self->clock);
self->clock = COMMON_HAL_MCU_NO_PIN;
reset_pin_number(self->data[0]);
self->data[0] = COMMON_HAL_MCU_NO_PIN;
if (self->num_data == 4) {
reset_pin_number(self->data[1]);
self->data[1] = COMMON_HAL_MCU_NO_PIN;
reset_pin_number(self->data[2]);
self->data[2] = COMMON_HAL_MCU_NO_PIN;
reset_pin_number(self->data[3]);
self->data[3] = COMMON_HAL_MCU_NO_PIN;
}
return;
}

void common_hal_sdioio_sdcard_never_reset(sdioio_sdcard_obj_t *self) {
if (common_hal_sdioio_sdcard_deinited(self)) {
return;
}
}

void sdioio_reset() {
return;
}
Loading
0