Skip to main content
jjpark78_superman
Associate II
June 16, 2021
Question

USB MSC + SDIO + DMA combination make me crazy. can't solve problem. help needed indeed.

  • June 16, 2021
  • 2 replies
  • 2021 views

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 ??

This topic has been closed for replies.

2 replies

jjpark78_superman
Associate II
June 16, 2021

HAL Document said "You could also check the DMA transfer process through the SD Rx interrupt event."

but how ?? any sample codes ??

jjpark78_superman
Associate II
June 20, 2021

i found solution myself,

MSC IRQ Priority should be lower than DMA's ...

i am a real idiot. -_-;

bmak
Senior
August 31, 2021

You are not!! Thanks! :)