Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions ports/raspberrypi/common-hal/microcontroller/Processor.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "py/mphal.h"
#include "py/runtime.h"
#include "common-hal/microcontroller/Processor.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/microcontroller/Processor.h"
#include "shared-bindings/microcontroller/ResetReason.h"
#include "shared-bindings/time/__init__.h"
Expand All @@ -20,6 +21,11 @@
#include "hardware/vreg.h"
#include "hardware/watchdog.h"

#ifdef CIRCUITPY_PSRAM_CHIP_SELECT
#include "hardware/regs/qmi.h"
#include "hardware/structs/qmi.h"
#endif

#if PICO_RP2040
#include "hardware/regs/vreg_and_chip_reset.h"
#include "hardware/structs/vreg_and_chip_reset.h"
Expand Down Expand Up @@ -50,6 +56,26 @@ uint32_t common_hal_mcu_processor_get_frequency(void) {
return clock_get_hz(clk_sys);
}

#ifdef CIRCUITPY_PSRAM_CHIP_SELECT
void __no_inline_not_in_flash_func(mcu_processor_update_psram_timing)(uint32_t sys_clk_khz) {
// MAX_SELECT is in units of 64 system clock cycles; PSRAM allows 8 us max CS
// assertion. Use 7.5 us so there is margin at any clk_sys.
uint32_t max_select = (75 * sys_clk_khz) / 640000;
// MIN_DESELECT is in system clock cycles; PSRAM needs 50 ns min CS
// deassertion. Round up so we are never under.
uint32_t min_deselect = (sys_clk_khz + 19999) / 20000;

qmi_hw->m[1].timing =
QMI_M0_TIMING_PAGEBREAK_VALUE_1024 << QMI_M0_TIMING_PAGEBREAK_LSB | // Break between pages.
3 << QMI_M0_TIMING_SELECT_HOLD_LSB | // Delay releasing CS for 3 extra system cycles.
1 << QMI_M0_TIMING_COOLDOWN_LSB |
1 << QMI_M0_TIMING_RXDELAY_LSB |
max_select << QMI_M0_TIMING_MAX_SELECT_LSB |
min_deselect << QMI_M0_TIMING_MIN_DESELECT_LSB |
2 << QMI_M0_TIMING_CLKDIV_LSB;
}
#endif

void common_hal_mcu_processor_set_frequency(mcu_processor_obj_t *self, uint32_t frequency) {
uint vco, postdiv1, postdiv2;
uint32_t freq_khz = frequency / 1000;
Expand All @@ -68,7 +94,17 @@ void common_hal_mcu_processor_set_frequency(mcu_processor_obj_t *self, uint32_t
vreg_set_voltage(voltage);
// Wait for a stable voltage
common_hal_time_delay_ms(10);

#ifdef CIRCUITPY_PSRAM_CHIP_SELECT
// Prevent interrupt handlers from accessing PSRAM until its timing matches
// the new system clock.
common_hal_mcu_disable_interrupts();
#endif
set_sys_clock_khz(freq_khz, false);
#ifdef CIRCUITPY_PSRAM_CHIP_SELECT
mcu_processor_update_psram_timing(freq_khz);
common_hal_mcu_enable_interrupts();
#endif
}

void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) {
Expand Down
4 changes: 4 additions & 0 deletions ports/raspberrypi/common-hal/microcontroller/Processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@ typedef struct {
mp_obj_base_t base;
// Stores no state currently.
} mcu_processor_obj_t;

#ifdef CIRCUITPY_PSRAM_CHIP_SELECT
void mcu_processor_update_psram_timing(uint32_t sys_clk_khz);
#endif
13 changes: 5 additions & 8 deletions ports/raspberrypi/supervisor/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include "supervisor/shared/stack.h"
#include "supervisor/shared/tick.h"

#include "hardware/clocks.h"
#include "hardware/structs/scb.h"
#include "hardware/structs/watchdog.h"
#include "hardware/gpio.h"
Expand Down Expand Up @@ -152,6 +153,9 @@ static size_t _psram_size = 0;
#include "hardware/structs/xip_ctrl.h"

static void __no_inline_not_in_flash_func(setup_psram)(void) {
// Read the system clock before QMI goes into direct mode; clock_get_hz() is
// in flash and XIP is reconfigured below.
uint32_t sys_clk_khz = clock_get_hz(clk_sys) / 1000;
gpio_set_function(CIRCUITPY_PSRAM_CHIP_SELECT->number, GPIO_FUNC_XIP_CS1);
_psram_size = 0;
common_hal_mcu_disable_interrupts();
Expand Down Expand Up @@ -237,14 +241,7 @@ static void __no_inline_not_in_flash_func(setup_psram)(void) {
// Disable direct csr.
qmi_hw->direct_csr &= ~(QMI_DIRECT_CSR_ASSERT_CS1N_BITS | QMI_DIRECT_CSR_EN_BITS);

qmi_hw->m[1].timing =
QMI_M0_TIMING_PAGEBREAK_VALUE_1024 << QMI_M0_TIMING_PAGEBREAK_LSB | // Break between pages.
3 << QMI_M0_TIMING_SELECT_HOLD_LSB | // Delay releasing CS for 3 extra system cycles.
1 << QMI_M0_TIMING_COOLDOWN_LSB |
1 << QMI_M0_TIMING_RXDELAY_LSB |
16 << QMI_M0_TIMING_MAX_SELECT_LSB | // In units of 64 system clock cycles. PSRAM says 8us max. 8 / 0.00752 / 64 = 16.62
7 << QMI_M0_TIMING_MIN_DESELECT_LSB | // In units of system clock cycles. PSRAM says 50ns.50 / 7.52 = 6.64
2 << QMI_M0_TIMING_CLKDIV_LSB;
mcu_processor_update_psram_timing(sys_clk_khz);
qmi_hw->m[1].rfmt = (QMI_M0_RFMT_PREFIX_WIDTH_VALUE_Q << QMI_M0_RFMT_PREFIX_WIDTH_LSB |
QMI_M0_RFMT_ADDR_WIDTH_VALUE_Q << QMI_M0_RFMT_ADDR_WIDTH_LSB |
QMI_M0_RFMT_SUFFIX_WIDTH_VALUE_Q << QMI_M0_RFMT_SUFFIX_WIDTH_LSB |
Expand Down
Loading