Сборка AVR ATMEGA128: алгоритм CRC

Я должен сделать простую проверку CRC для следующего: взять 8-битный вход из порта, получить его значение контрольной суммы CRC и вывести его. Пока что я могу взять ввод и прочитать алгоритм, поэтому я добавляю n - 1 ноль к своему вводу, фактически делая его достаточно большим, чтобы быть 16-битным. У меня это тоже работает, и я знаю, что здесь мне понадобится XOR, так как мы делаем по модулю 2 во время деления. Но я не могу идти дальше с алгоритмом, не знаю, с чего начать.

.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

РЕДАКТИРОВАТЬ: Теперь я получаю неправильный результат для сообщения 1100 1111 с кодом 10011. Вывод должен быть 1100, но я получаю 1101. Где это может быть неправильно?

1 ответ

Решение

В вашем коде пока что нет ничего полезного. Вам нужно подумать о том, как работает алгоритм, и выбрать хороший способ использования нужных вам байтов.

Поскольку ваш ввод - это только один байт вместо потока, я предлагаю вам поработать с этим байтом и выполнить сдвиг 8 раз. Я предлагаю вам использовать ROL, повернуть влево при переносе и CLC, сбросить бит переноса, а также инструкцию XOR.

Идея состоит в том, чтобы очистить флаг переноса, затем повернуть влево на одну позицию. Если бит переноса установлен, вам нужно выполнить инструкцию XOR с 00110000. Это полином без первой 1, смещенной влево.

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.

Напишите цикл, который выполняет этот алгоритм, проверяя бит C на ветвление. Обратите внимание, что старший бит многочлена не должен использоваться напрямую. Подразумевается, что вы устанавливаете только младшие биты XOR, если бит переноса установлен. CLC выполняет "XOR" для самого бита переноса.

Другие вопросы по тегам