Skip to main content
jjpark78_superman
Associate II
Jun 16, 2021 7:39 AM UTC
Question

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

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.

3 replies

jjpark78_superman
Associate II
Jun 16, 2021 7:58 AM UTC

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
Jun 20, 2021 1:32 AM UTC

i found solution myself,

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

i am a real idiot. -_-;

bmak
Senior
Aug 31, 2021 7:13 AM UTC

You are not!! Thanks! :)