cancel
Showing results for 
Search instead for 
Did you mean: 

eMMC 5.1 / STM32F4 Compatible?

Craig B
Associate II

Posted on January 23, 2018 at 19:55

We are looking to replace an eMMC 4.41 chip (by Micron) that we currently use with a new one SanDisk iNAND 7250-I (https://media.digikey.com/pdf/Data%20Sheets/Micron%20Technology%20Inc%20PDFs/EMMC_Series.pdf). This component can run at variable clock speeds and supports the the eMMC 5.1 standard. Has anyone tried this component or another 5.1 part with an STM32F4 successfully? Any issues or anything noteworthy?

Thanks,

Craig

12 REPLIES 12
Doug Kehn
Senior
Posted on January 24, 2018 at 14:16

I use F7 not F4 with eMMC so my comments may or may not apply.

There is no HAL support for reading the extended CSD register. The CSD register is read by the HAL.

Be cognizant of byte versus block addressing. The HAL assumes byte addressing if the size of the device is <2GB. Since the HAL only reads the CSD, it will think the device is only 1GB and use byte addressing.

Craig B
Associate II
Posted on January 24, 2018 at 18:52

Thanks Doug.  I will go back and review the CSD/Extended CSD as well as the byte vs. block addressing to see what implications they may have.  I appreciate you bringing this to my attention.

Thanks,

Craig

Jack3
Senior II

Hi Doug and Craig, this helps me understanding my problem. I exactly hit this issue. On an STM32F676ZI, I connected a Sandisk 16GB eMMC (8-bit).

The capacity read from CardInfo is 1GB (blocks * 512) and I can only access about 30MB, so this could be just byte addressing. Now I can test this soon, writing a "block" and the reading the next "block" to see if the data is also there, with 1 byte offset. (Next step)

If I multiply that ~30MB by 512 (block size) it would be nearly 16GB.

But how do I switch to block addressing mode?

Thanks,

Jack.

You need to read the EXTCSD, and stop the ST code converting to byte addressing.

Got eMMC working here thru 128GB on F4, F7 and L4 platforms, and can readily port to others.

00200000 2097152  1.00 GB GetCardCSD

00E40000  7.13 GB  7.47 GB EXTCSD

In 4-bit able to get 12.53 MBps Write, 17.96 MBps Read, observed read speed to double for 8-bit mode (on F427)

This is a 5.0 compatible part

https://www.micron.com/parts/nand-flash/managed-nand/mtfc8gakajcn-1m-wt

Worked with 4 and 8GB SanDisk parts, and 8, 64 and 128 GB Samsung

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Craig B
Associate II

Clive,

Would you be willing to share your code to read the EXTCSD register? I attempted it, and thought I was on the right path, but I must be missing something because the data I'm getting back doesn't look correct and I'm only getting 96 bytes rather then the 512 I was expecting. So any help would be greatly appreciated.

Jack and others,

One thing you can do just to get things going is to simply set the the max number of blocks and size yourself to the correct values for your eMMC like so:

MX_SDIO_MMC_Init();
hmmc.MmcCard.BlockNbr = MY_EMMC_BLOCK_COUNT;
hmmc->MmcCard.BlockSize = MY_EMMC_BLOCK_SIZE;
hmmc->MmcCard.LogBlockNbr =  (hmmc->MmcCard.BlockNbr) * ((hmmc->MmcCard.BlockSize) / 512U);

Make sure that you define MY_EMMC_BLOCK_COUNT and MY_EMMC_BLOCK_SIZE to your eMMC's respective values. There is a benefit to doing this even if you get your eMMC's max block count and size from the EXTCSD register. Throughout stm32f4xx_hal_mmc.c or your MCU's equivalent, there are numerous lines like this:

    /* Check the Card capacity in term of Logical number of blocks */
    if ((hmmc->MmcCard.LogBlockNbr) < CAPACITY)
    {
      BlockAdd *= 512U;
    }

This is the critical part where HAL converts the BlockAdd that you pass in to a byte address in various functions. CAPACITY for my project as generated by CubeMX is 0x400000U. So by setting this to the correct value for your eMMC, provided it is larger than CAPACITY, causes HAL to use Block addressing instead of byte addressing, which is what we want.

I have done this with hard coded values on my system and it works as desired with me able to use the full 8GB capacity of my eMMC (SanDisk SDINDBDG4-8G). Once I'm able to get the max block count/size from the EXTCSD register as mentioned by Clive, I will replace my hard coded values accordingly.

Thanks,

Craig

Sent you a PM, you'll likely have to dig for it as it doesn't flag under the bell icon

Need to go to Profile "My Messages"

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
MKupl
Associate

Clive,

if possible, I would also like to see your code to read EXTCSD register. I tried several approaches, but nothing seems to work.

Thank you and BR,

Matej

Craig B
Associate II

One thing I would like to point out to anyone trying to read the EXTCSD register or interacting with an eMMC with various sdio/mmc commands, that it is necessary when reading data from the FIFO to do it quickly. If you do not, you will get an RX overrun error. We are using embedded gcc and in a debug build with no optimizations, the typical code to read the data from the FIFO is not fast enough to keep up and you'll get an RX overrun. With Keil or IAR, I believe their debug builds are not as fat and slow as the gcc debug build, so this may not be an issue. I was able to solve this in my case by make just some small adjustments to the code that reads the data from the FIFO. Here's an example of a typical loop that would read data from the FIFO with my modifications:

    while (!__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND)) {
        if (__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXFIFOHF)) {
 
            /* Read data from SDMMC Rx FIFO */
            dst[0] = (hmmc->Instance->FIFO);
            dst[1] = (hmmc->Instance->FIFO);
            dst[2] = (hmmc->Instance->FIFO);
            dst[3] = (hmmc->Instance->FIFO);
            dst[4] = (hmmc->Instance->FIFO);
            dst[5] = (hmmc->Instance->FIFO);
            dst[6] = (hmmc->Instance->FIFO);
            dst[7] = (hmmc->Instance->FIFO);
            dst += 8;
        }
 
        if ((Timeout == 0U) || ((HAL_GetTick() - tickstart) >= Timeout)) {
            /* Clear all the static flags */
            __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
            hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
            return HAL_TIMEOUT;
        }
    }

The important differences in this code is that there is no pointer incrementation for each read and rather than call the function SDIO_ReadFIFO and incurring the function call overhead, we just read the value directly from hmmc->Instance->FIFO.

So if you are running into an RX overrun, perhaps this is helpful.

BTW, when I build with -O3 optimizations for a release build, I do not have the RX overrun, but it is nice to have the code work in both debug and release builds! 

Craig

ChrisH
Associate III

I'm also fighting with this problem, I managed to read EXT_CSD register issuing CMD8 and reading FIFO with DMA so I don't run into RXOVERR error. While EXT_CSD seem to have correct values after reading, SECT_SIZE is correct and others look ok. I'm performing disk test from fatfs library in order to test the driver, after writing a single block the test fails on read block when sending CMD_SET_BLOCKSIZE. Returned status is illegal command, I have no idea why is this happening, running the same test without reading ext_csd doesn't cause any failures. Is there some other step that I need to do?