cancel
Showing results for 
Search instead for 
Did you mean: 

Major issue with eMMC 8 bit

JOhn1
Associate III

We are currently experiencing a major issue with eMMC on our custom boards using STM32MP153CAC. Our boards are booting normally with 1 wire mode, but as soon as 8 wire/bit mode is enabled, it starts to bug out.

Here is the description of the problem from our linux developer:


- Starts up on 8 bit bus width, but
- Does not stay at 8 bit bus width
- And after it falls back to 4 bit, it tries to switch back to 8 bit, but fails
- The clock seems to "only" be 27 MHz, and not 52 MHz
- The actual read and write speed is lower then it should be, 8 bit DDR52 should be around 50 MByte/s read and 30 MByte/s write
but it looks to be more around 2-3 MBytes/s
- Read and write bigger file seems to prevoke the from 8 bit to 4 bit
- If configured to start at 4 bit DDR52, fallback 4 bit mmc high-speed (not DDR)

Here is information about the PCB:
- 8 layer
- We only use 3.3V for the emmc, on both power domains

- Here is how the emmc is connected
emmc_circuit.PNG
Here is information on clock set up in TF-A:

&etzpc{
	secure-status = "okay";
	st,decprot = <
	/*"NS_R S_W" peripherals*/
	DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)
	DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)
	/*"Non Secured" peripherals*/
	DECPROT(STM32MP1_ETZPC_ADC_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
	DECPROT(STM32MP1_ETZPC_TT_FDCAN_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
	DECPROT(STM32MP1_ETZPC_ETH_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
	DECPROT(STM32MP1_ETZPC_FMC_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
	DECPROT(STM32MP1_ETZPC_SPI1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
	DECPROT(STM32MP1_ETZPC_SPI2_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
	DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
	DECPROT(STM32MP1_ETZPC_DMA1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
	DECPROT(STM32MP1_ETZPC_DMAMUX_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
	DECPROT(STM32MP1_ETZPC_FMC_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
	DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
	DECPROT(STM32MP1_ETZPC_SPI1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
	DECPROT(STM32MP1_ETZPC_SPI2_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
	DECPROT(STM32MP1_ETZPC_UART4_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
	DECPROT(STM32MP1_ETZPC_UART5_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
	DECPROT(STM32MP1_ETZPC_UART7_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
	DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
	DECPROT(STM32MP1_ETZPC_USART2_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
	DECPROT(STM32MP1_ETZPC_USART3_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
	DECPROT(STM32MP1_ETZPC_USART6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
	DECPROT(STM32MP1_ETZPC_TIM1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
	/*"Secured" peripherals*/
	DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_UNLOCK)
	/*"Mcu Isolation" peripherals*/
	DECPROT(STM32MP1_ETZPC_DMA2_ID, DECPROT_MCU_ISOLATION, DECPROT_UNLOCK)

	/*Restriction: following IDs are not managed  - please to use User-Section if needed:
		  STM32MP1_ETZPC_SRAMx_ID  STM32MP1_ETZPC_RETRAM_ID  STM32MP1_ETZPC_BKPSRAM_ID*/

	/* USER CODE BEGIN etzpc_decprot */
		/*STM32CubeMX generates a basic and standard configuration for ETZPC.
		Additional device configurations can be added here if needed.
		"etzpc" node could be also overloaded in "addons" User-Section.*/
	/* USER CODE END etzpc_decprot */
	>;

	/* USER CODE BEGIN etzpc */
	/* USER CODE END etzpc */
};

&rcc{
	status = "okay";
	secure-status = "disabled";
	st,csi-cal;
	st,hsi-cal;
	st,cal-sec = <60>;
	st,clksrc=<
		CLK_MPU_PLL1P
		CLK_AXI_PLL2P
		CLK_MCU_HSI
		CLK_PLL12_HSE
		CLK_PLL3_HSE
		CLK_PLL4_HSE
		CLK_RTC_LSI
		CLK_MCO1_DISABLED
		CLK_MCO2_DISABLED
	>;
	st,clkdiv = <
		1 		/*MPU*/
		3 		/*AXI*/
		0 		/*MCU*/
		0 		/*APB1*/
		0 		/*APB2*/
		0 		/*APB3*/
		0 		/*APB4*/
		0 		/*APB5*/
		0 		/*RTC*/
		0 		/*MCO1*/
		0 		/*MCO2*/
	>;
	st,pkcs = <
		CLK_CKPER_DISABLED
		CLK_FMC_ACLK
		CLK_ETH_PLL4P
		CLK_SDMMC12_PLL4P
		CLK_STGEN_HSE
		CLK_USBPHY_PLL4R
		CLK_SPI2S1_PLL4P
		CLK_SPI2S23_PLL4P
		CLK_SPI45_DISABLED
		CLK_SPI6_DISABLED
		CLK_I2C46_PCLK5
		CLK_SDMMC3_DISABLED
		CLK_ADC_PLL4R
		CLK_CEC_DISABLED
		CLK_I2C12_DISABLED
		CLK_I2C35_DISABLED
		CLK_UART1_HSE
		CLK_UART24_HSE
		CLK_UART35_HSE
		CLK_UART6_HSE
		CLK_UART78_HSE
		CLK_SPDIF_DISABLED
		CLK_SAI1_DISABLED
		CLK_SAI2_DISABLED
		CLK_SAI3_DISABLED
		CLK_SAI4_DISABLED
		CLK_LPTIM1_DISABLED
		CLK_LPTIM23_DISABLED
		CLK_LPTIM45_DISABLED
		CLK_FDCAN_HSE
	>;
	pll2:st,pll@1 {
		compatible = "st,stm32mp1-pll";
		reg = <1>;
		cfg = < 0 35 1 1 1 PQR(1,0,1) >;
	};
	pll3:st,pll@2 {
		compatible = "st,stm32mp1-pll";
		reg = <2>;
		cfg = < 2 124 1 3 1 PQR(0,1,0) >;
	};
	pll4:st,pll@3 {
		compatible = "st,stm32mp1-pll";
		reg = <3>;
		cfg = < 0 35 3 4 17 PQR(1,1,0) >;
	};

	/* USER CODE BEGIN rcc */
	/* USER CODE END rcc */
};

Here is the initial configuration of the eMMC using u-boot:

enable_emmc_boot_partition=echo "Setting emmc device and boot partitions"; mmc dev "${emmc_device}"; mmc partconf 1 1 1 1;



Here is our device tree configuration of the eMMC with linux:

&sdmmc2{
	pinctrl-names = "default", "opendrain", "sleep";
	pinctrl-0 = <&sdmmc2_pins_mx>;
	pinctrl-1 = <&sdmmc2_opendrain_pins_mx>;
	pinctrl-2 = <&sdmmc2_sleep_pins_mx>;
	bus-width = <8>;
	non-removable;
	no-sd;
	no-sdio;
	no-1-8-v;
	st,neg-edge;
	mmc-ddr-3_3v;
	vmmc-supply = <&reg_3v3>;
	vqmmc-supply = <&reg_3v3>;
	status = "okay";
};


Linux kernel version: 5.10.61 med STM patch stm32mp1-5.10.61-r2

9 REPLIES 9

No series resistors? Usually designs have 27R or 33R to stop ringing. Traces also need matched lengths.

DDR implies data on both clock edges. DDR104 would have 52 MHz clock, not 104 MHz, although clock within peripheral will likely be higher internally.

Throughput on eMMC dictated by device, different brands have different performance.

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

Only series resistor on EMMC_CLK line. (See attached photo below)
emmc_mpu_circuit.png

We read this out from our kernel:

clock:		52000000 Hz
actual clock:	27000000 Hz
vdd:		21 (3.3 ~ 3.4 V)
bus mode:	2 (push-pull)
chip select:	0 (don't care)
power mode:	2 (on)
bus width:	3 (8 bits)
timing spec:	8 (mmc DDR52)
signal voltage:	0 (3.30 V)
driver type:	0 (driver type B)

And after running multiple threads it falls back to:

cat /sys/kernel/debug/mmc1/ios                                                                                                2000-01-01 01:04:39

clock:		52000000 Hz
actual clock:	27000000 Hz
vdd:		21 (3.3 ~ 3.4 V)
bus mode:	2 (push-pull)
chip select:	0 (don't care)
power mode:	2 (on)
bus width:	2 (4 bits)
timing spec:	8 (mmc DDR52)
signal voltage:	0 (3.30 V)
driver type:	0 (driver type B)
PatrickF
ST Employee

Hi @JOhn1 ,

27 MHz whereas 52MHz requested might depend on which combination the driver has found be not be above the 52MHz. Could you please share clock summary.

cat /sys/kernel/debug/clk/clk_summary

I think the issue of 8-bit to 4-bit is not linked to 27MHz clocking.

 

Did you have checked signal/power integrity on your board ?

Is the serie resistor on SDMMC2_CLK close to signal source ?

Is the eMMC far away from STM32MP15x ?

Did you enable more log from related Linux driver to see if there is details/explanation of the fallback from 8-bits to 4-bits ?

Could you share the eMMC reference you are using ? Did you tried another brand ?

For read and write performances, it depend on the memory itself, the driver efficiency as well as processor load.

 

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.

Failure suggests you have a signal integrity issue, and perhaps skewing of different data lines vs clock.

Would look critically at path lengths and drive strength settings. On the MCU series SPEEDR can be reduced on short trace, low load pin paths.

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

Agreed.

AN5031 recommend SPEEDR = 1 for ALL SDMMC1 signals when used up to DDR 52MHz up to 30pF (assuming relatively short track, 5-7 cm max).

Higher IO speed setting is sometimes getting worse results.

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.

@PatrickF wrote:

Hi @JOhn1 ,

27 MHz whereas 52MHz requested might depend on which combination the driver has found be not be above the 52MHz. Could you please share clock summary.

 

cat /sys/kernel/debug/clk/clk_summary

 


Clock Summary output is attached.


@PatrickF wrote:

Did you have checked signal/power integrity on your board ?


We are measuring D0 and CLK to see if any ringing or distortion is present on the signal. Currently we are running into issues with out probes not being capable to measure at those frequencies. Our latest measurements indicate good signal integrity, I will post a screenshot from the oscilloscope tomorrow.


@PatrickF wrote:

Is the serie resistor on SDMMC2_CLK close to signal source ?


Yes, according to our EDA tool, 3.75 mm from pad to pad. The series resistor is on same layer as IC, so getting it any closer would require us to move it to the opposite side.


@PatrickF wrote:

Is the eMMC far away from STM32MP15x ?


Each trace is matched withing 10 mil (0,254 mm) and each trace is 27,7 mm long (CLK, CMD D0-D7).


@PatrickF wrote:

Did you enable more log from related Linux driver to see if there is details/explanation of the fallback from 8-bits to 4-bits ?

Not sure what options are available.


@PatrickF wrote:

Could you share the eMMC reference you are using ? Did you tried another brand ?

The layout is according to the the reference design in AN5031 rev4.
It is our first design using eMMC, as we have many tens of thousands products using raw NAND flash, which also since transitioning to STM32mp153 have worked well. The particular emmc used is ASFC4G31M-51BIN from Alliance.









Our signal path lengths are 27 mm from pad to pad.
Perhaps our drive strenght is too much or what when at these shorter distances?

Hi,

I see HSE at 12MHz whereas it should be 24MHz. did you really use 12MHz and define it like that in DT ?

I see also your AXI is running at 54MHz (instead of up to 266MHz) and the DDR (PLL2) at 216MHz (instead of up to 533MHz). This would explain some issues (performance and stability).

You likely need to check and revise your overall clocking definitions of your platform.

Please have a look to

https://wiki.st.com/stm32mpu/wiki/STM32MP15_clock_tree

(or https://wiki.st.com/stm32mpu-ecosystem-v4/wiki/STM32MP15_clock_tree if you are still on ecosystem V4.x)

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.

@PatrickF wrote:

Hi,

I see HSE at 12MHz whereas it should be 24MHz. did you really use 12MHz and define it like that in DT ?

I see also your AXI is running at 54MHz (instead of up to 266MHz) and the DDR (PLL2) at 216MHz (instead of up to 533MHz). This would explain some issues (performance and stability).

You likely need to check and revise your overall clocking definitions of your platform.

Please have a look to

https://wiki.st.com/stm32mpu/wiki/STM32MP15_clock_tree

(or https://wiki.st.com/stm32mpu-ecosystem-v4/wiki/STM32MP15_clock_tree if you are still on ecosystem V4.x)

Regards.


We use a 12 MHz clock crystal for the HSE.