3232#include " ff.h"
3333#include " esp32-hal-periman.h"
3434
35+ #if SOC_SDMMC_IO_POWER_EXTERNAL
36+ #include " sd_pwr_ctrl_by_on_chip_ldo.h"
37+ #endif
38+
3539using namespace fs ;
3640
3741SDMMCFS::SDMMCFS (FSImplPtr impl) : FS(impl), _card(nullptr ) {
38- #if !defined(CONFIG_IDF_TARGET_ESP32P4)
39- #if defined(SOC_SDMMC_USE_GPIO_MATRIX) && defined(BOARD_HAS_SDMMC)
42+ #if defined(SOC_SDMMC_USE_GPIO_MATRIX) && defined(BOARD_HAS_SDMMC) && !defined(CONFIG_IDF_TARGET_ESP32P4)
4043 _pin_clk = SDMMC_CLK;
4144 _pin_cmd = SDMMC_CMD;
4245 _pin_d0 = SDMMC_D0;
@@ -45,9 +48,8 @@ SDMMCFS::SDMMCFS(FSImplPtr impl) : FS(impl), _card(nullptr) {
4548 _pin_d2 = SDMMC_D2;
4649 _pin_d3 = SDMMC_D3;
4750#endif // BOARD_HAS_1BIT_SDMMC
48- #endif // !defined(CONFIG_IDF_TARGET_ESP32P4)
4951
50- #elif SOC_SDMMC_USE_IOMUX && defined(BOARD_HAS_SDMMC) && defined(CONFIG_IDF_TARGET_ESP32)
52+ #elif defined( SOC_SDMMC_USE_IOMUX) && defined(BOARD_HAS_SDMMC) && defined(CONFIG_IDF_TARGET_ESP32)
5153 _pin_clk = SDMMC_SLOT1_IOMUX_PIN_NUM_CLK;
5254 _pin_cmd = SDMMC_SLOT1_IOMUX_PIN_NUM_CMD;
5355 _pin_d0 = SDMMC_SLOT1_IOMUX_PIN_NUM_D0;
@@ -57,7 +59,9 @@ SDMMCFS::SDMMCFS(FSImplPtr impl) : FS(impl), _card(nullptr) {
5759 _pin_d3 = SDMMC_SLOT1_IOMUX_PIN_NUM_D3;
5860#endif // BOARD_HAS_1BIT_SDMMC
5961
60- #elif SOC_SDMMC_USE_IOMUX && defined(BOARD_HAS_SDMMC) && defined(CONFIG_IDF_TARGET_ESP32P4)
62+ // ESP32-P4 can use either IOMUX or GPIO matrix
63+ #elif defined(BOARD_HAS_SDMMC) && defined(CONFIG_IDF_TARGET_ESP32P4)
64+ #if defined(BOARD_SDMMC_SLOT) && (BOARD_SDMMC_SLOT == 0)
6165 _pin_clk = SDMMC_SLOT0_IOMUX_PIN_NUM_CLK;
6266 _pin_cmd = SDMMC_SLOT0_IOMUX_PIN_NUM_CMD;
6367 _pin_d0 = SDMMC_SLOT0_IOMUX_PIN_NUM_D0;
@@ -66,6 +70,19 @@ SDMMCFS::SDMMCFS(FSImplPtr impl) : FS(impl), _card(nullptr) {
6670 _pin_d2 = SDMMC_SLOT0_IOMUX_PIN_NUM_D2;
6771 _pin_d3 = SDMMC_SLOT0_IOMUX_PIN_NUM_D3;
6872#endif // BOARD_HAS_1BIT_SDMMC
73+ #else
74+ _pin_clk = SDMMC_CLK;
75+ _pin_cmd = SDMMC_CMD;
76+ _pin_d0 = SDMMC_D0;
77+ #ifndef BOARD_HAS_1BIT_SDMMC
78+ _pin_d1 = SDMMC_D1;
79+ _pin_d2 = SDMMC_D2;
80+ _pin_d3 = SDMMC_D3;
81+ #endif // BOARD_HAS_1BIT_SDMMC
82+ #endif // BOARD_SDMMC_SLOT_NO
83+ #endif
84+ #if defined(SOC_SDMMC_IO_POWER_EXTERNAL) && defined(BOARD_SDMMC_POWER_CHANNEL)
85+ _power_channel = BOARD_SDMMC_POWER_CHANNEL;
6986#endif
7087}
7188
@@ -95,7 +112,7 @@ bool SDMMCFS::setPins(int clk, int cmd, int d0, int d1, int d2, int d3) {
95112 d2 = digitalPinToGPIONumber (d2);
96113 d3 = digitalPinToGPIONumber (d3);
97114
98- #ifdef SOC_SDMMC_USE_GPIO_MATRIX
115+ #if defined( SOC_SDMMC_USE_GPIO_MATRIX) && !defined(CONFIG_IDF_TARGET_ESP32P4)
99116 // SoC supports SDMMC pin configuration via GPIO matrix. Save the pins for later use in SDMMCFS::begin.
100117 _pin_clk = (int8_t )clk;
101118 _pin_cmd = (int8_t )cmd;
@@ -116,11 +133,42 @@ bool SDMMCFS::setPins(int clk, int cmd, int d0, int d1, int d2, int d3) {
116133 return false ;
117134 }
118135 return true ;
136+ #elif defined(CONFIG_IDF_TARGET_ESP32P4)
137+ #if defined(BOARD_SDMMC_SLOT) && (BOARD_SDMMC_SLOT == 0)
138+ // ESP32-P4 can use either IOMUX or GPIO matrix
139+ bool pins_ok =
140+ (clk == (int )SDMMC_SLOT0_IOMUX_PIN_NUM_CLK) && (cmd == (int )SDMMC_SLOT0_IOMUX_PIN_NUM_CMD) && (d0 == (int )SDMMC_SLOT0_IOMUX_PIN_NUM_D0)
141+ && (((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)));
142+ if (!pins_ok) {
143+ log_e (" SDMMCFS: specified pins are not supported when using IOMUX (SDMMC SLOT 0)." );
144+ return false ;
145+ }
146+ return true ;
147+ #else
148+ _pin_clk = (int8_t )clk;
149+ _pin_cmd = (int8_t )cmd;
150+ _pin_d0 = (int8_t )d0;
151+ _pin_d1 = (int8_t )d1;
152+ _pin_d2 = (int8_t )d2;
153+ _pin_d3 = (int8_t )d3;
154+ return true ;
155+ #endif
119156#else
120157#error SoC not supported
121158#endif
122159}
123160
161+ #ifdef SOC_SDMMC_IO_POWER_EXTERNAL
162+ bool SDMMCFS::setPowerChannel (int power_channel) {
163+ if (_card != nullptr ) {
164+ log_e (" SD_MMC.setPowerChannel must be called before SD_MMC.begin" );
165+ return false ;
166+ }
167+ _power_channel = power_channel;
168+ return true ;
169+ }
170+ #endif
171+
124172bool SDMMCFS::begin (const char *mountpoint, bool mode1bit, bool format_if_mount_failed, int sdmmc_frequency, uint8_t maxOpenFiles) {
125173 if (_card) {
126174 return true ;
@@ -135,7 +183,9 @@ bool SDMMCFS::begin(const char *mountpoint, bool mode1bit, bool format_if_mount_
135183 }
136184 // mount
137185 sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT ();
138- #ifdef SOC_SDMMC_USE_GPIO_MATRIX
186+ #if (defined(SOC_SDMMC_USE_GPIO_MATRIX) && !defined(CONFIG_IDF_TARGET_ESP32P4)) \
187+ || (defined (CONFIG_IDF_TARGET_ESP32P4) && ((defined (BOARD_SDMMC_SLOT) && (BOARD_SDMMC_SLOT == 1 )) || !defined (BOARD_HAS_SDMMC)))
188+ 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);
139189 // SoC supports SDMMC pin configuration via GPIO matrix.
140190 // Check that the pins have been set either in the constructor or setPins function.
141191 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_
175225
176226 sdmmc_host_t host = SDMMC_HOST_DEFAULT ();
177227 host.flags = SDMMC_HOST_FLAG_4BIT;
228+ #if defined(CONFIG_IDF_TARGET_ESP32P4) && defined(BOARD_SDMMC_SLOT) && (BOARD_SDMMC_SLOT == 0)
229+ host.slot = SDMMC_HOST_SLOT_0;
230+ // reconfigure slot_config to remove all pins in order to use IO_MUX
231+ slot_config = {
232+ .cd = SDMMC_SLOT_NO_CD,
233+ .wp = SDMMC_SLOT_NO_WP,
234+ .width = 4 ,
235+ .flags = 0 ,
236+ };
237+ #else
178238 host.slot = SDMMC_HOST_SLOT_1;
239+ #endif
179240 host.max_freq_khz = sdmmc_frequency;
180241#ifdef BOARD_HAS_1BIT_SDMMC
181242 mode1bit = true ;
@@ -186,6 +247,34 @@ bool SDMMCFS::begin(const char *mountpoint, bool mode1bit, bool format_if_mount_
186247 }
187248 _mode1bit = mode1bit;
188249
250+ #ifdef SOC_SDMMC_IO_POWER_EXTERNAL
251+ if (_power_channel == -1 ) {
252+ log_i (" On-chip power channel specified, use external power for SDMMC" );
253+ } else {
254+ sd_pwr_ctrl_ldo_config_t ldo_config = {
255+ .ldo_chan_id = _power_channel,
256+ };
257+ sd_pwr_ctrl_handle_t pwr_ctrl_handle = NULL ;
258+
259+ if (sd_pwr_ctrl_new_on_chip_ldo (&ldo_config, &pwr_ctrl_handle) != ESP_OK) {
260+ log_e (" Failed to create a new on-chip LDO power control driver" );
261+ return false ;
262+ }
263+ host.pwr_ctrl_handle = pwr_ctrl_handle;
264+ }
265+ #endif
266+
267+ #if defined(BOARD_SDMMC_POWER_PIN)
268+ #ifndef BOARD_SDMMC_POWER_ON_LEVEL
269+ #error "BOARD_SDMMC_POWER_ON_LEVEL not defined, please define it in pins_arduino.h"
270+ #endif
271+ pinMode (BOARD_SDMMC_POWER_PIN, OUTPUT);
272+ digitalWrite (BOARD_SDMMC_POWER_PIN, !BOARD_SDMMC_POWER_ON_LEVEL);
273+ delay (200 );
274+ digitalWrite (BOARD_SDMMC_POWER_PIN, BOARD_SDMMC_POWER_ON_LEVEL);
275+ perimanSetPinBusExtraType (BOARD_SDMMC_POWER_PIN, " SDMMC_POWER" );
276+ #endif
277+
189278 esp_vfs_fat_sdmmc_mount_config_t mount_config = {
190279 .format_if_mount_failed = format_if_mount_failed,
191280 .max_files = maxOpenFiles,
@@ -252,6 +341,9 @@ void SDMMCFS::end() {
252341 perimanClearPinBus (_pin_d2);
253342 perimanClearPinBus (_pin_d3);
254343 }
344+ #if defined(BOARD_SDMMC_POWER_PIN)
345+ perimanClearPinBus (BOARD_SDMMC_POWER_PIN);
346+ #endif
255347 }
256348}
257349
0 commit comments