Пример #1
0
unsigned char mmc_GoIdle()
{
  unsigned char response=0x01;
  CS_LOW();

  //Send Command 0 to put MMC in SPI mode
  mmcSendCmd(MMC_GO_IDLE_STATE,0,0x95);
  //Now wait for READY RESPONSE
  if((mmc_error = mmcGetResponse())!=0x01)
  {
    CS_HIGH();
    return MMC_INIT_ERROR;
  }

  while(response==0x01)
  {
    CS_HIGH();
    spiSendByte(0xff);
    CS_LOW();
    mmcSendCmd(MMC_SEND_OP_COND,0x00,0xff);
    response=mmcGetResponse();
  }
  CS_HIGH();
  spiSendByte(0xff);
  return MMC_SUCCESS;
}
Пример #2
0
// Reading the contents of the CSD and CID registers in SPI mode is a simple
// read-block transaction.
char mmcReadRegister (const char cmd_register, const unsigned char length, unsigned char *pBuffer)
{
  char uc;
  char rvalue = MMC_TIMEOUT_ERROR;

  if (mmcSetBlockLength (length) == MMC_SUCCESS)
  {
    MMC_CS_LOW ();
    mmcSendCmd(cmd_register, 0x000000, 0xff);	// CRC not used: 0xff as last byte
    if (mmcGetResponse() == 0x00) {	// Wait for R1 response (0x00 = OK)
      if (mmcGetXXResponse(0xfe)== 0xfe)
        for (uc = 0; uc < length; uc++)
          pBuffer[uc] = spiSendByte(DUMMY_CHAR);
      // get CRC bytes (not really needed by us, but required by MMC)
      spiSendByte(DUMMY_CHAR);
      spiSendByte(DUMMY_CHAR);
      rvalue = MMC_SUCCESS;
    }
    else
      rvalue = MMC_RESPONSE_ERROR;
    MMC_CS_HIGH ();

    spiSendByte(DUMMY_CHAR);	 // Send 8 Clock pulses of delay.
  }
  MMC_CS_HIGH ();
  return rvalue;
} // mmc_read_register
Пример #3
0
// Reading the contents of the CSD and CID registers in SPI mode is a simple
// read-block transaction.
unsigned char mmcReadRegister (const char cmd_register, const unsigned char length, unsigned char *pBuffer)
{
  unsigned char uc = 0;
  unsigned char rvalue = MMC_TIMEOUT_ERROR;

  if (mmcSetBlockLength (length) == MMC_SUCCESS)
  {
    CS_LOW ();
    // CRC not used: 0xff as last byte
    mmcSendCmd(cmd_register, 0x000000, 0xff);

    // wait for response
    // in the R1 format (0x00 is no errors)
    if (mmcGetResponse() == 0x00)
    {
      if (mmcGetXXResponse(0xfe)== 0xfe)
        for (uc = 0; uc < length; uc++)
          pBuffer[uc] = spiSendByte(0xff);  //mmc_buffer[uc] = spiSendByte(0xff);
      // get CRC bytes (not really needed by us, but required by MMC)
      spiSendByte(0xff);
      spiSendByte(0xff);
      rvalue = MMC_SUCCESS;
    }
    else
      rvalue = MMC_RESPONSE_ERROR;
    // CS = HIGH (off)
    CS_HIGH ();

    // Send 8 Clock pulses of delay.
    spiSendByte(0xff);
  }
  CS_HIGH ();
  return rvalue;
} // mmc_read_register
Пример #4
0
// set blocklength 2^n
char mmcSetBlockLength (const unsigned long blocklength)
{
  char response;

  MMC_CS_LOW ();
  mmcSendCmd(MMC_SET_BLOCKLEN, blocklength, 0xFF);	  // Set the block length to read
  response=mmcGetResponse(); // Test response =  0x00 (R1 OK format)
  MMC_CS_HIGH ();
  spiSendByte(DUMMY_CHAR); 	// Send 8 Clock pulses of delay.
  return response;
} // Set block_length
Пример #5
0
// set MMC in Idle mode
char mmcGoIdle() {
  int i;
  char response = 0x01;

  //Send Command 0 to put MMC in SPI mode
  MMC_CS_LOW();
  mmcSendCmd(MMC_GO_IDLE_STATE,0,0x95);

  //Now wait for READY RESPONSE
  if(mmcGetResponse()!=0x01){
	MMC_CS_HIGH();
    return MMC_INIT_ERROR;
  }
  // This timeout has been extended (transcend cards have i = 250-350 on init)
  for(i = 0; response == 0x01 && i<=1000; i++)
  {
    MMC_CS_HIGH();
    spiSendByte(DUMMY_CHAR);
    MMC_CS_LOW();
    mmcSendCmd(MMC_SEND_OP_COND,0x00,0xff);
    response = mmcGetResponse();
  }
  MMC_CS_HIGH();

  spiSendByte(DUMMY_CHAR);
  setUCB0Baud(MMC_DEF_BAUD, mmcID);

  switch(response){
    case 0:
	  return MMC_SUCCESS;
    case 1:
	  return MMC_TIMEOUT_ERROR;
    default:
	  return MMC_OTHER_ERROR;
  }
}
Пример #6
0
//--------------- set blocklength 2^n ------------------------------------------------------
char mmcSetBlockLength (const unsigned long blocklength)
{
  //  char rValue = MMC_TIMEOUT_ERROR;
  //  char i = 0;
  // SS = LOW (on)
  CS_LOW ();
  // Set the block length to read
  //MMC_SET_BLOCKLEN =CMD16
  mmcSendCmd(MMC_SET_BLOCKLEN, blocklength, 0xFF);

  // get response from MMC - make sure that its 0x00 (R1 ok response format)
  if(mmcGetResponse()!=0x00)
  { initMMC();
    mmcSendCmd(MMC_SET_BLOCKLEN, blocklength, 0xFF);
    mmcGetResponse();
  }

  CS_HIGH ();

  // Send 8 Clock pulses of delay.
  spiSendByte(0xff);

  return MMC_SUCCESS;
} // Set block_length
Пример #7
0
char mmcMountBlock(unsigned long address)
{
  char rvalue = MMC_RESPONSE_ERROR;
  
  // Set the block length to read
  if (mmcSetBlockLength (512) == MMC_SUCCESS)   // block length could be set
  {
    // SS = LOW (on)
    CS_LOW ();
    // send read command MMC_READ_SINGLE_BLOCK=CMD17
    mmcSendCmd (MMC_READ_SINGLE_BLOCK, address, 0xFF);
    // Send 8 Clock pulses of delay, check if the MMC acknowledged the read block command
    // it will do this by sending an affirmative response
    // in the R1 format (0x00 is no errors)
    if (mmcGetResponse() == 0x00)
    {
      // now look for the data token to signify the start of
      // the data
      if (mmcGetXXResponse(MMC_START_DATA_BLOCK_TOKEN) == MMC_START_DATA_BLOCK_TOKEN)
      {
         //success, data ready to read
         rvalue = MMC_SUCCESS;
      }
      else
      {
        // the data token was never received
        rvalue = MMC_DATA_TOKEN_ERROR;      // 3
        CS_HIGH ();
        spiSendByte(0xff);
      }
    }
    else
    {
      // the MMC never acknowledge the read command
      rvalue = MMC_RESPONSE_ERROR;          // 2
      CS_HIGH ();
      spiSendByte(0xff);
    }
  }
  else
  {
    rvalue = MMC_BLOCK_SET_ERROR;           // 1
    CS_HIGH ();
    spiSendByte(0xff);
  }
    return rvalue;
}// mmc_read_block
Пример #8
0
// read a size Byte big block beginning at the address.
char mmcReadBlock(const unsigned long address, const unsigned long count, unsigned char *pBuffer) {
  char rvalue = MMC_RESPONSE_ERROR;

  // Set the block length to read
  if (mmcSetBlockLength (count) == MMC_SUCCESS) {   // Attempt to set block length
    MMC_CS_LOW ();
    // send read command MMC_READ_SINGLE_BLOCK=CMD17
    mmcSendCmd (MMC_READ_SINGLE_BLOCK,address, 0xFF);
    // Send 8 Clock pulses of delay, check if the MMC acknowledged the read block command
    // it will do this by sending an affirmative response
    // in the R1 format (0x00 is no errors)
    if (mmcGetResponse() == 0x00) {
      // Look for the data token to signify the start of data
      if (mmcGetXXResponse(MMC_START_DATA_BLOCK_TOKEN) == MMC_START_DATA_BLOCK_TOKEN) {
        // Clock the actual data transfer and receive the bytes; spi_read automatically finds the Data Block
        spiReadFrame(pBuffer, count);
        // Get CRC bytes (not really needed by us, but required by MMC)
        spiSendByte(DUMMY_CHAR);
        spiSendByte(DUMMY_CHAR);
        rvalue = MMC_SUCCESS;
      }
      else { // The data token was never received
        rvalue = MMC_DATA_TOKEN_ERROR;      // 3
      }
    }
    else {   // The MMC never acknowledge the read command
      rvalue = MMC_RESPONSE_ERROR;          // 2
    }
  }
  else {	// The block length was not set correctly
    rvalue = MMC_BLOCK_SET_ERROR;           // 1
  }
  MMC_CS_HIGH ();
  spiSendByte(DUMMY_CHAR);
  return rvalue;
}// mmc_read_block
Пример #9
0
unsigned long mmcReadCardSize(void)
{
  // Read contents of Card Specific Data (CSD)
  int timeout = 0;
  unsigned long MMC_CardSize;
  unsigned short i,      // index
                 j,      // index
                 b,      // temporary variable
                 response,   // MMC response to command
                 mmc_C_SIZE;

  unsigned char mmc_READ_BL_LEN,  // Read block length
                mmc_C_SIZE_MULT;

  MMC_CS_LOW ();

  spiSendByte(MMC_READ_CSD);   // CMD 9
  for(i=4; i>0; i--) spiSendByte(0);  // Send four dummy byte
  spiSendByte(DUMMY_CHAR);   // Send CRC byte (why not just add one more byte above????)

  response = mmcGetResponse();
  b = spiSendByte(DUMMY_CHAR);   // data transmission always starts with 0xFE
  if(!response) {	// Response != 0xFF
    while (b != 0xFE ){
    	 b = spiSendByte(DUMMY_CHAR);
    	 if (timeout++ >= 150)
    	 	return 0;
    }
    // bits 127:87
    for(j=5; j>0; j--)          // Host must keep the clock running for at ?????
      b = spiSendByte(DUMMY_CHAR);

    // 4 bits of READ_BL_LEN
    // bits 84:80
    b =spiSendByte(DUMMY_CHAR);  // lower 4 bits of CCC and
    mmc_READ_BL_LEN = b & 0x0F;
    b = spiSendByte(DUMMY_CHAR);
    // bits 73:62  C_Size
    // xxCC CCCC CCCC CC
    mmc_C_SIZE = (b & 0x03) << 10;
    b = spiSendByte(DUMMY_CHAR);
    mmc_C_SIZE += b << 2;
    b = spiSendByte(DUMMY_CHAR);
    mmc_C_SIZE += b >> 6;
    // bits 55:53
    b = spiSendByte(DUMMY_CHAR);
    // bits 49:47
    mmc_C_SIZE_MULT = (b & 0x03) << 1;
    b = spiSendByte(DUMMY_CHAR);
    mmc_C_SIZE_MULT += b >> 7;
    // bits 41:37
    b = spiSendByte(DUMMY_CHAR);
    b = spiSendByte(DUMMY_CHAR);
    b = spiSendByte(DUMMY_CHAR);
    b = spiSendByte(DUMMY_CHAR);
    b = spiSendByte(DUMMY_CHAR);
  }

  for(j=4; j>0; j--)          // Host must keep the clock running for at
    b = spiSendByte(DUMMY_CHAR);  // least Ncr (max = 4 bytes) cycles after
                               // the card response is received
  b = spiSendByte(DUMMY_CHAR);
  MMC_CS_LOW ();

  MMC_CardSize = (mmc_C_SIZE + 1);
  // power function with base 2 is better with a loop
  // i = (pow(2,mmc_C_SIZE_MULT+2)+0.5);
  for(i = 2,j=mmc_C_SIZE_MULT+2; j>1; j--)
    i <<= 1;
  MMC_CardSize *= i;
  // power function with base 2 is better with a loop
  //i = (pow(2,mmc_READ_BL_LEN)+0.5);
  for(i = 2,j=mmc_READ_BL_LEN; j>1; j--)
    i <<= 1;
  MMC_CardSize *= i;

  return (MMC_CardSize);
}
Пример #10
0
unsigned char mmcReadBlock(const unsigned long address, const unsigned long count, unsigned char *pBuffer)
{
  unsigned long i = 0;
  unsigned char rvalue = MMC_RESPONSE_ERROR;

  // Set the block length to read
  if (mmcSetBlockLength (count) == MMC_SUCCESS)   // block length could be set
  {
    // SS = LOW (on)
    CS_LOW ();
    // send read command MMC_READ_SINGLE_BLOCK=CMD17
    mmcSendCmd (MMC_READ_SINGLE_BLOCK,address, 0xFF);
    // Send 8 Clock pulses of delay, check if the MMC acknowledged the read block command
    // it will do this by sending an affirmative response
    // in the R1 format (0x00 is no errors)
    if (mmcGetResponse() == 0x00)
    {
      // now look for the data token to signify the start of
      // the data
      mmc_error = mmcGetXXResponse(MMC_START_DATA_BLOCK_TOKEN);
      if (mmc_error == MMC_START_DATA_BLOCK_TOKEN)
//      if (mmcGetXXResponse(MMC_START_DATA_BLOCK_TOKEN) == MMC_START_DATA_BLOCK_TOKEN)
      {
#ifndef withDMA
        // clock the actual data transfer and receive the bytes; spi_read automatically finds the Data Block
        for (i = 0; i < count; i++)
          pBuffer[i] = spiSendByte(0xff);   // is executed with card inserted
#else
        U1IFG &= ~(URXIFG1 + URXIFG1);      /* clear flags */
        /* Get the block */
        /* DMA trigger is UART1 receive for both DMA0 and DMA1 */
        DMACTL0 &= ~(DMA0TSEL_15 | DMA1TSEL_15);
        DMACTL0 |= (DMA0TSEL_9 | DMA1TSEL_9);
        /* Source DMA address: receive register.  */
        DMA0SA = U1RXBUF_;
        /* Destination DMA address: the user data buffer. */
        DMA0DA = (unsigned short)pBuffer;
        /* The size of the block to be transferred */
        DMA0SZ = count;
        /* Configure the DMA transfer*/
        DMA0CTL =
          DMAIE   |                         /* Enable interrupt */
          DMADT_0 |                         /* Single transfer mode */
          DMASBDB |                         /* Byte mode */
          DMAEN |                           /* Enable DMA */
          DMADSTINCR1 | DMADSTINCR0;        /* Increment the destination address */

        /* We depend on the DMA priorities here.  Both triggers occur at
           the same time, since the source is identical.  DMA0 is handled
           first, and retrieves the byte.  DMA1 is triggered next, and
           sends the next byte. */
        /* Source DMA address: constant 0xFF (don't increment)*/
        DMA1SA = U1TXBUF_;
        /* Destination DMA address: the transmit buffer. */
        DMA1DA = U1TXBUF_;
        /* Increment the destination address */
        /* The size of the block to be transferred */
        DMA1SZ = count-1;
        /* Configure the DMA transfer*/
        DMA1CTL =
          DMADT_0 |                         /* Single transfer mode */
          DMASBDB |                         /* Byte mode */
          DMAEN;                            /* Enable DMA */

        /* Kick off the transfer by sending the first byte */
        U1TXBUF = 0xFF;
//      while (DMA0CTL & DMAEN) _NOP(); //LPM0;  // wait till done
//      while (DMA0CTL & DMAEN) _EINT(); LPM0;  // wait till done
        _EINT(); LPM0;  // wait till done
#endif
        // get CRC bytes (not really needed by us, but required by MMC)
        spiSendByte(0xff);
        spiSendByte(0xff);
        rvalue = MMC_SUCCESS;
      }
      else
      {
        // the data token was never received
        rvalue = MMC_DATA_TOKEN_ERROR;      // 3
      }
    }
    else
    {
      // the MMC never acknowledge the read command
      rvalue = MMC_RESPONSE_ERROR;          // 2
    }
  }
  else
  {
    rvalue = MMC_BLOCK_SET_ERROR;           // 1
  }
  CS_HIGH ();
  spiSendByte(0xff);
  return rvalue;
}// mmc_read_block