fix(usb): resolve USB CDC TX failure — DCache coherency + buffer + IMU API (bd-1lo) #6

Merged
seb merged 1 commits from sl-firmware/bd-1lo-usb-cdc-fix into main 2026-02-28 12:52:43 -05:00
3 changed files with 20 additions and 14 deletions
Showing only changes of commit 0bfd617c44 - Show all commits

View File

@ -121,7 +121,6 @@ static int8_t CDC_Receive(uint8_t *buf, uint32_t *len) {
USBD_CDC_ItfTypeDef USBD_CDC_fops = { CDC_Init, CDC_DeInit, CDC_Control, CDC_Receive };
uint8_t CDC_Transmit(uint8_t *buf, uint16_t len) {
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)hUsbDevice.pClassData;
if (hcdc == NULL) return USBD_FAIL;
if (hcdc->TxState != 0) {
@ -130,6 +129,12 @@ uint8_t CDC_Transmit(uint8_t *buf, uint16_t len) {
if (++busy_count > 100) { hcdc->TxState = 0; busy_count = 0; }
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDevice, buf, len);
/* Always copy into the static UserTxBuffer so the USB hardware reads
* from a known fixed SRAM address never from the caller's stack.
* The USB TXFE IRQ fires asynchronously; a stack buffer could be
* overwritten by the time the FIFO is loaded. */
if (len > sizeof(UserTxBuffer)) len = sizeof(UserTxBuffer);
memcpy(UserTxBuffer, buf, len);
USBD_CDC_SetTxBuffer(&hUsbDevice, UserTxBuffer, len);
return USBD_CDC_TransmitPacket(&hUsbDevice);
}

View File

@ -104,7 +104,8 @@ int icm42688_init(void) {
HAL_GPIO_Init(MPU_CS_PORT, &gpio);
cs_high();
SCB_DisableDCache(); /* Avoid SPI DCache issues on F7 */
/* DCache is disabled at startup in main.c before USB/peripherals init.
* No SCB_DisableDCache() here calling it after USB starts corrupts USB state. */
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
@ -137,7 +138,8 @@ int icm42688_init(void) {
imu_type = 2;
ret = -99; /* TODO: ICM init */
} else {
ret = -who;
/* who==0 means no SPI response — must not return 0 (false success) */
ret = (who != 0) ? -(int)who : -128;
}
/* Speed up SPI for reads */

View File

@ -3,8 +3,7 @@
#include "usbd_cdc.h"
#include "usbd_cdc_if.h"
#include "usbd_desc.h"
#include "icm42688.h"
#include "bmp280.h"
#include "mpu6000.h"
#include "balance.h"
#include "hoverboard.h"
#include "config.h"
@ -54,6 +53,7 @@ void SysTick_Handler(void) { HAL_IncTick(); }
int main(void) {
SCB_EnableICache();
SCB_DisableDCache(); /* Must be off before USB starts — STM32F7 DCache/USB coherency */
checkForBootloader(); /* Check RTC magic BEFORE HAL_Init — must be first thing */
HAL_Init();
SystemClock_Config();
@ -67,8 +67,8 @@ int main(void) {
status_init();
HAL_Delay(3000); /* Wait for USB host to enumerate */
/* Init IMU */
int imu_ret = icm42688_init();
/* Init IMU (MPU6000 via SPI1 — mpu6000.c wraps icm42688 + complementary filter) */
int imu_ret = mpu6000_init() ? 0 : -1;
/* Init hoverboard ESC UART */
hoverboard_init();
@ -80,14 +80,14 @@ int main(void) {
char buf[256];
int len;
icm42688_data_t imu;
IMUData imu;
uint32_t send_tick = 0;
uint32_t balance_tick = 0;
uint32_t esc_tick = 0;
const float dt = 1.0f / PID_LOOP_HZ; /* 1ms at 1kHz */
while (1) {
if (imu_ret == 0) icm42688_read(&imu);
if (imu_ret == 0) mpu6000_read(&imu);
uint32_t now = HAL_GetTick();
@ -123,10 +123,9 @@ int main(void) {
send_tick = now;
if (imu_ret == 0) {
len = snprintf(buf, sizeof(buf),
"{\"ax\":%d,\"ay\":%d,\"az\":%d,\"gx\":%d,\"gy\":%d,\"gz\":%d,"
"\"p\":%d,\"m\":%d,\"s\":%d}\n",
imu.ax, imu.ay, imu.az, imu.gx, imu.gy, imu.gz,
(int)(bal.pitch_deg * 10), /* pitch x10 for precision without %f */
"{\"p\":%d,\"r\":%d,\"m\":%d,\"s\":%d}\n",
(int)(imu.pitch * 10), /* fused pitch degrees x10 */
(int)(imu.pitch_rate * 10), /* gyro pitch rate °/s x10 */
(int)bal.motor_cmd,
(int)bal.state);
} else {