ARTICLE · 1130650
ODrive V3.x源码分析之Firmware/Board
ODrive 固件板级目录分析(Firmware/Board)
分析对象:
ODrive\Firmware\Board分析日期:2026-10-05 基准提交:
3a2e4dd1(fw-v0.5.6-5-g3a2e4dd1)
1. 目录总览
Board目录下只有一个v3子目录
(v4.0-56V / v4.1-58V 只是在 Tupfile.lua 中占位,指向已移除的 Private/v4,无法编译,也就是说ODrive没有v4版本的源码)。
Board/└── v3/ ├── board.cpp ★板级对象实例化、初始化、中断服务(手写核心) ├── Inc/ 头文件目录 │ ├── board.h ★板级公共契约(宏/extern/函数原型) │ ├── main.h ★PWM时序常量 + 引脚宏(按板型分支) │ ├── mxconstants.h CubeMX导出旧命名引脚宏 │ ├── FreeRTOSConfig.h ★FreeRTOS内核配置 │ ├── adc.h / tim.h / gpio.h / dma.h / spi.h / usart.h / i2c.h / can.h │ ├── usb_device.h / usbd_cdc_if.h / usbd_conf.h / usbd_desc.h │ ├── stm32f4xx_hal_conf.h HAL模块开关 │ ├── stm32f4xx_it.h │ └── prev_board_ver/ main_V3_2.h / main_V3_4.h 历史板型引脚 ├── Src/ CubeMX生成外设初始化C文件 │ └── prev_board_ver/ adc_V3_2.c / gpio_V3_2.c ... ├── Makefile CubeMX导出清单,构建不使用 ├── Odrive.ioc CubeMX工程文件 ├── startup_stm32f405xx.s ★向量表 + Reset_Handler ├── STM32F405RGTx_FLASH.ld ★链接脚本(内存布局) └── STM32F40x.svd CMSIS-SVD调试寄存器描述
注意
:Board/v3/Makefile 中的 C_SOURCES 指向 Drivers/、Middlewares/ 等目录,这些目录在 Board/v3/ 下并不存在——它是 CubeMX 导出的模板,真正的构建由 Firmware/Tupfile.lua 完成(Firmware/Makefile 仅是 tup 入口)。
2. 仓库版本
2.1 该仓库可编译的版本(Firmware/Tupfile.lua:315-328)
v3.1 | -DHW_VERSION_MINOR=1 -DHW_VERSION_VOLTAGE=24 | |
v3.2 | MINOR=2VOLTAGE=24 | |
v3.3 | MINOR=3VOLTAGE=24 | |
v3.4-24V | MINOR=4VOLTAGE=24 | |
v3.4-48V | MINOR=4VOLTAGE=48 | |
v3.5-24V | MINOR=5VOLTAGE=24 | |
v3.5-48V | MINOR=5VOLTAGE=48 | |
v3.6-24V | MINOR=6VOLTAGE=24 | |
v3.6-56V | MINOR=6VOLTAGE=56 | |
v4.0-56Vv4.1-58V | -DSTM32F722xx -DHW_VERSION_MAJOR=4 | Private/v4,不可编译 |
HW_VERSION_MAJOR 由 board_v3 分组统一给出(=3),与 OTP 中字节 [3..5] 比对。
2.2 由编译器宏派生的硬件差异
SHUNT_RESISTANCE | HW_VERSION_MINOR <= 3675e-6f,否则 500e-6f(Inc/board.h:25-29) | |
DEFAULT_BRAKE_RESISTANCE | MINOR>=5 && VOLTAGE>=482.0f,否则 0.47f(Inc/board.h:40-44) | |
VBUS_S_DIVIDER_RATIO | VOLTAGE>=4819.0f,==24 → 11.0f(Inc/board.h:120-126) | |
MINOR>=3board.cpp:63-67) | ||
MINOR>=5board.cpp:139-145) | ||
gpios[] | MINORboard.cpp:159-227) | |
alternate_functions[] | MINOR>=3board.cpp:232-240) | |
pwm0_input | MINOR<=2{0,0,0,4}(仅通道 4),否则 {1,2,3,4}(board.cpp:257-261) | |
MINOR 1/2prev_board_ver/main_V3_2.h;3/4 → main_V3_4.h(Inc/main.h:59-65) |
3. Inc/board.h —— 板级公共契约
3.1 预处理宏(C/C++ 通用)
SHUNT_RESISTANCE | 675e-6f500e-6f | |
AXIS_COUNT | (2) | |
GPIO_COUNT | (17) | |
CAN_FREQ | (2000000UL) | |
DEFAULT_BRAKE_RESISTANCE | 2.0f0.47f Ω | |
DEFAULT_ERROR_PIN | 0 | |
DEFAULT_MIN_DC_VOLTAGE | 8.0f | |
DEFAULT_GPIO_MODES | ||
TIM_TIME_BASE | TIM14 | |
CONTROL_TIMER_PERIOD_TICKS | 2 * TIM_1_8_PERIOD_CLOCKS * (TIM_1_8_RCR + 1) | |
TIM1_INIT_COUNT | TIM_1_8_PERIOD_CLOCKS / 2 - 128 | |
MAX_CONTROL_LOOP_UPDATE_TO_CURRENT_UPDATE_DELTA | TIM_1_8_PERIOD_CLOCKS / 2 + 128 | |
CURRENT_MEAS_PERIOD | static const float current_meas_period(:114) | |
CURRENT_MEAS_HZ | static const int current_meas_hz(:118) | |
VBUS_S_DIVIDER_RATIO | 19.0f11.0f | |
CURRENT_SENSE_MIN_VOLT | 0.3f | |
CURRENT_SENSE_MAX_VOLT | 3.0f |
3.2 C++ 类型别名与包含(board.h:79-90)
#include <Drivers/DRV8301/drv8301.hpp>#include <Drivers/STM32/stm32_gpio.hpp>#include <Drivers/STM32/stm32_spi_arbiter.hpp>#include <MotorControl/pwm_input.hpp>#include <MotorControl/thermistor.hpp>using TGateDriver = Drv8301; // board.h:86using TOpAmp = Drv8301; // board.h:87 同一颗芯片兼任运放配置3.3 对外变量声明(board.h:92-109)
axes | std::array<Axis, AXIS_COUNT> | |
motors | Motor[AXIS_COUNT] | |
fet_thermistors | OnboardThermistorCurrentLimiter[AXIS_COUNT] | |
encoders | Encoder[AXIS_COUNT] | |
gpios | Stm32Gpio[GPIO_COUNT] | |
GpioFunction | struct { int mode; uint8_t alternate_function; } | |
alternate_functions | std::array<GpioFunction, 3>[GPIO_COUNT] | |
usb_dev_handle | USBD_HandleTypeDef& | |
ext_spi_arbiter | Stm32SpiArbiter& | |
uart_auart_b / uart_c | UART_HandleTypeDef* | |
pwm0_input | PwmInput |
3.4 板级配置读写桩(board.h:134-137)
static inline bool board_read_config() { return true; }static inline bool board_write_config() { return true; }static inline void board_clear_config() {}static inline bool board_apply_config() { return true; }// 注释原文:This board has no board-specific user configurations3.5 对外函数原型(board.h:139-141)
void system_init(); // HAL_Init + 时钟 + OTP 板型校验(board.cpp:272)bool board_init(); // 外设初始化 + 中断优先级 + DRV 复位(board.cpp:292)void start_timers(); // TIM1/TIM8/TIM13 同步启动 + ADC 触发使能(board.cpp:380)4. board.cpp —— 板级实例化、初始化与中断
4.1 文件级全局
TaskTimer::enabled | booltask_timer.hpp,注释说明不想为一行建文件) | |
SystemClock_Config | extern "C"Src/main.c | |
ControlLoop_IRQHandlerControlLoop_IRQn | OTG_HS_IRQHandler / OTG_HS_IRQn(复用未用的 HS USB 中断跑控制环) | |
fake_otp[...] | __attribute__((section(".testdata")))0x20000000;内容 {0,0,0, HW_VERSION_MAJOR, HW_VERSION_MINOR, HW_VERSION_VOLTAGE},OTP 未烧录时用于生产测试/兜底 | |
timestamp_ | volatile uint32_t | |
counting_down_ | volatile bool |
4.2 板级对象实例(board.cpp)
spi3_arbiter | Stm32SpiArbiter{&hspi3} | |
ext_spi_arbiter | spi3_arbiter(供外部编码器共享) | |
uart_a | &huart4 | |
uart_b | &huart2 | |
uart_c | nullptr | |
m0_gate_driver | Drv8301{&spi3_arbiter, {PC13,nCS}, {}, {PD2,nFAULT}} | |
m1_gate_driver | ||
fet_thermistor_poly_coeffs | {363.93910201, -462.15369634, 307.55129571, -27.72569531} | |
fet_thermistor_num_coeffs | ||
fet_thermistors[2] | ||
motor_thermistors[2] | ||
motors[2] | current_sensor_mask=0b110、1/SHUNT_RESISTANCE、gate driver + opamp + 两个温度计 | |
encoders[2] | &spi3_arbiter | |
endstops[4] | 2 * AXIS_COUNT | |
mechanical_brakes[2] | ||
sensorless_estimators[2] | ||
controllers[2] | ||
trap[2] | TrapezoidalTrajectory | |
axes | osPriorityHigh+1;轴 1:step/dir 按板型(GPIO7/8 或 3/4)、优先级 osPriorityHigh | |
gpios[] | ||
alternate_functions[GPIO_COUNT] | {模式, AF} | |
pwm0_input | PwmInput{&htim5, {1,2,3,4}}{0,0,0,4}) | |
usb_dev_handle | = hUsbDeviceFSextern 自 usbd_conf.c) |
4.3 gpios[] 引脚表
v3.5 / v3.6(board.cpp:204-224,GPIO_COUNT = 17):
{nullptr,0} | |||||
v3.3 / v3.4(:182-202):GPIO1-4 = PA0-PA3,GPIO5 = PB2,GPIO6-8 = 不存在(nullptr),ENC0_Z = PA15,ENC1_Z = PB3。
v3.1 / v3.2(:160-180):GPIO1 = PB2、GPIO2 = PA5、GPIO3 = PA4、GPIO4 = PA3、GPIO5-8 = 不存在,编码器/Z 同 v3.3。
4.4 alternate_functions[] 复用表(board.cpp:229-255)
UART_A → GPIO_AF8_UART4PWM → GPIO_AF2_TIM5(仅 MINOR>=3;否则空) | |
UART_B → GPIO_AF7_USART2PWM → GPIO_AF2_TIM5(仅 MINOR>=3) | |
UART_B → GPIO_AF7_USART2PWM → GPIO_AF2_TIM5 | |
ENC0 → GPIO_AF2_TIM3 | |
I2C_A → GPIO_AF4_I2C1ENC1 → GPIO_AF2_TIM4 | |
CAN_A → GPIO_AF9_CAN1I2C_A → GPIO_AF4_I2C1 |
ODrive::GPIO_MODE_*与ODriveIntf::GPIO_MODE_*等价(ODrive : ODriveIntf)。
4.5 初始化函数
check_board_version(const uint8_t* otp_ptr) — board.cpp:266-270
return (otp_ptr[3] == HW_VERSION_MAJOR) && (otp_ptr[4] == HW_VERSION_MINOR) && (otp_ptr[5] == HW_VERSION_VOLTAGE);system_init() — board.cpp:272-290
HAL_Init()SystemClock_Config()( main.c:160)读 FLASH_OTP_BASE;若首字节0xff(OTP 未烧录)→ 改用 RAM 中的fake_otp(:280-283)check_board_version()失败则 for (;;);死循环(:287-289)
board_init() — board.cpp:292-378
依次调用 MX_GPIO_Init / MX_DMA_Init / MX_ADC1_Init / MX_ADC2_Init / MX_TIM1_Init / MX_TIM8_Init / MX_TIM3_Init / MX_TIM4_Init / MX_SPI3_Init / MX_ADC3_Init / MX_TIM2_Init / MX_TIM5_Init / MX_TIM13_Init(:294-306)- EXTI 中断优先级 = 1
:EXTI0/1/2/3/4/9_5/15_10( :309-322)——高于 FreeRTOSconfigMAX_SYSCALL_INTERRUPT_PRIORITY(5),故只能裸用、不可调FromISRAPI ControlLoop_IRQn(= OTG_HS)优先级 5, TIM8_UP_TIM13_IRQn优先级 0(:324-328)按配置初始化 UART4 / USART2,并写入用户波特率( :330-338)若 enable_i2c_a:把 GPIO3/4/5 配为上拉输入,读 3 位拨码拼出 I2C 从机地址,调MX_I2C1_Init(addr)(:340-352)——地址= (0xD<<3) | strap,即基址0x68若 enable_can_a:校验gpio_modes[15]/[16]必须是GPIO_MODE_CAN_A,否则odrv.misconfigured_ = true(:354-361)调试停核冻结 TIM1/TIM8/TIM13( :363-366)- DRV8301 硬复位
: EN_GATE拉低 →delay_us(40)→ 拉高 →delay_us(20000)(:368-375)
start_timers() — board.cpp:380-416
在 CRITICAL_SECTION() 中:
临时关闭 ADC 触发( ADC_CR2_JEXTEN/EXTEN,:384-386)Stm32Timer::start_synchronously<3>({&htim1,&htim8,&htim13}, {TIM1_INIT_COUNT, 0, TIM1_INIT_COUNT/2}): TIM1 三角波领先 TIM8 90° TIM13 每次重装载对齐 TIM1 下计数更新事件( :388-397)恢复 ADC 触发(注入上升沿 / 规则上升沿, :399-401)清 JEOC/EOC/OVR 标志,使能 TIM8 更新中断( :403-414)
4.6 ADC 读取:fetch_and_reset_adcs()(static,board.cpp:418-451)
等待 ADC1.JEOC、ADC2.EOC|JEOC、ADC3.EOC|JEOC全部就绪,否则返回falsevbus_sense_adc_cb(ADC1->JDR1)( :428)→ 更新vbus_voltage轴 0: ADC2->JDR1= M0_IB、ADC3->JDR1= M0_IC(注入组),用motors[0].phase_current_from_adcval()换算,缺失相由-phB - phC补(:430-436)轴 1: ADC2->DR= M1_IB、ADC3->DR= M1_IC(规则组)(:438-444)两轴共用 ADC2/ADC3,靠注入组(M0)与规则组(M1)分流 清标志后返回 true(:446-450)
4.7 中断服务程序(extern "C",board.cpp:453-593)
HAL_SPI_TxCpltCallbackHAL_SPI_RxCpltCallback | HAL_SPI_TxRxCpltCallback | |
HAL_SPI_TxRxCpltCallback | hspi == &hspi3spi3_arbiter.on_complete() | |
TIM5_IRQHandler | pwm0_input.on_capture() | |
TIM8_UP_TIM13_IRQHandler | 采样节拍核心 | |
ControlLoop_IRQHandlerOTG_HS_IRQHandler) | 控制环核心 | |
I2C1_EV_IRQHandlerI2C1_ER_IRQHandler | HAL_I2C_EV/ER_IRQHandler | |
OTG_FS_IRQHandler | HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS) |
TIM8_UP_TIM13_IRQHandler(采样触发)
清 TIM8 更新标志;读 TIM8->CR1 DIR判断当前计数方向timer_update_missed = (counting_down_ == counting_down),若为真 → 两轴 disarm_with_error(ERROR_TIMER_UPDATE_MISSED)(:488-493)timestamp_ += TIM_1_8_PERIOD_CLOCKS * (TIM_1_8_RCR + 1)( :496)- 上计数
(采到 SVM 矢量 0,真实电流): TaskTimer::enabled = odrv.task_timers_armed_、odrv.sampling_cb()、NVIC->STIR = ControlLoop_IRQn软触发控制环(:498-503) - 下计数
(SVM 矢量 7,零电流):先把 TIM1/TIM8 六路 CCR全部暂设为 50% 占空比作为兜底,控制环若及时完成则覆盖(:504-515)
ControlLoop_IRQHandler(控制环)
fetch_and_reset_adcs()失败 → ERROR_BAD_TIMING(:526-529)若 TIM1/TIM8的BDTR.MOE未置位(下桥未导通、无法测流)→ 该轴电流置 0(:536-541)motors[0].current_meas_cb(timestamp - TIM1_INIT_COUNT, current0)、 motors[1].current_meas_cb(timestamp, current1)(:543-544)odrv.control_loop_cb(timestamp)( :546)等待 ADC2->SR & ADC_SR_EOC(计入task_times_.dc_calib_wait,:550-552)再次 fetch_and_reset_adcs()→motors[*].dc_calib_cb(...)(:554-560)motors[*].pwm_update_cb(timestamp + 3 * 周期 ...)( :562-563)校验 timestamp_是否恰好推进一个周期,否则ERROR_CONTROL_DEADLINE_MISSED(:568-571)关闭 TaskTimer::enabled,并task_timers_armed_收敛(:573-574)
5. CubeMX 生成层(Inc/ + Src/)
5.1 Src/main.c
SystemClock_Config() | ||
MX_FREERTOS_Init() | ||
main() | //int main)/ 93(#if 0) | 被 #if 0 禁用MotorControl/main.cpp 的 main() |
SystemClock_Config() | ||
HAL_TIM_PeriodElapsedCallback() | htim->Instance == TIM14HAL_IncTick() | |
_Error_Handler(char*, int) | ||
assert_failed() | USE_FULL_ASSERT 时编译 |
时钟树(main.c:160-211):
PLLM / PLLN / PLLP / PLLQ | 4 / 168 / DIV2 / 7 | |
SYSCLKSource | RCC_SYSCLKSOURCE_PLLCLK | |
AHBCLKDivider | RCC_SYSCLK_DIV1 | |
APB1CLKDivider | RCC_HCLK_DIV4 | |
APB2CLKDivider | RCC_HCLK_DIV2 | |
FLASH_LATENCY_5 | ||
HAL_RCC_GetHCLKFreq()/1000main.c:204),优先级 15(main.c:211) | ||
HSE_ONLSI_ON |
5.2 Inc/main.h —— PWM 时序常量与引脚
时序常量(v3.5/3.6 分支,main.h:69-75;v3.1-v3.4 走 prev_board_ver/*.h):
TIM_1_8_CLOCK_HZ | 168000000 | ||
TIM_1_8_PERIOD_CLOCKS | 3500 | ||
TIM_1_8_DEADTIME_CLOCKS | 20 | ||
TIM_APB1_CLOCK_HZ | 84000000 | ||
TIM_APB1_PERIOD_CLOCKS | 4096 | ||
TIM_APB1_DEADTIME_CLOCKS | 40 | ||
TIM_1_8_RCR | 2 |
推导:PWM 载波 = 168e6 / (2×3500) = 24 kHz;更新/采样/控制环频率 = 168e6 / (2×3500×3) = 8 kHz(= CURRENT_MEAS_HZ,Inc/board.h:117)。
引脚宏(main.h:77-156,v3.5/3.6 版,_Pin + _GPIO_Port 成对):分组如下——
M0_nCSM1_nCS(PC14)、EN_GATE(PB12)、nFAULT(PD2) | ||
M0_IBM0_IC(PC1)、M1_IB(PC3)、M1_IC(PC2) | ||
M0_AH/BL/CHM1_AH/BH/CH(PC6-8) | ||
M0_AL/BL/CLM1_BL/CL(PB0-1)、AUX_L/H(PB10-11) | ||
GPIO_1..GPIO_8 | ||
M0_TEMPM1_TEMP(PA4)、AUX_TEMP(PA5)、AUX_I(PA2)、AUX_V(PA6)、VBUS_S(PA6) | ||
M0_ENC_A/BM0_ENC_Z(PC9)、M1_ENC_A/B(PB6/7)、M1_ENC_Z(PC15) |
注意:
VBUS_S与AUX_V同为 PA6 ——mxconstants.h是另一套(历史)命名,两者不同时包含。
其他:_Error_Handler 原型与 Error_Handler() 宏(main.h:172-174)。Inc/mxconstants.h:CubeMX 导出的等价引脚宏(M0_TEMP/AUX_I/AUX_V/GPIO_1.. 等),命名与 main.h 略有出入,当前代码以 main.h 为准。
5.3 外设句柄与 MX_* 接口
Inc/adc.h | hadc1hadc2hadc3:64-66) | MX_ADC1_InitMX_ADC2_InitMX_ADC3_Init:74-76) |
Inc/tim.h | htim1htim2htim3htim4htim5htim8htim13:64-70) | MX_TIM1..TIM13_Init:78-84)、HAL_TIM_MspPostInit(:86) |
Inc/gpio.h | MX_GPIO_Init:68) | |
Inc/dma.h | MX_DMA_Init:72) | |
Inc/spi.h | hspi3:64) | MX_SPI3_Init:72) |
Inc/usart.h | huart4huart2:64-65) | MX_UART4_InitMX_USART2_UART_Init:73-74) |
Inc/i2c.h | hi2c1:64) | MX_I2C1_Init(uint8_t addr):72) |
Inc/can.h | hcan1:64) | MX_CAN1_Init:72)——实现被注释,实际由 ODriveCAN::start_server() 配置 |
Inc/usb_device.h | hUsbDeviceFS:82) | MX_USB_DEVICE_Init:94) |
Inc/usbd_cdc_if.h | USBD_Interface_fops_FS:121) |
MX_CAN1_Init 在 Src/can.c:73-105 整段被注释,只保留 hcan1 结构体初始化(can.c:59-73)。
5.4 各外设配置要点
| adc.c | hadc1VBUS_S,软件触发) | 81-113 |
hadc2M1_IB)触发源 ADC_EXTERNALTRIGCONV_T8_TRGO;注入 CH10(M0_IB) | 133-166 | |
hadc3M1_IC)触发 T8_TRGO;注入 CH11(M0_IC) | 185-217 | |
hdma_adc1DMA2_Stream0 / CHANNEL_0、半字、DMA_CIRCULAR | 264-279 | |
ADC_SAMPLETIME_3CYCLES | 101/112/153/164/205/216 | |
| tim.c | htim1Period=TIM_1_8_PERIOD_CLOCKS、RCR=TIM_1_8_RCR、TRGO_UPDATE、PWM CH1-3 + OC CH4、死区 TIM_1_8_DEADTIME_CLOCKS | 76-144 |
htim8TRGO_UPDATE,死区 20 | 306-352 | |
htim2Period=TIM_APB1_PERIOD_CLOCKS(4096)、PWM CH3/CH4(AUX 输出) | 159-186 | |
htim3htim4:编码器模式、Period=0xffff、双通道 ICPSC_DIV1 | 201-252 | |
htim5Period=0xFFFFFFFF、输入捕获 CH3/CH4(PWM 输入) | 267-292 | |
htim13Period = (2×3500×3)×(84M/168M) − 1 = 10499 → 8 kHz | 365-368 | |
| gpio.c | MX_GPIO_Init | 输出高、EN_GATE 输出低、M1_ENC_Z |
| dma.c | DMA1_Stream0=4(SPI RX)、DMA1_Stream7=3(SPI TX,需高于 RX)、Stream2/4/5/6=10;DMA2_Stream0 被注释(改在 low_level.cpp 中动态使能) | 75-98 |
| spi.c | hspi3/16 分频、MSB 先行、CRC 关 | 69-79120/145 |
| usart.c | huart4huart2:8N1、无流控、16 倍过采样;波特率行被注释,实际由 board_init() 用 odrv.config_.uart_*_baudrate 写入 | 72-97 |
| i2c.c | MX_I2C1_Init(addr)OwnAddress1 = addr << 1 | 65-76 |
| can.c | hcan1Prescaler=8、SJW_4TQ、BS1_16TQ、BS2_4TQ、AutoBusOff/AutoWakeUp/AutoRetransmission=ENABLE | 59-73 |
CAN 波特率推导:PCLK1 = 42 MHz,位时间 = 1(sync)+16(BS1)+4(BS2) = 21 TQ,故 CAN_FREQ = 42e6/21 = 2 MHz 是「每个 prescaler 计数对应的波特率基数」,prescaler = CAN_FREQ / baud_rate(communication/can/odrive_can.cpp:31)。默认 baud_rate = CAN_BAUD_250K(communication/can/odrive_can.hpp:25),即 prescaler = 8,位速率 = 42e6/(8×21) = 250 kbit/s,与 can.c 静态值一致。
5.5 Src/stm32f4xx_it.c 中断向量
DMA1_Stream0_IRQHandler | ||
DMA1_Stream2_IRQHandler | ||
DMA1_Stream4_IRQHandler | ||
DMA1_Stream5_IRQHandler | ||
DMA1_Stream6_IRQHandler | ||
DMA1_Stream7_IRQHandler | ||
CAN1_TX_IRQHandler | ||
CAN1_RX0_IRQHandler | ||
CAN1_RX1_IRQHandler | ||
CAN1_SCE_IRQHandler | ||
USART2_IRQHandler | ||
TIM8_TRG_COM_TIM14_IRQHandler | ||
SPI3_IRQHandler | ||
UART4_IRQHandler |
不在本文件的中断:
OTG_HS_IRQn(控制环)、TIM8_UP_TIM13_IRQn、TIM5_IRQn、I2C1_EV/ER、OTG_FS_IRQn、EXTI*—— 它们全部在board.cpp:453-593或Drivers/STM32/stm32_gpio.cpp中实现。
5.6 Inc/FreeRTOSConfig.h
configUSE_PREEMPTION | 1 | |
configSUPPORT_STATIC/DYNAMIC_ALLOCATION | 01 | |
configUSE_IDLE_HOOK | 1 | |
configCPU_CLOCK_HZ | SystemCoreClock | |
configTICK_RATE_HZ | 1000 | |
configMAX_PRIORITIES | 7 | |
configMINIMAL_STACK_SIZE | 128 | |
configTOTAL_HEAP_SIZE | 65536ucHeap 放在 CCMRAM) | |
configUSE_MUTEXES | 1 | |
configCHECK_FOR_STACK_OVERFLOW | 1 | |
configUSE_PORT_OPTIMISED_TASK_SELECTION | 1 | |
configLIBRARY_LOWEST_INTERRUPT_PRIORITY | 15 | |
configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY | 5 | |
configASSERT(x) | ||
configAPPLICATION_ALLOCATED_HEAP | 1freertos.c/main.cpp 提供) |
Src/freertos.c:
StartDefaultTask | |
MX_FREERTOS_Init | |
osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, stack_size_default_task / sizeof(StackType_t)) | |
StartDefaultTask()MX_USB_DEVICE_Init() 后空转,实际启动流程在 main.cpp 的 rtos_main 中接管) | |
__weak vApplicationIdleHook() | |
__weak vApplicationStackOverflowHook() |
5.7 USB 栈
Src/usb_device.c | MX_USB_DEVICE_Init()USBD_Init → USBD_RegisterClass(&USBD_CDC) → USBD_CDC_RegisterInterface(&USBD_Interface_fops_FS) → USBD_Start | 93-106 |
Src/usbd_cdc_if.c | USBD_Interface_fops_FS{CDC_Init_FS, CDC_DeInit_FS, CDC_Control_FS, CDC_Receive_FS} | 156-162 |
CDC_Init_FS()CDC_DeInit_FS() → osMessagePut(usb_event_queue, 1/2, 0) | 169182 | |
CDC_Control_FS(cmd, pbuf, len) | 197 | |
CDC_Receive_FS(Buf, Len, endpoint_pair) | 283 | |
CDC_Transmit_FS(Buf, Len, endpoint_pair) | 303 | |
Inc/usbd_cdc_if.h | USB_RX_DATA_SIZEUSB_TX_DATA_SIZE = 64 | 81-83 |
Src/usbd_desc.c | USBD_VID = 0x1209USBD_PID_FS = 0x0D32、USBD_LANGID_STRING = 1033 | 94-97 |
USBD_MANUFACTURER_STRING = "ODrive Robotics" | 96 | |
USBD_PRODUCT_STRING_FS"ODrive HW_VERSION_MAJOR.HW_VERSION_MINOR CDC Interface" | 100 | |
NATIVE_STRING"... Native Interface"(fibre 端点用) | 101 | |