-
Notifications
You must be signed in to change notification settings - Fork 7.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- split test cases into separate files - added a component with information about dev. boards - added a console application to run the tests - added commands for lower level hacking/experimentation
- Loading branch information
Showing
32 changed files
with
2,342 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps | ||
|
||
components/sdmmc/test_apps: | ||
disable: | ||
- if: IDF_TARGET in ["esp32h2"] | ||
temporary: true | ||
reason: Console component not supported on H2 yet | ||
disable_test: | ||
- if: IDF_TARGET not in ["esp32", "esp32s2", "esp32c3"] | ||
temporary: true | ||
reason: No runners for other targets yet |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
cmake_minimum_required(VERSION 3.16) | ||
|
||
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/examples/system/console/advanced/components") | ||
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/unit-test-app/components") | ||
set(COMPONENTS main) | ||
|
||
include($ENV{IDF_PATH}/tools/cmake/project.cmake) | ||
project(sdmmc_test_console) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 | | ||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | | ||
|
||
# SDMMC Test Application | ||
|
||
This app is used to test the SDMMC protocol layer (in `sdmmc` component), as well as SDMMC and SDSPI drivers (in `driver` component). | ||
|
||
The app serves two purposes: | ||
|
||
1. It allows various Unity test cases for SDMMC protocol layer features: probing, data transfer, etc. | ||
2. It also allows running lower level operations from the console, which makes it useful as a debugging/hacking/experimentation tool when investigating SDMMC issues. | ||
- Initializing the SDMMC host in various modes | ||
- Probing the card | ||
- (more to come: sending commands, reading/writing data, etc.) | ||
|
||
## SDMMC test app code overview | ||
|
||
The app consists of several components: | ||
- `main` — small amount of code to initialize the console and register all the commands. | ||
- `components/cmd_unity` — console command to run Unity tests. | ||
- `components/cmd_sdmmc` — console commands for SDMMC low-level operations. | ||
- `components/sdmmc_test_board` — contains pin mappings for various development boards, and APIs for tests to access them. | ||
- `components/sdmmc_test` — contains the actual test cases. | ||
|
||
## Supported boards | ||
|
||
* ESP32-WROVER-KIT | ||
* ESP32 eMMC test board (black board with two SD card slots and eMMC) | ||
* ESP32-S3 USB_OTG v1. (Also works with an older ESP32-S2 variant of the board.) | ||
* ESP32-S3 eMMC test board (white board with two SD card slots and eMMC) | ||
* ESP32-S3-EYE | ||
* Breakout board for ESP32-C3 DevKitM-1 | ||
* Custom board definition: specify the pin mapping in `menuconfig`. | ||
|
||
## Using the app | ||
|
||
### Select the target, configure, build and flash the app | ||
|
||
1. Choose the chip target, and open menuconfig: | ||
```bash | ||
idf.py set-target esp32 | ||
idf.py menuconfig | ||
``` | ||
2. Select the development board in `SDMMC Test Board Configuration` menu. This will select the correct pins for the SD card slot on the board. | ||
3. Save the configuration and exit menuconfig. | ||
4. Build the app: | ||
```bash | ||
idf.py build | ||
``` | ||
5. Flash and monitor: | ||
```bash | ||
idf.py flash monitor | ||
``` | ||
|
||
### Advanced: multiple build configurations side-by-side | ||
|
||
It is often useful to verify changes in `sdmmc` component on multiple chips or development boards. To do this, it is possible to build the app multiple times, with different configurations, keeping the builds in separate directories. | ||
|
||
1. Build the app for the first target. This command does multiple things: selects the target, sets the build directory to `build_esp32`, and puts the sdkconfig file into the build directory: | ||
```bash | ||
idf.py -D IDF_TARGET=esp32 -B build_esp32 -D SDKCONFIG=build_esp32/sdkconfig build | ||
``` | ||
2. Flash and monitor. Note that the build directory has to be specified with `-B` option: | ||
```bash | ||
idf.py -B build_esp32 flash monitor | ||
``` | ||
3. Now you can build the app for the second target in another build directory: | ||
```bash | ||
idf.py -D IDF_TARGET=esp32s3 -B build_esp32s3 -D SDKCONFIG=build_esp32s3/sdkconfig build | ||
``` | ||
4. Flash and monitor, again specifying the build directory: | ||
```bash | ||
idf.py -B build_esp32s3 flash monitor | ||
``` | ||
|
||
Compared to the `idf.py set-target` approach, this method allows keeping multiple build configurations side-by-side, and switching between them easily. If you have multiple terminal windows open, you can use one window per board. Set ESPPORT environment variable to the correct serial port in each window, and flash and monitor the app in each window with the corresponding build directory (`-B`) argument. | ||
|
||
### Console commands | ||
|
||
The app supports the following console commands: | ||
|
||
- Common system commands: `help`, `restart`, `version`, `free`, `heap` | ||
- Log control: `log_level <tag> <level>` — dynamically change the log level for a given tag. For example, `log_level sdmmc_req debug` will enable debug logging in sdmmc_transaction.c | ||
- Running unit tests: `test [index|name|tag|*]`. | ||
- If no argument is given, prints the list of available tests. | ||
- If a test index is given, runs the test with that index. | ||
- If a test name is given, runs the test with that name. | ||
- If a test tag is given, runs all tests with that tag. You can negate the tag by prefixing it with `!`, for example `test ![sdspi]` will run all tests except those tagged with `[sdspi]`. | ||
- SDMMC low-level commands: `sdmmc_host_init`, `sdmmc_host_deinit`, `card_init`, `card_info`. Refer to the `help` output for more details. | ||
|
||
As most other IDF console applications, the app supports line editing, commands history and tab completion. | ||
|
||
### Running test cases | ||
|
||
When running the tests, keep in mind that once an SD card has been initialized in SPI mode, it cannot be re-initalized in SD mode without first powering it off. This means that on boards without an SD card power control circuit, it is not possible to run all the tests in one go with `test *` command. Run SDMMC tests first, then SDSPI tests: `test [sdmmc]` and then `test [sdspi]`. If you need to run SDMMC test again, power cycle the card first. | ||
|
||
On chips without an SDMMC host controller only SDSPI tests are compiled. In this case, `test *` can be used to run all tests. | ||
|
||
### Skipped tests | ||
|
||
To make the app compatible with various development boards without having lots of ifdefs in test cases, the tests will be ignored if the board is not compatible with the test case. For example, on boards with just one SD card slot (Slot 1), every test which uses Slot 0 is skipped. | ||
|
||
For example, when running sdspi tests on ESP32-WROVER-KIT you will see something like this: | ||
``` | ||
12 Tests 0 Failures 5 Ignored | ||
``` | ||
|
||
This means that the 5 tests which use Slot 0 were skipped. |
4 changes: 4 additions & 0 deletions
4
components/sdmmc/test_apps/sdmmc_console/components/cmd_sdmmc/CMakeLists.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
idf_component_register(SRCS cmd_sdmmc.c | ||
INCLUDE_DIRS . | ||
PRIV_REQUIRES console sdmmc sdmmc_test_board | ||
) |
209 changes: 209 additions & 0 deletions
209
components/sdmmc/test_apps/sdmmc_console/components/cmd_sdmmc/cmd_sdmmc.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,209 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* SDMMC related commands for the console application. | ||
*/ | ||
#include <stdio.h> | ||
#include <ctype.h> | ||
#include "esp_log.h" | ||
#include "esp_check.h" | ||
#include "esp_console.h" | ||
#include "soc/soc_caps.h" | ||
#include "driver/sdmmc_defs.h" | ||
#include "driver/sdmmc_types.h" | ||
#include "sdmmc_cmd.h" | ||
#ifdef SOC_SDMMC_HOST_SUPPORTED | ||
#include "driver/sdmmc_host.h" | ||
#endif // SOC_SDMMC_HOST_SUPPORTED | ||
#include "driver/sdspi_host.h" | ||
#include "argtable3/argtable3.h" | ||
#include "sdmmc_test_board.h" | ||
#include "cmd_sdmmc.h" | ||
|
||
|
||
static const char* TAG = "cmd_sdmmc"; | ||
static sdmmc_host_t s_host; | ||
static sdmmc_card_t s_card; | ||
|
||
|
||
/** ========== SDMMC host related commands ========== */ | ||
#ifdef SOC_SDMMC_HOST_SUPPORTED | ||
|
||
static void register_sdmmc_host_init(void); | ||
static void register_sdmmc_host_deinit(void); | ||
|
||
void register_sdmmc_host(void) | ||
{ | ||
register_sdmmc_host_init(); | ||
register_sdmmc_host_deinit(); | ||
} | ||
|
||
/** ========== sdmmc_host_init command ========== */ | ||
|
||
static struct { | ||
struct arg_int *slot; | ||
struct arg_lit *hs; | ||
struct arg_lit *ddr; | ||
struct arg_int *freq; | ||
struct arg_int *width; | ||
struct arg_end *end; | ||
} sdmmc_host_init_args; | ||
|
||
static int sdmmc_host_init_handler(int argc, char **argv) | ||
{ | ||
int nerrors = arg_parse(argc, argv, (void **) &sdmmc_host_init_args); | ||
if (nerrors != 0) { | ||
arg_print_errors(stderr, sdmmc_host_init_args.end, argv[0]); | ||
return 1; | ||
} | ||
|
||
esp_err_t err = sdmmc_host_init(); | ||
if (err == ESP_ERR_INVALID_STATE) { | ||
/* already initialized */ | ||
} else if (err != ESP_OK) { | ||
ESP_LOGE(TAG, "sdmmc_host_init: error 0x%x (%s)", err, esp_err_to_name(err)); | ||
return 1; | ||
} | ||
|
||
int slot = 1; | ||
if (sdmmc_host_init_args.slot->count > 0) { | ||
slot = sdmmc_host_init_args.slot->ival[0]; | ||
} | ||
|
||
s_host = (sdmmc_host_t) SDMMC_HOST_DEFAULT(); | ||
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); | ||
sdmmc_test_board_get_config_sdmmc(slot, &s_host, &slot_config); | ||
|
||
if (sdmmc_host_init_args.hs->count > 0) { | ||
s_host.max_freq_khz = SDMMC_FREQ_HIGHSPEED; | ||
} | ||
if (sdmmc_host_init_args.ddr->count > 0) { | ||
s_host.flags |= SDMMC_HOST_FLAG_DDR; | ||
} else { | ||
s_host.flags &= ~SDMMC_HOST_FLAG_DDR; | ||
} | ||
if (sdmmc_host_init_args.freq->count > 0) { | ||
s_host.max_freq_khz = sdmmc_host_init_args.freq->ival[0]; | ||
} | ||
if (sdmmc_host_init_args.width->count > 0) { | ||
slot_config.width = sdmmc_host_init_args.width->ival[0]; | ||
} | ||
err = sdmmc_host_init_slot(slot, &slot_config); | ||
if (err != ESP_OK) { | ||
ESP_LOGE(TAG, "sdmmc_host_init_slot: error 0x%x (%s)", err, esp_err_to_name(err)); | ||
return 1; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static void register_sdmmc_host_init(void) | ||
{ | ||
sdmmc_host_init_args.slot = arg_int0("s", "slot", "<0|1>", "SDMMC slot number"); | ||
sdmmc_host_init_args.hs = arg_lit0(NULL, "hs", "High-speed mode"); | ||
sdmmc_host_init_args.ddr = arg_lit0(NULL, "ddr", "DDR mode"); | ||
sdmmc_host_init_args.freq = arg_int0("f", "freq", "<kHz>", "Bus frequency in kHz"); | ||
sdmmc_host_init_args.width = arg_int0("w", "width", "<1|4|8>", "Bus width (1, 4, or 8 lines)"); | ||
sdmmc_host_init_args.end = arg_end(5); | ||
|
||
const esp_console_cmd_t cmd = { | ||
.command = "sdmmc_host_init", | ||
.help = "Initialize SDMMC host driver", | ||
.hint = NULL, | ||
.func = &sdmmc_host_init_handler, | ||
.argtable = &sdmmc_host_init_args | ||
}; | ||
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); | ||
} | ||
|
||
/** ========== sdmmc_host_deinit command ========== */ | ||
|
||
static int sdmmc_host_deinit_handler(int argc, char **argv) | ||
{ | ||
esp_err_t err = sdmmc_host_deinit(); | ||
if (err != ESP_OK) { | ||
ESP_LOGE(TAG, "sdmmc_host_deinit: error 0x%x (%s)", err, esp_err_to_name(err)); | ||
return 1; | ||
} | ||
return 0; | ||
} | ||
|
||
static void register_sdmmc_host_deinit(void) | ||
{ | ||
const esp_console_cmd_t cmd = { | ||
.command = "sdmmc_host_deinit", | ||
.help = "Deinitialize SDMMC host driver", | ||
.hint = NULL, | ||
.func = &sdmmc_host_deinit_handler | ||
}; | ||
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); | ||
} | ||
|
||
#endif // SOC_SDMMC_HOST_SUPPORTED | ||
/** ========== end of SDMMC host related commands ========== */ | ||
|
||
/** ========== SDSPI host related commands ========== */ | ||
|
||
/* TODO */ | ||
|
||
/** ========== end of SDSPI host related commands ========== */ | ||
|
||
/** ========== Common sdmmc protocol commands ========== */ | ||
|
||
static void register_sdmmc_card_init(void); | ||
static void register_sdmmc_card_info(void); | ||
|
||
void register_sdmmc_common(void) | ||
{ | ||
register_sdmmc_card_init(); | ||
register_sdmmc_card_info(); | ||
} | ||
|
||
static int sdmmc_card_init_handler(int argc, char **argv) | ||
{ | ||
/* In case the card was already initialized: reset the host to the default settings. | ||
* This could be moved to sdmmc_card_init. | ||
*/ | ||
esp_err_t err = s_host.set_card_clk(s_host.slot, SDMMC_FREQ_PROBING); | ||
ESP_RETURN_ON_ERROR(err, TAG, "set_card_clk: error 0x%x (%s)", err, esp_err_to_name(err)); | ||
s_host.set_bus_width(s_host.slot, 1); | ||
ESP_RETURN_ON_ERROR(err, TAG, "set_bus_width: error 0x%x (%s)", err, esp_err_to_name(err)); | ||
s_host.set_bus_ddr_mode(s_host.slot, false); | ||
ESP_RETURN_ON_ERROR(err, TAG, "set_bus_ddr_mode: error 0x%x (%s)", err, esp_err_to_name(err)); | ||
|
||
err = sdmmc_card_init(&s_host, &s_card); | ||
ESP_RETURN_ON_ERROR(err, TAG, "sdmmc_card_init: error 0x%x (%s)", err, esp_err_to_name(err)); | ||
return 0; | ||
} | ||
|
||
static void register_sdmmc_card_init(void) | ||
{ | ||
const esp_console_cmd_t cmd = { | ||
.command = "card_init", | ||
.help = "Initialize the card using sdmmc_card_init function", | ||
.hint = NULL, | ||
.func = &sdmmc_card_init_handler | ||
}; | ||
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); | ||
} | ||
|
||
static int sdmmc_card_info_handler(int argc, char** argv) | ||
{ | ||
sdmmc_card_print_info(stdout, &s_card); | ||
return 0; | ||
} | ||
|
||
static void register_sdmmc_card_info(void) | ||
{ | ||
const esp_console_cmd_t cmd = { | ||
.command = "card_info", | ||
.help = "Print information about the card to the console", | ||
.hint = NULL, | ||
.func = &sdmmc_card_info_handler | ||
}; | ||
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); | ||
} | ||
|
||
/** ========== End of common sdmmc protocol commands ========== */ |
28 changes: 28 additions & 0 deletions
28
components/sdmmc/test_apps/sdmmc_console/components/cmd_sdmmc/cmd_sdmmc.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
#pragma once | ||
|
||
#include "soc/soc_caps.h" | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
#if SOC_SDMMC_HOST_SUPPORTED | ||
/** | ||
* @brief Register console commands related to SDMMC host driver | ||
*/ | ||
void register_sdmmc_host(void); | ||
#endif | ||
|
||
/** | ||
* @brief Register console commands related to sdmmc protocol layer | ||
*/ | ||
void register_sdmmc_common(void); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif |
5 changes: 5 additions & 0 deletions
5
components/sdmmc/test_apps/sdmmc_console/components/cmd_unity/CMakeLists.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
idf_component_register( | ||
SRCS cmd_unity.c | ||
INCLUDE_DIRS . | ||
PRIV_REQUIRES unity console | ||
) |
Oops, something went wrong.