Skip to content
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

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

Merged
merged 17 commits into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
20 changes: 13 additions & 7 deletions libraries/SD_MMC/examples/SDMMC_Test/SDMMC_Test.ino
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -262,4 +266,6 @@ void setup() {
Serial.printf("Used space: %lluMB\n", SD_MMC.usedBytes() / (1024 * 1024));
}

void loop() {}
void loop() {
delay(10);
}
1 change: 1 addition & 0 deletions libraries/SD_MMC/examples/SDMMC_time/SDMMC_time.ino
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down
106 changes: 99 additions & 7 deletions libraries/SD_MMC/src/SD_MMC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this actually work? IIUC, the current sdmmc driver expects all pins to be set to 0 for IOMUX slots.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need the pins for Peripheral manager.
Later the config is cleared, as the SDMMC_SLOT_CONFIG_DEFAULT for P4 is setting the pins in the config.

sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();

#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

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For P4 it will be always this config:

#define SDMMC_SLOT_CONFIG_DEFAULT() {\
    .clk = GPIO_NUM_43, \
    .cmd = GPIO_NUM_44, \
    .d0 = GPIO_NUM_39, \
    .d1 = GPIO_NUM_40, \
    .d2 = GPIO_NUM_41, \
    .d3 = GPIO_NUM_42, \
    .d4 = GPIO_NUM_45, \
    .d5 = GPIO_NUM_46, \
    .d6 = GPIO_NUM_47, \
    .d7 = GPIO_NUM_48, \
    .cd = SDMMC_SLOT_NO_CD, \
    .wp = SDMMC_SLOT_NO_WP, \
    .width   = SDMMC_SLOT_WIDTH_DEFAULT, \
    .flags = 0, \
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As both IOMUX and GPIO Matrix are supported, this will never be used for P4.

#if SOC_SDMMC_USE_IOMUX && !SOC_SDMMC_USE_GPIO_MATRIX

/**
 * Macro defining default configuration of SDMMC host slot
 */
#define SDMMC_SLOT_CONFIG_DEFAULT() {\
    .cd = SDMMC_SLOT_NO_CD, \
    .wp = SDMMC_SLOT_NO_WP, \
    .width   = SDMMC_SLOT_WIDTH_DEFAULT, \
    .flags = 0, \
}

_pin_cmd = SDMMC_SLOT0_IOMUX_PIN_NUM_CMD;
_pin_d0 = SDMMC_SLOT0_IOMUX_PIN_NUM_D0;
Expand All @@ -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
}

Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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))) {
Expand Down Expand Up @@ -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;
Expand All @@ -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,
Expand Down Expand Up @@ -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
}
}

Expand Down
6 changes: 6 additions & 0 deletions libraries/SD_MMC/src/SD_MMC.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,19 @@ class SDMMCFS : public FS {
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;

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
Expand Down
28 changes: 19 additions & 9 deletions variants/esp32p4/pins_arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand All @@ -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 */
Loading