cancel
Showing results for 
Search instead for 
Did you mean: 

How to setup SDMMC with the HSI48 clock?

RBamf.1
Associate III

Hi, i'm trying to configure the SDMMC device to be driven by the HSI48 clock, here is my configuration at the moment. Previously, i had configured the SDMMC with the PLLSAI clock and it worked at certain frequencies (38KHz.etc) but i've read in the specification that the HSI48 is specifically for USB and SDMMC so howcome this doesn't work?

Cheers!

Richard

#pragma once
 
extern "C" void SystemClock_Config(void) {
    RCC_OscInitTypeDef RCC_OscInitStruct = {};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {};
    RCC_PeriphCLKInitTypeDef PeriphClkInit = { 0 };
 
    /* Configure LSE Drive Capability */
    HAL_PWR_EnableBkUpAccess();
    __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);
    /* Initializes the CPU, AHB and APB busses clocks */
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_MSI | RCC_OSCILLATORTYPE_HSI48;
    RCC_OscInitStruct.LSEState = RCC_LSE_ON;
    RCC_OscInitStruct.MSIState = RCC_MSI_ON;
    RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
    RCC_OscInitStruct.MSICalibrationValue = 0;
    RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
    RCC_OscInitStruct.PLL.PLLM = 1;
    RCC_OscInitStruct.PLL.PLLN = 40;
    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;
    RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
    RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
        Error_Handler();
    }
    /* Initializes the CPU, AHB and APB busses clocks */
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
        | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
 
    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) {
        Error_Handler();
    }
 
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SDMMC1;
    //PeriphClkInit.Sdmmc1ClockSelection = RCC_SDMMC1CLKSOURCE_PLLSAI1;
    PeriphClkInit.Sdmmc1ClockSelection = RCC_SDMMC1CLKSOURCE_HSI48;
    //PeriphClkInit.PLLSAI1.PLLSAI1Source = RCC_PLLSOURCE_MSI;
    //PeriphClkInit.PLLSAI1.PLLSAI1M = 1;
    //PeriphClkInit.PLLSAI1.PLLSAI1N = 8;
    //PeriphClkInit.PLLSAI1.PLLSAI1P = RCC_PLLP_DIV17;
    //PeriphClkInit.PLLSAI1.PLLSAI1Q = RCC_PLLQ_DIV2;
    //PeriphClkInit.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV2;
    //PeriphClkInit.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK | RCC_PLLSAI1_ADC1CLK | RCC_PLLSAI1_48M2CLK;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
        Error_Handler();
    }
 
 
    /* Configure the main internal regulator output voltage */
    if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK) {
        Error_Handler();
    }
 
    /* Enable MSI Auto calibration */
    HAL_RCCEx_EnableMSIPLLMode();
 
 
}

7 REPLIES 7

Hello,

32KHZ as clock to SDMMC is different than 48MHZ

With 80 MHZ sysclock is very difficult to handle 48MHZ sdmmc communication at full speed when use FATFS

At first increase sytemclock to maximum and try to clock the sdmmc in MHZ range by dividing by two the freq that does not work. (48,24, 12, etc) to find the max freq that the programm can run.

Provide some more information about device and what isn't work as expected.

>>With 80 MHZ sysclock is very difficult to handle 48MHZ sdmmc communication at full speed when use FATFS

Should be plenty on bandwidth, 12 MBps into memories capable of few hundred MBps

Guessing a L4, but really need to contextualize this better, as 2 or 3 SDMMC implementations.

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

Hello

Yes there is plenty of bandwidth after taking the 512 byte block from card at HAL layer

But the real problem is the CubeMx default settings . Polling mode , 32x32bit = 128BYTES FIFO on, executing in flash memory (x Wait States) and 48MHZ clock with 0 clockdivider., the function HAL_SD_ReadBlocks(..) that read the zero sector, called from f_mount, never returns without HAL_ERROR (responible for this is RX overrun Flag.).

if divider is increased is ok

Thankyou for the help, much appreciated!

It writes at a max of 8MHz, it's a class 10, 1u SD card so surely it should be able to handle much higher clock speeds than that?

I'm using an STM32L452RE some more details here https://www.stm32duino.com/viewtopic.php?f=7&t=902

Thing is, to get high speeds you don't write 512 bytes at a time, most of your time is burned in the command/response with the card, and the card trying to manage virtual blocks of 128KB or more.

To get any kind of streaming throughput into the card you're going to need to do much larger block writes. In FatFs this is typically the Cluster size. You might also need to get into specific Class 10 / Ultra 1 modes/commands.

Is this on a NUCLEO board, or something custom? As frequency rises signal integrity becomes an issue, along with termination and slew-rates.

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

Hmm ok, i'm trying writes of 36KB at a time and its reaching 2MB/s! Custom board, it runs at 16MHz 🙂