§ Использование
Для того, чтобы использовать код, необходимо объявить переменные: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}