2021-06-16 12:39 AM
i'm develop some custom encrypted Mass Storage Device using STM32F411
i want to use SDIO and DMA when need to process MSC Request,
Some of my code,
int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr,
uint16_t blk_len) {
/* USER CODE BEGIN 7 */
int8_t ret = USBD_FAIL;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);
switch (lun) {
case PB_LUN:
ret = STORAGE_Public_Write(buf, blk_addr + PB_SECTOR_START_OFFSET, blk_len);
break;
case PV_LUN:
ret = STORAGE_Secure_Write(buf, blk_addr, blk_len, 0);
break;
}
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);
return ret;
/* USER CODE END 7 */
}
int8_t STORAGE_Secure_Write(uint8_t *buf, uint32_t blk_addr, uint16_t blk_len, uint8_t offset) {
// Doing some encryption to buffer.
HAL_StatusTypeDef ret = HAL_SD_WriteBlocks_DMA(&hsd, buf, blk_addr + offset, blk_len);
switch(ret) {
case HAL_OK:
do {
; // do nothing
} while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER);
return USBD_OK;
break;
case HAL_BUSY:
printf(" HAL_SD_WriteBlocks_DMA returns BUSY\n");
return USBD_FAIL;
case HAL_TIMEOUT:
printf(" HAL_SD_WriteBlocks_DMA returns TIMEOUT\n");
return USBD_FAIL;
case HAL_ERROR:
printf(" HAL_SD_WriteBlocks_DMA returns ERROR\n");
//print_sdio_errorcode(hsd.ErrorCode);
return USBD_FAIL;
}
}
problem is HAL_SD_GetCardState returns value is always in BUSY.
how can i measure whether DMA transfer is done or still in busy ??
HAL Documents said HAL_SD_GetCardState should work, but i think STORAGE_Write_FS is a callback, so cannot working like normal routine.
for example in callback function HAL_Delay() is not working too,
but i dont know why.
plz help me.
void MX_SDIO_SD_Init(void)
{
/* USER CODE BEGIN SDIO_Init 0 */
/* USER CODE END SDIO_Init 0 */
/* USER CODE BEGIN SDIO_Init 1 */
/* USER CODE END SDIO_Init 1 */
hsd.Instance = SDIO;
hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_ENABLE;
hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
hsd.Init.ClockDiv = 12;
if (HAL_SD_Init(&hsd) != HAL_OK)
{
Error_Handler();
}
if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SDIO_Init 2 */
/* USER CODE END SDIO_Init 2 */
}
void HAL_SD_MspInit(SD_HandleTypeDef* sdHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(sdHandle->Instance==SDIO)
{
/* USER CODE BEGIN SDIO_MspInit 0 */
/* USER CODE END SDIO_MspInit 0 */
/* SDIO clock enable */
__HAL_RCC_SDIO_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**SDIO GPIO Configuration
PA6 ------> SDIO_CMD
PB15 ------> SDIO_CK
PA8 ------> SDIO_D1
PA9 ------> SDIO_D2
PB5 ------> SDIO_D3
PB7 ------> SDIO_D0
*/
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_8|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_15|GPIO_PIN_5|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* SDIO DMA Init */
/* SDIO_RX Init */
hdma_sdio_rx.Instance = DMA2_Stream3;
hdma_sdio_rx.Init.Channel = DMA_CHANNEL_4;
hdma_sdio_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_sdio_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_sdio_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_sdio_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_sdio_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_sdio_rx.Init.Mode = DMA_PFCTRL;
hdma_sdio_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_sdio_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_sdio_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_sdio_rx.Init.MemBurst = DMA_MBURST_INC4;
hdma_sdio_rx.Init.PeriphBurst = DMA_PBURST_INC4;
if (HAL_DMA_Init(&hdma_sdio_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(sdHandle,hdmarx,hdma_sdio_rx);
/* SDIO_TX Init */
hdma_sdio_tx.Instance = DMA2_Stream6;
hdma_sdio_tx.Init.Channel = DMA_CHANNEL_4;
hdma_sdio_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_sdio_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_sdio_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_sdio_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_sdio_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_sdio_tx.Init.Mode = DMA_PFCTRL;
hdma_sdio_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_sdio_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_sdio_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_sdio_tx.Init.MemBurst = DMA_MBURST_INC4;
hdma_sdio_tx.Init.PeriphBurst = DMA_PBURST_INC4;
if (HAL_DMA_Init(&hdma_sdio_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(sdHandle,hdmatx,hdma_sdio_tx);
/* SDIO interrupt Init */
HAL_NVIC_SetPriority(SDIO_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(SDIO_IRQn);
/* USER CODE BEGIN SDIO_MspInit 1 */
printf("HAL_SD_MspInit called\n");
/* USER CODE END SDIO_MspInit 1 */
}
}
void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA2_CLK_ENABLE();
/* DMA interrupt init */
/* DMA2_Stream3_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 6, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
/* DMA2_Stream6_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 7, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);
}
what am i doing wrong ??
2021-06-16 12:58 AM
HAL Document said "You could also check the DMA transfer process through the SD Rx interrupt event."
but how ?? any sample codes ??
2021-06-19 06:32 PM
i found solution myself,
MSC IRQ Priority should be lower than DMA's ...
i am a real idiot. -_-;
2021-08-31 12:13 AM
You are not!! Thanks! :)