/* * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. * * SPDX-License-Identifier: BSD-3-Clause */ #include "pico/runtime_init.h" // This file is sorted in the order of initialization // ------------------------------------- // 00050 PICO_RUNTIME_INIT_BOOTROM_RESET // ------------------------------------- #if !PICO_RUNTIME_NO_INIT_BOOTROM_RESET #include "pico/bootrom.h" void __weak runtime_init_bootrom_reset(void) { // todo can we tell if we came in thru the bootrom where this is not necessary (this is necessary for debugger) rom_bootrom_state_reset_fn state_reset = rom_func_lookup(ROM_FUNC_BOOTROM_STATE_RESET); state_reset(BOOTROM_STATE_RESET_GLOBAL_STATE); } #endif #if !PICO_RUNTIME_SKIP_INIT_BOOTROM_RESET PICO_RUNTIME_INIT_FUNC_RUNTIME(runtime_init_bootrom_reset, PICO_RUNTIME_INIT_BOOTROM_RESET); #endif // ---------------------------------------------- // 00051 PICO_RUNTIME_INIT_PER_CORE_BOOTROM_RESET // ---------------------------------------------- #if !PICO_RUNTIME_NO_INIT_PER_CORE_BOOTROM_RESET #include "pico/bootrom.h" void __weak runtime_init_per_core_bootrom_reset(void) { // todo can we tell if we came in thru the bootrom where this is not necessary (this is necessary for debugger) rom_bootrom_state_reset_fn state_reset = rom_func_lookup(ROM_FUNC_BOOTROM_STATE_RESET); state_reset(BOOTROM_STATE_RESET_CURRENT_CORE); } #endif #if !PICO_RUNTIME_SKIP_INIT_PER_CORE_BOOTROM_RESET PICO_RUNTIME_INIT_FUNC_PER_CORE(runtime_init_per_core_bootrom_reset, PICO_RUNTIME_INIT_PER_CORE_BOOTROM_RESET); #endif // ------------------------------------ // 00060 PICO_RUNTIME_INIT_H3_IRQ_REGISTERS // ------------------------------------ #if !PICO_RUNTIME_SKIP_INIT_PER_CORE_H3_IRQ_REGISTERS extern void runtime_init_per_core_h3_irq_registers(void); PICO_RUNTIME_INIT_FUNC_PER_CORE(runtime_init_per_core_h3_irq_registers, PICO_RUNTIME_INIT_PER_CORE_H3_IRQ_REGISTERS); #endif // ------------------------------------ // 00100 PICO_RUNTIME_INIT_EARLY_RESETS // ------------------------------------ #if !PICO_RUNTIME_NO_INIT_EARLY_RESETS #include "hardware/resets.h" void __weak runtime_init_early_resets(void) { static_assert(NUM_RESETS <= 32, ""); // Reset all peripherals to put system into a known state, // - except for QSPI pads and the XIP IO bank, as this is fatal if running from flash // - and the PLLs, as this is fatal if clock muxing has not been reset on this boot // - and USB, syscfg, as this disturbs USB-to-SWD on core 1 reset_block_mask(~( (1u << RESET_IO_QSPI) | (1u << RESET_PADS_QSPI) | (1u << RESET_PLL_USB) | (1u << RESET_USBCTRL) | (1u << RESET_SYSCFG) | (1u << RESET_PLL_SYS) )); // Remove reset from peripherals which are clocked only by clk_sys and // clk_ref. Other peripherals stay in reset until we've configured clocks. unreset_block_mask_wait_blocking(RESETS_RESET_BITS & ~( #if !PICO_RP2040 (1u << RESET_HSTX) | #endif (1u << RESET_ADC) | #if PICO_RP2040 (1u << RESET_RTC) | #endif (1u << RESET_SPI0) | (1u << RESET_SPI1) | (1u << RESET_UART0) | (1u << RESET_UART1) | (1u << RESET_USBCTRL) )); } #endif #if !PICO_RUNTIME_SKIP_INIT_EARLY_RESETS PICO_RUNTIME_INIT_FUNC_HW(runtime_init_early_resets, PICO_RUNTIME_INIT_EARLY_RESETS); #endif #if !PICO_RUNTIME_NO_INIT_USB_POWER_DOWN #include "hardware/structs/usb.h" void __weak runtime_init_usb_power_down(void) { // Ensure USB PHY is in low-power state -- must be cleared before beginning USB operations. Only // do this if USB appears to be in the reset state, to avoid breaking core1-as-debugger. if (usb_hw->sie_ctrl == USB_SIE_CTRL_RESET) { hw_set_bits(&usb_hw->sie_ctrl, USB_SIE_CTRL_TRANSCEIVER_PD_BITS); } } #endif #if !PICO_RUNTIME_SKIP_INIT_USB_POWER_DOWN PICO_RUNTIME_INIT_FUNC_HW(runtime_init_usb_power_down, PICO_RUNTIME_INIT_USB_POWER_DOWN); #endif #if !PICO_RUNTIME_NO_INIT_PER_CORE_ENABLE_COPROCESSORS #include "hardware/gpio.h" // PICO_USE_GPIO_COPROCESSOR is defined here #include "hardware/structs/m33.h" // ---------------------------------------------------- // 00200 PICO_RUNTIME_INIT_PER_CORE_ENABLE_COPROCESSORS // ---------------------------------------------------- void __weak runtime_init_per_core_enable_coprocessors(void) { // VFP copro (float) uint32_t cpacr = M33_CPACR_CP10_BITS; #if HAS_DOUBLE_COPROCESSOR cpacr |= M33_CPACR_CP4_BITS; #endif #if PICO_USE_GPIO_COPROCESSOR cpacr |= M33_CPACR_CP0_BITS; #endif arm_cpu_hw->cpacr |= cpacr; #if HAS_DOUBLE_COPROCESSOR asm volatile ("mrc p4,#0,r0,c0,c0,#1" : : : "r0"); // clear engaged flag via RCMP #endif } #endif #if !PICO_RUNTIME_SKIP_INIT_PER_CORE_ENABLE_COPROCESSORS PICO_RUNTIME_INIT_FUNC_PER_CORE(runtime_init_per_core_enable_coprocessors, PICO_RUNTIME_INIT_PER_CORE_ENABLE_COPROCESSORS); #endif // ---------------------------------------------------- // 00500 PICO_RUNTIME_INIT_CLOCKS // ---------------------------------------------------- #if !PICO_RUNTIME_SKIP_INIT_CLOCKS PICO_RUNTIME_INIT_FUNC_HW(runtime_init_clocks, PICO_RUNTIME_INIT_CLOCKS); #endif // ---------------------------------------------------- // 00600 PICO_RUNTIME_INIT_POST_CLOCK_RESETS // ---------------------------------------------------- #if !PICO_RUNTIME_NO_INIT_POST_CLOCK_RESETS #include "hardware/resets.h" void __weak runtime_init_post_clock_resets(void) { // Peripheral clocks should now all be running static_assert(NUM_RESETS <= 32, ""); unreset_block_mask_wait_blocking(RESETS_RESET_BITS); } #endif #if !PICO_RUNTIME_SKIP_POST_CLOCK_RESETS PICO_RUNTIME_INIT_FUNC_HW(runtime_init_post_clock_resets, PICO_RUNTIME_INIT_POST_CLOCK_RESETS); #endif // ---------------------------------------------------- // 00700 PICO_RUNTIME_INIT_RP2040_GPIO_IE_DISABLE // ---------------------------------------------------- #if !PICO_RUNTIME_NO_INIT_RP2040_GPIO_IE_DISABLE #include "hardware/structs/pads_bank0.h" void __weak runtime_init_rp2040_gpio_ie_disable(void) { #if PICO_RP2040 && !PICO_IE_26_29_UNCHANGED_ON_RESET // after resetting BANK0 we should disable IE on 26-29 as these may have mid-rail voltages when // ADC is in use (on RP2040 B2 and later, and non-RP2040 chips, ADC pins should already have // the correct reset state): pads_bank0_hw_t *pads_bank0_hw_clear = (pads_bank0_hw_t *)hw_clear_alias_untyped(pads_bank0_hw); pads_bank0_hw_clear->io[26] = pads_bank0_hw_clear->io[27] = pads_bank0_hw_clear->io[28] = pads_bank0_hw_clear->io[29] = PADS_BANK0_GPIO0_IE_BITS; #endif } #endif #if !PICO_RUNTIME_SKIP_INIT_RP2040_GPIO_IE_DISABLE PICO_RUNTIME_INIT_FUNC_HW(runtime_init_rp2040_gpio_ie_disable, PICO_RUNTIME_INIT_RP2040_GPIO_IE_DISABLE); #endif #if !PICO_RUNTIME_NO_INIT_SPIN_LOCKS_RESET #include "hardware/sync.h" void __weak runtime_init_spin_locks_reset(void) { spin_locks_reset(); } #endif #if !PICO_RUNTIME_SKIP_INIT_SPIN_LOCKS_RESET PICO_RUNTIME_INIT_FUNC_RUNTIME(runtime_init_spin_locks_reset, PICO_RUNTIME_INIT_SPIN_LOCKS_RESET); #endif // On RISC-V the vector table is not relocatable since it contains PC-relative // jump instructions, so rather than copying it into a RAM-resident array, we // just link it in an initialised RAM section. Note there is no requirement on // RISC-V to have an initial flash-resident vector table at a well-known // location, unlike Cortex-M which can take an NMI on cycle 0. #ifndef __riscv #if !PICO_RUNTIME_NO_INIT_INSTALL_RAM_VECTOR_TABLE uint32_t __attribute__((section(".ram_vector_table"))) ram_vector_table[PICO_RAM_VECTOR_TABLE_SIZE]; #include "hardware/structs/scb.h" void runtime_init_install_ram_vector_table(void) { // Note on RISC-V the RAM vector table is initialised during crt0 #if !(PICO_NO_RAM_VECTOR_TABLE || PICO_NO_FLASH) && !defined(__riscv) #if !PICO_NO_STORED_VECTOR_TABLE __builtin_memcpy(ram_vector_table, (uint32_t *) scb_hw->vtor, sizeof(ram_vector_table)); #else __builtin_memcpy(ram_vector_table, (uint32_t *) scb_hw->vtor, MIN(VTABLE_FIRST_IRQ, sizeof(ram_vector_table))); for(uint i = VTABLE_FIRST_IRQ; ivtor = (uintptr_t) ram_vector_table; #endif } #endif #endif #if !PICO_RUNTIME_SKIP_INIT_INSTALL_RAM_VECTOR_TABLE // todo this wants to be per core if we decide to support per core vector tables PICO_RUNTIME_INIT_FUNC_RUNTIME(runtime_init_install_ram_vector_table, PICO_RUNTIME_INIT_INSTALL_RAM_VECTOR_TABLE); #endif