telink:tc321x串口升级

1 telink升级原理概括

  tc3215m的flash 512KB,可设置AB分区启动,启动地址为 [ 0/128KB ]或 [ 0/256KB ],资源充裕所以选[ 0/256KB ];

  telinkIoT编译工具生成的bin文件的0x08地址偏移处的值都为0x544C4E4B "TLNK",该值sdk代码可访问,作为设置升级地址的标志;

  333

  1.1 升级流程

    telink-mcu在收到一帧fwbin之后,会预留0x08地址偏移处的4字节bin不写入flash,把其他fwbin数据写入flash;

    telink-mcu继续接收剩下的fwbin数据帧,每帧写入flash,且对每帧数据进行crc累计校验和;

    最后一帧fwbin数据帧的结尾会额外加2bytes的多项式crc,用于校验;

    telink-mcu在收完最后一帧后,会重新将flash数据读出进行crc校验得到一个crc校验和,对比这3个crc校验和是否相等;

    3个crc相等 >> 补全写入flash的0x08地址字节,然后将当前flash区的0x08地址字节写入0xff >> 软件重启完成升级;

    重启后romBoot通过判断flash 0x08偏移地址值决定从flash的0x000000还是0x040000启动;

===================================

对于串口升级数据流向是咋样的呢?

===================================

2 串口dmaBuff

  串口数据通过dmaBuff收进来,等接收中断置位后在irq中,将dmaBuffAddr作为msg发送到queue中处理;

//telink中,dmaBuff的结构
typedef struct{
    unsigned int    dma_len;                //dma硬件自动计数
    unsigned char   data[UART_DATA_LEN];    //dmaBuff,  RxIrq >> &data push >> pop处理
}uart_data_t;

//telink中,msg的结构
typedef struct {
    unsigned int   Type;                    //msgTypeData, msgTypeTimeout, msgTypeInvalid, msgTypeCheckFail
    unsigned char  *Data;                   //msgTypeData、msgTypeCheckFail时, 为dmaBuff地址
                                            //msgTypeTimeout, msgTypeInvalid时, 未用上
} FW_UPDATE_MsgTypeDef;

//telink中,queue的结构
typedef struct {
    FW_UPDATE_MsgTypeDef Msg[MSG_QUEUE_LEN];  // buffer storing msg
    unsigned char Cnt;                        // current num of msg
    unsigned char ReadPtr;                    // ptr of first msg should be read next
} FW_UPDATE_MsgQueueTypeDef;

3 收发数据帧

  这边queue收到数据后就需要处理,通过串口收发的 dmaRcvBuff /dmaSndBuff 的数据帧格式如下

//dma rcv/snd data struct
typedef struct {
    unsigned char  CheckSum;            //frameHeader >> checksum
    unsigned char  Type;                //frameType   >> typeCmd, typeData, typeAck, typeChkFail
    unsigned short payloadLen;          //payloadLen
    unsigned char  Payload[payloadLen]; //payload[ FW_UPDATE_FRAME_PAYLOAD_MAX ]
} FW_UPDATE_FrameTypeDef;

  当type不同时,4种payload的解析如下

#define FW_UPDATE_FRAME_FW_SIZE         1024
#define SIZE_LEN_PL_PARAMS              10
typedef enum{
    EC_SUCCESS = 0,
    EC_FRAME_CHECK = 1,
    EC_PAYLOAD_CHECK = 2,
}FW_UPDATE_errorCode;

typedef struct{
    unsigned char  checksum;
    unsigned char  reserved;
    unsigned short blockIndex;
    unsigned char  fwBinData[FW_UPDATE_FRAME_FW_SIZE];
}payload_typeData;

typedef struct{
    unsigned char  checksum;
    unsigned char  reserved;
    unsigned short blockIndex;
}payload_typeAck;

typedef struct{
    unsigned char  checksum;
    unsigned char  cmdid;
    unsigned char  cmdParams[SIZE_LEN_PL_PARAMS];
}payload_typeCmd;

typedef struct{
    unsigned char checksum;
    unsigned char checkErrorCode;
}payload_typeChecksumFail;

4 那么上面这4种串口通讯帧是如何通讯的呢?

  ble-mcu收到通讯帧后,首先计算两个checksum,如果checksum不对直接回复typeChkFail;连续收到3帧checksum错误则软件复位;

  接着ble-mcu对于不能解析的通讯帧不进行处理,2s内没有收到正确帧,超时复位;ble-mcu帧与帧之间的间隔也需要在2s内,超时复位;

  ble-mcu的正常通讯帧的收发顺序则如下所示;ble-mcu会对收到后执行的通讯帧都进行回复;

  666

  777

  4.1 通讯流程状态机

    555

5 校验方式

  ble-mcu的校验方式为:通讯帧帧头校验和校验,通讯帧payload校验和校验,固件包整包多项式校验;

  5.1 校验和校验

static unsigned char FW_UPDATE_checksumGenerate(const unsigned char *pDataValid, unsigned short dataLen){
    unsigned char CheckSum = 0;
    if (pDataValid == NULL || dataLen == 0) {
        return 0;
    }
    for (unsigned short i = 0; i < dataLen; i++) {
        CheckSum ^= pDataValid[i];
    }
    //CAECHAR("check:%02x \n",CheckSum );
    return CheckSum;
}

  5.2 固件包整包多项式校验

    mcu发送固件包的时候,多项式校验的2字节会加在最后一帧固件包的结尾,一起发送给ble-mcu校验;

    ble-mcu在接收每帧fwbin的时候会对fwbin每帧进行crc累计,ble-mcu在接收完fwbin整个固件后会从flash中读出所有固件再计算一遍crc;

    ble-mcu会将两次crc和mcu发过来的crc进行比对,都相同才回复CMDID_END_RSP;

//crc初值为0xffff
static unsigned short FW_UPDATE_crcGenerate(unsigned short crc, unsigned char *pd, int len){
    unsigned short crc16_poly[2] = { 0, 0x8408 }; 
    int i, j;
    for (j = len; j > 0; j--){
        unsigned char ds = *pd++;
        for (i = 0; i < 8; i++){
            crc = (crc >> 1) ^ crc16_poly[(crc ^ ds) & 1];
            ds = ds >> 1;
        }
    }
    return crc;
}

6 所以这玩意应该咋搞呢?

  1 状态机 >> 确认整体协议的收发流程,先发什么数据,后发什么数据;

  2 帧格式 >> 单帧的数据帧应该怎么发,帧本身数据可以放到payload中二次解析;[ crc : frameType : len : payload ]

  3 crc/ack,超时处理,丢包处理 >> 单帧的数据帧发的对不对;

  4 编写调试 >> 按照规划好的框架写代码然后调试;所以看别人的代码也可以这样看;

  所以这玩意我咋让AI帮我搞呢?

    1 先让AI生成状态机,状态转移表,空函数;

    2 自己补充边界条件,物理限制,错误处理,有些关键flash读写操作;

    3 再让AI按补充的条件编写重复性函数,辅助函数等;

 

posted @ 2026-01-04 19:14  rls_v  阅读(1)  评论(0)    收藏  举报