cancel
Showing results for 
Search instead for 
Did you mean: 

Bug for large SD cards in SDIO library code

infoinfo989
Associate III
Posted on June 01, 2011 at 22:33

FYI, there's a bug in the SDIO standard peripheral library code when dealing with SD cards greater than 4 GB in size.

The problem is the library code uses a parameter called ''address'' or similar in several of its functions. This parameter is of type uint32_t, which means it has a maximum value of 4 GB. Hence it can overflow for cards of greater than 4 GB capacity.

You can see this parameter in the following 5 functions:

SD_ReadBlock (uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize)

SD_ReadMultiBlocks (uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize, uint32_t NumberOfBlocks)

SD_WriteBlock(uint8_t *writebuff, uint32_t WriteAddr, uint16_t BlockSize)

SD_WriteMultiBlocks (uint8_t *writebuff, uint32_t WriteAddr, uint16_t BlockSize, uint32_t NumberOfBlocks)

SD_Erase(uint32_t startaddr, uint32_t endaddr)

Each of these functions takes the address, and divides it by 512 to create a sector number (block number) for use with large cards. Given that small cards are pretty much gone these days, one easy solution is simply to ''redefine'' the address parameter to be a sector parameter. That's what we've done, although this might not work for everyone.

It also crops up in:

SD_GetCardInfo(SD_CardInfo *cardinfo)

where cardinfo->CardCapacity is calculated; again this can overflow because it currently expresses card capacity in bytes into a uint32_t field. Leaving this in sectors (blocks) might make more sense if you're not concerned about small cards.

Hope this helps someone.

#sdio-standard-peripheral-library-stm32
10 REPLIES 10
Andrew Neil
Evangelist II
Posted on June 01, 2011 at 23:06

Is that actually a bug, or is it a stated limitation?

xzhang2
Associate II
Posted on June 01, 2011 at 23:18

Which version of library are you using? V3.5?

infoinfo989
Associate III
Posted on June 02, 2011 at 00:19

I don't believe it's a stated limitation - certainly it's not stated anywhere I've seen.

I'm using whatever the latest version is - I downloaded it off the ST website only about 3 weeks ago. From the file header:

@version V4.6.1

@date    18-April-2011

John F.
Senior
Posted on June 02, 2011 at 11:53

http://en.wikipedia.org/wiki/Secure_Digital#Compatibility_issues_with_4.C2.A0GB_and_larger_cards

discusses this. Any use to you?

infoinfo989
Associate III
Posted on June 03, 2011 at 22:25

We've no problem handling larger cards. I have a 16 GB card in the system right now, and I'm planning to find a 64 GB SDXC card at some point to do some testing with. I'm simply trying to point out that a 32-bit address field can only address 4 GB. 2^32 = 4GB. Beyond that it overflows. That's all. The cards themselves have no problems - they report size in sectors (512 bytes per sector) hence 2^32 sectors = 2 TB. It's just the library code that's trying to do things in bytes.

Gawie
Associate II
Posted on June 07, 2011 at 19:36

Thanks Frank for warning us about this ugly gotcha. This is also true for the just released SDIO library for the new STM32F2xx series.

I want to add that I came across another funny in the SDIO library for the new STM32F2xx series - Read and Write is working for 4GB cards, but not for 2GB cards. After a comparison with the STM32F10x SDIO library I found that the block size was not set prior to issue a Read or Write command. Adding it fixed my issues with 2GB Cards and it did not break anything when using a 4GB.

Anybody experienced the same?

Cheers,

Gawie

infoinfo989
Associate III
Posted on June 15, 2011 at 04:15

Well, this might as well be the place for other problems in the library SDIO code as well. This one isn't specific to large cards.

The problem is that in the stm32_eval_sdio_cd.c file, there are a whole bunch of timeouts which can timeout much faster than you'd expect. Resulting in functions timing out before the hardware function has had a chance to do its thing. For example:

static SD_Error CmdError(void)

{

  SD_Error errorstatus = SD_OK;

  uint32_t timeout;

  timeout = SDIO_CMD0TIMEOUT; /*!< 10000 */

  while ((timeout > 0) && (SDIO_GetFlagStatus(SDIO_FLAG_CMDSENT) == RESET))

  {

    timeout--;

  }

The problem with this timeout is there's no way to know what the compiler might do with it. It can potentially optimise it away completely! Making the ''timeout'' variable volatile will probably help, but isn't an ideal solution.

This is just a heads-up. These timeouts have been tripping in our code, causing errors to be generated that aren't actually correct. Whatever method you have for measuring time (like using one of the timer peripherals for example) would be a better choice than the simple loop counters used here.

jgreen
Associate
Posted on October 03, 2011 at 13:49

I am currently experiencing a problem with reading and writing to 2gb micro sd cards using the STM32F2xx series library. Its the only size i have right now so i can't test it with anything else until tomorrow to prove the problem is exclusive to that size card. Could you give me any more details on how you managed to over come this problem?

Regards

James

infoinfo989
Associate III
Posted on October 04, 2011 at 05:35

Yoou're going to have to be a lot more specific than just saying you're ''experiencing a problem'' if you're wanting any specific help.

I'd assume you're accessing the card in 4-bit parallel mode, and not SPI mode, seeing as you say you're using the ST libraries.

Do you have a level converter between the card and your processor? If so, try running at a slower SDIO clock speed and see if that helps.

The ST library code is riddled with problems, as discussed in this thread. The timeouts can, and do, timeout prematurely, generating errors when none should exist. You need to replace them with a timeout system of your own making (normally you'd have a timebase of some type already in the system, if not, take a look at the timer examples in the ST library).

For a 2 GB SD card, as was stated earlier, you may need to issue a blocksize command (CMD16) to the card, to tell it your blocksize is 512 bytes. I haven't personally seen this problem, but obviously other people have.

The library code doesn't pick up on a lot of errors. For example, the card can sometimes not be ready to accept data but the library code can try to write to it anyway, because it doesn't realise, resulting in write errors and timeouts.

Card initialisation can be a challenge - this was discussed in another thread on this board somewhere (but good luck using the search function to find it). The essence of it was, before doing the card initialisations, set the SDIO GPIO pins to be outputs and set them high, to present an idle state to the card, for a few milliseconds. Then do the SDIO initialisations (including changing the pins to their alternate function, in this case SDIO). This helped me a lot.

At the end of the day, you need to take the attitude that the ST SDIO library code is only example code, to give you a flavour of how to do it. For real-world, reliable, production code you're going to need to write it yourself.