Przybliżać nie ma co... przestudiowałem całą dokumentację na temat kart sd i zacząłem robić płytkę - 4 piny z szny danych na 4 dolne bity portu, wyżej pin z szyny poleceń/odpowiedzi, sygnał segara i 2 sygnały z gniazda - karta włożona i karta zabezpieczona przed zapisem... 6 sygnałów połączone na dzielniku rezystorowym(4 przewody z danych jak i przewód poleceń/odpowiedzi są dwukierunkowe) z tego powodu, że chciałem uzyskać maksymalną prędkość transmisji - karty SD mogą pracować w trybie 4-bit przy zegarze 25MHz, co teoretycznie daje prędkość wymiany danych na poziomie 12,5MB/s... problem się zaczął, kiedy doszedłem do wniosku, że nie da się wyłączyć mechanizmu sprawdzania sum kontrolnych, a ten jest naprawdę bardzo zmyślny - suma kontrolna jest liczona z generatora x16+x12+x5+1, ale żeby było zabawniej, to nie ze strumienia danych, tylko z poszczególnych bitów każdej linii z osobna - czyli trzeba na raz liczyć 4 sumy kontrolne - na jakimś układzie programowalnym to zrobić pewnie by nie problem, tyle że u siebie miałem tylko możliwość rozwiązania programowego, a poza tym nie znam vhdl'a. Z prostych obliczeń wynikło mi, że liczenie tak skomplikowanej sumy kontrolnej będzie bardziej spowalniać niż pobieranie danych za pomocą jednego pinu - dlatego przeszedłem na komunikację w trybie spi.
Przy pierwszym podejściu napisałem też funkcje do liczenia sum kontrolnych (crc16+crc7) i zoptymalizowałem je do tego stopnia, że nie wymagają tablic LUT ani nie wykorzystują pętli (w obrębie przetwarzania jednego bajtu), a jednocześnie są bardzo szybkie - jak ktoś chce, to tu je zamieszczam (pierwotnie napisane były w delphi - do testów. w takiej formie je zamieszczam):
function crc7(const AData;ALen: integer): Byte;
var vData: array[0..0] of byte absolute AData;
vByte: Integer;
ct: Byte;
begin
result := 0;
for vByte := 0 to ALen-1 do
begin
ct := result xor vData[vByte];
result := (ct shl 4) xor
(ct shl 1) xor
(ct and $F0 ) xor
(ct and $70 shr 3) xor
(ct and $80 shr 6);
end;
// crc w górnych 7 bitach, dolny bit skasowany - ta forma może być dogodna, gdyż w protokole sd/mmc suma crc7 jest przesyłana jako 7 bitów crc i jeden bit końca polecenia (i odpowiedzi - tylko w sd)
result := result shr 1;
end;
function crc16(const AData;ALen: integer): word;
var vData: array[0..0] of byte absolute AData;
vByte: Integer;
vCrcM: Word;
begin
result := 0;
for vByte := 0 to ALen-1 do
begin
vCrcM := (result shr 8) xor vData[vByte];
vCrcM := vCrcM xor (vCrcM shr 4);
result := vCrcM xor (vCrcM shl 5) xor (vCrcM shl 12) xor (result shl 8);
end;
end;
ps. mam też kilka innych funkcji do crc zoptymalizowanych do granic - np odwrócone crc przy generatorze 0x8408 - na procku avr przetworzenie stanu zajmuje 15 cykli i wykorzystuje 4 rejestry - jak by ktoś chciał, to mogę zamieścić wraz z obszernym opisem jak przebiegała optymalizacja