STMicroelectronics / stm32l4xx_hal_driver

Provides the STM32Cube MCU Component "hal_driver" of the STM32L4 series.
BSD 3-Clause "New" or "Revised" License
35 stars 15 forks source link

It seems that STM32L476 is capable for 4-bit SD/MMC bus, but it's not supported. #17

Closed attie-argentum closed 4 months ago

attie-argentum commented 5 months ago

Describe the set-up

I'm using a NUCLEO-L476RG with Zephyr (f51c8ee739).

Describe the bug

While trying to use a 4-bit SD/MMC bus, the system locks up... when using 1-bit bus the system works fine.

On investigation, it seems that this driver will never communicate the changed bus width with the card, resulting in a breakdown in stm32_sdmmc_access_read().

How To Reproduce

`.../samples/subsys/shell/shell_module/prj.conf` ```patch diff --git samples/subsys/shell/shell_module/prj.conf samples/subsys/shell/shell_module/prj.conf index 41d51f8e22..98567901fd 100644 --- samples/subsys/shell/shell_module/prj.conf +++ samples/subsys/shell/shell_module/prj.conf @@ -1,5 +1,6 @@ CONFIG_PRINTK=y CONFIG_SHELL=y +CONFIG_SHELL_STACK_SIZE=16384 CONFIG_LOG=y CONFIG_LOG_CMDS=y CONFIG_INIT_STACKS=y @@ -15,3 +16,24 @@ CONFIG_THREAD_RUNTIME_STATS=y CONFIG_THREAD_RUNTIME_STATS_USE_TIMING_FUNCTIONS=y CONFIG_STATS=y CONFIG_STATS_SHELL=y + +CONFIG_HEAP_MEM_POOL_SIZE=8192 + +CONFIG_I2C=y +CONFIG_I2C_SHELL=y + +CONFIG_DISK_DRIVERS=y +CONFIG_DISK_DRIVER_SDMMC=y +CONFIG_SDHC=y +CONFIG_FILE_SYSTEM=y +CONFIG_FILE_SYSTEM_SHELL=y +CONFIG_FILE_SYSTEM_SHELL_TEST_COMMANDS=y +CONFIG_FILE_SYSTEM_SHELL_BUFFER_SIZE=0x2000 +CONFIG_FAT_FILESYSTEM_ELM=y +CONFIG_FS_FATFS_MOUNT_MKFS=n +CONFIG_FS_FATFS_EXFAT=y + +CONFIG_CAN=y +CONFIG_CAN_SHELL=y + +CONFIG_GPIO_SHELL=y ```
`.../samples/subsys/shell/shell_module/boards/nucleo_l476rg.overlay` ```dts /delete-node/ &spi3; &sdmmc1 { bus-width = <4>; clk-div = <0>; pinctrl-0 = < &sdmmc1_ck_pc12 &sdmmc1_cmd_pd2 &sdmmc1_d0_pc8 &sdmmc1_d1_pc9 &sdmmc1_d2_pc10 &sdmmc1_d3_pc11 >; pinctrl-names = "default"; status = "okay"; }; &clk_msi { msi-range = <11>; /* ~48 MHz */ status = "okay"; }; ```
KRASTM commented 5 months ago

Hello @attie-argentum,

Thank you for this report, can you please share the reference and type of the SD card.

With regards.

attie-argentum commented 5 months ago

Hi @KRASTM,

I've primarily been using a SanDisk Extreme (32 GB, U3, UHS-I), but have also tried on a fairly generic 2GB Transcend card.

sromion commented 5 months ago

I've had a lot of problems with consumer cards (Sandisk, Samsung, etc.). SwissBit references are more stable. My case is not the truth ^^

KRASTM commented 5 months ago

ST Internal Reference: 179876

KRASTM commented 5 months ago

Hello @attie-argentum,

Pending the official fix, there is a work around that may help you to unblock the situation.

First you initialize your SD card with 1 bit bus width within the function HAL_SD_Init(). After that you can use the function HAL_SD_ConfigWideBusOperation with SDMMC_BUS_WIDE_4B.

I hope it will be useful. With regards.

attie-argentum commented 5 months ago

Hi @KRASTM,

Thanks for the potential workaround... unfortunately this has exposed another (unexpected) issue in SD_FindSCR(), where the loop below appears to exist cleanly after zero or one calls to SDMMC_ReadFIFO()... am I correct to expect 2 here?

https://github.com/STMicroelectronics/stm32l4xx_hal_driver/blob/0c6d747f576a62bdeb8b29ed665fbc515b2827ed/Src/stm32l4xx_hal_sd.c#L3961-L3973

For me, this leaves the scr[2] buffer in SD_WideBus_Enable() with the following contents... the first results in HAL_SD_ERROR_REQUEST_NOT_APPLICABLE, and the second results in a crash later in Zephyr (see below), even though there is now a non-zero SCR value present, and it appears to succeed.

00 00 00 00 00 00 00 00

or

00 00 00 00 43 84 35 02
`index=0`, results in 1-bit mode ``` *** Booting Zephyr OS build zephyr-v3.5.0-4761-g8c80a0693968 *** PK: WEST_TOPDIR/modules/hal/stm32/stm32cube/stm32l4xx/drivers/src/stm32l4xx_hal_sd.c:3981 SD_FindSCR(): index: 0 PK: WEST_TOPDIR/modules/hal/stm32/stm32cube/stm32l4xx/drivers/src/stm32l4xx_hal_sd.c:3829 SD_WideBus_Enable(): DUMP: SCR PK: WEST_TOPDIR/modules/hal/stm32/stm32cube/stm32l4xx/drivers/src/stm32l4xx_hal_sd.c:3829 SD_WideBus_Enable(): DUMP: 8 bytes @ 0x200035c8 PK: WEST_TOPDIR/modules/hal/stm32/stm32cube/stm32l4xx/drivers/src/stm32l4xx_hal_sd.c:3829 SD_WideBus_Enable(): DUMP: ---8<---[ dump begins ]---8<--- PK: WEST_TOPDIR/modules/hal/stm32/stm32cube/stm32l4xx/drivers/src/stm32l4xx_hal_sd.c:3829 SD_WideBus_Enable(): DUMP: 0x0000: 00 00 00 00 00 00 00 00 | ........ PK: WEST_TOPDIR/modules/hal/stm32/stm32cube/stm32l4xx/drivers/src/stm32l4xx_hal_sd.c:3829 SD_WideBus_Enable(): DUMP: ---8<---[ dump ends ]---8<--- PK: WEST_TOPDIR/modules/hal/stm32/stm32cube/stm32l4xx/drivers/src/stm32l4xx_hal_sd.c:3830 SD_WideBus_Enable(): scr[1U] & ((uint32_t)0x00040000U): 0x00000000 [00:00:00.110,000] stm32_sdmmc: failed to set bus width to 4-bit... (ErrorCode 0x4000000) Mount /SD:: 0 /SD:: bsize = 512 ; frsize = 32768 ; blocks = 973584 ; bfree = 973127 [00:00:00.181,000] main: The device is put in USB mass storage mode. ```
`index=1`, results in 4-bit mode, with later MPU FAULT ``` *** Booting Zephyr OS build zephyr-v3.5.0-4761-g8c80a0693968 *** PK: WEST_TOPDIR/modules/hal/stm32/stm32cube/stm32l4xx/drivers/src/stm32l4xx_hal_sd.c:3981 SD_FindSCR(): index: 1 PK: WEST_TOPDIR/modules/hal/stm32/stm32cube/stm32l4xx/drivers/src/stm32l4xx_hal_sd.c:3829 SD_WideBus_Enable(): DUMP: SCR PK: WEST_TOPDIR/modules/hal/stm32/stm32cube/stm32l4xx/drivers/src/stm32l4xx_hal_sd.c:3829 SD_WideBus_Enable(): DUMP: 8 bytes @ 0x200035c8 PK: WEST_TOPDIR/modules/hal/stm32/stm32cube/stm32l4xx/drivers/src/stm32l4xx_hal_sd.c:3829 SD_WideBus_Enable(): DUMP: ---8<---[ dump begins ]---8<--- PK: WEST_TOPDIR/modules/hal/stm32/stm32cube/stm32l4xx/drivers/src/stm32l4xx_hal_sd.c:3829 SD_WideBus_Enable(): DUMP: 0x0000: 00 00 00 00 43 84 35 02 | ....C.5. PK: WEST_TOPDIR/modules/hal/stm32/stm32cube/stm32l4xx/drivers/src/stm32l4xx_hal_sd.c:3829 SD_WideBus_Enable(): DUMP: ---8<---[ dump ends ]---8<--- PK: WEST_TOPDIR/modules/hal/stm32/stm32cube/stm32l4xx/drivers/src/stm32l4xx_hal_sd.c:3830 SD_WideBus_Enable(): scr[1U] & ((uint32_t)0x00040000U): 0x00040000 PK: WEST_TOPDIR/modules/hal/stm32/stm32cube/stm32l4xx/drivers/src/stm32l4xx_hal_sd.c:3836 SD_WideBus_Enable(): SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U)) --> 0 PK: WEST_TOPDIR/modules/hal/stm32/stm32cube/stm32l4xx/drivers/src/stm32l4xx_hal_sd.c:3843 SD_WideBus_Enable(): SDMMC_CmdBusWidth(hsd->Instance, 2U) --> 0 Mount /SD:: 0 /SD:: bsize = 512 ; frsize = 32768 ; blocks = 973584 ; bfree = 973127 [00:00:00.201,000] main: The device is put in USB mass storage mode. [00:00:01.709,000] os: ***** MPU FAULT ***** [00:00:01.715,000] os: Stacking error (context area might be not valid) [00:00:01.723,000] os: Data Access Violation [00:00:01.728,000] os: MMFAR Address: 0x20001abc [00:00:01.734,000] os: r0/a1: 0xf0040018 r1/a2: 0xf104fdb6 r2/a3: 0xf04f0758 [00:00:01.743,000] os: r3/a4: 0x6da50800 r12/ip: 0xd0da42bd r14/lr: 0xd0d82d00 [00:00:01.752,000] os: xpsr: 0xf105fc00 [00:00:01.757,000] os: Faulting instruction address (r15/pc): 0xf0044628 [00:00:01.765,000] os: >>> ZEPHYR FATAL ERROR 2: Stack overflow on CPU 0 [00:00:01.773,000] os: Current thread: 0x200002e0 (unknown) [00:00:01.780,000] os: Halting system ```
Zephyr Patch On top of: https://github.com/zephyrproject-rtos/zephyr/commit/f51c8ee73906e7414c7ff1c30e71978437616e71 (and above changes), [`sdmmc_stm32.c`](https://github.com/zephyrproject-rtos/zephyr/blob/f51c8ee73906e7414c7ff1c30e71978437616e71/drivers/disk/sdmmc_stm32.c) ```patch diff --git drivers/disk/sdmmc_stm32.c drivers/disk/sdmmc_stm32.c index 71c2c7cab8..fb2edebf7f 100644 --- drivers/disk/sdmmc_stm32.c +++ drivers/disk/sdmmc_stm32.c @@ -295,6 +295,11 @@ static int stm32_sdmmc_access_init(struct disk_info *disk) return -EIO; } + err = HAL_SD_ConfigWideBusOperation(&priv->hsd, SDMMC_BUS_WIDE_4B); + if (err != HAL_OK) { + LOG_ERR("failed to set bus width to 4-bit... (ErrorCode 0x%X)", priv->hsd.ErrorCode); + } + #ifdef CONFIG_SDMMC_STM32_HWFC stm32_sdmmc_fc_enable(priv); #endif ```
HAL STM32 Patch On top of https://github.com/zephyrproject-rtos/hal_stm32/commit/22925907a6faeb601fc9a0d8cbb65c4b26d38043, [`stm32l4xx_hal_sd.c`](https://github.com/zephyrproject-rtos/hal_stm32/blob/22925907a6faeb601fc9a0d8cbb65c4b26d38043/stm32cube/stm32l4xx/drivers/src/stm32l4xx_hal_sd.c) `pk.h` is a thin debug / insight tool, here: https://github.com/attie/print-macros/blob/master/pk.h ```patch diff --git stm32cube/stm32l4xx/drivers/src/stm32l4xx_hal_sd.c stm32cube/stm32l4xx/drivers/src/stm32l4xx_hal_sd.c index 62621261..4b0cd122 100644 --- stm32cube/stm32l4xx/drivers/src/stm32l4xx_hal_sd.c +++ stm32cube/stm32l4xx/drivers/src/stm32l4xx_hal_sd.c @@ -1,3 +1,4 @@ +#include /** ****************************************************************************** * @file stm32l4xx_hal_sd.c @@ -3824,18 +3825,21 @@ static uint32_t SD_WideBus_Enable(SD_HandleTypeDef *hsd) return errorstate; } + PKDUMP(scr, sizeof(scr), "SCR"); + PKV("0x%08x", scr[1U] & SDMMC_WIDE_BUS_SUPPORT); + /* If requested card supports wide bus operation */ if((scr[1U] & SDMMC_WIDE_BUS_SUPPORT) != SDMMC_ALLZERO) { /* Send CMD55 APP_CMD with argument as card's RCA.*/ - errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U)); + errorstate = PKR(uint32_t, "%d", SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U))); if(errorstate != HAL_SD_ERROR_NONE) { return errorstate; } /* Send ACMD6 APP_CMD with argument as 2 for wide bus mode */ - errorstate = SDMMC_CmdBusWidth(hsd->Instance, 2U); + errorstate = PKR(uint32_t, "%d", SDMMC_CmdBusWidth(hsd->Instance, 2U)); if(errorstate != HAL_SD_ERROR_NONE) { return errorstate; @@ -3971,6 +3975,7 @@ static uint32_t SD_FindSCR(SD_HandleTypeDef *hsd, uint32_t *pSCR) return HAL_SD_ERROR_TIMEOUT; } } + PKV("%d", index); #endif /* STM32L4P5xx || STM32L4Q5xx || STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT)) ```
KRASTM commented 5 months ago

Hello @attie-argentum,

In fact, I have already tested an example with an eval board, and it's working fine. Juste be sure that the value of BusWide is 1bit within the structure SD_HandleTypeDef while initializing the SD Card. After that you can change the config to 4bit with HAL_SD_ConfigWideBusOperation.

With regards.

RJMSTM commented 4 months ago

Fixed in https://github.com/STMicroelectronics/stm32l4xx_hal_driver/commit/5f7138a2bfb8a7e76a3ac7c3d39314ec365145f8

attie-argentum commented 4 months ago

Many thanks for this patch... I've finally got around to testing it(!) - though unfortunately it still doesn't work with Zephyr. I manually applied 5f7138a2bfb8a7e76a3ac7c3d39314ec365145f8 onto zephyrproject-rtos/hal_stm32, but no joy. I will investigate further at some point, but I'm very busy at the moment.

uart:~$ fs mount fat /SD:
Error mounting FAT fs. Error Code [-5]
[00:00:00.562,000] <err> stm32_sdmmc: sd read error 36
[00:00:00.562,000] <err> fs: fs mount error (-5)

I'll raise an issue, as I suspect this may now be a Zephyr driver issue.