BetaFlight模块设计之三十一:blackbox模块分析
基于BetaFlight开源代码框架简介的框架设计,逐步分析内部模块功能设计。
blackbox模块
描述:blackbox类似飞机黑匣子记录飞行数据,以便从数据面更好的理解飞行姿态,速度,高度,电机状态等性能参数。如出现异常或者crash,可以结合数据分析root cause,并定位最终原因。
src/main/blackbox/
├── blackbox.c
├── blackbox_encoding.c
├── blackbox_encoding.h
├── blackbox_fielddefs.h
├── blackbox.h
├── blackbox_io.c
└── blackbox_io.h
0 directories, 7 files
目前4.3的代码支持三种黑匣子设备:
- 内部Flash
- SD卡
- 串口日志设备
typedef enum BlackboxDevice {
BLACKBOX_DEVICE_NONE = 0,
BLACKBOX_DEVICE_FLASH = 1,
BLACKBOX_DEVICE_SDCARD = 2,
BLACKBOX_DEVICE_SERIAL = 3
} BlackboxDevice_e;
blackbox接口
blackbox_io子模块接口
这个io子模块是直接与不同设备(FLASH/SDCARD/SERIAL)驱动进行对接,并对上层业务呈现统一接口的适配层。
void blackboxOpen(void); //打开blackbox串口通道
void blackboxWrite(uint8_t value); //根据设备类型FLASH/SDCARD/SERIAL调用底层驱动写一个字节
int blackboxWriteString(const char *s); //根据设备类型FLASH/SDCARD/SERIAL调用底层驱动写一个字符串
void blackboxDeviceFlush(void); //在blackbox的PAUSED状态机下被调用到对FLASH设备进行同步
bool blackboxDeviceFlushForce(void); //在blackbox的SHUTTING_DOWN/CACHE_FLUSH状态被调用,用于数据一致性保存
bool blackboxDeviceFlushForceComplete(void); //在blackbox的CACHE_FLUSH状态,当Cache没有同步时被调用,确保数据一致性保存
bool blackboxDeviceOpen(void); //根据设备类型FLASH/SDCARD/SERIAL调用底层驱动打开设备
void blackboxDeviceClose(void); //根据设备类型FLASH/SDCARD/SERIAL调用底层驱动关闭设备
void blackboxEraseAll(void); //对FLASH设备进行擦除
bool isBlackboxErased(void); //对FLASH设备检查是Ready,其他设备始终Ready(在blackbox的ERASING状态下调用)
bool blackboxDeviceBeginLog(void); //对SD设备进行日志记录初始化;其他设备始终TRUE(无需处理)
bool blackboxDeviceEndLog(bool retainLog); //对SD设备结束日志记录;其他设备始终TRUE(无需处理)
bool isBlackboxDeviceFull(void); //检查blackbox设备存储是否已满(串口日志设备默认始终不会满)
bool isBlackboxDeviceWorking(void); //检查blackbox设备是否正常工作(Ready)
int32_t blackboxGetLogNumber(void); //获取SD设备日志文件最大的文件号码,其他设备没有这个返回(-1); (osdDisplayStat in Osd.c/osdElementLogStatus in Osd_elements.c)
void blackboxReplenishHeaderBudget(void); //根据设备类型FLASH/SDCARD/SERIAL, 在SEND_HEADER状态时,检查空闲的预算字节数
blackboxBufferReserveStatus_e blackboxDeviceReserveBufferSpace(int32_t bytes); //根据设备类型FLASH/SDCARD/SERIAL检查剩余的空间
int8_t blackboxGetLogFileNo(void); //与blackboxGetLogNumber函数类型,可能由于历史原因分别在不同的地方被使用(showBBPage in Dashboard.c)
blackbox_encoding子模块接口
对blackbox保存数据的编码,压缩保存有效数据位;降低通信带宽(*),减少数据存储空间。
int blackboxPrintf(const char *fmt, ...); //打印一行
void blackboxPrintfHeaderLine(const char *name, const char *fmt, ...); //打印name + 一行 + newline
void blackboxWriteUnsignedVB(uint32_t value); // USVB(7bit编码一个u32)
void blackboxWriteSignedVB(int32_t value); // SVB(7bit+zigzag编码一个s32)
void blackboxWriteSignedVBArray(int32_t *array, int count); // SVBA(7bit+zigzag编码一个s32数组)
void blackboxWriteSigned16VBArray(int16_t *array, int count); // S16VBA(7bit+zigzag编码一个s16数组)
void blackboxWriteS16(int16_t value); // 保存s16
void blackboxWriteU32(int32_t value); // 保存u32
void blackboxWriteFloat(float value); // 保存u32 + castFloatBytesToInt
void blackboxWriteTag2_3S32(int32_t *values); // 2bit Tag + 3S32, fields of 2, 4, 6 or 32 bits
int blackboxWriteTag2_3SVariable(int32_t *values); // 2bit Tag + 3Variable(S32), fields of 2, 554, 877 or 32 bits
void blackboxWriteTag8_4S16(int32_t *values); // 8bit Tag + 4S31, fields of size 0, 4, 8 or 16 bits.
void blackboxWriteTag8_8SVB(int32_t *values, int valueCount); // 8bit Tag + SVB or SVB
blackbox子模块接口
黑匣子日志记录工作主要是在MainPidLoop任务中被调用的。
主要业务接口
void blackboxInit(void); //初始化黑匣子业务
void blackboxFinish(void); //结束黑匣子业务
void blackboxUpdate(timeUs_t currentTimeUs); //黑匣子日志更新记录
相关函数接口
void blackboxLogEvent(FlightLogEvent event, union flightLogEventData_u *data);
int blackboxCalculatePDenom(int rateNum, int rateDenom);
uint8_t blackboxGetRateDenom(void);
uint16_t blackboxGetPRatio(void);
uint8_t blackboxCalculateSampleRate(uint16_t pRatio);
bool blackboxMayEditConfig(void);
blackbox状态机图
这里的状态机主要是blackboxUpdate函数给出,可以对应BetaFlight模块设计之二十八:MainPidLoop任务分析中的subTaskPidSubprocesses子任务。