Write/Read multiple blocks to SD card

Go To Last Post
15 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

Has anyone here been able to read and write to an SD card using multiple block transfers? I have been trying to modify the Atmel Software Framework to achieve it but haven't been able to. It doesn't seem very complicated but for some reason I can't make it work. Could someone give some advice or share some sample code showing the timings and commands?

Thanks in advance.

Daniel
www.weartech.es

Daniel Campora http://www.wipy.io

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In short:

Read one block:
1. SPI select card
2. Poll card for 0xFF (wait until not busy)
3. Multiply block address by 512 if card is not SDHC 
4. Send READ_SINGLE_BLOCK command to card with address etc
5. Poll card for 0x00 (OK response to command)
6. Poll card for 0xFE (data token)
7. Receive the 512 bytes.
8. (dummy) receive 2 CRC bytes
9. SPI deselect card 

Read multiple blocks is same as above except:
4. Send READ_MULTIPLE_BLOCK command to card with address, number of blocks etc
Repeat for number of blocks {
6. Poll card for 0xFE (data token)
7. Receive the 512 bytes.
8. (dummy) receive 2 CRC bytes
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Heihopp, I will try that. What about writing multiple blocks? Have you done it before?

Daniel Campora http://www.wipy.io

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks. I have already read those documents and I am following the steps as explained but still no luck...

Daniel Campora http://www.wipy.io

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My main problem now is that the card accpets the first block but rejects the second one. After accepting the first block I wait until the card is not busy and then send a new multiple_block_write token followed by the data block, so it should be working, but is not....

Daniel Campora http://www.wipy.io

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are you sure the card expect the multiple_block_write command for each block? It does not use the command this way for reading multiple blocks, but i am unsure about write...

Its seems in both cases (read_multiple or write_multiple), the card gets a single command and starts sending/receiving the data packets followed by CRC's, then the user must stop the transfer by sending a stop command. I forgot about the stop command in the above listing (it is IDE and compact flash that use number of blocks and no stop command).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Also check that CRC check is switched off in the card, it is a separate command to switch it off, but i guess it is off by default when you initialize it to SPI.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes I am sure the card expects the multiple block token before every block, at least it is specified that way in the sd card documentation and that is also the way Chan is doig it.

Daniel Campora http://www.wipy.io

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

danicampora wrote:
Yes I am sure the card expects the multiple block token before every block, at least it is specified that way in the sd card documentation and that is also the way Chan is doig it.

There is a command "CMD25" (WRITE_MULTIPLE_BLOCK) in front, then the packets seems to be handled without further commands but the stop command, see the attached figure

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

I am now able to write multiple blocks. The data write token must be sent before every packet. I am attaching my modified sd_mmc_spi.c and sd_mmc_spi.h files. File transfers to a mass storage device are now 2.5x faster than before. The bottleneck here is the USB full speed connection, but people using the high speed USB of the UC3A3 will be able to reach much higher writing speeds.

Attachment(s): 

Daniel Campora http://www.wipy.io

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Good. What transfer speed do you get (kB/sec)?

Did you add the pdca code to the write function or was it already there?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I added the PDCA code myself. Writing speed is around 500KB/s, as I said before the bottleneck is the USB full speed (12Mbits/second). Increasing the number ob blocks per transfer above 16 doesn't improve the overall speed.

Daniel Campora http://www.wipy.io

Last Edited: Tue. Mar 1, 2011 - 07:50 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

I added a routine to read multiple blocks using the PDCA. The TX channel is sending data from the MCU flash... I had to set the pointer to flash address 0x80038000 (I am using the AT32UC3B0256) otherwise the RX channel received corrupted data, I still don´t know why, but when using a flash an address where there is no code or data it works. I tried with ram buffers, and const buffers in flash and always received corrupted data. Does anyone have an explanation for this?

Attachment(s): 

Daniel Campora http://www.wipy.io

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This function also needs the following mod:

void sd_mmc_spi_read_multiple_sector_callback(const void *psector, unsigned char ucNbrSectors)
{
U16 data_to_transfer = MMC_SECTOR_SIZE * ucNbrSectors;

while (data_to_transfer)
{
while (!Is_usb_in_ready(g_scsi_ep_ms_in));

Usb_reset_endpoint_fifo_access(g_scsi_ep_ms_in);
data_to_transfer = usb_write_ep_txpacket(g_scsi_ep_ms_in, psector,
data_to_transfer, &psector);
Usb_ack_in_ready_send(g_scsi_ep_ms_in);
}
}

Th same goes for the usb write callback...

Daniel Campora http://www.wipy.io