This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F280025: 使用SPRUHS1C文件内642页提供CRC例程输出结果不正确。

Part Number: TMS320F280025
Other Parts Discussed in Thread: C2000WARE, CONTROLSUITE

创建的.asm文件如下:

调用汇编函数如下:

Uint16 inputdata[6]= {1,2,3,4,5,6};

mycrc.CRCData = inputdata;
mycrc.CRCLen = 12;

 CRC16P1(&mycrc);

返回结果为 0x8059  ,与正确结果0xDDBA不对应.

请问是原因什么导致的?

  • 我没有用过0025

    我是在28388D上我用VCU计算的CRC16

    不过我想应该是类似的

    你说的正确的结果 是不是找的第三方工具计算的 比如现在有很多在线crc工具

    你检查下

    1.crc seed值

    2.字节校验顺序,是先校验低字节 还是高字节

    3.有没有reflect,就是没有掉换msb和lsb

    基本检查这三点

    https://mp.weixin.qq.com/s/RBHNHbrkdD43E5kPhuQO1w

    这个链接是我总结的28388 vcu做校验 你可以参考一下

  • 与正确结果0xDDBA不对应

    这个结果是如何得出的?请提供一下计算的过程

  • 你好,多项式类型如下:

    CRC-16-MODBUS
        x16+x15+x2+1

     在线计算器计算的正常结果是 0xDDBA。

  • 我觉得他是把那段代码复制出来用的

    按照注释理解 这段代码是做了4个字节的crc校验吧 而不是12个字节

    而且注意

    这种计算 输入 输出都做了反转

    工具默认就是反转的 而且不能更改

    我在做校验对比验证的时候 用的是这种校验方式

    把要校验的数据 以16bit为单位 按照低字节在前 高字节在后的顺序 输入到这个工具输入框里

    在388里 选择crc16 poly2 0x1021 也是按照低字节在前 高字节在后的顺序进行校验,不过这个无所谓 应为校验顺序可选的 哪个在前哪个在后都行 只要验证工具和388设置的方式一致就可以 因为我的系统里要和430单片机通许,所以我才选择低字节在前

  • 那我要用VCRC单元做如下图的校验需要调用那个汇编例程?具体怎么操作?另外我用查表方式校验的结果是和在线计算器校验的结果是一致的

  • 以下是查表校验程序

  • 你是已经用查表法实现校验了对吗 那是不是就不比一定要用文档里的汇编了呢

    至于这个“那我要用VCRC单元做如下图的校验需要调用那个汇编例程?

    C2000ware 没有相关的280025的例程

  • 感谢 user78960159参与讨论~

    CRC-16-MODBUS
        x16+x15+x2+1

     在线计算器计算的正常结果是 0xDDBA。

    我把这些同步给相关的工程师看一下

  • 主要想用VCRC单元来实现,看计算速度快不快。查表方式占用空间比较大。

  • 恩是的 应该还是用VCU算合理一些 VCU和C28是并行的结构 这也是我在用388时候校验选择VCU的原因

  • 主要想用VCRC单元来实现,看计算速度快不快。查表方式占用空间比较大。

    好的

  • 其实你用cla用查表算crc也行 不占用c28的资源

  • 如果CLA没有被使用的话,这也是一个方法。

  • CRC-16-MODBUS
        x16+x15+x2+1这种校验模式初始值是固定的为0xFFFF,

    我试了下controlSUITE\libs\dsp\VCU\v110\source\C28x_VCU_LIB这里面的例程结果也是不对,.asm文件代码如下

    ; -------------------
    ; Calculate the CRC of a block of data
    ; This function assumes the block is a multiple of 2 16-bit words
    ;
    		.if __TI_EABI__
    	  	.asg getCRC16P1_vcu, _getCRC16P1_vcu
    	  	.asg CRC16P1 , _CRC16P1
    	  	.asg getCRC16P2_vcu, _getCRC16P2_vcu
    	  	.endif
    
    ;	  	.def _getCRC16P1_vcu
    ;		.def    CRC16P1
    		.global _CRC16P1
    		.global _getCRC16P2_vcu
    		.global	_getCRC16P1_vcu
    
    ;		.text
    
    _CRC16P1
    		VCRCCLR 					; Clear the result register
    		MOV		AL, 	*+XAR4[4] 	; AL = CRCLen
    		ASR 	AL, 	2 			; AL = CRCLen/4
    		SUBB 	AL, 	#1 			; AL = CRCLen/4 - 1
    		MOVL 	XAR7, 	*+XAR4[2]	; XAR7 = &CRCData
    		.align 2
    		NOP 						; Align RPTB to an odd address
    		RPTB _CRC16P1_done, AL 		; Execute block of code AL + 1 times
    		VCRC16P1L_1 *XAR7 			; Calculate CRC for 4 bytes
    		VCRC16P1H_1 *XAR7++ 		; ...
    		VCRC16P1L_1 *XAR7 			; ...
    		VCRC16P1H_1 *XAR7++ 		; ...
    
    _CRC16P1_done
    		MOVL 	XAR7, 	*+XAR4[0] 	; XAR7 = &CRCResult
    		VMOV32 	*+XAR7[0], VCRC 	; Store the result
    		LRETR						; return to caller
    
    
    
    
    
    _getCRC16P2_vcu:
    	  PUSH		  XAR0
    	  PUSH        XAR1
    
    	  MOVZ        AR0, *-SP[7]        ; load rxLen
          ADDB        SP, #4              ; allocate 4 words for local
          VMOV32      *-SP[2], VCRC       ; Store current CRC
          VCRCCLR
          MOVL        *-SP[4], ACC
          VMOV32      VCRC,*-SP[4]        ; VCRC = Inital value
          MOV         AL,AR5              ; check the parity
          SBF         _CRC16p2_loop_prep, EQ
          VCRC16P2H_1 *XAR4++             ; if parity=1, calculate high byte first
          DEC         AR0
          SBF         _CRC16p2done, EQ
    _CRC16p2_loop_prep:
          MOV         AL, AR0
          MOV         AH, AR0
          AND         AL, #0xFFF8         ; check to see if the length is greater than 8 bytes
          BF          _CRC16p2_LSB,EQ
          LSR         AL, #3              ; loop in 8 bytes
          MOV         AR1, AL
          SUB         AR1, #1
    
          .align     (2)                  ; align at 32-bit boundary to remove penalty
          RPTB        _CRC16p2_post, AR1  ; loop for the middle part of the packet
          VCRC16P2L_1 *XAR4
          VCRC16P2H_1 *XAR4++
          VCRC16P2L_1 *XAR4
          VCRC16P2H_1 *XAR4++
          VCRC16P2L_1 *XAR4
          VCRC16P2H_1 *XAR4++
          VCRC16P2L_1 *XAR4
          VCRC16P2H_1 *XAR4++
    _CRC16p2_post
          LSL         AL, #3              ; calculating remaining number of bytes
          SUB         AH, AL
          SBF         _CRC16p2done, EQ	  ;branch to end on 0 remainder
          MOV         AR0, AH
    _CRC16p2_LSB
          VCRC16P2L_1 *XAR4               ; if parity=0, calculate the low byte
          DEC         AR0
          SBF         _CRC16p2done, EQ
          VCRC16P2H_1 *XAR4++
          DEC         AR0
          SBF         _CRC16p2_LSB, NEQ
    _CRC16p2done
          VMOV32       *-SP[4], VCRC        ; Store CRC
          MOV          AL, *-SP[4]          ; return AL
          VMOV32       VCRC, *-SP[2]        ; Restore VCRC
          SUBB         SP, #4               ; restore stack pointer
          POP          XAR1
          POP		   XAR0
          LRETR
    
    
    _getCRC16P1_vcu:
    	  PUSH 		  XAR0
    	  PUSH        XAR1
    
    	  MOVZ        AR0, *-SP[7]        ; load rxLen
          ADDB        SP, #4              ; allocate 4 words for local
          VMOV32      *-SP[2], VCRC       ; Store current CRC
          VCRCCLR
          MOVL        *-SP[4], ACC
          VMOV32      VCRC,*-SP[4]        ; VCRC = Inital value
          MOV         AL, AR5             ; check the parity
          SBF         _CRC16p1_loop_prep, EQ
          VCRC16P1H_1 *XAR4++             ; if parity=1, calculate high byte first
          DEC         AR0
          SBF         _CRC16p1done, EQ
    _CRC16p1_loop_prep:
          MOV         AL, AR0
          MOV         AH, AR0
          AND         AL, #0xFFF8         ; check to see if the length is greater than 8 bytes
          BF          _CRC16p1_LSB,EQ
          LSR         AL, #3              ; loop in 8 bytes
          MOV         AR1, AL
          SUB         AR1, #1
    
          .align     (2)                  ; align at 32-bit boundary to remove penalty
          RPTB        _CRC16p1_post, AR1  ; loop for the middle part of the packet
          VCRC16P1L_1 *XAR4
          VCRC16P1H_1 *XAR4++
          VCRC16P1L_1 *XAR4
          VCRC16P1H_1 *XAR4++
          VCRC16P1L_1 *XAR4
          VCRC16P1H_1 *XAR4++
          VCRC16P1L_1 *XAR4
          VCRC16P1H_1 *XAR4++
    _CRC16p1_post
          LSL         AL, #3              ; calculating remaining number of bytes
          SUB         AH, AL
          SBF         _CRC16p1done, EQ	  ;branch to end on 0 remainder
    	  MOV         AR0, AH
    _CRC16p1_LSB
          VCRC16P1L_1 *XAR4               ; if parity=0, calculate the low byte
          DEC         AR0
          SBF         _CRC16p1done, EQ
          VCRC16P1H_1 *XAR4++
          DEC         AR0
          SBF         _CRC16p1_LSB, NEQ
    _CRC16p1done
          VMOV32       *-SP[4], VCRC        ; Store CRC
          MOV          AL, *-SP[4]          ; return AL
          VMOV32       VCRC, *-SP[2]        ; Restore VCRC
          SUBB         SP, #4               ; restore stack pointer
          POP          XAR1
          POP		   XAR0
          LRETR
    
    

    函数调用代码如下:

    typedef enum{
        CRC_parity_even = 0,
        CRC_parity_odd = 1
    }CRC_parity_e;
    
    typedef struct {
        Uint32 *CRCResult;      // Address where result should be stored
        Uint16 *CRCData;        // Start of data
        Uint16 CRCLen ;          // Length of data in bytes
    }CRC_CALC;
    CRC_CALC mycrc;
    
    extern Uint32 CRC16P1(CRC_CALC *mycrc);
    extern Uint16 getCRC16P1_vcu(Uint32 input_crc16_accum, Uint16 *msg, CRC_parity_e parity, Uint16 rxLen);
    extern Uint16 getCRC16P2_vcu(Uint32 input_crc16_accum, Uint16 *msg, CRC_parity_e parity, Uint16 rxLen);
    
    Uint32 CRC16resultP1;
    Uint32 CRC16resultP2;
    Uint16 inputdata[6]= {0x01,0x02,0x03,0x04,0x05,0x06};
    static const Uint16 CRC16inputdata[6] = {0x01,0x02,0x03,0x04,0x05,0x06};
    void main(void)
    {
        //mycrc.CRCResult = TESTresult;
        mycrc.CRCData = inputdata;
        mycrc.CRCLen = 6;
    
        while(1)
        {
            CRC16P1(&mycrc);
            CRC16resultP1 = getCRC16P1_vcu(0xFFFF, (Uint16*)CRC16inputdata, (CRC_parity_e)CRC_parity_even, 6);
            CRC16resultP2 = getCRC16P2_vcu(0xFFFF, (Uint16*)CRC16inputdata, (CRC_parity_e)CRC_parity_even, 6);
         }

    得到结果是:

    *(CRCResult) = 0x00001800;

    CRC16resultP1 = 0x00005AD8,CRC16resultP2  = 0x0000F38B,

    当初始改为0x0000时,j结果是:

    CRC16resultP1 = 0x00005A00,CRC16resultP2  = 0x0000FD9B,

    以上结果都与在线计算的结果不对应,正确结果应为DDBA

    可用如下地址在线计算:

    https://www.lddgo.net/en/encrypt/crc

    当我使用VCU检验时,校验方式为CRC-16-MODBUS   x16+x15+x2+1 

    是我使用的例程不对吗?该使用那个例程?

    麻烦帮忙问一些,谢谢!

  • 好的,我已经跟进过去了

  • 函数调用的程序好像没跟进过去。

  • 你好,根据回答的方法,

    我将

    Uint16 inputdata[6]= {0x01,0x02,0x03,0x04,0x05,0x06};

    Uint16 CRC16inputdata[3] ={0x01,0x02,0x03,0x04,0x05,0x06};

    修改为

    Uint16 inputdata[3]= {0x0201,0x0403,0x0605};

    Uint16 CRC16inputdata[3] ={0x0201,0x0403,0x0605};

    得到的结果是

    *(CRCResult) = 0x00009E33;

    CRC16resultP1 = 0x0000DA6F,

    CRC16resultP2  = 0x0000D71C,

    其中CRC16resultP2  = 0x0000D71C,符合多项式CRC-16-CCITT-FALSE   x16+x12+x5+1的结果,

    但是我需要多项式CRC-16-MODBUS   x16+x15+x2+1 的VCU计算例程,

    请问我需要怎么修改才能得到我想要的结果?

    谢谢

  • 好的,我跟进过去了

  • 当RefIn为True时,输入的原始数据的每个字节需要做个逆序的处理,注意:针对的每个字节,而不是整个数据,以一个4字节的原始数据为例:

    当Refout为True,需要对输出数据做一次整个数据的逆序处理,注意:这里做的逆序和RefIn不同,它不是按字节逆序,而是整个逆序,以CRC-32为例来说明,最后的数据为32位,当Refout为True时,翻转如下:

  • 好的,我跟进过去了