Protocol_Lib.c 10.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/**
 * @file        Protocol_Lib.c
 * @brief       串口协议解析
 * @details     串口协议解析
 * @author      myliu
 * @date        2022.05.09
 * @version     V1.0
 * @copyright   myiu
 */

#include <stdio.h>
#include <string.h>
#include "Protocol_CRC16.h"
#include "gatts_table_creat_demo.h"
static UARTOpen          UARTOpen_Cbk;
static UARTSend          UARTSend_Cbk;
static UARTRead          UARTRead_Cbk;
static ProcParse         ProcParseCbk;
static UARTClose         UARTClose_Cbk;
static ProtocolSetData   ProtocolSetData_Cbk;
static Protocol_uint8_t *mDataBufPtr   = Protocol_NULL;
static Protocol_uint16_t mDataBufLen   = 0;
static Protocol_uint32_t DataBufMaxLen = 0;
24 25

BAT32A239_ACK_Structure BAT32A239_ACK;
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
//#define DEBUG_PRO_DATA 0
/**
 * @brief 初始化函数
 * @param[in] pMemSpace 分配给协议库的内存空间,用来缓存串口数据
 * @param[in] MemLen    分配的内存空间大小
 * @param[in] pFunc     回调函数,包括串口打开、发送、读取、关闭,也包括解析后数据回传
 * @param[in] ProcParseCbk 此回调函数,返回数据从FrameNo开始到CRC16之前,和ProtocolSetData_Cbk二选一
 * @param[in] ProtocolSetData_Cbk 此回调函数,返回数据区分命令字、电源状态等,和ProcParseCbk二选一,详见结构体Protocol_Data_t
 *
 * @warning 此函数KL30和Wakeup都要调用,否则未分配内存,功能不好使,也有可能造成野指针复位
 *
 * @since 1.0.0
 */
void Protocol_Init(Protocol_uint8_t *pMemSpace, Protocol_uint32_t MemLen, Protocol_Func_t *pFunc)
{
    mDataBufPtr         = pMemSpace;
    DataBufMaxLen       = MemLen;
    UARTOpen_Cbk        = pFunc->UARTOpen_Cbk;
    UARTSend_Cbk        = pFunc->UARTSend_Cbk;
    UARTRead_Cbk        = pFunc->UARTRead_Cbk;
    ProcParseCbk        = pFunc->ProcParseCbk;
    UARTClose_Cbk       = pFunc->UARTClose_Cbk;
    ProtocolSetData_Cbk = pFunc->ProtocolSetData_Cbk;

    if ( UARTOpen_Cbk != Protocol_NULL )
    {
        UARTOpen_Cbk( );
    }

    return;
}
57 58
extern Protocol_uint32_t UpdateBAT32A239Protocol_Parse(const Protocol_uint8_t *pData, Protocol_uint32_t len);
extern uint32_t SwitchMode;
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
/**
 * @brief 串口协议服务函数,包括读取数据,解析数据,如在外部读取数据,可不调用此函数
 *
 * @warning 此函数可自定义周期调用,建议20ms周期调用,最大不可超过协议的最小发送周期
 *
 * @since 1.0.0
 */
void Protocol_Service(void)
{
    int               len;
    Protocol_uint32_t readNum = 0;

    if ( UARTRead_Cbk != Protocol_NULL )
    {
        readNum = UARTRead_Cbk(mDataBufPtr + mDataBufLen, 256 - mDataBufLen);
        if ( readNum > 0 )
        {
            mDataBufLen += readNum;
            // 解析协议
78 79 80 81 82 83 84 85 86
            if(SwitchMode==0)//处理升级协议
            {
                len = Protocol_Parse(mDataBufPtr, mDataBufLen);
            }
            else//处理应用协议
            {
                len = UpdateBAT32A239Protocol_Parse(mDataBufPtr, mDataBufLen);
            }
            
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
            if ( (len > 0) && (len < mDataBufLen) )
            {
                // 将未解析的数据移到头部
                // Move unparsed data to the head
                memcpy(mDataBufPtr, mDataBufPtr + len, mDataBufLen - len);
            }

            mDataBufLen -= len;
        }
    }
}

/**
 * @brief 协议解析函数,如外部获取数据(例如中断),可直接调用此函数解析数据
 * @param[in] pData     协议数据内容
 * @param[in] len       需要处理的协议数据长度
 *
 * @return    剩余已处理的数据长度
 *
 * @since 1.0.0
 */
Protocol_uint32_t Protocol_Parse(const Protocol_uint8_t *pData, Protocol_uint32_t len)
{
    Protocol_uint32_t remainLen = len;    // 剩余数据长度 Remaining data length
    Protocol_uint32_t dataLen;            // 数据包长度 Packet length
    Protocol_uint32_t frameLen;           // 帧长度 Frame length
    Protocol_uint32_t frameSum;
    Protocol_Data_t   ProcData;
    int               i = 0;
    int               dataBuf [ 256 ];

    /**
     * 以下部分需要根据协议格式进行相应的修改,解析出每一帧的数据
     */
    while ( remainLen >= DATA_PACKAGE_MIN_LEN )
    {
        // 找到一帧数据的数据头
        // Find the data header of a frame of data
        while ( (remainLen >= 2) && ((pData [ 0 ] != CMD_HEAD1) || (pData [ 1 ] != CMD_HEAD2)) )
        {
            pData++;
            remainLen--;
            continue;
        }

        if ( remainLen < DATA_PACKAGE_MIN_LEN )
        {
#ifdef DEBUG_PRO_DATA

            d_printf("too short!!!!!!\n");
#endif
            break;
        }

        dataLen  = pData [ 2 ];
        frameLen = dataLen + DATA_PACKAGE_FIXED_LEN;
        if ( frameLen > remainLen )
        {
            // 数据内容不全
#ifdef DEBUG_PRO_DATA

            d_printf("Incomplete data packet!!!!!!\n");
#endif
            break;
        }

        // 打印一帧数据,需要时在CommDef.h文件中打开DEBUG_PRO_DATA宏
#ifdef DEBUG_PRO_DATA
        for ( i = 0; i < frameLen; ++i )
        {
            d_printf("%x ", pData [ i ]);
        }
        d_printf("\n");
#endif

        // 检测校验码 Checksum 
        frameSum = (pData [ frameLen - 2 ] << 8) | (pData [ frameLen - 1 ]);
        if ( frameLen > 4 )
        {
            if ( getCheckSum(pData + 2, frameLen - 4) == frameSum )
            {
                // 解析一帧数据
                if ( ProcParseCbk != Protocol_NULL )
                {
                    ProcParseCbk(pData + 3, dataLen - 2);
                }

                if ( ProtocolSetData_Cbk != Protocol_NULL )
                {
                    ProcData.FrameNo  = pData [ 3 ];
                    ProcData.PowerSts = (pData [ 4 ] >> 6) & 0x03;
                    ProcData.CmdID    = pData [ 4 ] & 0x3F;
                    if ( ProcData.CmdID == 0x10 )
                    {
#ifdef DEBUG_PRO_DATA
                        for ( i = 0; i < frameLen; ++i )
                        {
                            d_printf("%x ", pData [ i ]);
                        }
                        d_printf("\n");
#endif
                    }
                    if ( ProcData.CmdID == 0x12 )
                    {
#ifdef DEBUG_PRO_DATA
                        for ( i = 0; i < frameLen; ++i )
                        {
                            d_printf("%x ", pData [ i ]);
                        }
                        d_printf("\n");
#endif
                    }
                    ProcData.DataLen = dataLen - 4;
                    memcpy(ProcData.Data, pData + 5, ProcData.DataLen);
                    ProtocolSetData_Cbk(&ProcData);
                }
            }
            else
            {
                for ( i = 0; i < frameLen; ++i )
                {
                    dataBuf [ i ] = pData [ i ];
                }
                i = 0;
#ifdef DEBUG_PRO_DATA

                d_printf("CheckSum error: new = %x, old = %x!!!!!!\n", getCheckSum(pData + 2, frameLen - 4), frameSum);
#endif
            }
        }
217
 
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
        pData += frameLen;
        remainLen -= frameLen;
    }

    return len - remainLen;
}

/**
 * 根据协议格式进行拼接
 */
/**
 * @brief 串口协议数据拼接,如初始化发送函数,调用此函数后,数据已通过串口发送
 * @param[in] cmdID     命令字
 * @param[in] pData     协议数据内容(不包括协议头、长度、帧序号、命令字、校验和,从数据域算起)
 * @param[in] len       数据域长度
 *
 * @return    已发送的数据长度
 *
 * @since 1.0.0
 */
238

239 240 241 242 243 244 245 246
Protocol_uint32_t Protocol_Send(const Protocol_uint16_t cmdID, const Protocol_uint8_t *pData, Protocol_uint8_t len)
{
    int               i        = 0;
    Protocol_uint16_t checksum = 0;
    Protocol_uint8_t  dataBuf [ 256 ];
    Protocol_uint32_t frameLen;
    if ( len + DATA_PACKAGE_MIN_LEN > 256 )
    {
247
          //  printf("sendProtocol data is too len !!!\n");
248 249 250 251 252 253 254
        return 0;
    }

    dataBuf [ 0 ] = CMD_HEAD1;
    dataBuf [ 1 ] = CMD_HEAD2;    // 同步帧头 Sync frame header

    dataBuf [ 2 ] = len + 4;
255
    dataBuf [ 3 ] = 0;    // 命令字节 Command byte
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274

    dataBuf [ 4 ] = ( Protocol_uint8_t )cmdID;

    frameLen = 5;

    // 数据 Data
    for ( i = 0; i < len; ++i )
    {
        dataBuf [ frameLen ] = pData [ i ];
        frameLen++;
    }

    // 校验码 Checksum
    checksum             = getCheckSum(dataBuf + 2, frameLen - 2);
    dataBuf [ frameLen ] = (checksum >> 8) & 0x00FF;
    frameLen++;
    dataBuf [ frameLen ] = checksum & 0x00FF;
    frameLen++;

275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
    if ( UARTSend_Cbk != Protocol_NULL )
    {
        return UARTSend_Cbk(dataBuf, frameLen);
    }
    else
    {
        return 0;
    }
}

Protocol_uint32_t CalcCrc32(Protocol_uint8_t buf[], int Len);
/**
 * 根据协议格式进行拼接
 */
/**
 * @brief 串口协议数据拼接,如初始化发送函数,调用此函数后,数据已通过串口发送
 * @param[in] cmdID     命令字
 * @param[in] pData     协议数据内容(不包括协议头、长度、帧序号、命令字、校验和,从数据域算起)
 * @param[in] len       数据域长度
 *
 * @return    已发送的数据长度
 *
 * @since 1.0.0
 */
Protocol_uint32_t UpdateBAT32A239Protocol_Send(UpdateProtocolStructure SendPd)
{
    int               i        = 0;
    Protocol_uint16_t checksum = 0;
    Protocol_uint8_t  dataBuf [ 256 ];
    Protocol_uint16_t checksumXor = 0;
    Protocol_uint32_t frameLen = 0;
    Protocol_uint32_t DAT_CRC;

    if ( SendPd.LEN  > 256 )
    {
        // printf("sendProtocol data is too len !!!\n");
        return 0;
    }
313

314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
    frameLen = SendPd.LEN + 7;
    

    dataBuf [ 0 ] = 0xAA;
    dataBuf [ 1 ] = 0x55;        // 同步帧头 Sync frame header
    dataBuf [ 2 ] = SendPd.CMDH; //CMDH
    dataBuf [ 3 ] = SendPd.CMDL; // CMDL
    dataBuf [ 4 ] = frameLen;
    dataBuf [ 5 ] = frameLen >> 8;    // 命令字节 Command byte
    
    if(SendPd.CMDH == CMD_FLASH_DWNLD)
    {
        
        if(SendPd.LEN > 4)
        {
            memcpy(&dataBuf[6],&SendPd.DAT[0],SendPd.LEN - 4);
            DAT_CRC=CalcCrc32(&SendPd.DAT[0], SendPd.LEN - 4 );//计算Address + Data的CRC 32
            dataBuf[frameLen-5]=(Protocol_uint8_t)(DAT_CRC);
            dataBuf[frameLen-4]=(Protocol_uint8_t)(DAT_CRC>>8);
            dataBuf[frameLen-3]=(Protocol_uint8_t)(DAT_CRC>>16);
            dataBuf[frameLen-2]=(Protocol_uint8_t)(DAT_CRC>>24);
        }
    }
    if(SendPd.CMDH == CMD_FLASH_ERASE)
    {
        memcpy(&dataBuf[6],&SendPd.DAT[0],SendPd.LEN);
    }
    for(i = 0 ;i < (frameLen - 1); i++)
    {
        checksumXor^=dataBuf[i];
    }
    dataBuf[frameLen - 1]=(Protocol_uint8_t)checksumXor;
    //printf("dataBuf[frameLen - 1] = %2x\n", dataBuf[frameLen - 1]);
    //printf("frameLen = %d\n", frameLen);
348 349 350 351 352 353 354 355 356
    if ( UARTSend_Cbk != Protocol_NULL )
    {
        return UARTSend_Cbk(dataBuf, frameLen);
    }
    else
    {
        return 0;
    }
}