# SDXC Card Reader with LPC1822

in my application I have an SD Card reader using the NXP LPC1822 microcontroller. It works very good with all SD- and SDHC-Cards I've tested so far. Only thing that does not work is SDXC.

I already contacted some Distributor and NXP FAEs about that problem, but all they could say was "We haven't tried SDXC on a microcontroller yet". So first question: Is there someone in the SE Universe which did that already? Doesn't matter if with NXP or others.

It is basically a "dumb" SD Card reader. I only tunnel requests coming from a windows 7 machine over USB (MassStorageDevice of LPCUSBLib) and SCSI to the SD Card Interface. Any data requested I tunnel back over USB to the host. So no FAT file system or any data handling on my controller. Just shovelling masses of bytes. I use LPCOpen (heavily modified to get better performance) to talk to the SD Card interface. This works perfectly as already told.

When I plug in a 64 GB SDXC card, it gets enumerated and is displayed in the windows explorer as an unformatted SDHC card with 32 GB. If I format it, I get a normally usable 32GB SDHC Card out of it.

Next Question:

I am no member of the SD Association, so the only thing I have is the simplified spec. And this does not say anything about SDXC. Because of the behaviour stated above I wonder if there are some obscure status bit flags which identify a card to be sdxc? there is such a bit for sdhc, but I can not find anything about xc.

64 GB SDXC card, it gets enumerated and is displayed in the windows explorer as an unformatted SDHC card with 32 GB [...]

Check the USB Mass storage code. There might be another limit.

[...] simplified spec. And this does not say anything about SDXC

Download an updated copy from sdcard.org. Newer versions have infos about SDXC in them.

• Already changed the mass storage code, initially it worked just upt to 4 GB, but i'll take another look. Even in the online version of the simplified spec I haven't found anything useful. There are remarks about sdxc, but mostly over some speedups that I don't need. Have you something specific in mind? – jwsc May 7 '15 at 14:12
• I checked the sdmmc driver again. As I should have expected, all the havoc about sdxc is caused by a bug. Fixed it, now sdxc works basically. Very slow in writing, don't know why, but it works. I hate NXP libs. Will check with my customer if I am allowed to publish my bugfix. If I can, I will post it here. Thank you for your remark with checking the spec, this basically pointed me to the bug. – jwsc May 11 '15 at 11:29

I checked with my cusomer, I am allowed to post the bug.

SDXC functionality with the LPCOpen drivers and LPC18xx/LPC43xx suffers from a bug in sdmmc_18xx_43xx.c. I found the same bug also in the implementations for LPC17xx, so it's safe to assume NXP has that problem in all implementations of SD-Card Interfaces. Current release of LPCOpen which I am looking at is 2.15 for LPC18xx.

Around line 228 in sdmmc_18xx_43xx.c there is this:

c_size = prv_get_bits(48, 63, (uint32_t *) g_card_info->card_info.csd) + 1;


This should extract size information from the SD-Card CSD register. According to the SD Specifications Part 1 Physical Layer Simplified Specification Version 4.10, on page 122:

the C_SIZE information spans not from bit 48 to bit 63. It spans from bit 48 to bit 69. This means, the NXP Lib cuts away the higher bits of the size information. This works fine for SD Cards up to 32 GB, but if you have bigger cards you get an truncated size which leads the Windows driver to the assumption that something has to be wrong with the card.

If you change the above line 228 in sdmmc_18xx_43xx.c to the following, bigger SD-Cards do also work fine:

c_size = prv_get_bits(48, 69, (uint32_t *) g_card_info->card_info.csd) + 1; //BUGFIX


Fix your Software, NXP!

EDIT:

Due to request, I'll show another bug in the lib: the Chip_SDMMC_GetDeviceSize() function returns a signed 32-bit integer. This integer will overflow with cards bigger than 4GB. A workaround would be changing the return value to unsigned 64-bits, or only using Chip_SDMMC_GetDeviceBlocks().