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 例程时输出不正确

Guru**** 2551040 points
Other Parts Discussed in Thread: CONTROLSUITE, C2000WARE

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1260124/tms320f280025-incorrect-output-using-the-crc-routine-provided-on-page-642-of-spruhs1c

器件型号:TMS320F280025
主题中讨论的其他器件:controlSUITEC2000WARE

大家好、

以下是客户可能需要您的帮助的问题:

下面显示了客户创建的.asm 文件:

被称为汇编函数:

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

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

CRC16P1(&mycrc);

返回的结果为 0x8059 ,它不对应于正确的结果 0xDDBA

原因是什么?

--

谢谢、此致

耶鲁

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好,耶鲁,

    让我来看看我们的软件团队的功能。 是否可以确认用于计算预期正确结果的多项式?

    此致、

    维维克·辛格  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    谢谢  Vivek、

    它是:  

    CRC-16-MODBUS
      x 16 + x 15 + x 2 + 1

    在线计算得出的正确结果为 0xDDBA。

    --

    谢谢、此致

    耶鲁

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好,耶鲁,

    谢谢。 在这里、您可以将初始值设置为 FFFF。 您能否尝试将其变为0000、看看这是否有用。

    此致、

    维维克·辛格

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Vivek、

    客户反馈:

    此检查模式的初始值是固定的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、结果为

    CRC16resultP1 = 0x00005A00,CRC16resultP2 = 0x0000FD9B、

    上述结果与在线计算结果不对应、正确结果应为0xDDBA。

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

    当我使用 VCU 进行验证时、验证方法是 CRC-16-MODBUS x16+x15+x2+1  。

    我使用的例程是否错误? 我应该使用哪种例程?

    --

    谢谢、此致

    耶鲁

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    耶鲁大学

    uint16 inputdata[6]={0x01、0x02、0x03、0x04、0x05、0x06};

    最终这个值为0x0001、0x0002、0x0003、0x0004、0x0005、 0x0006

    然后、当您对6个字节计算 CRC 时、将按照以下顺序 LSB-MSB-LSB-MSB 进行计算、因此您正在计算0x01-0x00-0x02-0x00-0x03-0x00上的 CRC。

    如果您希望在0x01-0x02-0x03-0x04-0x05-0x06上计算它、那么您的输入缓冲区需要定义为

    uint16 inputdata[3]={0x0201、0x0403、0x0605};

    谢谢。

    Sira

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Sira:

    感谢您的答复。

    根据您提供的方法、我的客户改变了  

    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 计算例程。

    我的客户需要如何修改才能获得所需的结果?

    --

    谢谢、此致

    耶鲁

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    耶鲁大学

    在您共享的在线 CRC 计算器工具的图片中、"Reverse (反向)"字段中的 REFIN 和 REFOUT 上的复选标记是什么?

    谢谢。

    Sira

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Sira:

    当 REFIN 为真时、每个 字节 需要以相反的顺序处理输入原始数据。 请注意:对于每个字节而不是整个数据,以4字节的原始数据为例:

    当 REFOUT 为 True 时、输出数据的处理顺序与 整个 数据 。 请注意:此处执行的反向顺序操作与 REFIN 不同、它不是字节反向顺序、而是整个反向顺序。 以 CRC-32为例、最终数据为32位。 当 REFOUT 为 true 时、 反向如下:

    --

    谢谢、此致

    耶鲁

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    耶鲁大学

    那么在计算 CRC 时是否使用相应的设置、即通过 VSETCRCMSGFLIP 指令位反转输入字节、通过位反转输出(例如通过_flip32 ()内在函数)。

    C2000Ware 有一个示例可提供帮助、它既具有常规计算、也具有位反向计算(称为"反射")。

    C:\ti\cc2000\C2000Ware_5_00_00\libraries\dsp\VCU\c28\examples\crc\28003x_vcrc_crc_16

    谢谢。

    Sira