说明:记录自己阅读源码的笔记。
1.目录说明
固件位于Firmare下面:
Board\V3: 板级文件,都是自带或者cube生成的,
----drivers:stm32库代码
----Inc:cube生成的头文件
----Src:cube生成的源文件 启动函数在main.c里面
----Middlewares:
----ST\STM32_USB_Device_Library:USB库
----Thired_Party/FreeRTOS: FreeRTOS库
----makefile 文件
----Odrive.ioc sm32Cube文件
build:编译过程文件以及最终的bin,hex等文件
communication: 通信相关文件
doctest:Catch2文件,自动生成的,没有用过,暂不理会.
Drivers\DRV8301: DRV8301驱动文件
fibre:fibre标准库,是一套上位机与下位机通信用的应用层协议,暂时不用管。
MotorControl:主要编程文件
----arm_cos_f32.c:CMSIS DSP 库 浮点数快速余弦计算
----arm_sin_f32.c: CMSIS DSP 库 浮点数快速正弦计算
----axis.cpp/axis.hpp void Axis::run_state_machine_loop() 为主要轴任务根据不同状态调用不同函数
----board_config_v3.h 定义底层的结构体
----controller.cpp/hpp 主要控制函数,update在这个文件里
----current_limiter.hpp
----encoder.cpp/hpp 编码器相关函数
----enstop.cpp/hpp 限位处理函数
----gpio_utils.hpp 获取gpio_port地址和GPIO_pin
----low_level.cpp/hpp adc,pwm,定时器底层相关。
----main.cpp 进行一些初始化,钩子函数设置,进入DFU模式等函数
----motor.cpp/hpp 电机控制,P_GIAN.I_GIAN,电压foc,电流FOC,测量相电阻电流等函数
----nvm_config.hpp,nvm.c/h 基于flash的非易失内存管理,stm32f405一共12个扇区,最后两个128k扇区用于数据保存
----odrive_main.h 头文件的包含
----sensorless_estimator.cpp/hpp
----thermistor.cpp/hpp 热敏电阻
----timer.hpp 看着像全局定时管理
----trapTraj.cpp/hpp 梯形轨迹规划
----utils.cpp/hpp get id,delay_us,SVM,快速atan2,dedline等相关函数
1.首先看 int main(void) 函数,此函数位于Firmware/Board/v3/Src/main.c中
首先是获取唯一ID作为USB num
接下来是常规初始化,
OC4_PWM_Override(&htim1); 是触发ADC用,保证和PWM同步
接下来是freertos初始化,和调度启动。
2.任务启动函数分析void MX_FREERTOS_Init(void)
创建了几个usb和uart的信号量,作为通信同步使用。
之后是创建启动任务StartDefaultTask。在启动任务里创建其他任务。
3.启动任务分析void StartDefaultTask(void * argument)
void StartDefaultTask(void * argument)
{
MX_USB_DEVICE_Init(); //初始化USB
odrive_main(); //调用Odrive主函数
vTaskDelete(defaultTaskHandle); //删除本任务
}
odrvie相关任务创建
int odrive_main(void) {
start_general_purpose_adc(); // 热敏电阻和用户ADC采集
// 串口使能
#if HW_VERSION_MAJOR == 3 && HW_VERSION_MINOR >= 3
if (odrv.config_.enable_uart) {
SetGPIO12toUART();
}
#endif
init_communication(); //创建通信任务,之后由通信任务分别创建串口任务,ucb任务和can任务
// Start pwm-in compare modules
// must happen after communication is initialized
pwm_in_init();
// Set up the CS pins for absolute encoders
for(auto& axis : axes){
if(axis->encoder_.config_.mode & Encoder::MODE_FLAG_ABS){
axis->encoder_.abs_spi_cs_pin_init();
}
}
// Setup motors (DRV8301 SPI transactions here)
for(auto& axis : axes){
axis->motor_.setup();
}
// Setup encoders (Starts encoder SPI transactions)
for(auto& axis : axes){
axis->encoder_.setup();
}
// Setup anything remaining in each axis
for(auto& axis : axes){
axis->setup();
}
// Start PWM and enable adc interrupts/callbacks
start_adc_pwm();
// This delay serves two purposes:
// - Let the current sense calibration converge (the current
// sense interrupts are firing in background by now)
// - Allow a user to interrupt the code, e.g. by flashing a new code,
// before it does anything crazy
// TODO make timing a function of calibration filter tau
osDelay(1500);
// Start state machine threads. Each thread will go through various calibration
// procedures and then run the actual controller loops.
// TODO: generalize for AXIS_COUNT != 2
for (size_t i = 0; i < AXIS_COUNT; ++i) {
axes[i]->start_thread(); } //创建用户轴控制任务。之后主要控制在这个创建的任务里
start_analog_thread(); //启动用户模拟量采集任务
odrv.system_stats_.fully_booted = true;
return 0;
}