Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ESP-IDF-FactCheck

Harvests verified facts about espressif/esp-idf and espressif/arduino-esp32 directly from their real git history — instead of hand-typed tables that go stale and get guessed at. Three axes, four harvesters, real provenance on every fact.

New here? Read ABOUT.md first — it explains the problem this solves and why it matters, with a real historical example of what happens without it.


The three axes

Axis Question Answered by
Version Since which ESP-IDF release does enum member X exist? esp_reset_reason_t, esp_sleep_source_t harvesters
Target Does this chip's hardware actually support this feature? soc_caps.h harvester
Framework Does Arduino-ESP32 support this chip, and which ESP-IDF does it pin? idf_component.yml harvester

A #ifdef check can only ever answer one of these at a time — and picking the wrong one is exactly how projects end up with silently-broken guards. See ABOUT.md for the historical case that motivated this.


Quick start: use the data as-is

The harvested facts are already in data/*.yaml — you don't need Python or network access just to read them.

cat data/esp_sleep_source_t.harvested.yaml

Each file has the same shape:

enum: esp_sleep_source_t
header: components/esp_hw_support/include/esp_sleep.h
repo: https://github.com/espressif/esp-idf
harvested_tags: [ ... ]        # every ref actually checked, with commit SHA
members:
  ESP_SLEEP_WAKEUP_VAD:
    first_seen_tag: v5.4
    first_seen_commit: 67c1de1eebe095d554d281952fde63c16ee2dca0
    source_url: https://raw.githubusercontent.com/espressif/esp-idf/v5.4/...

Every fact traces back to a specific commit you can go look at yourself.


Re-running a harvester

Each harvester is a standalone script. Running it re-fetches from the real GitHub repos and rewrites its data/*.yaml output.

cd tools
pip install pyyaml --break-system-packages   # only dependency

python3 harvest_reset_enum.py
python3 harvest_wakeup_enum.py
python3 harvest_soc_caps.py
python3 harvest_arduino_targets.py

Each prints a summary table to stdout before writing its YAML — useful for a quick sanity check without opening the file.

To extend a harvester to a new tag, target, or macro: edit the relevant list near the top of the script (TAGS_IN_ORDER, TARGETS, or MACROS_OF_INTEREST) and re-run. The parsing logic doesn't need to change.


Generating a capability header for your own project

examples/generate_capability_header/ is a worked reference, not a one-size-fits-all tool — copy and adapt it, don't import it as-is. It shows the full pipeline: read data/*.yaml → emit #if/#define guards with the correct mechanism per axis.

cd examples/generate_capability_header
python3 generate_capability_header.py

The critical detail worth copying exactly, not just the output: which C preprocessor mechanism applies to which axis.

// Axis 1 (version) — enum members are NOT preprocessor-visible.
// #ifdef/#if defined() on an enum member ALWAYS evaluates false,
// silently, on every target and every ESP-IDF version. Use a numeric
// version comparison instead:
#if defined(ESP_IDF_VERSION) && ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 0)
    #define MY_HAS_WAKEUP_VAD 1
#else
    #define MY_HAS_WAKEUP_VAD 0
#endif

// Axis 2 (target) — soc_caps.h macros ARE real #defines, #if defined() works:
#if defined(SOC_BOD_SUPPORTED)
    #define MY_HAS_BOD 1
#else
    #define MY_HAS_BOD 0
#endif

// Axis 3 (framework) — __has_include, not #ifdef ESP32. The latter is not
// auto-defined under "Arduino as an ESP-IDF component," a documented,
// officially-supported build path (needed for esp32c2/esp32c61) where
// <Arduino.h> is genuinely includable but ARDUINO/ESP32 build macros are not:
#if __has_include(<Arduino.h>)
    #define MY_FRAMEWORK_ARDUINO 1
#else
    #define MY_FRAMEWORK_ARDUINO 0
#endif

Mixing these up — testing an enum member with #ifdef, or testing framework presence with a macro that isn't reliably auto-defined — is precisely how the historical failure in ABOUT.md happened.


Verifying the generated guards actually work

Don't trust that generated #if logic is correct just because it compiles — a guard that's silently always false still compiles cleanly. verify/verify_generated.cpp proves the guards evaluate correctly by simulating two different ESP_IDF_VERSION values and checking the resulting macro values are exactly what's expected:

cd verify
g++ -std=c++17 -DTEST_V5_3 -I fake_arduino verify_generated.cpp -o verify_v53 && ./verify_v53
# expect: WAKEUP_VAD=0 WAKEUP_VBAT_UNDER_VOLT=0 WAKEUP_UART1=0 WAKEUP_UART2=0

g++ -std=c++17 -DTEST_V6_0 -I fake_arduino verify_generated.cpp -o verify_v60 && ./verify_v60
# expect: WAKEUP_VAD=1 WAKEUP_VBAT_UNDER_VOLT=1 WAKEUP_UART1=1 WAKEUP_UART2=1

No real ESP32 hardware or toolchain needed — this runs on any machine with a C++17 compiler. It doesn't validate real-hardware behavior, only that the preprocessor logic itself is internally consistent and version-gated correctly.


Known limitations (stated plainly, not hidden)

  • Target-axis coverage is partial. soc_caps.h has hundreds of macros; harvest_soc_caps.py currently checks a curated list (see MACROS_OF_INTEREST in the script), not the whole file.
  • Textual "first appears," not semantic diffing. The version-axis harvesters detect the first tag where a member's name textually appears. A member removed and later re-added under the same name would be misreported as "always present." Not observed in practice, not structurally ruled out.
  • master is a moving target. Any fact whose first_seen_tag is master reflects an unreleased, unstable state — the commit SHA recorded is a snapshot; re-running later may find more (or find the member has moved into an actual release, and get a proper version number instead).
  • Not wired into CI. Harvesting is currently a manual, on-demand step, not a scheduled job that would catch drift automatically as upstream releases happen.
  • GitHub REST API rate limits. Commit SHA resolution uses git ls-remote --tags instead of api.github.com, specifically because the REST API got rate-limited during development on a shared IP. If you have API access with a token, that path is faster but isn't wired up here.

For Tanaka-san, or anyone extending the target axis

ESP-IDF-SoC-Check already solves the target axis well — it's the tool that prompted checking harvest_soc_caps.py's method against a second, independent implementation in the first place. If you're maintaining that tool and see a way the two could share data or cross-validate results, an issue or PR here is welcome. See ABOUT.md for the fuller context on how this project relates to it.


Suggested GitHub topics (tags)

For repository discoverability once this is pushed:

esp32  esp-idf  arduino-esp32  esp32-arduino  embedded  iot
soc-caps  chip-capabilities  provenance  data-harvesting
fact-checking  build-tools  code-generation  verification

License

MIT — see LICENSE.

CRA applicability

See CRA-EXEMPTION.md — short version: this is a build-time tool, never shipped as part of a product, and the EU Cyber Resilience Act does not apply to it.

About

Does this API exist? Does this chip support it? Does Arduino-ESP32? Harvested answers, not guesses.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages