// 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
// 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
//char mmcWriteBlock (const unsigned long address) char mmcWriteBlock (const unsigned long address, const unsigned long count, unsigned char *pBuffer) { char rvalue = MMC_RESPONSE_ERROR; // MMC_SUCCESS; if (mmcSetBlockLength (count) == MMC_SUCCESS) { // Set the block length to read MMC_CS_LOW (); mmcSendCmd (MMC_WRITE_BLOCK,address, 0xFF); // Send write command // Check if the MMC acknowledged the write block command // it will do this by sending an affirmative response // in the R1 format (0x00 is no errors) if (mmcGetXXResponse(MMC_R1_RESPONSE) == MMC_R1_RESPONSE) { spiSendByte(DUMMY_CHAR); spiSendByte(0xfe); // Send the data token to signify the start of the data spiSendFrame(pBuffer, count); // Clock the actual data transfer and transmit the bytes // Put CRC bytes (not really needed by us, but required by MMC) spiSendByte(DUMMY_CHAR); spiSendByte(DUMMY_CHAR); // Read the data response xxx0<status>1 // Status = 010: Data accepted // Status 101: Data rejected due to a CRC error // Status 110: Data rejected due to a write error. rvalue = mmcCheckBusy(); if(rvalue==MMC_SUCCESS) { // check status after write for any possible errors during write (see sandisk.pdf, p.63) MMC_CS_HIGH(); spiSendByte(DUMMY_CHAR); MMC_CS_LOW(); mmcSendCmd(MMC_SEND_STATUS, 0, 0xFF); if (mmcGetR2Response() != 0x0000) { rvalue = MMC_WRITE_ERROR; } } } else { // The MMC never acknowledge the write command rvalue = MMC_RESPONSE_ERROR; // 2 } } else { rvalue = MMC_BLOCK_SET_ERROR; // 1 } MMC_CS_HIGH(); spiSendByte(DUMMY_CHAR); // Send 8 Clock pulses of delay. return rvalue; } // mmc_write_block
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
// 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
//--------------------------------------------------------------------- //char mmcWriteBlock (const unsigned long address) unsigned char mmcWriteBlock (const unsigned long address, const unsigned long count, unsigned char *pBuffer) { unsigned long i = 0; unsigned char rvalue = MMC_RESPONSE_ERROR; // MMC_SUCCESS; // char c = 0x00; // Set the block length to read if (mmcSetBlockLength (count) == MMC_SUCCESS) // block length could be set { // SS = LOW (on) CS_LOW (); // send write command mmcSendCmd (MMC_WRITE_BLOCK,address, 0xFF); // check if the MMC acknowledged the write block command // it will do this by sending an affirmative response // in the R1 format (0x00 is no errors) if (mmcGetXXResponse(MMC_R1_RESPONSE) == MMC_R1_RESPONSE) { spiSendByte(0xff); // send the data token to signify the start of the data spiSendByte(0xfe); // clock the actual data transfer and transmitt the bytes #ifndef withDMA for (i = 0; i < count; i++) spiSendByte(pBuffer[i]); #else /* Get the block */ /* DMA trigger is UART send */ DMACTL0 &= ~(DMA0TSEL_15); DMACTL0 |= (DMA0TSEL_9); /* Source DMA address: the data buffer. */ DMA0SA = (unsigned short)pBuffer; /* Destination DMA address: the UART send register. */ DMA0DA = U1TXBUF_; /* The size of the block to be transferred */ DMA0SZ = count; /* Configure the DMA transfer*/ DMA0CTL = DMAREQ | /* start transfer */ DMADT_0 | /* Single transfer mode */ DMASBDB | /* Byte mode */ DMAEN | /* Enable DMA */ DMASRCINCR1 | DMASRCINCR0; /* Increment the source address */ #endif // put CRC bytes (not really needed by us, but required by MMC) spiSendByte(0xff); spiSendByte(0xff); // read the data response xxx0<status>1 : status 010: Data accected, status 101: Data // rejected due to a crc error, status 110: Data rejected due to a Write error. mmcCheckBusy(); rvalue = MMC_SUCCESS; } else { // the MMC never acknowledge the write command rvalue = MMC_RESPONSE_ERROR; // 2 } } else { rvalue = MMC_BLOCK_SET_ERROR; // 1 } // give the MMC the required clocks to finish up what ever it needs to do // for (i = 0; i < 9; ++i) // spiSendByte(0xff); CS_HIGH (); // Send 8 Clock pulses of delay. spiSendByte(0xff); return rvalue; } // mmc_write_block
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