简体   繁体   中英

Assembly AVR ATMEGA128: CRC Algorithm

I have to do a simple CRC check for the following: Take an 8-bit input from a port, get it's CRC checksum value and output it. So far, I can take the input and I read the algorithm, so I append n - 1 zeros to my input, effectively making it big enough to be 16 bit. I got that working as well and I know I'll need a XOR here as we do a modulo 2 while dividing. But, I can't go any further with the algorithm, don't know where to even start.

.MACRO INITSTACK
LDI         R16,        HIGH(RAMEND)
OUT         SPH,        R16
LDI         R16,        LOW(RAMEND)
OUT         SPL,        R16
.ENDMACRO

.MACRO LOADIO
LDI         R20,        @1
OUT         @0,         R20
.ENDMACRO

.include    "m128def.inc"
.EQU        ones = 0xFF             ; output
.EQU        zeros = 0x00            ; input
.EQU        CRC_CODE = 0x13         ; our CRC polynomial in binary (10011)
.DEF        INPUTREG = R16          ; input register
.DEF        CRC_RES = R17           ; Holds the CRC result (4 bits)
.DEF        OPREG1 = R18            ; temp operation register 1
.DEF        OPREG2 = R19            ; temp operation register 2
.DEF        OPREG3 = R20            ; temp operation register 3
.DEF        OPREG4 = R21            ; temp operation register 4
.DEF        OPREG5 = R22            ; temp operation register 5
.ORG        0x0000

main:

INITSTACK

; Modifies the INPUTREG
RCALL       TakeInput
RCALL       CreateCRC

LOADIO      DDRA,           ones
LOADIO      DDRB,           ones
OUT         PORTA,          CRC_RES

Stop:
NOP
JMP         Stop


TakeInput:
    LOADIO      DDRA,       zeros
    IN          INPUTREG,   PORTA
    CLR         XH
    MOV         XL,         INPUTREG
    LSL         XL          ; do a shift 4 times, for the 4 (5 - 1) zeros
    ROL         XH
    LSL         XL          ; do a shift 4 times, for the 4 (5 - 1) zeros
    ROL         XH
    LSL         XL          ; do a shift 4 times, for the 4 (5 - 1) zeros
    ROL         XH
    LSL         XL          ; do a shift 4 times, for the 4 (5 - 1) zeros
    ROL         XH
    RET

CreateCRC:
    LDI         OPREG1,     0x08        ; do shift 8 times
    LDI         OPREG2,     CRC_CODE    ; load the polynom
    LSL         OPREG2                  ; no need for 5th bit, we only do operation with lower 4 bits (CLC does XOR for the high bit we skipped)
    SWAP        OPREG2                  ; Swap nibbles, so the number has the bits we want at higher 4 bits
    CLZ
crc_loop:
    CLC
    ROL         INPUTREG
    DEC         OPREG1
    BREQ        crc_end                 ; if we did this 8 times, stop
    BRCC        crc_loop                ; no carry, then keep shifting, if its set we go to XOR
crc_do_xor:
    EOR         INPUTREG,   OPREG2
    JMP         crc_loop
crc_end:
    SWAP        INPUTREG                ; Swap the higher 4 bits to lower 4 bits
    MOV         CRC_RES,    INPUTREG
    RET

EDIT: Now I get an incorrect result for the message 1100 1111 with code 10011. Output should be 1100 but I get 1101. Where could it be wrong?

Your code doesn't seem to have anything useful yet. You need to think about how the algorithm works, and decide on a good way to use the bytes you need.

Since your input is only a single byte instead of a stream, I suggest you work with that byte and perform the shift 8 times. I suggest you use ROL, rotate left through carry, and CLC, clear carry bit, as well as an XOR instruction.

The idea is to clear the carry flag, then rotate left one position. If the carry bit is set, then you need to do an XOR instruction with 00110000. This is the polynomial without the first 1, shifted to the left.

1) 11001111 CLC and ROL
2) 10011110 with C=1, so do an XOR
   10101110 CLC and ROL
3) 01011100 with C=1, so do an XOR
   01101100 CLC and ROL
4) 11011000 with C=0, so don't XOR. 
            CLC and ROL
5) 10110000 with C=1, so do an XOR
   01000000 CLC and ROL
6) 10000000 with C=0, so don't XOR.
            CLC and ROL
7) 00000000 with C=1, so do an XOR
   00110000 CLC and ROL
8) 01100000 with C=0, so don't XOR. 
            CLC and ROL
9) 11000000 The first four bits are the result. SWAP to get it to the right.

Write a loop that does this algorithm, testing the C bit for branching. Notice that the high bit of the polynomial doesn't need to be used directly. It is implied, in that you only XOR the lower bits if the carry bit is set. CLC does the "XOR" for the carry bit itself.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM