cancel
Showing results for 
Search instead for 
Did you mean: 

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

jjpark78_superman
Associate II

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

3 REPLIES 3
jjpark78_superman
Associate II

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

i found solution myself,

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

i am a real idiot. -_-;

You are not!! Thanks! 🙂