STM32L4 + emmc write & read speed is so slow...
@Hi all!
Thank you for your hard work.
Device : STM32L496 (Nucleo board)
eMMC : Hardkernel emmc reader + eMMC (sandisk 16GB / SDIN9DW4-16G)
env : stm32cudeide
I can read eMMC infomation and other CSD info.
Write and read function are works well. but it is very slow to our application.
HAL_MMC_ReadBlocks_DMA function is very fast(microsecond). but when i added HAL_MMC_GetCardState(&hmmc1) function, it almost stop. (millisecond dimension)
i searched in google and stm32 forum . In spite of these try, I don't have any solution about this problem.
this is my main code.
I'm very glad to any help.
int main(void)
{
/* USER CODE BEGIN 1 */
uint32_t dataSize = 512; // byte
uint32_t blockSize = 512;
uint32_t numberOfBlocks = 1;
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;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
HAL_Delay(3000);
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
DWT_Delay_Init();
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_SDMMC1_MMC_Init();
MX_LPUART1_UART_Init();
/* USER CODE BEGIN 2 */
printf("All init done \r\n ");
#if 1
{
if( HAL_MMC_GetCardInfo(&hmmc1, &CardInfo) != HAL_OK )
{
printf("HAL_MMC_GetCardInfo Err\n");
}
HAL_MMC_GetCardCSD(&hmmc1, &csd);
printf("ECC = %d \r\n", csd.ECC);
printf("\r\n BlockNbr = %d", CardInfo.BlockNbr);
printf("\r\n BlockSize = %d", CardInfo.BlockSize);
printf("\r\n CardType = %d", CardInfo.CardType);
printf("\r\n Class = %d", CardInfo.Class);
printf("\r\n LogBlockNbr = %d", CardInfo.LogBlockNbr);
printf("\r\n LogBlockSize = %d", CardInfo.LogBlockSize);
}
#endif
HAL_Delay(1000);
int status = 0;
#if 1
{
status = HAL_MMC_Erase(&hmmc1, 0, 4096);
if( status != HAL_OK )
{
printf("\r\n Single HAL_MMC_Erase Fail \r\n");
}
else
{
while( HAL_MMC_GetCardState(&hmmc1) != HAL_MMC_CARD_TRANSFER);
printf("\r\n Single HAL_MMC_Erase OK \n");
}
}
#endif
printf("\r\n Start write / read data \r\n");
int cmp_fail_cnt = 0;
for (int iteration = 0; iteration < 4096; 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;
}
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET);
errorState = HAL_MMC_WriteBlocks(&hmmc1, wData, blockAdd, numberOfBlocks, timeout);
// errorState = HAL_MMC_WriteBlocks_DMA(&hmmc1, wData, blockAdd, numberOfBlocks);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
while (HAL_MMC_GetCardState(&hmmc1) != HAL_MMC_CARD_TRANSFER) {
// Error_Handler();
// HAL_Delay(1);
}
// printf("Wr ");
// for (int j = 0; j < numberOfBlocks; j++) {
// for (int i = 0; i < 16; i++) {
// printf("%02X ", wData[i+ j*16]);
// }
// printf("\n");
// }
// Read
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET);
// errorState = HAL_MMC_ReadBlocks(&hmmc1, rData, blockAdd, numberOfBlocks, timeout);
errorState = HAL_MMC_ReadBlocks_DMA(&hmmc1, rData, blockAdd, numberOfBlocks);
while (HAL_MMC_GetCardState(&hmmc1) != HAL_MMC_CARD_TRANSFER){
// Error_Handler();
// HAL_Delay(1);
}
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
// printf("Rd ");
// for (int j = 0; j < numberOfBlocks; j++) {
// for (int i = 0; i < 16; i++) {
// printf("%02X ", rData[i+ j*16]);
// }
// printf("\n");
// }
if (memcmp(wData, rData, dataSize) == 0) {
// printf("Compare Passed. (BA: %8ld, %8ld kB) %d \r\n", blockAdd, kB, status);
}
else {
status = 1;
cmp_fail_cnt += 1;
// printf("Compare FAILED! (BA: %8ld, %8ld kB) %d \r\n", blockAdd, kB, status);
}
} /* End of write & read data */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_Delay(5000);
printf("\r\n cmp_fail_cnt = %d", cmp_fail_cnt);
}
/* USER CODE END 3 */
}
static void MX_SDMMC1_MMC_Init(void)
{
/* USER CODE BEGIN SDMMC1_Init 0 */
/* USER CODE END SDMMC1_Init 0 */
/* USER CODE BEGIN SDMMC1_Init 1 */
/* USER CODE END SDMMC1_Init 1 */
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_ENABLE;
hmmc1.Init.ClockDiv = 15;
if (HAL_MMC_Init(&hmmc1) != HAL_OK)
{
Error_Handler();
}
if (HAL_MMC_ConfigWideBusOperation(&hmmc1, SDMMC_BUS_WIDE_4B) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SDMMC1_Init 2 */
/* USER CODE END SDMMC1_Init 2 */
}
/**
* Enable DMA controller clock
*/
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA2_CLK_ENABLE();
/* DMA interrupt init */
/* DMA2_Channel4_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Channel4_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(DMA2_Channel4_IRQn);
}
