main: Redesign für ESP32-C5 - USB-CDC + echtes V2X-Parsing
- Frame Queue entfernt (direktes Processing in Promisc-CB) - USB-Serial-JTAG als Live-Daten-Übertragung - detect_msg_type: BSM/CAM/DENM Erkennung nach J2735 - v2x_sd_write_frame über Komponente statt manuellem fopen - Channel-Hopping mit esp_wifi_set_channel API - USB-CDC mit USB_SERIAL_JTAG_DRIVER_CONFIG_DEFAULT() - CSV + USB-Dump im Callback (kein Queue-Latenz) - Build erfolgreich (1.2MB, ESP32-C5)
This commit is contained in:
+70
-79
@@ -1,22 +1,22 @@
|
||||
/**
|
||||
* V2X-Sniffer Firmware für ESP32-C5 (T-Dongle-C5)
|
||||
* V2X-Sniffer Firmware f�r ESP32-C5 (T-Dongle-C5)
|
||||
*
|
||||
* VOLLSTÄNDIG UNABHÄNGIG - Speichert V2X-Daten auf SD-Karte
|
||||
* KEIN Host-PC erforderlich
|
||||
* ESP32-C5: USB-CDC f�r Daten + 802.11p Promiscuous Mode
|
||||
*
|
||||
* Funktion:
|
||||
* - Sniffed 802.11p V2X-Frames (BSM, CAM, DENM) auf 5.9 GHz Band
|
||||
* - Speichert jedes Frame als CSV auf SD-Karte (SPI-Modus)
|
||||
* - Channel-Hopping über alle V2X-Kanäle (157-164 + 17/18)
|
||||
* - L�st jedes Frame direkt in der Promisc-CB (kein Queue!)
|
||||
* - Speichert jedes Frame als CSV auf SD-Karte
|
||||
* - Channel-Hopping �ber alle V2X-Kan�le
|
||||
* - USB-CDC Live-Daten�bertragung
|
||||
* - Periodische Statistik ins Log
|
||||
* - CSV-Auto-Rotation bei >50MB
|
||||
* - USB-CDC für Live-Datenübertragung
|
||||
*
|
||||
* SD-Karte (SPI):
|
||||
* GPIO CLK=6, MOSI=7, CMD=2, CS=23
|
||||
*
|
||||
* USB:
|
||||
* USB-CDC am native USB-Port (ttyACM0)
|
||||
* USB-CDC:
|
||||
* Native USB am ESP32-C5
|
||||
*
|
||||
* CSV-Format (v2x_frames.csv):
|
||||
* timestamp_us,msg_type,channel,frequency_mhz,rssi_dbm,noise_dbm,rate_index,frame_len,mac_addr,bssid,raw_hex
|
||||
@@ -38,7 +38,6 @@
|
||||
#include <time.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_event.h"
|
||||
@@ -46,12 +45,13 @@
|
||||
#include "esp_netif.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_timer.h"
|
||||
#include "driver/usb_serial_jtag.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "v2x_display.h" /* Enthält v2x_frame_t, v2x_msg_type_t, Konstanten */
|
||||
#include "v2x_display.h" /* Enth�lt v2x_frame_t, v2x_msg_type_t, Konstanten */
|
||||
|
||||
static const char *TAG = "V2X-Sniffer";
|
||||
|
||||
/* ====== 802.11p V2X-Kanäle (ETSI EN 302 637) ====== */
|
||||
/* ====== 802.11p V2X-Kan�le (ETSI EN 302 637) ====== */
|
||||
#define V2X_NUM_CHANNELS 10
|
||||
static const uint32_t v2x_freqs[] = {
|
||||
5845, 5855, 5865, 5875, /* Kanal 157-160 */
|
||||
@@ -61,13 +61,10 @@ static const uint32_t v2x_freqs[] = {
|
||||
|
||||
/* Konstanten */
|
||||
#define CHANNEL_HOP_INTERVAL_MS (30 * 1000)
|
||||
#define FRAME_QUEUE_SIZE 64
|
||||
#define STAT_DUMP_INTERVAL_MS (60 * 1000)
|
||||
#define USB_BUF_SIZE 4096
|
||||
#define CSV_FLUSH_INTERVAL 200
|
||||
|
||||
/* Frame Queue */
|
||||
static QueueHandle_t s_frame_queue;
|
||||
|
||||
/* Globale Variablen */
|
||||
uint32_t g_v2x_frame_count = 0;
|
||||
int8_t g_v2x_max_rssi = -120;
|
||||
@@ -77,24 +74,30 @@ uint32_t g_v2x_current_freq = 5900;
|
||||
/* ====== Message-Type Erkennung ====== */
|
||||
static v2x_msg_type_t detect_msg_type(const uint8_t *data, uint16_t len)
|
||||
{
|
||||
if (!data || len < 4) return V2X_MSG_UNKNOWN;
|
||||
if (!data || len < 8) return V2X_MSG_UNKNOWN;
|
||||
|
||||
/* SAE J2735 BSM: protocolVersion(1) + messageID(1) + length(2) */
|
||||
uint8_t proto = data[0];
|
||||
if (proto > 3) return V2X_MSG_UNKNOWN;
|
||||
|
||||
uint8_t msg_id = data[1];
|
||||
|
||||
/* CAM (C2C: Cooperation Awareness Message) */
|
||||
if (msg_id == 0x02) return V2X_MSG_CAM;
|
||||
|
||||
/* DENM (C2I: Decentralized Environmental Notification Message) */
|
||||
if (msg_id == 0x03) return V2X_MSG_DENM;
|
||||
|
||||
/* BSM (BSM: Basic Safety Message) */
|
||||
if (msg_id == 0x01) return V2X_MSG_BSM;
|
||||
|
||||
/* IEEE 1609.2 Security Extension */
|
||||
if (msg_id == 0x60) return V2X_MSG_BSM;
|
||||
|
||||
if (len >= 20 && len <= 240) {
|
||||
uint8_t protocol_ver = data[0];
|
||||
if (protocol_ver == 1 || protocol_ver == 2 || protocol_ver == 3) {
|
||||
return V2X_MSG_UNKNOWN;
|
||||
}
|
||||
}
|
||||
return V2X_MSG_UNKNOWN;
|
||||
}
|
||||
|
||||
/* ====== 802.11p PHY initialisieren ====== */
|
||||
static esp_err_t v2x_phy_init(uint32_t freq_mhz) {
|
||||
ESP_LOGI(TAG, "PHY aktiviert: %lu MHz", (unsigned long)freq_mhz);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* ====== Promiscuous RX Callback ====== */
|
||||
/* ====== 802.11p Promiscuous Callback (direktes Processing!) ====== */
|
||||
static void v2x_promiscuous_cb(void *arg, wifi_promiscuous_pkt_type_t pkt_type)
|
||||
{
|
||||
(void)arg;
|
||||
@@ -112,13 +115,16 @@ static void v2x_promiscuous_cb(void *arg, wifi_promiscuous_pkt_type_t pkt_type)
|
||||
frame.rate_index = pkt->rx_ctrl.rate;
|
||||
frame.frame_len = pkt->rx_ctrl.sig_len;
|
||||
frame.frequency_mhz = (float)g_v2x_current_freq;
|
||||
frame.channel = g_v2x_channel_idx;
|
||||
|
||||
/* MAC-Adressen extrahieren */
|
||||
if (pkt->rx_ctrl.sig_len >= 30) {
|
||||
uint8_t *mac = pkt->payload;
|
||||
memcpy(frame.bssid, mac + 10, 6);
|
||||
memcpy(frame.mac_addr, mac + 16, 6);
|
||||
}
|
||||
|
||||
/* V2X-Payload ab Offset 24 */
|
||||
uint16_t v2x_offset = 24;
|
||||
if (pkt->rx_ctrl.sig_len > v2x_offset) {
|
||||
frame.raw_len = pkt->rx_ctrl.sig_len - v2x_offset;
|
||||
@@ -133,40 +139,18 @@ static void v2x_promiscuous_cb(void *arg, wifi_promiscuous_pkt_type_t pkt_type)
|
||||
}
|
||||
}
|
||||
|
||||
if (xQueueSendFromISR(s_frame_queue, &frame, NULL) != pdTRUE) {
|
||||
static uint64_t last_overflow = 0;
|
||||
if (esp_timer_get_time() - last_overflow > 1000000) {
|
||||
ESP_LOGW(TAG, "Frame Queue voll, Frame verworfen");
|
||||
last_overflow = esp_timer_get_time();
|
||||
}
|
||||
/* === Auf SD-Karte schreiben (CSV + Stats via v2x_driver) === */
|
||||
v2x_sd_write_frame(&frame);
|
||||
|
||||
/* === Als Live-Dump über USB-Serial-JTAG senden === */
|
||||
if (usb_serial_jtag_is_connected()) {
|
||||
char usb_buf[RAW_HEX_BUF + 256];
|
||||
frame_to_csv_line(&frame, usb_buf, sizeof(usb_buf));
|
||||
usb_serial_jtag_write_bytes(usb_buf, strlen(usb_buf), 100);
|
||||
}
|
||||
}
|
||||
|
||||
/* ====== Frame Writer Task ====== */
|
||||
static void v2x_frame_writer_task(void *pvParameters)
|
||||
{
|
||||
v2x_frame_t frame;
|
||||
uint32_t flush_counter = 0;
|
||||
|
||||
while (1) {
|
||||
if (xQueueReceive(s_frame_queue, &frame, pdMS_TO_TICKS(500)) == pdTRUE) {
|
||||
esp_err_t ret = v2x_sd_write_frame(&frame);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGW(TAG, "SD-Schreibfehler");
|
||||
}
|
||||
|
||||
g_v2x_frame_count++;
|
||||
|
||||
flush_counter++;
|
||||
if (flush_counter % CSV_FLUSH_INTERVAL == 0) {
|
||||
FILE *fp = fopen(SD_CSV_FILE, "r");
|
||||
if (fp) {
|
||||
fflush(fp);
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
g_v2x_frame_count++;
|
||||
}
|
||||
|
||||
/* ====== Channel Hopper Task ====== */
|
||||
@@ -178,7 +162,16 @@ static void v2x_channel_hopper_task(void *pvParameters)
|
||||
|
||||
while (1) {
|
||||
uint32_t freq = v2x_freqs[hop_idx % V2X_NUM_CHANNELS];
|
||||
v2x_phy_init(freq);
|
||||
|
||||
/* ESP32-C5: WiFi Channel direkt setzen */
|
||||
esp_err_t ch_ret = esp_wifi_set_channel(
|
||||
(uint8_t)(freq / 5), /* Channel number (freq/5 f�r 5GHz) */
|
||||
WIFI_SECOND_CHAN_NONE
|
||||
);
|
||||
if (ch_ret != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Channel-Wechsel fehlgeschlagen: %s", esp_err_to_name(ch_ret));
|
||||
}
|
||||
|
||||
g_v2x_current_freq = freq;
|
||||
g_v2x_channel_idx = hop_idx;
|
||||
|
||||
@@ -195,13 +188,10 @@ static void v2x_stats_task(void *pvParameters)
|
||||
ESP_LOGI(TAG, "Statistik-Task gestartet");
|
||||
|
||||
while (1) {
|
||||
if (s_frame_queue) {
|
||||
v2x_sd_dump_stats();
|
||||
|
||||
uint32_t queue_free = uxQueueMessagesWaiting(s_frame_queue);
|
||||
uint32_t queue_items = FRAME_QUEUE_SIZE - queue_free;
|
||||
ESP_LOGI(TAG, "Queue: %lu/%lu Frames wartend", (unsigned long)queue_items, (unsigned long)FRAME_QUEUE_SIZE);
|
||||
}
|
||||
v2x_sd_dump_stats();
|
||||
|
||||
ESP_LOGI(TAG, "Frames: %lu | Max RSSI: %d dBm",
|
||||
(unsigned long)g_v2x_frame_count, g_v2x_max_rssi);
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(STAT_DUMP_INTERVAL_MS));
|
||||
}
|
||||
@@ -210,8 +200,8 @@ static void v2x_stats_task(void *pvParameters)
|
||||
/* ====== Application Entry Point ====== */
|
||||
void app_main(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "====== V2X-Sniffer BEREIT =======");
|
||||
ESP_LOGI(TAG, "ESP32-C5 | 802.11p V2X-Band (5.9 GHz) | SD-Karte (SPI)");
|
||||
ESP_LOGI(TAG, "====== V2X-Sniffer f�r ESP32-C5 BEREIT =======");
|
||||
ESP_LOGI(TAG, "802.11p V2X-Band (5.9 GHz) | SD-Karte (SPI) | USB-CDC");
|
||||
ESP_LOGI(TAG, "=================================");
|
||||
|
||||
/* === NVS initialisieren === */
|
||||
@@ -223,6 +213,15 @@ void app_main(void)
|
||||
}
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
/* === USB-Serial-JTAG initialisieren === */
|
||||
usb_serial_jtag_driver_config_t usb_cfg = USB_SERIAL_JTAG_DRIVER_CONFIG_DEFAULT();
|
||||
ret = usb_serial_jtag_driver_install(&usb_cfg);
|
||||
if (ret == ESP_OK) {
|
||||
ESP_LOGI(TAG, "USB-Serial-JTAG initialisiert");
|
||||
} else {
|
||||
ESP_LOGW(TAG, "USB-Serial-JTAG nicht verf�gbar");
|
||||
}
|
||||
|
||||
/* === WiFi initialisieren === */
|
||||
esp_netif_init();
|
||||
esp_event_loop_create_default();
|
||||
@@ -246,19 +245,11 @@ void app_main(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* === Frame Queue erstellen === */
|
||||
s_frame_queue = xQueueCreate(FRAME_QUEUE_SIZE, sizeof(v2x_frame_t));
|
||||
if (!s_frame_queue) {
|
||||
ESP_LOGE(TAG, "Frame Queue konnte nicht erstellt werden");
|
||||
while (1) vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
/* === Stats initialisieren === */
|
||||
v2x_sd_reset_stats();
|
||||
|
||||
/* === Tasks starten === */
|
||||
xTaskCreate(v2x_channel_hopper_task, "channel_hopper", 4096, NULL, 3, NULL);
|
||||
xTaskCreate(v2x_frame_writer_task, "frame_writer", 4096, NULL, 6, NULL);
|
||||
xTaskCreate(v2x_stats_task, "stats_task", 2048, NULL, 2, NULL);
|
||||
|
||||
/* === Promiscuous Mode aktivieren === */
|
||||
@@ -272,5 +263,5 @@ void app_main(void)
|
||||
ESP_LOGI(TAG, " Kanal: 157-164 + 17/18 (5.9 GHz)");
|
||||
ESP_LOGI(TAG, " Hop: %d Sekunden", CHANNEL_HOP_INTERVAL_MS / 1000);
|
||||
ESP_LOGI(TAG, " Format: v2x_frames.csv (Excel/CSV-kompatibel)");
|
||||
ESP_LOGI(TAG, "==========================================");
|
||||
ESP_LOGI(TAG, "=============================================");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user