这篇我们主要是学习下app部分固件的设计逻辑。
1. 初始化过程中开辟一个环形缓冲区,设置串口为中断接收,重写串口中断回调函数,也就是每次接收一个字节的数据就往环形缓冲区里丢一个数据。
void gizwitsInit(void)
{
pRb.rbCapacity = RB_MAX_LEN;
pRb.rbBuff = rbBuf;
if(0 == rbCreate(&pRb)) //初始化一个环形缓冲区,实际就是一个链表结构
{
GIZWITS_LOG("rbCreate Success \n");
}
else
{
GIZWITS_LOG("rbCreate Faild \n");
}
memset((uint8_t *)&gizwitsProtocol, 0, sizeof(gizwitsProtocol_t));
}
int32_t gizPutData(uint8_t *buf, uint32_t len) //往环形缓冲区里添加数据
{
int32_t count = 0;
if(NULL == buf)
{
GIZWITS_LOG("ERR: gizPutData buf is empty \n");
return -1;
}
count = rbWrite(&pRb, buf, len);
if(count != len)
{
GIZWITS_LOG("ERR: Failed to rbWrite \n");
return -1;
}
return count;
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef*UartHandle) //串口接收中断的回调函数
{
if(UartHandle->Instance == USART2)
{
gizPutData((uint8_t *)&aRxBuffer, 1); //串口接收到一个字节数据就存进环形缓冲区
HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1);//开启下一次接收中断
}
}
2.死循环里会一直尝试解析一个完整的数据包,如果发现环形缓冲区里有一个完整的数据包就取出并解析出对应的命令,然后根据串口协议完成数据的接收。例如和OTA相关的指令。
以下是关于OTA指令的部分代码。
int32_t gizwitsHandle(dataPoint_t *currentData){
...
...
...
//判断是否有一包完整的数据
ret = gizProtocolGetOnePacket(&pRb, gizwitsProtocol.protocolBuf, &protocolLen);
if(0 == ret)
{
GIZWITS_LOG("Get One Packet!\n");
recvHead = (protocolHead_t *)gizwitsProtocol.protocolBuf;
switch (recvHead->cmd) //根据命令进行相应的操作
{
.....
.....
.....
case CMD_ASK_BIGDATA: //云端通知MCU准备进行OTA
GIZWITS_LOG("CMD_ASK_BIGDATA \n");
gizProtocolCommonAck(recvHead);
if(0 == Pro_W2D_UpdateCmdHandle((uint8_t
*)gizwitsProtocol.protocolBuf + sizeof(protocolHead_t),
protocolLen - sizeof(protocolComm