#include "mmc.h"
#include "board.h"
#include "storage.h"
#include "console.h"
#include "buffer.h"
Include dependency graph for mmc.c:
Go to the source code of this file.
Defines | |
#define | USE_C_CODE_INSTEAD_OF_ASM 0 |
Functions | |
unsigned char | MmcCommand (unsigned char c1, unsigned char c2, unsigned char c3, unsigned char c4, unsigned char c5) |
Do one MMC command and return the MMC SPI R1 response. | |
unsigned char | MmcWaitForData () |
MMC Wait For Data start token 0xfe. | |
void | MmcGetData (unsigned int amountOctets) |
Read a Data Block from MMC. | |
unsigned char | GetStorageInformation () |
Returns MMC Card Identification Register in diskSect. | |
unsigned char | RebootMMC () |
Try to switch on the MMC. | |
Public unsigned char | InitMMC () |
Start-up the MMC card. | |
void | PerformBlockRead () |
Perform the actual reading of 512 octets from MMC. | |
Public unsigned char | SeekSector (unsigned long sectorN) |
Perform MMC Seek Command for offset sectorN*512. | |
Public unsigned char | ReadPhysicalSector () |
Perform block read of previously sought sector to diskSect. | |
unsigned char | WritePhysicalSector () |
Perform MMC block write from *dataBufPtr to sector sectorAddress.l. |
Definition in file mmc.c.
|
|
|
Returns MMC Card Identification Register in diskSect.
Definition at line 171 of file mmc.c. References DiskBlock::Raw::buf, ConsolePutChar, ConsolePutHex8, ConsolePutUInt, ConsoleWrite, diskSect, MmcCommand(), MmcGetData(), MmcWaitForData(), and DiskBlock::raw. Referenced by InitMMC(). 00171 { 00172 if (MmcCommand(0x4a,0,0,0,0)&0xfe) 00173 return 4; /* no storage info */ 00174 MmcWaitForData(); 00175 MmcGetData(30); 00176 00177 ConsoleWrite("\rMMC Manufacturer#: "); 00178 ConsolePutUInt(diskSect.raw.buf[0]); 00179 ConsoleWrite("Product Name: "); 00180 ConsolePutChar(diskSect.raw.buf[3]); 00181 ConsolePutChar(diskSect.raw.buf[4]); 00182 ConsolePutChar(diskSect.raw.buf[5]); 00183 ConsolePutChar(diskSect.raw.buf[6]); 00184 ConsolePutChar(diskSect.raw.buf[7]); 00185 ConsolePutChar(diskSect.raw.buf[8]); 00186 ConsoleWrite(" Production date: "); 00187 ConsolePutUInt(diskSect.raw.buf[14]>>4); 00188 ConsoleWrite("/ "); 00189 ConsolePutUInt((diskSect.raw.buf[14]&0x0f)+1997); 00190 ConsolePutChar('\r'); 00191 ConsoleWrite("Media serial number: "); 00192 ConsolePutHex8(diskSect.raw.buf[10]); 00193 ConsolePutHex8(diskSect.raw.buf[11]); 00194 ConsolePutHex8(diskSect.raw.buf[12]); 00195 ConsolePutHex8(diskSect.raw.buf[13]); 00196 00197 //mediaSerialNumber[0] = diskSect.raw.buf[10]; 00198 //mediaSerialNumber[1] = diskSect.raw.buf[11]; 00199 //mediaSerialNumber[2] = diskSect.raw.buf[12]; 00200 //mediaSerialNumber[3] = diskSect.raw.buf[13]; 00201 00202 ConsolePutChar('\r'); 00203 00204 /* print out card ident register 00205 for (c=0; c<30; c++){ 00206 if ((c&0x03)==0) ConsolePutChar(' '); 00207 ConsolePutHex8(diskSect.raw.buf[c]); 00208 } 00209 */ 00210 00211 return 0; /* All OK return */ 00212 }
|
Here is the call graph for this function:
|
Start-up the MMC card.
Definition at line 246 of file mmc.c. References DiskBlock::Raw::buf, ConsoleWrite, Delay(), diskSect, GetStorageInformation(), Temp::i, MmcCommand(), MMCDeselect, MMCSelect, Public, DiskBlock::raw, ReadPhysicalSector(), RebootMMC(), SeekSector(), SPIPutChar, SPIPutCharWithoutWaiting, SPIWait, and temp. Referenced by InitStorage(). 00246 { 00247 unsigned char c; 00248 00249 00250 ConsoleWrite ("Init: MMC\r"); 00251 MMCSelect(); 00252 /* Allow MMC some time and clock cycles to reset */ 00253 for (c=0; c<200; c++){ 00254 SPIPutCharWithoutWaiting(0xff); 00255 SPIWait(); 00256 } 00257 Delay(20); 00258 00259 if (RebootMMC()) return 1; //not able to powerup; 00260 //An existing MMC card should be able to respond now. 00261 00262 GetStorageInformation(); 00263 00264 /* Set Block Size of 512 bytes (2 == 512 << 8) */ 00265 if ((c=MmcCommand(0x50,0,0,2,0))) return c|0x80; /* blocksize error */ 00266 00267 /* Check if MMC supports interrupted data transfer */ 00268 /* This does a simple checksum check to see if interrupted and 00269 * non-interrupted read blocks are the same. */ 00270 /* This could be a function, so it is in braces for clarity purposes */ 00271 { 00272 if (SeekSector(0)) return 2; //Storage powerup failure 00273 if (ReadPhysicalSector()) return 2; //Storage powerup failure 00274 00275 temp.i = diskSect.raw.buf[511]; 00276 for (c=0; c<250; c++){ 00277 temp.i += diskSect.raw.buf[c]; 00278 } 00279 00280 if (SeekSector(0)) return 2;//Storage powerup failure 00281 00282 /* Send some extra SPI clocks */ 00283 MMCDeselect(); 00284 SPIPutCharWithoutWaiting(0xff); 00285 for (c=0; c<100; c++){ 00286 SPIPutChar(0xff); 00287 } 00288 SPIWait(); 00289 00290 if (ReadPhysicalSector()){ 00291 ConsoleWrite("Interrupted read failed.\r"); 00292 ConsoleWrite("Using compatibility mode.\r"); 00293 return 0x0e; //ok but no support for seek-before-read 00294 00295 }else{ 00296 //Check if received data was same 00297 temp.i -= diskSect.raw.buf[511]; 00298 for (c=0; c<250; c++){ 00299 temp.i -= diskSect.raw.buf[c]; 00300 } 00301 } 00302 00303 if (temp.i) { /* Checksum does not match */ 00304 ConsoleWrite("This MMC has no support for interrupted read. "); 00305 ConsoleWrite("Using compatibility mode.\r"); 00306 return 0x0e; //ok but no support for seek-before-read 00307 } 00308 00309 ConsoleWrite("\rInitMMC ok.\r"); 00310 } 00311 00312 /* All OK return */ 00313 return 0; //ok and MMC supports seek-before-read 00314 00315 }
|
Here is the call graph for this function:
|
Do one MMC command and return the MMC SPI R1 response. Returns 0xff in case of timeout (relies on weak pull-up on the MISO pin). Note that the parameter bytes are used for temporary storage after they are written out. Definition at line 19 of file mmc.c. References ConsolePutChar, ConsolePutHex16, ConsolePutHex8, ConsoleWrite, DebugMessage, Delay(), MMCDeselect, MMCSelect, SPI8Clocks(), SPIGetChar(), SPIPutChar, SPIPutCharWithoutWaiting, and SPIWait. Referenced by GetStorageInformation(), InitMMC(), RebootMMC(), SeekSector(), and WritePhysicalSector(). 00023 { 00024 00025 00026 unsigned int i; 00027 00028 00029 /* Note: c1, c2 are used for temporary variables after use! */ 00030 00031 // MMC_OFF = NO; //MMC should be powered, but switch power on just-in-case 00032 // MMCDeselect(); //put MMC on-line. 00033 // Provide clock edges before and after asserting MMC CS 00034 00035 MMCDeselect(); 00036 SPI8Clocks(8); 00037 MMCSelect(); 00038 SPI8Clocks(8); 00039 00040 i=0; 00041 // If card still seems to be busy, give it some time... 00042 // changed 12/2005 to give quite a lot of time. 00043 while ((SPIGetChar()!=0xff) && (++i<60000)); 00044 ; 00045 00046 // The bus should be stable high now 00047 if ((i=SPI_RESULT_BYTE) != 0xff){ 00048 ConsoleWrite("\rUnexpected busy signal from MMC. "); 00049 ConsolePutHex16(i); 00050 MMCDeselect(); 00051 Delay(1000); 00052 return 0x81; //MMC unexpectedly Busy 00053 } 00054 00055 #ifdef MMCDEBUG 00056 DebugMessage(" \x1b[7m"); 00057 ConsolePutChar('C'); ConsolePutHex8(c1); ConsolePutHex8(c2); ConsolePutHex8(c3); 00058 ConsolePutHex8(c4); ConsolePutHex8(c5); ConsolePutChar('|'); 00059 #endif 00060 00061 // Send the MMC command 00062 SPIPutCharWithoutWaiting(c1); 00063 SPIPutChar(c2); 00064 SPIPutChar(c3); 00065 SPIPutChar(c4); 00066 SPIPutChar(c5); 00067 SPIPutChar(0x95); /* Valid CRC for init, then don't care */ 00068 SPIWait(); 00069 /* Now ok to use c1..c5 as temporaries (dirty but kool) */ 00070 00071 // Wait for R1 style response (bit 7 low) from MMC 00072 #ifdef MMCDEBUG 00073 { 00074 c1=100; /* try max. 100 times */ 00075 while((c1--)&&((c2=SPIGetChar())&0x80)){ //wait for R1 or timeout 00076 // R1 response not detected, if it's not 0xff, print it for debugging. 00077 if (c2!=0xff){ConsolePutHex8(c2);ConsolePutChar('|');} 00078 } 00079 ConsolePutHex8(c2); 00080 DebugMessage("\x1b[0m "); 00081 } 00082 #else 00083 { 00084 c1=100; 00085 while((c1--)&&((c2=SPIGetChar())&0x80)) //wait for R1 or timeout 00086 ; 00087 } 00088 #endif 00089 00090 return c2; //return the R1 response 00091 }
|
Here is the call graph for this function:
|
Read a Data Block from MMC. Use shared global pointer dataBufPtr declared in buffer.h. Does not affect MMC chip select signal.
Definition at line 159 of file mmc.c. References DiskBlock::Raw::buf, dataBufPtr, DebugMessage, diskSect, DiskBlock::raw, and SPIGetChar(). Referenced by GetStorageInformation(). 00159 { 00160 DebugMessage("<G"); 00161 00162 dataBufPtr = diskSect.raw.buf; 00163 while (amountOctets--){ 00164 *dataBufPtr++=SPIGetChar(); 00165 } 00166 DebugMessage("G>"); 00167 }
|
Here is the call graph for this function:
|
MMC Wait For Data start token 0xfe. First any 0xFF's are read off the mmc. The first non-ff octet is examined. If it's the 0xfe data start token, everything is fine. If not, then some error has occurred. Since we're in an embedded system, it's unclear what we should do then. Current approach is to say all ok but make read block return 0xff's by dropping the MMC card offline. Before that we read "lots" of octets from the MMC to flush any pending data. Finally we return "ALL OK". It's not disasterous at least as long as we don't WRITE to MMC. 12/2005: Well, now we do write to mmc... Definition at line 105 of file mmc.c. References ConsolePutHex8, ConsoleWrite, DebugMessage, MMCDeselect, SPI8Clocks(), and SPIGetChar(). Referenced by GetStorageInformation(), ReadPhysicalSector(), TransferSectorSCI(), and TransferSectorSDI(). 00105 { 00106 00107 unsigned char c; 00108 unsigned int i; 00109 00110 DebugMessage("<t:"); //Token Wait 00111 00112 i = 60000; //try max. 60000 bus cycles 00113 // Wait until something else than 0xff is read from the bus 00114 do { 00115 c=SPIGetChar(); 00116 --i; 00117 } while ((c == 0xff) && (i)); 00118 00119 // Something was received from the bus? Might it actually be te 00120 // desired 0xFE data start token? 00121 if (c != 0xfe){ 00122 // No data start token, read fail. In an OS an error message would display. 00123 // Since we're in an embedded system, it's unclear what we should do now. 00124 // Current approach is to say all ok but make read block return 0xff's. 00125 // It's not disasterous at least as long as we don't WRITE to MMC. 00126 00127 // Flush any data that might be pending from the MMC. 00128 #ifdef MMCLONGDEBUG 00129 { 00130 unsigned int i; 00131 ConsoleWrite("\rMMCWaitForData failed. "); 00132 ConsoleWrite("Expected 0xFE token, received: "); 00133 for (i=0;i<550;i++){ 00134 ConsolePutHex8(c); 00135 c=SPIGetChar(); 00136 } 00137 } 00138 #else 00139 ConsoleWrite(" NoData "); 00140 SPI8Clocks(200); /* Flush MMC by sending lots of FF's to it */ 00141 SPI8Clocks(200); 00142 SPI8Clocks(200); 00143 #endif 00144 00145 MMCDeselect(); 00146 DebugMessage("!t>"); 00147 return 5; //Return error 00148 } 00149 DebugMessage("t>"); //Exit Token Wait 00150 return 0; 00151 }
|
Here is the call graph for this function:
|
Perform the actual reading of 512 octets from MMC. Note: This is the fast routine to read complete disk block If you have DMA, write this to use it! Definition at line 325 of file mmc.c. References DiskBlock::Raw::buf, ConsoleWrite, dataBufPtr, diskSect, DiskBlock::raw, SPIPutCharWithoutWaiting, and SPIWait. Referenced by ReadPhysicalSector(), TransferSectorSCI(), and TransferSectorSDI(). 00325 { 00326 00327 #ifdef MMCDEBUG 00328 ConsoleWrite("<R"); //Actual Read 00329 #endif 00330 00331 // LED1 = LED_ON; 00332 00333 /* Use shared global buffer pointer for speed*/ 00334 /* Loop unrolled 16 times for SPEED! :) */ 00335 dataBufPtr = diskSect.raw.buf; 00336 00337 00338 00339 #if USE_C_CODE_INSTEAD_OF_ASM 00340 00341 while (dataBufPtr < diskSect.raw.buf+512){ 00342 SPIPutCharWithoutWaiting(0xff); 00343 SPIWait(); 00344 *dataBufPtr++=SPI_RESULT_BYTE; 00345 SPIPutCharWithoutWaiting(0xff); 00346 SPIWait(); 00347 *dataBufPtr++=SPI_RESULT_BYTE; 00348 SPIPutCharWithoutWaiting(0xff); 00349 SPIWait(); 00350 *dataBufPtr++=SPI_RESULT_BYTE; 00351 SPIPutCharWithoutWaiting(0xff); 00352 SPIWait(); 00353 *dataBufPtr++=SPI_RESULT_BYTE; 00354 SPIPutCharWithoutWaiting(0xff); 00355 SPIWait(); 00356 *dataBufPtr++=SPI_RESULT_BYTE; 00357 SPIPutCharWithoutWaiting(0xff); 00358 SPIWait(); 00359 *dataBufPtr++=SPI_RESULT_BYTE; 00360 SPIPutCharWithoutWaiting(0xff); 00361 SPIWait(); 00362 *dataBufPtr++=SPI_RESULT_BYTE; 00363 SPIPutCharWithoutWaiting(0xff); 00364 SPIWait(); 00365 *dataBufPtr++=SPI_RESULT_BYTE; 00366 SPIPutCharWithoutWaiting(0xff); 00367 SPIWait(); 00368 *dataBufPtr++=SPI_RESULT_BYTE; 00369 SPIPutCharWithoutWaiting(0xff); 00370 SPIWait(); 00371 *dataBufPtr++=SPI_RESULT_BYTE; 00372 SPIPutCharWithoutWaiting(0xff); 00373 SPIWait(); 00374 *dataBufPtr++=SPI_RESULT_BYTE; 00375 SPIPutCharWithoutWaiting(0xff); 00376 SPIWait(); 00377 *dataBufPtr++=SPI_RESULT_BYTE; 00378 SPIPutCharWithoutWaiting(0xff); 00379 SPIWait(); 00380 *dataBufPtr++=SPI_RESULT_BYTE; 00381 SPIPutCharWithoutWaiting(0xff); 00382 SPIWait(); 00383 *dataBufPtr++=SPI_RESULT_BYTE; 00384 SPIPutCharWithoutWaiting(0xff); 00385 SPIWait(); 00386 *dataBufPtr++=SPI_RESULT_BYTE; 00387 SPIPutCharWithoutWaiting(0xff); 00388 SPIWait(); 00389 *dataBufPtr++=SPI_RESULT_BYTE; 00390 } 00391 00392 #else 00393 00394 // BlockRead in Assembler 00395 00396 _asm 00397 //asm prologue start 00398 push psw 00399 push acc 00400 mov a,r2 00401 push acc 00402 push dpl 00403 push dph 00404 //prologue end 00405 00406 mov dpl,_dataBufPtr 00407 mov dph,(_dataBufPtr + 1) 00408 2106$: 00409 clr c 00410 mov a,_dataBufPtr 00411 subb a,#(_diskSect + 0x0200) 00412 mov a,(_dataBufPtr + 1) 00413 subb a,#((_diskSect + 0x0200) >> 8) 00414 jc 2122$ 00415 ljmp 2108$ 00416 2122$: 00417 mov _SPDAT,#0xFF 00418 mov dpl,_dataBufPtr 00419 mov dph,(_dataBufPtr + 1) 00420 00421 mov a,_SPSTA 00422 mov a,_SPDAT 00423 mov _SPDAT,#0xFF 00424 movx @dptr,a 00425 inc dptr 00426 00427 mov a,_SPSTA 00428 mov a,_SPDAT 00429 mov _SPDAT,#0xFF 00430 movx @dptr,a 00431 inc dptr 00432 00433 mov a,_SPSTA 00434 mov a,_SPDAT 00435 mov _SPDAT,#0xFF 00436 movx @dptr,a 00437 inc dptr 00438 00439 mov a,_SPSTA 00440 mov a,_SPDAT 00441 mov _SPDAT,#0xFF 00442 movx @dptr,a 00443 inc dptr 00444 00445 mov a,_SPSTA 00446 mov a,_SPDAT 00447 mov _SPDAT,#0xFF 00448 movx @dptr,a 00449 inc dptr 00450 00451 mov a,_SPSTA 00452 mov a,_SPDAT 00453 mov _SPDAT,#0xFF 00454 movx @dptr,a 00455 inc dptr 00456 00457 mov a,_SPSTA 00458 mov a,_SPDAT 00459 mov _SPDAT,#0xFF 00460 movx @dptr,a 00461 inc dptr 00462 00463 mov a,_SPSTA 00464 mov a,_SPDAT 00465 mov _SPDAT,#0xFF 00466 movx @dptr,a 00467 inc dptr 00468 00469 mov a,_SPSTA 00470 mov a,_SPDAT 00471 mov _SPDAT,#0xFF 00472 movx @dptr,a 00473 inc dptr 00474 00475 mov a,_SPSTA 00476 mov a,_SPDAT 00477 mov _SPDAT,#0xFF 00478 movx @dptr,a 00479 inc dptr 00480 00481 mov a,_SPSTA 00482 mov a,_SPDAT 00483 mov _SPDAT,#0xFF 00484 movx @dptr,a 00485 inc dptr 00486 00487 mov a,_SPSTA 00488 mov a,_SPDAT 00489 mov _SPDAT,#0xFF 00490 movx @dptr,a 00491 inc dptr 00492 00493 mov a,_SPSTA 00494 mov a,_SPDAT 00495 mov _SPDAT,#0xFF 00496 movx @dptr,a 00497 inc dptr 00498 00499 mov a,_SPSTA 00500 mov a,_SPDAT 00501 mov _SPDAT,#0xFF 00502 movx @dptr,a 00503 inc dptr 00504 00505 mov a,_SPSTA 00506 mov a,_SPDAT 00507 mov _SPDAT,#0xFF 00508 movx @dptr,a 00509 inc dptr 00510 00511 mov a,_SPSTA 00512 mov a,_SPDAT 00513 movx @dptr,a 00514 inc dptr 00515 00516 00517 mov a, dph 00518 mov (_dataBufPtr + 1),a 00519 mov a, dpl 00520 mov _dataBufPtr,a 00521 00522 ljmp 2106$ 00523 2108$: 00524 //asm epilogue start 00525 pop dph 00526 pop dpl 00527 pop acc 00528 mov r2,a 00529 pop acc 00530 pop psw 00531 //epilogue end 00532 _endasm; 00533 00534 00535 00536 00537 #endif 00538 00539 00540 00541 00542 #ifdef MMCDEBUG 00543 ConsoleWrite("R>"); 00544 #endif 00545 00546 // LED1 = LED_OFF; 00547 00548 }
|
|
Perform block read of previously sought sector to diskSect.
Definition at line 587 of file mmc.c. References MMCDeselect, MMCSelect, MmcWaitForData(), PerformBlockRead(), Public, and SPI8Clocks(). Referenced by InitMMC(), and ReadDiskSector(). 00587 { 00588 00589 // RED_LED = LED_ON; /* Disk Read LED on */ 00590 00591 MMCSelect(); 00592 MmcWaitForData(); 00593 PerformBlockRead(); 00594 00595 /* generate SPI clock edges to finish up the command */ 00596 00597 SPI8Clocks(4); //Send 8*4=32 clocks (4 ff's) to MMC to be nice. 00598 MMCDeselect(); 00599 SPI8Clocks(4); //Again, give the poor MMC some clocks, it likes them. 00600 00601 //RED_LED = LED_OFF; /* Disk Read LED off */ 00602 00603 return 0; //ok return 00604 }
|
Here is the call graph for this function:
|
Try to switch on the MMC.
Definition at line 217 of file mmc.c. References ConsoleWrite, Delay(), MmcCommand(), and SPI8Clocks(). Referenced by InitMMC(), and SeekSector(). 00217 { 00218 unsigned char c; 00219 00220 //Try (indefinitely) to switch on the MMC card 00221 do{ 00222 SPI8Clocks(8); 00223 /* MMC Don't use CRC - seems to be required by some MMC cards? */ 00224 MmcCommand(0x7B,0,0,0,0); 00225 /* MMC Init, command 0x40 should return 0x01 (idle) if all is ok. */ 00226 }while (MmcCommand(0x40,0,0,0,0)!=0x01); 00227 // 0x01(idle) response detected. 00228 00229 ConsoleWrite("Card found, starting... "); 00230 /*Try max 255 times MMC Wake-up call: set to Not Idle (mmc returns 0x00)*/ 00231 c=255; 00232 while ((c--)&&(MmcCommand(0x41,0,0,0,16))){ 00233 Delay(10); 00234 if (c==1){ 00235 //timeout 00236 ConsoleWrite("Failed.\r"); 00237 return 2; /* Not able to power up mmc */ 00238 } 00239 } 00240 00241 ConsoleWrite("Ok.\r"); 00242 return 0; 00243 }
|
Here is the call graph for this function:
|
Perform MMC Seek Command for offset sectorN*512. In English: Send the Read Sector command to MMC Definition at line 555 of file mmc.c. References Address::b, Address::B::b0, Address::B::b1, Address::B::b2, Address::l, MmcCommand(), MMCDeselect, Public, RebootMMC(), and sectorAddress. Referenced by InitMMC(), ReadDiskSector(), TransferSectorSCI(), and TransferSectorSDI(). 00555 { 00556 unsigned char c, retries; 00557 00558 retries = 0; 00559 do{ 00560 retries++; 00561 sectorAddress.l = sectorN * 2; //convert to bytes (combined with 8bit shift) 00562 c=MmcCommand(0x51,sectorAddress.b.b2,sectorAddress.b.b1, 00563 sectorAddress.b.b0, 0); 00564 sectorAddress.l = sectorAddress.l >> 1; //convert back to blocks 00565 00566 // If MMC works properly, it returns Busy (== Not idle) at this stage. 00567 if (c!=0x00){ 00568 if (c != 0xff){ 00569 //MMC returns something else than Busy or "Idle Bus", print what it is 00570 //ConsoleDecipherMMCResponse(c); 00571 } 00572 // Something is wrong, take the standard action... 00573 RebootMMC(); 00574 if (retries > 10){ 00575 return 7; /* failed to execute mmc command */ 00576 } 00577 } 00578 }while(c!=0x00); //repeat until we get busy signal from MMC. 00579 00580 MMCDeselect(); 00581 00582 return 0; //ok return 00583 }
|
Here is the call graph for this function:
|
Perform MMC block write from *dataBufPtr to sector sectorAddress.l.
Definition at line 609 of file mmc.c. References Address::b, Address::B::b0, Address::B::b1, Address::B::b2, ConsoleWrite, dataBufPtr, Address::l, MmcCommand(), MMCDeselect, sectorAddress, SPI8Clocks(), SPIGetChar(), SPIPutCharWithoutWaiting, and SPIWait. Referenced by WriteDiskSector(). 00609 { 00610 unsigned char c; 00611 00612 #ifdef MMCDEBUG 00613 ConsoleWrite("<W"); 00614 #endif 00615 00616 00617 //RED_LED = LED_ON; 00618 sectorAddress.l = sectorAddress.l * 2; //convert to bytes (combined with 8bit shift) 00619 c=MmcCommand(0x40 | 24, sectorAddress.b.b2, sectorAddress.b.b1, 00620 sectorAddress.b.b0, 0); 00621 sectorAddress.l = sectorAddress.l >> 1; //convert back to blocks 00622 00623 //ConsolePutChar('w'); 00624 //ConsolePutHex8(c); 00625 00626 if (c!=0x00) return (c); //Error - MMC did not go to write mode 00627 00628 /* 00629 while (c!=0x00) { //wait for BUSY token, if you get 0x01(idle), it's an ERROR! 00630 c = SPIGetChar(); 00631 ConsolePutHex8(c); 00632 } 00633 */ 00634 //dataBufPtr = diskSect.raw.buf;//already set! 00635 SPIPutCharWithoutWaiting(0xFE); 00636 SPIWait(); 00637 00638 for (c=0;c<32;c++){ 00639 SPIPutCharWithoutWaiting(*dataBufPtr++); 00640 SPIPutCharWithoutWaiting(*dataBufPtr++); 00641 SPIPutCharWithoutWaiting(*dataBufPtr++); 00642 SPIPutCharWithoutWaiting(*dataBufPtr++); 00643 SPIPutCharWithoutWaiting(*dataBufPtr++); 00644 SPIPutCharWithoutWaiting(*dataBufPtr++); 00645 SPIPutCharWithoutWaiting(*dataBufPtr++); 00646 SPIPutCharWithoutWaiting(*dataBufPtr++); 00647 SPIPutCharWithoutWaiting(*dataBufPtr++); 00648 SPIPutCharWithoutWaiting(*dataBufPtr++); 00649 SPIPutCharWithoutWaiting(*dataBufPtr++); 00650 SPIPutCharWithoutWaiting(*dataBufPtr++); 00651 SPIPutCharWithoutWaiting(*dataBufPtr++); 00652 SPIPutCharWithoutWaiting(*dataBufPtr++); 00653 SPIPutCharWithoutWaiting(*dataBufPtr++); 00654 SPIPutCharWithoutWaiting(*dataBufPtr++); 00655 } 00656 //ConsolePutChar('-'); 00657 00658 c = SPIGetChar(); //crc 1st byte (sends 0xff) 00659 c = SPIGetChar(); //crc 2nd byte (sends 0xff) 00660 c = SPIGetChar(); 00661 //ConsolePutHex8(c); //This prints xxx00101, (usually e5) when data ok 00662 00663 // while (SPIGetChar()!=0xff) //busy wait moved to mmcCommand 00664 // ; // Wait until MMC not busy. 00665 00666 #ifdef MMCDEBUG 00667 ConsoleWrite("W>"); 00668 #endif 00669 00670 00671 SPI8Clocks(16); 00672 MMCDeselect(); 00673 SPI8Clocks(16); 00674 00675 //RED_LED = LED_OFF; 00676 00677 return 0; 00678 }
|
Here is the call graph for this function: