Command Context 设计
在application层的命令系统中,在处理回调函数时,由于命令解析框架(RSL CommandEngine)中的回调函数由框架主动调用,其执行上下文不再处于原本的RocketCommand对象成员函数调用链中,因此需要通过context将Application层对象传递给回调函数在app_command->mid_command->回调函数这一整个链条里面,保留了一个“context”指针,app_handler文件里面的回调函数可以通过context来操作rocket类里面的其他对象的指针。
Commander 设计
rocket类作为总类,其下包含若干个commander类指针,而每个commander类实例只能包含一个数据来源,比如UARTcommander,LORAcommander。
本航电拥有两个commander,UARTcommander和LoRacommander,而每个commander对应一个数据的来源,这个数据来源函数需要转移两个数据:一个是数据的Buffer指针,另一个是数据的长度,本版本航电中,UART数据采用的是系统中断回调,放在tsk_isr内,当UART收到一个包,HAL库会中断并自动调用uart1Callback这个函数,紧接着调用rocket类内的receiveUARTCommandData函数,receiveUARTCommandData函数的作用是在中断内把Buffer指针和数据长度的信息转移到rocket类内的私有变量,并且把标志位置为收到Data的状态,而住循环内的另一个函数handleUARTCommandData在检测到标志位后自动处理rocket类内私有变量(buffer)所存储的Data。这样设计是为了把“数据写入”和“数据解析”分开,避免中断内处理大量解析的操作,占用中断。
接着上文,而LoraCommander的数据来源来自于app层内Communication封装里面的communicatorLoop函数,这个函数会不断循环,承担两个作用:将rocket其他部分的发送请求所产生的队列内的待发送包发送出去,以及在不发送的时候将lora硬件置为Rx接收状态,当接收到数据时,在communicatorLoop的输入值内把标志位置1并返回buffer的指针。所以可以看到Lora的信息来自于RocketTask在调用communicatorLoop的自我循环,不需要中断,而Rocket类大可以直接在communicatorLoop后面直接判断是否收到消息并调用commander解析,但是处于两个考虑:1 为了让commander的格式尽可能相同。2以后communicatorLoop可能不在rocketLoop中循环而是加入中断等其他措施。所以communicatorLoop执行完的后面,同样延续了UartCommand的结构,先把communicatorLoop接收到的buffer转换到rocket类内自己的buffer里面,然后把自己的标志位置1,主循环内的handleLoraCommandData会自动去解析收到的一包数据。
双commander设计的特性
双commander导致UART和LoRa命令如果同时进行发送指令的操作,可能导致优先级冲突。使用时绝不能同时使用两种通信方式同时发送指令。
遥测序列号定义
遥测协议内的包头中的遥测序列号定义为:底层LoRa发送的序列,而并非Application层往队列内塞入数据的序列。这样设计是考虑到,上层application如果发生数据覆盖,属于“数据自我翻新”不应该被认定为是数据丢失。