fix(usb): resolve USB CDC TX failure — DCache coherency + buffer + IMU API (bd-1lo) #6
@ -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 };
|
USBD_CDC_ItfTypeDef USBD_CDC_fops = { CDC_Init, CDC_DeInit, CDC_Control, CDC_Receive };
|
||||||
|
|
||||||
uint8_t CDC_Transmit(uint8_t *buf, uint16_t len) {
|
uint8_t CDC_Transmit(uint8_t *buf, uint16_t len) {
|
||||||
|
|
||||||
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)hUsbDevice.pClassData;
|
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)hUsbDevice.pClassData;
|
||||||
if (hcdc == NULL) return USBD_FAIL;
|
if (hcdc == NULL) return USBD_FAIL;
|
||||||
if (hcdc->TxState != 0) {
|
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; }
|
if (++busy_count > 100) { hcdc->TxState = 0; busy_count = 0; }
|
||||||
return USBD_BUSY;
|
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);
|
return USBD_CDC_TransmitPacket(&hUsbDevice);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -104,7 +104,8 @@ int icm42688_init(void) {
|
|||||||
HAL_GPIO_Init(MPU_CS_PORT, &gpio);
|
HAL_GPIO_Init(MPU_CS_PORT, &gpio);
|
||||||
cs_high();
|
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.Instance = SPI1;
|
||||||
hspi1.Init.Mode = SPI_MODE_MASTER;
|
hspi1.Init.Mode = SPI_MODE_MASTER;
|
||||||
@ -137,7 +138,8 @@ int icm42688_init(void) {
|
|||||||
imu_type = 2;
|
imu_type = 2;
|
||||||
ret = -99; /* TODO: ICM init */
|
ret = -99; /* TODO: ICM init */
|
||||||
} else {
|
} 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 */
|
/* Speed up SPI for reads */
|
||||||
|
|||||||
19
src/main.c
19
src/main.c
@ -3,8 +3,7 @@
|
|||||||
#include "usbd_cdc.h"
|
#include "usbd_cdc.h"
|
||||||
#include "usbd_cdc_if.h"
|
#include "usbd_cdc_if.h"
|
||||||
#include "usbd_desc.h"
|
#include "usbd_desc.h"
|
||||||
#include "icm42688.h"
|
#include "mpu6000.h"
|
||||||
#include "bmp280.h"
|
|
||||||
#include "balance.h"
|
#include "balance.h"
|
||||||
#include "hoverboard.h"
|
#include "hoverboard.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
@ -54,6 +53,7 @@ void SysTick_Handler(void) { HAL_IncTick(); }
|
|||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
SCB_EnableICache();
|
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 */
|
checkForBootloader(); /* Check RTC magic BEFORE HAL_Init — must be first thing */
|
||||||
HAL_Init();
|
HAL_Init();
|
||||||
SystemClock_Config();
|
SystemClock_Config();
|
||||||
@ -67,8 +67,8 @@ int main(void) {
|
|||||||
status_init();
|
status_init();
|
||||||
HAL_Delay(3000); /* Wait for USB host to enumerate */
|
HAL_Delay(3000); /* Wait for USB host to enumerate */
|
||||||
|
|
||||||
/* Init IMU */
|
/* Init IMU (MPU6000 via SPI1 — mpu6000.c wraps icm42688 + complementary filter) */
|
||||||
int imu_ret = icm42688_init();
|
int imu_ret = mpu6000_init() ? 0 : -1;
|
||||||
|
|
||||||
/* Init hoverboard ESC UART */
|
/* Init hoverboard ESC UART */
|
||||||
hoverboard_init();
|
hoverboard_init();
|
||||||
@ -80,14 +80,14 @@ int main(void) {
|
|||||||
char buf[256];
|
char buf[256];
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
icm42688_data_t imu;
|
IMUData imu;
|
||||||
uint32_t send_tick = 0;
|
uint32_t send_tick = 0;
|
||||||
uint32_t balance_tick = 0;
|
uint32_t balance_tick = 0;
|
||||||
uint32_t esc_tick = 0;
|
uint32_t esc_tick = 0;
|
||||||
const float dt = 1.0f / PID_LOOP_HZ; /* 1ms at 1kHz */
|
const float dt = 1.0f / PID_LOOP_HZ; /* 1ms at 1kHz */
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (imu_ret == 0) icm42688_read(&imu);
|
if (imu_ret == 0) mpu6000_read(&imu);
|
||||||
|
|
||||||
uint32_t now = HAL_GetTick();
|
uint32_t now = HAL_GetTick();
|
||||||
|
|
||||||
@ -123,10 +123,9 @@ int main(void) {
|
|||||||
send_tick = now;
|
send_tick = now;
|
||||||
if (imu_ret == 0) {
|
if (imu_ret == 0) {
|
||||||
len = snprintf(buf, sizeof(buf),
|
len = snprintf(buf, sizeof(buf),
|
||||||
"{\"ax\":%d,\"ay\":%d,\"az\":%d,\"gx\":%d,\"gy\":%d,\"gz\":%d,"
|
"{\"p\":%d,\"r\":%d,\"m\":%d,\"s\":%d}\n",
|
||||||
"\"p\":%d,\"m\":%d,\"s\":%d}\n",
|
(int)(imu.pitch * 10), /* fused pitch degrees x10 */
|
||||||
imu.ax, imu.ay, imu.az, imu.gx, imu.gy, imu.gz,
|
(int)(imu.pitch_rate * 10), /* gyro pitch rate °/s x10 */
|
||||||
(int)(bal.pitch_deg * 10), /* pitch x10 for precision without %f */
|
|
||||||
(int)bal.motor_cmd,
|
(int)bal.motor_cmd,
|
||||||
(int)bal.state);
|
(int)bal.state);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user