BetaFlight模块设计之八:GPS任务分析
Posted lida2003
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BetaFlight模块设计之八:GPS任务分析相关的知识,希望对你有一定的参考价值。
BetaFlight模块设计之八:GPS任务分析
基于BetaFlight开源代码框架简介的框架设计,逐步分析内部模块功能设计。
GPS任务
描述:主要从GPS硬件获取GPS数据,并通知相关任务。
注:这里发现一个BetaFlight的问题,基本上都是全局变量(查询)在做通知,而没有像Paparazzi有内部总线(消息机制)。从设计耦合度的角度,全局变量是一种强依赖,而消息就已经解耦。
├──> 初始化
│ ├──> [v]硬件初始化gpsInitHardware
│ └──> [v]业务初始化gpsInit
├──> 任务
│ ├──> [x]实时任务
│ ├──> [x]事件任务
│ └──> [v]时间任务[TASK_GPS] = DEFINE_TASK("GPS", NULL, NULL, gpsUpdate, TASK_PERIOD_HZ(TASK_GPS_RATE), TASK_PRIORITY_MEDIUM),
├──> 驱动
│ ├──> [v]查询serialRxBytesWaiting/serialRead
│ └──> [x]中断
└──> 接口
├──> bool gpsIsHealthy()
├──> void gpsEnablePassthrough(serialPort_t *gpsPassthroughPort)
├──> void GPS_reset_home_position(void)
├──> 支持NMEA协议
└──> 支持UBLOX协议
gpsUpdate函数分析
任务主函数,从结构化的角度看,如果能引入消息机制和组件模块化设计,程序结构上可能会更加便于理解和阅读。
gpsUpdate
├──> <GPS data from gpsPort>
│ ├──> <serialRxBytesWaiting>
│ │ ├──> <cmpTimeUs(micros(), currentTimeUs) > GPS_MAX_WAIT_DATA_RX>
│ │ │ ├──> rescheduleTask(TASK_SELF, TASK_PERIOD_HZ(TASK_GPS_RATE_FAST));
│ │ │ └──> return
│ │ └──> gpsNewData(serialRead(gpsPort));
│ └──> rescheduleTask(TASK_SELF, TASK_PERIOD_HZ(TASK_GPS_RATE));
├──> <GPS data from MSP, no serial port>
│ ├──> gpsSetState(GPS_STATE_RECEIVING_DATA); // Never timeout
│ ├──> onGpsNewData();
│ └──> GPS_update &= ~GPS_MSP_UPDATE;
├──> <gpsData.state>
│ ├──> <GPS_STATE_UNKNOWN><GPS_STATE_INITIALIZED>
│ │ └──> break;
│ ├──> <GPS_STATE_INITIALIZING><GPS_STATE_CHANGE_BAUD><GPS_STATE_CONFIGURE>
│ │ └──> gpsInitHardware
│ ├──> <GPS_STATE_LOST_COMMUNICATION>
│ │ ├──> gpsData.timeouts++;
│ │ ├──> <gpsConfig()->autoBaud>
│ │ │ └──> Loop config baudrate
│ │ └──> Init state config // gpsSol.numSat = 0; DISABLE_STATE(GPS_FIX); gpsSetState(GPS_STATE_INITIALIZING);
│ └──> <GPS_STATE_RECEIVING_DATA>
│ ├──> <Timeout check>
│ │ └──> gpsSetState(GPS_STATE_LOST_COMMUNICATION);
│ └──> <USE_GPS_UBLOX>
│ └──> <gpsConfig()->autoConfig == GPS_AUTOCONFIG_ON>
│ └──> <gpsData.state_position>
│ ├──> <0>
│ ├──> <!isConfiguratorConnected()>
│ │ ├──> [gpsData.ubloxUseSAT配置CLASS_NAV,MSG_SAT or MSG_SVINFO]
│ │ └──> gpsData.state_position = 1;
│ ├──> <1>
│ │ ├──> <STATE(GPS_FIX) && (gpsConfig()->gps_ublox_mode == UBLOX_DYNAMIC)>
│ │ │ ├──> ubloxSendNAV5Message(true);
│ │ │ └──> gpsData.state_position = 2;
│ │ └──> <isConfiguratorConnected()>
│ │ └──> gpsData.state_position = 2;
│ └──> <2>
│ └──> <isConfiguratorConnected()>
│ ├──> [gpsData.ubloxUseSAT配置CLASS_NAV,MSG_SAT or MSG_SVINFO]
│ └──>gpsData.state_position = 0;
├──> 状态执行时间更新
├──> <sensors(SENSOR_GPS)>
│ └──> updateGpsIndicator(currentTimeUs);
├──> <!ARMING_FLAG(ARMED) && !gpsConfig()->gps_set_home_point_once>
│ └──> uDISABLE_STATE(GPS_FIX_HOME);
├──> <USE_GPS_RESCUE><gpsRescueIsConfigured>
│ ├──> updateGPSRescueState
│ └──> minSats = gpsRescueConfig()->minSats;
└──> <STATE(GPS_FIX)><gpsIsHealthy() && gpsSol.numSat >= minSats && !hasFix>
└──>beeper(BEEPER_READY_BEEP);
gpsNewData函数分析
除了任务处理相关GPS状态,告警等处理外,gpsUpdate中真正GPS数据处理在这里完成。
gpsNewData
├──> <!gpsNewFrame(c)>
│ └──> return
├──> <gpsData.state == GPS_STATE_RECEIVING_DATA>
│ ├──> gpsData.lastLastMessage = gpsData.lastMessage;
│ ├──> gpsData.lastMessage = millis();
│ └──> sensorsSet(SENSOR_GPS);
├──> GPS_update ^= GPS_DIRECT_TICK;
└──> onGpsNewData
gpsNewFrame函数分析
这里可以看出GPS大体两种协议格式:NEMA和UBLOX,其他不支持。
gpsNewFrame
├──> <GPS_NMEA><USE_GPS_NMEA>
│ └──> gpsNewFrameNMEA
├──> <GPS_UBLOX><USE_GPS_UBLOX>
│ └──> gpsNewFrameUBLOX
└──> <other excep>
└──> return false
onGpsNewData 函数分析
这里有GPS数据更新主要有两个大体用途:距离告警和GPS安全救援。
onGpsNewData
├──> <!(STATE(GPS_FIX) && gpsSol.numSat >= 5)>
│ └──> return
├──> [Delta Time in milliseconds for navigation computations, updated with every good GPS read]
├──> GPS_calculateDistanceAndDirectionToHome
├──> <ARMING_FLAG(ARMED)>
│ └──> GPS_calculateDistanceFlownVerticalSpeed(false);
└──> <USE_GPS_RESCUE>
└──> rescueNewGpsData
以上是关于BetaFlight模块设计之八:GPS任务分析的主要内容,如果未能解决你的问题,请参考以下文章