2018-08-07 08:24 AM
Hi, I connected a 16GB Sandisk eMMC in 8-bit mode to an STM32F676ZI SDMMC interface.
I use HAL drivers and TrueStudio for development.
HAL_MMC_GetCardInfo returns this information:
CardType : 0
Class : 2293
RelCardAdd : 0
BlockNbr : 2097152
BlockSize : 512
LogBlockNbr : 2097152
LogBlockSize: 512
If I multiply 2097152 * 512, I get 1GB, instead of 16GB.
When I use HAL_MMC_WriteBlocks and HAL_MMC_ReadBlocks, this works well, but only up to block 60111 (~30MB). After this, bot read and rite fails, and I see HAL_MMC_ERROR_CMD_CRC_FAIL.
This is about 512 times less capacity which I can access, making me think bytes addressing was used instead of block addressing.
What went wrong?
Just in case, the CID and CSD details.
HAL_MMC_GetCardCID returns:
ManufacturerID: 45
OEM_AppliID : 100
ProdName1 : DG40
ProdName2 : 1
ProdRev : 6
ProdSN : 019B4A6F
ManufactDate : 0315
CID_CRC : 7F
HAL_MMC_GetCardCSD returns:
CSDStruct : 3
SysSpecVersion : 4
TAAC : 15
NSAC : 0
MaxBusClkFrec : 50
CardComdClasses : 2293
RdBlockLen : 9
PartBlockRead : 0
WrBlockMisalign : 0
RdBlockMisalign : 0
DSRImpl : 0
DeviceSize : 4095
MaxRdCurrentVDDMin : 7
MaxRdCurrentVDDMax : 7
MaxWrCurrentVDDMin : 7
MaxWrCurrentVDDMax : 7
DeviceSizeMul : 7
EraseGrSize : 1
EraseGrMul : 127
WrProtectGrSize : 111
WrProtectGrEnable : 1
ManDeflECC : 0
WrSpeedFact : 2
MaxWrBlockLen : 9
WriteBlockPaPartial: 0
ContentProtectAppli: 0
FileFormatGrouop : 0
CopyFlag : 1
PermWrProtect : 0
TempWrProtect : 0
FileFormat : 0
ECC : 0
CSD_CRC : 17
Some code. I use for testing:
void MX_SDMMC1_MMC_Init(void)
{
hmmc1.Instance = SDMMC1;
hmmc1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
hmmc1.Init.ClockBypass = SDMMC_CLOCK_BYPASS_DISABLE;
hmmc1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
hmmc1.Init.BusWide = SDMMC_BUS_WIDE_1B;
hmmc1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
hmmc1.Init.ClockDiv = 0;
if (HAL_MMC_Init(&hmmc1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
if (HAL_MMC_ConfigWideBusOperation(&hmmc1, SDMMC_BUS_WIDE_8B) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
uint32_t dataSize = 512; // 131072
uint32_t blockSize = 512;
uint32_t numberOfBlocks = dataSize / blockSize;
uint32_t errorState = 0;
uint32_t timeout = 1000000;
uint32_t blockAdd = 0;
uint8_t *wData = (uint8_t *) malloc(dataSize);
uint8_t *rData = (uint8_t *) malloc(dataSize);
uint32_t kB = 0;
uint32_t capacity = 32*1024*1024;
uint32_t iterations = capacity / dataSize;
printf("\n*** Reset Card...\n");
ResetCard();
GetCardState();
printf("\n*** Init Card (HAL_MMC_InitCard)...\n");
HAL_Delay(100);
errorState = HAL_MMC_InitCard(&hmmc1);
if(errorState == HAL_MMC_ERROR_NONE) {
printf("HAL_MMC_InitCard OK\n");
}
else {
printf("HAL_MMC_InitCard FAILED\n");
}
GetCardState();
GetCardErrorState(errorState);
// SDMMC_CmdBlockLength(SDMMC_TypeDef *SDMMCx, uint32_t BlockSize)
// HAL_Delay(100);
// errorstate = HAL_MMC_InitCard(&hmmc1);
printf("\n*** Get Card Info (HAL_MMC_GetCardInfo)...\n");
HAL_Delay(100);
HAL_MMC_CardInfoTypeDef pCardInfo;
errorState = HAL_MMC_GetCardInfo(&hmmc1, &pCardInfo);
// errorstate = HAL_MMC_InitCard(&hmmc1);
int status = 0;
blockAdd = 0;
for (int iteration = 0; iteration < iterations; iteration++) {
blockAdd += numberOfBlocks; // + 2097152 HAL_MMC_ERROR_CMD_CRC_FAIL
kB = blockAdd / 2;
// Write
for (int i = 0; i < dataSize; i++) {
wData[i] = (i + iteration) & 0xff;
}
errorState = HAL_MMC_WriteBlocks(&hmmc1, wData, blockAdd, numberOfBlocks, timeout);
while (HAL_MMC_GetCardState(&hmmc1) != HAL_MMC_CARD_TRANSFER) {
HAL_Delay(1);
}
HAL_Delay(50);
printf("Wr ");
for (int j = 0; j < 1; j++) {
for (int i = 0; i < 16; i++) {
printf("%02X ", wData[i+ j*16]);
}
printf("\n");
}
// Read
for (int i = 0; i < 512; i++) {
rData[i] = 0xff;
}
errorState = HAL_MMC_ReadBlocks(&hmmc1, rData, blockAdd, numberOfBlocks, timeout);
while (HAL_MMC_GetCardState(&hmmc1) != HAL_MMC_CARD_TRANSFER) {
HAL_Delay(1);
}
HAL_Delay(50);
printf("Rd ");
for (int j = 0; j < 1; j++) {
for (int i = 0; i < 16; i++) {
printf("%02X ", rData[i+ j*16]);
}
printf("\n");
}
// }
if (memcmp(wData, rData, 512) == 0) {
printf("Compare Passed. (BA: %8ld, %8ld kB) %d\n", blockAdd, kB, status);
}
else {
status = 1;
printf("Compare FAILED! (BA: %8ld, %8ld kB) %d\n", blockAdd, kB, status);
}
}
free(wData);
free(rData);
Kind regards,
Jack.
2018-08-07 11:47 AM
PD4 USART2_EN enable? active high/low ?
PD14 MMC_RST eMMC NRST pin active low?
PE11/PE13 LED High or Low ON?
2018-08-07 12:27 PM
50/50 shot that PD4 is high, if not you'll need to use the ST-LINK SWV Viewer tuned to 216 MHz to see output, otherwise USART2 at 115200 8N1
2018-08-07 12:32 PM
Hi Clive,
USART2_EN is not used.
MMC_RST eMMC is active low connected to a GPIO.
I reset during startup one time, high during operation.
PE11 LED low is on.
PE13 LED high is on.
If I comment out
if ((hmmc->MmcCard.LogBlockNbr) < CAPACITY)
{
BlockAdd *= 512;
}
for HAL_MMC_WriteBlocks and HAL_MMC_ReadBlocks, I can access 1GB out of 16GB.
If I comment out this part, I can access beyond 1GB:
if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
{
hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
return HAL_ERROR;
}
I will make an substitute for the last part.
The last block address I can access with this Sandisk eMMC is 30777343, which gives me nearly 16GB.
Thank you very much for pointing me to the piece of the library that needed some rework.
So now I need to make a function HAL_MMC_GetCardEXTCID.
Regards,
Jack.
2018-08-08 05:24 PM
Did the demo code work?
2018-08-09 07:04 AM
Hi Clive,
I'm sorry, the demo is just a hex file, blindly running it wouldn't be any helpful.
So I went on and made some modifications, and made the full eMMC capacity available.
At STM they seem not aware that most applications would require eMM's greater than 2GB today. In their code, they rely on assumptions, the mother of all f-ups.
And they made a little miscalculation where one block of capacity would be wasted. Not a big deal, but by fixed it, I adding an extra block of capacity.
Things look pretty good now, all blocks 0 - 30777343 are accessible without read or write errors, so this gives me a reasonable 92% usable capacity of 16GB.
Since an eMMC is typically fixed on the board, and the capacity is not going to change, I omitted reading EXTCSD for now. I will figure that once time permits.
Thank you very much!
Regards, Jack.
2018-08-09 07:42 AM
It would help me. I'd be interested in the performance/function.
2018-08-10 07:17 AM
I'm reading EXTCSD too, capacity shows up as in the datasheet.
It appears, I have to reduce the clock speed when increasing the bus width, to avoid CRC errors. The speed is rather slow.
Update: I enabled hardware flow control, set IO Pin speed to Medium, then set ClockDiv to 0. In a write/read test, the combined throughput is 5 MB/s. Just reading is about 64 MB/sec.
FATFS works well, with almost 16GB available.
Directory: /
Attr. Last modified Size Name
----- ---------------- ---------- ----------------
-a--- 15-08-2018 10:08 55 hello.txt
-a--- 15-08-2018 10:09 45 hello2.txt
-a--- 15-08-2018 10:14 84 my_text_file.txt
d---- 15-08-2018 10:00 logs
-a--- 15-08-2018 10:43 1728 logs/log.txt
15386720 kB total disk space
15386528 kB available
Regards,
Jack.
2018-12-20 04:17 AM
Hi jack how are you?iam trying to write some data to emmc using stm32l4 i have 4gb emmc from issi,i wanted to use cubemx generated code for sd card which is only available in cubemx to write to eMMC.can u provide me what and functions i need to edit to get this working. thanking you in advance
2021-07-20 12:28 AM
Hi @Jack @Community member,
How can i read the EXTCSD please ?
Best regards.
Pyke