Keep the colleague's microbu-esp32c5 tree in this repository

obu-firmware builds against vanetza-idf from microbu-esp32c5/external, but
that tree was gitignored, so a clone of this repository could not build the
firmware it ships. It is now committed here as ordinary files in its own
folder, microbu-esp32c5/: the colleague's commit cf4b99f plus the V2X2MAP
bridge's signature verification (--trust) used on the bench. Nothing is
fetched from or pushed to the colleague's repository; this repository and
its remotes carry everything. The folder's own .gitignore keeps build output,
downloaded components and private key material out, as it did there; the
committed file set is identical to that repository's tracked files.

The ESP32-C5 is still flashed from obu-firmware/, which only takes
vanetza-idf from microbu-esp32c5/, so the two stay separate folders.
FLASHING.md says how to take a newer version of the colleague's tree (copy
it over the folder, rebuild, test, commit).
This commit is contained in:
Ashin Walpola
2026-09-23 17:46:40 +02:00
parent 2f60623e18
commit 0e9525162d
9881 changed files with 1582523 additions and 17 deletions
@@ -0,0 +1,4 @@
cmake_minimum_required(VERSION 3.22)
list(APPEND EXTRA_COMPONENT_DIRS "${CMAKE_CURRENT_LIST_DIR}/../..")
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(vanetza_idf_example)
@@ -0,0 +1,2 @@
idf_component_register(SRCS "main.cpp" REQUIRES vanetza-idf esp_timer)
target_compile_features(${COMPONENT_LIB} PRIVATE cxx_std_17)
@@ -0,0 +1,31 @@
#include <vanetza_idf/access.hpp>
#include <esp_log.h>
#if VIDF_NETWORK
#include <vanetza_idf/stack.hpp>
#endif
/** Replace this adapter with a hardware driver or test lower port. No radio is
* enabled by this integration example. A non-existent device rejects requests.
*/
class ExampleAccess : public vanetza_idf::Access {
public:
vanetza_idf::Result request(vanetza_idf::AlDataRequest) override {
return vanetza_idf::Result::unsupported;
}
};
extern "C" void app_main() {
ExampleAccess access;
#if VIDF_NETWORK
vanetza::ManualRuntime runtime;
vanetza_idf::StackConfig config;
config.mib.vanetzaDisableBeaconing = true;
vanetza_idf::Stack stack(config, runtime, access);
ESP_LOGI("vanetza-idf", "Network profile ready; inject position, time, security and Access adapter");
// The application event loop owns stack lifetime. In production, keep this
// object alive while processing queued sensor, receive and timer events.
#else
vanetza_idf::AccessStack stack(access);
ESP_LOGI("vanetza-idf", "Access profile ready; inject AL_DATA.request primitives");
#endif
}
@@ -0,0 +1,3 @@
CONFIG_VANETZA_IDF_PROFILE_ACCESS=y
# CONFIG_VANETZA_IDF_PROFILE_FACILITIES is not set
# CONFIG_VANETZA_IDF_PROFILE_NETWORK is not set
@@ -0,0 +1,10 @@
CONFIG_COMPILER_CXX_EXCEPTIONS=y
CONFIG_COMPILER_CXX_RTTI=y
CONFIG_ESP_MAIN_TASK_STACK_SIZE=32768
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y
CONFIG_VANETZA_IDF_PROFILE_FACILITIES=y
CONFIG_VANETZA_IDF_CAM=y
CONFIG_VANETZA_IDF_DENM=y
CONFIG_VANETZA_IDF_VAM=y
CONFIG_VANETZA_IDF_HIL=y
@@ -0,0 +1,6 @@
CONFIG_VANETZA_IDF_PROFILE_NETWORK=y
# CONFIG_VANETZA_IDF_PROFILE_FACILITIES is not set
# CONFIG_VANETZA_IDF_PROFILE_ACCESS is not set
# CONFIG_VANETZA_IDF_CAM is not set
# CONFIG_VANETZA_IDF_DENM is not set
# CONFIG_VANETZA_IDF_VAM is not set
@@ -0,0 +1,6 @@
cmake_minimum_required(VERSION 3.22)
list(APPEND EXTRA_COMPONENT_DIRS "${CMAKE_CURRENT_LIST_DIR}/../..")
set(SDKCONFIG_DEFAULTS "${CMAKE_CURRENT_LIST_DIR}/../esp_idf/sdkconfig.defaults;${CMAKE_CURRENT_LIST_DIR}/sdkconfig.defaults")
set(COMPONENTS main)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(vanetza_idf_component_tests)
@@ -0,0 +1,15 @@
set(_tests "../../../ports/esp_idf/tests")
idf_component_register(SRCS "main.cpp" "hil_server.cpp" "${_tests}/test_main.cpp" "${_tests}/test_its_time.cpp" "${_tests}/hil_sut.cpp"
REQUIRES vanetza-idf esp_driver_usb_serial_jtag nvs_flash)
if(CONFIG_VANETZA_IDF_NETWORK)
target_sources(${COMPONENT_LIB} PRIVATE "${_tests}/test_management.cpp")
endif()
if(CONFIG_VANETZA_IDF_SECURITY)
target_sources(${COMPONENT_LIB} PRIVATE "${_tests}/test_backend_kat.cpp" "${_tests}/test_security_entity.cpp"
"${_tests}/test_trust_domain.cpp" "${_tests}/test_credentials.cpp")
endif()
if(CONFIG_VANETZA_IDF_PKI)
target_sources(${COMPONENT_LIB} PRIVATE "${_tests}/test_pki.cpp")
endif()
target_compile_definitions(${COMPONENT_LIB} PRIVATE main=vidf_test_main)
target_compile_features(${COMPONENT_LIB} PRIVATE cxx_std_17)
@@ -0,0 +1,80 @@
#include <vanetza_idf/hil.hpp>
#include "../../../ports/esp_idf/tests/hil_sut.hpp"
#include <driver/usb_serial_jtag.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <algorithm>
#include <memory>
#if CONFIG_VANETZA_IDF_RADIO_C5
#include <vanetza_idf/c5_radio.hpp>
#endif
void run_hil_server() {
using namespace vanetza_idf;
using vanetza::ByteBuffer;
usb_serial_jtag_driver_config_t config {};
config.rx_buffer_size = 8192; config.tx_buffer_size = 8192;
ESP_ERROR_CHECK(usb_serial_jtag_driver_install(&config));
hil::Decoder decoder;
vidf_test::Sut sut;
#if CONFIG_VANETZA_IDF_RADIO_C5
std::unique_ptr<C5Radio> radio;
std::uint16_t radio_channel = 180;
#endif
auto handle = [&](hil::Frame frame) {
if (frame.channel != hil::Channel::diagnostic) return;
const auto& in = frame.payload;
ByteBuffer reply;
#if CONFIG_VANETZA_IDF_RADIO_C5
if (in.size() == 4 && in[0] == 3 && in[3] <= 1) {
radio.reset();
C5RadioConfig rc;
rc.channel_number = (in[1] << 8) | in[2];
radio_channel = rc.channel_number;
rc.laboratory_transmission = in[3] != 0;
radio = std::make_unique<C5Radio>(rc);
const auto error = radio->start();
if (error != ESP_OK) radio.reset();
reply = {static_cast<std::uint8_t>(error == ESP_OK ? Result::accepted : Result::rejected), 0};
} else if (in.size() > 15 && in[0] == 4 && radio) {
AlDataRequest request;
std::copy(in.begin() + 1, in.begin() + 7, request.source.octets.begin());
std::copy(in.begin() + 7, in.begin() + 13, request.destination.octets.begin());
request.priority = in[13]; request.mcs = static_cast<OfdmMcs>(in[14]);
request.transmit_power_dbm = 10.0;
request.channel_number = radio_channel;
request.data.assign(in.begin() + 15, in.end());
reply = {static_cast<std::uint8_t>(radio->request(std::move(request))), 0};
} else if (in.size() == 1 && in[0] == 5 && radio) {
reply = {static_cast<std::uint8_t>(Result::accepted), 0};
radio->poll({}, [&](const ByteBuffer& bytes, int rssi, std::uint32_t time) {
if (reply.size() + bytes.size() + 8 > 4096) {
reply[0] = static_cast<std::uint8_t>(Result::resource_limit); return;
}
++reply[1]; reply.push_back(3);
reply.push_back((bytes.size() + 5) >> 8); reply.push_back(bytes.size() + 5);
reply.push_back(static_cast<std::uint8_t>(rssi));
for (int shift = 24; shift >= 0; shift -= 8) reply.push_back(time >> shift);
reply.insert(reply.end(), bytes.begin(), bytes.end());
});
} else if (in.size() == 1 && in[0] == 6) {
radio.reset();
reply = {static_cast<std::uint8_t>(Result::accepted), 0};
} else
#endif
reply = sut.execute(in);
const auto encoded = hil::encode({hil::Channel::diagnostic, frame.sequence, std::move(reply)});
std::size_t sent = 0;
while (sent < encoded.size()) {
const int count = usb_serial_jtag_write_bytes(encoded.data() + sent,
encoded.size() - sent, pdMS_TO_TICKS(2000));
if (count <= 0) break; // The host detects an incomplete reply by timeout/CRC.
sent += count;
}
};
std::uint8_t bytes[256];
for (;;) {
const int count = usb_serial_jtag_read_bytes(bytes, sizeof(bytes), pdMS_TO_TICKS(20));
if (count > 0) decoder.feed(bytes, count, handle);
}
}
@@ -0,0 +1,30 @@
#include <cstdio>
#include <esp_task_wdt.h>
#include <nvs_flash.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
int vidf_test_main();
void run_hil_server();
extern "C" void app_main() {
// The ESP32-C5 ROM UART0 clock repair for warm resets is applied by the component
// itself (ports/esp_idf/src/esp32c5_rom_uart_clock.c) before app_main runs.
std::puts("vanetza-idf component tests beginning");
// NVS for the credential store tests (the application's job, credentials.hpp)
esp_err_t nvs = nvs_flash_init();
if (nvs == ESP_ERR_NVS_NO_FREE_PAGES || nvs == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
nvs = nvs_flash_init();
}
ESP_ERROR_CHECK(nvs);
// The security tests run about a minute of software ECDSA without yielding; give the
// idle-task watchdog that long instead of interleaving its reports with the output.
esp_task_wdt_config_t watchdog = {};
watchdog.timeout_ms = 300000;
watchdog.idle_core_mask = (1 << portNUM_PROCESSORS) - 1;
watchdog.trigger_panic = false;
esp_task_wdt_reconfigure(&watchdog);
const int result = vidf_test_main();
std::printf("VIDF_TEST_RESULT=%d\n", result);
if (result == 0) run_hil_server();
for (;;) vTaskDelay(pdMS_TO_TICKS(1000));
}
@@ -0,0 +1,4 @@
# Name, Type, SubType, Offset, Size, Flags
nvs,data,nvs,0x9000,0x6000,
phy_init,data,phy,0xf000,0x1000,
factory,app,factory,0x10000,0x300000,
1 # Name Type SubType Offset Size Flags
2 nvs data nvs 0x9000 0x6000
3 phy_init data phy 0xf000 0x1000
4 factory app factory 0x10000 0x300000
@@ -0,0 +1,7 @@
CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y
CONFIG_VANETZA_IDF_RADIO_C5=y
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_VANETZA_IDF_SECURITY_VERIFY=y
CONFIG_VANETZA_IDF_PKI=y
CONFIG_VANETZA_IDF_NVS_CREDENTIALS=y