Skip to main content
Hueli.1
Associate III
April 14, 2023
Question

Using SDMMC_TRANSFER_MODE_STREAM with SDMMC1 on STMH7

  • April 14, 2023
  • 3 replies
  • 2854 views

I am using the STMH7A3ZI-Q Nucleo Board together with the WFM200S Silicon Labs WiFi Board.

The example project of the WFM200S uses the deprecated SDIO library with an F4 Nucelo ( (https://github.com/SiliconLabs/wfx-fullMAC-tools/tree/wifi_examples_ssv4))

I would like to adapt the code to work with the STMH7. Currently the following works:

  • Data End Interrupt arrives and the SDMMC1_IRQHandler is called when interrupts are enabled
  • I can also read directly from the FIFO with some issues where I receive the same data several times.

My questions/issues:

  • DMA: I adapted the example code for the SDIO read of the original example to use the same method as the SD function HAL_SD_ReadBlocks_DMA() but this DMA transfer does not work somehow (the variable at defined adress SDMMC1->IDMABASE0 just remains unchanged)
    • Do I need to enable the MDMA or something similar like DMA Streams in the original example? (when MDMA was enabled as on image its callback was never called)
  • In general is using SDMMC_TRANSFER_MODE_STREAM even possible with SDMMC1? Or do I need to use BLOCK mode always?


_legacyfs_online_stmicro_images_0693W00000bi7yjQAA.png 

Original code:

sl_status_t sl_wfx_host_sdio_read_cmd53 (uint8_t function,
 uint32_t address,
 uint8_t* buffer,
 uint16_t buffer_length) { 
 SDIO_CmdInitTypeDef command;
 SDIO_DataInitTypeDef config;
 
 SDIO->DCTRL = 0U; 
 
 if(buffer_length >= SL_WFX_SDIO_BLOCK_MODE_THRESHOLD) {
 uint32_t block_count = ( buffer_length / SL_WFX_SDIO_BLOCK_SIZE ) + ( ( ( buffer_length % SL_WFX_SDIO_BLOCK_SIZE ) == 0 ) ? 0 : 1 );
 command.Argument = SDIO_CMD53_BLOCK_MODE | SDIO_CMD53_COUNT(block_count);
 config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
 config.DataBlockSize = sdio_optimal_block_size(SL_WFX_SDIO_BLOCK_SIZE);
 } else {
 command.Argument = SDIO_CMD53_COUNT(buffer_length);
 config.TransferMode = SDIO_TRANSFER_MODE_STREAM;
 config.DataBlockSize = sdio_optimal_block_size(buffer_length);
 }
 command.Argument |= SDIO_CMD53_FUNCTION( function ) | SDIO_CMD53_OPMODE_INCREASING_ADDRESS | SDIO_CMD53_ADDRESS( address );
 config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO;
 
 SDIO->DCTRL |= SDIO_DCTRL_SDIOEN;
 /* Prepare Data */
 config.DataTimeOut = SDMMC_DATATIMEOUT;
 config.DataLength = buffer_length;
 config.DPSM = SDIO_DPSM_ENABLE;
 SDIO_ConfigData(SDIO, &config);
 
 __SDIO_ENABLE_IT(SDIO, SDIO_IT_DATAEND);
 hdma_sdio_rx.XferCpltCallback = SDIO_receive_cplt;
 HAL_DMA_Start_IT(&hdma_sdio_rx, (uint32_t)&SDIO->FIFO, (uint32_t)buffer, (uint32_t)buffer_length/4);
 __SDIO_DMA_ENABLE(SDIO);
 
 /* Prepare SDIO command */ 
 command.CmdIndex = SDMMC_CMD_SDMMC_RW_EXTENDED;
 command.Response = SDIO_RESPONSE_SHORT;
 command.WaitForInterrupt = SDIO_WAIT_NO;
 command.CPSM = SDIO_CPSM_ENABLE;
 SDIO_SendCommand(SDIO, &command);
 SDMMC_GetCmdResp(SDIO);
 uint32_t response_flags = SDIO_GetResponse(SDIO, SDIO_RESP1);
 if (((response_flags>> 8) & 0xFF) != 0x20) {
 return SL_STATUS_FAIL;
 }
 return SL_STATUS_OK;
}
 
 
------------------------------ IRQ handler -----------------------------
void SDIO_IRQHandler (void) {
 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
 
 if (((SDIO->MASK & SDIO_IT_SDIOIT) == SDIO_IT_SDIOIT)
 && (__SDIO_GET_FLAG(SDIO, SDIO_FLAG_SDIOIT))) {
 /*Receive SDIO interrupt on SDIO_DAT1 from WF200*/
 __SDIO_CLEAR_FLAG(SDIO, SDIO_FLAG_SDIOIT);
 xSemaphoreGiveFromISR(sl_wfx_wake_up_sem, 
 &xHigherPriorityTaskWoken);
 xEventGroupSetBitsFromISR(sl_wfx_event_group,
 SL_WFX_RX_PACKET_AVAILABLE,
 &xHigherPriorityTaskWoken);
 }
 
 if (((SDIO->MASK & SDIO_IT_DATAEND) == SDIO_IT_DATAEND)
 && (__SDIO_GET_FLAG(SDIO, SDIO_FLAG_DATAEND))) {
 /*SDIO transfer over*/
 __SDIO_CLEAR_FLAG(SDIO, SDIO_IT_DATAEND);
 xSemaphoreGiveFromISR(sdioDMASemaphore, &xHigherPriorityTaskWoken);
 }
 portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
 
/**************************************************************************//**
 * Handle DMA2 stream3 global interrupt
 *****************************************************************************/
void DMA2_Stream3_IRQHandler (void) {
 HAL_DMA_IRQHandler(&hdma_sdio_rx);
}
 
/**************************************************************************//**
 * Handle DMA2 stream6 global interrupt
 *****************************************************************************/
void DMA2_Stream6_IRQHandler (void) {
 HAL_DMA_IRQHandler(&hdma_sdio_tx);
}
#endif /* SL_WFX_USE_SDIO */

My adapted code

sl_status_t sl_wfx_host_sdio_read_cmd53 (uint8_t function,
 uint32_t address,
 uint8_t* buffer,
 uint16_t buffer_length) {
	SDMMC_CmdInitTypeDef command;
	SDMMC_DataInitTypeDef config;
 
	SDMMC1->DCTRL = 0U;
 
 if(buffer_length >= SL_WFX_SDIO_BLOCK_MODE_THRESHOLD) {
 uint32_t block_count = ( buffer_length / SL_WFX_SDIO_BLOCK_SIZE ) + ( ( ( buffer_length % SL_WFX_SDIO_BLOCK_SIZE ) == 0 ) ? 0 : 1 );
 command.Argument = SDIO_CMD53_BLOCK_MODE | SDIO_CMD53_COUNT(block_count);
 config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
 config.DataBlockSize = sdio_optimal_block_size(SL_WFX_SDIO_BLOCK_SIZE);
 } else {
 command.Argument = SDIO_CMD53_COUNT(buffer_length);
 config.TransferMode = SDMMC_TRANSFER_MODE_STREAM;
 config.DataBlockSize = sdio_optimal_block_size(buffer_length);
 }
 command.Argument |= SDIO_CMD53_FUNCTION( function ) | SDIO_CMD53_OPMODE_INCREASING_ADDRESS | SDIO_CMD53_ADDRESS( address );
 config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
 
// SDIO->DCTRL |= SDIO_DCTRL_SDIOEN;
 
 /* Prepare Data */
 config.DataTimeOut = SDMMC_DATATIMEOUT;
 config.DataLength = buffer_length;
 config.DPSM = SDMMC_DPSM_DISABLE; //todo
 (void)SDMMC_ConfigData(SDMMC1, &config);
 
 __SDMMC_CMDTRANS_ENABLE(SDMMC1);
 SDMMC1->IDMABASE0 = (uint32_t) buffer;
 SDMMC1->IDMACTRL = SDMMC_ENABLE_IDMA_SINGLE_BUFF;
 
// __SDIO_ENABLE_IT(SDIO, SDIO_IT_DATAEND);
// hdma_sdio_rx.XferCpltCallback = SDIO_receive_cplt;
// HAL_DMA_Start_IT(&hdma_sdio_rx, (uint32_t)&SDIO->FIFO, (uint32_t)buffer, (uint32_t)buffer_length/4);
// __SDIO_DMA_ENABLE(SDIO);
 
 /* Prepare SDIO command */
 //todo .Argument which is Block address from where data is to be read...
 command.CmdIndex = SDMMC_CMD_SDMMC_RW_EXTENDED;
 command.Response = SDMMC_RESPONSE_SHORT;
 command.WaitForInterrupt = SDMMC_WAIT_NO;
 command.CPSM = SDMMC_CPSM_ENABLE;
 (void)SDMMC_SendCommand(SDMMC1, &command);
 SDMMC_GetCmdResp(SDMMC1);
 uint32_t response_flags = SDMMC_GetResponse(SDMMC1, SDMMC_RESP1);
 if (((response_flags>> 8) & 0xFF) != 0x20) {
 return SL_STATUS_FAIL;
 }
 
 __SDMMC_ENABLE_IT(SDMMC1, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND));
// __SDIO_ENABLE_IT(SDIO, SDIO_IT_DATAEND);
 
 
 return SL_STATUS_OK;
}
 
 
 
----------------------- Interrupt handler ----------------------
	 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
 
	 if (((SDMMC1->MASK & SDMMC_IT_SDIOIT) == SDMMC_IT_SDIOIT)
	 && (__SDMMC_GET_FLAG(SDMMC1, SDMMC_FLAG_SDIOIT))) {
	 /*Receive SDMMC interrupt on SDMMC_DAT1 from WF200*/
	 __SDMMC_CLEAR_FLAG(SDMMC1, SDMMC_FLAG_SDIOIT);
	 xSemaphoreGiveFromISR(sl_wfx_wake_up_sem,
	 &xHigherPriorityTaskWoken);
	 xEventGroupSetBitsFromISR(sl_wfx_event_group,
	 SL_WFX_RX_PACKET_AVAILABLE,
	 &xHigherPriorityTaskWoken);
	 }
 
	 /* DATA END interrupt */
	 if (((SDMMC1->MASK & SDMMC_IT_DATAEND) == SDMMC_IT_DATAEND)
	 && (__SDMMC_GET_FLAG(SDMMC1, SDMMC_FLAG_DATAEND))) {
 
 
	 //done in SD:
	 __SDMMC_CLEAR_FLAG(SDMMC1, SDMMC_FLAG_DATAEND);
	 __SDMMC_DISABLE_IT(SDMMC1, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | \
	 SDMMC_IT_TXUNDERR | SDMMC_IT_RXOVERR | SDMMC_IT_TXFIFOHE | \
	 SDMMC_IT_RXFIFOHF);
 
	 __SDMMC_DISABLE_IT(SDMMC1, SDMMC_IT_IDMABTC);
	 __SDMMC_CMDTRANS_DISABLE(SDMMC1);
 
 
	 /***********************************************************************/
 
	 //done in SD specifically for DMA
	 SDMMC1->DLEN = 0;
	 SDMMC1->DCTRL = 0;
	 SDMMC1->IDMACTRL = SDMMC_DISABLE_IDMA;
 
	 xSemaphoreGiveFromISR(sdioDMASemaphore, &xHigherPriorityTaskWoken);
	 }
 
	 portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

This topic has been closed for replies.

3 replies

Associate III
October 21, 2023

I am having exactly the same issue. It appears that the SDMMC_IT_DATAEND does not get set  when using config.TransferMode = SDMMC_TRANSFER_MODE_STREAM;

Has anyone got a solution to this?

AScha.3
Super User
October 21, 2023

solution for -- what ?

maybe better, you open new thread and tell, what you want and how you tried it... + cpu type.

ie. > file access on sd-card with fatfs not working . <

If you feel a post has answered your question, please click on " Best Answer ".
Associate III
October 23, 2023

Yeah I realise I've been lazy... It was late at night and I felt desperate. I will post my problem into a new thread. It was just that the code I wrote was so similar to that posted here by Hueli.1