Issues mounting and using SD card with SPI on STM32L433xx

Hello everyone,

I'm currently working on a project where i need my STM32L433 (that runs RTOS) to communicate with an SD card wired to its SPI 1 bus.

The SPI bus also needs to work with DMA and I also wish to use the File System package.

As of today, everything seem to be initialized correctly but my code fails to mount the SD card (the fmount() function always return fsMediaError).

I've been trying to get it working for the past few days and can't find what i'm doing wrong, maybe i forgot something.

Here's the relevant parts of my code :

First, the main() :

int main(void)
{
  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  // Init GPIO
  MX_GPIO_Init();
    
  // Init DMA
  DMA_Init();
    
  // Init SPI_1
  SPI_1_Init();
    
  // Initialise RT OS
  osKernelInitialize();
  osThreadNew(Main_Thread, NULL, &main_thread_attributes);
  osKernelStart();

  /* Infinite loop */
  while (1)
  {
  }
}

GPIO configuration :

The SD card module is connected to the SPI 1 bus with the current layout :

SD CS : PB12 (chip select)

SD CK : PA1 (clock)

SD MISO : PA6

SD MOSI : PA7

SD IN : PB13 (this GPIO is use to read the module's pin that tells is an SD card is inserted)

void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

    /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOE_CLK_ENABLE();
    
  /*Configure GPIO pin : SD_IN_Pin (PB13) */
  GPIO_InitStruct.Pin = SDIO_IN_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(SDIO_IN_PORT, &GPIO_InitStruct);
    
  /*Configure GPIO pin : SDIO_CS (PB12) */
  GPIO_InitStruct.Pin = SDIO_CS_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(SDIO_CS_PORT, &GPIO_InitStruct);
    
  HAL_GPIO_WritePin(SDIO_CS_PORT, SDIO_CS_PIN, GPIO_PIN_SET);
}

DMA configuration :

void DMA_Init(void)
{
   /* DMA controller clock enable */
   __HAL_RCC_DMA1_CLK_ENABLE();

   /* DMA interrupt init */
    
   /* DMA1_Channel2_IRQn interrupt configuration */
   HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0);
   HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
    
   /* DMA1_Channel3_IRQn interrupt configuration */
   HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 0, 0);
   HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
}

SPI 1 configuration :

void SPI_1_Init(void)
{
   /* Peripheral clock enable */
   __HAL_RCC_SPI1_CLK_ENABLE();
    
   hspi1.Instance = SPI1;
   hspi1.Init.Mode = SPI_MODE_MASTER;
   hspi1.Init.Direction = SPI_DIRECTION_2LINES;
   hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
    
   hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
   hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
    
   hspi1.Init.NSS = SPI_NSS_SOFT;    
   hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLED;
    
   hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;    
   hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
    
   hspi1.Init.TIMode = SPI_TIMODE_DISABLED;
    
   hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
   hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
   hspi1.Init.CRCPolynomial = 7;
            
   /* SPI_1 GPIO Configuration */
   // PA1 -> SDIO_CK_PIN
   // PA6 -> SDIO_MISO_PIN
   // PA7 -> SDIO_MOSI_PIN
   GPIO_InitTypeDef GPIO_InitStruct = {0};
   GPIO_InitStruct.Pin = SDIO_CK_PIN | SDIO_MISO_PIN | SDIO_MOSI_PIN;
   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
   GPIO_InitStruct.Pull = GPIO_NOPULL;
   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
   GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;

   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);        
        
   if (HAL_SPI_Init(&hspi1) != HAL_OK)
   {
      Error_Handler();
   }
        
   /* SPI1 DMA Init */
        
    /* SPI1_RX Init */
    hdma_spi1_rx.Instance = DMA1_Channel2;
    hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_spi1_rx.Init.Mode = DMA_NORMAL;
    hdma_spi1_rx.Init.Priority = DMA_PRIORITY_LOW;
    if (HAL_DMA_Init(&hdma_spi1_rx) != HAL_OK)
    {
      Error_Handler();
    }
    __HAL_LINKDMA(&hspi1, hdmarx, hdma_spi1_rx);

    /* SPI1_TX Init */
    hdma_spi1_tx.Instance = DMA1_Channel3;
    hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_spi1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi1_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_spi1_tx.Init.Mode = DMA_NORMAL;
    hdma_spi1_tx.Init.Priority = DMA_PRIORITY_LOW;
    if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(&hspi1, hdmatx, hdma_spi1_tx);
}

Then, in the Main Thread function, i initialize the file system (using this https://www.keil.com/pack/doc/mw/FileSystem/html/index.html)

__NO_RETURN void Main_Thread (void *arg)
{
    (void)arg;

    fsStatus status;
    
    int a = 0;
    
    // Initialize file system
    status = finit("M0:");
    if(status == fsOK)
    {
        // Mount SD card in M0:
        status = fmount("M0:");
        if(status == fsOK)
        {
            // Successfuly mounted M0:
            a = 0;
        }
        else
        {

            // Fails here everytime with error code fsMediaError
            a = 1;
        }
    }
    
    while(1)
    {
    }
}

The SD card is configured on M0: for use with the SPI Driver.

This doesn't look like a hardware issue, the SD card is fine and if i run the code with an empy SD slot, it gives me the fsNoMedia code.

I think there's something wrong with my GPIO/DMA config, but i can't figure what's wrong with them.

For more details, i uploaded the full project on github : https://github.com/MonsieurJM/STM_SD

Thank you in advance for your time and support.

Parents
  • I finally managed to get this issue resolved.

    The issue is entirely resolved, the SD card is now working perfectly. The root of the issue was caused by missing data about the SPI bus in my CubeMX config files. After some digging, the CubeMX project files were altered early in the project's development i didn't notice it until now.

    For those facing a similar issue, open the CubeMX files with a code editor and check if there's data missing about the devices you want to use, it is critical that everything is declared here in order for the SPI driver to know which GPIO lines are to be used.

Reply
  • I finally managed to get this issue resolved.

    The issue is entirely resolved, the SD card is now working perfectly. The root of the issue was caused by missing data about the SPI bus in my CubeMX config files. After some digging, the CubeMX project files were altered early in the project's development i didn't notice it until now.

    For those facing a similar issue, open the CubeMX files with a code editor and check if there's data missing about the devices you want to use, it is critical that everything is declared here in order for the SPI driver to know which GPIO lines are to be used.

Children