Odrive 代码开发随笔(一)

说明:记录自己阅读源码的笔记。

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;
}

 

你可能感兴趣的:(odrive,odrvie)