cancel
Showing results for 
Search instead for 
Did you mean: 

FatFs - SDMMC - STM32H7

JC Lebreton
Associate II
Posted on February 21, 2018 at 16:20

Hi,

I have the problem that many of us have as seen on the number of post on the forum. Unfortunatly for me nobody have the same issue as i have!

Let s point out first what i'm trying to do.

I'm on a small project of data gathering. Of course I need to store the data somewhere and the card won't have acces to LoraWan or any similar network. So the only idea i got was using an USB stick or an SD card. I came with the idea to use an SD card for its small size. If some of you think it's easier to implement USB stick we can explore this option.

 

OK. this settled, let me explain what i did at the moment.

I try the code given by ST and adafruit, where they are using the SPI connection with the SD card. But i don't really like this technique.

So i try with the Cube to implement the SDMMC (1bit bus at the moment) and FatFs interface for an SD card. (configuration of the Cube on attachement).

I then create a projet on eclipse and try so stuff.

I use the function BSP_SD_Init(), wich result in a succes

I then try functions lie : f_mount(), 

FATFS_LinkDriver(&SD_Driver, SDPath),

f_mount()... But none of them seems to work!

I'm totaly lost... 

Do I have to Initialise more things? 

Do I have to complete .c files? like sd_diskio.c ?

well, if some of you have some clue or some working sample code it will be awesome.

Best regards,

JC

15 REPLIES 15
Posted on February 21, 2018 at 17:27

My approach has been to port the HAL code from the STM32H743xI-EVAL board to the NUCLEO-H743ZI, creating a stm32h7xx_nucleo_sd.c

0690X0000060421QAA.jpg0690X00000604POQAY.jpg
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on February 21, 2018 at 17:53

So far, the pinout i'm using is OK. 

I can say that because my SD card is answering me.

The command BSP_SD_IsDetected() provided by the cube is working 

it returns me 1 if there is an SD card and 0 if there is none.

Second point that can confirm what i'm saying is that f_mount(&SDFatFS, (TCHAR const*)SDPath, 0) answer me 'FR_OK'

I dig up a few an come to f_open(&SDFile, 'STM32.TXT', FA_CREATE_ALWAYS | FA_WRITE). but this one is not working. Indeed, i code the answer

FR_NOT_ENABLED

Note : &SDFile is declared like so : 'FIL SDFile'

And ... well  i have no clue at the moment why it's not working ...

Posted on February 21, 2018 at 18:17

Is your FatFs built as read-only? 

ffconf.h

...

♯ define _FS_READONLY 0

/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)

/ Read-only configuration removes writing API functions, f_write(), f_sync(),

/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()

/ and optional writing functions as well. */

...

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
JC Lebreton
Associate II
Posted on February 22, 2018 at 09:33

two things in one!

First of all, it works like a charm! (some issue about permissions but that's not a big of a deal now!)

I remove as mentionned before the '0ohm' resistor on pin SB116 and SB117 

and ... well it makes things work! 

if also changed a bit two functions :
  • FATFS_LinkDriver(&SD_Driver,(TCHAR const*)SDPath)

     ->

    FATFS_LinkDriver(&SD_Driver,'')
  • f_mount(&SDFatFS, (TCHAR const*)SDPath, 0) 

    ->f_mount(&SDFatFS, '', 0)

I keep things simple here to start understanding how things work!

thank you Clive for the help you provide me!

And for the others who would like to make the same stuff work, here is an easly understandable code!
Posted on February 22, 2018 at 09:35

Add after all the MX_XX_ init()

/* USER CODE BEGIN 2 */

 FRESULT res;

BSP_SD_Init();

if(FATFS_LinkDriver(&SD_Driver,'')!=0)

{

}

if(BSP_SD_IsDetected())

{

if(f_mount(&SDFatFS, '', 0)==FR_OK)

{

res = f_open(&SDFile, 'STM32.TXT', FA_CREATE_NEW | FA_WRITE | FA_READ);

datasend(res);

if(res == FR_OK)

{

HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_SET);

res = f_write(&SDFile, wtext, sizeof(wtext), (void *)&byteswritten);

datasend(res);

if((byteswritten>0)&&(res == FR_OK))

{

f_close(&SDFile);

}

}

else

{

HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14,GPIO_PIN_SET);

}

}

}

/* USER CODE END 2 */

/* Infinite loop */

/* USER CODE BEGIN WHILE */

while (1)

{

}
Posted on March 18, 2018 at 03:02

Hi Clive, I was wondering if you managed to get the SDMMC working in DMA mode ? I'm following the ST example (uSD_DMA_Standalone) but only polling mode works for me. I'm not sure if I'm reading the datasheet right (Table 1. Bus-master-to-bus-slave interconnect) but it seems SDMMC has access to AXI SRAM only ? I thought the MDMA managed the transfer (which has access to all RAMs I think) I noticed that if I use an SRAM1 buffer I get some error (HAL_SD_ErrorCallback is called) if I use an AXI SRAM buffer instead I don't get an error, but ReadBlocks_DMA timesout (HAL_SD_TxCpltCallback is never called). Here's my code it's a bit messy, sorry for that, am I missing anything obvious ? 

void HAL_SD_MspInit(SD_HandleTypeDef *hsd)

{

// MDMA controller clock enable

__HAL_RCC_MDMA_CLK_ENABLE();

// Enable SDMMC clock

__HAL_RCC_SDMMC1_CLK_ENABLE()

__HAL_RCC_SDMMC1_FORCE_RESET();

__HAL_RCC_SDMMC1_RELEASE_RESET();

// NVIC configuration for SDMMC interrupts

HAL_NVIC_SetPriority(SDMMC_IRQn, IRQ_PRI_SDMMC, IRQ_SUBPRI_SDMMC);

HAL_NVIC_EnableIRQ(SDMMC_IRQn);

// GPIOs have already been initialised by sdcard_init

}

// SD device interface configuration

sd_handle.Instance = SDMMC1;

sd_handle.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;

sd_handle.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_ENABLE;

sd_handle.Init.BusWide = SDMMC_BUS_WIDE_4B;

sd_handle.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;

sd_handle.Init.ClockDiv = SDMMC_TRANSFER_CLK_DIV;

// init the SD interface, with retry if it's not ready yet

for (int retry = 10; HAL_SD_Init(&sd_handle) != HAL_OK; retry--) {

   if (retry == 0) {

      led_flash_error(1);

      goto error;

   }

   HAL_Delay(10);

}

Later I call HAL_SD_ReadBlocks_DMA() and wait for WriteStaus == 0.. But this is never called using AXI buffer:

void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)

{

WriteStatus = 1;

}

And this gets called if I use SRAM1 buffer:

void HAL_SD_ErrorCallback(SD_HandleTypeDef *hsd)

{

led_flash_error(1);

}
Posted on March 18, 2018 at 16:44

It has been several weeks and I've moved on to other tasks. My recollection is that I did get DMA working. Seen to also recall that the ErrorCallback was called on every WriteMultipleDMA of ONE sector on the L4R9 platform

https://community.st.com/0D50X00009XkgY3SAJ

 

There were some issues on one SanDisk 16GB or 32GB card on the NUCLEO build, I suspect there is some code related to the UHS and low voltage operation that defines didn't remove properly/completely. The EVAL board has a transceiver and additional pins.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on March 18, 2018 at 19:11

Never mind I got it working in DMA mode, thanks anyway...

For anyone else having the same problem, the DMA buffer has to be in AXI SRAM, and you have to invalidate the cache of course. Note MDMA initialization, configuration and IRQ handler are not required (just enable the clock).

EDIT:  Also for the NUCLEO board the SD transceiver has to be disabled in hal_conf.h

&sharpdefine  USE_SD_TRANSCEIVER           0U 

Posted on March 29, 2018 at 18:45

>>

&sharpdefine  USE_SD_TRANSCEIVER           0U 

That deals with the bulk of the logic, but with one card there still seems to be a command level issue.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..