This repository holds the tests, samples and SoC files for the Espressif's Built-In Self Test (BIST) library.
The BIST library is a cmake library with a set of routines designed to verify the integrity and proper operation of the hardware components in Espressif's SoCs. The library includes tests for the CPU registers, configuration and status registers (CSRs), volatile memory, non-volatile memory, cpu stack, program counter (PC), and clock sources. The tests are intended for use in safety-critical applications that require compliance with the IEC 60730 Class B standard.
This repository includes the necessary files to build an application that runs the BIST library tests.
- ESP32-C3
This repository is licensed under the LGPL-3.0 license. For more information, see the LICENSE file.
To download the repository, execute the following command:
git clone --recursive https://github.com/espressif/esp-bist.git
Fetch the submodules with the following command:
git submodule update --init --recursive
This repository includes a dev container configuration to ease the development process. The dev container includes all the necessary tools and libraries to build and test the BIST library.
- Install the Dev Container CLI:
npm install -g @devcontainers/cli
- Start a dev container in your workspace folder:
devcontainer up --workspace-folder .
- You can run commands in this dev container, for example:
devcontainer exec --workspace-folder . bash
Before building the project, make sure to set the IDF_PATH environment variable to access all the necessary tools.
To set up the IDF environment variables, execute the following command:
. $IDF_PATH/export.sh
The Critical Firmware is designed to run on top of the MCUboot bootloader.
MCUboot is a submodule located at modules/mcuboot.
cd modules/mcuboot/boot/espressif
cmake -DCMAKE_TOOLCHAIN_FILE=tools/toolchain-esp32c3.cmake -DMCUBOOT_TARGET=esp32c3 -DESP_HAL_PATH=$IDF_PATH -B build -GNinja
ninja -C build
Inside any of the tests or samples directories:
cmake -DSOC_TARGET=esp32c3 -B build -GNinja
ninja -C build
The project uses Kconfig to configure the BIST library. Application developers can open a terminal-based project configuration menu using the following command:
ninja -C build menuconfig
The file bist.conf
in the root directory of any application is mandatory and can be used to set the default configuration the project. The configuration file is automatically included in the build process. If empty, the BIST library will use the default configuration.
To run on the QEMU emulator, execute the following command:
ninja -C build qemu
To run tests using the QEMU emulator in debug mode, execute the following command:
ninja -C build qemu_debug
In another terminal, run gdb with the following command:
riscv32-esp-elf-gdb build/critical_fw_esp32c3.elf -ex "target remote :1234" -ex "tb main" -ex "c"
By default, the flashing process assumes the board is connected to /dev/ttyUSB0. The port can be set with -DESP_PORT
.
ninja -C build flash -DESP_PORT=/dev/ttyUSBx
To monitor the device output, execute the following command:
ninja -C build monitor
To close the monitor, press Ctrl+]
.
The Main System Watchdog Timer (MWDT) of Timer 1 is enabled by default. The MWDT is a hardware watchdog timer that can be used to monitor the system's operation and detect potential failures. The MWDT is configured to trigger a system reset if the system fails to clear the watchdog within a specified time frame. The MWDT is enabled by default to ensure the system can recover from potential failures and maintain operational integrity.
Before resetting the system, the watchdog can trigger an interrupt to allow the application to perform any necessary operation. The interrupt handler can be defined in the application and registered using wdt_register_callback(void (*callback)(void *), void *arg)
.
The CONFIG_WDT_TIMEOUT_US
configuration defines the watchdog timeout in microseconds. The watchdog timeout should be set according to the system's requirements, ensuring it provides sufficient time for the application to complete its operations. The interrupt will be triggered when the watchdog timer reaches its timeout value. The system will be reset after double the timeout value.
The system implements a Windowed Watchdog using a private timer in conjunction with the main watchdog timer. This mechanism provides indirect time-slot monitoring of the application execution flow.
A Program Counter (PC) Fault is detected if the watchdog timer is not reset within a specified time window. If an underflow occurs (early reset), subsequent attempts to reset the watchdog within the same time window will fail, ensuring fault detection.
The Underflow value is defined in microseconds by CONFIG_WDT_UNDERFLOW_US
in the sdkconfig.h
file. The overflow value is the same as the main watchdog timer timeout, defined by CONFIG_WDT_TIMEOUT_US
.
The windowed watchdog can be enabled with void wdt_init_windowed(uint32_t underflow_timeout_us)
.
The tests are located in the tests
directory. The tests are divided into two categories: QEMU and device testing.
We use Pytest in conjunction with Unity, GDB scripting and QEMU to run the test suite. The tests are meant to verify the correct execution of the BIST library and to introduce faults deliberately to verify that the system can detect and recover from such situations, either by restoring the correct data from backup or entering a safe state. To run the tests, execute the following command:
pytest pytest_qemu_* --junitxml=build/tests/report.xml
The test will output a report in the build/tests
directory.
To run the tests on the device, execute the following command:
pytest pytest_device_* --junitxml=build/tests/report.xml
The samples are located in the samples
directory. The samples demonstrate how to use the BIST library to verify the integrity and proper operation of the hardware components.
The proper documentation for the BIST library can be found in the src/bist
directory.