📄 sdms.c
字号:
#include "sdms.h"#define SDMS_DEBUG 1#ifdef PB1100 #define SDMS_CAPABLE#endif#ifdef DB1100 #define SDMS_CAPABLE#endif#ifdef HYDROGEN3 #define SDMS_CAPABLE#endifunsigned char Data;sdms_param sd0_param, sd1_param;int sdms_rca, sdms_base;int sdms_blksze = 512; // default block size: 512int sdms_blkcnt = 1; // default block count: 1int sdms_sectorsize = 512;int sdmsInit (int base){ int i, rca, busy, resp; // initial config, must set I bit for interrupts - not used right now sdms_config (base) = 0x00000200 // set DE | 0x000000cf; // set divider sync (); sdms_ctrl (base) = 0x00000002 // set FF to flush & reset | 0x00000001; // set EN sync (); sdms_ctrl (base) = 0x00000001; // clear FF to exit reset sync (); sdms_blksze (base) = 0x00000000; // block size & count = 1 sync (); sdms_tocnt (base) = 0x001fffff; // max timeout sync (); // reset to idle sdms_CMD00 (base, 0x00000000); while (sdms_cmd (base) & 0x00000001); // wait when CBSY = 1 while (sdms_status (base) & 0x00000010); // wait when CRBSY = 1 // check for response & set voltage do { sdms_CMD55(base, 0x00000000); while (!(sdms_cmd (base) & 0x00000002)) // wait when RRDY = 0 { if (sdms_status (base) & 0x00020000) // if timeout on response { return (0); } } sdms_ACMD41 (base, 0x00ff8000); // operating voltage range while (!(sdms_cmd (base) & 0x00000002)) // wait when RRDY = 0 { if (sdms_status (base) & 0x00020000) // if timeout on response { return (0); } } busy = (sdms_resp0 (base) >> 31); nop(); // wait 1 ms i = 0; while( i < 400000 ) { i++; } } while (!busy); for (i = 0; i < 400000; i++); // obtain rca sdms_CMD02 (base, 0x00000000); while (sdms_cmd (base) & 0x00000001); // wait when CBSY = 1 while (!(sdms_cmd (base) & 0x00000002)); // wait when RRDY = 0 sdms_CMD03 (base, 0x00000000); while (sdms_cmd (base) & 0x00000001); // wait when CBSY = 1 while (!(sdms_cmd (base) & 0x00000002)); // wait when RRDY = 0 rca = sdms_resp0 (base); rca = ((rca & 0xffff0000) >> 16); return (rca);}sdms_param sdmsParam (int base, int rca) // this function taken from testsuite2's sdms_walk.c{ sdms_param param; int resp; int c_size; int c_size_mult; int data; int tmp; param.rca = rca; sdms_CMD09(base, (param.rca << 16) | 0x00000000); while(sdms_cmd(base) & 0x00000001) {} // wait when CBSY = 1 while(!(sdms_cmd(base) & 0x00000002)) {} // wait when RRDY = 0 tmp = ((sdms_resp2(base) & 0x00000f00) >> 8); param.rd_blk_len = (0x00000001 << tmp); tmp = ((sdms_resp2(base) & 0x00000080) >> 7); param.rd_blk_partial = tmp; c_size = (((sdms_resp2(base) & 0x00000003) << 10) | ((sdms_resp1(base) & 0xffc00000) >> 22)); c_size_mult = ((sdms_resp1(base) & 0x00000380) >> 7); param.mem_capacity = (c_size+1)*(0x00000001 << (c_size_mult+2))*param.rd_blk_len; tmp = ((sdms_resp0(base) & 0x0003c000) >> 14); param.wr_blk_len = 0x00000001 << tmp; tmp = ((sdms_resp0(base) & 0x00002000) >> 13); param.wr_blk_partial = tmp; // host control // change clock frequency to 25 MHz sdms_config(base) = 0x00008201; // clock divided by 4 to 25 MHz sdms_CMD07(base, (param.rca << 16) | 0x00000000); // response is R1b, check DBSY bit while(sdms_status(base) & 0x00000020) {} // wait when DBSY = 1 while(sdms_cmd(base) & 0x00000001) {} // wait when CBSY = 1 while(!(sdms_cmd(base) & 0x00000002)) {} // wait when RRDY = 0 sdms_CMD13(base, (param.rca << 16) | 0x00000000); while(sdms_cmd(base) & 0x00000001) {} // wait when CBSY = 1 while(!(sdms_cmd(base) & 0x00000002)) {} // wait when RRDY = 0 sdms_CMD13(base, (param.rca << 16) | 0x00000000); while(sdms_cmd(base) & 0x00000001) {} // wait when CBSY = 1 while(!(sdms_cmd(base) & 0x00000002)) {} // wait when RRDY = 0 // flush the fifo sdms_ctrl(base) = (sdms_ctrl(base) | 0x00000002); sdms_CMD55(base, (param.rca << 16) | 0x00000000); while(sdms_cmd(base) & 0x00000001) {} // wait when CBSY = 1 while(!(sdms_cmd(base) & 0x00000002)) {} // wait when RRDY = 0 // ACMD51, treated as single block read // need to set the host blk size to 7 (meaning 7 + 1 = 8 bytes block) sdms_blksze(base) = 0x00000007; sdms_ACMD51(base, (param.rca << 16) | 0x00000000); while(sdms_cmd(base) & 0x00000001) {} // wait when CBSY = 1 while(!(sdms_cmd(base) & 0x00000002)) {} // wait when RRDY = 0 // read response resp = sdms_resp0(base); while(sdms_status(base) & 0x00000010) {} // wait when CRBSY = 1 while(sdms_status(base) & 0x00000020) {} // wait when DBSY = 1 while(!(sdms_status(base) & 0x00040000)) {} // wait when DTD = 0 data = sdms_rxfifo(base); data = sdms_rxfifo(base); sdms_ctrl(base) = (sdms_ctrl(base) | 0x00000002); // flush the fifo param.bus_width = data & 0x0000000f; sync(); // set blksze back to 511 (meaning 512 bytes) sdms_blksze(base) = 0x000001ff; //printf("SET: p_sd0_blksze = 0x%08x\n", sdms_blksze(base)); return param;}int sdmsOpen (int slot){ int i, rca, base, resp; volatile unsigned *memory_cards; sdms_param sd_param; printf("SDMS Opnen\n"); if (!slot) base = sd0; else #ifdef PB1100 base = sd1; #else return (0); // only Pb1100 has two SD slots #endif // power up (board-specific) #ifdef SDMS_CAPABLE #ifdef DB1100 memory_cards = (uint32 *)0xae000014; *memory_cards = 0x000000C0; #endif #ifdef PB1100 memory_cards = (uint32 *)0xae000010; *memory_cards = (3<<10) << 16; #endif #ifdef HYDROGEN3 // no power up required #endif #else return (0); #endif // enable sd slot sdms_enable (base) = 0x00000001; // reset sync (); for (i = 0; i < 400000; i++); // give it some time or else won't function correctly sdms_enable (base) = 0x00000003; // take out of reset sync (); for (i = 0; i < 400000; i++); // give it some time or else won't function correctly sdms_status (base) = 0xffffffff; // clear status register sync (); // initialize & obtain card parameters rca = sdmsInit (base); if (rca) { sd_param = sdmsParam (base, rca);// printf ("sd card found in slot %d, capacity = %dkB\n", slot, sd_param.mem_capacity/1024); sdms_config (base) = 0x00000200 // set DE | 0x00000002; // set divider [0x000000cf] sync (); } else {// printf ("no sd card found in slot %d\n", slot); return (0); } if (!slot) { sd0_param = sd_param; sdms_rca = sd0_param.rca; sdms_base = sd0; } else { sd1_param = sd_param; sdms_rca = sd1_param.rca; sdms_base = sd1; } // for some reason 'set bus width' and 'set block size' won't work inside sdmsInit, will try to figure out later // set bus width to 4 bits (comment this out for 1 wire mode) sdms_ctrl (sdms_base) = 0x00000101; // 4-bit bus sdms_CMD55 (sdms_base, (sdms_rca << 16) | 0x00000000); sdms_ACMD06 (sdms_base, 0x00000002); // set to 4-bit // set block size sdms_blksze (sdms_base) = (((sdms_blkcnt - 1) & 0x000001ff) << 16) // block count [24:16] | ((sdms_blksze - 1) & 0x000007ff); // block size [10:0] sync (); sdms_CMD16 (sdms_base, sdms_blksze); while (sdms_cmd (sdms_base) & 0x00000001); // wait when CBSY = 1 while (!(sdms_cmd (sdms_base) & 0x00000002)); // wait when RRDY = 0 resp = sdms_resp0 (sdms_base); return (1);}int sdmsEject (){/* sdms_status (sd0) = 0xffffffff; sdms_enable (sd0) = 0x00000000; sync (); sdms_status (sd1) = 0xffffffff; sdms_enable (sd1) = 0x00000000; sync (); printf ("sd slots disabled; it is safe to remove sd cards\n");*/ return (1);}void sdmsStopX (void){ sdms_cmdarg (sdms_base) = 0x00000000; sync (); sdms_cmd (sdms_base) = 0x00010c71; // STOP_TRANSMISSION sync (); sdms_ctrl (sdms_base) = (sdms_ctrl (sdms_base) | 0x00000008); // set CFDIS to force clk to be on sync (); while (sdms_cmd (sdms_base) & 0x00000001); // wait until CBSY = 0 while (sdms_status (sdms_base) & 0x00000020); // wait until DBSY = 0 while (!(sdms_status (sdms_base) & 0x00010000)); // wait when CRD = 0 while (!(sdms_cmd (sdms_base) & 0x00000002)); // wait when RRDY = 0 sdms_ctrl (sdms_base) = (sdms_ctrl (sdms_base) & 0xfffffff7); // reset CFDIS to 0 sync (); sdms_status (sdms_base) = (sdms_status (sdms_base) | 0x00040000); // reset data done bit sync ();}int sdmsRead (int sect, int n, void* buf){ int t, bytesToRead, startAddress; bytesToRead = n * sdms_sectorsize; startAddress = sect * sdms_sectorsize; if (SDMS_DEBUG) printf ("sector: %d\n", sect); t = sdmsReadBytes (bytesToRead, startAddress, buf); return (t);}int sdmsReadBytes (int bytesToRead, int startAddress, uint8* buf){ int i, temp; if (SDMS_DEBUG) printf ("start address: 0x%04X (%d)\n", startAddress, startAddress); // flush RxFIFO of any extraneous bytes from previous read sdms_ctrl (sdms_base) |= 0x00000002; // set FF to flush & reset sync (); sdms_ctrl (sdms_base) &= ~0x00000002; // clear FF to exit reset sync (); sdms_CMD18 (sdms_base, startAddress); for (i = 0; i < bytesToRead; i++) { while (!(sdms_status (sdms_base) & 0x00000400)) ;// {// if (sdms_status(sdms_base) & 0x00080000)// {// printf ("ERROR: SDMS communication error\n");// sdmsStopTxRx ();// return (i);// }// } buf[i] = (uint8) sdms_rxfifo (sdms_base); } if (SDMS_DEBUG) { for (i = 0; i < bytesToRead; i++) { if (!(i % 10)) printf ("\n%d\t", i); printf ("%02X ", buf[i]); } printf ("\n\n"); } sdmsStopX (); return (i);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -