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.

how to use CRC on 2806x

Other Parts Discussed in Thread: CONTROLSUITE

hallo,

I would like to use the CRC instructions to calculate the CRC of a packet being sent through SCI.

in the documentation there are some examples, such as:

typedef struct {
uint32_t *CRCResult;      //  Address where result should be stored
uint16_t *CRCData;        //  Start of data
uint16_t CRCLen; //  Length of data in bytes
}CRC_CALC;
CRC_CALC mycrc;
...
CRC16P1(&mycrc);
...

; -------------------
; Calculate the CRC of a block of data
; This function assumes the block is a multiple of 2 16-bit words
;
.global _CRC16P1
_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
MOV32  *+XAR7[0], VCRC    ; Store the     result
LRETR ; return to caller

 

 

after reading the documentation I still have some questions:

1. I need to initialize mycrc struct with my vector of bytes address and the length. this is trivial. true ?

2. as I understand the VCU works parallel to the CPU. do I need to wait for the result to be ready (VCRC register) ? I didn't see any flags indicating the result is ready... or the call to one of the CRC functions will be done when the result is ready ?

3. why is it written "this function assumes the block is a multiple of 2 16-bit words" ?

4. does the CRClen field in the struct is the length in bytes or words ?

5. if you could post a simple example showing how to calculate the CRC of a given vector of Uint16 will be great.

 

thanks

Ari.

 

  • Hi Ari,

    The answers to your question:

    1. true- shown in controlSUITE demo (see point 5)

    2. The VCU shares the pipeline with the CPU. It doesnt operate parallel to it.

    3. The CRC module in hardware operates on 8-bit data only. The example uses 4 crc instructions in a repeat block to calculate the CRC for 4 bytes, so it assumes the size of your data block is a multiple of 4 bytes

    VCRC16P1L_1 *XAR7         ; Calculate CRC for 4 bytes
    VCRC16P1H_1 *XAR7++       ; ...
    VCRC16P1L_1 *XAR7         ; ...
    VCRC16P1H_1 *XAR7++       ; ...


    4. The length is in bytes only!

    5. there is a VCU library in controlSUITE: controlSUITE/libs/dsp/VCU that has a crc demo.

  • Hi Vishal,

    thanks for your quick reply...

    just to clarify - if my data vector is NOT a multiple of 4 bytes (let's say it's 5 words), can I still use the library ? if so, do I need to change something ? if not, then it could be a problem because it hurts the generality of the software design (or communication protocol in this case)...

    another thing - in your example for the CRC I think you didn't apply the workaround mentioned in the errata. I think it should be included. for now, I took the assembly code that is in the errata (making a dummy CRC calculation) "as is". that should be enough, right ?

     

    thanks again

    Ari.

  • Hi Ari,

    I made a mistake in my earlier post. the library implementation of the crc routine requires the input to be a multiple of 8 bytes. The library implementation was meant for the generic use case. If your message size is fixed to 10 bytes(5 words) it would be easier to implement your own function ...something along these lines

    in a seperate .asm file :

        .cdecls C,LIST,"header.h"

        .sect ".text"
        .def _getCRC8_pkt
    _getCRC8_pkt:
    ; pointers passed to this function automatically
    ; get passed to XAR4/XAR5
          ADDB       SP, #4              ; allocate 2 words for local
          VCRCCLR
          VCRC8L_1   *XAR4         ;note i start CRC at the low byte. I assume little endianess of the data     
          VCRC8H_1   *XAR4++
          VCRC8L_1   *XAR4               
          VCRC8H_1   *XAR4++
          VCRC8L_1   *XAR4               
          VCRC8H_1   *XAR4++
          VCRC8L_1   *XAR4               
          VCRC8H_1   *XAR4++
          VCRC8L_1   *XAR4               
          VCRC8H_1   *XAR4++
          VMOV32     *-SP[2], VCRC        ; Store CRC
          MOV         AL, *-SP[4]         ; return AL
          SUBB         SP, #2             ; restore stack pointer
          LRETR

    In the header.h file specify the prototype for this functions as:

    extern uint16 getCRC8_pkt(uint16 *);

    In your code you should be able to use it by passing the address of your data packet and get the CRC as the return variable in AL. This implementation assumes that your CRC is not being calcuated over fragmented messages. If you want to calculate CRC over a bunch of packets you will have to modify the library code to not use a repeat block and calculate CRC over 10 bytes instead of 8.

     

    Im glad you brought up the workaround in the errata. It is sufficent to run that code once at the beginning of your program

    I agree that it needs to be included in the library. Ill peg it as update for the next release.

  • Hi Vishal,

    thanks for the insight.

    maybe it's possible to write a function that would be parametric and would not be "size-constant" ?

    I wouldn't want to implement such a code in my application and then one day someone would change the packet size and the crc will not work...

    maybe something like

    CRC = Calc_CRC16(uint16 CRC_TYPE, (uint16 *) vec, uint16 vec_size)

    thanks

    Ari

  • you could, the library makes use of the RPTB instruction which needs atleast 8 words or 4 32-bit instructions in the block....which imposes a multiplicative constraint on the size of your input data. If you want to make it truly generic you probably would have to resort to iterative loops of the kind::

    Note i havent done any argument checking and odd byte checking. this is a very simple UNTESTED loop

     

     .cdecls C,LIST,"header.h"

        .sect ".text"
        .def _Calc_CRC16
    _Calc_CRC16:
    ; XAR4 <- pointer to packet
    ; AL <- length in WORDS
          ADDB       SP, #4              ; allocate 2 words for local
          MOV         AR0,AL                 ; store count in AR0
          VCRCCLR
    _loop:
          DEC         AR0
          SBF        _done, EQ
          VCRC16P1L_1   *XAR4         ;note i start CRC at the low byte. I assume little endianess of the data     
          VCRC16P1H_1   *XAR4++
          SBF         _loop, UNC       ;keep branching till 0
    _done:
          VMOV32     *-SP[2], VCRC        ; Store CRC
          MOV         AL, *-SP[4]         ; return AL
          SUBB         SP, #2             ; restore stack pointer
          LRETR

     

    and the protototype for the function is as you have described in your earlier post