Add overclocking
.. not currently compatible with PSRAM (sadly), even though I tried doing the right things with PSRAM clocking.
This commit is contained in:
parent
082f3175f0
commit
bfc9f6f0f0
6 changed files with 234 additions and 5 deletions
10
.github/workflows/build.yaml
vendored
10
.github/workflows/build.yaml
vendored
|
|
@ -39,18 +39,24 @@ jobs:
|
|||
./fruitjam-build.sh -m 4096 -v
|
||||
./fruitjam-build.sh -m 400
|
||||
./fruitjam-build.sh -m 400 -v
|
||||
./fruitjam-build.sh -m 400 -o
|
||||
./fruitjam-build.sh -m 400 -v -o
|
||||
mkdir uf2s
|
||||
cp build*/*.uf2 uf2s/
|
||||
mkdir elfs
|
||||
cp build*/*.elf elfs/
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: uf2 files
|
||||
path: build*/*.uf2
|
||||
path: uf2s/*
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: elf files
|
||||
path: build*/*.elf
|
||||
path: elfs/*
|
||||
|
||||
- name: Create release
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@ set(HSTX_D0P 15 CACHE STRING "HSTX D0+ PIN")
|
|||
set(HSTX_D1P 17 CACHE STRING "HSTX D1+ PIN")
|
||||
set(HSTX_D2P 19 CACHE STRING "HSTX D2+ PIN")
|
||||
|
||||
option(OVERCLOCK "Overclock to 264MHz (known incompatible with psram)" OFF)
|
||||
|
||||
# Options for analog VGA output
|
||||
option(USE_VGA_RES "Video uses VGA (640x480) resolution" OFF)
|
||||
set(VIDEO_PIN 18 CACHE STRING "VGA Video GPIO base pin (followed by VS, CLK, HS)")
|
||||
|
|
@ -84,6 +86,13 @@ else()
|
|||
set(VIDEO_SRC src/video_vga.c)
|
||||
endif()
|
||||
|
||||
if (OVERCLOCK)
|
||||
add_compile_definitions(OVERCLOCK=1)
|
||||
set(OPT_OC "-oc")
|
||||
else()
|
||||
set(OPT_OC "")
|
||||
endif()
|
||||
|
||||
if (USE_VGA_RES)
|
||||
add_compile_definitions(USE_VGA_RES=1)
|
||||
add_compile_definitions(DISP_WIDTH=640)
|
||||
|
|
@ -105,7 +114,7 @@ else()
|
|||
set(OPT_PSRAM "")
|
||||
endif()
|
||||
|
||||
set(FIRMWARE "pico-mac-${PICO_BOARD}-${MEMSIZE}k-${RES}${OPT_PSRAM}")
|
||||
set(FIRMWARE "pico-mac-${PICO_BOARD}-${MEMSIZE}k-${RES}${OPT_PSRAM}${OPT_OC}")
|
||||
|
||||
|
||||
# initialize the SDK based on PICO_SDK_PATH
|
||||
|
|
@ -180,6 +189,7 @@ if (TARGET tinyusb_device)
|
|||
${VIDEO_SRC}
|
||||
src/kbd.c
|
||||
src/hid.c
|
||||
src/clocking.c
|
||||
${EXTRA_SD_SRC}
|
||||
|
||||
${PICO_TINYUSB_PATH}/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c
|
||||
|
|
|
|||
|
|
@ -12,9 +12,13 @@ DISP_HEIGHT=342
|
|||
MEMSIZE=400
|
||||
DISC_IMAGE=
|
||||
CMAKE_ARGS=""
|
||||
OVERCLOCK=0
|
||||
|
||||
while getopts "hvd:m:" o; do
|
||||
while getopts "hovd:m:" o; do
|
||||
case "$o" in
|
||||
(o)
|
||||
OVERCLOCK=1
|
||||
;;
|
||||
(v)
|
||||
DISP_WIDTH=640
|
||||
DISP_HEIGHT=480
|
||||
|
|
@ -30,8 +34,9 @@ while getopts "hvd:m:" o; do
|
|||
echo "Usage: $0 [-v] [-m KiB] [-d diskimage]"
|
||||
echo ""
|
||||
echo " -v: Use framebuffer resolution 640x480 instead of 512x342"
|
||||
echo " -m: Set memory size in KiB"
|
||||
echo " -m: Set memory size in KiB (over 400kB requires psram)"
|
||||
echo " -d: Specify disc image to include"
|
||||
echo " -o: Overclock to 264MHz (known to be incompatible with psram)"
|
||||
echo ""
|
||||
echo "PSRAM is automatically set depending on memory & framebuffer details"
|
||||
exit
|
||||
|
|
@ -44,6 +49,9 @@ shift $((OPTIND-1))
|
|||
TAG=fruitjam_${DISP_WIDTH}x${DISP_HEIGHT}_${MEMSIZE}k
|
||||
PSRAM=$((MEMSIZE > 400))
|
||||
if [ $PSRAM -ne 0 ] ; then
|
||||
if [ $OVERCLOCK -ne 0 ]; then
|
||||
echo "*** Overclock + PSRAM is known not to work. You have been warned."
|
||||
fi
|
||||
TAG=${TAG}_psram
|
||||
CMAKE_ARGS="$CMAKE_ARGS -DUSE_PSRAM=1"
|
||||
fi
|
||||
|
|
@ -61,6 +69,10 @@ if [ -n "$DISC_IMAGE" ] && [ -f "$DISC_IMAGE" ]; then
|
|||
TAG=${TAG}_${DISC_IMAGE}
|
||||
fi
|
||||
|
||||
if [ $OVERCLOCK -ne 0 ]; then
|
||||
TAG=${TAG}_overclock
|
||||
fi
|
||||
|
||||
set -x
|
||||
rm -rf build_${TAG}
|
||||
cmake -S . -B build_${TAG} \
|
||||
|
|
@ -72,5 +84,7 @@ cmake -S . -B build_${TAG} \
|
|||
-DSD_TX=35 -DSD_RX=36 -DSD_SCK=34 -DSD_CS=39 -DUSE_SD=1 \
|
||||
-DUART_TX=44 -DUART_RX=45 -DUART=0 \
|
||||
-DBOARD_FILE=boards/adafruit_fruit_jam.c \
|
||||
-DSD_MHZ=16 \
|
||||
-DOVERCLOCK=${OVERCLOCK} \
|
||||
${CMAKE_ARGS} "$@"
|
||||
make -C build_${TAG} -j$(nproc)
|
||||
|
|
|
|||
11
include/clocking.h
Normal file
11
include/clocking.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum clk_sys_speed {
|
||||
CLK_SYS_264MHZ = 2,
|
||||
CLK_SYS_176MHZ = 3,
|
||||
CLK_SYS_132MHZ = 4,
|
||||
};
|
||||
|
||||
extern void overclock(enum clk_sys_speed clk_sys_div, uint32_t bit_clk_hz);
|
||||
172
src/clocking.c
Normal file
172
src/clocking.c
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
#include "clocking.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include "pico.h"
|
||||
#include "pico/stdio.h"
|
||||
#include "hardware/clocks.h"
|
||||
#include "hardware/pll.h"
|
||||
#include "hardware/structs/ioqspi.h"
|
||||
#include "hardware/structs/qmi.h"
|
||||
#include "hardware/sync.h"
|
||||
#include "hardware/vreg.h"
|
||||
|
||||
static void __no_inline_not_in_flash_func(set_qmi_timing)() {
|
||||
// Make sure flash is deselected - QMI doesn't appear to have a busy flag(!)
|
||||
while ((ioqspi_hw->io[1].status & IO_QSPI_GPIO_QSPI_SS_STATUS_OUTTOPAD_BITS) != IO_QSPI_GPIO_QSPI_SS_STATUS_OUTTOPAD_BITS)
|
||||
;
|
||||
|
||||
qmi_hw->m[0].timing = 0x40000202;
|
||||
//qmi_hw->m[0].timing = 0x40000101;
|
||||
// Force a read through XIP to ensure the timing is applied
|
||||
volatile uint32_t* ptr = (volatile uint32_t*)0x14000000;
|
||||
(void) *ptr;
|
||||
}
|
||||
|
||||
#ifndef RP2350_PSRAM_MAX_SELECT_FS64
|
||||
#define RP2350_PSRAM_MAX_SELECT_FS64 (125000000)
|
||||
#endif
|
||||
|
||||
#ifndef RP2350_PSRAM_MIN_DESELECT_FS
|
||||
#define RP2350_PSRAM_MIN_DESELECT_FS (50000000)
|
||||
#endif
|
||||
|
||||
#ifndef RP2350_PSRAM_MAX_SCK_HZ
|
||||
#define RP2350_PSRAM_MAX_SCK_HZ (109000000)
|
||||
#endif
|
||||
|
||||
#define SEC_TO_FS 1000000000000000ll
|
||||
|
||||
static void __no_inline_not_in_flash_func(set_psram_timing)(void) {
|
||||
// Get secs / cycle for the system clock - get before disabling interrupts.
|
||||
uint32_t sysHz = (uint32_t)clock_get_hz(clk_sys);
|
||||
|
||||
// Calculate the clock divider - goal to get clock used for PSRAM <= what
|
||||
// the PSRAM IC can handle - which is defined in RP2350_PSRAM_MAX_SCK_HZ
|
||||
volatile uint8_t clockDivider = (sysHz + RP2350_PSRAM_MAX_SCK_HZ - 1) / RP2350_PSRAM_MAX_SCK_HZ;
|
||||
|
||||
uint32_t intr_stash = save_and_disable_interrupts();
|
||||
|
||||
// Get the clock femto seconds per cycle.
|
||||
|
||||
uint32_t fsPerCycle = SEC_TO_FS / sysHz;
|
||||
|
||||
// the maxSelect value is defined in units of 64 clock cycles
|
||||
// So maxFS / (64 * fsPerCycle) = maxSelect = RP2350_PSRAM_MAX_SELECT_FS64/fsPerCycle
|
||||
volatile uint8_t maxSelect = RP2350_PSRAM_MAX_SELECT_FS64 / fsPerCycle;
|
||||
|
||||
// minDeselect time - in system clock cycle
|
||||
// Must be higher than 50ns (min deselect time for PSRAM) so add a fsPerCycle - 1 to round up
|
||||
// So minFS/fsPerCycle = minDeselect = RP2350_PSRAM_MIN_DESELECT_FS/fsPerCycle
|
||||
|
||||
volatile uint8_t minDeselect = (RP2350_PSRAM_MIN_DESELECT_FS + fsPerCycle - 1) / fsPerCycle;
|
||||
|
||||
printf("syshz=%u\n", sysHz);
|
||||
printf("Max Select: %d, Min Deselect: %d, clock divider: %d\n", maxSelect, minDeselect, clockDivider);
|
||||
|
||||
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.
|
||||
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;
|
||||
|
||||
restore_interrupts(intr_stash);
|
||||
}
|
||||
|
||||
|
||||
static void __no_inline_not_in_flash_func(clock_init)(int sys_clk_div) {
|
||||
uint32_t intr_stash = save_and_disable_interrupts();
|
||||
|
||||
// Before messing with clock speeds ensure QSPI clock is nice and slow
|
||||
hw_write_masked(&qmi_hw->m[0].timing, 6, QMI_M0_TIMING_CLKDIV_BITS);
|
||||
|
||||
// We're going to go fast, boost the voltage a little
|
||||
vreg_set_voltage(VREG_VOLTAGE_1_15);
|
||||
|
||||
// Force a read through XIP to ensure the timing is applied before raising the clock rate
|
||||
volatile uint32_t* ptr = (volatile uint32_t*)0x14000000;
|
||||
(void) *ptr;
|
||||
|
||||
// Before we touch PLLs, switch sys and ref cleanly away from their aux sources.
|
||||
hw_clear_bits(&clocks_hw->clk[clk_sys].ctrl, CLOCKS_CLK_SYS_CTRL_SRC_BITS);
|
||||
while (clocks_hw->clk[clk_sys].selected != 0x1)
|
||||
tight_loop_contents();
|
||||
hw_write_masked(&clocks_hw->clk[clk_ref].ctrl, CLOCKS_CLK_REF_CTRL_SRC_VALUE_XOSC_CLKSRC, CLOCKS_CLK_REF_CTRL_SRC_BITS);
|
||||
while (clocks_hw->clk[clk_ref].selected != 0x4)
|
||||
tight_loop_contents();
|
||||
|
||||
// Stop the other clocks so we don't worry about overspeed
|
||||
clock_stop(clk_usb);
|
||||
clock_stop(clk_adc);
|
||||
clock_stop(clk_peri);
|
||||
clock_stop(clk_hstx);
|
||||
|
||||
// Set USB PLL to 528MHz
|
||||
pll_init(pll_usb, PLL_COMMON_REFDIV, 1584 * MHZ, 3, 1);
|
||||
|
||||
const uint32_t usb_pll_freq = 528 * MHZ;
|
||||
|
||||
// CLK SYS = PLL USB 528MHz / sys_clk_div = 264MHz, 176MHz, or 132MHz
|
||||
clock_configure(clk_sys,
|
||||
CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX,
|
||||
CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB,
|
||||
usb_pll_freq, usb_pll_freq / sys_clk_div);
|
||||
|
||||
// CLK PERI = PLL USB 528MHz / 4 = 132MHz
|
||||
clock_configure(clk_peri,
|
||||
0, // Only AUX mux on ADC
|
||||
CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB,
|
||||
usb_pll_freq, usb_pll_freq / 4);
|
||||
|
||||
// CLK USB = PLL USB 528MHz / 11 = 48MHz
|
||||
clock_configure(clk_usb,
|
||||
0, // No GLMUX
|
||||
CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB,
|
||||
usb_pll_freq,
|
||||
USB_CLK_KHZ * KHZ);
|
||||
|
||||
// CLK ADC = PLL USB 528MHz / 11 = 48MHz
|
||||
clock_configure(clk_adc,
|
||||
0, // No GLMUX
|
||||
CLOCKS_CLK_ADC_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB,
|
||||
usb_pll_freq,
|
||||
USB_CLK_KHZ * KHZ);
|
||||
|
||||
// Now we are running fast set fast QSPI clock and read delay
|
||||
set_qmi_timing();
|
||||
|
||||
restore_interrupts(intr_stash);
|
||||
}
|
||||
|
||||
void overclock(enum clk_sys_speed clk_sys_div, uint32_t bit_clk_khz) {
|
||||
clock_init(clk_sys_div);
|
||||
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);
|
||||
SHOW_CLK(clk_hstx);
|
||||
SHOW_CLK(clk_usb);
|
||||
SHOW_CLK(clk_adc);
|
||||
|
||||
|
||||
const uint32_t dvi_clock_khz = bit_clk_khz >> 1;
|
||||
printf("bit_clk_khz = %u dvi_clock_khz = %u\n", bit_clk_khz, dvi_clock_khz);
|
||||
uint vco_freq, post_div1, post_div2;
|
||||
if (!check_sys_clock_khz(dvi_clock_khz, &vco_freq, &post_div1, &post_div2))
|
||||
panic("System clock of %u kHz cannot be exactly achieved", dvi_clock_khz);
|
||||
const uint32_t freq = vco_freq / (post_div1 * post_div2);
|
||||
|
||||
// Set the sys PLL to the requested freq
|
||||
pll_init(pll_sys, PLL_COMMON_REFDIV, vco_freq, post_div1, post_div2);
|
||||
|
||||
// CLK HSTX = Requested freq
|
||||
clock_configure(clk_hstx,
|
||||
0,
|
||||
CLOCKS_CLK_HSTX_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS,
|
||||
freq, freq);
|
||||
}
|
||||
16
src/main.c
16
src/main.c
|
|
@ -45,6 +45,7 @@
|
|||
#include "tusb.h"
|
||||
|
||||
#include "umac.h"
|
||||
#include "clocking.h"
|
||||
|
||||
#if USE_SD
|
||||
#include "f_util.h"
|
||||
|
|
@ -471,6 +472,9 @@ static void __no_inline_not_in_flash_func(setup_psram)(void) {
|
|||
|
||||
int main()
|
||||
{
|
||||
#if defined(OVERCLOCK) && OVERCLOCK+0
|
||||
overclock(CLK_SYS_264MHZ, 252000);
|
||||
#endif
|
||||
// set_sys_clock_khz(250*1000, true);
|
||||
|
||||
setup_psram();
|
||||
|
|
@ -478,6 +482,18 @@ int main()
|
|||
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);
|
||||
|
||||
#if ENABLE_AUDIO
|
||||
audio_setup();
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in a new issue