Created
December 3, 2025 07:09
-
-
Save sylefeb/3d5e31bda879c09da24fbc33cbf21ce5 to your computer and use it in GitHub Desktop.
Patched sdcard code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| SL - 2020-01-24 | |
| SDCARD bit-banging from RV32I CPU | |
| (revised for Ice-V from Fire-V implementation) | |
| Useful Links | |
| http://www.rjhcoding.com/avrc-sd-interface-1.php | |
| http://www.dejazzer.com/ee379/lecture_notes/lec12_sd_card.pdf | |
| http://chlazza.nfshost.com/sdcardinfo.html | |
| // https://github.com/sylefeb/Silice | |
| // MIT license, see LICENSE_MIT in Silice repo root | |
| */ | |
| #include "config.h" | |
| #include "std.h" | |
| //#include "printf.h" | |
| //#include "display.h" | |
| const unsigned char cmd0[] = {0x40,0x00,0x00,0x00,0x00,0x95}; | |
| const unsigned char cmd8[] = {0x48,0x00,0x00,0x01,0xAA,0x87}; | |
| const unsigned char cmd55[] = {0x77,0x00,0x00,0x00,0x00,0x01}; | |
| const unsigned char acmd41[] = {0x69,0x40,0x00,0x00,0x00,0x01}; | |
| const unsigned char cmd16[] = {0x50,0x00,0x00,0x02,0x00,0x15}; | |
| const unsigned char cmd17[] = {0x51,0x00,0x00,0x00,0x00,0x55}; | |
| void (*sdcard_while_loading_callback)(); | |
| void sdcard_idle() { } | |
| void sdcard_select() | |
| { | |
| *SDCARD = 2; | |
| } | |
| // Keep the clock running a bit | |
| // unclear whether this is really important https://electronics.stackexchange.com/questions/303745/sd-card-initialization-problem-cmd8-wrong-response | |
| __attribute__((optimize("O0"))) void sdcard_ponder() | |
| { | |
| int clk = 0; | |
| for (int i = 0; i < 16 ; i++) { | |
| *SDCARD = 4 | 2 | clk; | |
| clk = 1 - clk; | |
| asm volatile ("nop;"); | |
| } | |
| } | |
| void sdcard_unselect() | |
| { | |
| *SDCARD = 4 | 2; | |
| } | |
| #define sdcard_send_step(data) \ | |
| mosi = (data >> 7)&1;\ | |
| data = data << clk;\ | |
| *SDCARD = (mosi<<1) | clk;\ | |
| clk = 1-clk; | |
| __attribute__((optimize("O0"))) void sdcard_send(int indata) | |
| { | |
| int clk = 0; | |
| int mosi = 0; | |
| int data = indata; | |
| sdcard_send_step(data); sdcard_send_step(data); | |
| sdcard_send_step(data); sdcard_send_step(data); | |
| sdcard_send_step(data); sdcard_send_step(data); | |
| sdcard_send_step(data); sdcard_send_step(data); | |
| sdcard_send_step(data); sdcard_send_step(data); | |
| sdcard_send_step(data); sdcard_send_step(data); | |
| sdcard_send_step(data); sdcard_send_step(data); | |
| sdcard_send_step(data); sdcard_send_step(data); | |
| *SDCARD = 2; // mosi = 1 | |
| sdcard_while_loading_callback(); | |
| } | |
| #define sdcard_read_step_L() \ | |
| *SDCARD = 2;\ | |
| ud = *SDCARD;\ | |
| answer = (answer << 1) | (ud); | |
| #define sdcard_read_step_H() \ | |
| *SDCARD = 3;\ | |
| n ++; | |
| __attribute__((optimize("O0"))) unsigned char sdcard_read(unsigned char in_len,unsigned char in_wait) | |
| { | |
| int wait = in_wait; | |
| int len = in_len; | |
| int ud; | |
| int n = 0; | |
| int answer = 0xff; | |
| while ( (wait && (answer&(1<<(len-1)))) || (!wait && n < len)) { | |
| sdcard_read_step_H(); | |
| sdcard_read_step_L(); | |
| sdcard_while_loading_callback(); | |
| } | |
| return answer; | |
| } | |
| __attribute__((optimize("O0"))) unsigned char sdcard_get(unsigned char len,unsigned char wait) | |
| { | |
| unsigned char status; | |
| sdcard_select(); | |
| status = sdcard_read(len,wait); | |
| for (int i=1;i<len>>3;i++) { | |
| status = sdcard_read(8,0); | |
| } | |
| sdcard_unselect(); | |
| // sdcard_ponder(); | |
| return status; | |
| } | |
| __attribute__((optimize("O0"))) void sdcard_cmd(const unsigned char *cmd) | |
| { | |
| sdcard_select(); | |
| for (int i=0;i<6;i++) { | |
| sdcard_send(cmd[i]); | |
| } | |
| sdcard_unselect(); | |
| } | |
| __attribute__((optimize("O0"))) unsigned char sdcard_start_sector(int sector) | |
| { | |
| sdcard_select(); | |
| sdcard_send(cmd17[0]); | |
| sdcard_send((sector>>24)&255); | |
| sdcard_send((sector>>16)&255); | |
| sdcard_send((sector>> 8)&255); | |
| sdcard_send((sector )&255); | |
| sdcard_send(cmd17[5]); | |
| sdcard_unselect(); | |
| sdcard_ponder(); | |
| return sdcard_get(8,1); | |
| } | |
| __attribute__((optimize("O0"))) unsigned char *sdcard_read_sector(int sector,unsigned char *dst) | |
| { | |
| unsigned char status = sdcard_start_sector(sector); | |
| //display_set_cursor(0,0); | |
| //printf("cmd17: %x\n",status); | |
| //display_refresh(); | |
| //while (status != 0) { *LEDS = status; } | |
| if (status != 0) { | |
| return dst; | |
| } else { | |
| sdcard_get(1,1); // start token | |
| for (int i=0;i<512;i++) { | |
| unsigned char by = sdcard_get(8,0); | |
| *(dst++) = by; | |
| //if (i < 8) { | |
| // printf("%b ",by); | |
| //} | |
| } | |
| int crc = sdcard_get(16,0); // CRC | |
| sdcard_unselect(); | |
| sdcard_ponder(); | |
| //printf("crc: %x\n",crc); | |
| //display_refresh(); | |
| } | |
| return dst; | |
| } | |
| __attribute__((optimize("O0"))) void sdcard_preinit() | |
| { | |
| *SDCARD = 4 | 2; | |
| pause(20000000); | |
| { | |
| int clk = 0; | |
| for (int i = 0; i < 160 ; i++) { | |
| *SDCARD = 4 | 2 | clk; | |
| clk = 1 - clk; | |
| } | |
| } | |
| *SDCARD = 4 | 2; | |
| } | |
| __attribute__((optimize("O0"))) void sdcard_init() | |
| { | |
| unsigned char status; | |
| sdcard_while_loading_callback = sdcard_idle; | |
| //*LEDS = 0xAA; | |
| while (1) { | |
| sdcard_preinit(); | |
| sdcard_cmd(cmd0); | |
| status = sdcard_get(8,1); | |
| //printf("cmd0: %x\n",status); | |
| //display_refresh(); | |
| sdcard_ponder(); | |
| if (status != 0xff) { | |
| break; | |
| } | |
| pause(20000000); | |
| } | |
| //*LEDS = 0x55; | |
| sdcard_cmd(cmd8); | |
| status = sdcard_get(40,1); | |
| sdcard_ponder(); | |
| while (1) { | |
| sdcard_cmd(cmd55); | |
| status = sdcard_get(8,1); | |
| //printf("cmd55: %x\n",status); | |
| //display_refresh(); | |
| sdcard_ponder(); | |
| sdcard_cmd(acmd41); | |
| status = sdcard_get(8,1); | |
| //printf("acmd41: %x\n",status); | |
| //display_refresh(); | |
| //*LEDS = status; | |
| sdcard_ponder(); | |
| if (status == 0) { | |
| break; | |
| } | |
| sdcard_unselect(); | |
| sdcard_ponder(); | |
| pause(2000000); | |
| sdcard_select(); | |
| } | |
| //*LEDS = 0xC3; | |
| sdcard_cmd(cmd16); | |
| status = sdcard_get(8,1); | |
| //printf("cmd16: %x\n",status); | |
| //display_refresh(); | |
| //while (status != 0) { *LEDS = status; } | |
| sdcard_ponder(); | |
| } | |
| int sdcard_readsector( | |
| long unsigned int start_block, | |
| unsigned char *buffer, | |
| long unsigned int sector_count) | |
| { | |
| if (sector_count == 0) { | |
| return 0; | |
| } | |
| while (sector_count--) { | |
| buffer = sdcard_read_sector(start_block++,buffer); | |
| } | |
| return 1; | |
| } | |
| int sdcard_writesector( | |
| long unsigned int start_block, | |
| unsigned char *buffer, | |
| long unsigned int sector_count) | |
| { | |
| // ignore | |
| return 0; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // @sylefeb 2022 | |
| // MIT license, see LICENSE_MIT in Silice repo root | |
| // https://github.com/sylefeb/Silice/ | |
| #pragma once | |
| // --- basic functions, call sdcard_init then use sdcard_read_sector --- | |
| void sdcard_init(); | |
| unsigned char *sdcard_read_sector(int sector,unsigned char *dst); | |
| extern void (*sdcard_while_loading_callback)(); // if used, keep it short! | |
| // (a few instructions) | |
| // --- fat_io_lib sdcard implementation --- | |
| int sdcard_readsector( | |
| long unsigned int start_block, | |
| unsigned char *buffer, | |
| long unsigned int sector_count); | |
| int sdcard_writesector( // not implemented | |
| long unsigned int start_block, | |
| unsigned char *buffer, | |
| long unsigned int sector_count); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment