apache / nuttx

Apache NuttX is a mature, real-time embedded operating system (RTOS)
https://nuttx.apache.org/
Apache License 2.0
2.51k stars 1.06k forks source link

NUCLEO-L4R5ZI - SDMMC - SDIO - no communication on CMD line #6796

Open qbazd opened 1 year ago

qbazd commented 1 year ago

Hi,

I'm trying to get working Nuttx 10.3.0 on NUCLEO-L4R5ZI. I'm stuck on SDIO interface. (Clock setup works, serial communication works). I've based my work on the stm32l4r9ai-disco, as it seams for me the closest relative.

The issue is there is no signals changing on CMD, D0-D3 CLK is working - is about 93kHz

Here is the log:

ABCDF
stm32l4_rng_initialize: Initializing RNG
Mounting procfs to /proc
stm32l4_mco_initialize: STM32L4_RCC_CFGR:0x4200000F
stm32l4_mco_initialize: STM32L4_RCC_AHB2ENR:4401FF
stm32l4_sdio_initialize: Initializing SDIO slot 0
stm32l4_sdio_initialize: STM32L4_RCC_CR:0xF000563
stm32_setclkcr: CLKCR: 00000110 PWR: 00000000
stm32_reset: CLCKR: 00000110 POWER: 00000003
stm32l4_sdio_initialize: Bind SDIO to the MMC/SD driver, minor=0
stm32_registercallback: Register 0x802cf8d(0x100032d8)
stm32_callbackenable: eventset: 02
stm32_callback: Callback 0x802cf8d(0x100032d8) cbevents: 02 cdstatus: 00
stm32l4_sdio_initialize: Successfully bound SDIO to the MMC/SD driver
sdio_mediachange: cdstatus OLD: 00 NEW: 01
stm32_callback: Callback 0x802cf8d(0x100032d8) cbevents: 02 cdstatus: 01
stm32_callback: Callback to 0x802cf8d(0x100032d8)
stm32_setclkcr: CLKCR: 00000110 PWR: 00000003
stm32_sendcmd: cmd: 00000000 arg: 00000000 regval: 00000400
stm32_waitresponse: ERROR: Timeout cmd: 00000000 events: 00000080 STA: 00000000
mmcsd_sendcmdpoll: ERROR: Wait for response to cmd: 00000000 failed: -116
stm32_sendcmd: cmd: 00000208 arg: 000001aa regval: 00000448
stm32_waitresponse: ERROR: Timeout cmd: 00000208 events: 00000045 STA: 00000000
mmcsd_sendcmdpoll: ERROR: Wait for response to cmd: 00000208 failed: -116
stm32_sendcmd: cmd: 00000077 arg: 00000000 regval: 00000477
<freezes there for couple of minutes>
stm32_waitresponse: ERROR: Timeout cmd: 00000077 events: 00000045 STA: 00000000
mmcsd_sendcmdpoll: ERROR: Wait for response to cmd: 00000077 failed: -116
stm32_recvshortcrc: ERROR: RESCMD=00 CMD=00000077
mmcsd_cardidentify: ERROR: mmcsd_recv_r1(CMD55) failed: -22
mmcsd_cardidentify: ERROR: Failed to identify card
mmcsd_probe: ERROR: Failed to initialize card: -5
romfs_open: ERROR: Failed to find directory directory entry for 'init.d/rc.sysinit': -2
nsh: sysinit: fopen failed: 2

NuttShell (NSH) NuttX-10.3.0
nsh> 

As I understand STM32L4R5ZI doesn't have SDMMC DMA - I've compiled without DMA.

What I've checked:

Things I don't know:

Any constructive thoughts will be appreciated.

All the best, Jakub

davids5 commented 1 year ago

@qbazd

Did you add the HW and and pull ~50 pull ups on all the lines to the card but not the clock line?

Check that "MMC cards support" is disabled Check the pin assignments. Ensure the pins are setup correctly (Verify it with JTAG by looking at the GPIO registers). Break after the pins are setup Then check them again when used to probe the card. Some times anther pin is being used and has the wrong config. It could over write one of the SDIO pins. Remember too that the interface is booted in 1 Bit mode first and the clock should be <= 400 Khz see SDIO_INIT_CLKDIV.

qbazd commented 1 year ago

@davids5

Hi, tnx for reply.

Did you add the HW and and pull ~50 pull ups on all the lines to the card but not the clock line?

Yes - I have 10k each line - clk, cmd, d0-d3

I've confirmed my hardware setup by working software made with stm32duino (arduino framework) for this NUCLEO-L4R5ZI board.

Check that "MMC cards support" is disabled Check the pin assignments.

Here is my screen of config:

image

Ensure the pins are setup correctly (Verify it with JTAG by looking at the GPIO registers). Break after the pins are setup > Then check them again when used to probe the card. Some times anther pin is being used and has the wrong config.

I understand. I will try to debug GPIO PINS setup registers of SDMMC. Have to learn how exactly, what addresses/values. Will get back with results.

It could over write one of the SDIO pins. Remember too that the interface is booted in 1 Bit mode first and the clock should be <= 400 Khz see SDIO_INIT_CLKDIV.

Tried to manipulate SDIO_INIT_CLKDIV without success (CLK varies then in +/- couple kHz)

qbazd commented 1 year ago

@davids5 GPIO setup seams to be OK.

Mode is set for pins as Alternate Alternate function of pins is set - ALT12 (1100) I even added internal pullup config for pins, so they are pulled up without external pullup to check if they are configured.

I've used stm32l4_dumpgpio() to dump GPIO config registers.

This is pinout for SDMMC interface for STM32L4R5ZI

    // D2 - CMD
    // C12 - CLK
    // C8-11 - D0-D3

This is debug with pre and post sdio_initialize():

ABCDF
stm32l4_rng_initialize: Initializing RNG
Mounting procfs to /proc
stm32l4_sdio_initialize: STM32L4_RCC_CR:0xF000563
stm32l4_sdio_initialize: STM32L4_NPORTS 9
stm32l4_dumpgpio: GPIOC pinset: 00000020 base: 48000800 -- pre sdio_initialize
stm32l4_dumpgpio:  MODE: ffffffff OTYPE: 0000     OSPEED: 00000000 PUPDR: 00000000
stm32l4_dumpgpio:   IDR: 0000       ODR: 0000       BSRR: 00000000  LCKR: 0000
stm32l4_dumpgpio:  AFRH: 00000000  AFRL: 00000000
stm32l4_dumpgpio: GPIOD pinset: 00000030 base: 48000c00 -- pre sdio_initialize
stm32l4_dumpgpio:  MODE: ffffebff OTYPE: 0000     OSPEED: 00000000 PUPDR: 00000000
stm32l4_dumpgpio:   IDR: 0040       ODR: 0000       BSRR: 00000000  LCKR: 0000
stm32l4_dumpgpio:  AFRH: 00000000  AFRL: 07700000
stm32l4_sdio_initialize: Initializing SDIO slot 0
stm32_setclkcr: CLKCR: 00000110 PWR: 00000000
stm32_reset: CLCKR: 00000110 POWER: 00000003
stm32l4_dumpgpio: GPIOC pinset: 00000020 base: 48000800 -- post sdio_initialize
stm32l4_dumpgpio:  MODE: feaaffff OTYPE: 0000     OSPEED: 00000000 PUPDR: 01550000
stm32l4_dumpgpio:   IDR: 0f00       ODR: 0000       BSRR: 00000000  LCKR: 0000
stm32l4_dumpgpio:  AFRH: 000ccccc  AFRL: 00000000
stm32l4_dumpgpio: GPIOD pinset: 00000030 base: 48000c00 -- post sdio_initialize
stm32l4_dumpgpio:  MODE: ffffebef OTYPE: 0000     OSPEED: 00000000 PUPDR: 00000010
stm32l4_dumpgpio:   IDR: 0044       ODR: 0000       BSRR: 00000000  LCKR: 0000
stm32l4_dumpgpio:  AFRH: 00000000  AFRL: 07700c00
stm32l4_sdio_initialize: Bind SDIO to the MMC/SD driver, minor=0
stm32_registercallback: Register 0x802fb3d(0x100032d8)
stm32_callbackenable: eventset: 02
stm32_callback: Callback 0x802fb3d(0x100032d8) cbevents: 02 cdstatus: 00
stm32l4_sdio_initialize: Successfully bound SDIO to the MMC/SD driver
sdio_mediachange: cdstatus OLD: 00 NEW: 01
stm32_callback: Callback 0x802fb3d(0x100032d8) cbevents: 02 cdstatus: 01
stm32_callback: Callback to 0x802fb3d(0x100032d8)
stm32_setclkcr: CLKCR: 00000110 PWR: 00000003
stm32_sendcmd: cmd: 00000000 arg: 00000000 regval: 00000400
stm32_waitresponse: ERROR: Timeout cmd: 00000000 events: 00000080 STA: 00000000
mmcsd_sendcmdpoll: ERROR: Wait for response to cmd: 00000000 failed: -116
stm32_sendcmd: cmd: 00000208 arg: 000001aa regval: 00000448
stm32_waitresponse: ERROR: Timeout cmd: 00000208 events: 00000045 STA: 00000000
mmcsd_sendcmdpoll: ERROR: Wait for response to cmd: 00000208 failed: -116
stm32_sendcmd: cmd: 00000077 arg: 00000000 regval: 00000477
<freeze>
qbazd commented 1 year ago

I think there is no tested support for STM32L4R5ZI uC SDMMC - SDIO - yet. And comparing registers gave me clues (tnx @davids5) but GPIO is the least problem.

What I found is that definition of SDMMC clock control register (SDMMC_CLKCR) bits in file stm32l4_sdmmc.h does not match uC documentation (RM0432) section 54.10.2 at all.

Additionally enabling or disabling in nuttx config RNG in peripherials, does strangely enable or disable clock output for SDMMC interface.

When I've modified clock section of stm32l4_sdmmc.h and enabled RNG. Then setting STM32_SDMMC_INIT_CLKDIV 64 gave correct results observed SDMMC clock was about 375kHz 2 64 ~= 48Mhz which is AHB2 clock.

Next question is how to make/start making support for STM32L4R5ZI SDMMC - SDIO? Make another issue or edit subject?

qbazd commented 1 year ago

RNG and OTGFS dependency on SDMMC system is introduced by an error in header file stm32l4r9ai-disco-clocking.h

There is an config variable STM32L4_SDMMC but should be CONFIG_STM32L4_SDMMC on lines 135, 245, 342 Error prevents from setting up clock properly when no CONFIG_STM32L4_OTGFS or CONFIG_STM32L4_RNG options are selected.

davids5 commented 1 year ago

This may be an IP versioning issues (SDMMCv1 vs SDMMCv2.) Or just some clocking. If it is just clocking the solution is using ifdef based on CONFIG_STM32L4_SDMMC. If it is an IP issues have a look at the H7 SDMMC and see if it is a closer match. The port it in to the L4.

qbazd commented 1 year ago

@davids5, I exacly went that road H7 have same registers as L4+. I went further and have some preliminary results. But eventualy L4+ will have different config variables than L4. I have H743 board, so I can compare results.

davids5 commented 1 year ago

Ok Good hear! Now the question is":Is the L4+ just marketing hype or different IP?

qbazd commented 1 year ago

Hi, I've reached out to google, and here is the nice L4+ vs L4 comparison. I mean it's better than comparing 2k+ pages documents ;) Unfortunately document doesn't mention things like: "O! L4+ have simmilar SDMMC as H7 line, check that out!".

Questions:

davids5 commented 1 year ago

The approach I use is see if there is a migration guide. I also compare the register summary pages for each of the IP blocks. Sometimes this is has to be across families to be able to Identify versions of the IP. SVD file may help as well but the diffs tend to be noisy.

Can we treat L4+ as a special case of L4, is this sensible?

I had a quick look as the comparison doc. I think so, but as they say: "the devil is in the details" So I suggest you go devil hunting and map out the patterns and solutions first, to see if there any reasons to bifurcate and have a stm32l4p. I did not see any, but you are closer to the problem then I am.

RCC The width and ranges of the clock tree will call for a L4+ (L4P) stm32l4PNxx_rcc.c file. That pattern is already in place. The additional IP can be enabled with something like CONFIG_STM32L4PLUS and included as need.

There will be a need to break out hardware stm32l4_memorymap.h (see for the pattern) in to Include the map for a family or use a HAS_XXXX if it is a very small change. (only 3-4 #ifdefs)

Same is true of the the pinmap - that pattern already established.

Rise-lather-repeat.

How to apply difference for L4+ to L4 not to brake it and bloat (to much) it with #ifdefs?

  1. By inclusion based on Family type. I.E The pinmap does this already - extend it.
  2. Arbitrarily assigning a IP version number. Or find ST docs or prior art in other repos. that establishes a version number for the IP. Then use the as CONFIG_STM32_HAVE_IP_XXXX_V1 that is selected in in the Kconfig when the SoC is chosen (@raiden00pl did a great job of this in the stm32 for the ADC etc) this avoids many term If defs in the files that have to be changed every time a new variant is released.