cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H743 SDMMC1

Posted on May 16, 2018 at 20:13

I try to use SDMMC1 on STM32H743I Nucleo: It works fine but just if I use PLL1: PeriphClkInitStruct.SdmmcClockSelection = RCC_SDMMCCLKSOURCE_PLL;

If I try to use PLL2, the PLL2R clock output via: PeriphClkInitStruct.SdmmcClockSelection = RCC_SDMMCCLKSOURCE_PLL2; it fails: there does not seem to be a clock for the SDMMC1 peripheral block: the state machine does not proceed, the very first command for PowerOn does not complete (times out) and the status register bit in STA for command complete is never set.

It looks like the PPL2R and RCC_SDMMCCLKSOURCE_PLL2 cannot be used, not working and SDMMC1 does not get a peripheral device clock. But PLL2 (PLL2P and PLL2Q) should be OK because I use for SPI peripherals and all fine.

Using FatFS on SD card needs careful handling of DCache. Even enabling the Cache Maintenance via macro ENABLE_SD_DMA_CACHE_MAINTENANCE=1 is not enough. All the SD card commands are working error free, the f_read() or f_write() functions return properly but the data buffers are not updated (and writes to SD card will corrupt file system).

The only solution was to setup also the MPU, for the SRAM region used for variables (RAM_D1, start address: 0x24000000), data structures and buffers related to the SD card functions. The MPU is configured for the RAM_D1 region as:   MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE; - then it works.

Very strange: just DCache enabled but w/o related MPU entry fails, even with cache maintenance properly used.

it seems to me: if DCache is enabled - the MPU 'must' be used and configured in order to specify the cache and buffer modes for the SRAM regions.

BTW:

Be careful when using SDMMC1: I found a remark in an application note the SDMMC1 cannot access D2 SRAM.

And I have also realized that D2 SRAM (D2SRAM1, D2SRAM2, D2SRAM3) is not powered on, not enabled on reset and MCU startup. I had to enable those (via __HAL_RCC_D2SRAM1_CLK_ENABLE(); etc.) and it results in fact, that D2 SRAM cannot have initialized global variables (.data): they would not be loaded, not initialized by the debugger. Just during run time, after enabling D2 SRAM it can be used, but w/o to have it initialized (e.g. not filled with zero by startup).

The STM32H7 is a nice MCU but it seems to be a bit tricky, a bit 'sensitive' in terms of clock configurations and when DCache is enabled (strange is also: if I just disable DCache, do not enable - my working project crashes now in a HardFaultHandler). My experience is: this H7 MCU is quite different, even if a similar project is working fine on an F7 MCU - you cannot really compare and use as a reference. You had to study carefully the H7 datasheet, 'try this and that' and be aware of a quite different system architecture (e.g. how the DCache works, how to deal with the D1..D3 domains, memories and bus fabric = data paths).

==> what is your experience with this H7 MCU?

8 REPLIES 8
Posted on May 16, 2018 at 21:09

>>

what is your experience with this H7 MCU?

H7 is a lot more complicated, complexity in the clocking and DMA routing, etc.

Documentation is poor, things not named consistently, portions of PDF not searchable.

Software could do with refactoring, there is some ugly stuff in the RCC code, and a lack of understanding of how volatile prevents code reduction by compiler/optimizer.

Definitely had the SDMMC running off all available clocks sources. Wrote a clock decoder to crack the PLL and SDMMC clock settings and display. Most likely don't have the PLL running correctly. ST puts code all over the place.

There is 128KB of DTCMRAM, use that for SDMMC+DMA, no coherency issues. The cache flushing has 32-byte granularity, align your buffers suitably if use that method, watch for it discarding write-back buffers and faulting.

Watch for alignment issues with FPU/doubles.

Design has significant headroom, CPU/FPU ran at 500 MHz in tests.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on May 16, 2018 at 21:26

{

     PLL1_ClocksTypeDef PLL1_Clocks;

     HAL_RCCEx_GetPLL1ClockFreq(&PLL1_Clocks);

     printf('PLL1_Q_CK=%d, %6.2lf MHz\n', PLL1_Clocks.PLL1_Q_Frequency, (double)PLL1_Clocks.PLL1_Q_Frequency*1e-6);

}

{

     PLL2_ClocksTypeDef PLL2_Clocks;

     HAL_RCCEx_GetPLL2ClockFreq(&PLL2_Clocks);

     printf('PLL2_R_CK=%d, %6.2lf MHz\n', PLL2_Clocks.PLL2_R_Frequency, (double)PLL2_Clocks.PLL2_R_Frequency*1e-6);

}

{

     uint32_t ck = SDMMC1->CLKCR & 0x3FF;

     uint32_t sdmmcsel = RCC->D1CCIPR & (1 << 16);

     PLL1_ClocksTypeDef PLL1_Clocks;

     PLL2_ClocksTypeDef PLL2_Clocks;

     uint32_t sdmmc_ker_ck;

     HAL_RCCEx_GetPLL1ClockFreq(&PLL1_Clocks);

     HAL_RCCEx_GetPLL2ClockFreq(&PLL2_Clocks);

     printf('PLL1_Q_CK=%d, %6.2lf MHz\n', PLL1_Clocks.PLL1_Q_Frequency, (double)PLL1_Clocks.PLL1_Q_Frequency*1e-6);

     printf('PLL2_R_CK=%d, %6.2lf MHz\n', PLL2_Clocks.PLL2_R_Frequency, (double)PLL2_Clocks.PLL2_R_Frequency*1e-6);

     sdmmc_ker_ck = (sdmmcsel ? PLL2_Clocks.PLL2_R_Frequency : PLL1_Clocks.PLL1_Q_Frequency);

     printf('SDMMC1_CK %4d, %6.2lf MHz\n', ck, ((double)sdmmc_ker_ck * 1e-6) / (double)(2.0 * ck));

}
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on May 17, 2018 at 04:55

On STM32H743I-EVAL, using an off frequency as easier to quantify

//*****************************************************************************

void PLL2Clock_Config(void)

{

  RCC_PeriphCLKInitTypeDef RCC_PeriphCLKInitStruct = {0};

  HAL_StatusTypeDef ret = HAL_OK;

  /*  SDMMC Clk: (((25/5) * 180) / 6) = 150 MHz

      sdmmc_ker_ck max 200 MHz */

  RCC_PeriphCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SDMMC;

  RCC_PeriphCLKInitStruct.SdmmcClockSelection = RCC_SDMMCCLKSOURCE_PLL2;

  RCC_PeriphCLKInitStruct.PLL2.PLL2RGE = RCC_PLL1VCIRANGE_2;

  RCC_PeriphCLKInitStruct.PLL2.PLL2M = 5; // 5 MHz

  RCC_PeriphCLKInitStruct.PLL2.PLL2N = 180;

  RCC_PeriphCLKInitStruct.PLL2.PLL2P = 2;

  RCC_PeriphCLKInitStruct.PLL2.PLL2R = 6;

  RCC_PeriphCLKInitStruct.PLL2.PLL2Q = 4;

  RCC_PeriphCLKInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;

  ret = HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphCLKInitStruct);

  if (ret != HAL_OK)

  {

    Error_Handler();

  }

}

//***************************************************************************

32768000 Bytes, 1561694022 Cycles

 8.39 MBps Read (FatFs)

32768000 Bytes, 1561891660 Cycles

 8.39 MBps Read (FatFs)

7820 ms run time

 8.38 MBps (Sanity Check)

PLL1_Q_CK=200000000, 200.00 MHz

PLL2_R_CK=150000000, 150.00 MHz

SDMMC1_CK    4,  18.75 MHz
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on May 17, 2018 at 18:13

Thank you. Great idea to read back PLL config and to get current frequencies.

Yes, DTCM is great for 'DMA consistency', just to make sure that DMA can transfer from/to it. As I understand, most of the DMAs cannot. My understanding is: just MDMA can transfer between 'other' SRAM to DTCM, all other DMA cannot (?).

The 32-byte aligned for cache line size - I am aware of it. The cache maintenance already there in HAL (enable via macro defined) is doing it (round down the start address to 32-byte address, length increased by alignment 'offset').

I will try to fix my main issue, with the PLL2. Still not clear why it should not work (similar code you use also in my project).

The H7 is a little 'beast' (but nice system).
Amel NASRI
ST Employee
Posted on May 23, 2018 at 12:35

Hi

Jaekel.Torsten

‌,

Could you please check if SDMMC works as expected with PLL2R as clock source

when there is no other peripheral having PLL2 output (P or Q) as clock source

?

Thanks.

-Amel

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Posted on May 23, 2018 at 18:22

Hi Amel,

interesting question. I use PLL2, the other outputs, e.g. 4x for SPI (SPI1 and 2 as master, SPI4 and 5 as slave). Do you think it is a bug and related to the fact that all PLL2 outputs are used?

This is my clock configuration on PLL2 (SDMMC uses PLL1 now, PLL2 fails). I can try w/o to enable the SPIs, just SDMMC on PLL2.

  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART3|RCC_PERIPHCLK_SPI5

                              |RCC_PERIPHCLK_SPI4|RCC_PERIPHCLK_SPI1

                              |RCC_PERIPHCLK_SPI2|RCC_PERIPHCLK_SDMMC

                              |RCC_PERIPHCLK_USB;

  PeriphClkInitStruct.PLL2.PLL2M = 4;

  PeriphClkInitStruct.PLL2.PLL2N = 200;

  PeriphClkInitStruct.PLL2.PLL2P = 4;    //100 MHz SPI

  PeriphClkInitStruct.PLL2.PLL2Q = 4;    //100 MHz SPI

  PeriphClkInitStruct.PLL2.PLL2R = 2;    //RCC_SPI123CLKSOURCE_PLL2 - FAILS!!!

  PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_1;

  PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;

  PeriphClkInitStruct.PLL2.PLL2FRACN = 0;

  PeriphClkInitStruct.PLL3.PLL3M = 4;

  PeriphClkInitStruct.PLL3.PLL3N = 96;    //for USB

  PeriphClkInitStruct.PLL3.PLL3P = 4;

  PeriphClkInitStruct.PLL3.PLL3Q = 4;

  PeriphClkInitStruct.PLL3.PLL3R = 2;

  PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_1;

  PeriphClkInitStruct.PLL3.PLL3VCOSEL = RCC_PLL3VCOWIDE;

  PeriphClkInitStruct.PLL3.PLL3FRACN = 0;

  ////PeriphClkInitStruct.SdmmcClockSelection = RCC_SDMMCCLKSOURCE_PLL2;       //FAILS!!!

  PeriphClkInitStruct.SdmmcClockSelection = RCC_SDMMCCLKSOURCE_PLL;            //WORKS!!!

  PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL2;

  PeriphClkInitStruct.Spi45ClockSelection = RCC_SPI45CLKSOURCE_PLL2;

  PeriphClkInitStruct.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1;

  PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLL3;

  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
Posted on May 24, 2018 at 12:04

Hi

Jaekel.Torsten

‌,

Indeed there is a bug with the current HAL driver implementation when there is more than one output to be used for PLL2or PLL3.

That is why I suggested to try with only SDMMC on PLL2.

Hopefully the fix will be applied in next version of STM32CubeH7 (all depends on the planning of the releases).

Workaround to be applied waiting for the fix is to avoid using multiple outputs for same PLL (2 or 3).

-Amel

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Amel NASRI
ST Employee

Fix applied in RCC driver available in last STM32H7 package version (1.3.0).

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.