Сборка 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" для самого бита переноса.