Skip to main content
Visitor II
January 22, 2021
Solved

Questions about setting the spi clock (devicetree file, M4 Core side)

  • January 22, 2021
  • 5 replies
  • 4146 views

Hi ST.

I set the clock in the dts file as below.

&rcc {

st,hsi-cal;

st,csi-cal;

st,cal-sec = <60>;

st,clksrc = <

CLK_MPU_PLL1P

CLK_AXI_PLL2P

CLK_MCU_PLL3P

CLK_PLL12_HSE

CLK_PLL3_HSE

CLK_PLL4_HSE

CLK_RTC_LSE

CLK_MCO1_DISABLED

CLK_MCO2_DISABLED

>;

st,clkdiv = <

1 /*MPU*/

0 /*AXI*/

0 /*MCU*/

1 /*APB1*/

1 /*APB2*/

1 /*APB3*/

1 /*APB4*/

2 /*APB5*/

23 /*RTC*/

0 /*MCO1*/

0 /*MCO2*/

>;

st,pkcs = <

CLK_CKPER_HSI

CLK_QSPI_ACLK

CLK_ETH_DISABLED

CLK_SDMMC12_PLL4P

CLK_STGEN_HSE

CLK_USBPHY_HSE

CLK_SPI2S1_CKPER

CLK_SPI2S23_PLL3Q

CLK_SPI45_PLL4Q

CLK_SPI6_DISABLED

CLK_I2C46_HSI

CLK_SDMMC3_DISABLED

CLK_USBO_USBPHY

CLK_ADC_PLL4R

CLK_CEC_DISABLED

CLK_I2C12_HSI

CLK_I2C35_DISABLED

CLK_UART1_HSI

CLK_UART24_HSI

CLK_UART35_HSI

CLK_UART6_HSI

CLK_UART78_HSI

CLK_SPDIF_DISABLED

CLK_SAI1_DISABLED

CLK_SAI2_DISABLED

CLK_SAI3_DISABLED

CLK_SAI4_DISABLED

CLK_RNG1_LSI

CLK_RNG2_LSI

CLK_LPTIM1_PCLK1

CLK_LPTIM23_PCLK3

CLK_LPTIM45_LSE

>;

/* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */

pll2: st,pll@1 {

compatible = "st,stm32mp1-pll";

reg = <1>;

cfg = < 2 65 1 1 0 PQR(1,0,1) >;

frac = <0x1400>;

};

/* VCO = 600.0 MHz => P = 200, Q = 40, R = 60 */

pll3: st,pll@2 {

compatible = "st,stm32mp1-pll";

reg = <2>;

cfg = < 3 99 2 14 9 PQR(1,1,1) >;

/*

frac = <0x1a04>;

*/

};

/* VCO = 792.0 MHz => P = 99, Q = 66, R = 72 */

pll4: st,pll@3 {

compatible = "st,stm32mp1-pll";

reg = <3>;

cfg = < 5 197 7 11 10 PQR(1,1,1) >;

};

};

The following is the SPI setting part of M4 Core Side.

static void MX_SPI5_Init(void)

{

  LL_SPI_InitTypeDef SPI_InitStruct = {0};

  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  if (IS_ENGINEERING_BOOT_MODE())

  {

    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPI45;

    PeriphClkInit.Spi45ClockSelection = RCC_SPI45CLKSOURCE_PLL4;

    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)

    {

      Error_Handler();

    }

  }

  else

{

  if (!LL_RCC_PLL4_IsReady())

{

LL_RCC_PLL4_Enable();

}

LL_RCC_PLL4Q_Enable();

}

  // Peripheral clock enable

  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI5);

  LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOK);

  LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOJ);

  /* SPI5 GPIO Configuration

    PK0  ------> SPI5_SCK

    PJ10  ------> SPI5_MOSI

  */

  GPIO_InitStruct.Pin = LL_GPIO_PIN_0;

  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;

  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_MEDIUM;

  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;

  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;

  GPIO_InitStruct.Alternate = LL_GPIO_AF_5;

  LL_GPIO_Init(GPIOK, &GPIO_InitStruct);`

  GPIO_InitStruct.Pin = LL_GPIO_PIN_10;

  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;

  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_MEDIUM;

  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;

  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;

  GPIO_InitStruct.Alternate = LL_GPIO_AF_5;

  LL_GPIO_Init(GPIOJ, &GPIO_InitStruct);

  SPI_InitStruct.TransferDirection = LL_SPI_SIMPLEX_TX;

  SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;

  SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_16BIT;

  SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW;

  SPI_InitStruct.ClockPhase = LL_SPI_PHASE_1EDGE;

  SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;

  SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2;

  SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;

  SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;

  SPI_InitStruct.CRCPoly = 0x0;

  LL_SPI_Init(SPI5, &SPI_InitStruct);

  LL_SPI_SetStandard(SPI5, LL_SPI_PROTOCOL_MOTOROLA);

}

The following is the part that transmits data using SPI in M4 Core Side.

uint16_t uData = 0xFF0F;

LL_SPI_SetTransferSize(SPI5, 1);

LL_SPI_Enable(SPI5);

LL_SPI_StartMasterTransfer(SPI5);

LL_SPI_TransmitData16(SPI5, uData);

while (LL_SPI_IsActiveFlag_EOT(SPI5) == 0);

LL_SPI_ClearFlag_EOT(SPI5);

LL_SPI_ClearFlag_TXTF(SPI5);

LL_SPI_SuspendMasterTransfer(SPI5);

LL_SPI_Disable(SPI5);

SPI5 uses PLL4Q.

PLL4Q = 66Mhz -> 66/2 -> 33Mhz

The clock of SPI5 should operate at 33Mhz, but as a result of checking with an actual oscilloscope, it is about 2.6Mhz.

When I check it with an oscilloscope in Engineering Mode, it is about 33Mhz, but it is 2.6Mhz in Production Mode (Linux).

Am I wrong clock or SPI5 settings?

Below is the development environment.

Board : Custom board using stm32mp151c chip.

OS : Ecosystem 2.1.0 (202-11-12)

IDE : STM32CubeIDE

Debugger : STLINK-V3SET

Please tell me a solution.

Regards

Machilus

    This topic has been closed for replies.
    Best answer by PatrickF

    Hello,

    Did you use CubeMx ? Is the SPI5 correctly assigned to M4 in the Linux Device Tree ?

    You should see something like:

    m4_spi5_pins_mx: m4_spi5_mx-0 {
     pins {
     pinmux = <STM32_PINMUX('J', 10, RSVD)>, /* SPI5_MOSI */
     <STM32_PINMUX('J', 11, RSVD)>, /* SPI5_MISO */
     <STM32_PINMUX('K', 0, RSVD)>; /* SPI5_SCK */
     };
     };
    .....
    &m4_spi5{
     pinctrl-names = "default";
     pinctrl-0 = <&m4_spi5_pins_mx>;
     status = "okay";
    };

    Otherwise, I think related clock/pll is maybe not setup by Linux (and so SPI5 might be still on pclk2).

    Btw, in production mode, GPIO are set by Linux, so using LL_GPIO_Init( ) could result in conflicts hard to debug.

    To debug clock, you could also use cat /sys/kernel/debug/clk/clk_summary on Linux to see which frequencies are set in production mode.

    Maybe https://wiki.st.com/stm32mpu/wiki/How_to_configure_system_resources#Configuring_clock_and_regulator_system_resources could help you.

    Regards.

    5 replies

    PatrickFAnswer
    Technical Moderator
    January 22, 2021

    Hello,

    Did you use CubeMx ? Is the SPI5 correctly assigned to M4 in the Linux Device Tree ?

    You should see something like:

    m4_spi5_pins_mx: m4_spi5_mx-0 {
     pins {
     pinmux = <STM32_PINMUX('J', 10, RSVD)>, /* SPI5_MOSI */
     <STM32_PINMUX('J', 11, RSVD)>, /* SPI5_MISO */
     <STM32_PINMUX('K', 0, RSVD)>; /* SPI5_SCK */
     };
     };
    .....
    &m4_spi5{
     pinctrl-names = "default";
     pinctrl-0 = <&m4_spi5_pins_mx>;
     status = "okay";
    };

    Otherwise, I think related clock/pll is maybe not setup by Linux (and so SPI5 might be still on pclk2).

    Btw, in production mode, GPIO are set by Linux, so using LL_GPIO_Init( ) could result in conflicts hard to debug.

    To debug clock, you could also use cat /sys/kernel/debug/clk/clk_summary on Linux to see which frequencies are set in production mode.

    Maybe https://wiki.st.com/stm32mpu/wiki/How_to_configure_system_resources#Configuring_clock_and_regulator_system_resources could help you.

    Regards.

    MachilusAuthor
    Visitor II
    January 25, 2021

    Hi PatrickF (ST Employee)

    I modified DTS and Firware by referring to the advice.

    I looked at it using the command "cat /sys/kernel/debug/clk/clk_summary" and spi5_k was assigned to "pll4_q".

    But didn't solve the problem.

    If you set "PCLK2", "HSI", "CSI" and "HSE" in the SPI5 clock mux, it operates normally.

    However, only "PLL4Q" does not generate the clock as set.

    Is there anything else we need to look into?

    P.S : SPI1, SPI2, and SPI3 generate normal clocks as set regardless of the clock source.

    Regards

    Machilus

    Technical Moderator
    January 25, 2021

    ​Hi Machilus (Community Member)

    Could you please share your DTS? and .ioc file if generated by CubeMX/CubeIDE?

    When you say SPI1, SPI2, and SPI3 generate normal clocks as set, does it includes PLL4_P as clk source for instance?

    Regards,

    Olivier

    MachilusAuthor
    Visitor II
    January 26, 2021

    Hi OlivierK (ST Employee)

    Please tell me the e-mail address to send dts and ioc files.

    Regards

    Machilus

    Technical Moderator
    January 26, 2021

    Hi,

    You could send Private Message using pop-up menu which appear when you leave the cursor on a name. You could also uses the Message area.

    Technical Moderator
    February 4, 2021

    ​Hi Machilus (Community Member)

    Regarding the linux side of your configuration, I've found your PLL4 freq out of spec. Did you use CubeMx to modify the clock tree? Also for the M4 configuration it would have been much safer to use this tool to prevent setup errors.

    root@stm32mp1:~# cat /sys/kernel/debug/clk/clk_summary                                                    

        pll4                             2       2       0  792000000         0    0 50000                        

    Using your setup, changing the TF-a clock settings on the DK2 board using the spi5 node with the CLK_SPI45_PLLQ

    I found spi5_k  around 30MHz                  0       0       0   29700000         0    0 50000

    Regards

                                         

    MachilusAuthor
    Visitor II
    February 8, 2021

    Hi OlivierK (ST Employee)

    I entered the same frequency settings into the STM32CubeMX as the shared DTS file, but there are no errors.

    If I set "/6" in DIVM4, CubeMX will not throw an error if the condition of "400Mhz =< PLL4 <= 800Mhz" is met.

    So setting "792Mhz" in PLL4 didn't cause any warnings or errors in CubeMX.

    0693W000007EGA8QAO.jpg 

    Is the STM32CubeMX wrong?, We can also share "ioc" files.

    I used STM32CubeMX version 6.1.1

    I look forward to your reply.

    Thanks and regards

    Machilus

    Technical Moderator
    February 8, 2021

    ​Hi Machilus (Community Member),

    For the PLL VCO specifications it is indeed correct, anyway if you've generated your project with CubeMX it should be error free. I did not see the .ioc in the files you've shared, so I was assuming you didn't use CubeMX.

    Anyway, I did use you settings in TF-a and regarding the spi5_k do you see the same once booted?

    spi5_k                  0       0       0   29700000         0    0 50000

    Regards,

    Olivier

    MachilusAuthor
    Visitor II
    February 9, 2021

    Hi OlivierK (ST Employee)

    0693W000007ERSDQA4.jpgIn the picture above, you can see that "spi5_k" is set to 66Mhz in "PLL4Q".

    Since the clock setting of "PLL4" is as follows, it is normal that 66Mhz appears in "PLL4Q".

    /* VCO = 792.0 MHz => P = 99, Q = 66, R = 72 */

    pll4: st,pll@3 {

    compatible = "st,stm32mp1-pll";

    reg = <3>;

    cfg = < 5 197 7 11 10 PQR(1,1,1) >;

    };

    };

    However, if i set the Baudrate of SPI5 of M4 firmware to "LL_SPI_BAUDRATEPRESCALER_DIV2" in production mode booted with Linux, "SPI5_SCK" will output 2.6Mhz instead of 33Mhz.

    Regards

    Machilus

    Technical Moderator
    February 10, 2021

    ​Hi Machilus (Community Member),

    ​There should be no influence at all of M4 clock init code in production mode since all the clock settings are initialized exclusively by the Linux DT in production mode. Mixing M4 code calling RCC clock setting such as the prescaler is conflicting with openstlinux RCC init in DT.

    Therefore this LL_SPI_BAUDRATEPRESCALER_DIV2 may work in engineering mode where the M4 is isolated from the Cortex A7 and Linux, but not in production mode.

    So I would strip out first all the RCC code settings from the M4, regenerate/reload the .elf file. Refer to the CubeMX code generator tool to generate the clock tree (including the clock prescalers) in production mode and see how it goes.

    you can refer to the wiki ressources for that if not clear:

    https://wiki.st.com/stm32mpu/wiki/Getting_started/STM32MP1_boards/STM32MP157x-DK2/Develop_on_Arm®_Cortex®-M4/Modify,_rebuild_and_reload_a_firmware

    Regards,

    Olivier