§ Использование

Для того, чтобы использовать код, необходимо объявить переменные:
1uint8_t     spi_data, spi_st = 2, spi_status, spi_command, spi_crc, spi_resp;
2uint32_t    spi_arg, spi_lba;
3int         spi_phase;
4uint8_t     spi_sector[512];
5FILE*       spi_file;
А потом где-нибудь начертать код, который указан будет ниже.
Вызывая команду sdspi, происходит эмуляция отсылки 8 бит и приема 8 бит в тот же момент.
1unsigned char sdspi(unsigned char data) {
2
3    switch (spi_status) {
4
5        // IDLE
6        case 0:
7
8            // Чтение в 0-м дает последний ответ от команды
9            if (data == 0xFF) {
10
11                spi_data = spi_resp;
12                spi_resp = 0xFF;
13            }
14            // Запуск приема команды
15            else if ((data & 0xC0) == 0x40) {
16
17                spi_status  = 1;
18                spi_command = data & 0x3F;
19                spi_arg     = 0;
20                spi_phase   = 0;
21            }
22
23            break;
24
25        // COMMAND (прием)
26        case 1: {
27
28            if (spi_phase < 4) {
29
30                spi_arg = (spi_arg << 8) | data;
31                spi_phase++;
32
33            } else {
34
35                spi_phase = 0;
36                spi_crc   = data;
37
38                /* Ответ зависит от команды */
39                switch (spi_command) {
40
41                    /* CMDxx */
42                    case 0:  spi_status = 0; spi_resp = 0x01; break;
43                    case 8:  spi_status = 2; spi_resp = 0x00; break;
44                    case 13: spi_status = 6; spi_resp = 0x00; break;    // STATUS
45                    case 17: spi_status = 4; spi_lba  = spi_arg; break; // BLOCK SEARCH READ
46                    case 24: spi_status = 5; spi_lba  = spi_arg; break; // BLOCK SEARCH WRITE
47                    case 41: spi_status = 0; spi_resp = 0x00; break;    // READY=0
48                    case 55: spi_status = 0; spi_resp = 0x01; break;    // ACMD=1
49                    case 58: spi_status = 3; spi_resp = 0x00; break;    // CHECK=0
50                    default: spi_status = 0; spi_resp = 0xFF; break;    // Unknown
51                }
52            }
53
54            break;
55        }
56
57        // OCR Read (5 bytes)
58        case 2: {
59
60            if (data == 0xFF) {
61
62                if (spi_phase == 4) {
63                    spi_data = 0xAA;
64                    spi_status = 0;
65                } else {
66                    spi_data = 0x00;
67                }
68
69                spi_phase++;
70            }
71            else {
72                printf("SPI Illegal Write #1"); exit(1);
73            }
74
75            break;
76        }
77
78        // Информация о SDHC поддержке
79        case 3: {
80
81            if (data == 0xFF) {
82
83                if (spi_phase == 0) {
84                    spi_data = 0x00;
85                } else if (spi_phase == 1) {
86                    spi_data = 0xC0;
87                } else if (spi_phase < 4) {
88                    spi_data = 0xFF;
89                } else {
90                    spi_data = 0xFF;
91                    spi_status = 0;
92                }
93
94                spi_phase++;
95
96            } else {
97                printf("SPI Illegal Write #2"); exit(1);
98            }
99
100            break;
101        }
102
103        // Чтение с диска
104        case 4: {
105
106            if (spi_phase == 0) {
107
108                spi_data = 0x00;
109                spi_file = fopen("sd.img", "ab+");
110                if (spi_file == NULL) { printf("Error open file\n"); exit(0); }
111                fseek(spi_file, 512 * spi_lba, SEEK_SET);
112                (void) fread(spi_sector, 1, 512, spi_file);
113                fclose(spi_file);
114
115            } else if (spi_phase == 1) {
116                spi_data = 0xFE;
117            } else if (spi_phase < 514) {
118                spi_data = spi_sector[spi_phase - 2];
119            }
120
121            spi_phase++;
122            if (spi_phase == 514) {
123
124                spi_status = 0;
125                spi_resp   = 0xFF;
126            }
127
128            break;
129        }
130
131        // Запись на диск
132        case 5: {
133
134            if (spi_phase == 0) {
135                spi_data = 0x00; // ACK
136
137            } else if (spi_phase == 1) {
138
139                if (data != 0xFE) {
140                    printf("Illegal opcode (non FE)\n"); exit(1);
141                }
142
143            } else if (spi_phase < 514) {
144                spi_sector[spi_phase - 2] = data;
145
146            } else if (spi_phase == 516) {
147                spi_data = 0x05; // ACK
148
149            } else if (spi_phase < 520) {
150                spi_data = 0xFF;
151            }
152
153            spi_phase++;
154
155            // Окончание программирования
156            if (spi_phase == 520) {
157
158                spi_status = 0;
159                spi_resp   = 0x00;
160
161                // Запись новых данных на диск
162                spi_file = fopen("sd.img", "r+b");
163                if (spi_file == NULL) { printf("Error open file\n"); exit(0); }
164                fseek(spi_file, 512 * spi_lba, SEEK_SET);
165                (void) fwrite(spi_sector, 1, 512, spi_file);
166                fclose(spi_file);
167            }
168
169            break;
170        }
171
172        // STATUS [2 Byte 00 00]
173        case 6: {
174
175            if (data == 0xFF) {
176
177                if (spi_phase == 1)
178                    spi_status = 0;
179
180                spi_data = 0x00;
181                spi_phase++;
182            }
183            else {
184                printf("SPI Illegal Write #1"); exit(1);
185            }
186        }
187    }
188
189    return spi_data;
190}