test(freertos): Added support for gcov code coverage for FreeRTOS source files

This commit adds the following:
- Added support to FreeRTOS component to report code coverage using gcov
  and app trace.
- Added a new sdkconfig.ci.code_coverage for code coverage tests.
- Added a new Kconfig option CONFIG_FREERTOS_ENABLE_COVERAGE_TESTS to
  control the code instrumentation.
- Added an idf_component.yml file to the test_app to fetch the esp_gcov
  component from the component registry.
- Updated the README to explain how to take code coverage data.
This commit is contained in:
Sudeep Mohanty
2025-12-17 10:15:21 +01:00
parent ededccc839
commit fb3b5d93cc
5 changed files with 225 additions and 0 deletions

View File

@@ -19,3 +19,36 @@ set(EXTRA_COMPONENT_DIRS
set(COMPONENTS main esp_psram)
project(freertos_test)
# ============================================================================
# Code Coverage Instrumentation
# ============================================================================
# When CONFIG_FREERTOS_ENABLE_COVERAGE_TESTS is enabled, instrument FreeRTOS
# kernel, port, and ESP additions source files for coverage analysis.
if(CONFIG_FREERTOS_ENABLE_COVERAGE_TESTS)
# Get the FreeRTOS component library and directory
idf_component_get_property(freertos_lib freertos COMPONENT_LIB)
idf_component_get_property(freertos_dir freertos COMPONENT_DIR)
# Add coverage flags to the entire FreeRTOS component
target_compile_options(${freertos_lib} PRIVATE "--coverage")
target_link_options(${freertos_lib} PRIVATE "--coverage")
# Create coverage report generation targets
file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}/coverage_report" _coverage_report_path)
idf_create_coverage_report(
${_coverage_report_path}
SOURCE_DIR ${freertos_dir}
GCOV_OPTIONS "--gcov-ignore-parse-errors=negative_hits.warn"
)
idf_clean_coverage_report(${_coverage_report_path})
message(STATUS "================================================")
message(STATUS "FreeRTOS code coverage instrumentation enabled for test app")
message(STATUS "Coverage report will be generated in: ${_coverage_report_path}")
message(STATUS "Coverage root directory: ${freertos_dir}")
message(STATUS "Use 'idf.py gcovr-report' to generate coverage report after running tests")
message(STATUS "Use 'idf.py cov-data-clean' to clean coverage data")
endif()

View File

@@ -1,2 +1,70 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- |
## Manual Code Coverage Workflow
This test_app can be set up to enable FreeRTOS code coverage using GCOV via JTAG and AppTrace.
Follow these steps to manually build, flash, run, and collect code coverage from a FreeRTOS app:
### 1. **Configure the project and build the application**
The sdkconfig.ci.code_coverage enables code coverage settings and other FreeRTOS options to maximize coverage.
```sh
idf.py set-target <target> # e.g., esp32s3
idf.py -DSDKCONFIG_DEFAULTS="sdkconfig.defaults;sdkconfig.ci.code_coverage" build flash monitor
```
### 2. **Flash the Device**
```sh
idf.py -p <PORT> flash
```
### 3. **Launch OpenOCD**
Start OpenOCD in a new terminal (adjust for your board/target if needed):
```sh
openocd -f board/esp32<target>-builtin.cfg
```
### 4. **Run Tests**
Interact with the device over serial (`idf.py monitor -p <PORT>`) and run tests.
### 5. **Collect Coverage Data**
Flush coverage data regularly, and collect `.gcda` files from the device using a telnet session
```sh
telnet localhost 4444
```
Then run
```sh
esp gcov
```
All `.gcda` files will be retrieved into your build directory.
Make sure to regularly collect `.gcda` files to avoid memory overflow problems.
Coverage data should be collected before tests that reset the target.
The coverage data is cumulative.
### 6. **Generate Coverage Report**
Adjust the `gcov` tool to be used based on the target
```sh
xtensa-esp32s3-elf-gcov -b \
../esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/*.gcda
xtensa-esp32s3-elf-gcov -b \
../esp-idf/freertos/CMakeFiles/__idf_freertos.dir/esp_additions/*gcda
```
Then run:
```sh
mkdir coverage_report
cd coverage_report
mkdir html
▶ gcovr \
--gcov-use-existing-files \
--gcov-keep \
--root $IDF_PATH/components/freertos \
--html-details \
--output html/index.html \
.
```
This generates a detailed, navigable HTML coverage report in `html` folder.

View File

@@ -0,0 +1,14 @@
menu "FreeRTOS Test App Configuration"
config FREERTOS_ENABLE_COVERAGE_TESTS
bool "Enable code coverage instrumentation for FreeRTOS"
depends on ESP_GCOV_ENABLE
default n
help
When enabled, FreeRTOS kernel, port, and ESP additions source files will be compiled with
code coverage instrumentation flags (--coverage) to enable GCOV code coverage testing.
Note: This option will increase binary size and may impact performance. It should only be
enabled when running coverage tests.
endmenu

View File

@@ -0,0 +1,7 @@
## IDF Component Manager Manifest File
dependencies:
## Required IDF version
idf:
version: '>=6.0'
# # Put list of dependencies here
espressif/esp_gcov: ^1

View File

@@ -0,0 +1,103 @@
# Code Coverage Configuration for FreeRTOS Tests
# This is a configuration file for maximum code coverage.
# It includes all necessary settings for GCOV coverage instrumentation and enables
# many optional FreeRTOS features, hooks, and debugging options to maximize coverage.
# ============================================================================
# GCOV Coverage Infrastructure
# ============================================================================
CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y
CONFIG_APPTRACE_DEST_JTAG=y
CONFIG_APPTRACE_LOCK_ENABLE=y
CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO=-1
CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH=0
CONFIG_ESP_GCOV_ENABLE=y
# GCOV needs __getreent() which currently newlib provides, and not picolibc
CONFIG_LIBC_NEWLIB=y
# ============================================================================
# FreeRTOS Coverage Instrumentation
# ============================================================================
# Enable code coverage instrumentation for FreeRTOS kernel, port, and ESP additions
CONFIG_FREERTOS_ENABLE_COVERAGE_TESTS=y
# ============================================================================
# Compiler Optimizations (Debug mode for maximum coverage)
# ============================================================================
# Use debug optimizations to prevent code elimination
CONFIG_COMPILER_OPTIMIZATION_DEBUG=y
# Keep assertions enabled to test error paths
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y
# Bootloader should use size optimization to keep bootloader size small
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
# ============================================================================
# FreeRTOS Kernel Options (from sdkconfig.ci.freertos_options)
# ============================================================================
# Core timer selection
CONFIG_FREERTOS_CORETIMER_1=y
CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=n
# Stack overflow checking
CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL=y
CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y
# Interrupt backtrace
CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y
# Static allocation support
CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y
# Task pre-deletion hook
CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK=y
# Queue registry
CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=10
# Trace facility and stats
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y
CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID=y
CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y
CONFIG_FREERTOS_RUN_TIME_COUNTER_TYPE_U64=y
# FreeRTOS in IRAM
CONFIG_FREERTOS_IN_IRAM=y
# FPU in ISR
CONFIG_FREERTOS_FPU_IN_ISR=y
# Task notifications
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
# List data integrity checks
CONFIG_FREERTOS_USE_LIST_DATA_INTEGRITY_CHECK_BYTES=y
# Timer task affinity
CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU1=y
# Tick hook - enables vApplicationTickHook()
CONFIG_FREERTOS_USE_TICK_HOOK=y
# Idle hook - enables vApplicationIdleHook()
CONFIG_FREERTOS_USE_IDLE_HOOK=y
# Application task tag
CONFIG_FREERTOS_USE_APPLICATION_TASK_TAG=y
# ============================================================================
# FreeRTOS Port Options
# ============================================================================
# Task function wrapper
CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y
# Thread local storage deletion callbacks
CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS=y
# Mutex owner check
CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y
# Port critical compliance check
CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE=y