diff options
Diffstat (limited to 'ports/raspberrypi/supervisor/port.c')
| -rw-r--r-- | ports/raspberrypi/supervisor/port.c | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/ports/raspberrypi/supervisor/port.c b/ports/raspberrypi/supervisor/port.c new file mode 100644 index 000000000..b2f73c7b4 --- /dev/null +++ b/ports/raspberrypi/supervisor/port.c @@ -0,0 +1,200 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <string.h> +#include <stdlib.h> + +#include "supervisor/board.h" +#include "supervisor/port.h" + +#include "bindings/rp2pio/StateMachine.h" +#include "genhdr/mpversion.h" +#include "shared-bindings/busio/I2C.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/rtc/__init__.h" +#include "shared-bindings/pwmio/PWMOut.h" + +#include "supervisor/shared/safe_mode.h" +#include "supervisor/shared/stack.h" +#include "supervisor/shared/tick.h" + +#include "src/rp2040/hardware_structs/include/hardware/structs/watchdog.h" +#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" +#include "src/rp2_common/hardware_uart/include/hardware/uart.h" +#include "src/rp2_common/hardware_sync/include/hardware/sync.h" +#include "src/rp2_common/hardware_timer/include/hardware/timer.h" +#include "src/common/pico_time/include/pico/time.h" +#include "src/common/pico_binary_info/include/pico/binary_info.h" + +#include "tusb.h" + + +extern volatile bool mp_msc_enabled; + +STATIC void _tick_callback(uint alarm_num); + +STATIC void _binary_info(void) { + // Binary info readable with `picotool`. + bi_decl(bi_program_name("CircuitPython")); + bi_decl(bi_program_version_string(MICROPY_GIT_TAG)); + bi_decl(bi_program_build_date_string(MICROPY_BUILD_DATE)); + bi_decl(bi_program_url("https://circuitpython.org")); + + bi_decl(bi_program_build_attribute("BOARD=" CIRCUITPY_BOARD_ID)); + // TODO: Add build attribute for debug builds. Needs newer CircuitPython with CIRCUITPY_DEBUG. +} + +safe_mode_t port_init(void) { + _binary_info(); + // Set brown out. + + // Reset everything into a known state before board_init. + reset_port(); + + // For the tick. + hardware_alarm_claim(0); + hardware_alarm_set_callback(0, _tick_callback); + + // Check brownout. + + if (board_requests_safe_mode()) { + return USER_SAFE_MODE; + } + + return NO_SAFE_MODE; +} + +void reset_port(void) { + #if CIRCUITPY_BUSIO + reset_i2c(); + reset_spi(); + #endif + + #if CIRCUITPY_RP2PIO + reset_rp2pio_statemachine(); + #endif + + #if CIRCUITPY_PWMIO + pwmout_reset(); + #endif + + reset_all_pins(); +} + +void reset_to_bootloader(void) { + // reset(); + while (true) {} +} + +void reset_cpu(void) { + // reset(); + while (true) {} +} + +bool port_has_fixed_stack(void) { + return false; +} + +// From the linker script +extern uint32_t __HeapLimit; +extern uint32_t __StackTop; +uint32_t *port_stack_get_limit(void) { + return &__HeapLimit; +} + +uint32_t *port_stack_get_top(void) { + return &__StackTop; +} + +uint32_t *port_heap_get_bottom(void) { + return port_stack_get_limit(); +} + +uint32_t *port_heap_get_top(void) { + return port_stack_get_top(); +} + +void port_set_saved_word(uint32_t value) { + // NOTE: This doesn't survive pressing the reset button (aka toggling RUN). + watchdog_hw->scratch[0] = value; +} + +uint32_t port_get_saved_word(void) { + return watchdog_hw->scratch[0]; +} + +uint64_t port_get_raw_ticks(uint8_t* subticks) { + uint64_t microseconds = time_us_64(); + return 1024 * (microseconds / 1000000) + (microseconds % 1000000) / 977; +} + +STATIC void _tick_callback(uint alarm_num) { + supervisor_tick(); + hardware_alarm_set_target(0, delayed_by_us(get_absolute_time(), 977)); +} + +// Enable 1/1024 second tick. +void port_enable_tick(void) { + hardware_alarm_set_target(0, delayed_by_us(get_absolute_time(), 977)); +} + +// Disable 1/1024 second tick. +void port_disable_tick(void) { + // hardware_alarm_cancel(0); +} + +// This is called by sleep, we ignore it when our ticks are enabled because +// they'll wake us up earlier. If we don't, we'll mess up ticks by overwriting +// the next RTC wake up time. +void port_interrupt_after_ticks(uint32_t ticks) { +} + +void port_idle_until_interrupt(void) { + common_hal_mcu_disable_interrupts(); + if (!tud_task_event_ready()) { +// asm volatile ("dsb 0xF":::"memory"); +// __wfi(); + } + common_hal_mcu_enable_interrupts(); +} + +/** + * \brief Default interrupt handler for unused IRQs. + */ +__attribute__((used)) void HardFault_Handler(void) +{ +#ifdef ENABLE_MICRO_TRACE_BUFFER + // Turn off the micro trace buffer so we don't fill it up in the infinite + // loop below. + REG_MTB_MASTER = 0x00000000 + 6; +#endif + + reset_into_safe_mode(HARD_CRASH); + while (true) { + asm("nop;"); + } +} |
