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:
@@ -0,0 +1,126 @@
|
||||
// micrOBU firmware: the ESP32-C5 half of the VRU ITS-S on vanetza-idf.
|
||||
// One station task owns stack, security entity and radio; the serial reader task only
|
||||
// enqueues frames. Link messages: implementation/station-link/README.md.
|
||||
#include "link_protocol.hpp"
|
||||
#include "link_service.hpp"
|
||||
#include "board_controls.hpp"
|
||||
#include "simple_ble.hpp"
|
||||
#include "serial_link.hpp"
|
||||
#include "station.hpp"
|
||||
#if CONFIG_MICROBU_TEST_CHANNEL
|
||||
#include "test_channel.hpp"
|
||||
#endif
|
||||
#include <esp_log.h>
|
||||
#include <esp_task_wdt.h>
|
||||
#include <nvs_flash.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/queue.h>
|
||||
#include <freertos/task.h>
|
||||
#include <cstdio>
|
||||
#include <new>
|
||||
|
||||
namespace {
|
||||
const char* TAG = "microbu";
|
||||
|
||||
/// @brief Represents one frame received from a transport, to be queued for the station task.
|
||||
struct Incoming {
|
||||
microbu::LinkTransport transport;
|
||||
microbu::serial::Frame frame;
|
||||
};
|
||||
|
||||
QueueHandle_t frames = nullptr; // FIFO of Incoming* (8 bytes each); frame bytes never enter the queue itself
|
||||
|
||||
/// @brief Attempts to heap-allocate an Incoming so it can be pushed onto the frames queue.
|
||||
/// @param transport Transport the frame arrived on.
|
||||
/// @param frame Decoded frame to take ownership of.
|
||||
/// @return Owning pointer to push onto the queue, or nullptr if allocation failed.
|
||||
Incoming* try_new_incoming(microbu::LinkTransport transport, microbu::serial::Frame frame) noexcept {
|
||||
try {
|
||||
// std::move here steals frame's payload buffer into the heap Incoming (no byte copy);
|
||||
// it has nothing to do with the queue below, which only ever transports the resulting pointer.
|
||||
return new Incoming {transport, std::move(frame)};
|
||||
} catch (const std::bad_alloc&) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Dispatches one queued frame to the link service (or the test channel); logs and drops it on failure.
|
||||
void handle_incoming(microbu::Station& station, microbu::LinkService& link, const Incoming& incoming) {
|
||||
try {
|
||||
if (incoming.frame.type == microbu::serial::FrameType::LINK)
|
||||
link.handle(incoming.frame.payload, incoming.transport);
|
||||
#if CONFIG_MICROBU_TEST_CHANNEL
|
||||
else if (incoming.transport == microbu::LinkTransport::serial &&
|
||||
incoming.frame.type == microbu::serial::FrameType::TEST)
|
||||
microbu::serial::write(microbu::serial::FrameType::TEST,
|
||||
microbu::test_channel_execute(station, incoming.frame.payload));
|
||||
#endif
|
||||
} catch (const std::bad_alloc&) {
|
||||
ESP_LOGE(TAG, "out of memory while handling a frame");
|
||||
} catch (const std::exception& e) {
|
||||
ESP_LOGE(TAG, "frame handling failed: %s", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief FreeRTOS task body: owns the station, link service and board controls. Drains the incoming queue.
|
||||
void station_task(void*) {
|
||||
microbu::Station station;
|
||||
microbu::LinkService link(station);
|
||||
microbu::BoardControls controls;
|
||||
station.on_disseminated([&controls] { controls.blink(); });
|
||||
station.on_received([&controls] { controls.blink(); });
|
||||
ESP_LOGI(TAG, "station task ready; the phone/PC configures the station over BLE or USB Serial-JTAG");
|
||||
for (;;) { /// main loop: drain the incoming queue, tick the station and link service, tick the controls
|
||||
Incoming* incoming = nullptr;
|
||||
if (xQueueReceive(frames, &incoming, pdMS_TO_TICKS(5)) == pdTRUE && incoming) {
|
||||
handle_incoming(station, link, *incoming);
|
||||
delete incoming;
|
||||
}
|
||||
station.tick();
|
||||
link.tick();
|
||||
controls.tick();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Firmware entry point: initializes NVS, watchdog, serial/BLE transports, and starts the station task.
|
||||
extern "C" void app_main() {
|
||||
// NVS: the credential store (and the Wi-Fi driver's calibration data)
|
||||
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);
|
||||
// Signing and verification take tens of milliseconds each on the C5. This keeps the idle
|
||||
// watchdog from reporting a busy station task (5 s default) while a credential bundle applies.
|
||||
esp_task_wdt_config_t watchdog = {};
|
||||
watchdog.timeout_ms = 30000;
|
||||
watchdog.idle_core_mask = (1 << portNUM_PROCESSORS) - 1;
|
||||
watchdog.trigger_panic = false; // log, don't reboot, on timeout
|
||||
esp_task_wdt_reconfigure(&watchdog);
|
||||
|
||||
frames = xQueueCreate(32, sizeof(Incoming*));
|
||||
microbu::serial::start([](microbu::serial::Frame frame) {
|
||||
auto* copy = try_new_incoming(microbu::LinkTransport::serial, std::move(frame));
|
||||
if (!copy) return;
|
||||
// xQueueSend copies the 8-byte pointer value into the queue, not *copy itself.
|
||||
// station_task then pops pointers FIFO and owns/deletes whatever it receives.
|
||||
if (xQueueSend(frames, ©, 0) != pdTRUE) delete copy; // the phone retries on a missing RESULT
|
||||
});
|
||||
if (!microbu::ble::start([](microbu::link::Bytes message) {
|
||||
microbu::serial::Frame frame {microbu::serial::FrameType::LINK, std::move(message)};
|
||||
auto* copy = try_new_incoming(microbu::LinkTransport::ble, std::move(frame));
|
||||
if (!copy) return;
|
||||
if (xQueueSend(frames, ©, 0) != pdTRUE) delete copy; // same hand-off as the serial callback above
|
||||
})) {
|
||||
ESP_LOGE(TAG, "BLE station link failed to start. USB remains available");
|
||||
}
|
||||
ESP_LOGI(TAG, "micrOBU firmware on vanetza-idf, link protocol version 1%s",
|
||||
#if CONFIG_MICROBU_TEST_CHANNEL
|
||||
", test channel enabled");
|
||||
#else
|
||||
"");
|
||||
#endif
|
||||
xTaskCreate(station_task, "station", 12288, nullptr, 10, nullptr);
|
||||
}
|
||||
Reference in New Issue
Block a user