使用数据结构自动解析协议

本文介绍了如何通过数据结构自动计算偏移来拆分和格式化输出二级指令协议,使得16进制协议在调试过程中更易理解和排查问题。日志输出效果清晰,包括SOF、DEV、CMD、SEQID、LEN、DATA、XOR和EOF等字段,便于快速定位和理解数据包内容。
摘要由CSDN通过智能技术生成

问题描述

在对接调试中,有时候需要看16进制的协议,这个往往是比较晦涩的,当时间旧了之后再去看这个协议就很烦,于是想能否直接在协议输出数据的时候直接格式化输出

问题分析

此处使用数据结构的自动计算偏移拆分协议

协议格式:注意协议是2级指令协议,在data域还有一层协议

typedef struct
{
  uint8_t Sof;
  uint8_t dev;
  uint8_t cmd;
  uint8_t seqid[4];
  uint8_t Len;
  uint8_t Data[SPI_PAC_DATA_MAX];   // DATA 与中有很多小指令格式:[ cmd(1b) + len(1b) + data(nb) ]
  uint8_t Xor;
  uint8_t Eof;
} spi_pac_t;

协议解析函数:

if ((port_ant[port].dbg_en.bits.shex_en == 1) && (((uint8_t *)send_buf)[(unsigned long)(&((spi_pac_t *)0)->Len)] != 0x7F))
{
  uint8_t i;
  uint8_t *pdata = (uint8_t *)send_buf;
  uint8_t cmd_pos = 0;
  uint8_t len_pos = 0;
  uint8_t dtq_pos = 0;
  uint8_t crc_pos = (unsigned long)(&((spi_pac_t *)0)->Data) + tpac->Len;

  LOG_RAW("[%d]: [ %d:%02x ] s_SPI%d: cmd:%02x, crc: data:", HAL_GetTick(),
          *(uint32_t *)(tpac->seqid),
          tpac->Data[tpac->Len], port, ((uint8_t *)send_buf)[(unsigned long)(&((spi_pac_t *)0)->Len)]);

  for (i = 0; i < tpac->Len + 10; i++)
  {
    if (port_ant[port].dbg_en.bits.scmd_en == 1)
    {
			/* s0: SPI 层指令切割  */
      switch (i)
      {
      case (unsigned long)(&((spi_pac_t *)0)->Sof):
        LOG_RAW("\nsof:");
        break;
      case (unsigned long)(&((spi_pac_t *)0)->dev):
        LOG_RAW("\ndev:");
        break;
      case (unsigned long)(&((spi_pac_t *)0)->cmd):
        LOG_RAW("\ncmd:");
        break;
      case (unsigned long)(&((spi_pac_t *)0)->seqid):
        LOG_RAW("\nseq:");
        break;
      case (unsigned long)(&((spi_pac_t *)0)->Len):
        LOG_RAW("\nlen:");
        break;
      case (unsigned long)(&((spi_pac_t *)0)->Data):
        cmd_pos = (unsigned long)(&((spi_pac_t *)0)->Data);
        len_pos = (unsigned long)(&((spi_pac_t *)0)->Data) + 1;
        dtq_pos = (unsigned long)(&((spi_pac_t *)0)->Data) + 2;
        break;
      }

			if (i == crc_pos)
				LOG_RAW("\ncrc:");
			if (i == (crc_pos + 1))
				LOG_RAW("\neof:");

			/* s1: DTQ 层指令切割  */
			if (((cmd_pos > 0) && (i == cmd_pos)) && (crc_pos > i))
				LOG_RAW("\ndtq_cmd:");
			if (((len_pos > 0) && (i == len_pos)) && (crc_pos > i))
				LOG_RAW(" len:");
			if (((dtq_pos > 0) && (i == dtq_pos)) && (crc_pos > i))
			{
				LOG_RAW(" dat:");
				cmd_pos = dtq_pos + pdata[len_pos];
				len_pos = cmd_pos + 1;
				dtq_pos = cmd_pos + 2;
			}
    }
    LOG_RAW(" %02x", pdata[i]);
  }
  LOG_RAW("\n\n");
}

日志输出效果如下:

00> [80085]: [ 2430:1a ] s_SPI0: cmd:10, crc: data:
00> sof: 61
00> dev: 02
00> cmd: 10
00> seq: 7e 09 00 00
00> len: 73
00> dtq_cmd: 01 len: 4b dat: 64 00 00 00 08 63 00 00 00 08 62 00 00 00 08 61 00 00 00 08 ff ff ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00> dtq_cmd: 09 len: 07 dat: 67 84 7c 66 00 00 40
00> dtq_cmd: 0c len: 13 dat: 08 08 08 08 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00> dtq_cmd: 0e len: 06 dat: 01 04 07 9f 3b 83
00> crc: 1a
00> eof: 21

相对于满屏的16进制,这个稍微看起来会更加容易理解些。使用这个格式一下数据,在排查协议异常的问题就会方便很多

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值