feat(sdmmc): Add SDMMC support for P4 + remove BUILTIN LED (#10460)

* feat(sdmmc): Add support for P4

* fix(board): Remove builtin led

* Update libraries/SD_MMC/examples/SDMMC_Test/SDMMC_Test.ino

Add missing note about power pin for P4

Co-authored-by: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com>

* ci(pre-commit): Apply automatic fixes

* feat(sdmmc): Option to set power channel

* feat(sdmmc): Update pins_arduino.h

* feat(sdmmc): remove sdmmc power from periman

* fix(sdmmc): use corrent variable

* fix(sdmmc): Remove periman

* feat(sdmmc): Toggle power pin if defined

* feat(sdmmc): setPowerChannel available only when supported

* feat(sdmmc): Toggle sd power pin for 200ms

* fix(example): Remove p4 pins as they are listed already

* feat(sdmmc): Check if power channel is specified

* ci(pre-commit): Apply automatic fixes

* fix(ci): codespell fix

---------

Co-authored-by: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
This commit is contained in:
Jan Procházka 2024-10-21 14:03:44 +02:00 committed by GitHub
parent 7cfe470d8d
commit 83d35683c3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 138 additions and 23 deletions

View file

@ -14,6 +14,7 @@
* Connections for
* full-sized
* SD card
* ESP32-P4 Func EV | 40 39 GND 43 3V3 GND 44 43 42 | SLOT 0 (IO_MUX)
* ESP32-S3 DevKit | 21 47 GND 39 3V3 GND 40 41 42 |
* ESP32-S3-USB-OTG | 38 37 GND 36 3V3 GND 35 34 33 |
* ESP32 | 4 2 GND 14 3V3 GND 15 13 12 |
@ -42,6 +43,7 @@
#include "FS.h"
#include "SD_MMC.h"
#ifdef CONFIG_IDF_TARGET_ESP32S3
// Default pins for ESP-S3
// Warning: ESP32-S3-WROOM-2 is using most of the default GPIOs (33-37) to interface with on-board OPI flash.
// If the SD_MMC is initialized with default pins it will result in rebooting loop - please
@ -54,6 +56,7 @@ int d0 = 37;
int d1 = 38;
int d2 = 33;
int d3 = 39; // GPIO 34 is not broken-out on ESP32-S3-DevKitC-1 v1.1
#endif
void listDir(fs::FS &fs, const char *dirname, uint8_t levels) {
Serial.printf("Listing directory: %s\n", dirname);
@ -211,15 +214,16 @@ void testFileIO(fs::FS &fs, const char *path) {
void setup() {
Serial.begin(115200);
/*
// If you want to change the pin assignment on ESP32-S3 uncomment this block and the appropriate
// If you want to change the pin assignment or you get an error that some pins
// are not assigned on ESP32-S3/ESP32-P4 uncomment this block and the appropriate
// line depending if you want to use 1-bit or 4-bit line.
// Please note that ESP32 does not allow pin change and will always fail.
// Please note that ESP32 does not allow pin change and setPins() will always fail.
//if(! SD_MMC.setPins(clk, cmd, d0)){
//if(! SD_MMC.setPins(clk, cmd, d0, d1, d2, d3)){
Serial.println("Pin change failed!");
return;
}
*/
// Serial.println("Pin change failed!");
// return;
//}
*/
if (!SD_MMC.begin()) {
Serial.println("Card Mount Failed");
@ -262,4 +266,6 @@ void setup() {
Serial.printf("Used space: %lluMB\n", SD_MMC.usedBytes() / (1024 * 1024));
}
void loop() {}
void loop() {
delay(10);
}

View file

@ -14,6 +14,7 @@
* Connections for
* full-sized
* SD card
* ESP32-P4 Func EV | 40 39 GND 43 3V3 GND 44 43 42 | SLOT 0 (IO_MUX)
* ESP32-S3 DevKit | 21 47 GND 39 3V3 GND 40 41 42 |
* ESP32-S3-USB-OTG | 38 37 GND 36 3V3 GND 35 34 33 |
* ESP32 | 4 2 GND 14 3V3 GND 15 13 12 |

View file

@ -32,11 +32,14 @@
#include "ff.h"
#include "esp32-hal-periman.h"
#if SOC_SDMMC_IO_POWER_EXTERNAL
#include "sd_pwr_ctrl_by_on_chip_ldo.h"
#endif
using namespace fs;
SDMMCFS::SDMMCFS(FSImplPtr impl) : FS(impl), _card(nullptr) {
#if !defined(CONFIG_IDF_TARGET_ESP32P4)
#if defined(SOC_SDMMC_USE_GPIO_MATRIX) && defined(BOARD_HAS_SDMMC)
#if defined(SOC_SDMMC_USE_GPIO_MATRIX) && defined(BOARD_HAS_SDMMC) && !defined(CONFIG_IDF_TARGET_ESP32P4)
_pin_clk = SDMMC_CLK;
_pin_cmd = SDMMC_CMD;
_pin_d0 = SDMMC_D0;
@ -45,9 +48,8 @@ SDMMCFS::SDMMCFS(FSImplPtr impl) : FS(impl), _card(nullptr) {
_pin_d2 = SDMMC_D2;
_pin_d3 = SDMMC_D3;
#endif // BOARD_HAS_1BIT_SDMMC
#endif // !defined(CONFIG_IDF_TARGET_ESP32P4)
#elif SOC_SDMMC_USE_IOMUX && defined(BOARD_HAS_SDMMC) && defined(CONFIG_IDF_TARGET_ESP32)
#elif defined(SOC_SDMMC_USE_IOMUX) && defined(BOARD_HAS_SDMMC) && defined(CONFIG_IDF_TARGET_ESP32)
_pin_clk = SDMMC_SLOT1_IOMUX_PIN_NUM_CLK;
_pin_cmd = SDMMC_SLOT1_IOMUX_PIN_NUM_CMD;
_pin_d0 = SDMMC_SLOT1_IOMUX_PIN_NUM_D0;
@ -57,7 +59,9 @@ SDMMCFS::SDMMCFS(FSImplPtr impl) : FS(impl), _card(nullptr) {
_pin_d3 = SDMMC_SLOT1_IOMUX_PIN_NUM_D3;
#endif // BOARD_HAS_1BIT_SDMMC
#elif SOC_SDMMC_USE_IOMUX && defined(BOARD_HAS_SDMMC) && defined(CONFIG_IDF_TARGET_ESP32P4)
// ESP32-P4 can use either IOMUX or GPIO matrix
#elif defined(BOARD_HAS_SDMMC) && defined(CONFIG_IDF_TARGET_ESP32P4)
#if defined(BOARD_SDMMC_SLOT) && (BOARD_SDMMC_SLOT == 0)
_pin_clk = SDMMC_SLOT0_IOMUX_PIN_NUM_CLK;
_pin_cmd = SDMMC_SLOT0_IOMUX_PIN_NUM_CMD;
_pin_d0 = SDMMC_SLOT0_IOMUX_PIN_NUM_D0;
@ -66,6 +70,19 @@ SDMMCFS::SDMMCFS(FSImplPtr impl) : FS(impl), _card(nullptr) {
_pin_d2 = SDMMC_SLOT0_IOMUX_PIN_NUM_D2;
_pin_d3 = SDMMC_SLOT0_IOMUX_PIN_NUM_D3;
#endif // BOARD_HAS_1BIT_SDMMC
#else
_pin_clk = SDMMC_CLK;
_pin_cmd = SDMMC_CMD;
_pin_d0 = SDMMC_D0;
#ifndef BOARD_HAS_1BIT_SDMMC
_pin_d1 = SDMMC_D1;
_pin_d2 = SDMMC_D2;
_pin_d3 = SDMMC_D3;
#endif // BOARD_HAS_1BIT_SDMMC
#endif // BOARD_SDMMC_SLOT_NO
#endif
#if defined(SOC_SDMMC_IO_POWER_EXTERNAL) && defined(BOARD_SDMMC_POWER_CHANNEL)
_power_channel = BOARD_SDMMC_POWER_CHANNEL;
#endif
}
@ -95,7 +112,7 @@ bool SDMMCFS::setPins(int clk, int cmd, int d0, int d1, int d2, int d3) {
d2 = digitalPinToGPIONumber(d2);
d3 = digitalPinToGPIONumber(d3);
#ifdef SOC_SDMMC_USE_GPIO_MATRIX
#if defined(SOC_SDMMC_USE_GPIO_MATRIX) && !defined(CONFIG_IDF_TARGET_ESP32P4)
// SoC supports SDMMC pin configuration via GPIO matrix. Save the pins for later use in SDMMCFS::begin.
_pin_clk = (int8_t)clk;
_pin_cmd = (int8_t)cmd;
@ -116,11 +133,42 @@ bool SDMMCFS::setPins(int clk, int cmd, int d0, int d1, int d2, int d3) {
return false;
}
return true;
#elif defined(CONFIG_IDF_TARGET_ESP32P4)
#if defined(BOARD_SDMMC_SLOT) && (BOARD_SDMMC_SLOT == 0)
// ESP32-P4 can use either IOMUX or GPIO matrix
bool pins_ok =
(clk == (int)SDMMC_SLOT0_IOMUX_PIN_NUM_CLK) && (cmd == (int)SDMMC_SLOT0_IOMUX_PIN_NUM_CMD) && (d0 == (int)SDMMC_SLOT0_IOMUX_PIN_NUM_D0)
&& (((d1 == -1) && (d2 == -1) && (d3 == -1)) || ((d1 == (int)SDMMC_SLOT0_IOMUX_PIN_NUM_D1) && (d2 == (int)SDMMC_SLOT0_IOMUX_PIN_NUM_D2) && (d3 == (int)SDMMC_SLOT0_IOMUX_PIN_NUM_D3)));
if (!pins_ok) {
log_e("SDMMCFS: specified pins are not supported when using IOMUX (SDMMC SLOT 0).");
return false;
}
return true;
#else
_pin_clk = (int8_t)clk;
_pin_cmd = (int8_t)cmd;
_pin_d0 = (int8_t)d0;
_pin_d1 = (int8_t)d1;
_pin_d2 = (int8_t)d2;
_pin_d3 = (int8_t)d3;
return true;
#endif
#else
#error SoC not supported
#endif
}
#ifdef SOC_SDMMC_IO_POWER_EXTERNAL
bool SDMMCFS::setPowerChannel(int power_channel) {
if (_card != nullptr) {
log_e("SD_MMC.setPowerChannel must be called before SD_MMC.begin");
return false;
}
_power_channel = power_channel;
return true;
}
#endif
bool SDMMCFS::begin(const char *mountpoint, bool mode1bit, bool format_if_mount_failed, int sdmmc_frequency, uint8_t maxOpenFiles) {
if (_card) {
return true;
@ -135,7 +183,9 @@ bool SDMMCFS::begin(const char *mountpoint, bool mode1bit, bool format_if_mount_
}
//mount
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
#ifdef SOC_SDMMC_USE_GPIO_MATRIX
#if (defined(SOC_SDMMC_USE_GPIO_MATRIX) && !defined(CONFIG_IDF_TARGET_ESP32P4)) \
|| (defined(CONFIG_IDF_TARGET_ESP32P4) && ((defined(BOARD_SDMMC_SLOT) && (BOARD_SDMMC_SLOT == 1)) || !defined(BOARD_HAS_SDMMC)))
log_d("pin_cmd: %d, pin_clk: %d, pin_d0: %d, pin_d1: %d, pin_d2: %d, pin_d3: %d", _pin_cmd, _pin_clk, _pin_d0, _pin_d1, _pin_d2, _pin_d3);
// SoC supports SDMMC pin configuration via GPIO matrix.
// Check that the pins have been set either in the constructor or setPins function.
if (_pin_cmd == -1 || _pin_clk == -1 || _pin_d0 == -1 || (!mode1bit && (_pin_d1 == -1 || _pin_d2 == -1 || _pin_d3 == -1))) {
@ -175,7 +225,18 @@ bool SDMMCFS::begin(const char *mountpoint, bool mode1bit, bool format_if_mount_
sdmmc_host_t host = SDMMC_HOST_DEFAULT();
host.flags = SDMMC_HOST_FLAG_4BIT;
#if defined(CONFIG_IDF_TARGET_ESP32P4) && defined(BOARD_SDMMC_SLOT) && (BOARD_SDMMC_SLOT == 0)
host.slot = SDMMC_HOST_SLOT_0;
// reconfigure slot_config to remove all pins in order to use IO_MUX
slot_config = {
.cd = SDMMC_SLOT_NO_CD,
.wp = SDMMC_SLOT_NO_WP,
.width = 4,
.flags = 0,
};
#else
host.slot = SDMMC_HOST_SLOT_1;
#endif
host.max_freq_khz = sdmmc_frequency;
#ifdef BOARD_HAS_1BIT_SDMMC
mode1bit = true;
@ -186,6 +247,34 @@ bool SDMMCFS::begin(const char *mountpoint, bool mode1bit, bool format_if_mount_
}
_mode1bit = mode1bit;
#ifdef SOC_SDMMC_IO_POWER_EXTERNAL
if (_power_channel == -1) {
log_i("On-chip power channel specified, use external power for SDMMC");
} else {
sd_pwr_ctrl_ldo_config_t ldo_config = {
.ldo_chan_id = _power_channel,
};
sd_pwr_ctrl_handle_t pwr_ctrl_handle = NULL;
if (sd_pwr_ctrl_new_on_chip_ldo(&ldo_config, &pwr_ctrl_handle) != ESP_OK) {
log_e("Failed to create a new on-chip LDO power control driver");
return false;
}
host.pwr_ctrl_handle = pwr_ctrl_handle;
}
#endif
#if defined(BOARD_SDMMC_POWER_PIN)
#ifndef BOARD_SDMMC_POWER_ON_LEVEL
#error "BOARD_SDMMC_POWER_ON_LEVEL not defined, please define it in pins_arduino.h"
#endif
pinMode(BOARD_SDMMC_POWER_PIN, OUTPUT);
digitalWrite(BOARD_SDMMC_POWER_PIN, !BOARD_SDMMC_POWER_ON_LEVEL);
delay(200);
digitalWrite(BOARD_SDMMC_POWER_PIN, BOARD_SDMMC_POWER_ON_LEVEL);
perimanSetPinBusExtraType(BOARD_SDMMC_POWER_PIN, "SDMMC_POWER");
#endif
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
.format_if_mount_failed = format_if_mount_failed,
.max_files = maxOpenFiles,
@ -252,6 +341,9 @@ void SDMMCFS::end() {
perimanClearPinBus(_pin_d2);
perimanClearPinBus(_pin_d3);
}
#if defined(BOARD_SDMMC_POWER_PIN)
perimanClearPinBus(BOARD_SDMMC_POWER_PIN);
#endif
}
}

View file

@ -44,6 +44,9 @@ protected:
int8_t _pin_d1 = -1;
int8_t _pin_d2 = -1;
int8_t _pin_d3 = -1;
#ifdef SOC_SDMMC_IO_POWER_EXTERNAL
int8_t _power_channel = -1;
#endif
uint8_t _pdrv = 0xFF;
bool _mode1bit = false;
@ -51,6 +54,9 @@ public:
SDMMCFS(FSImplPtr impl);
bool setPins(int clk, int cmd, int d0);
bool setPins(int clk, int cmd, int d0, int d1, int d2, int d3);
#ifdef SOC_SDMMC_IO_POWER_EXTERNAL
bool setPowerChannel(int power_channel);
#endif
bool begin(
const char *mountpoint = "/sdcard", bool mode1bit = false, bool format_if_mount_failed = false, int sdmmc_frequency = BOARD_MAX_SDMMC_FREQ,
uint8_t maxOpenFiles = 5

View file

@ -4,15 +4,6 @@
#include <stdint.h>
#include "soc/soc_caps.h"
#define PIN_NEOPIXEL 44
// BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino
static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_NEOPIXEL;
#define BUILTIN_LED LED_BUILTIN // backward compatibility
#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN
// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite()
#define RGB_BUILTIN LED_BUILTIN
#define RGB_BRIGHTNESS 64
// BOOT_MODE 35
// BOOT_MODE2 36 pullup
@ -58,6 +49,8 @@ static const uint8_t T11 = 13;
static const uint8_t T12 = 14;
static const uint8_t T13 = 15;
/* ESP32-P4 EV Function board specific definitions */
//ETH
#define ETH_PHY_TYPE ETH_PHY_TLK110
#define ETH_PHY_ADDR 1
#define ETH_PHY_MDC 31
@ -72,4 +65,21 @@ static const uint8_t T13 = 15;
#define ETH_RMII_CLK 50
#define ETH_CLK_MODE EMAC_CLK_EXT_IN
//SDMMC
#define BOARD_HAS_SDMMC
#define BOARD_SDMMC_SLOT 0
#define BOARD_SDMMC_POWER_CHANNEL 4
#define BOARD_SDMMC_POWER_PIN 45
#define BOARD_SDMMC_POWER_ON_LEVEL LOW
//WIFI - ESP32C6
#define BOARD_HAS_SDIO_ESP_HOSTED
#define BOARD_SDIO_ESP_HOSTED_CLK 18
#define BOARD_SDIO_ESP_HOSTED_CMD 19
#define BOARD_SDIO_ESP_HOSTED_D0 14
#define BOARD_SDIO_ESP_HOSTED_D1 15
#define BOARD_SDIO_ESP_HOSTED_D2 16
#define BOARD_SDIO_ESP_HOSTED_D3 17
#define BOARD_SDIO_ESP_HOSTED_RESET 54
#endif /* Pins_Arduino_h */