carlk3 / no-OS-FatFS-SD-SPI-RPi-Pico

A FAT filesystem with SPI driver for SD card on Raspberry Pi Pico
Apache License 2.0
273 stars 47 forks source link

SDIO and set_sys_clock_khz #81

Open jess-sheneberger opened 12 months ago

jess-sheneberger commented 12 months ago

(my background is software. I'm a newbie to most hardware stuff. Forgive my ignorance and if this seems strange or silly)

I'm trying to combine SDIO from your project and this: https://github.com/Wren6991/PicoDVI

I've been able to make my sd card work over SPI, and I can make SDIO work alone but as soon as I add this line:

set_sys_clock_khz(252000, true); it quits working with error "A hard error occurred in the low level disk I/O"

My (limited) understanding is that 252000khz is related to the output DVI/TMDS clock.

via trial and error I've discovered that 206000khz works and seems to make both SDIO and DVI (or at least my monitor) happy.

so I'm curious: is there a tweak to the SDIO code that I can make which will make it work at 252mhz? i suspect that I'm pushing the DVI timing pretty far outside spec and I'd like to bump that back up to maybe make this work on less forgiving monitors.

carlk3 commented 12 months ago

It's on my list of things to do to make the SDIO clock rate configurable in the H/W config. It is currently hard coded in sd_sdio_begin in sd_driver\SDIO\sd_card_sdio.c. It is derived by applying a divider to the system clock frequency.

// Increase to 25 MHz clock rate
// Actually, clk_sys / CLKDIV (from rp2040_sdio.pio),
// So, say, 125 MHz / 4 = 31.25 MHz (see src\sd_driver\SDIO\rp2040_sdio.pio)
// rp2040_sdio_init(sd_card_p, 1, 0); // 31.25 MHz
rp2040_sdio_init(sd_card_p, 1, 128); // 20.8 MHz

so you would have to modify that directly.

void rp2040_sdio_init(sd_card_t *sd_card_p, uint16_t clock_divider, uint8_t clock_div_256ths)

The clock_divider and clock_div_256ths parameters are passed to the SDK's sm_config_set_clkdiv_int_frac:

/*! \brief Set the state machine clock divider (from integer and fractional parts - 16:8) in a state machine configuration
 *  \ingroup sm_config
 *
 * The clock divider can slow the state machine's execution to some rate below
 * the system clock frequency, by enabling the state machine on some cycles
 * but not on others, in a regular pattern. This can be used to generate e.g.
 * a given UART baud rate. See the datasheet for further detail.
 *
 * \param c Pointer to the configuration structure to modify
 * \param div_int Integer part of the divisor
 * \param div_frac Fractional part in 1/256ths
 * \sa sm_config_set_clkdiv()
 */

Note that the PIO state machine effectively divides the clock rate by 4.

When I get around to making the SDIO baud rate configurable in the H/W config., I should use a scheme like that used in the SDK's spi_set_baudrate and take the system clock frequency into account.

carlk3 commented 11 months ago

I am able to run reliably with system clock at 252000 and SDIO baud rate 5 MHz.

jess-sheneberger commented 11 months ago

Thanks Carl!