Skip to content

[BACKPORT] mmcsd: eMMC 4-bit wide bus support for STM32 - #390

Open
13022591351 wants to merge 9 commits into
PX4:px4_firmware_nuttx-10.3.0+from
13022591351:backport-emmc-4bit-widebus
Open

[BACKPORT] mmcsd: eMMC 4-bit wide bus support for STM32#390
13022591351 wants to merge 9 commits into
PX4:px4_firmware_nuttx-10.3.0+from
13022591351:backport-emmc-4bit-widebus

Conversation

@13022591351

Copy link
Copy Markdown
Contributor

Summary

Backport the eMMC/MMC 4-bit wide bus support from upstream NuttX to
px4_firmware_nuttx-10.3.0+.

This supersedes #387, which implemented the same feature as a single
squashed commit that did not follow the PX4/NuttX backport conventions.
The two upstream commits carrying this feature have since been merged in
apache/nuttx, so this PR redoes the change as proper [BACKPORT]
cherry-picks with full upstream traceability.

Backported upstream commits (in dependency order):

The first seven are prerequisites of the final two: they introduce the
MMC CMD6 bus-width switch path, the EXT_CSD access macros, and the
SDIO_WIDEBUS condition fix that the sequencing fix modifies. Without
5238c3b the chain would also regress SD card 4-bit operation.

Deviations from upstream (documented in the respective commit messages):

  • struct mmcsd_state_s still lives in mmcsd_sdio.c on this branch;
    the mode:2 -> mode:4 bitfield change is applied there.
  • MMCSD_USLEEP does not exist on this branch; nxsig_usleep is used
    instead, matching the surrounding code.
  • Upstream's arch/arm/src/common/stm32/stm32_sdio_m3m4_v1.c exists as
    arch/arm/src/stm32/stm32_sdio.c on this branch; the common-driver
    change is applied there.

Impact

  • eMMC on STM32H7/F7/L4 hosts can now switch to 4-bit bus: the host is
    switched to wide bus before CMD6, and the transfer clock is selected
    before the switch sequence, fixing data transfer timeouts and the bus
    being stuck at ~400 kHz.
  • No behavior change for SD cards beyond restoring correct widebus
    handling, and no change on hosts whose widebus callback only records
    the requested state.

Testing

  • Builds cleanly for an STM32H743 PX4 target.
  • The identical upstream change was hardware-tested on a custom
    STM32H743 board with eMMC: sd_bench sequential write ~4.1 MB/s,
    sequential read ~6.3 MB/s (previously all data transfers timed out).

RadekPesina and others added 9 commits July 23, 2026 19:40
- Fix DMA addressing issues within litex_sendsetup/litex_recvsetup
- Extend with handling specific to eMMC commands during init & use.
- Cleanup of 4-bit BUS handling for SD and eMMC
- For eMMC, Send CMD0 during init as per JEDEC v4.41 for pre-idle

Backport note: the CMD1 failure recovery context differed on this branch (intermediate upstream commit 0797b03 is not present); resolved to the upstream end state of this region.

(cherry picked from commit 50a8ec6)
Commit 50a8ec6 broke many mmc devices.  Only if the flag
priv->caps & SDIO_CAPS_4BIT_ONLY was set, it migth work.
Without the flag, the mmc clock is never set (mmcsd_widebus()
call is terminated early stopping the clock).  This flag
is probably not very generic because most mmc hw support
1, 4 and 8 bit modes.

JEDEC specifies a bus width selection procedure, but it's
not implemented in this mmcsd_sdio.c driver.  Thus, it's
not known whether the hw supports 1, 4 anf 8 bit modes or
a combination of them.

However, with priv->caps & SDIO_CAPS_4BIT_ONLY the driver
suddenly assigns priv->buswidth = MMCSD_SCR_BUSWIDTH_4BIT
making it the only way to have the driver working.

Fix this by relaxing the above mentioned restrictions.

Signed-off-by: Eero Nurkkala <eero.nurkkala@offcode.fi>

(cherry picked from commit db13d5e)
…ce to 4-bit bus width mode

All eMMC devices support 4-bit bus width, so we should mark the
device as supporting 4-bit bus width after detecting that the
device type is eMMC.

Signed-off-by: Yinzhe Wu <Yinzhe.Wu@sony.com>
Reviewed-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Reviewed-by: Jacky Cao <Jacky.Cao@sony.com>
Tested-by: Yinzhe Wu <Yinzhe.Wu@sony.com>

(cherry picked from commit 4f7f751)
…EXT_CSD

CMD6 can use these macros to set any writable EXT_CSD field, not
just the bus width, so optimize these macro definitions to make
them general.

Signed-off-by: Yinzhe Wu <Yinzhe.Wu@sony.com>
Reviewed-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Reviewed-by: Jacky Cao <Jacky.Cao@sony.com>
Tested-by: Yinzhe Wu <Yinzhe.Wu@sony.com>

Backport note: the CMD6 call site on this branch used the pre-existing open-coded argument form; conflict resolved to the upstream macro form.

(cherry picked from commit 08ce36d)
…MC high speed SDR mode

According to the eMMC specification, in Backwards Compatibility
with legacy MMC card mode, the frequency of the SD clock must be
0-26 MHZ; in high speed SDR mode, it must be 0-52MHZ. So we should
switch to high speed SDR mode if the clock frequency is higher than
26MHZ.

Signed-off-by: Yinzhe Wu <Yinzhe.Wu@sony.com>
Reviewed-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Reviewed-by: Jacky Cao <Jacky.Cao@sony.com>
Tested-by: Yinzhe Wu <Yinzhe.Wu@sony.com>

Backport note: struct mmcsd_state_s lives in mmcsd_sdio.c on this branch (upstream moved it to mmcsd.h); the mode:2 -> mode:4 bitfield change is applied there instead.

(cherry picked from commit 49cbcfb)
…D cards

This corrects the setting widebus for SD cards, which was recently broken in 4f7f751.

The if checking the priv->caps, priv->buswidth and IS_MMC has been wrong for
some time. The proper logic is that for MMC only the priv->caps is checked.
For SD card, both priv->caps and priv->buswidth need to be checked.

Signed-off-by: Jukka Laitinen <jukkax@ssrc.tii.ae>

(cherry picked from commit 5238c3b)
…add 8-bit support

The MMC CMD6 bus width switch was gated on priv->buswidth which is
derived from the SD SCR register. For MMC cards this field is never
set (unless SDIO_CAPS_4BIT_ONLY), so the CMD6 was skipped while the
host PROCTL DTW was still changed - causing a bus width mismatch and
data transfer timeouts.

Fix by checking priv->caps instead of priv->buswidth for MMC cards.
Also select EXT_CSD_BUS_WIDTH_8 when host reports SDIO_CAPS_8BIT.

Signed-off-by: buxiasen <buxiasen@xiaomi.com>

(cherry picked from commit 9feaa4d)
…or MMC/eMMC cards

The STM32H7, STM32F7, STM32L4 and common STM32 SDIO/SDMMC drivers failed
to program the WIDBUS bits when switching MMC/eMMC cards to 4-bit mode,
and the MMC transfer clock presets were hardwired to 1-bit bus width.

Add CLOCK_MMC_TRANSFER_4BIT to the common SDIO clock enum, add 4-bit
MMC clock presets, and update stm32_widebus() to use modifyreg32/
sdmmc_modifyreg32 to set the host controller bus width.

Signed-off-by: DuoYuWang <thirteenking.wang@gmail.com>

Backport note: upstream's arch/arm/src/common/stm32/stm32_sdio_m3m4_v1.c exists as arch/arm/src/stm32/stm32_sdio.c on this branch; the common-driver change is applied there.

(cherry picked from commit 82ab33a)
Two sequencing problems in the MMC wide bus path break eMMC 4-bit
operation on hosts that program the bus width in the SDIO widebus /
clock callbacks (e.g. STM32H7):

1. The SWITCH command (CMD6) is issued before the host has switched
   to wide bus operation.  When the card completes the switch while
   the host is still in 1-bit mode the switch never takes effect and
   every following data transfer times out.  Switch the host to wide
   bus operation before issuing CMD6.

2. The transfer clock is selected only at the end of mmcsd_widebus(),
   so the whole switch sequence runs at ID-mode clock and, on the
   affected hosts, the final clock update does not take effect either,
   leaving the bus at ~400 kHz.  Select the MMC transfer clock before
   calling mmcsd_widebus(), and pick CLOCK_MMC_TRANSFER_4BIT when wide
   bus operation is active (mirroring the SD card path) so a later
   clock selection cannot revert the host to 1-bit.

No behavior change for SD cards, and no change on hosts whose widebus
callback only records the requested state.

Tested on a custom STM32H743 board with eMMC: sd_bench sequential
write ~4.1 MB/s, sequential read ~6.3 MB/s (previously all data
transfers timed out).

Signed-off-by: DuoYuWang <thirteenking.wang@gmail.com>

Backport note: MMCSD_USLEEP does not exist on this branch (introduced upstream by 4435195, not backported); nxsig_usleep is used instead, matching the surrounding code.

(cherry picked from commit e84259c)
@dakejahl

Copy link
Copy Markdown
Contributor

BTW we are upgrading to a newer NuttX soon, in case you wanted to test your board against this branch
PX4/PX4-Autopilot#26215

@13022591351

Copy link
Copy Markdown
Contributor Author

BTW we are upgrading to a newer NuttX soon, in case you wanted to test your board against this branch PX4/PX4-Autopilot#26215

From this perspective, there is indeed no need to backport too much future code to the px4_firmware_nuttx-10.3.0+ branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants