Skip to content

Commit

Permalink
esp32s3: Implement sdioio
Browse files Browse the repository at this point in the history
  • Loading branch information
RetiredWizard committed Sep 18, 2024
1 parent 13d659a commit 32537ed
Show file tree
Hide file tree
Showing 15 changed files with 309 additions and 20 deletions.
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
224 changes: 224 additions & 0 deletions ports/espressif/common-hal/sdioio/SDCard.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
// 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 "ports/espressif/esp-idf/components/esp_driver_sdmmc/include/driver/sdmmc_host.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 comments on commit 32537ed

Please sign in to comment.