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) { }}
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);}
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.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);}
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);}
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_InitStruct.Pin = SDIO_CK_PIN | SDIO_MISO_PIN | SDIO_MOSI_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
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)
__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)
__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 {
__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:");
// Successfuly mounted M0:
a = 0;
else
// Fails here everytime with error code fsMediaError a = 1; } } while(1) { }}
// 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.
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.
Thank you for coming back to share the solution you found for your question!