From 09140ead879f81313689ea7f9f9b014261ca5834 Mon Sep 17 00:00:00 2001 From: sh83 Date: Fri, 21 Oct 2022 22:52:30 +0300 Subject: [PATCH] rp2040: Added needed options to Kconfig, cleaned up. Modified linker script and loader to load whole bootloader to the RAM. Removed whatchdog. Fixed gpio.c compilation. Signed-off-by: Alex Malishev --- src/rp2040/Kconfig | 27 ++++--- src/rp2040/Makefile | 39 +++++----- src/rp2040/armcm_canboot.c | 135 +++++++++++++++++++++++++++++++++++ src/rp2040/gpio.c | 8 --- src/rp2040/main.c | 37 +--------- src/rp2040/rp2040_link.lds.S | 15 ++-- 6 files changed, 180 insertions(+), 81 deletions(-) create mode 100644 src/rp2040/armcm_canboot.c diff --git a/src/rp2040/Kconfig b/src/rp2040/Kconfig index 37862d3..6deae3d 100644 --- a/src/rp2040/Kconfig +++ b/src/rp2040/Kconfig @@ -1,4 +1,4 @@ -# Kconfig settings for STM32 processors +# Kconfig settings for RP2040 processor if MACH_RP2040 @@ -6,14 +6,7 @@ config RP2040_SELECT bool default y select HAVE_GPIO - select HAVE_GPIO_ADC - select HAVE_GPIO_SPI - select HAVE_GPIO_I2C - select HAVE_GPIO_BITBANGING - select HAVE_STRICT_TIMING select HAVE_CHIPID - select HAVE_GPIO_HARD_PWM - select HAVE_STEPPER_BOTH_EDGE config BOARD_DIRECTORY string @@ -47,6 +40,21 @@ config FLASH_START hex default 0x10000000 +config APPLICATION_START + default 0x10004000 + hex + +config DEPLOYER_START + hex + default 0x10004000 + +config RP2040_BOOTLOADER_START + hex + default 0x10000100 + +config BLOCK_SIZE + int + default 64 ###################################################################### # Bootloader options @@ -86,9 +94,6 @@ choice config RP2040_CANBUS bool "CAN bus" select CANSERIAL - config RP2040_USBCANBUS - bool "USB to CAN bus bridge" - select USBCANBUS endchoice config RP2040_CANBUS_GPIO_RX diff --git a/src/rp2040/Makefile b/src/rp2040/Makefile index 5bb572f..71e7281 100644 --- a/src/rp2040/Makefile +++ b/src/rp2040/Makefile @@ -8,27 +8,22 @@ dirs-y += src/rp2040 src/generic lib/rp2040/elf2uf2 lib/fast-hash lib/can2040 CFLAGS += -mcpu=cortex-m0plus -mthumb -Ilib/cmsis-core CFLAGS += -Ilib/rp2040 -Ilib/rp2040/cmsis_include -Ilib/fast-hash -Ilib/can2040 -CFLAGS_klipper.elf += --specs=nano.specs --specs=nosys.specs -CFLAGS_klipper.elf += -T $(OUT)src/rp2040/rp2040_link.ld -$(OUT)klipper.elf: $(OUT)stage2.o $(OUT)src/rp2040/rp2040_link.ld +CFLAGS_canboot.elf += --specs=nano.specs --specs=nosys.specs +CFLAGS_canboot.elf += -T $(OUT)src/rp2040/rp2040_link.ld # Add source files -src-y += rp2040/main.c rp2040/gpio.c rp2040/adc.c generic/crc16_ccitt.c -src-y += generic/armcm_boot.c generic/armcm_irq.c generic/armcm_reset.c -src-y += generic/timer_irq.c rp2040/timer.c rp2040/bootrom.c +mcu-y = rp2040/main.c rp2040/gpio.c rp2040/timer.c rp2040/flash.c rp2040/hw_flash.c +mcu-y += generic/armcm_irq.c generic/crc16_ccitt.c + +src-y += rp2040/armcm_canboot.c $(mcu-y) src-$(CONFIG_USBSERIAL) += rp2040/usbserial.c generic/usb_cdc.c src-$(CONFIG_USBSERIAL) += rp2040/chipid.c src-$(CONFIG_SERIAL) += rp2040/serial.c generic/serial_irq.c src-$(CONFIG_CANSERIAL) += rp2040/can.c rp2040/chipid.c ../lib/can2040/can2040.c src-$(CONFIG_CANSERIAL) += generic/canserial.c generic/canbus.c src-$(CONFIG_CANSERIAL) += ../lib/fast-hash/fasthash.c -src-$(CONFIG_USBCANBUS) += rp2040/can.c rp2040/chipid.c ../lib/can2040/can2040.c -src-$(CONFIG_USBCANBUS) += generic/canserial.c generic/usb_canbus.c -src-$(CONFIG_USBCANBUS) += ../lib/fast-hash/fasthash.c rp2040/usbserial.c -src-$(CONFIG_HAVE_GPIO_HARD_PWM) += rp2040/hard_pwm.c -src-$(CONFIG_HAVE_GPIO_SPI) += rp2040/spi.c -src-$(CONFIG_HAVE_GPIO_I2C) += rp2040/i2c.c +$(OUT)canboot.elf: $(OUT)stage2.o $(OUT)src/rp2040/rp2040_link.ld # rp2040 stage2 building STAGE2_FILE := $(shell echo $(CONFIG_RP2040_STAGE2_FILE)) $(OUT)stage2.o: lib/rp2040/boot_stage2/$(STAGE2_FILE) $(OUT)autoconf.h @@ -38,24 +33,30 @@ $(OUT)stage2.o: lib/rp2040/boot_stage2/$(STAGE2_FILE) $(OUT)autoconf.h $(Q)$(OBJCOPY) -O binary $(OUT)stage2raw.o $(OUT)stage2raw.bin $(Q)lib/rp2040/boot_stage2/pad_checksum -s 0xffffffff $(OUT)stage2raw.bin $(OUT)stage2.S $(Q)$(CC) $(CFLAGS) -c $(OUT)stage2.S -o $(OUT)stage2.o -OBJS_klipper.elf += $(OUT)stage2.o +OBJS_canboot.elf += $(OUT)stage2.o # Binary output file rules -target-y += $(OUT)klipper.uf2 +target-y += $(OUT)canboot.uf2 $(OUT)lib/rp2040/elf2uf2/elf2uf2: lib/rp2040/elf2uf2/main.cpp @echo " Building $@" $(Q)g++ -g -O -Ilib/rp2040 $< -o $@ -$(OUT)klipper.uf2: $(OUT)klipper.elf $(OUT)lib/rp2040/elf2uf2/elf2uf2 +$(OUT)canboot.uf2: $(OUT)canboot.elf $(OUT)lib/rp2040/elf2uf2/elf2uf2 @echo " Creating uf2 file $@" - $(Q)$(OUT)lib/rp2040/elf2uf2/elf2uf2 $< $@ + $(Q)$(OUT)lib/rp2040/elf2uf2/elf2uf2 $(OUT)canboot.elf $(OUT)canboot.uf2 lib/rp2040_flash/rp2040_flash: @echo " Building rp2040_flash" $(Q)make -C lib/rp2040_flash rp2040_flash # Flash rules -flash: $(OUT)klipper.uf2 lib/rp2040_flash/rp2040_flash - @echo " Flashing $< to $(FLASH_DEVICE)" - $(Q)$(PYTHON) ./scripts/flash_usb.py -t $(CONFIG_MCU) -d "$(FLASH_DEVICE)" $(if $(NOSUDO),--no-sudo) $(OUT)klipper.uf2 +flash: $(OUT)canboot.uf2 lib/rp2040_flash/rp2040_flash + @echo " Flashing $< " + $(Q)./lib/rp2040_flash/rp2040_flash $(OUT)canboot.uf2 + +# Deployer build +deployer-y += generic/armcm_boot.c generic/armcm_reset.c $(mcu-y) +CFLAGS_deployer.elf += --specs=nano.specs --specs=nosys.specs +CFLAGS_deployer.elf += -T $(OUT)src/generic/armcm_deployer.ld +$(OUT)deployer.elf: $(OUT)src/generic/armcm_deployer.ld diff --git a/src/rp2040/armcm_canboot.c b/src/rp2040/armcm_canboot.c new file mode 100644 index 0000000..f573488 --- /dev/null +++ b/src/rp2040/armcm_canboot.c @@ -0,0 +1,135 @@ +// CanBoot specific entry code for ARM Cortex-M vector table and bootup +// +// Copyright (C) 2019 Kevin O'Connor +// +// This file may be distributed under the terms of the GNU GPLv3 license. + +#include // memcpy +#include "generic/armcm_boot.h" // DECL_ARMCM_IRQ +#include "autoconf.h" // CONFIG_MCU +#include "board/internal.h" // SysTick +#include "board/irq.h" // irq_disable +#include "board/misc.h" // get_bootup_code +#include "command.h" // DECL_CONSTANT_STR + +// Export MCU type +DECL_CONSTANT_STR("MCU", CONFIG_MCU); + +// Symbols created by armcm_link.lds.S linker script +extern uint32_t _data_start, _data_end, _data_flash; +extern uint32_t _bss_start, _bss_end, _stack_start; +extern uint32_t _stack_end; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" + +uint64_t +get_bootup_code(void) +{ + uint64_t *req_code = (void*)&_stack_end; + return *req_code; +} + +void +set_bootup_code(uint64_t code) +{ + uint64_t *req_code = (void*)&_stack_end; + *req_code = code; + barrier(); +} + +#pragma GCC diagnostic pop + +// Helper function to read area of flash +void +application_read_flash(uint32_t address, uint32_t *dest) +{ + memcpy(dest, (void*)address, CONFIG_BLOCK_SIZE); +} + +// Check if the application flash area looks valid +int +application_check_valid(void) +{ + uint32_t *app = (void*)CONFIG_APPLICATION_START; + return *app != 0 && *app != 0xffffffff; +} + +// Jump to the main application (exiting the bootloader) +void +application_jump(void) +{ + irq_disable(); + set_bootup_code(REQUEST_START_APP); + NVIC_SystemReset(); +} + +static void +start_application(void) +{ + set_bootup_code(0); + uint32_t *vtor = (void*)CONFIG_APPLICATION_START; + SCB->VTOR = (uint32_t)vtor; + asm volatile("MSR msp, %0\n bx %1" : : "r"(vtor[0]), "r"(vtor[1])); +} + +void __noreturn __visible +__attribute__((used, section(".reset_handler_flash.reset_handler_stage_two"))) +reset_handler_stage_two(void) +{ + // Copy global variables from flash to ram + uint32_t count = (&_data_end - &_data_start); + for(int i = 0; i < count; i++) { + (&_data_start)[i] = (&_data_flash)[i]; + barrier(); + } + // Clear the bss segment + count = (&_bss_end - &_bss_start); + for(int i = 0 ; i < count; i++ ) { + (&_bss_start)[i] = 0; + barrier(); + } + SCB->VTOR = (uint32_t)VectorTable; + barrier(); + //All data have been transferred to the ram. + //Now it is safe to call any function, not just in .reset_handler_flash. + + // Initializing the C library isn't needed... + //__libc_init_array(); + + uint64_t bootup_code = get_bootup_code(); + if (bootup_code == REQUEST_START_APP) + start_application(); + + // Run the main board specific code + armcm_main(); + + // The armcm_main() call should not return + for (;;) + ; +} + +// Initial code entry point - invoked by the processor after a reset +asm(".section .reset_handler_flash.ResetHandler\n" + ".balign 8\n" + ".8byte " __stringify(CANBOOT_SIGNATURE) "\n" + ".global ResetHandler\n" + ".type ResetHandler, %function\n" + "ResetHandler:\n" + " b reset_handler_stage_two\n" + ); +extern void ResetHandler(); +DECL_ARMCM_IRQ(ResetHandler, -15); + +// Code called for any undefined interrupts +void +DefaultHandler(void) +{ + for (;;) + ; +} + +const void *VectorTableFlash[32] __attribute__((used, section(".vector_table_flash"))) = { + &_stack_end, + ResetHandler +}; diff --git a/src/rp2040/gpio.c b/src/rp2040/gpio.c index bac67d2..36d191e 100644 --- a/src/rp2040/gpio.c +++ b/src/rp2040/gpio.c @@ -48,13 +48,9 @@ mask_to_pin(uint32_t mask) struct gpio_out gpio_out_setup(uint8_t pin, uint8_t val) { - if (pin > 30) - goto fail; struct gpio_out g = { .bit=1< 30) - goto fail; struct gpio_in g = { .bit=1<load = 0x800000; // ~350ms -} -DECL_TASK(watchdog_reset); - -void -watchdog_init(void) -{ - watchdog_reset(); - watchdog_hw->ctrl = (WATCHDOG_CTRL_PAUSE_DBG0_BITS - | WATCHDOG_CTRL_PAUSE_DBG1_BITS - | WATCHDOG_CTRL_PAUSE_JTAG_BITS - | WATCHDOG_CTRL_ENABLE_BITS); -} -DECL_INIT(watchdog_init); - - -/**************************************************************** - * Bootloader - ****************************************************************/ - -void -bootloader_request(void) -{ - // Use the bootrom-provided code to reset into BOOTSEL mode - reset_to_usb_boot(0, 0); -} - - /**************************************************************** * Clock setup ****************************************************************/ @@ -163,6 +127,7 @@ clock_setup(void) // Main entry point - called from armcm_boot.c:ResetHandler() void +noinline armcm_main(void) { clock_setup(); diff --git a/src/rp2040/rp2040_link.lds.S b/src/rp2040/rp2040_link.lds.S index 3ffcd90..8df488d 100644 --- a/src/rp2040/rp2040_link.lds.S +++ b/src/rp2040/rp2040_link.lds.S @@ -20,11 +20,9 @@ SECTIONS .text : { . = ALIGN(4); KEEP(*(.boot2)) - _text_vectortable_start = .; - KEEP(*(.vector_table)) - _text_vectortable_end = .; - *(.text .text.*) - *(.rodata .rodata*) + KEEP(*(.vector_table_flash)) + KEEP(*(.reset_handler_flash)) + KEEP(*(.reset_handler_flash.*)) } > rom . = ALIGN(4); @@ -32,8 +30,11 @@ SECTIONS .data : AT (_data_flash) { - . = ALIGN(4); + . = ALIGN(128); _data_start = .; + KEEP(*(.vector_table)) + *(.text .text.*) + *(.rodata .rodata*) *(.ramfunc .ramfunc.*); *(.data .data.*); . = ALIGN(4); @@ -50,7 +51,7 @@ SECTIONS _bss_end = .; } > ram - _stack_start = CONFIG_RAM_START + CONFIG_RAM_SIZE - CONFIG_STACK_SIZE ; + _stack_start = CONFIG_RAM_START + CONFIG_RAM_SIZE - CONFIG_STACK_SIZE - 1024; .stack _stack_start (NOLOAD) : { . = . + CONFIG_STACK_SIZE;