From 873994107face0b9694b59f3adf90bdf326e6465 Mon Sep 17 00:00:00 2001 From: eightycc Date: Fri, 28 Mar 2025 06:25:15 -0700 Subject: [PATCH 1/2] Allow PSRAM overclocking by enabling burst wrap mode. --- src/main.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/main.c b/src/main.c index 8283058..2896728 100644 --- a/src/main.c +++ b/src/main.c @@ -395,14 +395,25 @@ static void __no_inline_not_in_flash_func(setup_psram)(void) { } // RESETEN, RESET and quad enable - for (uint8_t i = 0; i < 3; i++) { + for (uint8_t i = 0; i < 4; i++) { qmi_hw->direct_csr |= QMI_DIRECT_CSR_ASSERT_CS1N_BITS; - if (i == 0) { - qmi_hw->direct_tx = 0x66; - } else if (i == 1) { - qmi_hw->direct_tx = 0x99; - } else { - qmi_hw->direct_tx = 0x35; + switch (i) { + case 0: + // RESETEN + qmi_hw->direct_tx = 0x66; + break; + case 1: + // RESET + qmi_hw->direct_tx = 0x99; + break; + case 2: + // Quad enable + qmi_hw->direct_tx = 0x35; + break; + case 3: + // Toggle wrap boundary mode + qmi_hw->direct_tx = 0xc0; + break; } while ((qmi_hw->direct_csr & QMI_DIRECT_CSR_BUSY_BITS) != 0) { } From bd9c3e1cae414be8acdc00edf0fdef5b183a1955 Mon Sep 17 00:00:00 2001 From: eightycc Date: Sun, 30 Mar 2025 07:30:42 -0700 Subject: [PATCH 2/2] Add support for clocking PSRAM QSPI up to 133MHz. --- .github/workflows/build.yaml | 2 ++ src/clocking.c | 20 ++++++++++----- src/main.c | 47 +++++++++++++++++++++++------------- 3 files changed, 46 insertions(+), 23 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 7107b81..3479fa9 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -37,6 +37,8 @@ jobs: ./fetch-rom-dsk.sh ./fruitjam-build.sh -m 4096 ./fruitjam-build.sh -m 4096 -v + ./fruitjam-build.sh -m 4096 -o + ./fruitjam-build.sh -m 4096 -v -o ./fruitjam-build.sh -m 400 ./fruitjam-build.sh -m 400 -v ./fruitjam-build.sh -m 400 -o diff --git a/src/clocking.c b/src/clocking.c index d095255..99b5a17 100644 --- a/src/clocking.c +++ b/src/clocking.c @@ -30,8 +30,12 @@ static void __no_inline_not_in_flash_func(set_qmi_timing)() { #define RP2350_PSRAM_MIN_DESELECT_FS (50000000) #endif +#ifndef RP2350_PSRAM_RX_DELAY_FS +#define RP2350_PSRAM_RX_DELAY_FS (3333333) +#endif + #ifndef RP2350_PSRAM_MAX_SCK_HZ -#define RP2350_PSRAM_MAX_SCK_HZ (109000000) +#define RP2350_PSRAM_MAX_SCK_HZ (133000000) #endif #define SEC_TO_FS 1000000000000000ll @@ -49,6 +53,7 @@ static void __no_inline_not_in_flash_func(set_psram_timing)(void) { // Get the clock femto seconds per cycle. uint32_t fsPerCycle = SEC_TO_FS / sysHz; + uint32_t fsPerHalfCycle = fsPerCycle / 2; // the maxSelect value is defined in units of 64 clock cycles // So maxFS / (64 * fsPerCycle) = maxSelect = RP2350_PSRAM_MAX_SELECT_FS64/fsPerCycle @@ -60,11 +65,18 @@ static void __no_inline_not_in_flash_func(set_psram_timing)(void) { volatile uint8_t minDeselect = (RP2350_PSRAM_MIN_DESELECT_FS + fsPerCycle - 1) / fsPerCycle; + // RX delay (RP2350 datasheet 12.14.3.1) delay between between rising edge of SCK and + // the start of RX sampling. Expressed in 0.5 system clock cycles. Smallest value + // >= 3.3ns. + volatile uint8_t rxDelay = (RP2350_PSRAM_RX_DELAY_FS + fsPerHalfCycle - 1) / fsPerHalfCycle; + printf("syshz=%u\n", sysHz); - printf("Max Select: %d, Min Deselect: %d, clock divider: %d\n", maxSelect, minDeselect, clockDivider); + printf("Max Select: %d, Min Deselect: %d, RX delay: %d, clock divider: %d\n", maxSelect, minDeselect, rxDelay, clockDivider); + printf("PSRAM clock rate %.1fMHz\n", (float)sysHz / clockDivider / 1e6); qmi_hw->m[1].timing = QMI_M1_TIMING_PAGEBREAK_VALUE_1024 << QMI_M1_TIMING_PAGEBREAK_LSB | // Break between pages. 3 << QMI_M1_TIMING_SELECT_HOLD_LSB | // Delay releasing CS for 3 extra system cycles. + rxDelay << QMI_M1_TIMING_RXDELAY_LSB | // Delay between SCK and RX sampling 1 << QMI_M1_TIMING_COOLDOWN_LSB | 1 << QMI_M1_TIMING_RXDELAY_LSB | maxSelect << QMI_M1_TIMING_MAX_SELECT_LSB | minDeselect << QMI_M1_TIMING_MIN_DESELECT_LSB | clockDivider << QMI_M1_TIMING_CLKDIV_LSB; @@ -142,10 +154,6 @@ void overclock(enum clk_sys_speed clk_sys_div, uint32_t bit_clk_khz) { stdio_init_all(); set_psram_timing(); #define SHOW_CLK(i) printf("clk_get_hz(%s) -> %u\n", #i, clock_get_hz(i)); - SHOW_CLK(clk_gpout0); - SHOW_CLK(clk_gpout1); - SHOW_CLK(clk_gpout2); - SHOW_CLK(clk_gpout3); SHOW_CLK(clk_ref); SHOW_CLK(clk_sys); SHOW_CLK(clk_peri); diff --git a/src/main.c b/src/main.c index 256f7d9..9a61ddd 100644 --- a/src/main.c +++ b/src/main.c @@ -491,27 +491,40 @@ static void __no_inline_not_in_flash_func(setup_psram)(void) { int main() { -#if defined(OVERCLOCK) && OVERCLOCK+0 + setup_psram(); +#if OVERCLOCK overclock(CLK_SYS_264MHZ, 252000); #endif - // set_sys_clock_khz(250*1000, true); - - setup_psram(); - stdio_init_all(); - io_init(); -#define SHOW_CLK(i) printf("clk_get_hz(%s) -> %u\n", #i, clock_get_hz(i)); - SHOW_CLK(clk_gpout0); - SHOW_CLK(clk_gpout1); - SHOW_CLK(clk_gpout2); - SHOW_CLK(clk_gpout3); - SHOW_CLK(clk_ref); - SHOW_CLK(clk_sys); - SHOW_CLK(clk_peri); - SHOW_CLK(clk_hstx); - SHOW_CLK(clk_usb); - SHOW_CLK(clk_adc); +printf("psram size %u\n", _psram_size); + +#ifndef RAM_TEST +#define RAM_TEST (0) +#endif + +#if RAM_TEST +for(int pass=0; pass<10; pass++) { + uint8_t acc = 1; + for(int i=0; i < _psram_size; i++) { + umac_ram[i] = acc; + acc = acc * 13 + 21; + } + + acc = 1; + for(int i=0; i < _psram_size; i++) { + uint8_t ri = umac_ram[i]; + if(ri != acc) { + panic("[%08x] Stored %02x read %02x", i, acc, ri); + } + acc = acc * 13 + 21; + } + + printf("ram test pass %d OK\n", pass); +} +#endif + + io_init(); #if ENABLE_AUDIO audio_setup();