Obliczanie cyklicznych kontroli redundancji
Obliczenie cyklicznej kontroli redundancji wywodzi się z matematyki dzielenia wielomianowego modulo dwa . W praktyce przypomina to długie dzielenie łańcucha komunikatu binarnego , z dołączoną stałą liczbą zer, przez ciąg „wielomianu generatora”, z wyjątkiem tego, że operacje wykluczające lub operacje zastępują odejmowanie. Podział tego typu jest skutecznie realizowany w sprzęcie za pomocą zmodyfikowanego rejestru przesuwnego , aw oprogramowaniu za pomocą szeregu równoważnych algorytmów , zaczynając od prostego kodu zbliżonego do matematyki i stając się szybszym (i prawdopodobnie bardziej zaciemnionym ) poprzez równoległość bajtów i spację- kompromisy czasowe .
Różne standardy CRC rozszerzają algorytm dzielenia wielomianowego, określając początkową wartość rejestru przesuwnego, końcowy krok Exclusive-Or i, co najważniejsze, kolejność bitów ( endianność ). W rezultacie kod widziany w praktyce łudząco odbiega od „czystego” podziału, a rejestr może przesuwać się w lewo lub w prawo.
Przykład
Jako przykład implementacji dzielenia wielomianowego w sprzęcie, załóżmy, że próbujemy obliczyć 8-bitowy CRC 8-bitowej wiadomości złożonej ze znaku ASCII „W”, który jest binarny 01010111 2 , dziesiętny 87 10 lub szesnastkowy 57 16 . użyjemy wielomianu HEC ) Zapisując pierwszy przesłany bit (współczynnik najwyższej potęgi lewej stronie, odpowiada to 9-bitowemu ciągowi „100000111”.
Wartość bajtu 57 16 może być przesyłana w dwóch różnych rzędach, w zależności od zastosowanej konwencji porządkowania bitów. Każdy z nich generuje inny wielomian wiadomości . Najpierw Msbit, to jest = 01010111, podczas gdy lsbit-first , to jest = 11101010. Te mogą następnie pomnożyć przez , aby utworzyć dwa 16-bitowe wielomiany wiadomości .
Obliczenie reszty polega następnie na odjęciu wielokrotności wielomianu generatora sol . Jest to podobne do dzielenia dziesiętnego, ale jeszcze prostsze, ponieważ jedynymi możliwymi wielokrotnościami na każdym kroku są 0 i 1, a odejmowanie pożycza „od nieskończoności” zamiast zmniejszać górne cyfry. Ponieważ nie dbamy o iloraz, nie ma potrzeby go zapisywać.
Najpierw najbardziej znaczący bit | Najpierw najmniej znaczący bit | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
Zauważ, że po każdym odejmowaniu bity są dzielone na trzy grupy: na początku grupa, w której wszystkie są zerowe; na koniec grupa niezmieniona w stosunku do oryginału; i niebieska zacieniona grupa pośrodku, która jest „interesująca”. „Interesująca” grupa ma długość 8 bitów, co odpowiada stopniowi wielomianu. Na każdym kroku odejmuje się odpowiednią wielokrotność wielomianu, aby grupa zerowa była o jeden bit dłuższa, a niezmieniona grupa stawała się o jeden bit krótsza, aż zostanie tylko ostatnia reszta.
W przykładzie msbit-first wielomian reszty to . Konwersja na liczbę szesnastkową przy użyciu konwencji, że najwyższą potęgą x jest msbit; to jest A2 16 . W lsbit-first, reszta to . Konwersja na szesnastkowy przy użyciu konwencji, że najwyższą potęgą x jest lsbit, to jest 19 16 .
Realizacja
Pisanie pełnej wiadomości na każdym kroku, jak w powyższym przykładzie, jest bardzo uciążliwe. Wydajne implementacje wykorzystują rejestr przesuwny przechowywania tylko interesujących bitów. Mnożenie wielomianu przez miejsce, ponieważ współczynniki nie zmieniają wartości, a jedynie przesuwają się w górę do następnego wyrazu wielomianu.
Oto pierwszy szkic pseudokodu do obliczania n -bitowego CRC. Wykorzystuje wymyślony złożony typ danych dla wielomianów, gdzie x
nie jest zmienną całkowitą, ale konstruktorem generującym obiekt wielomianu , który można dodawać, mnożyć i potęgować. Xor to
dodać je, modulo dwa; to znaczy, aby wykluczyć LUB współczynniki każdego pasującego terminu z obu wielomianów.
0 function crc( tablica bitów bitString[1..len], int len) { resztaPolynomial := polynomialForm (bitString[1..n]) // Pierwszych n bitów wiadomości // Popularny wariant uzupełnia tutaj resztaPolynomial; patrz § Preset na −1 poniżej dla i od 1 do len {reszta wielomianu := reszta wielomianu * x + bitString[i+n] * x // Zdefiniuj bitString[k]=0 dla k>len jeśli współczynnik x n reszty wielomianu = 1 {reszta wielomianu := reszta wielomianu xor generatorPolynomial } } // Popularny wariant uzupełnia tutaj resztę wielomianu; zobacz § Post-odwróć poniżej return resztaWielomian }
- Fragment kodu 1: Proste dzielenie wielomianowe
Należy zauważyć, że ten przykładowy kod pozwala uniknąć konieczności określania konwencji porządkowania bitów przez nieużywanie bajtów; wejściowy bitString
jest już w postaci tablicy bitów, a pozostała część Wielomian
jest manipulowana w kategoriach operacji wielomianowych; mnożenie przez prawo, a dodanie [i + n]
jest wykonywane do współczynnika, który może być prawy lub lewy koniec rejestru.
Ten kod ma dwie wady. Po pierwsze, wymaga rejestru n + 1-bitowego do przechowywania pozostałego wielomianu
aby można było przetestować współczynnik. Co ważniejsze, wymaga dopełnienia bitString
n bitami zerowymi.
można rozwiązać, testując współczynnik reszty wielomianu
przed pomnożeniem go przez }
Drugi problem można rozwiązać, wykonując ostatnie n iteracji inaczej, ale istnieje bardziej subtelna optymalizacja, która jest stosowana powszechnie, zarówno w implementacjach sprzętowych, jak i programowych.
Ponieważ operacja XOR używana do odejmowania wielomianu generatora od komunikatu jest przemienna i asocjacyjna , nie ma znaczenia, w jakiej kolejności różne dane wejściowe są łączone w pozostałą część wielomianu
. A dokładniej, danego bitu bitString nie
trzeba dodawać do resztyPolynomial
aż do ostatniej chwili, kiedy jest testowany w celu ustalenia, czy należy xorować
za pomocą generatorPolynomial
.
Eliminuje to również konieczność wstępnego ładowania pozostałego wielomianu
z pierwszymi n bitami wiadomości:
function crc( tablica bitów bitString[1..len], int len) {resztaPolynomial := 0 // Popularny wariant uzupełnia tutaj resztęPolynomial; patrz § Preset na −1 poniżej dla i od 1 do len {reszta Wielomianu := reszta Wielomianu xor (ciąg bitów [i] * x n−1 ) if (współczynnik x n−1 reszty Wielomianu) = 1 { reszta Wielomianu := (reszta Wielomianu * x ) xor generatorPolynomial } else {resztaPolynomial := (remainderPolynomial * x ) } } } // Popularny wariant uzupełnia tutaj resztaPolynomial; patrz § Post-invert poniżej return resztaWielomian }
- Fragment kodu 2: Dzielenie wielomianu z odroczoną wiadomością XOR
Jest to standardowa sprzętowa implementacja CRC typu „bit-at-a-time” i jest warta przestudiowania; kiedy zrozumiesz, dlaczego to oblicza dokładnie taki sam wynik jak pierwsza wersja, pozostałe optymalizacje są dość proste. Jeśli reszta wielomianu
tylko n bitów długości, to współczynniki tego i wielomianu generatora są po
odrzucane To jest powód, dla którego zwykle zobaczysz wielomiany CRC zapisane binarnie z pominięciem wiodącego współczynnika.
W oprogramowaniu wygodnie jest zauważyć, że chociaż można opóźnić xor każdego
bitu do ostatniej chwili, można to również zrobić wcześniej. Zwykle wygodnie jest wykonywać xor
bajt po bajcie, nawet w implementacji typu bit-a-time, takiej jak ta :
function crc( byte array string[1..len], int len) {resztaPolynomial := 0 // Popularny wariant uzupełnia tutaj resztęPolynomial; patrz § Preset to −1 poniżej dla i od 1 do len {reszta wielomianu := reszta wielomianu xor polynomialForm (string[i]) * x n−8 dla j od 1 do 8 { // Zakładając 8 bitów na bajt, jeśli współczynnik x n −1 z reszty Wielomianu = 1 { reszta Wielomianu := (reszta Wielomianu * x ) xor generator Wielomianu } else { reszta Wielomianu := (reszta Wielomianu * x ) } } } // Popularny wariant uzupełnia tutaj resztę Wielomianu; patrz § Post-invert poniżej return resztaWielomian }
- Fragment kodu 3: Dzielenie wielomianowe z komunikatem XORing po bajtach
Jest to zwykle najbardziej kompaktowa implementacja oprogramowania, stosowana w mikrokontrolerach , gdy przestrzeń jest ważniejsza niż prędkość.
Kolejność bitów (endianowość)
Po zaimplementowaniu w sprzęcie szeregowym bitowym wielomian generatora jednoznacznie opisuje przypisanie bitów; pierwszy transmitowany bit jest zawsze współczynnikiem najwyższej potęgi , a ostatnie to reszta CRC , od współczynnik i kończący się współczynnikiem , czyli współczynnikiem 1.
Jednak gdy bity są przetwarzane bajt po bajcie, na przykład podczas transmisji równoległej , ramek bajtów, jak w kodowaniu 8B/10B lub asynchronicznej komunikacji szeregowej w stylu RS-232 , lub podczas implementacji CRC w oprogramowaniu , konieczne jest określenie kolejność bitów (endianowość) danych; który bit w każdym bajcie jest uważany za „pierwszy” i będzie współczynnikiem wyższej potęgi .
Jeśli dane są przeznaczone do komunikacji szeregowej , najlepiej jest użyć kolejności bitów, w której dane zostaną ostatecznie wysłane. Dzieje się tak, ponieważ zdolność CRC do wykrywania błędów serii jest oparta na bliskości wielomianu wiadomości ; jeśli sąsiednie wyrażenia wielomianowe nie są przesyłane sekwencyjnie, seria błędów fizycznych o jednej długości może być postrzegana jako seria dłuższa z powodu przegrupowania bitów.
Na przykład zarówno standardy IEEE 802 (ethernet), jak i RS - 232 ( port szeregowy ) określają transmisję z najmniej znaczącym bitem (little-endian), więc programowa implementacja CRC do ochrony danych przesyłanych przez takie łącze powinna mapować najmniej znaczące bity w każdym bajcie do współczynników o najwyższych potęgach . Z drugiej strony dyskietki i większość dysków twardych najpierw zapisuje najbardziej znaczący bit każdego bajtu.
CRC lsbit-first jest nieco prostszy do zaimplementowania w oprogramowaniu, więc jest nieco częściej spotykany, ale wielu programistów uważa, że kolejność msbit-first bit jest łatwiejsza do naśladowania. Tak więc, na przykład, XMODEM -CRC, wczesne użycie CRC w oprogramowaniu, wykorzystuje msbit-first CRC.
opisując przesunięcia w pseudokodzie jako mnożenia przez zapisując wyraźne konwersje z postaci binarnej na wielomianową. W praktyce CRC jest przechowywany w standardowym rejestrze binarnym przy użyciu określonej konwencji porządkowania bitów. W postaci pierwszego bitu najbardziej znaczące bity binarne będą wysyłane jako pierwsze i zawierają współczynniki wielomianu wyższego rzędu, podczas gdy w postaci pierwszego bitu najmniej znaczące bity binarne zawierają współczynniki wyższego rzędu. Powyższy pseudokod można zapisać w obu formach. Dla konkretności wykorzystuje to 16-bitowy wielomian CRC-16- CCITT : }
// Najpierw najbardziej znaczący bit (big-endian) // x^16+x^12+x^5+1 = (1) 0001 0000 0010 0001 = 0x1021 function crc( byte array string[1..len], int len) { rem := 0 // Popularny wariant uzupełnia rem tutaj dla i od 1 do len { rem := rem xor (string[i] leftShift (n-8)) // n = 16 w tym przykładzie dla j od 1 do 8 { // Zakładając 8 bitów na bajt , jeśli rem i 0x8000 { // jeśli ustawiony jest najbardziej lewy (najbardziej znaczący) bit rem := (rem leftShift 1) xor 0x1021 } else { rem := rem leftShift 1 } rem := rem i 0xffff // Przytnij resztę do 16 bitów } } // Popularny wariant uzupełnia tutaj rem return rem }
- Fragment kodu 4: Dzielenie oparte na rejestrze przesuwnym, najpierw MSB
// Najpierw najmniej znaczący bit (little-endian) // x^16 +x^12+x^5+1 = 1000 0100 0000 1000 (1) = 0x8408 function crc( byte array string[1..len], int len) { rem := 0 // Popularny wariant uzupełnia rem tutaj dla i od 1 do len { rem := rem xor string[i] for j od 1 do 8 { // Zakładając 8 bitów na bajt , jeśli rem i 0x0001 { // jeśli ustawiony jest prawy (najbardziej znaczący) bit rem := (rem rightShift 1) xor 0x8408 } else { rem := rem rightShift 1 } } } // Popularny wariant uzupełnia rem tutaj return rem }
- Fragment kodu 5: Dzielenie oparte na rejestrze przesuwnym, najpierw LSB
Zauważ, że forma lsbit-first pozwala uniknąć konieczności przesuwania string[i]
przed xor
. W obu przypadkach pamiętaj o przesyłaniu bajtów CRC w kolejności zgodnej z wybraną konwencją porządkowania bitów.
Obliczenia wielobitowe
Algorytm Sarwate (pojedyncza tabela przeglądowa)
Inna powszechna optymalizacja wykorzystuje tablicę przeglądową indeksowaną przez współczynniki rem najwyższego rzędu
do przetwarzania więcej niż jednego bitu dywidendy na iterację. Najczęściej używana jest tablica przeglądowa zawierająca 256 wpisów, zastępując treść zewnętrznej pętli (nad i
) przez:
// Msbit-first rem = (rem leftShift 8) xor big_endian_table[string[i] xor ((ostatnie lewe 8 bitów rem) rightShift (n-8))] // Lsbit-first rem = (rem rightShift 8) xor little_endian_table [string[i] xor (8 najbardziej wysuniętych na prawo bitów rem)]
- Fragment kodu 6: Rdzenie podziału opartego na tabelach
Jeden z najczęściej spotykanych algorytmów CRC jest znany jako CRC-32 , używany (między innymi) przez Ethernet , FDDI , ZIP i inne formaty archiwów oraz format obrazów PNG . Jego wielomian można zapisać najpierw msbit jako 0x04C11DB7 lub najpierw lsbit jako 0xEDB88320. Strona internetowa W3C w PNG zawiera dodatek z krótką i prostą implementacją opartą na tabelach w C CRC-32. Zauważysz, że kod odpowiada przedstawionemu tutaj pseudokodowi lsbit-first bajt-a-czasu, a tabela jest generowana przy użyciu kodu bit-at-a-time.
Zwykle najwygodniejszy jest stół z 256 wpisami, ale można użyć innych rozmiarów. W małych mikrokontrolerach użycie 16-wejściowej tablicy do przetwarzania czterech bitów jednocześnie daje użyteczną poprawę szybkości przy jednoczesnym zachowaniu niewielkich rozmiarów tablicy. Na komputerach z dużą ilością pamięci 65 536 wpisów może służyć do jednoczesnego przetwarzania 16 bitów.
Generowanie tabel
Oprogramowanie do generowania tabel jest tak małe i szybkie, że zwykle szybciej jest je obliczyć podczas uruchamiania programu niż ładować wstępnie obliczone tabele z pamięci. Jedną z popularnych technik jest użycie kodu bit-at-a-time 256 razy w celu wygenerowania CRC z 256 możliwych 8-bitowych bajtów. Można to jednak znacznie zoptymalizować, korzystając z właściwości table[i xor j] == table[i] xor table[j]
. Tylko wpisy w tabeli odpowiadające potęgom dwójki muszą być obliczane bezpośrednio.
W poniższym przykładowym kodzie crc
przechowuje wartość table[i]
:
0 big_endian_table[0] := 0 crc := 0x8000 // Zakładając 16-bitowy wielomian i := 1 do { if crc i 0x8000 { crc := (crc leftShift 1) xor 0x1021 // Wielomian CRC } else { crc : = crc leftShift 1 } // crc jest wartością big_endian_table[i] ; niech j iteruje po już zainicjowanych wpisach dla j od do i−1 { big_endian_table[i + j] := crc xor big_endian_table[j]; } i := i przesunięcie w lewo 1 } while i < 256
- Fragment kodu 7: Generowanie tablicy CRC bajt-po-czasie, najpierw MSB
0 little_endian_table[0] := 0 crc := 1; i := 128 do { if crc i 1 { crc := (crc rightShift 1) xor 0x8408 // Wielomian CRC } else { crc := crc rightShift 1 } // crc jest wartością little_endian_table[i] ; niech j iteruje po już zainicjowanych wpisach dla j od do 255 przez 2 × i { little_endian_table[i + j] := crc xor little_endian_table[j]; } i := i przesunięcie w prawo 1 } while i > 0
- Fragment kodu 8: Generowanie tablicy CRC bajt-po-czasie, najpierw LSB
W tych przykładach kodu indeks tabeli i + j
jest równoważny z i xor j
; możesz użyć dowolnej formy, która jest dla Ciebie wygodniejsza.
Podział bajtów przy użyciu wielu tabel
Istnieje algorytm krojenia po N (zwykle krojenie po 8 dla CRC32; N ≤ 64), który zwykle podwaja lub potraja wydajność w porównaniu z algorytmem Sarwate. Zamiast odczytywać 8 bitów na raz, algorytm odczytuje 8N bitów na raz. W ten sposób maksymalizuje się wydajność superskalarnych .
Nie jest jasne, kto faktycznie wynalazł algorytm.
Obliczenia równoległe bez tabeli
Aktualizacja równoległa dla bajtu lub słowa na raz może być również wykonana jawnie, bez tabeli. Jest to zwykle używane w szybkich implementacjach sprzętowych. Dla każdego bitu rozwiązywane jest równanie po przesunięciu 8 bitów. Poniższe tabele zawierają równania dla niektórych powszechnie używanych wielomianów, używając następujących symboli:
c ja | Bit CRC 7…0 (lub 15…0) przed aktualizacją |
r ja | Bit CRC 7…0 (lub 15…0) po aktualizacji |
d ja | bit danych wejściowych 7…0 |
mi ja = re ja + do ja | 0 e p = e 7 + e 6 + … + e 1 + e (bit parzystości) |
s ja = re ja + do ja + 8 | 0 s p = s 7 + s 6 + … + s 1 + s (bit parzystości) |
Wielomian: | ( x 7 + x 3 + 1) × x (przesunięty w lewo CRC-7-CCITT) | x 8 + x 5 + x 4 + 1 (CRC-8-Dallas/Maxim) |
---|---|---|
Współczynniki: | 0x12 = (0x09 << 1) ( MSBF /normalny) | 0x8c ( LSBF /rewers) |
0 r ← r 1 ← r 2 ← r 3 ← r 4 ← r 5 ← r 6 ← r 7 ← |
0 0 0 mi + mi 4 + mi 7 mi 1 + mi 5 mi 2 + mi 6 mi 3 + mi 7 + mi + mi 4 + mi 7 mi 4 + mi 1 + mi 5 mi 5 + mi 2 + mi 6 mi 6 + mi 3 + mi 7 |
0 0 0 00 00 mi + mi 4 + mi 1 + mi + mi 5 + mi 2 + mi 1 mi 1 + mi 5 + mi 2 + mi 1 + mi 6 + mi 3 + mi 2 + mi mi 2 + mi 6 + mi 3 + mi 2 + mi + mi 7 + mi 4 + mi 3 + mi 1 mi 3 + mi + mi 7 + mi 4 + mi 3 + mi 1 mi 4 + mi 1 + mi mi 5 + mi 2 + mi 1 mi 6 + mi 3 + mi 2 + mi mi 7 + mi 4 + mi 3 + mi 1 |
Fragmenty kodu C : |
uint8_t c , re , mi , fa , r ; … mi = do ^ re ; fa = mi ^ ( mi >> 4 ) ^ ( mi >> 7 ); r = ( fa << 1 ) ^ ( fa << 4 );
|
uint8_t c , re , mi , fa , r ; … mi = do ^ re ; fa = mi ^ ( mi << 3 ) ^ ( mi << 4 ) ^ ( mi << 6 ); r = fa ^ ( fa >> 4 ) ^ ( fa >> 5 );
|
Wielomian: | x 16 + x 12 + x 5 + 1 (CRC-16-CCITT) | x 16 + x 15 + x 2 + 1 (CRC-16-ANSI) | ||
---|---|---|---|---|
Współczynniki: | 0x1021 (MSBF/normalny) | 0x8408 (LSBF/wsteczny) | 0x8005 (MSBF/normalny) | 0xa001 (LSBF/wsteczny) |
0 r ← r 1 ← r 2 ← r 3 ← r 4 ← r 5 ← r 6 ← r 7 ← r 8 ← r 9 ← r 10 ← r 11 ← r 12 ← r 13 ← r 14 ← r 15 ← |
0 0 0 0 s 4 + s s 5 + s 1 s 6 + s 2 s 7 + s 3 s 4 s 5 + s 4 + s s 6 + s 5 + s 1 s 7 + s 6 + s 2 do + s 7 + s 3 do 1 + s 4 do 2 + s 5 do 3 + s 6 do 4 + s 7 + s 4 + s do 5 + s 5 + s 1 do 6 + s 6 + s 2 do 7 + s 7 + s 3 |
0 0 0 0 0 do 8 + mi 4 + mi do 9 + mi 5 + mi 1 do 10 + mi 6 + mi 2 do 11 + mi + mi 7 + mi 3 do 12 + mi 1 do 13 + mi 2 do 14 + mi 3 do 15 + mi 4 + mi mi + mi 5 + mi 1 mi 1 + mi 6 + mi 2 mi 2 + mi 7 + mi 3 mi 3 mi 4 + mi mi 5 + mi 1 mi 6 + mi 2 mi 7 + mi 3 |
0 0 0 s p s + s p s 1 + s s 2 + s 1 s 3 + s 2 s 4 + s 3 s 5 + s 4 s 6 + s 5 do + s 7 + s 6 do 1 + s 7 do 2 do 3 do 4 do 5 do 6 do 7 + s str |
00 do 8 + e p do 9 do 10 do 11 do 12 do 13 do 14 + mi do 15 + mi 1 + mi mi 2 + mi 1 mi 3 + mi 2 mi 4 + mi 3 mi 5 + mi 4 mi 6 + mi 5 mi 7 + mi 6 mi p + mi 7 mi s |
Fragmenty kodu C : |
uint8_t re , s , t ; uint16_t c , r ; … s = re ^ ( do >> 8 ); t = s ^ ( s >> 4 ); r = ( do << 8 ) ^ t ^ ( t << 5 ) ^ ( t << 12 );
|
uint8_t d , e , f ; uint16_t c , r ; … mi = do ^ re ; fa = mi ^ ( mi << 4 ); r = ( do >> 8 ) ^ ( fa << 8 ) ^ ( fa << 3 ) ^ ( fa >> 4 );
|
uint8_t re , s , p ; uint16_t c , r , t ; … s = re ^ ( do >> 8 ); p = s ^ ( s >> 4 ); p = p ^ ( p >> 2 ); p = p ^ ( p >> 1 ); p = p & 1 ; t = p | ( s << 1 ); r = ( do << 8 ) ^ ( t << 15 ) ^ t ^ ( t << 1 );
|
uint8_t d , e , p ; uint16_t c , r , f ; … mi = do ^ re ; p = mi ^ ( mi >> 4 ); p = p ^ ( p >> 2 ); p = p ^ ( p >> 1 ); p = p & 1 ; fa = mi | ( p << 8 ); r = ( do >> 8 ) ^ ( fa << 6 ) ^ ( fa << 7 ) ^ ( fa >> 8 );
|
Obliczenia dwuetapowe
Ponieważ wielomian CRC-32 ma dużą liczbę składników, podczas obliczania reszty po bajcie na raz każdy bit zależy od kilku bitów poprzedniej iteracji. W sprzętowych implementacjach bajtowo-równoległych wymaga to bramek XOR z wieloma wejściami lub kaskadowych, co zwiększa opóźnienie propagacji .
Aby zmaksymalizować szybkość obliczeń, resztę pośrednią można obliczyć, przepuszczając wiadomość przez 123-bitowy rejestr przesuwny. Wielomian jest starannie dobraną wielokrotnością standardowego wielomianu, tak że terminy (odbiory sprzężenia zwrotnego) są szeroko rozstawione, a żaden bit pozostałej części nie jest poddawany operacji XOR więcej niż raz na iterację bajtu. Potrzebne są więc tylko dwuwejściowe bramki XOR, możliwie najszybsze. Ostatecznie reszta pośrednia jest dzielona przez standardowy wielomian w drugim rejestrze przesuwnym, aby uzyskać resztę CRC-32.
Obliczenia blokowe
Blokowe obliczenie reszty można wykonać sprzętowo dla dowolnego wielomianu CRC, rozkładając na czynniki macierz transformacji przestrzeni stanów potrzebną do obliczenia reszty na dwie prostsze macierze Toeplitza.
Jednoprzebiegowa kontrola
Podczas dołączania CRC do wiadomości, możliwe jest odłączenie przesyłanego CRC, ponowne obliczenie i zweryfikowanie przeliczonej wartości z przesłaną. Jednak prostsza technika jest powszechnie stosowana w sprzęcie.
Kiedy CRC jest przesyłane z prawidłową kolejnością bajtów (zgodną z wybraną konwencją porządkowania bitów), odbiornik może obliczyć całkowitą CRC na podstawie wiadomości i CRC, a jeśli są poprawne, wynik będzie równy zero. Ta możliwość jest powodem, dla którego większość protokołów sieciowych zawierających CRC robi to przed końcowym ogranicznikiem; nie trzeba wiedzieć, czy zbliża się koniec pakietu, aby sprawdzić CRC.
warianty CRC
W praktyce większość standardów określa ustawienie rejestru na wszystkie jedynki i odwrócenie CRC przed transmisją. Nie ma to wpływu na zdolność CRC do wykrywania zmienionych bitów, ale daje mu możliwość zauważenia bitów dodanych do wiadomości.
Wstępnie ustawione na −1
Podstawowa matematyka CRC akceptuje (uważa za poprawnie przesłane) komunikaty, które interpretowane jako wielomian są wielokrotnością wielomianu CRC. Jeśli do takiego komunikatu dołączy się kilka początkowych bitów 0, nie zmienią one jego interpretacji jako wielomianu. Jest to równoważne z faktem, że 0001 i 1 to ta sama liczba.
Ale jeśli przesyłanej wiadomości zależy na początkowych bitach 0, niezdolność podstawowego algorytmu CRC do wykrycia takiej zmiany jest niepożądana. Jeśli jest możliwe, że błąd transmisji mógłby dodać takie bity, prostym rozwiązaniem jest rozpoczęcie od rejestru rem
ustawionego na jakąś niezerową wartość; dla wygody zwykle używana jest wartość all-one. Jest to matematycznie równoważne z uzupełnieniem (binarnym NOT) pierwszych n bitów wiadomości, gdzie n jest liczbą bitów w rejestrze CRC.
Nie wpływa to w żaden sposób na generowanie i sprawdzanie CRC, o ile zarówno generator, jak i kontroler używają tej samej wartości początkowej. Dowolna niezerowa wartość początkowa wystarczy, a kilka standardów określa nietypowe wartości, ale wartość zerowa (-1 w systemie binarnym dopełnienia do dwóch) jest zdecydowanie najczęstsza. Należy zauważyć, że jednoprzebiegowe generowanie/sprawdzanie CRC nadal będzie dawać wynik zerowy, gdy komunikat jest poprawny, niezależnie od ustawionej wartości.
Po odwróceniu
Ten sam rodzaj błędu może wystąpić na końcu komunikatu, aczkolwiek w przypadku bardziej ograniczonego zestawu komunikatów. Dodanie 0 bitów do wiadomości jest równoważne pomnożeniu jej wielomianu przez x , a jeśli wcześniej był to wielokrotność wielomianu CRC, wynik tego mnożenia również będzie taki sam. Jest to równoważne z faktem, że ponieważ 726 jest wielokrotnością 11, więc jest 7260.
Podobne rozwiązanie można zastosować na końcu komunikatu, odwracając rejestr CRC przed jego dołączeniem do komunikatu. Ponownie wystarczy każda niezerowa zmiana; odwrócenie wszystkich bitów (XORing ze wzorcem all-one) jest po prostu najczęstsze.
Ma to wpływ na jednoprzebiegowe sprawdzanie CRC: zamiast generowania wyniku zerowego, gdy komunikat jest poprawny, daje stały wynik niezerowy. (Ściślej mówiąc, wynikiem jest CRC (bez niezerowego ustawienia wstępnego, ale z post-odwróceniem) wzorca inwersji). dowolny komunikat), można go użyć bezpośrednio do weryfikacji poprawności dowolnego innego komunikatu sprawdzanego przy użyciu tego samego algorytmu CRC.
Zobacz też
Kategoria ogólna
- Kod poprawiający błąd
- Lista funkcji skrótu
- Parzystość odpowiada 1-bitowemu CRC z wielomianem x +1 .
Sumy kontrolne inne niż CRC
- ^ Dubrowa, Elena; Mansouri, Shohreh Sharif (maj 2012). „Podejście oparte na BDD do konstruowania LFSR do równoległego kodowania CRC” . Proceedings of IEEE International Symposium on Multiple-Valued Logic : 128–133. doi : 10.1109/ISMVL.2012.20 . ISBN 978-0-7695-4673-5 . S2CID 27306826 .
- ^ a b Williams, Ross N. (24.09.1996). „Bezbolesny przewodnik po algorytmach wykrywania błędów CRC, wersja 3.00” . Zarchiwizowane od oryginału w dniu 2006-09-27 . Źródło 2016-02-16 .
- ^ Sarwate, Dilip V. (sierpień 1998). „Obliczanie cyklicznych kontroli redundancji za pomocą wyszukiwania w tabeli” . Komunikaty ACM . 31 (8): 1008–1013. doi : 10.1145/63030.63037 . S2CID 5363350 .
- ^ „Specyfikacja przenośnej grafiki sieciowej (PNG) (wydanie drugie): załącznik D, przykładowa implementacja kodu cyklicznej nadmiarowości” . W3C . 2003-11-10 . Źródło 2016-02-16 .
- ^ Kounavis, Michael E.; Berry, Frank L. (27–30 czerwca 2005). Systematyczne podejście do budowania wysokowydajnych, opartych na oprogramowaniu generatorów CRC (PDF) . Sympozjum IEEE 2013 na temat komputerów i komunikacji (ISCC). Cartagena, Murcja, Hiszpania. s. 855–862. doi : 10.1109/ISCC.2005.18 . ISBN 0-7695-2373-0 .
- Bibliografia _ Kounavis, Michael E. (listopad 2008). „Nowe algorytmy oparte na wyszukiwaniu w tabeli do wysokowydajnego generowania CRC” . Transakcje IEEE na komputerach . 57 (11): 1550-1560. doi : 10.1109/TC.2008.85 . S2CID 206624854 .
- ^ Generowanie CRC o wysokiej liczbie oktanowej z algorytmem Intel Slicing-by-8 (PDF) (raport techniczny). Intel . Zarchiwizowane od oryginału (PDF) w dniu 22.07.2012.
- ^ „Krótki samouczek dotyczący obliczania CRC” . Archiwa jądra Linuksa .
- ^ Menon-Sen, Abhijit (20.01.2017). „Kto wynalazł algorytm slicing-by-N CRC32?” .
- ^ Jon Buller (15.03.1996). „Re: 8051 i CRC-CCITT” . Grupa dyskusyjna : comp.arch.embedded . Usenet: [email protected] . Źródło 2016-02-16 .
- ^ Glaise, René J. (1997-01-20). „Dwuetapowe obliczenie kodu cyklicznej redundancji CRC-32 dla sieci ATM” . IBM Journal of Research and Development . Armonk, Nowy Jork : IBM . 41 (6): 705. doi : 10.1147/rd.416.0705 . Zarchiwizowane od oryginału w dniu 2009-01-30 . Źródło 2016-02-16 .
- ^ Das, Arindam (2022). „Obliczanie blokowe kodu cyklicznej redundancji przy użyciu faktoryzowanych macierzy Toeplitza zamiast tabeli przeglądowej” . Transakcje IEEE na komputerach : 1–12. doi : 10.1109/TC.2022.3189574 . ISSN 0018-9340 . S2CID 250472783 .
-
^ Np
. karta katalogowa (PDF) , Texas Instruments , listopad 2009, s. 39 , dostęp 2016-02-16 ,
Generator CRC jest inicjowany wartością 0x3791, jak pokazano na rysunku 50.
RFID TMS37157 o niskiej częstotliwości - pasywne urządzenie interfejsu niskiej częstotliwości z pamięcią EEPROM i interfejsem transpondera 134,2 kHz
Linki zewnętrzne
- Jan Paweł Adamowski. „64-bitowy cykliczny nadmiarowy kod - długie dzielenie XOR na bajtowe wyszukiwanie w tabeli” .
- Andrew Kadarcha, Boba Jenkinsa. „Wydajna (~ 1 cykl procesora na bajt) implementacja CRC” . GitHub .