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.

TMS320F280049: CRC-32 reflected by using VCU0

Part Number: TMS320F280049


Hi,

VCU2 has " VSETCRCMSGFLIP / VCLRCRCMSGFLIP" instructions to process CRC-32 reflected input .

But TMS320F280049 VCU0 has no these instructions.

Is there any example code  to replace these instructions?

thanks,

best regards,

Simen

  • Simen,

    Sorry, we don't have any example code, but the description should indicate what steps you need to take.

    Set the CRCMSGFLIP bit in the VSTATUS register. This causes the VCU to process
    message bits starting from least-significant to most-significant for CRC computation. In
    this case, bytes loaded from memory are “flipped” and then fed for CRC computation. (so you need to write C code to flip the byte)

    Clear the CRCMSGFLIP bit in the VSTATUS register. This causes the VCU to process
    message bits starting from most-significant to least-significant for CRC computation. In
    this case, bytes loaded from memory are fed directly for CRC computation. (in other words, you don't need to do anything)

    Thanks,

    Sira

  • Sira,

    However input data can be flipped.

    But reflected type CRC also must use flipped polynomial.

    I can not find how to flip polynomial on VCU0.

    Therefore VCU0 can not process reflected CRC.

    Is it right?

    refer to www.sunshine2k.de/.../understanding_crc.html

    best regards,

    Simen

  • Simen,

    That link is blocked when trying to access it from within the TI network.

    I don't believe the Reflected CRC computation requires the CRC polynomial to also be reflected. I believe it is just the input bits that need to be reflected. The reasons for believing this are:

    1. The instruction guide description of CRCMSGFLIP, which I pasted in my previous message.

    2. The assembly code indicates that the only difference between the regular CRC computation and the reflected CRC computation is the setting of the bit prior to the CRC computation, and clearing this bit after the computation. And as indicated in (1) above, the implication is that this bit only affects the order of the input bits to the CRC calculator, not the CRC polynomial.

    _CRC_run16BitPoly1Reflected:
    VSETCRCMSGFLIP
    LCR _CRC_run16BitPoly1
    VCLRCRCMSGFLIP
    LRETR

    Thanks,

    Sira

  • Hi Sira,

    I do the experiment on F2837x VCU2.
    I just disable CRCMSGFLIP bit, and manually flip input data .  
    But the result (CRC32_result02) is not the same with use  " VSETCRCMSGFLIP / VCLRCRCMSGFLIP" instructions (CRC32_result01).
    Could you help me to point out why I can not get the same result?
    This help me implement CRC-32 reflected type on VCU0.

    unsigned int CRC_Test_01[16] = {0xFE,0x12,0x00,0x09,0x01,0x03,0x04,0x00,0x01,0x00,0x00,0xAB,0xF3,0x00,0x00,0x00};
    unsigned int CRC_Test_02[16] = {0x7F,0x48,0x00,0x90,0x80,0xC0,0x20,0x00,0x80,0x00,0x00,0xD5,0xCF,0x00,0x00,0x00};  //flip data

    final result data: CRC32_result01=0x70F15A61, CRC32_result02=0x94C49E23

    attach file: replace cpu_timers_cpu01.c  file  in TMS320F2837x  cpu_timers_cpu01 project.

    //###########################################################################
    //
    // FILE:   cpu_Timers_cpu01.c
    //
    // TITLE:  Cpu Timers Example for F2837xD.
    //
    //! \addtogroup cpu01_example_list
    //! <h1> CPU Timers </h1>
    //!
    //! This example configures CPU Timer0, 1, and 2 and increments
    //! a counter each time the timer asserts an interrupt.
    //!
    //! \b Watch \b Variables \n
    //! - CpuTimer0.InterruptCount
    //! - CpuTimer1.InterruptCount
    //! - CpuTimer2.InterruptCount
    //!
    //
    //###########################################################################
    // $TI Release: F2837xD Support Library v3.06.00.00 $
    // $Release Date: Mon May 27 06:48:24 CDT 2019 $
    // $Copyright:
    // Copyright (C) 2013-2019 Texas Instruments Incorporated - http://www.ti.com/
    //
    // Redistribution and use in source and binary forms, with or without 
    // modification, are permitted provided that the following conditions 
    // are met:
    // 
    //   Redistributions of source code must retain the above copyright 
    //   notice, this list of conditions and the following disclaimer.
    // 
    //   Redistributions in binary form must reproduce the above copyright
    //   notice, this list of conditions and the following disclaimer in the 
    //   documentation and/or other materials provided with the   
    //   distribution.
    // 
    //   Neither the name of Texas Instruments Incorporated nor the names of
    //   its contributors may be used to endorse or promote products derived
    //   from this software without specific prior written permission.
    // 
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    // $
    //###########################################################################
    
    //
    // Included Files
    //
    #include "F28x_Project.h"
    
    //
    // Function Prototypes
    //
    __interrupt void cpu_timer0_isr(void);
    __interrupt void cpu_timer1_isr(void);
    __interrupt void cpu_timer2_isr(void);
    void CRC32_ADCCP_01(unsigned int *CRCResult, unsigned int  *CRCData, unsigned int   CRCLen);
    void CRC32_ADCCP_02(unsigned int *CRCResult, unsigned int  *CRCData, unsigned int   CRCLen);
    
    // Test data
    unsigned int CRC_Test_01[16] = {0xFE,0x12,0x00,0x09,0x01,0x03,0x04,0x00,0x01,0x00,0x00,0xAB,0xF3,0x00,0x00,0x00};
    unsigned int CRC_Test_02[16] = {0x7F,0x48,0x00,0x90,0x80,0xC0,0x20,0x00,0x80,0x00,0x00,0xD5,0xCF,0x00,0x00,0x00};  //flip data
    
    //result put after pattern[16] 4 bytes
    //CRC32_MODBUS(&CRC_Test[16], &CRC_Test[0], 16);
    Uint16  test_CRC[20];
    Uint32 CRC32_result01=0,CRC32_result02=0;
    
    void main(void)
    {
    //
    // Step 1. Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the F2837xD_SysCtrl.c file.
    //
        InitSysCtrl();
    
    //
    // Step 2. Initialize GPIO:
    // This example function is found in the F2837xD_Gpio.c file and
    // illustrates how to set the GPIO to it's default state.
    //
        InitGpio();
        GPIO_SetupPinMux(65, GPIO_MUX_CPU1, 0);
        GPIO_SetupPinOptions(65, GPIO_OUTPUT, GPIO_PUSHPULL);
    
    //
    // Step 3. Clear all interrupts and initialize PIE vector table:
    // Disable CPU interrupts
    //
        DINT;
    
    //
    // Initialize the PIE control registers to their default state.
    // The default state is all PIE interrupts disabled and flags
    // are cleared.
    // This function is found in the F2837xD_PieCtrl.c file.
    //
        InitPieCtrl();
    
    //
    // Disable CPU interrupts and clear all CPU interrupt flags:
    //
        IER = 0x0000;
        IFR = 0x0000;
    
    //
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    // This will populate the entire table, even if the interrupt
    // is not used in this example.  This is useful for debug purposes.
    // The shell ISR routines are found in F2837xD_DefaultIsr.c.
    // This function is found in F2837xD_PieVect.c.
    //
        InitPieVectTable();
    
    //
    // Interrupts that are used in this example are re-mapped to
    // ISR functions found within this file.
    //
        EALLOW;  // This is needed to write to EALLOW protected registers
        PieVectTable.TIMER0_INT = &cpu_timer0_isr;
        PieVectTable.TIMER1_INT = &cpu_timer1_isr;
        PieVectTable.TIMER2_INT = &cpu_timer2_isr;
        EDIS;    // This is needed to disable write to EALLOW protected registers
    
    //
    // Step 4. Initialize the Device Peripheral. This function can be
    //         found in F2837xD_CpuTimers.c
    //
        InitCpuTimers();   // For this example, only initialize the Cpu Timers
    
    //
    // Configure CPU-Timer 0, 1, and 2 to interrupt every second:
    // 200MHz CPU Freq, 1 second Period (in uSeconds)
    //
        ConfigCpuTimer(&CpuTimer0, 200, 1000000);
        ConfigCpuTimer(&CpuTimer1, 200, 1000000);
        ConfigCpuTimer(&CpuTimer2, 200, 1000000);
    
    //
    // To ensure precise timing, use write-only instructions to write to the
    // entire register. Therefore, if any of the configuration bits are changed in
    // ConfigCpuTimer and InitCpuTimers (in F2837xD_cputimervars.h), the below
    // settings must also be updated.
    //
        CpuTimer0Regs.TCR.all = 0x4000;
        CpuTimer1Regs.TCR.all = 0x4000;
        CpuTimer2Regs.TCR.all = 0x4000;
    
    //
    // Step 5. User specific code, enable interrupts:
    //
    
    //
    // Enable CPU int1 which is connected to CPU-Timer 0, CPU int13
    // which is connected to CPU-Timer 1, and CPU int 14, which is connected
    // to CPU-Timer 2:
    //
        IER |= M_INT1;
        IER |= M_INT13;
        IER |= M_INT14;
    
    //
    // Enable TINT0 in the PIE: Group 1 interrupt 7
    //
        PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
    
    //
    // Enable global Interrupts and higher priority real-time debug events:
    //
    //    EINT;  // Enable Global interrupt INTM
        ERTM;  // Enable Global realtime interrupt DBGM
    
    //
    // Step 6. IDLE loop. Just sit and loop forever (optional):
    //
        test_CRC[0]=1;
        test_CRC[1]=2;
    //    CRC_Test[0]=0xFE;
        CRC32_ADCCP_01(&CRC_Test_01[16], &CRC_Test_01[0], 16);  //result 0x70F15A61
        CRC32_ADCCP_02(&CRC_Test_02[16], &CRC_Test_02[0], 16);  //result
    
    
        while(1)
        {
    
        }
    }
    
    //
    // cpu_timer0_isr - CPU Timer0 ISR with interrupt counter
    //
    __interrupt void cpu_timer0_isr(void)
    {
       CpuTimer0.InterruptCount++;
    
       //
       // Acknowledge this interrupt to receive more interrupts from group 1
       //
       PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
    }
    
    //
    // cpu_timer1_isr - CPU Timer1 ISR
    //
    __interrupt void cpu_timer1_isr(void)
    {
       CpuTimer1.InterruptCount++;
       asm("    NOP"); //1
       asm("    NOP"); //2
       asm("    NOP"); //3
       asm("    NOP"); //4
       asm("    NOP"); //5
       asm("    NOP"); //6
    }
    
    //
    // cpu_timer2_isr CPU Timer2 ISR
    //
    __interrupt void cpu_timer2_isr(void)
    {
       CpuTimer2.InterruptCount++;
    }
    
    
    void CRC32_ADCCP_01(unsigned int *CRCResult, unsigned int  *CRCData, unsigned int   CRCLen)
    {             //                *XAR4:CRCResult           XAR5 :CRCData            AL:CRCLen
        asm("    MOV AL,#16              ; AL = CRCLen, buffer to AR7");
        asm("    MOV AR7,AL              ; AL = CRCLen, buffer to AR7");
        asm("    MOVB ACC, #0            ; Init CRCResult            ");
        asm("    SUBB ACC, #1            ; Set to be 0xFFFFFFFF      ");
        asm("    MOVL *XAR4,ACC          ; *CRCResult = 0xFFFFFFFF   ");
        asm("    VMOV32 VCRC, *XAR4      ; Set VCRC = 0xFFFFFFFF     ");
    
        asm("    MOV AL, AR7             ; Restore AL = CRCLen");
        asm("    LSR AL, #2              ; AL = CRCLen/4      ");
        asm("    SUBB AL, #1             ; AL = AL - 1        ");
        asm("    VSETCRCMSGFLIP                               ");
        asm("    NOP                     ; Align RPTB to an odd address");
    //    asm("    NOP                     ; Align RPTB to an odd address");
    //    asm(".align     (2)                     ; Align RPTB to an odd address");
        asm("    RPTB CRC32MBS_done, AL   ; Execute block of code AL + 1 times");
        asm("    VCRC32L_1 *XAR5++       ; Calculate CRC for 4 bytes         ");
        asm("    VCRC32L_1 *XAR5++       ; ...");
        asm("    VCRC32L_1 *XAR5++       ; ...");
        asm("    VCRC32L_1 *XAR5++       ; ...");
        asm("CRC32MBS_done: ");
    
        asm("    VCLRCRCMSGFLIP                               ");
        asm("    VMOV32 ACC, VCRC        ; Store the result   ");
        asm("    FLIP AL                 ; Relect final result");
        asm("    FLIP AH                                      ");
        asm("    XOR AL, #0xffff         ; XOR to 0xFFFFFFFF  ");
        asm("    XOR AH, #0xffff");
    
        asm("    MOV DP,#_CRC32_result01            ; get DP");
        asm("    MOVW @_CRC32_result01, AH          ; byte switch");
        asm("    MOVW @_CRC32_result01+1, AL        ; ");
    
    
        asm("    LRETR                       ; return to caller");
    }
    
    void CRC32_ADCCP_02(unsigned int *CRCResult, unsigned int  *CRCData, unsigned int   CRCLen)
    {             //                *XAR4:CRCResult           XAR5 :CRCData            AL:CRCLen
        asm("    MOV AL,#16              ; AL = CRCLen, buffer to AR7");
        asm("    MOV AR7,AL              ; AL = CRCLen, buffer to AR7");
        asm("    MOVB ACC, #0            ; Init CRCResult            ");
        asm("    SUBB ACC, #1            ; Set to be 0xFFFFFFFF      ");
        asm("    MOVL *XAR4,ACC          ; *CRCResult = 0xFFFFFFFF   ");
        asm("    VMOV32 VCRC, *XAR4      ; Set VCRC = 0xFFFFFFFF     ");
    
        asm("    MOV AL, AR7             ; Restore AL = CRCLen");
        asm("    LSR AL, #2              ; AL = CRCLen/4      ");
        asm("    SUBB AL, #1             ; AL = AL - 1        ");
    //    asm("    VSETCRCMSGFLIP                               ");
        asm("    NOP                     ; Align RPTB to an odd address");
        asm("    NOP                     ; Align RPTB to an odd address");
    //    asm(".align     (2)                     ; Align RPTB to an odd address");
        asm("    RPTB CRC32MBS_done2, AL   ; Execute block of code AL + 1 times");
        asm("    VCRC32L_1 *XAR5++       ; Calculate CRC for 4 bytes         ");
        asm("    VCRC32L_1 *XAR5++       ; ...");
        asm("    VCRC32L_1 *XAR5++       ; ...");
        asm("    VCRC32L_1 *XAR5++       ; ...");
        asm("CRC32MBS_done2: ");
    
    //    asm("    VCLRCRCMSGFLIP                               ");
        asm("    VMOV32 ACC, VCRC        ; Store the result   ");
        asm("    FLIP AL                 ; Relect final result");
        asm("    FLIP AH                                      ");
        asm("    XOR AL, #0xffff         ; XOR to 0xFFFFFFFF  ");
        asm("    XOR AH, #0xffff");
    
        asm("    MOV DP,#_CRC32_result02            ; get DP");
        asm("    MOVW @_CRC32_result02, AH          ; byte switch");
        asm("    MOVW @_CRC32_result02+1, AL        ; ");
    
        asm("    LRETR                       ; return to caller");
    }
    
    
    //
    // End of file
    //
    


    attach picture: CRC-32/ADCCP result

    best regards,

    Simen

  • Simen,

    Your approach is an interesting way of verifying the results.

    Please give me a day to dig into this and get back to you.

    Thanks,

    Sira

  • Simen,

    I am suspecting the byte order may matter.

    Could you try swapping the low-high bytes.

    unsigned int CRC_Test_02[16] = {0x48, 0x7F,,0x90,0x00,0xC0,0x80,0x00,0x20,0x00,0x80,0xD5,0x00,0x00,0xCF,0x00,0x00}; //flip data

    Ideally it is good to define the input as static const uint16_t testInput[NWORDS] = { <16-bit words>}; as in the library examples.

    Thanks,

    Sira

  • Simen,

    I am eager to know what you found.

    Thanks,

    Sira

  • Sira,

    unsigned int CRC_Test_02[16] = {0x48,0x7F,0x90,0x00,0xC0,0x80,0x00,0x20,0x00,0x80,0xD5,0x00,0x00,0xCF,0x00,0x00}; //flip data

    The result is 0x1F75E26F from you provide data matrix.

    It is still not correct.

    I have modified the program (I have provided) for 8-bit data matrix.

    No more high/low byte issue.

    best regards,

    Simen

  • Simen,

    Ok, thanks for checking.

    I tried to run the test at my end with your test data, and I am not able to even generate the CRC 0x70F15A61 that you obtained. I presume you were able to obtain this value using the VCU library. Can you tell me the settings and test data format you used for this?

    I presume you used 

    CRC.seedValue = 0xFFFFFFFF; 
    CRC.nMsgBytes = 16;
    CRC.parity = CRC_parity_even;

    Thanks,

    Sira

  • Sira,

    I have tried out CRC-32 reflected type on F28377D VCU0 .

    My program may have the bugs..

    I will try to implement it on F280049 VCU0 by myself.

    Thanks for your a lot of suggestions.

    best regards,

    Simen

  • Simen,

    OK, please do come back if you continue to have issues.

    Thanks,

    Sira