BetaFlight开源代码框架简介
BetaFlight开源代码框架简介
- 1. 框架设计分析考量
- 2. 框架分析前提条件
- 3. 主程序框架
- 4. 调度框架
- 5. 模块方法
- 6. 典型任务&模块
- 6.1 典型任务
- 6.2 典型模块
- 6.3 传感模块
- 7. 回顾
- 8. 分析模板
1. 框架设计分析考量
框架设计重点要做到各切分模块的业务融合,分析的主要考量点:
- 突出业务框架逻辑
- 从框架引入模块概念
- 功能模块化实现方法
- 性能及优化实现方法
2. 框架分析前提条件
- 【打开】所有功能代码宏定义,以便有全局性了解
- 【忽略】UNIT_TEST等测试代码,暂不考虑自测
- 【侧重】框架代码逻辑实现,突出业务框架逻辑
- 【忽略】框架算法逻辑伪代码处理,强调概念
- 【举例】模块分析方法(配典型模块入门分析)
3. 主程序框架
C语言工程代码函数入口为main,之前启动及C环境初始化代码不做介绍,启动文件代码文件(lib\main\STM32H7\Drivers\CMSIS\Device\ST\STM32H7xx\Source\Templates\arm\startup_stm32h745xx.s)。业务逻辑方面主要是从main来分析框架代码,这里也不会对HAL(Hardware Adapter Layer)做分析,对底层感兴趣的朋友可以从STM官网或者其他网站得到更多的STM32开发方面的资讯。
这里着重飞控业务&功能方面的学习和简介,所以回归话题,从main入口进入后,主程序框架分为两部分:初始化(init)和调度执行(schedule)。
main├──> init│ ├──> ... // module initialization code here│ └──> tasksInit└──> run├──> scheduler // NOT normal OS scheduler, quite special related to flight control task prioirty└──> SIMULATOR_BUILD // if simulation enabled, baremetal loop for max rate 20kHz NOT full CPU└──> delayMicroseconds_real(50)└──> microsleep└──> nanosleep
4. 调度框架
这里为什么说调度框架,主要是由于这个schedule和操作系统常规的OS调度不太一样,它有业务相关的特殊处理部分。因此,从概念上来说,调度器和业务是紧耦合。
目前其他的一些开源飞控代码用到OS的有nuttx,chibios等。后续我们如果介绍Paparazzi项目就会用到chibios。这里BetaFlight可能由于其发展历史,沿用了目前裸奔+业务调度的方式。
scheduler├──> <陀螺仪使能>│ ├──> <修正调度异常剩余时间> //其他耗时任务导致任务调度时间不足,比如USB任务│ ├──> <修正调度触发阈值时间> //调度代码耗散时间,控制接近边界 schedLoopStartMinCycles,调整粒度schedLoopStartDeltaUpCycles│ └──> <触发调度> // schedLoopRemainingCycles < schedLoopStartCycles│ ├──> <修正调度触发阈值时间> //控制接近边界 schedLoopStartMinCycles,调整粒度schedLoopStartDeltaDownCycles│ ├──> [精准对齐调度触发时间]│ ├──> schedulerExecuteTask(gyroTask, currentTimeUs); //执行陀螺仪传感任务│ ├──> schedulerExecuteTask(getTask(TASK_FILTER), currentTimeUs); //按比例执行过滤任务│ ├──> schedulerExecuteTask(getTask(TASK_PID), currentTimeUs); //按比例执行PID任务│ ├──> rxFrameCheck //检查接收机数据│ ├──> [故障保护模式检查]│ └──> <使用陀螺仪外部中断模式锁定调度器时间>├──> [更新调度器剩余时间,schedLoopRemainingCycles]└──> <陀螺仪不使能 或者 调度剩余时间大于非实时任务检查时间>├──> [更新所有非实时任务的任务动态优先级]│ ├──> <事件驱动任务>│ │ ├──> <执行任务checkFunc,并更新任务动态优先级>│ │ └──> <已执行checkFunc,未调度执行任务,继续提升任务动态优先级>│ ├──> <时间驱动任务>│ │ └──> [更新基于上次调度与当前时间间隔的任务动态优先级]│ └──> <挑选最高优先级任务,并计算剩余执行时间> //TASK_SERIAL只要优先级够,就直接执行不进行阻塞├──> [更新checkCycles,所有非实时任务最优任务选择本次计算时间]└──> <有高优先级任务选中>├──> [更新taskRequiredTimeCycles和schedLoopRemainingCycles数据]├──> <陀螺仪不使能 或者 (taskRequiredTimeCycles < schedLoopRemainingCycles)>│ ├──> schedulerExecuteTask(selectedTask, currentTimeUs); //执行选中高优先级任务│ ├──> [TASK_OSD/TASK_RX, skippedRxAttempts/skippedOSDAttempts清零]│ └──> [修正taskGuardCycles,以便下次更精确的预估执行时间]└──> <TASK_OSD/TASK_RX 或者 (taskAgePeriods > TASK_AGE_EXPEDITE_COUNT)>└──> [能找TASK_AGE_EXPEDITE_SCALE比率缩短任务预计时间]
注:目前4.3代码只有3个实时任务:GYRO、FILTER、PID。
5. 模块方法
基于主程序框架和调度框架,一个模块涉及以下几部分:
- 初始化
- 硬件初始化
- 业务初始化
- 任务
- 实时任务
- 事件任务
- 时间任务
- 驱动
- 查询
- 中断
- 接口
6. 典型任务&模块
6.1 典型任务
- BetaFlight模块设计之一:系统任务模块分析
- BetaFlight模块设计之二:SERIAL任务分析
- BetaFlight模块设计之三:芯片温度&参考电压和电池监测模块分析
- BetaFlight模块设计之四:ESC传感任务分析
- BetaFlight模块设计之五:最大栈使用量监测
- BetaFlight模块设计之六:Beeper任务分析
- BetaFlight模块设计之七:LEDSTRIP任务分析
- BetaFlight模块设计之八:GPS任务分析
- BetaFlight模块设计之九:气压计任务分析
- BetaFlight模块设计之十:磁力计任务分析
- BetaFlight模块设计之十一:Gyro&Acc任务分析
- BetaFlight模块设计之十二:电传任务分析
- BetaFlight模块设计之十三:Gyro过滤任务分析
- BetaFlight模块设计之十四:高度计算任务分析
- BetaFlight模块设计之十五:RunCam设备任务分析
- BetaFlight模块设计之十六:OSD更新任务分析
- BetaFlight模块设计之十七:pinioBox任务分析
- BetaFlight模块设计之十八:图传模块同步任务分析
- BetaFlight模块设计之十九:摄像头按键控制模拟任务分析
- BetaFlight模块设计之二十:CMS菜单模块分析
- BetaFlight模块设计之二十一:dashboard任务分析
- BetaFlight模块设计之二十二:地面测距任务分析
- BetaFlight模块设计之二十三:CRSF V3串口速率协商任务分析
- BetaFlight模块设计之二十四:transponder任务分析
- BetaFlight模块设计之二十五:dispatch任务分析
- BetaFlight模块设计之二十六:接收机任务分析
- BetaFlight模块设计之二十七:姿态更新任务分析
- BetaFlight模块设计之二十八:MainPidLoop任务分析
任务相关的分析基本结束,因为看的节奏比较快,时间也仓促,所以肯定存在诸多问题,希望能通过交流,大家多留言给出错误的批示,以便我尽快纠正。
6.2 典型模块
关于软件模块,会尽量一点点的补充详细起来,以便对飞控的具体细节方面更加透彻的理解。
- BetaFlight模块设计之二十九:滤波模块分析
- BetaFlight模块设计之三十:Cli模块分析
- BetaFlight模块设计之三十一:blackbox模块分析
- BetaFlight模块设计之三十二:MSP协议模块分析
- BetaFlight模块设计之三十三:Pid模块分析
- BetaFlight模块设计之三十四:OSD模块分析
- BetaFlight模块设计之三十五:RSSI信号强度&链路稳定性分析
6.3 传感模块
深入传感数据,挖掘物理特性与飞控之间的关系,请查阅:BetaFlight深入传感设计:传感模块设计框架
7. 回顾
基于上述代码框架,BetaFlight从大块任务切分的角度看,需要深入分析和理解下面的各个任务模块。这也为后续分析代码提供了方向。
注:后续有时间将会深入每个任务和模块进行分析。
// Task ID data in .data (initialised data)
task_attribute_t task_attributes[TASK_COUNT] = {[TASK_SYSTEM] = DEFINE_TASK("SYSTEM", "LOAD", NULL, taskSystemLoad, TASK_PERIOD_HZ(10), TASK_PRIORITY_MEDIUM_HIGH),[TASK_MAIN] = DEFINE_TASK("SYSTEM", "UPDATE", NULL, taskMain, TASK_PERIOD_HZ(1000), TASK_PRIORITY_MEDIUM_HIGH),[TASK_SERIAL] = DEFINE_TASK("SERIAL", NULL, NULL, taskHandleSerial, TASK_PERIOD_HZ(100), TASK_PRIORITY_LOW), // 100 Hz should be enough to flush up to 115 bytes @ 115200 baud[TASK_BATTERY_ALERTS] = DEFINE_TASK("BATTERY_ALERTS", NULL, NULL, taskBatteryAlerts, TASK_PERIOD_HZ(5), TASK_PRIORITY_MEDIUM),[TASK_BATTERY_VOLTAGE] = DEFINE_TASK("BATTERY_VOLTAGE", NULL, NULL, batteryUpdateVoltage, TASK_PERIOD_HZ(SLOW_VOLTAGE_TASK_FREQ_HZ), TASK_PRIORITY_MEDIUM), // Freq may be updated in tasksInit[TASK_BATTERY_CURRENT] = DEFINE_TASK("BATTERY_CURRENT", NULL, NULL, batteryUpdateCurrentMeter, TASK_PERIOD_HZ(50), TASK_PRIORITY_MEDIUM),#ifdef USE_TRANSPONDER[TASK_TRANSPONDER] = DEFINE_TASK("TRANSPONDER", NULL, NULL, transponderUpdate, TASK_PERIOD_HZ(250), TASK_PRIORITY_LOW),
#endif#ifdef USE_STACK_CHECK[TASK_STACK_CHECK] = DEFINE_TASK("STACKCHECK", NULL, NULL, taskStackCheck, TASK_PERIOD_HZ(10), TASK_PRIORITY_LOWEST),
#endif[TASK_GYRO] = DEFINE_TASK("GYRO", NULL, NULL, taskGyroSample, TASK_GYROPID_DESIRED_PERIOD, TASK_PRIORITY_REALTIME),[TASK_FILTER] = DEFINE_TASK("FILTER", NULL, NULL, taskFiltering, TASK_GYROPID_DESIRED_PERIOD, TASK_PRIORITY_REALTIME),[TASK_PID] = DEFINE_TASK("PID", NULL, NULL, taskMainPidLoop, TASK_GYROPID_DESIRED_PERIOD, TASK_PRIORITY_REALTIME),
#ifdef USE_ACC[TASK_ACCEL] = DEFINE_TASK("ACC", NULL, NULL, taskUpdateAccelerometer, TASK_PERIOD_HZ(1000), TASK_PRIORITY_MEDIUM),[TASK_ATTITUDE] = DEFINE_TASK("ATTITUDE", NULL, NULL, imuUpdateAttitude, TASK_PERIOD_HZ(100), TASK_PRIORITY_MEDIUM),
#endif[TASK_RX] = DEFINE_TASK("RX", NULL, rxUpdateCheck, taskUpdateRxMain, TASK_PERIOD_HZ(33), TASK_PRIORITY_HIGH), // If event-based scheduling doesn't work, fallback to periodic scheduling[TASK_DISPATCH] = DEFINE_TASK("DISPATCH", NULL, NULL, dispatchProcess, TASK_PERIOD_HZ(1000), TASK_PRIORITY_HIGH),#ifdef USE_BEEPER[TASK_BEEPER] = DEFINE_TASK("BEEPER", NULL, NULL, beeperUpdate, TASK_PERIOD_HZ(100), TASK_PRIORITY_LOW),
#endif#ifdef USE_GPS[TASK_GPS] = DEFINE_TASK("GPS", NULL, NULL, gpsUpdate, TASK_PERIOD_HZ(TASK_GPS_RATE), TASK_PRIORITY_MEDIUM), // Required to prevent buffer overruns if running at 115200 baud (115 bytes / period < 256 bytes buffer)
#endif#ifdef USE_MAG[TASK_COMPASS] = DEFINE_TASK("COMPASS", NULL, NULL, taskUpdateMag, TASK_PERIOD_HZ(10), TASK_PRIORITY_LOW),
#endif#ifdef USE_BARO[TASK_BARO] = DEFINE_TASK("BARO", NULL, NULL, taskUpdateBaro, TASK_PERIOD_HZ(20), TASK_PRIORITY_LOW),
#endif#if defined(USE_BARO) || defined(USE_GPS)[TASK_ALTITUDE] = DEFINE_TASK("ALTITUDE", NULL, NULL, taskCalculateAltitude, TASK_PERIOD_HZ(40), TASK_PRIORITY_LOW),
#endif#ifdef USE_DASHBOARD[TASK_DASHBOARD] = DEFINE_TASK("DASHBOARD", NULL, NULL, dashboardUpdate, TASK_PERIOD_HZ(10), TASK_PRIORITY_LOW),
#endif#ifdef USE_OSD[TASK_OSD] = DEFINE_TASK("OSD", NULL, osdUpdateCheck, osdUpdate, TASK_PERIOD_HZ(OSD_FRAMERATE_DEFAULT_HZ), TASK_PRIORITY_LOW),
#endif#ifdef USE_TELEMETRY[TASK_TELEMETRY] = DEFINE_TASK("TELEMETRY", NULL, NULL, taskTelemetry, TASK_PERIOD_HZ(250), TASK_PRIORITY_LOW),
#endif#ifdef USE_LED_STRIP[TASK_LEDSTRIP] = DEFINE_TASK("LEDSTRIP", NULL, NULL, ledStripUpdate, TASK_PERIOD_HZ(100), TASK_PRIORITY_LOW),
#endif#ifdef USE_BST[TASK_BST_MASTER_PROCESS] = DEFINE_TASK("BST_MASTER_PROCESS", NULL, NULL, taskBstMasterProcess, TASK_PERIOD_HZ(50), TASK_PRIORITY_LOWEST),
#endif#ifdef USE_ESC_SENSOR[TASK_ESC_SENSOR] = DEFINE_TASK("ESC_SENSOR", NULL, NULL, escSensorProcess, TASK_PERIOD_HZ(100), TASK_PRIORITY_LOW),
#endif#ifdef USE_CMS[TASK_CMS] = DEFINE_TASK("CMS", NULL, NULL, cmsHandler, TASK_PERIOD_HZ(20), TASK_PRIORITY_LOW),
#endif#ifdef USE_VTX_CONTROL[TASK_VTXCTRL] = DEFINE_TASK("VTXCTRL", NULL, NULL, vtxUpdate, TASK_PERIOD_HZ(5), TASK_PRIORITY_LOWEST),
#endif#ifdef USE_RCDEVICE[TASK_RCDEVICE] = DEFINE_TASK("RCDEVICE", NULL, NULL, rcdeviceUpdate, TASK_PERIOD_HZ(20), TASK_PRIORITY_MEDIUM),
#endif#ifdef USE_CAMERA_CONTROL[TASK_CAMCTRL] = DEFINE_TASK("CAMCTRL", NULL, NULL, taskCameraControl, TASK_PERIOD_HZ(5), TASK_PRIORITY_LOW),
#endif#ifdef USE_ADC_INTERNAL[TASK_ADC_INTERNAL] = DEFINE_TASK("ADCINTERNAL", NULL, NULL, adcInternalProcess, TASK_PERIOD_HZ(1), TASK_PRIORITY_LOWEST),
#endif#ifdef USE_PINIOBOX[TASK_PINIOBOX] = DEFINE_TASK("PINIOBOX", NULL, NULL, pinioBoxUpdate, TASK_PERIOD_HZ(20), TASK_PRIORITY_LOWEST),
#endif#ifdef USE_RANGEFINDER[TASK_RANGEFINDER] = DEFINE_TASK("RANGEFINDER", NULL, NULL, taskUpdateRangefinder, TASK_PERIOD_HZ(10), TASK_PRIORITY_LOWEST),
#endif#ifdef USE_CRSF_V3[TASK_SPEED_NEGOTIATION] = DEFINE_TASK("SPEED_NEGOTIATION", NULL, NULL, speedNegotiationProcess, TASK_PERIOD_HZ(100), TASK_PRIORITY_LOW),
#endif
};
8. 分析模板
这里补充一个模板用于后续模块分析使用,后续会逐步一个个一起与大家分享每个模块的设计和实现。
【模板】模块 & 任务├──> 初始化│ ├──> [x]硬件初始化│ └──> [V]业务初始化├──> 任务│ ├──> [x]实时任务│ ├──> [x]事件任务│ └──> [V]时间任务bla...bla...├──> 驱动│ ├──> [x]查询│ └──> [x]中断└──> 接口├──> bla...bla...└──> bla...bla...函数分析:
bla...bla...
BetaFlight开源代码框架简介相关推荐
- 最大开源代码sourceforge 简介 及视音频方面常用的开源代码
所有的音视频凯源代码在这里:http://sourceforge.net/directory/audio-video/os:windows/,你可以下载分析,视频不懂请发邮件给我,帮你分析. 0.视频 ...
- ArduPilot之开源代码LibrarySketches设计
ArduPilot之开源代码Library&Sketches设计 1. 简介 1.1 Core libraries 1.2 Sensor libraries 1.3 Other librari ...
- ArduPilot之开源代码基础知识Threading概念
ArduPilot之开源代码基础知识&Threading概念 1. 源由 2. 基础知识 2.1 The timer callbacks 2.2 HAL specific threads 2. ...
- ArduPilot之开源代码Sensor Drivers设计
ArduPilot之开源代码Sensor Drivers设计 1. 源由 2. Sensor Drivers设计 2.1 front-end / back-end分层 2.2 设计思想分析 3 实例理 ...
- Java开源——常见J2EE框架简介
Java开源--常见J2EE框架简介 Spring Framework Spring是一个解决了许多在J2EE开发中常见的问题的强大框架. Spring提供了管理业务对象的一致方法并且鼓励了注入对接口 ...
- 流量回放开源代码Java_流量回放框架 jvm-sandbox-repeater 的实践
一. 前言 你是否和我一样遇到过以下的问题? 1)服务重构,一堆接口需要回归,让人头疼 2)每次迭代,都要花很多精力来进行回归测试 3)线上 bug,线下复现不了 4)接口自动化用例写辛苦,维护更辛苦 ...
- 六款值得推荐的Android开源框架简介
六款值得推荐的Android开源框架简介 技术不再多,知道一些常用的.不错的就够了.下面就是最近整理的"性价比"比较高的Android开源框架,应该是相对实用的. 1.volley ...
- [转载]Zookeeper开源客户端框架Curator简介
转载声明:http://macrochen.iteye.com/blog/1366136 Zookeeper开源客户端框架Curator简介 博客分类: Distributed Open Source ...
- 开源推荐 | 携程 Foxpage 前端低代码框架
作者简介 Jason Wang,携程研发经理,目前主要负责低代码类产品的设计和研发,关注低代码行业的发展及相关解决方案在企业内部的落地. 大厂技术 高级前端 Node进阶 点击上方 程序员成长指北 ...
- 开源 | 携程 Foxpage 前端低代码框架
作者简介 Jason Wang,携程研发经理,目前主要负责低代码类产品的设计和研发,关注低代码行业的发展及相关解决方案在企业内部的落地. 一.背景 随着低代码开发方式被越来越多的人接受和认可,低代码得 ...
最新文章
- 解决Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.7.0:compile
- 【Android 内存优化】Android 工程中使用 libjpeg-turbo 压缩图片 ( JNI 传递 Bitmap | 获取位图信息 | 获取图像数据 | 图像数据过滤 | 释放资源 )
- Linux学习之创建子进程
- 如何设计区块链项目的通证(token)模型
- 申请补办 CET(纸笔考试)成绩证明的方法
- ClickHouse:人群圈选业务的大杀器
- 《ext江湖》第8章继承-代码片段
- python中forward函数的引用_pytorch 调用forward 的具体流程
- 局域网查看计算机慢,局域网内的电脑访问共享文件夹速度很慢如何解决
- ASP.NET Core 处理 404 Not Found
- 安全,从写第一行代码开始!
- 用java制作心理测试软件_Java 程序员必备的10款开源工具
- 如何 tune spark jobs
- 11-23-day05-python入门-字典与集合及文件
- 地下城php补丁怎么用,dnf技能补丁怎么用到WeGame(附其使用教程)
- 操作系统之调度 (十) --- 处理机调度、高级调度、中级调度、低级调度...
- oracle 验证 lob 坏块,Oracle LOB坏块处理
- SDL库的安装,spca5xx的安装,spcaview 的安装,摄像头的查看,及常见问题的解决方法。
- Ubuntu 14.04 LTS 安装配置搜狗拼音输入法
- matlab julia分形图,Three.js 朱丽亚集(Julia set)分形图案
热门文章
- python打印网页成pdf_html – 在chrome-python 2.7中自动打印/保存网页为pdf
- origin拟合曲线方法
- x58服务器主板装win7系统,技嘉Z390主板重装win7方法|Z390主板Bios设置及安装win7图文教程...
- cpolar内网穿透工具
- idea中自动生成Java类图和时序图
- Java IO流知识点总结
- html点击图片可以放全屏,html:点击图片放大到全屏,再次点击缩回
- python之父去面试-Django面试题
- 二进制原码一位乘法运算
- 人脸识别技术软件测试测什么,人脸识别这么火,你知道它是什么吗?