fix(usb): MPU non-cacheable region + IWDG ordering fix (bd-3ulu) #10
@ -16,8 +16,21 @@ volatile uint8_t cdc_disarm_request = 0; /* set by D command */
|
|||||||
volatile uint8_t cdc_cmd_ready = 0;
|
volatile uint8_t cdc_cmd_ready = 0;
|
||||||
volatile char cdc_cmd_buf[32];
|
volatile char cdc_cmd_buf[32];
|
||||||
|
|
||||||
static uint8_t UserRxBuffer[256];
|
/*
|
||||||
static uint8_t UserTxBuffer[256];
|
* USB TX/RX buffers grouped into a single 512-byte aligned struct so that
|
||||||
|
* one MPU region (configured in usbd_conf.c) can mark them non-cacheable.
|
||||||
|
* Size must be a power-of-2 >= total size for MPU RASR SIZE encoding.
|
||||||
|
*/
|
||||||
|
static struct {
|
||||||
|
uint8_t tx[256];
|
||||||
|
uint8_t rx[256];
|
||||||
|
} __attribute__((aligned(512))) usb_nc_buf;
|
||||||
|
|
||||||
|
#define UserTxBuffer usb_nc_buf.tx
|
||||||
|
#define UserRxBuffer usb_nc_buf.rx
|
||||||
|
|
||||||
|
/* Exported so usbd_conf.c USB_NC_MPU_Config() can set the region base */
|
||||||
|
void * const usb_nc_buf_base = &usb_nc_buf;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Betaflight-proven DFU reboot:
|
* Betaflight-proven DFU reboot:
|
||||||
|
|||||||
@ -5,6 +5,33 @@
|
|||||||
#include "usbd_cdc.h"
|
#include "usbd_cdc.h"
|
||||||
#include "usbd_conf.h"
|
#include "usbd_conf.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mark USB TX/RX buffers non-cacheable via MPU Region 0.
|
||||||
|
* Cortex-M7 TEX=1, C=0, B=0 → Normal Non-cacheable.
|
||||||
|
* Called before HAL_PCD_Init() so the region is active before the USB
|
||||||
|
* hardware ever touches the buffers.
|
||||||
|
*/
|
||||||
|
extern void * const usb_nc_buf_base; /* defined in usbd_cdc_if.c */
|
||||||
|
|
||||||
|
static void USB_NC_MPU_Config(void)
|
||||||
|
{
|
||||||
|
MPU_Region_InitTypeDef r = {0};
|
||||||
|
HAL_MPU_Disable();
|
||||||
|
r.Enable = MPU_REGION_ENABLE;
|
||||||
|
r.Number = MPU_REGION_NUMBER0;
|
||||||
|
r.BaseAddress = (uint32_t)usb_nc_buf_base;
|
||||||
|
r.Size = MPU_REGION_SIZE_512B;
|
||||||
|
r.SubRegionDisable = 0x00;
|
||||||
|
r.TypeExtField = MPU_TEX_LEVEL1; /* TEX=1 */
|
||||||
|
r.AccessPermission = MPU_REGION_FULL_ACCESS;
|
||||||
|
r.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
|
||||||
|
r.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
|
||||||
|
r.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; /* C=0 */
|
||||||
|
r.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; /* B=0 */
|
||||||
|
HAL_MPU_ConfigRegion(&r);
|
||||||
|
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
PCD_HandleTypeDef hpcd;
|
PCD_HandleTypeDef hpcd;
|
||||||
|
|
||||||
void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
|
void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
|
||||||
@ -68,6 +95,7 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)
|
|||||||
hpcd.pData = pdev;
|
hpcd.pData = pdev;
|
||||||
pdev->pData = &hpcd;
|
pdev->pData = &hpcd;
|
||||||
|
|
||||||
|
USB_NC_MPU_Config(); /* Mark USB buffers non-cacheable before USB hardware init */
|
||||||
HAL_PCD_Init(&hpcd);
|
HAL_PCD_Init(&hpcd);
|
||||||
|
|
||||||
HAL_PCDEx_SetRxFiFo(&hpcd, 0x80);
|
HAL_PCDEx_SetRxFiFo(&hpcd, 0x80);
|
||||||
|
|||||||
19
src/crsf.c
Normal file
19
src/crsf.c
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* crsf.c — CRSF RC receiver stub (UART not yet wired on MAMBA F722S).
|
||||||
|
* crsf_state.last_rx_ms stays 0 so safety_rc_alive() always returns false,
|
||||||
|
* which keeps USB-only mode active (RC timeout disarm is commented out in main.c).
|
||||||
|
*/
|
||||||
|
#include "crsf.h"
|
||||||
|
|
||||||
|
volatile CRSFState crsf_state = {0};
|
||||||
|
|
||||||
|
void crsf_init(void) {}
|
||||||
|
|
||||||
|
void crsf_parse_byte(uint8_t byte) { (void)byte; }
|
||||||
|
|
||||||
|
int16_t crsf_to_range(uint16_t val, int16_t min, int16_t max)
|
||||||
|
{
|
||||||
|
/* CRSF range 172-1811 → linear map to [min, max] */
|
||||||
|
int32_t v = (int32_t)val;
|
||||||
|
return (int16_t)(min + (v - 172) * (max - min) / (1811 - 172));
|
||||||
|
}
|
||||||
18
src/main.c
18
src/main.c
@ -90,7 +90,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 */
|
/* DCache stays ON — MPU Region 0 in usbd_conf.c marks USB buffers non-cacheable. */
|
||||||
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();
|
||||||
@ -104,14 +104,6 @@ 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 */
|
||||||
|
|
||||||
/*
|
|
||||||
* IWDG starts after the USB enumeration delay — avoids spurious reset
|
|
||||||
* during the 3s startup hold. Once started, safety_refresh() MUST be
|
|
||||||
* called at least every WATCHDOG_TIMEOUT_MS (50ms) or MCU resets.
|
|
||||||
* IWDG cannot be stopped once started (hardware enforced).
|
|
||||||
*/
|
|
||||||
safety_init();
|
|
||||||
|
|
||||||
/* Init IMU (MPU6000 via SPI1 — mpu6000.c wraps icm42688 + complementary filter) */
|
/* Init IMU (MPU6000 via SPI1 — mpu6000.c wraps icm42688 + complementary filter) */
|
||||||
int imu_ret = mpu6000_init() ? 0 : -1;
|
int imu_ret = mpu6000_init() ? 0 : -1;
|
||||||
|
|
||||||
@ -122,6 +114,14 @@ int main(void) {
|
|||||||
balance_t bal;
|
balance_t bal;
|
||||||
balance_init(&bal);
|
balance_init(&bal);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IWDG starts AFTER all peripheral inits — avoids reset during mpu6000_init()
|
||||||
|
* which takes ~510ms (well above the 50ms WATCHDOG_TIMEOUT_MS).
|
||||||
|
* Once started, safety_refresh() MUST be called every WATCHDOG_TIMEOUT_MS
|
||||||
|
* or MCU resets. IWDG cannot be stopped once started (hardware enforced).
|
||||||
|
*/
|
||||||
|
safety_init();
|
||||||
|
|
||||||
char buf[256];
|
char buf[256];
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
|
|||||||
@ -16,8 +16,9 @@
|
|||||||
|
|
||||||
/* IWDG prescaler 32 → LSI(40kHz)/32 = 1250 ticks/sec → 0.8ms/tick */
|
/* IWDG prescaler 32 → LSI(40kHz)/32 = 1250 ticks/sec → 0.8ms/tick */
|
||||||
#define IWDG_PRESCALER IWDG_PRESCALER_32
|
#define IWDG_PRESCALER IWDG_PRESCALER_32
|
||||||
#define IWDG_TICK_MS (32.0f / 40.0f) /* 0.8ms per tick */
|
/* Integer formula: timeout_ms * LSI_HZ / (prescaler * 1000)
|
||||||
#define IWDG_RELOAD ((uint32_t)(WATCHDOG_TIMEOUT_MS / IWDG_TICK_MS))
|
* = WATCHDOG_TIMEOUT_MS * 40000 / (32 * 1000) = WATCHDOG_TIMEOUT_MS * 40 / 32 */
|
||||||
|
#define IWDG_RELOAD (WATCHDOG_TIMEOUT_MS * 40UL / 32UL)
|
||||||
|
|
||||||
#if IWDG_RELOAD > 4095
|
#if IWDG_RELOAD > 4095
|
||||||
# error "WATCHDOG_TIMEOUT_MS too large for IWDG_PRESCALER_32 — increase prescaler"
|
# error "WATCHDOG_TIMEOUT_MS too large for IWDG_PRESCALER_32 — increase prescaler"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user