Archive STM32 firmware to legacy/stm32/: - src/, include/, lib/USB_CDC/, platformio.ini, test stubs, flash_firmware.py - test/test_battery_adc.c, test_hw_button.c, test_pid_schedule.c, test_vesc_can.c, test_can_watchdog.c - USB_CDC_BUG.md Rename: stm32_protocol → esp32_protocol, mamba_protocol → balance_protocol, stm32_cmd_node → esp32_cmd_node, stm32_cmd_params → esp32_cmd_params, stm32_cmd.launch.py → esp32_cmd.launch.py, test_stm32_protocol → test_esp32_protocol, test_stm32_cmd_node → test_esp32_cmd_node Content cleanup across all files: - Mamba F722S → ESP32-S3 BALANCE - BlackPill → ESP32-S3 IO - STM32F722/F7xx → ESP32-S3 - stm32Mode/Version/Port → esp32Mode/Version/Port - STM32 State/Mode labels → ESP32 State/Mode - Jetson Nano → Jetson Orin Nano Super - /dev/stm32 → /dev/esp32 - stm32_bridge → esp32_bridge - STM32 HAL → ESP-IDF docs/SALTYLAB.md: - Update "Drone FC Details" to describe ESP32-S3 BALANCE board (Waveshare ESP32-S3 Touch LCD 1.28) - Replace verbose "Self-Balancing Control" STM32 section with brief note pointing to SAUL-TEE-SYSTEM-REFERENCE.md TEAM.md: Update Embedded Firmware Engineer role to ESP32-S3 / ESP-IDF No new functionality — cleanup only. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
97 lines
4.4 KiB
C
97 lines
4.4 KiB
C
#ifndef UART_PROTOCOL_H
|
||
#define UART_PROTOCOL_H
|
||
|
||
/*
|
||
* uart_protocol.h — UART command protocol for Jetson-STM32 communication (Issue #629)
|
||
*
|
||
* Frame format:
|
||
* [STX][LEN][CMD][PAYLOAD...][CRC8][ETX]
|
||
* 0x02 1B 1B 0-12 B 1B 0x03
|
||
*
|
||
* CRC8-SMBUS: poly=0x07, init=0x00, computed over CMD+PAYLOAD bytes.
|
||
*
|
||
* Physical layer: UART5 (PC12=TX / PD2=RX), GPIO_AF8_UART5, 115200 baud, no hw flow.
|
||
* NOTE: Spec requested USART1 @ 115200, but USART1 is occupied by JLink @ 921600.
|
||
* Implemented on UART5 instead; Jetson must connect to PC12/PD2.
|
||
*
|
||
* DMA: DMA1_Stream0_Channel4, circular 256-byte ring buffer.
|
||
* Heartbeat: if no frame received in UART_PROT_HB_TIMEOUT_MS (500 ms), Jetson is
|
||
* considered lost; caller must handle estop if needed.
|
||
*/
|
||
|
||
#include <stdint.h>
|
||
#include <stdbool.h>
|
||
|
||
/* ── Frame delimiters ─────────────────────────────────────────────────────── */
|
||
#define UPROT_STX 0x02u
|
||
#define UPROT_ETX 0x03u
|
||
|
||
/* ── Command IDs (host → STM32) ───────────────────────────────────────────── */
|
||
#define UCMD_SET_VELOCITY 0x01u /* payload: int16 left_rpm, int16 right_rpm (4 B) */
|
||
#define UCMD_GET_STATUS 0x02u /* payload: none */
|
||
#define UCMD_SET_PID 0x03u /* payload: float kp, float ki, float kd (12 B) */
|
||
#define UCMD_ESTOP 0x04u /* payload: none */
|
||
#define UCMD_CLEAR_ESTOP 0x05u /* payload: none */
|
||
|
||
/* ── Response IDs (STM32 → host) ──────────────────────────────────────────── */
|
||
#define URESP_ACK 0x80u /* payload: 1 B — echoed CMD */
|
||
#define URESP_NACK 0x81u /* payload: 2 B — CMD, error_code */
|
||
#define URESP_STATUS 0x82u /* payload: sizeof(uart_prot_status_t) = 8 B */
|
||
|
||
/* ── NACK error codes ─────────────────────────────────────────────────────── */
|
||
#define UERR_BAD_CRC 0x01u
|
||
#define UERR_BAD_LEN 0x02u
|
||
#define UERR_BAD_ETX 0x03u
|
||
#define UERR_ESTOP 0x04u /* command rejected — estop active */
|
||
#define UERR_DISARMED 0x05u /* velocity rejected — not armed */
|
||
|
||
/* ── STATUS payload (URESP_STATUS, 8 bytes packed) ───────────────────────── */
|
||
typedef struct __attribute__((packed)) {
|
||
int16_t pitch_x10; /* pitch angle ×10 deg (balance controller) */
|
||
int16_t motor_cmd; /* ESC motor command -1000..+1000 */
|
||
uint16_t vbat_mv; /* battery voltage in mV */
|
||
uint8_t balance_state; /* BalanceState enum (0=DISARMED, 1=ARMED, …) */
|
||
uint8_t estop_active; /* non-zero if remote estop is latched */
|
||
} uart_prot_status_t;
|
||
|
||
/* ── Shared state (read by main.c) ────────────────────────────────────────── */
|
||
typedef struct {
|
||
volatile uint8_t vel_updated; /* 1 when SET_VELOCITY received */
|
||
volatile int16_t left_rpm;
|
||
volatile int16_t right_rpm;
|
||
|
||
volatile uint8_t pid_updated; /* 1 when SET_PID received */
|
||
volatile float pid_kp;
|
||
volatile float pid_ki;
|
||
volatile float pid_kd;
|
||
|
||
volatile uint8_t estop_req; /* 1 on UCMD_ESTOP */
|
||
volatile uint8_t estop_clear_req; /* 1 on UCMD_CLEAR_ESTOP */
|
||
|
||
volatile uint32_t last_rx_ms; /* HAL_GetTick() of last valid frame */
|
||
} UartProtState;
|
||
|
||
extern UartProtState uart_prot_state;
|
||
|
||
/* ── API ───────────────────────────────────────────────────────────────────── */
|
||
|
||
/**
|
||
* uart_protocol_init() — configure UART5 + DMA, start circular receive.
|
||
* Must be called once during system init, before main loop.
|
||
*/
|
||
void uart_protocol_init(void);
|
||
|
||
/**
|
||
* uart_protocol_process() — drain DMA ring buffer, parse frames, dispatch commands.
|
||
* Call once per main loop iteration (every ~1 ms).
|
||
*/
|
||
void uart_protocol_process(void);
|
||
|
||
/**
|
||
* uart_protocol_send_status() — build and TX a URESP_STATUS frame.
|
||
* @param s Pointer to status payload to send.
|
||
*/
|
||
void uart_protocol_send_status(const uart_prot_status_t *s);
|
||
|
||
#endif /* UART_PROTOCOL_H */
|