⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmc.c

📁 keil lpc2138 epson6610 lcd source
💻 C
字号:
 #include "mmc.h"
 #include "board.h"
 #include "buffer.h"

 extern void SPIWait(void);


unsigned char MmcCommand(unsigned char c1, 
                         unsigned char c2, 
                          unsigned char c3, 
                         unsigned char c4, 
                        unsigned char c5){

 
  char c;

  /* Note: c1, c2 are used for temporary variables after use! */  
   //MMC_OFF = NO; //MMC should be powered, but switch power on just-in-case
  // MMC_XCS = MMC_NOT_SELECTED; //put MMC on-line.
 
  // Provide clock edges before and after asserting MMC CS
   SPI8Clocks(8); 
   IOCLR0 |= MMC_CS;
   SPI8Clocks(8);   
	   c=0;
  // If card still seems to be busy, give it some time...
   while ((SPIGetChar()!=0xff) && (c<100)){
     //ConsolePutChar('.');
     c++;
   }

  // The bus should be stable high now
   if (SPI_RESULT_BYTE != 0xff){
    //ConsoleWrite("\rUnexpected busy signal from MMC. ");
     IOSET0 |= MMC_CS; //drop MMC offline.
     return 0x81; //MMC unexpectedly Busy
   }
  
 // Send the MMC command
   SPIPutCharWithoutWaiting(c1);
   SPIPutChar(c2);
   SPIPutChar(c3);
   SPIPutChar(c4);
   SPIPutChar(c5);
   if(c1 ==0x40)
   {
  SPIPutChar(0x95); 
  }
  else 
  {	 
  SPIPutChar(0xFF);
  }								 		  
     /* Valid CRC for init, then don't care */
   SPIWait();
  /* Now ok to use c1..c5 as temporaries (dirty but kool) */  
  // Wait for R1 style response (bit 7 low) from MMC  
  
     c1=100;
     while((c1--)&&((c2=SPIGetChar())&0x80)) //wait for R1 or timeout
       ;	  
  return c2; //return the R1 response
 }


 unsigned char MmcWaitForData(void){

  unsigned char c;
    
   // Wait until something else than 0xff is read from the bus
   do {
     c=SPIGetChar(); 
   } while ((c == 0xff));
 
  // Something was received from the bus? Might it actually be te 
  // desired 0xFE data start token? 
   if (c != 0xfe){
     // No data start token, read fail. In an OS an error message would display.
    // Since we're in an embedded system, it's unclear what we should do now.
    // Current approach is to say all ok but make read block return 0xff's.
    // It's not disasterous at least as long as we don't WRITE to MMC.

    // Flush any data that might be pending from the MMC.
 
    SPI8Clocks(200); /* Flush MMC by sending lots of FF's to it */
    SPI8Clocks(200);
    SPI8Clocks(200);
    
    
    return 5; //Return error
 
   }
 
  // DebugMessage("t>"); //Exit Token Wait
   return 0;

 }
 /*
 void MmcGetData(unsigned int amountOctets){
  //DebugMessage("<G");

  dataBufPtr = diskSect.raw.buf;
   while (amountOctets--){
     *dataBufPtr++=SPIGetChar();
 }
  // DebugMessage("G>");
 }
 
  */
 
 unsigned char RebootMMC(void){
   unsigned char c;
   
	   		
   //Try (indefinitely) to switch on the MMC card
   do{
    /* MMC Don't use CRC - seems to be required by some MMC cards? */
     MmcCommand(0x7B,0,0,0,0);
    /* MMC Init, command 0x40 should return 0x01 (idle) if all is ok. */
   }while (MmcCommand(0x40,0,0,0,0)!=0x01);
   // 0x01(idle) response detected.
  
   //ConsoleWrite("Card found, starting... ");
   /*Try max 255 times MMC Wake-up call: set to Not Idle (mmc returns 0x00)*/
   c=255;
  while ((c--)&&(MmcCommand(0x41,0,0,0,16))){
     delay_ms(10);
    if (c==1){
      //timeout
     // ConsoleWrite("Failed.\r");
      return 2; /* Not able to power up mmc */
     }
   }
 
   //ConsoleWrite("Ok.\r");
   return 0;
 }


  unsigned char InitMMC(){
   unsigned char c;	
   //Delay(10);
  /* Allow MMC some time and clock cycles to reset */
   for (c=0; c<200; c++){    
     SPIPutCharWithoutWaiting(0xff);
    SPIWait();
  }
   delay_ms(20);

   if (RebootMMC()) return 1; //not able to powerup;
  //An existing MMC card should be able to respond now.
 
  		 c=MmcCommand(0x50,0,0,2,0);
  /* Set Block Size of 512 bytes (2 == 512 << 8) */
  if (c) return c|0x80; /* blocksize error */
  
 /* Check if MMC supports interrupted data transfer */
   /* This does a simple checksum check to see if interrupted and 
    * non-interrupted read blocks are the same. */
  /* This could be a function, so it is in braces for clarity purposes */
   {  
     if (SeekSector(0)) return 2; //Storage powerup failure    
    if (ReadPhysicalSector()) return 2; //Storage powerup failure
 
    tempo.i = diskSect.raw.buf[511];
    for (c=0; c<250; c++){
       tempo.i += diskSect.raw.buf[c];
   }
    
    if (SeekSector(0)) return 2;//Storage powerup failure
    
     /* Send some extra SPI clocks */
   IOSET0 |= MMC_CS;
     SPIPutCharWithoutWaiting(0xff);
     for (c=0; c<100; c++){
      SPIPutChar(0xff);
    }
    SPIWait();
    
     if (ReadPhysicalSector()){
      //ConsoleWrite("Interrupted read failed.\r");
       //ConsoleWrite("Using compatibility mode.\r");
      return 0x0e; //ok but no support for seek-before-read
      
    }else{
      //Check if received data was same
      tempo.i -= diskSect.raw.buf[511];
      for (c=0; c<250; c++){
        tempo.i -= diskSect.raw.buf[c];
       }
    }
     
    if (tempo.i) { /* Checksum does not match */
      // ConsoleWrite("This MMC has no support for interrupted read. ");
      // ConsoleWrite("Using compatibility mode.\r");
      return 0x0e; //ok but no support for seek-before-read
    }
     
     //ConsoleWrite("\rInitMMC ok.\r");
   }
 
   /* All OK return */
   return 0; //ok and MMC supports seek-before-read
 
 }	 

 void PerformBlockRead(void){	 
   /* Use shared global buffer pointer for speed*/
  /* Loop unrolled 16 times for SPEED! :) */
  dataBufPtr = diskSect.raw.buf;
   while (dataBufPtr < diskSect.raw.buf+512){
    SPIPutCharWithoutWaiting(0xff);
     SPIWait();
     *dataBufPtr++=SPI_RESULT_BYTE;
/*
     SPIPutCharWithoutWaiting(0xff);
     SPIWait();
    *dataBufPtr++=SPI_RESULT_BYTE;
     SPIPutCharWithoutWaiting(0xff);
     SPIWait();
     *dataBufPtr++=SPI_RESULT_BYTE;
    SPIPutCharWithoutWaiting(0xff);
     SPIWait();
     *dataBufPtr++=SPI_RESULT_BYTE;
     SPIPutCharWithoutWaiting(0xff);
     SPIWait();
     *dataBufPtr++=SPI_RESULT_BYTE;
     SPIPutCharWithoutWaiting(0xff);
     SPIWait();
     *dataBufPtr++=SPI_RESULT_BYTE;
     SPIPutCharWithoutWaiting(0xff);
     SPIWait();
    *dataBufPtr++=SPI_RESULT_BYTE;
     SPIPutCharWithoutWaiting(0xff);
     SPIWait();
     *dataBufPtr++=SPI_RESULT_BYTE;
*/
/*
     SPIPutCharWithoutWaiting(0xff);
     SPIWait();
    *dataBufPtr++=SPI_RESULT_BYTE;
    SPIPutCharWithoutWaiting(0xff);
     SPIWait();
    *dataBufPtr++=SPI_RESULT_BYTE;
     SPIPutCharWithoutWaiting(0xff);
     SPIWait();
     *dataBufPtr++=SPI_RESULT_BYTE;
    SPIPutCharWithoutWaiting(0xff);
    SPIWait();
     *dataBufPtr++=SPI_RESULT_BYTE;
     SPIPutCharWithoutWaiting(0xff);
     SPIWait();
     *dataBufPtr++=SPI_RESULT_BYTE;
     SPIPutCharWithoutWaiting(0xff);
    SPIWait();
     *dataBufPtr++=SPI_RESULT_BYTE;
     SPIPutCharWithoutWaiting(0xff);
     SPIWait();
     *dataBufPtr++=SPI_RESULT_BYTE;
    SPIPutCharWithoutWaiting(0xff);
     SPIWait();
     *dataBufPtr++=SPI_RESULT_BYTE;
*/
   }
   
 }
 
 
 /* Unconditionally (really just do it!) seek MMC at offset sectorN*512 */
 
 unsigned char SeekSector(unsigned long sectorN){
   
   unsigned char c;
		  
	      sectorAddress.l = sectorN * 2; //convert to bytes (combined with 8bit shift)
		    
    do{
     		 
     c=MmcCommand(0x51,sectorAddress.b.b2,sectorAddress.b.b1,
               sectorAddress.b.b0,0);	
               
          	
     sectorAddress.l = sectorAddress.l >> 1; //convert back to blocks
 
     //if MMC returs "nothing" (0xff) or 0x81(busy), 
     //toggle chip select and retry
    if ((c==0xff)||(c==0x81)){
       c=0xff;
       RebootMMC();
     }
    if (c==0x01){ //MMC says "busy"
      c=0xff; //try again
     }

   }while(c==0xff); //repeat until we get signal from MMC.
   
   if ((c & 0xfe)){ //MMC returns something else than idle or busy signal
        return 7; /* failed to execute mmc command */
   }	 
   return 0; //ok return
 }
 

 

 /* Wait for data start token and read 512 bytes to global buffer */ 
 
unsigned char ReadPhysicalSector(void){
 
//PORTBbits.RB7=1;
   IOCLR0 |= MMC_CS; 
   MmcWaitForData();
   PerformBlockRead();
 
   /* generate SPI clock edges to finish up the command */
 
   //SPI8Clocks(8); //Send 8*4=32 clocks (4 ff's) to MMC to be nice.
   //MMC_XCS = MMC_NOT_SELECTED;
   //SPI8Clocks(8); //Again, give the poor MMC some clocks, it likes them.


 //PORTBbits.RB7=0;
   return 0; //ok return
 }
 

 unsigned char WritePhysicalSector(){
   unsigned char c;  
  
   //RED_LED = LED_ON;
   sectorAddress.l = sectorAddress.l * 2; //convert to bytes (combined with 8bit shift)
   c=MmcCommand(24 | 0x40 ,sectorAddress.b.b2,sectorAddress.b.b1,
                sectorAddress.b.b0, 0);
   sectorAddress.l = sectorAddress.l >> 1; //convert back to blocks
   IOCLR0 |= MMC_CS;
 
 
  dataBufPtr = diskSect.raw.buf;
   SPIPutCharWithoutWaiting(0xFE);
   SPIWait();
   
   for (c=0;c<128;c++){
    SPIPutCharWithoutWaiting(*dataBufPtr++);   
     SPIWait();
    SPIPutCharWithoutWaiting(*dataBufPtr++);   
    SPIWait();
    SPIPutCharWithoutWaiting(*dataBufPtr++);   
   SPIWait();
    SPIPutCharWithoutWaiting(*dataBufPtr++);   
     SPIWait();
  }

   MmcWaitForData(); //Wait for 0xFE token
   while (SPIGetChar()==0) 
    ; // Wait until MMC not busy.     
   
   SPI8Clocks(16);
 IOSET0 |= MMC_CS;
  SPI8Clocks(16);
 
  //RED_LED = LED_OFF;
   return (0);
 }
 
 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -