2023-04-14 12:51 PM - edited 2023-11-20 08:08 AM
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:
My questions/issues:
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>> & 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>> & 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);
}
2023-10-21 05:23 AM
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?
2023-10-21 07:01 AM
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 . <
2023-10-23 08:57 AM
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