Skip to content

Commit 5b12c98

Browse files
committed
feat: Add example code
To be squashed
1 parent c72f40f commit 5b12c98

File tree

10 files changed

+466
-0
lines changed

10 files changed

+466
-0
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
cmake_minimum_required(VERSION 3.16)
2+
3+
set(COMPONENTS main)
4+
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
5+
project(esp_ext_part_tables_example_basic)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# esp_ext_part_tables basic example
2+
3+
This example demonstrates how to use an ESP32 to read and parse the Master Boot Record (MBR) from a (micro)SD card. It shows how to extract and display information about the card's partitions, such as their type, size, and starting sector, using the ESP-IDF framework.
4+
5+
## Requirements
6+
7+
- any ESP32 board which supports SPI with a (micro)SD card slot or breakout board connected
8+
- formatted (micro)SD card using MBR (not GPT) as a partition table
9+
10+
## Build and Flash
11+
12+
The example runs on any ESP development board with SD card connected via SPI (use `idf.py menuconfig` -> `Example config` to set used GPIO pins). For example, to build and run the code on ESP32-S3, use:
13+
14+
```
15+
idf.py set-target esp32s3
16+
idf.py menuconfig
17+
idf.py build flash monitor
18+
```
19+
20+
NOTE 1: This example uses SDSPI instead of SDMMC to connect to SD card due to more ESP32 devices supporting it but it doesn't matter which one one you use in your project to load the first sector containing MBR.
21+
22+
NOTE 2: ESP-IDF 5.1 or newer enviroment must be set properly before running the example.
23+
24+
## Example output
25+
26+
MicroSD card used in the example showcase has capacity 64GiB and was formatted using Windows Disk Management program to two ~32GiB FAT32 partitions as seen in the picture:
27+
28+
![Screenshot of Disk Management Windows program showing removable Disk 0 (a microSD card) containing 2 FAT32 partitions both roughly 30GB is size](/esp_ext_part_tables/examples/basic/assets/two_fat_partitions.png)
29+
30+
The example code parsed the MBR and printed the loaded partition information (`type 4` corresponds to `ESP_EXT_PART_TYPE_FAT32` in `esp_ext_part_type_known_t` enum, etc.). The second task generated MBR from `esp_ext_part_list_t` definition and then parsed it again and printed the output.
31+
32+
```log
33+
I (275) esp_ext_part_tables_example_basic: Example started
34+
I (275) esp_ext_part_tables_example_basic: Starting MBR parsing example task
35+
I (335) esp_ext_part_tables_example_basic: MBR loaded successfully
36+
I (335) esp_ext_part_tables_example_basic: MBR parsed successfully
37+
Partition 0:
38+
LBA start sector: 2048, address: 1048576,
39+
sector count: 59392000, size: 30408704000,
40+
type: 4
41+
42+
Partition 1:
43+
LBA start sector: 59394048, address: 30409752576,
44+
sector count: 62746624, size: 32126271488,
45+
type: 4
46+
47+
I (365) esp_ext_part_tables_example_basic: Starting MBR generation example task
48+
I (365) esp_ext_part_tables_example_basic: MBR generated successfully
49+
Partition 0:
50+
LBA start sector: 2048, address: 1048576,
51+
sector count: 7953, size: 4071936,
52+
type: 2
53+
54+
Partition 1:
55+
LBA start sector: 10240, address: 5242880,
56+
sector count: 10240, size: 5242880,
57+
type: 2
58+
59+
I (395) esp_ext_part_tables_example_basic: Example ended
60+
```
61+
62+
Your output will be different based on (micro)SD card used, partitioning and formatting applied.
63+
64+
## Documentation
65+
66+
See the esp_ext_part_tables component's README.md file.
33.3 KB
Loading
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
idf_component_register(
2+
SRCS "main.c" "example_utils.c"
3+
REQUIRES driver sdmmc
4+
)
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
menu "Example Configuration"
2+
3+
config EXAMPLE_PIN_MOSI
4+
int "MOSI GPIO number"
5+
default 15 if IDF_TARGET_ESP32
6+
default 35 if IDF_TARGET_ESP32S2
7+
default 4 if IDF_TARGET_ESP32S3
8+
default 5 if IDF_TARGET_ESP32H2
9+
default 36 if IDF_TARGET_ESP32P4
10+
default 4 # C3 and others
11+
12+
config EXAMPLE_PIN_MISO
13+
int "MISO GPIO number"
14+
default 2 if IDF_TARGET_ESP32
15+
default 37 if IDF_TARGET_ESP32S2
16+
default 5 if IDF_TARGET_ESP32S3
17+
default 0 if IDF_TARGET_ESP32H2
18+
default 47 if IDF_TARGET_ESP32P4
19+
default 6 # C3 and others
20+
21+
config EXAMPLE_PIN_CLK
22+
int "CLK GPIO number"
23+
default 14 if IDF_TARGET_ESP32
24+
default 36 if IDF_TARGET_ESP32S2
25+
default 2 if IDF_TARGET_ESP32S3
26+
default 4 if IDF_TARGET_ESP32H2
27+
default 53 if IDF_TARGET_ESP32P4
28+
default 5 # C3 and others
29+
30+
config EXAMPLE_PIN_CS
31+
int "CS GPIO number"
32+
default 13 if IDF_TARGET_ESP32
33+
default 34 if IDF_TARGET_ESP32S2
34+
default 8 if IDF_TARGET_ESP32S3
35+
default 33 if IDF_TARGET_ESP32P4
36+
default 1 # C3 and others
37+
38+
config EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
39+
depends on SOC_SDMMC_IO_POWER_EXTERNAL
40+
bool "SD power supply comes from internal LDO IO (READ HELP!)"
41+
default n
42+
help
43+
Only needed when the SD card is connected to specific IO pins which can be used for high-speed SDMMC.
44+
Please read the schematic first and check if the SD VDD is connected to any internal LDO output.
45+
Unselect this option if the SD card is powered by an external power supply.
46+
47+
config EXAMPLE_SD_PWR_CTRL_LDO_IO_ID
48+
depends on SOC_SDMMC_IO_POWER_EXTERNAL && EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
49+
int "LDO ID"
50+
default 4 if IDF_TARGET_ESP32P4
51+
help
52+
Please read the schematic first and input your LDO ID.
53+
endmenu
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <stdio.h>
8+
#include <stdlib.h>
9+
#include <stdint.h>
10+
#include "esp_err.h"
11+
#include "esp_log.h"
12+
#include "driver/sdspi_host.h"
13+
#include "sdmmc_cmd.h"
14+
#if SOC_SDMMC_IO_POWER_EXTERNAL
15+
#include "sd_pwr_ctrl_by_on_chip_ldo.h"
16+
#endif
17+
18+
static const char *TAG = "esp_ext_part_tables_example_basic_utils";
19+
20+
#define PIN_NUM_MISO CONFIG_EXAMPLE_PIN_MISO
21+
#define PIN_NUM_MOSI CONFIG_EXAMPLE_PIN_MOSI
22+
#define PIN_NUM_CLK CONFIG_EXAMPLE_PIN_CLK
23+
#define PIN_NUM_CS CONFIG_EXAMPLE_PIN_CS
24+
25+
esp_err_t load_first_sector_from_sd_card(void* mbr_buffer)
26+
{
27+
// This function loads the first sector (MBR) from the SD card into the provided buffer
28+
// It uses SDSPI but can be adapted for SDMMC as well
29+
esp_err_t ret = ESP_OK;
30+
sdmmc_host_t host = SDSPI_HOST_DEFAULT();
31+
32+
// For SoCs where the SD power can be supplied both via an internal or external (e.g. on-board LDO) power supply.
33+
// When using specific IO pins (which can be used for ultra high-speed SDMMC) to connect to the SD card
34+
// and the internal LDO power supply, we need to initialize the power supply first.
35+
#if CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
36+
sd_pwr_ctrl_ldo_config_t ldo_config = {
37+
.ldo_chan_id = CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_IO_ID,
38+
};
39+
sd_pwr_ctrl_handle_t pwr_ctrl_handle = NULL;
40+
41+
ret = sd_pwr_ctrl_new_on_chip_ldo(&ldo_config, &pwr_ctrl_handle);
42+
if (ret != ESP_OK) {
43+
ESP_LOGE(TAG, "Failed to create a new on-chip LDO power control driver");
44+
return;
45+
}
46+
host.pwr_ctrl_handle = pwr_ctrl_handle;
47+
#endif
48+
49+
spi_bus_config_t bus_cfg = {
50+
.mosi_io_num = PIN_NUM_MOSI,
51+
.miso_io_num = PIN_NUM_MISO,
52+
.sclk_io_num = PIN_NUM_CLK,
53+
.quadwp_io_num = -1,
54+
.quadhd_io_num = -1,
55+
.max_transfer_sz = 4000,
56+
};
57+
58+
ret = spi_bus_initialize(host.slot, &bus_cfg, SDSPI_DEFAULT_DMA);
59+
if (ret != ESP_OK) {
60+
ESP_LOGE(TAG, "Failed to initialize bus.");
61+
return ret;
62+
}
63+
64+
sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
65+
slot_config.gpio_cs = PIN_NUM_CS;
66+
slot_config.host_id = host.slot;
67+
68+
ret = host.init();
69+
if (ret != ESP_OK) {
70+
ESP_LOGE(TAG, "Failed to initialize host.");
71+
spi_bus_free(host.slot);
72+
return ret;
73+
}
74+
75+
int slot = -1;
76+
ret = sdspi_host_init_device((const sdspi_device_config_t*)&slot_config, &slot);
77+
if (ret != ESP_OK) {
78+
ESP_LOGE(TAG, "Failed to initialize SPI device.");
79+
spi_bus_free(host.slot);
80+
return ret;
81+
}
82+
host.slot = slot;
83+
84+
sdmmc_card_t card = {0};
85+
ret = sdmmc_card_init(&host, &card);
86+
if (ret != ESP_OK) {
87+
ESP_LOGE(TAG, "Failed to initialize SD card.");
88+
spi_bus_free(host.slot);
89+
return ret;
90+
}
91+
92+
ret = sdmmc_read_sectors(&card, mbr_buffer, 0, 1);
93+
if (ret != ESP_OK) {
94+
ESP_LOGE(TAG, "Failed to read first sector from SD card.");
95+
spi_bus_free(host.slot);
96+
return ret;
97+
}
98+
99+
return ESP_OK;
100+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#pragma once
8+
9+
#include "esp_err.h"
10+
11+
#ifdef __cplusplus
12+
extern "C" {
13+
#endif
14+
15+
esp_err_t load_first_sector_from_sd_card(void* mbr_buffer);
16+
17+
#ifdef __cplusplus
18+
}
19+
#endif
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
dependencies:
2+
esp_ext_part_tables:
3+
version: "*"
4+
override_path: '../../..'

0 commit comments

Comments
 (0)