§ Использование
Для того, чтобы использовать код, необходимо объявить переменные:uint8_t spi_data, spi_st = 2, spi_status, spi_command, spi_crc, spi_resp; uint32_t spi_arg, spi_lba; int spi_phase; uint8_t spi_sector[512]; FILE* spi_file;А потом где-нибудь начертать код, который указан будет ниже.
Вызывая команду sdspi, происходит эмуляция отсылки 8 бит и приема 8 бит в тот же момент.
unsigned char sdspi(unsigned char data) { switch (spi_status) { // IDLE case 0: // Чтение в 0-м дает последний ответ от команды if (data == 0xFF) { spi_data = spi_resp; spi_resp = 0xFF; } // Запуск приема команды else if ((data & 0xC0) == 0x40) { spi_status = 1; spi_command = data & 0x3F; spi_arg = 0; spi_phase = 0; } break; // COMMAND (прием) case 1: { if (spi_phase < 4) { spi_arg = (spi_arg << 8) | data; spi_phase++; } else { spi_phase = 0; spi_crc = data; /* Ответ зависит от команды */ switch (spi_command) { /* CMDxx */ case 0: spi_status = 0; spi_resp = 0x01; break; case 8: spi_status = 2; spi_resp = 0x00; break; case 13: spi_status = 6; spi_resp = 0x00; break; // STATUS case 17: spi_status = 4; spi_lba = spi_arg; break; // BLOCK SEARCH READ case 24: spi_status = 5; spi_lba = spi_arg; break; // BLOCK SEARCH WRITE case 41: spi_status = 0; spi_resp = 0x00; break; // READY=0 case 55: spi_status = 0; spi_resp = 0x01; break; // ACMD=1 case 58: spi_status = 3; spi_resp = 0x00; break; // CHECK=0 default: spi_status = 0; spi_resp = 0xFF; break; // Unknown } } break; } // OCR Read (5 bytes) case 2: { if (data == 0xFF) { if (spi_phase == 4) { spi_data = 0xAA; spi_status = 0; } else { spi_data = 0x00; } spi_phase++; } else { printf("SPI Illegal Write #1"); exit(1); } break; } // Информация о SDHC поддержке case 3: { if (data == 0xFF) { if (spi_phase == 0) { spi_data = 0x00; } else if (spi_phase == 1) { spi_data = 0xC0; } else if (spi_phase < 4) { spi_data = 0xFF; } else { spi_data = 0xFF; spi_status = 0; } spi_phase++; } else { printf("SPI Illegal Write #2"); exit(1); } break; } // Чтение с диска case 4: { if (spi_phase == 0) { spi_data = 0x00; spi_file = fopen("sd.img", "ab+"); if (spi_file == NULL) { printf("Error open file\n"); exit(0); } fseek(spi_file, 512 * spi_lba, SEEK_SET); (void) fread(spi_sector, 1, 512, spi_file); fclose(spi_file); } else if (spi_phase == 1) { spi_data = 0xFE; } else if (spi_phase < 514) { spi_data = spi_sector[spi_phase - 2]; } spi_phase++; if (spi_phase == 514) { spi_status = 0; spi_resp = 0xFF; } break; } // Запись на диск case 5: { if (spi_phase == 0) { spi_data = 0x00; // ACK } else if (spi_phase == 1) { if (data != 0xFE) { printf("Illegal opcode (non FE)\n"); exit(1); } } else if (spi_phase < 514) { spi_sector[spi_phase - 2] = data; } else if (spi_phase == 516) { spi_data = 0x05; // ACK } else if (spi_phase < 520) { spi_data = 0xFF; } spi_phase++; // Окончание программирования if (spi_phase == 520) { spi_status = 0; spi_resp = 0x00; // Запись новых данных на диск spi_file = fopen("sd.img", "r+b"); if (spi_file == NULL) { printf("Error open file\n"); exit(0); } fseek(spi_file, 512 * spi_lba, SEEK_SET); (void) fwrite(spi_sector, 1, 512, spi_file); fclose(spi_file); } break; } // STATUS [2 Byte 00 00] case 6: { if (data == 0xFF) { if (spi_phase == 1) spi_status = 0; spi_data = 0x00; spi_phase++; } else { printf("SPI Illegal Write #1"); exit(1); } } } return spi_data; }