cancel
Showing results for 
Search instead for 
Did you mean: 

STM32MP157CA SPI1 Clock does not work

DBaes.1
Associate III

We use the STM32MP157CA and the STM32CubeIDE and let the code generator generate a confiuration with the required modules. In our case the SPI1 on the pins (PZ0,PZ1,PZ2). The generated functions provide the initializations for the SPI1. Unfortunately the SPI1 does not work for us in normal operation mode. If we call the HAL_SPI_Transmit(...) function after the initialization we get a SPI timeout. On the oscilloscope we see no clock on the spi clock line. We also noticed that when we use the engineering mode for the M4 the SPI1 works.

If we change the SPI to the SPI5 (also generated with the code generator) everything works in normal operation mode and in engineering mode. How can we use the SPI1 in normal operation mode on the M4?

1 ACCEPTED SOLUTION

Accepted Solutions

Hi,

could you also check if

cat /proc/device-tree/ahb/m4@10000000/m4_system_resources/status

return 'okay' too ?

In case you rebuilt the kernel, please check if the following config are enabled (they are ON by default in the starter package):

  • REMOTEPROC_SRM_DEV
  • REMOTEPROC_SRM_CORE

Regards.

In order 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.

View solution in original post

18 REPLIES 18
PatrickF
ST Employee

Hi,

did you update the complete DT from CubeIDE outputs ? See https://wiki.st.com/stm32mpu/wiki/How_to_compile_the_device_tree_with_the_Developer_Package

Linux should be aware of m4 resources (e.g. to start relevant clocks). See https://wiki.st.com/stm32mpu/wiki/How_to_assign_an_internal_peripheral_to_a_runtime_context

SPI5 works maybe because it is defined in default starter package or benefit from an already enabled shared clock.

Regards.

In order 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.

We use the diff tool to get all required device tree options by compare the generated devicetree without SPI1 and with SPI1 enabled. We apply this changes with an path at our yocto build.

The difference looks like this:

diff --git a/CA7/DeviceTree/xyz/kernel/stm32mp157c-xyz.dts b/CA7/DeviceTree/xyz/kernel/stm32mp157c-xyz.dts
index 45cf88a..5e549e4 100644
--- a/CA7/DeviceTree/xyz/kernel/stm32mp157c-xyz.dts
+++ b/CA7/DeviceTree/xyz/kernel/stm32mp157c-xyz.dts
@@ -136,6 +136,14 @@
 &pinctrl_z {
 	u-boot,dm-pre-reloc;
 
+	m4_spi1_pins_z_mx: m4_spi1_mx-0 {
+		pins {
+			pinmux = <STM32_PINMUX('Z', 0, RSVD)>, /* SPI1_SCK */
+					 <STM32_PINMUX('Z', 1, RSVD)>, /* SPI1_MISO */
+					 <STM32_PINMUX('Z', 2, RSVD)>; /* SPI1_MOSI */
+		};
+	};
+
 	/* USER CODE BEGIN pinctrl_z */
 	/* USER CODE END pinctrl_z */
 };
@@ -234,6 +242,15 @@
 	/* USER CODE END m4_dma2 */
 };
 
+&m4_spi1{
+	pinctrl-names = "default";
+	pinctrl-0 = <&m4_spi1_pins_z_mx>;
+	status = "okay";
+};
+
 &m4_spi5{
 	pinctrl-names = "default";
 	pinctrl-0 = <&m4_spi5_pins_mx>;
diff --git a/CA7/DeviceTree/xyz/tf-a/stm32mp157c-xyz.dts b/CA7/DeviceTree/xyz/tf-a/stm32mp157c-xyz.dts
index 49c6302..75dee09 100644
--- a/CA7/DeviceTree/xyz/tf-a/stm32mp157c-xyz.dts
+++ b/CA7/DeviceTree/xyz/tf-a/stm32mp157c-xyz.dts
@@ -92,7 +92,7 @@
 		CLK_SDMMC12_DISABLED
 		CLK_STGEN_HSI
 		CLK_USBPHY_DISABLED
-		CLK_SPI2S1_DISABLED
+		CLK_SPI2S1_PLL3R
 		CLK_SPI2S23_DISABLED
 		CLK_SPI45_PCLK2
 		CLK_SPI6_DISABLED
@@ -116,6 +116,11 @@
 		CLK_LPTIM23_DISABLED
 		CLK_LPTIM45_DISABLED
 	>;
+	pll3:st,pll@2 {
+		compatible = "st,stm32mp1-pll";
+		reg = <2>;
+		cfg = < 3 24 1 1 1 PQR(0,0,1) >;
+	};
 	pll4:st,pll@3 {
 		compatible = "st,stm32mp1-pll";
 		reg = <3>;
@@ -142,6 +147,7 @@
 	/*"Mcu Isolation" peripherals*/
 	DECPROT(STM32MP1_ETZPC_CRC2_ID, DECPROT_MCU_ISOLATION, DECPROT_UNLOCK)
 	DECPROT(STM32MP1_ETZPC_DMA2_ID, DECPROT_MCU_ISOLATION, DECPROT_UNLOCK)
+	DECPROT(STM32MP1_ETZPC_SPI1_ID, DECPROT_MCU_ISOLATION, DECPROT_UNLOCK)
 	DECPROT(STM32MP1_ETZPC_SPI5_ID, DECPROT_MCU_ISOLATION, DECPROT_UNLOCK)
 	DECPROT(STM32MP1_ETZPC_TIM2_ID, DECPROT_MCU_ISOLATION, DECPROT_UNLOCK)
 	DECPROT(STM32MP1_ETZPC_USART2_ID, DECPROT_MCU_ISOLATION, DECPROT_UNLOCK)
diff --git a/CA7/DeviceTree/xyz/u-boot/stm32mp157c-xyz-u-boot.dtsi b/CA7/DeviceTree/xyz/u-boot/stm32mp157c-xyz-u-boot.dtsi
index 88fcdce..604e7ad 100644
--- a/CA7/DeviceTree/xyz/u-boot/stm32mp157c-xyz-u-boot.dtsi
+++ b/CA7/DeviceTree/xyz/u-boot/stm32mp157c-xyz-u-boot.dtsi
@@ -94,7 +94,7 @@
 		CLK_SDMMC12_DISABLED
 		CLK_STGEN_HSI
 		CLK_USBPHY_DISABLED
-		CLK_SPI2S1_DISABLED
+		CLK_SPI2S1_PLL3R
 		CLK_SPI2S23_DISABLED
 		CLK_SPI45_PCLK2
 		CLK_SPI6_DISABLED
@@ -118,6 +118,12 @@
 		CLK_LPTIM23_DISABLED
 		CLK_LPTIM45_DISABLED
 	>;
+	pll3:st,pll@2 {
+		compatible = "st,stm32mp1-pll";
+		reg = <2>;
+		cfg = < 3 24 1 1 1 PQR(0,0,1) >;
+		u-boot,dm-pre-reloc;
+	};
 	pll4:st,pll@3 {
 		compatible = "st,stm32mp1-pll";
 		reg = <3>;
diff --git a/CA7/DeviceTree/xyz/u-boot/stm32mp157c-xyz.dts b/CA7/DeviceTree/xyz/u-boot/stm32mp157c-xyz.dts
index f094748..217ac06 100644
--- a/CA7/DeviceTree/xyz/u-boot/stm32mp157c-xyz.dts
+++ b/CA7/DeviceTree/xyz/u-boot/stm32mp157c-xyz.dts
@@ -136,6 +136,14 @@
 &pinctrl_z {
 	u-boot,dm-pre-reloc;
 
+	m4_spi1_pins_z_mx: m4_spi1_mx-0 {
+		pins {
+			pinmux = <STM32_PINMUX('Z', 0, RSVD)>, /* SPI1_SCK */
+					 <STM32_PINMUX('Z', 1, RSVD)>, /* SPI1_MISO */
+					 <STM32_PINMUX('Z', 2, RSVD)>; /* SPI1_MOSI */
+		};
+	};
+
 	/* USER CODE BEGIN pinctrl_z */
 	/* USER CODE END pinctrl_z */
 };
@@ -234,6 +242,15 @@
 	/* USER CODE END m4_dma2 */
 };
 
+&m4_spi1{
+	pinctrl-names = "default";
+	pinctrl-0 = <&m4_spi1_pins_z_mx>;
+	status = "okay";
+};
+
 &m4_spi5{
 	pinctrl-names = "default";
 	pinctrl-0 = <&m4_spi5_pins_mx>;

Did we miss a function that was already active in the generated device tree with disabled SPI1?

Hi,

few toughts:

Your PLL3 settings sound strange, at least P divider should be enabled to use M4.

R post divider to 1 sound too high resulting frequency.

I would see more something like (P = 208.87793MHz, Q = 24.573874, R = 11.290699) to be tailored to your needs (CubeMx could help).

pll3:st,pll@2 {
		compatible = "st,stm32mp1-pll";
		reg = <2>;
		cfg = < 1 33 1 16 36 PQR(1,1,1) >;
		frac = < 0x1a04 >;
		u-boot,dm-pre-reloc;
	};

See also https://wiki.st.com/stm32mpu/wiki/Clock_device_tree_configuration_-_Bootloader_specific#Defining_peripheral_PLL_frequencies_with_st-2Cpll_property

Did you try to debug your FW to see why you get this timeout ?

With debugger, please check RCC_MC_APB2ENSETR.SPI1EN bit, RCC_SPI2S1CKSELR.SPI1SRC field.

We know that sometimes, when reloading M4 FW more than once (i.e. stop/start copro FW), some peripherals does not re-init well (as there is no reset on M4 side).

You could try adding these lines in the /* USER CODE BEGIN SysInit */ section of your main.c to force a reset of SPI1 settings before the M4 init it.

hspi1.Instance = SPI1;
 HAL_SPI_DeInit(&hspi1);
 HAL_SPI_MspDeInit(&hspi1);
 HAL_NVIC_DisableIRQ(SPI1_IRQn);
 __HAL_RCC_SPI1_FORCE_RESET();
 __HAL_RCC_SPI1_RELEASE_RESET();

Regards.

In order 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.

Hello PatrickF,

we use the following PLL3 settings in our yocto device tree:

/* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */
pll3: st,pll@2 {
	cfg = < 2 50 1 16 36 PQR(1,1,1) >;
	frac = < 0x1a04 >;
	u-boot,dm-pre-reloc;
};

The SPI Timeout comes from: HAL_SPI_Transmit(&hspi1, ...) -> HAL_SPI_Transmit(...) in stm32mp1xx_hal_spi.c -> SPI_WaitOnFlagUntilTimeout(...) in stm32mp1xx_hal_spi.c

static HAL_StatusTypeDef SPI_WaitOnFlagUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Flag, FlagStatus Status,
                                                    uint32_t Tickstart, uint32_t Timeout)
{
 /* Wait until flag is set */
  while ((__HAL_SPI_GET_FLAG(hspi, Flag) ? SET : RESET) == Status)
  {
    /* Check for the Timeout */
    if ((((HAL_GetTick() - Tickstart) >=  Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
    {
      return HAL_TIMEOUT; // <-- SPI1 Timeout
    }
  }
  return HAL_OK;
}

I check the Values for:

- RCC_MC_APB2ENSETR: 1793

- RCC_SPI2S1CKSELR: 1

but i could not find the declarations for the register bits SPI1EN and SPI1SRC in the project library.

The additional SPI1 reset commands did not change anything, we still have a timeout on SPI1 and no clock signal for SPI1 -> so it must have something to do with the clocks.

Hi,

Assuming your values are decimal, RCC_MC_APB2ENSETR = 1793 = 0x701, which mean SPI1EN=1

but RCC_SPI2S1CKSELR = 1 mean pll3_q, which is not what you have in your DT (CLK_SPI2S1_PLL3R). This clock is maybe too high.

For register field description, refer to STM32MP157C reference manual.

Are your sure to have regenerated and correctly flashed the updated TF-A binary, uBoot FIP and kernel DT ?

Worth to look at effective clock setup, see https://wiki.st.com/stm32mpu/wiki/Clock_overview#How_to_trace_and_debug_the_framework

Could be worth to see if SPI1 is accessible (i.e. clocked) from M4 by reading a known register, e.g. SPI1_SIDR register (address is 0x440043FC), returned value should be 0xA3C5DD01.

Regards.

In order 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.

Hello PatrickF,

thank you for the hints.

It may not be wise to talk about the diff above, so I'll add the patched devicetree for our yocto build here

// SPDX-License-Identifier: GPL-2.0
/*
 *  Copyright (C) 2019 bytes at work AG - http://www.bytesatwork.ch
 */
 
/dts-v1/;
 
#include "stm32mp157c-byteengine-m5.dtsi"
 
/ {
	model = "hp00164";
	compatible = "mesomatic,hp00164", "batw,m5", "st,stm32mp157";
 
	aliases {
		serial0 = &uart4;
		spi0 = &qspi;
	};
 
	chosen {
		stdout-path = "serial0:115200n8";
	};
 
	memory@c0000000 {
		reg = <0xc0000000 0x20000000>;
	};
 
	usb_phy_tuning: usb-phy-tuning {
		st,hs-dc-level = <2>;
		st,fs-rftime-tuning;
		st,hs-rftime-reduction;
		st,hs-current-trim = <15>;
		st,hs-impedance-trim = <1>;
		st,squelch-level = <3>;
		st,hs-rx-offset = <2>;
		st,no-lsfs-sc;
	};
 
	usb_vbus: regulator-vbus {
		compatible = "regulator-fixed";
		regulator-name = "usb_en_vbus";
		gpio = <&gpiob 13 GPIO_ACTIVE_HIGH>;
		enable-active-high;
	};
};
 
&pinctrl {
	uart4_pins: uart4 {
		pins1 {
			pinmux = <STM32_PINMUX('H', 13, AF8)>; /* UART4_TX */
			bias-disable;
			drive-push-pull;
			slew-rate = <0>;
		};
 
		pins2 {
			pinmux = <STM32_PINMUX('H', 14, AF8)>; /* UART4_RX */
			bias-disable;
		};
	};
 
	uart4_idle_pins: uart4-idle {
		pins1 {
			pinmux = <STM32_PINMUX('H', 13, ANALOG)>; /* UART4_TX */
		};
 
		pins2 {
			pinmux = <STM32_PINMUX('H', 14, AF8)>; /* UART4_RX */
			bias-disable;
		};
	};
 
	uart4_sleep_pins: uart4-sleep {
		pins {
			pinmux = <STM32_PINMUX('H', 13, ANALOG)>, /* UART4_TX */
				 <STM32_PINMUX('H', 14, ANALOG)>; /* UART4_RX */
		};
	};
};
 
&pinctrl_z {
	u-boot,dm-pre-reloc;
 
	m4_spi1_pins_z_mx: m4_spi1_mx-0 {
		pins {
			pinmux = <STM32_PINMUX('Z', 0, RSVD)>, /* SPI1_SCK */
					 <STM32_PINMUX('Z', 1, RSVD)>, /* SPI1_MISO */
					 <STM32_PINMUX('Z', 2, RSVD)>; /* SPI1_MOSI */
		};
	};
};
 
&uart4 {
	pinctrl-names = "default", "sleep", "idle", "no_console_suspend";
	pinctrl-0 = <&uart4_pins>;
	pinctrl-1 = <&uart4_sleep_pins>;
	pinctrl-2 = <&uart4_idle_pins>;
	pinctrl-3 = <&uart4_pins>;
	status = "okay";
};
 
&sdmmc1 {
	pinctrl-names = "default", "opendrain", "sleep";
	pinctrl-0 = <&sdmmc1_b4_pins_a>;
	pinctrl-1 = <&sdmmc1_b4_od_pins_a>;
	pinctrl-2 = <&sdmmc1_b4_sleep_pins_a>;
	broken-cd;
	st,neg-edge;
	bus-width = <4>;
	vmmc-supply = <&v3v3>;
	status = "okay";
};
 
&usbh_ehci {
	phys = <&usbphyc_port0>;
	phy-names = "usb";
	vbus-supply = <&usb_vbus>;
	status = "okay";
};
 
&usbphyc {
	vdd3v3-supply = <&vdd_usb>;
	status = "okay";
};
 
&usbphyc_port0 {
	st,phy-tuning = <&usb_phy_tuning>;
};
 
&m4_spi1{
	pinctrl-names = "default";
	pinctrl-0 = <&m4_spi1_pins_z_mx>;
	status = "okay";
};
 
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
/*
 * Copyright : STMicroelectronics 2018
 */
 
#include <dt-bindings/clock/stm32mp1-clksrc.h>
#include "stm32mp15-u-boot.dtsi"
#include "stm32mp15-ddr3-1x4Gb-1066-binG.dtsi"
 
/ {
	aliases {
		i2c3 = &i2c4;
		mmc0 = &sdmmc1;
		spi0 = &qspi;
	};
};
 
&clk_hse {
	st,digbypass;
};
 
&i2c4 {
	u-boot,dm-pre-reloc;
};
 
&i2c4_pins_a {
	u-boot,dm-pre-reloc;
	pins {
		u-boot,dm-pre-reloc;
	};
};
 
&pmic {
	u-boot,dm-pre-reloc;
};
 
&rcc {
	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_HSE
		CLK_FMC_ACLK
		CLK_QSPI_ACLK
		CLK_ETH_PLL4P
		CLK_SDMMC12_PLL4P
		CLK_DSI_DSIPLL
		CLK_STGEN_HSE
		CLK_USBPHY_HSE
		CLK_SPI2S1_PLL3Q
		CLK_SPI2S23_PLL3Q
		CLK_SPI45_HSI
		CLK_SPI6_HSI
		CLK_I2C46_HSI
		CLK_SDMMC3_PLL4P
		CLK_USBO_USBPHY
		CLK_ADC_CKPER
		CLK_CEC_LSE
		CLK_I2C12_HSI
		CLK_I2C35_HSI
		CLK_UART1_HSI
		CLK_UART24_HSI
		CLK_UART35_HSI
		CLK_UART6_HSI
		CLK_UART78_HSI
		CLK_SPDIF_PLL4P
		CLK_FDCAN_PLL4Q
		CLK_SAI1_PLL3Q
		CLK_SAI2_PLL3Q
		CLK_SAI3_PLL3Q
		CLK_SAI4_PLL3Q
		CLK_RNG1_LSI
		CLK_RNG2_LSI
		CLK_LPTIM1_PCLK1
		CLK_LPTIM23_PCLK3
		CLK_LPTIM45_LSE
	>;
 
	/* VCO = 1300.0 MHz => P = 650 (CPU) */
	pll1: st,pll@0 {
		cfg = < 2 80 0 0 0 PQR(1,0,0) >;
		frac = < 0x800 >;
		u-boot,dm-pre-reloc;
	};
 
	/* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */
	pll2: st,pll@1 {
		cfg = < 2 65 1 0 0 PQR(1,1,1) >;
		frac = < 0x1400 >;
		u-boot,dm-pre-reloc;
	};
 
	/* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */
	pll3: st,pll@2 {
		cfg = < 2 50 1 16 36 PQR(1,1,1) >;
		frac = < 0x1a04 >;
		u-boot,dm-pre-reloc;
	};
 
	/* VCO = 750.0 MHz => P = 125, Q = 62.5, R = 62.5 */
	pll4: st,pll@3 {
		cfg = < 3 124 5 11 11 PQR(1,1,1) >;
		u-boot,dm-pre-reloc;
	};
};
 
&sdmmc1 {
	u-boot,dm-spl;
};
 
&sdmmc1_b4_pins_a {
	u-boot,dm-spl;
	pins1 {
		u-boot,dm-spl;
	};
	pins2 {
		u-boot,dm-spl;
	};
};
 
&uart4 {
	u-boot,dm-pre-reloc;
};
 
 
&flash0 {
	compatible = "spi-flash";
	u-boot,dm-spl;
};
 
&qspi {
	u-boot,dm-spl;
};
 
&qspi_clk_pins_a {
	u-boot,dm-spl;
	pins {
		u-boot,dm-spl;
	};
};
 
&qspi_bk1_pins_a {
	u-boot,dm-spl;
	pins1 {
		u-boot,dm-spl;
	};
	pins2 {
		u-boot,dm-spl;
	};
};
 
&uart4_pins {
	u-boot,dm-pre-reloc;
	pins1 {
		u-boot,dm-pre-reloc;
	};
	pins2 {
		u-boot,dm-pre-reloc;
	};
};
 
&v3v3 {
	regulator-always-on;
};

PLL3_Q should be the correct one. But we could try to lower the PLL3_Q Freq.

I have also check the address 0x440043F. The value is 0xA3C5DD01.

I have attach the output of /sys/kernel/debug/clk/clk_summary

Sound like the pll3_q is not enabled by Linux, I'm not expert on that. SPI5 was working as on a clock already enabled.

Maybe need to enable the resource manager:

&m4_rproc {
	m4_system_resources {
		status = "okay";
	};
};

You could maybe also try with CLK_SPI2S1_CKPER (which is enabled by default).

Regards.

In order 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.

Hello PatrickF,

i have changed the CLK_SPI2S1_PLL3Q to CLK_SPI2S1_CKPER and rebuild our yocto image. Now we can see an clock for the SPI1 and no timout ocures:grinning_face: . Do you have any idea what else is involved in activating pll3_q ?

The resource manager is already enabled in a sub layer ("stm32mp157c-byteengine-m5.dtsi") of our device tree.

We are investigating. clocks should be started when the M4 coprocessor FW is started by Linux.

Could you check that when you start your M4 application thru sysfs (see https://wiki.st.com/stm32mpu/wiki/Linux_remoteproc_framework_overview#Remote_processor_boot_through_sysfs), you get a console message such as the following ?

[xxxx.xxxx] remoteproc remoteproc0: Booting fw image xxxx.elf, size xxxx
...
[xxxx.xxxx] rproc-srm-core 10000000.m4:m4_system_resources: bound 10000000.m4:m4_system_resources:spi@44004000 (ops xxxx)
...

Regards.

In order 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.