From b59ad4b088ffc93c2abf54c9da762d0c307b09bb Mon Sep 17 00:00:00 2001 From: marble Date: Sun, 4 Feb 2024 03:04:18 +0100 Subject: [PATCH 01/14] firmware: rename uart_init to uart_initialize rename uart_init to prevent collision with pico sdk --- firmware/src/boards/cynthion_d11/uart.c | 2 +- firmware/src/boards/cynthion_d21/uart.c | 2 +- firmware/src/boards/daisho/uart.c | 2 +- firmware/src/boards/qtpy/uart.c | 2 +- firmware/src/boards/samd11_xplained/uart.c | 2 +- firmware/src/console.c | 6 +++--- firmware/src/uart.h | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/firmware/src/boards/cynthion_d11/uart.c b/firmware/src/boards/cynthion_d11/uart.c index 9b1198c..7dead05 100644 --- a/firmware/src/boards/cynthion_d11/uart.c +++ b/firmware/src/boards/cynthion_d11/uart.c @@ -68,7 +68,7 @@ void uart_release_pinmux(void) * Configures the UART we'll use for our system console. * TODO: support more configuration (parity, stop, etc.) */ -void uart_init(bool configure_pinmux, unsigned long baudrate) +void uart_initialize(bool configure_pinmux, unsigned long baudrate) { // Disable the SERCOM before configuring it, to 1) ensure we're not transacting // during configuration; and 2) as many of the registers are R/O when the SERCOM is enabled. diff --git a/firmware/src/boards/cynthion_d21/uart.c b/firmware/src/boards/cynthion_d21/uart.c index 915dca2..ea4a7d7 100644 --- a/firmware/src/boards/cynthion_d21/uart.c +++ b/firmware/src/boards/cynthion_d21/uart.c @@ -68,7 +68,7 @@ void uart_release_pinmux(void) * Configures the UART we'll use for our system console. * TODO: support more configuration (parity, stop, etc.) */ -void uart_init(bool configure_pinmux, unsigned long baudrate) +void uart_initialize(bool configure_pinmux, unsigned long baudrate) { // Disable the SERCOM before configuring it, to 1) ensure we're not transacting // during configuration; and 2) as many of the registers are R/O when the SERCOM is enabled. diff --git a/firmware/src/boards/daisho/uart.c b/firmware/src/boards/daisho/uart.c index 36dbc28..1ae9b88 100644 --- a/firmware/src/boards/daisho/uart.c +++ b/firmware/src/boards/daisho/uart.c @@ -18,7 +18,7 @@ * @param configure_pinmux If true, the pinmux will be configured for UART use during init. * @param baudrate The baud rate to apply, in symbols/second. */ -void uart_init(bool configure_pinmux, unsigned long baudrate) +void uart_initialize(bool configure_pinmux, unsigned long baudrate) { } diff --git a/firmware/src/boards/qtpy/uart.c b/firmware/src/boards/qtpy/uart.c index cb2b029..00ff118 100644 --- a/firmware/src/boards/qtpy/uart.c +++ b/firmware/src/boards/qtpy/uart.c @@ -68,7 +68,7 @@ void uart_release_pinmux(void) * Configures the UART we'll use for our system console. * TODO: support more configuration (parity, stop, etc.) */ -void uart_init(bool configure_pinmux, unsigned long baudrate) +void uart_initialize(bool configure_pinmux, unsigned long baudrate) { // Disable the SERCOM before configuring it, to 1) ensure we're not transacting // during configuration; and 2) as many of the registers are R/O when the SERCOM is enabled. diff --git a/firmware/src/boards/samd11_xplained/uart.c b/firmware/src/boards/samd11_xplained/uart.c index 35aab82..23ef1f9 100644 --- a/firmware/src/boards/samd11_xplained/uart.c +++ b/firmware/src/boards/samd11_xplained/uart.c @@ -68,7 +68,7 @@ void uart_release_pinmux(void) * Configures the UART we'll use for our system console. * TODO: support more configuration (parity, stop, etc.) */ -void uart_init(bool configure_pinmux, unsigned long baudrate) +void uart_initialize(bool configure_pinmux, unsigned long baudrate) { // Disable the SERCOM before configuring it, to 1) ensure we're not transacting // during configuration; and 2) as many of the registers are R/O when the SERCOM is enabled. diff --git a/firmware/src/console.c b/firmware/src/console.c index 1c62faa..a9e89a8 100644 --- a/firmware/src/console.c +++ b/firmware/src/console.c @@ -61,7 +61,7 @@ void console_task(void) */ void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* coding) { - uart_init(true, coding->bit_rate); + uart_initialize(true, coding->bit_rate); } @@ -72,13 +72,13 @@ void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* coding) void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) { if (!uart_active) { - uart_init(true, 115200); + uart_initialize(true, 115200); } } void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { if (!uart_active) { - uart_init(true, 115200); + uart_initialize(true, 115200); } } diff --git a/firmware/src/uart.h b/firmware/src/uart.h index 12166c3..4d395d1 100644 --- a/firmware/src/uart.h +++ b/firmware/src/uart.h @@ -17,7 +17,7 @@ * @param configure_pinmux If true, the pinmux will be configured for UART use during init. * @param baudrate The baud rate to apply, in symbols/second. */ -void uart_init(bool configure_pinmux, unsigned long baudrate); +void uart_initialize(bool configure_pinmux, unsigned long baudrate); /** * Configures the relevant UART's target's pins to be used for UART. From c5297e8791f056337468c08f383d90d04eb9ee22 Mon Sep 17 00:00:00 2001 From: marble Date: Sun, 4 Feb 2024 03:08:32 +0100 Subject: [PATCH 02/14] modules: add pico sdk --- .gitmodules | 3 +++ lib/pico-sdk | 1 + 2 files changed, 4 insertions(+) create mode 160000 lib/pico-sdk diff --git a/.gitmodules b/.gitmodules index f2e3e70..60fe12a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "lib/tinyusb"] path = lib/tinyusb url = https://github.com/hathach/tinyusb +[submodule "lib/pico-sdk"] + path = lib/pico-sdk + url = https://github.com/raspberrypi/pico-sdk.git diff --git a/lib/pico-sdk b/lib/pico-sdk new file mode 160000 index 0000000..6a7db34 --- /dev/null +++ b/lib/pico-sdk @@ -0,0 +1 @@ +Subproject commit 6a7db34ff63345a7badec79ebea3aaef1712f374 From f613c051a1426e9db1053ac721b3a85aad5abae4 Mon Sep 17 00:00:00 2001 From: marble Date: Sun, 4 Feb 2024 03:17:11 +0100 Subject: [PATCH 03/14] firmware: add support for the raspberry pi pico --- firmware/CMakeLists.txt | 60 +++++ .../src/{ => boards/cynthion_d11}/button.c | 0 .../{ => boards/cynthion_d11}/usb_switch.c | 0 firmware/src/boards/cynthion_d21/button.c | 37 +++ firmware/src/boards/cynthion_d21/usb_switch.c | 36 +++ firmware/src/boards/daisho/button.c | 37 +++ firmware/src/boards/daisho/usb_switch.c | 36 +++ firmware/src/boards/qtpy/button.c | 37 +++ firmware/src/boards/qtpy/usb_switch.c | 36 +++ .../boards/raspberry_pi_pico/apollo_board.h | 109 +++++++++ .../src/boards/raspberry_pi_pico/board.mk | 11 + .../src/boards/raspberry_pi_pico/button.c | 36 +++ .../src/boards/raspberry_pi_pico/debug_spi.c | 36 +++ firmware/src/boards/raspberry_pi_pico/dfu.c | 22 ++ firmware/src/boards/raspberry_pi_pico/fpga.c | 44 ++++ firmware/src/boards/raspberry_pi_pico/jtag.c | 34 +++ firmware/src/boards/raspberry_pi_pico/led.c | 127 ++++++++++ .../boards/raspberry_pi_pico/platform_jtag.h | 44 ++++ firmware/src/boards/raspberry_pi_pico/spi.c | 171 +++++++++++++ firmware/src/boards/raspberry_pi_pico/spi.h | 59 +++++ .../boards/raspberry_pi_pico/tusb_config.h | 119 +++++++++ firmware/src/boards/raspberry_pi_pico/uart.c | 147 +++++++++++ .../raspberry_pi_pico/usb_descriptors.c | 231 ++++++++++++++++++ .../src/boards/raspberry_pi_pico/usb_switch.c | 35 +++ firmware/src/boards/samd11_xplained/button.c | 37 +++ .../src/boards/samd11_xplained/usb_switch.c | 36 +++ 26 files changed, 1577 insertions(+) create mode 100644 firmware/CMakeLists.txt rename firmware/src/{ => boards/cynthion_d11}/button.c (100%) rename firmware/src/{ => boards/cynthion_d11}/usb_switch.c (100%) create mode 100644 firmware/src/boards/cynthion_d21/button.c create mode 100644 firmware/src/boards/cynthion_d21/usb_switch.c create mode 100644 firmware/src/boards/daisho/button.c create mode 100644 firmware/src/boards/daisho/usb_switch.c create mode 100644 firmware/src/boards/qtpy/button.c create mode 100644 firmware/src/boards/qtpy/usb_switch.c create mode 100644 firmware/src/boards/raspberry_pi_pico/apollo_board.h create mode 100644 firmware/src/boards/raspberry_pi_pico/board.mk create mode 100644 firmware/src/boards/raspberry_pi_pico/button.c create mode 100644 firmware/src/boards/raspberry_pi_pico/debug_spi.c create mode 100644 firmware/src/boards/raspberry_pi_pico/dfu.c create mode 100644 firmware/src/boards/raspberry_pi_pico/fpga.c create mode 100644 firmware/src/boards/raspberry_pi_pico/jtag.c create mode 100644 firmware/src/boards/raspberry_pi_pico/led.c create mode 100644 firmware/src/boards/raspberry_pi_pico/platform_jtag.h create mode 100644 firmware/src/boards/raspberry_pi_pico/spi.c create mode 100644 firmware/src/boards/raspberry_pi_pico/spi.h create mode 100644 firmware/src/boards/raspberry_pi_pico/tusb_config.h create mode 100644 firmware/src/boards/raspberry_pi_pico/uart.c create mode 100644 firmware/src/boards/raspberry_pi_pico/usb_descriptors.c create mode 100644 firmware/src/boards/raspberry_pi_pico/usb_switch.c create mode 100644 firmware/src/boards/samd11_xplained/button.c create mode 100644 firmware/src/boards/samd11_xplained/usb_switch.c diff --git a/firmware/CMakeLists.txt b/firmware/CMakeLists.txt new file mode 100644 index 0000000..b0687a8 --- /dev/null +++ b/firmware/CMakeLists.txt @@ -0,0 +1,60 @@ +cmake_minimum_required(VERSION 3.17) +set_property(GLOBAL PROPERTY USE_FOLDERS ON) +# set(CMAKE_C_COMPILER_WORKS 1) + +#set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +include(${CMAKE_CURRENT_SOURCE_DIR}/../lib/tinyusb/hw/bsp/family_support.cmake) + +# gets PROJECT name for the example (e.g. -) +family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) + +project(${PROJECT} C CXX ASM) + +# Checks this example is valid for the family and initializes the project +family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) + +# Espressif has its own cmake build system +if(FAMILY STREQUAL "espressif") + return() +endif() + +add_executable(${PROJECT}) + +# Example source +target_sources(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src/console.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/debug_spi.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/jtag.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/jtag_tap.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/vendor.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/button.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/dfu.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/jtag.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/fpga.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/debug_spi.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/spi.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/led.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/uart.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/usb_descriptors.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/usb_switch.c + ) + +# Example include +target_include_directories(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src + ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD} + ) + +target_compile_definitions(${PROJECT} PUBLIC +# CFG_TUSB_OS=OPT_OS_PICO + _BOARD_REVISION_MAJOR_=${BOARD_REVISION_MAJOR} + _BOARD_REVISION_MINOR_=${BOARD_REVISION_MINOR} + ) + +# Configure compilation flags and libraries for the example... see the corresponding function +# in hw/bsp/FAMILY/family.cmake for details. +# family_configure_device_example(${PROJECT} noos) +family_configure_target(${PROJECT} noos) +target_link_libraries(${PROJECT} PUBLIC pico_stdlib tinyusb_device pico_unique_id pico_fix_rp2040_usb_device_enumeration hardware_spi) + diff --git a/firmware/src/button.c b/firmware/src/boards/cynthion_d11/button.c similarity index 100% rename from firmware/src/button.c rename to firmware/src/boards/cynthion_d11/button.c diff --git a/firmware/src/usb_switch.c b/firmware/src/boards/cynthion_d11/usb_switch.c similarity index 100% rename from firmware/src/usb_switch.c rename to firmware/src/boards/cynthion_d11/usb_switch.c diff --git a/firmware/src/boards/cynthion_d21/button.c b/firmware/src/boards/cynthion_d21/button.c new file mode 100644 index 0000000..ff2d7b8 --- /dev/null +++ b/firmware/src/boards/cynthion_d21/button.c @@ -0,0 +1,37 @@ +/** + * button handler + * + * Copyright (c) 2023 Great Scott Gadgets + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "button.h" +#include "usb_switch.h" +#include "fpga.h" +#include "apollo_board.h" +#include + + +/** + * Detect button press. + */ +bool button_pressed(void) +{ +#ifdef BOARD_HAS_PROGRAM_BUTTON + return (gpio_get_pin_level(PROGRAM_BUTTON) == false); +#else + return false; +#endif +} + + +/** + * Handle button events. + */ +void button_task(void) +{ + if (button_pressed()) { + force_fpga_offline(); + take_over_usb(); + } +} diff --git a/firmware/src/boards/cynthion_d21/usb_switch.c b/firmware/src/boards/cynthion_d21/usb_switch.c new file mode 100644 index 0000000..8b13ac7 --- /dev/null +++ b/firmware/src/boards/cynthion_d21/usb_switch.c @@ -0,0 +1,36 @@ +/** + * switch control for USB port shared by Apollo and FPGA + * + * This file is part of Apollo. + * + * Copyright (c) 2023 Great Scott Gadgets + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "usb_switch.h" +#include "apollo_board.h" +#include + + +/** + * Hand off shared USB port to FPGA. + */ +void hand_off_usb(void) +{ +#ifdef BOARD_HAS_USB_SWITCH + gpio_set_pin_level(USB_SWITCH, false); + gpio_set_pin_direction(USB_SWITCH, GPIO_DIRECTION_OUT); +#endif +} + + +/** + * Take control of USB port from FPGA. + */ +void take_over_usb(void) +{ +#ifdef BOARD_HAS_USB_SWITCH + gpio_set_pin_level(USB_SWITCH, true); + gpio_set_pin_direction(USB_SWITCH, GPIO_DIRECTION_OUT); +#endif +} diff --git a/firmware/src/boards/daisho/button.c b/firmware/src/boards/daisho/button.c new file mode 100644 index 0000000..ff2d7b8 --- /dev/null +++ b/firmware/src/boards/daisho/button.c @@ -0,0 +1,37 @@ +/** + * button handler + * + * Copyright (c) 2023 Great Scott Gadgets + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "button.h" +#include "usb_switch.h" +#include "fpga.h" +#include "apollo_board.h" +#include + + +/** + * Detect button press. + */ +bool button_pressed(void) +{ +#ifdef BOARD_HAS_PROGRAM_BUTTON + return (gpio_get_pin_level(PROGRAM_BUTTON) == false); +#else + return false; +#endif +} + + +/** + * Handle button events. + */ +void button_task(void) +{ + if (button_pressed()) { + force_fpga_offline(); + take_over_usb(); + } +} diff --git a/firmware/src/boards/daisho/usb_switch.c b/firmware/src/boards/daisho/usb_switch.c new file mode 100644 index 0000000..8b13ac7 --- /dev/null +++ b/firmware/src/boards/daisho/usb_switch.c @@ -0,0 +1,36 @@ +/** + * switch control for USB port shared by Apollo and FPGA + * + * This file is part of Apollo. + * + * Copyright (c) 2023 Great Scott Gadgets + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "usb_switch.h" +#include "apollo_board.h" +#include + + +/** + * Hand off shared USB port to FPGA. + */ +void hand_off_usb(void) +{ +#ifdef BOARD_HAS_USB_SWITCH + gpio_set_pin_level(USB_SWITCH, false); + gpio_set_pin_direction(USB_SWITCH, GPIO_DIRECTION_OUT); +#endif +} + + +/** + * Take control of USB port from FPGA. + */ +void take_over_usb(void) +{ +#ifdef BOARD_HAS_USB_SWITCH + gpio_set_pin_level(USB_SWITCH, true); + gpio_set_pin_direction(USB_SWITCH, GPIO_DIRECTION_OUT); +#endif +} diff --git a/firmware/src/boards/qtpy/button.c b/firmware/src/boards/qtpy/button.c new file mode 100644 index 0000000..ff2d7b8 --- /dev/null +++ b/firmware/src/boards/qtpy/button.c @@ -0,0 +1,37 @@ +/** + * button handler + * + * Copyright (c) 2023 Great Scott Gadgets + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "button.h" +#include "usb_switch.h" +#include "fpga.h" +#include "apollo_board.h" +#include + + +/** + * Detect button press. + */ +bool button_pressed(void) +{ +#ifdef BOARD_HAS_PROGRAM_BUTTON + return (gpio_get_pin_level(PROGRAM_BUTTON) == false); +#else + return false; +#endif +} + + +/** + * Handle button events. + */ +void button_task(void) +{ + if (button_pressed()) { + force_fpga_offline(); + take_over_usb(); + } +} diff --git a/firmware/src/boards/qtpy/usb_switch.c b/firmware/src/boards/qtpy/usb_switch.c new file mode 100644 index 0000000..8b13ac7 --- /dev/null +++ b/firmware/src/boards/qtpy/usb_switch.c @@ -0,0 +1,36 @@ +/** + * switch control for USB port shared by Apollo and FPGA + * + * This file is part of Apollo. + * + * Copyright (c) 2023 Great Scott Gadgets + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "usb_switch.h" +#include "apollo_board.h" +#include + + +/** + * Hand off shared USB port to FPGA. + */ +void hand_off_usb(void) +{ +#ifdef BOARD_HAS_USB_SWITCH + gpio_set_pin_level(USB_SWITCH, false); + gpio_set_pin_direction(USB_SWITCH, GPIO_DIRECTION_OUT); +#endif +} + + +/** + * Take control of USB port from FPGA. + */ +void take_over_usb(void) +{ +#ifdef BOARD_HAS_USB_SWITCH + gpio_set_pin_level(USB_SWITCH, true); + gpio_set_pin_direction(USB_SWITCH, GPIO_DIRECTION_OUT); +#endif +} diff --git a/firmware/src/boards/raspberry_pi_pico/apollo_board.h b/firmware/src/boards/raspberry_pi_pico/apollo_board.h new file mode 100644 index 0000000..3e05f06 --- /dev/null +++ b/firmware/src/boards/raspberry_pi_pico/apollo_board.h @@ -0,0 +1,109 @@ +/** + * Apollo board definitions for Adafruit QT Py RP2040 + * + * This file is part of LUNA. + * + * Copyright (c) 2020 Great Scott Gadgets + * Copyright (c) 2022 Markus Blechschmidt + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __APOLLO_BOARD_H__ +#define __APOLLO_BOARD_H__ + +#include + +#include "boards/pico.h" +#include "bsp/rp2040/board.h" +#include "pico/stdlib.h" +#include "hardware/gpio.h" +#include "hardware/sync.h" + + +#define __NOP() {asm volatile("nop");} + + +typedef unsigned int gpio_t; + + +typedef enum gpio_direction{ + GPIO_DIRECTION_IN = GPIO_IN, + GPIO_DIRECTION_OUT = GPIO_OUT, +} gpio_direction_t; + + +typedef enum gpio_pull_mode { + GPIO_PULL_OFF, + GPIO_PULL_UP, + GPIO_PULL_DOWN, +} gpio_pull_mode_t; + + +/** + * GPIO pins for each of the microcontroller LEDs. + */ +typedef enum { + LED_A = LED_PIN, // Green + + LED_COUNT = 1, +} led_t; + +/** + * GPIO pin numbers. + */ + + + +enum { + // // Each of the JTAG pins. SPI0 + TMS_GPIO = 5, + TDI_GPIO = 3, // MOSI + TDO_GPIO = 4, // MISO + TCK_GPIO = 6, // SCK + + // // Connected to orangecrab pins 0 and 1. SERCOM0 + UART_RX = UART_RX_PIN, + UART_TX = UART_TX_PIN, +}; + + +static inline void gpio_set_pin_level(const gpio_t gpio_pin, bool level) { + gpio_put(gpio_pin, level); +} + + +static inline bool gpio_get_pin_level(const gpio_t gpio_pin) { + return gpio_get(gpio_pin); +} + + +static inline void gpio_toggle_pin_level(const gpio_t gpio_pin) { + gpio_set_pin_level(gpio_pin, !gpio_get_pin_level(gpio_pin)); +} + + +static inline void gpio_set_pin_direction(const gpio_t gpio_pin, const enum gpio_direction direction) { + gpio_init(gpio_pin); + gpio_set_dir(gpio_pin, direction); +} + + +static inline void gpio_set_pin_pull_mode(const gpio_t gpio_pin, const gpio_pull_mode_t pull_mode) { + switch(pull_mode) { + case GPIO_PULL_OFF: { + gpio_disable_pulls(gpio_pin); + } break; + case GPIO_PULL_UP: { + gpio_pull_up(gpio_pin); + } break; + case GPIO_PULL_DOWN: { + gpio_pull_down(gpio_pin); + } break; + default: { + + } break; + } +} + + +#endif diff --git a/firmware/src/boards/raspberry_pi_pico/board.mk b/firmware/src/boards/raspberry_pi_pico/board.mk new file mode 100644 index 0000000..7f6a213 --- /dev/null +++ b/firmware/src/boards/raspberry_pi_pico/board.mk @@ -0,0 +1,11 @@ + +# This is an external board, so its identity is determined by its revision number. +# MAJOR = external board +# MINOR = generic Apollo board +BOARD_REVISION_MAJOR := 255 +BOARD_REVISION_MINOR := 3 + +CMAKE_DEFSYM += \ + -DBOARD_REVISION_MAJOR=$(BOARD_REVISION_MAJOR) \ + -DBOARD_REVISION_MINOR=$(BOARD_REVISION_MINOR) \ + -DPICO_SDK_PATH=../lib/pico-sdk diff --git a/firmware/src/boards/raspberry_pi_pico/button.c b/firmware/src/boards/raspberry_pi_pico/button.c new file mode 100644 index 0000000..c4fdf90 --- /dev/null +++ b/firmware/src/boards/raspberry_pi_pico/button.c @@ -0,0 +1,36 @@ +/** + * button handler + * + * Copyright (c) 2023 Great Scott Gadgets + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "button.h" +#include "usb_switch.h" +#include "fpga.h" +#include "apollo_board.h" + + +/** + * Detect button press. + */ +bool button_pressed(void) +{ +#ifdef BOARD_HAS_PROGRAM_BUTTON + return (gpio_get_pin_level(PROGRAM_BUTTON) == false); +#else + return false; +#endif +} + + +/** + * Handle button events. + */ +void button_task(void) +{ + if (button_pressed()) { + force_fpga_offline(); + take_over_usb(); + } +} diff --git a/firmware/src/boards/raspberry_pi_pico/debug_spi.c b/firmware/src/boards/raspberry_pi_pico/debug_spi.c new file mode 100644 index 0000000..0c85a10 --- /dev/null +++ b/firmware/src/boards/raspberry_pi_pico/debug_spi.c @@ -0,0 +1,36 @@ +/** + * Interface code for communicating with the FPGA over the Debug SPI connection. + * + * This file is part of LUNA. + * + * Copyright (c) 2020 Great Scott Gadgets + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include + +extern uint8_t spi_in_buffer[256 + 4]; +extern uint8_t spi_out_buffer[256 + 4]; + + +// Imported internal functions from main debug_spi.c: +void debug_spi_send(uint8_t *tx_buffer, uint8_t *rx_buffer, size_t length); + + +/** + * Request that sends a block of data over our debug SPI. + */ +bool handle_flash_spi_send(uint8_t rhport, tusb_control_request_t const* request) +{ + return false; +} + + +bool handle_flash_spi_send_complete(uint8_t rhport, tusb_control_request_t const* request) +{ + return false; +} diff --git a/firmware/src/boards/raspberry_pi_pico/dfu.c b/firmware/src/boards/raspberry_pi_pico/dfu.c new file mode 100644 index 0000000..438654a --- /dev/null +++ b/firmware/src/boards/raspberry_pi_pico/dfu.c @@ -0,0 +1,22 @@ +/** + * DFU Runtime Support + * + * This file provides support for automatically rebooting into the DFU bootloader. + * + * This file is part of LUNA. + * + * Copyright (c) 2020 Great Scott Gadgets + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "pico/bootrom.h" +#include "tusb.h" + +/** + * Handler for DFU_DETACH events, which should cause us to reboot into the bootloader. + */ +void tud_dfu_runtime_reboot_to_dfu_cb(void) +{ + reset_usb_boot(0, 0); + while(1); +} diff --git a/firmware/src/boards/raspberry_pi_pico/fpga.c b/firmware/src/boards/raspberry_pi_pico/fpga.c new file mode 100644 index 0000000..8a556f5 --- /dev/null +++ b/firmware/src/boards/raspberry_pi_pico/fpga.c @@ -0,0 +1,44 @@ +/** + * Code for basic FPGA interfacing. + * + * This file is part of LUNA. + * + * Copyright (c) 2020 Great Scott Gadgets + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + + +/* + * Allows or disallows the FPGA from configuring. When disallowed, + * initialization (erasing of configuration memory) takes place, but the FPGA + * does not proceed to the configuration phase. + */ +void permit_fpga_configuration(bool enable) +{ +} + +/** + * Sets up the I/O pins needed to configure the FPGA. + */ +void fpga_io_init(void) +{ +} + + +/** + * Requests that the FPGA clear its configuration and try to reconfigure. + */ +void trigger_fpga_reconfiguration(void) +{ +} + + +/** + * Requests that we hold the FPGA in an unconfigured state. + */ +void force_fpga_offline(void) +{ +} diff --git a/firmware/src/boards/raspberry_pi_pico/jtag.c b/firmware/src/boards/raspberry_pi_pico/jtag.c new file mode 100644 index 0000000..48c7d88 --- /dev/null +++ b/firmware/src/boards/raspberry_pi_pico/jtag.c @@ -0,0 +1,34 @@ +/** + * This file is part of LUNA. + * + * Copyright (c) 2020 Great Scott Gadgets + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#include +#include +#include "spi.h" + +#include + +extern uint8_t jtag_in_buffer[256]; +extern uint8_t jtag_out_buffer[256]; + + +/** + * Hook that performs hardware-specific initialization. + */ +void jtag_platform_init(void) +{ + // Set up our SPI port for SPI-accelerated JTAG. + spi_initialize(SPI_FPGA_JTAG, true, false, 1, 1, 1); +} + + +/** + * Hook that performs hardware-specific deinitialization. + */ +void jtag_platform_deinit(void) +{ +} diff --git a/firmware/src/boards/raspberry_pi_pico/led.c b/firmware/src/boards/raspberry_pi_pico/led.c new file mode 100644 index 0000000..94afd33 --- /dev/null +++ b/firmware/src/boards/raspberry_pi_pico/led.c @@ -0,0 +1,127 @@ +/* + * LED control abstraciton code. + * + * This file is part of LUNA. + * + * Copyright (c) 2020 Great Scott Gadgets + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#include +#include +#include + +#include +#include + + +#include "led.h" + + +/** Store the current LED blink pattern. */ +static blink_pattern_t blink_pattern = BLINK_IDLE; + + +/** + * Sets the active LED blink pattern. + */ +void led_set_blink_pattern(blink_pattern_t pattern) +{ + blink_pattern = pattern; + leds_off(); +} + + +/** + * Sets up each of the LEDs for use. + */ +void led_init(void) +{ + uint8_t pins[] = { LED_A, }; + + // Default each LED to an output and _off_. + for (unsigned i = 0; i < LED_COUNT; ++i) { + gpio_set_pin_direction(pins[i], GPIO_DIRECTION_OUT); + gpio_set_pin_level(pins[i], true); + } +} + + +/** + * Turns the provided LED on. + */ +void led_on(led_t led) +{ + gpio_set_pin_level(led, false); +} + + +/** + * Turns the provided LED off. + */ +void led_off(led_t led) +{ + gpio_set_pin_level(led, true); +} + + +/** + * Toggles the provided LED. + */ +void led_toggle(led_t led) +{ + gpio_toggle_pin_level(led); +} + + +/** + * Sets whether a given led is on. + */ +void led_set(led_t led, bool on) +{ + gpio_set_pin_level(led, !on); +} + + +/** + * Turns off all of the device's LEDs. + */ +void leds_off(void) +{ + led_t leds[] = {LED_A}; + + for (unsigned i = 0; i < LED_COUNT; ++i) { + led_off(leds[i]); + } +} + + +/** + * Turns on the given LED. + */ +static void display_led_number(uint8_t number) +{ + led_t leds[] = {LED_A}; + + if (number < LED_COUNT) { + led_on(leds[number]); + } +} + + +/** + * Task that handles blinking the heartbeat LED. + */ +void heartbeat_task(void) +{ + static uint32_t start_ms = 0; + + // Blink every interval ms + if ( board_millis() - start_ms < blink_pattern) { + return; // not enough time + } + + start_ms += blink_pattern; + led_toggle(LED_A); +} diff --git a/firmware/src/boards/raspberry_pi_pico/platform_jtag.h b/firmware/src/boards/raspberry_pi_pico/platform_jtag.h new file mode 100644 index 0000000..1c12f85 --- /dev/null +++ b/firmware/src/boards/raspberry_pi_pico/platform_jtag.h @@ -0,0 +1,44 @@ +/** + * Platform-specific JTAG I/O helpers. + * Using these rather than the raw GPIO functions allows read optimizations. + * + * Copyright (c) 2020 Great Scott Gadgets + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#ifndef __PLATFORM_JTAG_H__ +#define __PLATFORM_JTAG_H__ + +#include + +static inline void jtag_set_tms(void) +{ + gpio_set_pin_level(TMS_GPIO, true); +} + + +static inline void jtag_clear_tms(void) +{ + gpio_set_pin_level(TMS_GPIO, false); +} + + +static inline void jtag_set_tdi(void) +{ + gpio_set_pin_level(TDI_GPIO, true); +} + + +static inline void jtag_clear_tdi(void) +{ + gpio_set_pin_level(TDI_GPIO, false); +} + + +static inline bool jtag_read_tdo(void) +{ + return gpio_get_pin_level(TDO_GPIO); +} + +#endif diff --git a/firmware/src/boards/raspberry_pi_pico/spi.c b/firmware/src/boards/raspberry_pi_pico/spi.c new file mode 100644 index 0000000..47c8b56 --- /dev/null +++ b/firmware/src/boards/raspberry_pi_pico/spi.c @@ -0,0 +1,171 @@ +/* + * SPI driver code. + * + * This file is part of LUNA. + * + * Copyright (c) 2020 Great Scott Gadgets + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "hardware/spi.h" +#include "hardware/resets.h" +#include "hardware/clocks.h" + +#include "apollo_board.h" +#include "spi.h" +#include "led.h" + + +static const char reverse_char[0x100] = {0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, + 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, + 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, + 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, + 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, + 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, + 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, + 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, + 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, + 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, + 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, + 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, + 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, + 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF}; + +static volatile bool _lsb_first = false; + + +/** + * Returns the SPI object associated with the given target. + */ +static spi_inst_t *spi_inst_for_target(spi_target_t target) +{ + switch (target) { + case SPI_FPGA_JTAG: return spi0; + case SPI_FPGA_DEBUG: return NULL; + } + + return NULL; +} + + +/** + * Pinmux the relevent pins so the can be used for SPI. + */ +static void _spi_configure_pinmux(spi_target_t target, bool use_for_spi) +{ + switch (target) { + + // FPGA JTAG connection -- configure TDI, TCK, TDO + case SPI_FPGA_JTAG: + if (use_for_spi) { + gpio_set_function(TDI_GPIO, GPIO_FUNC_SPI); + gpio_set_function(TCK_GPIO, GPIO_FUNC_SPI); + gpio_set_function(TDO_GPIO, GPIO_FUNC_SPI); + } else { + gpio_set_function(TDI_GPIO, GPIO_FUNC_SIO); + gpio_set_function(TCK_GPIO, GPIO_FUNC_SIO); + gpio_set_function(TDO_GPIO, GPIO_FUNC_SIO); + } + break; + case SPI_FPGA_DEBUG: + // not implemented + break; + } +} + + +/** + * Configures the relevant SPI target's pins to be used for SPI. + */ +void spi_configure_pinmux(spi_target_t target) +{ + _spi_configure_pinmux(target, true); +} + + +/** + * Returns the relevant SPI target's pins to being used for GPIO. + */ +void spi_release_pinmux(spi_target_t target) +{ + _spi_configure_pinmux(target, false); +} + + +/** + * Configures the provided target to be used as an SPI port. + */ +void spi_initialize(spi_target_t target, bool lsb_first, bool configure_pinmux, uint8_t baud_divider, + uint8_t clock_polarity, uint8_t clock_phase) +{ + spi_inst_t *spi = spi_inst_for_target(target); + _lsb_first = lsb_first; + + // Disable the SPI before configuring it. + spi_deinit(spi); + + // Set up clocking for the SPI peripheral. + spi_init(spi, 8 * 1000 * 1000 / (2*(baud_divider+1))); + + // Configure the SPI for master mode. + spi_set_slave(spi, false); + + // Set SPI format + spi_set_format( spi, // SPI instance + 8, // Number of bits per transfer + clock_polarity, // Polarity (CPOL) + clock_phase, // Phase (CPHA) + SPI_MSB_FIRST); + + // Pinmux the relevant pins to be used for the SPI. + if (configure_pinmux) { + spi_configure_pinmux(target); + } +} + + +/** + * Synchronously send a single byte on the given SPI bus. + * Does not manage the SSEL line. + */ +uint8_t spi_send_byte(spi_target_t target, uint8_t data) +{ + uint8_t dst; + spi_inst_t *spi = spi_inst_for_target(target); + + if (_lsb_first) { + data = reverse_char[data]; + } + + spi_write_read_blocking(spi, &data, &dst, 1); + + if (_lsb_first) { + dst = reverse_char[dst]; + } + + return dst; +} + + +/** + * Sends a block of data over the SPI bus. + * + * @param port The port on which to perform the SPI transaction. + * @param data_to_send The data to be transferred over the SPI bus. + * @param data_received Any data received during the SPI transaction. + * @param length The total length of the data to be exchanged, in bytes. + */ +void spi_send(spi_target_t port, void *data_to_send, void *data_received, size_t length) +{ + uint8_t *to_send = data_to_send; + uint8_t *received = data_received; + + // TODO: use the FIFO to bulk send data + for (unsigned i = 0; i < length; ++i) { + received[i] = spi_send_byte(port, to_send[i]); + } +} diff --git a/firmware/src/boards/raspberry_pi_pico/spi.h b/firmware/src/boards/raspberry_pi_pico/spi.h new file mode 100644 index 0000000..f1a4972 --- /dev/null +++ b/firmware/src/boards/raspberry_pi_pico/spi.h @@ -0,0 +1,59 @@ +/* + * SPI driver code. + * + * This file is part of LUNA. + * + * Copyright (c) 2020 Great Scott Gadgets + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SPI_H__ +#define __SPI_H__ + +#include +#include +#include + +typedef enum { + SPI_FPGA_JTAG, + SPI_FPGA_DEBUG + } spi_target_t; + + +/** + * Configures the relevant SPI target's pins to be used for SPI. + */ +void spi_configure_pinmux(spi_target_t target); + + +/** + * Returns the relevant SPI target's pins to being used for GPIO. + */ +void spi_release_pinmux(spi_target_t target); + + +/** + * Configures the provided target to be used as an SPI port via the SERCOM. + */ +void spi_initialize(spi_target_t target, bool lsb_first, bool configure_pinmux, uint8_t baud_divider, + uint8_t clock_polarity, uint8_t clock_phase); + + +/** + * Synchronously send a single byte on the given SPI bus. + * Does not manage the SSEL line. + */ +uint8_t spi_send_byte(spi_target_t target, uint8_t data); + + +/** + * Sends a block of data over the SPI bus. + * + * @param target The port on which to perform the SPI transaction. + * @param data_to_send The data to be transferred over the SPI bus. + * @param data_received Any data received during the SPI transaction. + * @param length The total length of the data to be exchanged, in bytes. + */ +void spi_send(spi_target_t target, void *data_to_send, void *data_received, size_t length); + +#endif diff --git a/firmware/src/boards/raspberry_pi_pico/tusb_config.h b/firmware/src/boards/raspberry_pi_pico/tusb_config.h new file mode 100644 index 0000000..14c8ea9 --- /dev/null +++ b/firmware/src/boards/raspberry_pi_pico/tusb_config.h @@ -0,0 +1,119 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * 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. + * + */ + +#ifndef _TUSB_CONFIG_H_ +#define _TUSB_CONFIG_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//-------------------------------------------------------------------- +// COMMON CONFIGURATION +//-------------------------------------------------------------------- + +// defined by compiler flags for flexibility +#ifndef CFG_TUSB_MCU + #error CFG_TUSB_MCU must be defined +#endif + +// RHPort number used for device can be defined by board.mk, default to port 0 +#ifndef BOARD_DEVICE_RHPORT_NUM + #define BOARD_DEVICE_RHPORT_NUM 0 +#endif + +// RHPort max operational speed can defined by board.mk +// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed +#ifndef BOARD_DEVICE_RHPORT_SPEED + #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56) + #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED + #else + #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED + #endif +#endif + +// Device mode with rhport and speed defined by board.mk +#if BOARD_DEVICE_RHPORT_NUM == 0 + #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) +#elif BOARD_DEVICE_RHPORT_NUM == 1 + #define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) +#else + #error "Incorrect RHPort configuration" +#endif + +// This example doesn't use an RTOS +#ifndef CFG_TUSB_OS +#define CFG_TUSB_OS OPT_OS_NONE +#endif + +// CFG_TUSB_DEBUG is defined by compiler in DEBUG build +// #define CFG_TUSB_DEBUG 0 + +/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. + * Tinyusb use follows macros to declare transferring memory so that they can be put + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN +#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) +#endif + +//-------------------------------------------------------------------- +// DEVICE CONFIGURATION +//-------------------------------------------------------------------- + +#ifndef CFG_TUD_ENDPOINT0_SIZE +#define CFG_TUD_ENDPOINT0_SIZE 64 +#endif + + +//------------- CLASS -------------// +#define CFG_TUD_CDC 1 +#define CFG_TUD_DFU_RUNTIME 1 +#define CFG_TUD_VENDOR 1 + +// VENDOR FIFO size of TX and RX +#define CFG_TUD_VENDOR_RX_BUFSIZE 16 +#define CFG_TUD_VENDOR_TX_BUFSIZE 512 + + +// CDC FIFO size of TX and RX +#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) +#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) + + + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_CONFIG_H_ */ diff --git a/firmware/src/boards/raspberry_pi_pico/uart.c b/firmware/src/boards/raspberry_pi_pico/uart.c new file mode 100644 index 0000000..3d546d0 --- /dev/null +++ b/firmware/src/boards/raspberry_pi_pico/uart.c @@ -0,0 +1,147 @@ +/** + * UART driver code. + * + * This file is part of LUNA. + * + * Copyright (c) 2020 Great Scott Gadgets + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#include "hardware/uart.h" +#include "hardware/irq.h" + +#include "apollo_board.h" + + +// Create a quick reference to our uart object. +static uart_inst_t *uart_inst = PICO_DEFAULT_UART; + +// Keep track of whether our UART has been configured and is active. +bool uart_active = false; + +// Declare interrupt handler +static void on_uart_rx(); + + +/** + * Pinmux the relevent pins so the can be used for SERCOM UART. + */ +static void _uart_configure_pinmux(bool use_for_uart) +{ + if (use_for_uart) { + gpio_set_function(UART_TX, GPIO_FUNC_UART); + gpio_set_function(UART_RX, GPIO_FUNC_UART); + } else { + gpio_set_function(UART_TX, GPIO_FUNC_NULL); + gpio_set_function(UART_RX, GPIO_FUNC_NULL); + } +} + + +/** + * Configures the relevant UART's target's pins to be used for UART. + */ +void uart_configure_pinmux(void) +{ + _uart_configure_pinmux(true); + uart_active = true; +} + + +/** + * Releases the relevant pins from being used for UART, returning them + * to use as GPIO. + */ +void uart_release_pinmux(void) +{ + _uart_configure_pinmux(false); + uart_active = false; +} + + +/** + * Configures the UART we'll use for our system console. + * TODO: support more configuration (parity, stop, etc.) + */ +void uart_initialize(bool configure_pinmux, unsigned long baudrate) +{ + uart_deinit(uart_inst); + + if (configure_pinmux) { + uart_configure_pinmux(); + } + + uart_init(uart_inst, baudrate); + + while(!uart_is_enabled(uart_inst)); + + // Turn off FIFO's - we want to do this character by character + uart_set_fifo_enabled(uart_inst, false); + + // Set up a RX interrupt + // We need to set up the handler first + // Select correct interrupt for the UART we are using + int UART_IRQ = (uart_inst == uart0) ? UART0_IRQ : UART1_IRQ; + + // And set up and enable the interrupt handlers + irq_set_exclusive_handler(UART_IRQ, on_uart_rx); + irq_set_enabled(UART_IRQ, true); + + // Now enable the UART to send interrupts - RX only + uart_set_irq_enables(uart_inst, true, false); +} + + +/** + * Callback issued when the UART recieves a new byte. + */ +__attribute__((weak)) void uart_byte_received_cb(uint8_t byte) { + (void) byte; // unused +} + + +/** + * UART interrupt handler. + */ +void on_uart_rx() { + while (uart_is_readable(uart_inst)) { + uint8_t ch = uart_getc(uart_inst); + uart_byte_received_cb(ch); + } +} + + +/** + * @return True iff the UART can accept data. + */ +bool uart_ready_for_write(void) +{ + return uart_is_writable(uart_inst); +} + + +/** + * Starts a write over the Apollo console UART. + + * Does not check for readiness; it is assumed the caller knows that the + * UART is avaiable (e.g. by calling uart_ready_for_write). + */ +void uart_nonblocking_write(uint8_t byte) +{ + if(uart_ready_for_write()) { + uart_putc_raw(uart_inst, byte); + } +} + + +/** + * Writes a byte over the Apollo console UART. + * + * @param byte The byte to be written. + */ +void uart_blocking_write(uint8_t byte) +{ + while(!uart_ready_for_write()) {} + uart_putc_raw(uart_inst, byte); +} diff --git a/firmware/src/boards/raspberry_pi_pico/usb_descriptors.c b/firmware/src/boards/raspberry_pi_pico/usb_descriptors.c new file mode 100644 index 0000000..d04fb19 --- /dev/null +++ b/firmware/src/boards/raspberry_pi_pico/usb_descriptors.c @@ -0,0 +1,231 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * 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 "tusb.h" + +#include "pico.h" +#include "pico/unique_id.h" + +#define SERIAL_NUMBER_STRING_INDEX 3 + +/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. + * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. + * + * Auto ProductID layout's Bitmap: + * [MSB] MIDI | HID | MSC | CDC [LSB] + */ +#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) +#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ + _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) + +//--------------------------------------------------------------------+ +// Device Descriptors +//--------------------------------------------------------------------+ +tusb_desc_device_t const desc_device = +{ + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + + // Use Interface Association Descriptor (IAD) for CDC + // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + + // These are a unique VID/PID for development LUNA boards. + .idVendor = 0x1d50, + .idProduct = 0x615c, + .bcdDevice = (_BOARD_REVISION_MAJOR_ << 8) | _BOARD_REVISION_MINOR_, + + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = SERIAL_NUMBER_STRING_INDEX, + + .bNumConfigurations = 0x01 +}; + +// Invoked when received GET DEVICE DESCRIPTOR +// Application return pointer to descriptor +uint8_t const * tud_descriptor_device_cb(void) +{ + return (uint8_t const *) &desc_device; +} + +//--------------------------------------------------------------------+ +// Configuration Descriptor +//--------------------------------------------------------------------+ + +enum +{ + ITF_NUM_CDC = 0, + ITF_NUM_CDC_DATA, + ITF_NUM_DFU_RT, + ITF_NUM_TOTAL +}; + +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_DFU_RT_DESC_LEN) + +#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX + // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number + // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... + #define EPNUM_CDC_NOTIF 0x81 + #define EPNUM_CDC_DATA 0x02 +#else + #define EPNUM_CDC_NOTIF 0x81 + #define EPNUM_CDC_DATA 0x02 +#endif + +uint8_t const desc_fs_configuration[] = +{ + // Interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + + // Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_DATA, 0x80 | EPNUM_CDC_DATA, 64), + + // Interface descriptor for the DFU runtime interface. + TUD_DFU_RT_DESCRIPTOR(ITF_NUM_DFU_RT, 5, 0x0d, 500, 4096), +}; + +#if TUD_OPT_HIGH_SPEED +uint8_t const desc_hs_configuration[] = +{ + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + + // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 5, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_DATA, 0x80 | EPNUM_CDC_DATA, 512), + + // Interface number, string index, attributes, detach timeout, transfer size */ + TUD_DFU_RT_DESCRIPTOR(ITF_NUM_DFU_RT, 4, 0x0d, 1000, 4096), +}; +#endif + +// Invoked when received GET CONFIGURATION DESCRIPTOR +// Application return pointer to descriptor +// Descriptor contents must exist long enough for transfer to complete +uint8_t const * tud_descriptor_configuration_cb(uint8_t index) +{ + (void) index; // for multiple configurations +#if TUD_OPT_HIGH_SPEED + // Although we are highspeed, host may be fullspeed. + return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration; +#else + return desc_fs_configuration; +#endif +} + +//--------------------------------------------------------------------+ +// String Descriptors +//--------------------------------------------------------------------+ + + +// array of pointer to string descriptors +char const* string_desc_arr [] = +{ + (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) + "Great Scott Gadgets", // 1: Manufacturer + "LUNA Debug Controller", // 2: Product + NULL, // 3: Serials, should use chip ID + "UART Bridge", // 4: CDC Interface + "DFU Runtime" // 5: DFU Interface +}; + +static uint16_t _desc_str[34]; + + +/** + * Returns a USB string descriptor that describes this device's unique ID. + */ +static uint16_t *get_serial_number_string_descriptor(void) +{ + static pico_unique_board_id_t uID; + static bool got_unique_board_id = false; + + const unsigned serial_number_chars = PICO_UNIQUE_BOARD_ID_SIZE_BYTES*2; + + int count = 0; + + if (!got_unique_board_id) { + pico_get_unique_board_id(&uID); + got_unique_board_id = true; + } + + // Populate the length and string type, as these are the first two bytes + // of our descriptor... + _desc_str[count++] = (TUSB_DESC_STRING << 8 ) | ((serial_number_chars * 2) + 2);; + + // ... and convert our serial number into hex. + for (unsigned i = 0; i < serial_number_chars; ++i) { + uint8_t hexit = (uID.id[i / 2] >> (4 * (1 - (i % 2)))); + _desc_str[count++] = "0123456789abcdef"[hexit & 0xF]; + } + + return _desc_str; +} + +// Invoked when received GET STRING DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) +{ + uint8_t chr_count; + + // If we're looking for the "supported languages" descriptor, return it directly. + if (index == 0) { + memcpy(&_desc_str[1], string_desc_arr[0], 2); + chr_count = 1; + } + // If this is a request for the serial number, return the device's unique ID> + else if (index == SERIAL_NUMBER_STRING_INDEX) { + return get_serial_number_string_descriptor(); + } + + // Otherwise, take the ASCII string provided and encode it as UTF-16. + else { + + if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) { + return NULL; + } + + const char* str = string_desc_arr[index]; + + // Cap at max char + chr_count = strlen(str); + if ( chr_count > 31 ) chr_count = 31; + + for(uint8_t i=0; i + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "usb_switch.h" +#include "apollo_board.h" + + +/** + * Hand off shared USB port to FPGA. + */ +void hand_off_usb(void) +{ +#ifdef BOARD_HAS_USB_SWITCH + gpio_set_pin_level(USB_SWITCH, false); + gpio_set_pin_direction(USB_SWITCH, GPIO_DIRECTION_OUT); +#endif +} + + +/** + * Take control of USB port from FPGA. + */ +void take_over_usb(void) +{ +#ifdef BOARD_HAS_USB_SWITCH + gpio_set_pin_level(USB_SWITCH, true); + gpio_set_pin_direction(USB_SWITCH, GPIO_DIRECTION_OUT); +#endif +} diff --git a/firmware/src/boards/samd11_xplained/button.c b/firmware/src/boards/samd11_xplained/button.c new file mode 100644 index 0000000..ff2d7b8 --- /dev/null +++ b/firmware/src/boards/samd11_xplained/button.c @@ -0,0 +1,37 @@ +/** + * button handler + * + * Copyright (c) 2023 Great Scott Gadgets + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "button.h" +#include "usb_switch.h" +#include "fpga.h" +#include "apollo_board.h" +#include + + +/** + * Detect button press. + */ +bool button_pressed(void) +{ +#ifdef BOARD_HAS_PROGRAM_BUTTON + return (gpio_get_pin_level(PROGRAM_BUTTON) == false); +#else + return false; +#endif +} + + +/** + * Handle button events. + */ +void button_task(void) +{ + if (button_pressed()) { + force_fpga_offline(); + take_over_usb(); + } +} diff --git a/firmware/src/boards/samd11_xplained/usb_switch.c b/firmware/src/boards/samd11_xplained/usb_switch.c new file mode 100644 index 0000000..8b13ac7 --- /dev/null +++ b/firmware/src/boards/samd11_xplained/usb_switch.c @@ -0,0 +1,36 @@ +/** + * switch control for USB port shared by Apollo and FPGA + * + * This file is part of Apollo. + * + * Copyright (c) 2023 Great Scott Gadgets + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "usb_switch.h" +#include "apollo_board.h" +#include + + +/** + * Hand off shared USB port to FPGA. + */ +void hand_off_usb(void) +{ +#ifdef BOARD_HAS_USB_SWITCH + gpio_set_pin_level(USB_SWITCH, false); + gpio_set_pin_direction(USB_SWITCH, GPIO_DIRECTION_OUT); +#endif +} + + +/** + * Take control of USB port from FPGA. + */ +void take_over_usb(void) +{ +#ifdef BOARD_HAS_USB_SWITCH + gpio_set_pin_level(USB_SWITCH, true); + gpio_set_pin_direction(USB_SWITCH, GPIO_DIRECTION_OUT); +#endif +} From 6dc635e7cbfa5fb750197bee676304a69c91b13c Mon Sep 17 00:00:00 2001 From: marble Date: Sat, 2 Mar 2024 22:52:46 +0100 Subject: [PATCH 04/14] ci: add raspberry_pi_pico target board --- .github/workflows/firmware.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/firmware.yml b/.github/workflows/firmware.yml index 19fb2af..c0b78bc 100644 --- a/.github/workflows/firmware.yml +++ b/.github/workflows/firmware.yml @@ -20,6 +20,7 @@ jobs: - target-board: 'cynthion r0.4' board-major: 0 board-minor: 4 + - 'raspberry_pi_pico' steps: - name: Install ARM GCC uses: carlosperate/arm-none-eabi-gcc-action@v1 From 2baf437f469b77f2de19ccd91663f5ab347551e7 Mon Sep 17 00:00:00 2001 From: marble Date: Mon, 6 May 2024 23:41:06 +0200 Subject: [PATCH 05/14] incorporate suggestions from @mndza --- .gitmodules | 3 - firmware/CMakeLists.txt | 4 +- firmware/src/boards/cynthion_d11/button.c | 56 ------------ firmware/src/boards/cynthion_d11/usb_switch.c | 88 ------------------- firmware/src/boards/cynthion_d21/button.c | 37 -------- firmware/src/boards/cynthion_d21/usb_switch.c | 36 -------- firmware/src/boards/daisho/button.c | 37 -------- firmware/src/boards/daisho/usb_switch.c | 36 -------- firmware/src/boards/qtpy/button.c | 37 -------- firmware/src/boards/qtpy/usb_switch.c | 36 -------- .../src/boards/raspberry_pi_pico/board.mk | 9 +- firmware/src/boards/samd11_xplained/button.c | 37 -------- .../src/boards/samd11_xplained/usb_switch.c | 36 -------- .../{boards/raspberry_pi_pico => }/button.c | 0 .../raspberry_pi_pico => }/usb_switch.c | 0 lib/pico-sdk | 1 - 16 files changed, 9 insertions(+), 444 deletions(-) delete mode 100644 firmware/src/boards/cynthion_d11/button.c delete mode 100644 firmware/src/boards/cynthion_d11/usb_switch.c delete mode 100644 firmware/src/boards/cynthion_d21/button.c delete mode 100644 firmware/src/boards/cynthion_d21/usb_switch.c delete mode 100644 firmware/src/boards/daisho/button.c delete mode 100644 firmware/src/boards/daisho/usb_switch.c delete mode 100644 firmware/src/boards/qtpy/button.c delete mode 100644 firmware/src/boards/qtpy/usb_switch.c delete mode 100644 firmware/src/boards/samd11_xplained/button.c delete mode 100644 firmware/src/boards/samd11_xplained/usb_switch.c rename firmware/src/{boards/raspberry_pi_pico => }/button.c (100%) rename firmware/src/{boards/raspberry_pi_pico => }/usb_switch.c (100%) delete mode 160000 lib/pico-sdk diff --git a/.gitmodules b/.gitmodules index 60fe12a..f2e3e70 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ [submodule "lib/tinyusb"] path = lib/tinyusb url = https://github.com/hathach/tinyusb -[submodule "lib/pico-sdk"] - path = lib/pico-sdk - url = https://github.com/raspberrypi/pico-sdk.git diff --git a/firmware/CMakeLists.txt b/firmware/CMakeLists.txt index b0687a8..02d8b71 100644 --- a/firmware/CMakeLists.txt +++ b/firmware/CMakeLists.txt @@ -22,13 +22,14 @@ add_executable(${PROJECT}) # Example source target_sources(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src/button.c ${CMAKE_CURRENT_SOURCE_DIR}/src/console.c ${CMAKE_CURRENT_SOURCE_DIR}/src/debug_spi.c ${CMAKE_CURRENT_SOURCE_DIR}/src/jtag.c ${CMAKE_CURRENT_SOURCE_DIR}/src/jtag_tap.c ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_switch.c ${CMAKE_CURRENT_SOURCE_DIR}/src/vendor.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/button.c ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/dfu.c ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/jtag.c ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/fpga.c @@ -37,7 +38,6 @@ target_sources(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/led.c ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/uart.c ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/usb_descriptors.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/usb_switch.c ) # Example include diff --git a/firmware/src/boards/cynthion_d11/button.c b/firmware/src/boards/cynthion_d11/button.c deleted file mode 100644 index 9496383..0000000 --- a/firmware/src/boards/cynthion_d11/button.c +++ /dev/null @@ -1,56 +0,0 @@ -/** - * button handler - * - * Copyright (c) 2023-2024 Great Scott Gadgets - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include "button.h" -#include "usb_switch.h" -#include "fpga.h" -#include "apollo_board.h" -#include - -static inline void delay(int cycles) -{ - while (cycles-- != 0) - __NOP(); -} - - -/** - * Detect button press. - */ -bool button_pressed(void) -{ -#ifdef BOARD_HAS_PROGRAM_BUTTON - -#ifdef BOARD_HAS_SHARED_BUTTON - bool level = gpio_get_pin_level(PROGRAM_BUTTON); - gpio_set_pin_direction(PROGRAM_BUTTON, GPIO_DIRECTION_IN); - gpio_set_pin_pull_mode(PROGRAM_BUTTON, GPIO_PULL_UP); - delay(50); - bool pressed = (gpio_get_pin_level(PROGRAM_BUTTON) == false); - gpio_set_pin_direction(PROGRAM_BUTTON, GPIO_DIRECTION_OUT); - gpio_set_pin_level(PROGRAM_BUTTON, level); - return pressed; -#else - return (gpio_get_pin_level(PROGRAM_BUTTON) == false); -#endif - -#else - return false; -#endif -} - - -/** - * Handle button events. - */ -void button_task(void) -{ - if (button_pressed()) { - force_fpga_offline(); - take_over_usb(); - } -} diff --git a/firmware/src/boards/cynthion_d11/usb_switch.c b/firmware/src/boards/cynthion_d11/usb_switch.c deleted file mode 100644 index 5df4242..0000000 --- a/firmware/src/boards/cynthion_d11/usb_switch.c +++ /dev/null @@ -1,88 +0,0 @@ -/** - * switch control for USB port shared by Apollo and FPGA - * - * This file is part of Apollo. - * - * Copyright (c) 2023-2024 Great Scott Gadgets - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include "usb_switch.h" -#include "apollo_board.h" -#include - -#include -#include - -enum { - SWITCH_UNKNOWN = 0, - SWITCH_MCU = 1, - SWITCH_FPGA = 2, -}; - -#ifdef BOARD_HAS_SHARED_USB -static int switch_state = SWITCH_UNKNOWN; -#endif - -/** - * Hand off shared USB port to FPGA. - */ -void hand_off_usb(void) -{ -#ifdef BOARD_HAS_SHARED_USB - if (switch_state == SWITCH_FPGA) return; - - // Disable internal pull-up resistor on D+/D- pins for a moment to force a disconnection - tud_disconnect(); - board_delay(100); - -#ifdef BOARD_HAS_USB_SWITCH - gpio_set_pin_level(USB_SWITCH, false); - gpio_set_pin_direction(USB_SWITCH, GPIO_DIRECTION_OUT); -#else - gpio_set_pin_pull_mode(PHY_RESET, GPIO_PULL_DOWN); - gpio_set_pin_direction(PHY_RESET, GPIO_DIRECTION_IN); -#endif - - switch_state = SWITCH_FPGA; -#endif -} - - -/** - * Take control of USB port from FPGA. - */ -void take_over_usb(void) -{ -#ifdef BOARD_HAS_SHARED_USB - if (switch_state == SWITCH_MCU) return; - -#ifdef BOARD_HAS_USB_SWITCH - gpio_set_pin_level(USB_SWITCH, true); - gpio_set_pin_direction(USB_SWITCH, GPIO_DIRECTION_OUT); -#else - gpio_set_pin_level(PHY_RESET, false); - gpio_set_pin_direction(PHY_RESET, GPIO_DIRECTION_OUT); -#endif - - // Disable internal pull-up resistor on D+/D- pins for a moment to force a disconnection - tud_disconnect(); - board_delay(100); - tud_connect(); - - switch_state = SWITCH_MCU; -#endif -} - - -/** - * True if the USB switch handed over the port to the FPGA. - */ -bool fpga_controls_usb_port(void) -{ -#ifdef BOARD_HAS_SHARED_USB - return switch_state == SWITCH_FPGA; -#else - return false; -#endif -} diff --git a/firmware/src/boards/cynthion_d21/button.c b/firmware/src/boards/cynthion_d21/button.c deleted file mode 100644 index ff2d7b8..0000000 --- a/firmware/src/boards/cynthion_d21/button.c +++ /dev/null @@ -1,37 +0,0 @@ -/** - * button handler - * - * Copyright (c) 2023 Great Scott Gadgets - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include "button.h" -#include "usb_switch.h" -#include "fpga.h" -#include "apollo_board.h" -#include - - -/** - * Detect button press. - */ -bool button_pressed(void) -{ -#ifdef BOARD_HAS_PROGRAM_BUTTON - return (gpio_get_pin_level(PROGRAM_BUTTON) == false); -#else - return false; -#endif -} - - -/** - * Handle button events. - */ -void button_task(void) -{ - if (button_pressed()) { - force_fpga_offline(); - take_over_usb(); - } -} diff --git a/firmware/src/boards/cynthion_d21/usb_switch.c b/firmware/src/boards/cynthion_d21/usb_switch.c deleted file mode 100644 index 8b13ac7..0000000 --- a/firmware/src/boards/cynthion_d21/usb_switch.c +++ /dev/null @@ -1,36 +0,0 @@ -/** - * switch control for USB port shared by Apollo and FPGA - * - * This file is part of Apollo. - * - * Copyright (c) 2023 Great Scott Gadgets - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include "usb_switch.h" -#include "apollo_board.h" -#include - - -/** - * Hand off shared USB port to FPGA. - */ -void hand_off_usb(void) -{ -#ifdef BOARD_HAS_USB_SWITCH - gpio_set_pin_level(USB_SWITCH, false); - gpio_set_pin_direction(USB_SWITCH, GPIO_DIRECTION_OUT); -#endif -} - - -/** - * Take control of USB port from FPGA. - */ -void take_over_usb(void) -{ -#ifdef BOARD_HAS_USB_SWITCH - gpio_set_pin_level(USB_SWITCH, true); - gpio_set_pin_direction(USB_SWITCH, GPIO_DIRECTION_OUT); -#endif -} diff --git a/firmware/src/boards/daisho/button.c b/firmware/src/boards/daisho/button.c deleted file mode 100644 index ff2d7b8..0000000 --- a/firmware/src/boards/daisho/button.c +++ /dev/null @@ -1,37 +0,0 @@ -/** - * button handler - * - * Copyright (c) 2023 Great Scott Gadgets - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include "button.h" -#include "usb_switch.h" -#include "fpga.h" -#include "apollo_board.h" -#include - - -/** - * Detect button press. - */ -bool button_pressed(void) -{ -#ifdef BOARD_HAS_PROGRAM_BUTTON - return (gpio_get_pin_level(PROGRAM_BUTTON) == false); -#else - return false; -#endif -} - - -/** - * Handle button events. - */ -void button_task(void) -{ - if (button_pressed()) { - force_fpga_offline(); - take_over_usb(); - } -} diff --git a/firmware/src/boards/daisho/usb_switch.c b/firmware/src/boards/daisho/usb_switch.c deleted file mode 100644 index 8b13ac7..0000000 --- a/firmware/src/boards/daisho/usb_switch.c +++ /dev/null @@ -1,36 +0,0 @@ -/** - * switch control for USB port shared by Apollo and FPGA - * - * This file is part of Apollo. - * - * Copyright (c) 2023 Great Scott Gadgets - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include "usb_switch.h" -#include "apollo_board.h" -#include - - -/** - * Hand off shared USB port to FPGA. - */ -void hand_off_usb(void) -{ -#ifdef BOARD_HAS_USB_SWITCH - gpio_set_pin_level(USB_SWITCH, false); - gpio_set_pin_direction(USB_SWITCH, GPIO_DIRECTION_OUT); -#endif -} - - -/** - * Take control of USB port from FPGA. - */ -void take_over_usb(void) -{ -#ifdef BOARD_HAS_USB_SWITCH - gpio_set_pin_level(USB_SWITCH, true); - gpio_set_pin_direction(USB_SWITCH, GPIO_DIRECTION_OUT); -#endif -} diff --git a/firmware/src/boards/qtpy/button.c b/firmware/src/boards/qtpy/button.c deleted file mode 100644 index ff2d7b8..0000000 --- a/firmware/src/boards/qtpy/button.c +++ /dev/null @@ -1,37 +0,0 @@ -/** - * button handler - * - * Copyright (c) 2023 Great Scott Gadgets - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include "button.h" -#include "usb_switch.h" -#include "fpga.h" -#include "apollo_board.h" -#include - - -/** - * Detect button press. - */ -bool button_pressed(void) -{ -#ifdef BOARD_HAS_PROGRAM_BUTTON - return (gpio_get_pin_level(PROGRAM_BUTTON) == false); -#else - return false; -#endif -} - - -/** - * Handle button events. - */ -void button_task(void) -{ - if (button_pressed()) { - force_fpga_offline(); - take_over_usb(); - } -} diff --git a/firmware/src/boards/qtpy/usb_switch.c b/firmware/src/boards/qtpy/usb_switch.c deleted file mode 100644 index 8b13ac7..0000000 --- a/firmware/src/boards/qtpy/usb_switch.c +++ /dev/null @@ -1,36 +0,0 @@ -/** - * switch control for USB port shared by Apollo and FPGA - * - * This file is part of Apollo. - * - * Copyright (c) 2023 Great Scott Gadgets - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include "usb_switch.h" -#include "apollo_board.h" -#include - - -/** - * Hand off shared USB port to FPGA. - */ -void hand_off_usb(void) -{ -#ifdef BOARD_HAS_USB_SWITCH - gpio_set_pin_level(USB_SWITCH, false); - gpio_set_pin_direction(USB_SWITCH, GPIO_DIRECTION_OUT); -#endif -} - - -/** - * Take control of USB port from FPGA. - */ -void take_over_usb(void) -{ -#ifdef BOARD_HAS_USB_SWITCH - gpio_set_pin_level(USB_SWITCH, true); - gpio_set_pin_direction(USB_SWITCH, GPIO_DIRECTION_OUT); -#endif -} diff --git a/firmware/src/boards/raspberry_pi_pico/board.mk b/firmware/src/boards/raspberry_pi_pico/board.mk index 7f6a213..5a9a3df 100644 --- a/firmware/src/boards/raspberry_pi_pico/board.mk +++ b/firmware/src/boards/raspberry_pi_pico/board.mk @@ -7,5 +7,10 @@ BOARD_REVISION_MINOR := 3 CMAKE_DEFSYM += \ -DBOARD_REVISION_MAJOR=$(BOARD_REVISION_MAJOR) \ - -DBOARD_REVISION_MINOR=$(BOARD_REVISION_MINOR) \ - -DPICO_SDK_PATH=../lib/pico-sdk + -DBOARD_REVISION_MINOR=$(BOARD_REVISION_MINOR) + +ifeq "$(PICO_SDK_PATH)" "" +CMAKE_DEFSYM += -DPICO_SDK_FETCH_FROM_GIT=1 +else +CMAKE_DEFSYM += -DPICO_SDK_PATH=$(PICO_SDK_PATH) +endif \ No newline at end of file diff --git a/firmware/src/boards/samd11_xplained/button.c b/firmware/src/boards/samd11_xplained/button.c deleted file mode 100644 index ff2d7b8..0000000 --- a/firmware/src/boards/samd11_xplained/button.c +++ /dev/null @@ -1,37 +0,0 @@ -/** - * button handler - * - * Copyright (c) 2023 Great Scott Gadgets - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include "button.h" -#include "usb_switch.h" -#include "fpga.h" -#include "apollo_board.h" -#include - - -/** - * Detect button press. - */ -bool button_pressed(void) -{ -#ifdef BOARD_HAS_PROGRAM_BUTTON - return (gpio_get_pin_level(PROGRAM_BUTTON) == false); -#else - return false; -#endif -} - - -/** - * Handle button events. - */ -void button_task(void) -{ - if (button_pressed()) { - force_fpga_offline(); - take_over_usb(); - } -} diff --git a/firmware/src/boards/samd11_xplained/usb_switch.c b/firmware/src/boards/samd11_xplained/usb_switch.c deleted file mode 100644 index 8b13ac7..0000000 --- a/firmware/src/boards/samd11_xplained/usb_switch.c +++ /dev/null @@ -1,36 +0,0 @@ -/** - * switch control for USB port shared by Apollo and FPGA - * - * This file is part of Apollo. - * - * Copyright (c) 2023 Great Scott Gadgets - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include "usb_switch.h" -#include "apollo_board.h" -#include - - -/** - * Hand off shared USB port to FPGA. - */ -void hand_off_usb(void) -{ -#ifdef BOARD_HAS_USB_SWITCH - gpio_set_pin_level(USB_SWITCH, false); - gpio_set_pin_direction(USB_SWITCH, GPIO_DIRECTION_OUT); -#endif -} - - -/** - * Take control of USB port from FPGA. - */ -void take_over_usb(void) -{ -#ifdef BOARD_HAS_USB_SWITCH - gpio_set_pin_level(USB_SWITCH, true); - gpio_set_pin_direction(USB_SWITCH, GPIO_DIRECTION_OUT); -#endif -} diff --git a/firmware/src/boards/raspberry_pi_pico/button.c b/firmware/src/button.c similarity index 100% rename from firmware/src/boards/raspberry_pi_pico/button.c rename to firmware/src/button.c diff --git a/firmware/src/boards/raspberry_pi_pico/usb_switch.c b/firmware/src/usb_switch.c similarity index 100% rename from firmware/src/boards/raspberry_pi_pico/usb_switch.c rename to firmware/src/usb_switch.c diff --git a/lib/pico-sdk b/lib/pico-sdk deleted file mode 160000 index 6a7db34..0000000 --- a/lib/pico-sdk +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6a7db34ff63345a7badec79ebea3aaef1712f374 From b5664cd682e11bfb7823f1da1b9a9ce84894759f Mon Sep 17 00:00:00 2001 From: marble Date: Mon, 10 Jun 2024 23:38:33 +0200 Subject: [PATCH 06/14] rebase onto main --- firmware/CMakeLists.txt | 3 ++ .../boards/raspberry_pi_pico/apollo_board.h | 3 ++ .../src/boards/raspberry_pi_pico/board.mk | 3 +- firmware/src/boards/raspberry_pi_pico/fpga.c | 33 ++++++++++++---- .../src/boards/raspberry_pi_pico/fpga_adv.c | 38 +++++++++++++++++++ firmware/src/boards/raspberry_pi_pico/led.c | 16 ++++---- 6 files changed, 79 insertions(+), 17 deletions(-) create mode 100644 firmware/src/boards/raspberry_pi_pico/fpga_adv.c diff --git a/firmware/CMakeLists.txt b/firmware/CMakeLists.txt index 02d8b71..afaae7f 100644 --- a/firmware/CMakeLists.txt +++ b/firmware/CMakeLists.txt @@ -25,6 +25,7 @@ target_sources(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/button.c ${CMAKE_CURRENT_SOURCE_DIR}/src/console.c ${CMAKE_CURRENT_SOURCE_DIR}/src/debug_spi.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/fpga.c ${CMAKE_CURRENT_SOURCE_DIR}/src/jtag.c ${CMAKE_CURRENT_SOURCE_DIR}/src/jtag_tap.c ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c @@ -32,6 +33,7 @@ target_sources(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/vendor.c ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/dfu.c ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/jtag.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/fpga_adv.c ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/fpga.c ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/debug_spi.c ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/spi.c @@ -50,6 +52,7 @@ target_compile_definitions(${PROJECT} PUBLIC # CFG_TUSB_OS=OPT_OS_PICO _BOARD_REVISION_MAJOR_=${BOARD_REVISION_MAJOR} _BOARD_REVISION_MINOR_=${BOARD_REVISION_MINOR} + VERSION_STRING="${VERSION_STRING}" ) # Configure compilation flags and libraries for the example... see the corresponding function diff --git a/firmware/src/boards/raspberry_pi_pico/apollo_board.h b/firmware/src/boards/raspberry_pi_pico/apollo_board.h index 3e05f06..e113323 100644 --- a/firmware/src/boards/raspberry_pi_pico/apollo_board.h +++ b/firmware/src/boards/raspberry_pi_pico/apollo_board.h @@ -64,6 +64,9 @@ enum { // // Connected to orangecrab pins 0 and 1. SERCOM0 UART_RX = UART_RX_PIN, UART_TX = UART_TX_PIN, + + // Connected to orangecrab RSTFPGA_RESET, ecp5 PROGRAMN + PIN_PROG = 7, }; diff --git a/firmware/src/boards/raspberry_pi_pico/board.mk b/firmware/src/boards/raspberry_pi_pico/board.mk index 5a9a3df..9f92389 100644 --- a/firmware/src/boards/raspberry_pi_pico/board.mk +++ b/firmware/src/boards/raspberry_pi_pico/board.mk @@ -7,7 +7,8 @@ BOARD_REVISION_MINOR := 3 CMAKE_DEFSYM += \ -DBOARD_REVISION_MAJOR=$(BOARD_REVISION_MAJOR) \ - -DBOARD_REVISION_MINOR=$(BOARD_REVISION_MINOR) + -DBOARD_REVISION_MINOR=$(BOARD_REVISION_MINOR) \ + -DVERSION_STRING="$(VERSION_STRING)" ifeq "$(PICO_SDK_PATH)" "" CMAKE_DEFSYM += -DPICO_SDK_FETCH_FROM_GIT=1 diff --git a/firmware/src/boards/raspberry_pi_pico/fpga.c b/firmware/src/boards/raspberry_pi_pico/fpga.c index 8a556f5..721e9e5 100644 --- a/firmware/src/boards/raspberry_pi_pico/fpga.c +++ b/firmware/src/boards/raspberry_pi_pico/fpga.c @@ -10,6 +10,10 @@ #include #include +#include "apollo_board.h" +#include "jtag.h" +#include "fpga.h" + /* * Allows or disallows the FPGA from configuring. When disallowed, @@ -33,12 +37,25 @@ void fpga_io_init(void) */ void trigger_fpga_reconfiguration(void) { -} - - -/** - * Requests that we hold the FPGA in an unconfigured state. - */ -void force_fpga_offline(void) -{ + /* + * If the JTAG TAP was left in certain states, pulsing PROGRAMN has no + * effect, so we reset the state first. + */ + jtag_init(); + jtag_go_to_state(STATE_TEST_LOGIC_RESET); + jtag_wait_time(2); + jtag_deinit(); + /* + * Now pulse PROGRAMN to instruct the FPGA to configure itself. + */ + gpio_set_pin_direction(PIN_PROG, GPIO_DIRECTION_OUT); + gpio_set_pin_level(PIN_PROG, false); + + board_delay(1); + + gpio_set_pin_level(PIN_PROG, true); + gpio_set_pin_direction(PIN_PROG, GPIO_DIRECTION_IN); + + // Update internal state. + fpga_set_online(true); } diff --git a/firmware/src/boards/raspberry_pi_pico/fpga_adv.c b/firmware/src/boards/raspberry_pi_pico/fpga_adv.c new file mode 100644 index 0000000..3900456 --- /dev/null +++ b/firmware/src/boards/raspberry_pi_pico/fpga_adv.c @@ -0,0 +1,38 @@ +/** + * FPGA advertisement pin handling code. + * + * This file is part of Apollo. + * + * Copyright (c) 2023 Great Scott Gadgets + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +/** + * Initialize FPGA_ADV receive-only serial port + */ +void fpga_adv_init(void) +{ +} + +/** + * Task for things related with the advertisement pin + */ +void fpga_adv_task(void) +{ +} + +/** + * Allow FPGA takeover of the USB port + */ +void allow_fpga_takeover_usb(bool allow) +{ +} + +/** + * True if we received an advertisement message within the last time window. + */ +bool fpga_requesting_port(void) +{ + return false; +} diff --git a/firmware/src/boards/raspberry_pi_pico/led.c b/firmware/src/boards/raspberry_pi_pico/led.c index 94afd33..a479919 100644 --- a/firmware/src/boards/raspberry_pi_pico/led.c +++ b/firmware/src/boards/raspberry_pi_pico/led.c @@ -20,15 +20,15 @@ /** Store the current LED blink pattern. */ -static blink_pattern_t blink_pattern = BLINK_IDLE; +static led_pattern_t led_pattern = LED_IDLE; /** - * Sets the active LED blink pattern. + * Sets the active LED pattern. */ -void led_set_blink_pattern(blink_pattern_t pattern) +void led_set_pattern(led_pattern_t pattern) { - blink_pattern = pattern; + led_pattern = pattern; leds_off(); } @@ -111,17 +111,17 @@ static void display_led_number(uint8_t number) /** - * Task that handles blinking the heartbeat LED. + * Task that handles LED updates. */ -void heartbeat_task(void) +void led_task(void) { static uint32_t start_ms = 0; // Blink every interval ms - if ( board_millis() - start_ms < blink_pattern) { + if ( board_millis() - start_ms < led_pattern) { return; // not enough time } - start_ms += blink_pattern; + start_ms += led_pattern; led_toggle(LED_A); } From e9bc6772019e4dbf77a4b2af3ae10228ff4f98d8 Mon Sep 17 00:00:00 2001 From: marble Date: Mon, 10 Jun 2024 23:41:49 +0200 Subject: [PATCH 07/14] fix github workflow --- .github/workflows/firmware.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/firmware.yml b/.github/workflows/firmware.yml index c0b78bc..3265161 100644 --- a/.github/workflows/firmware.yml +++ b/.github/workflows/firmware.yml @@ -13,6 +13,7 @@ jobs: - 'qtpy' - 'cynthion r0.2' - 'cynthion r0.4' + - 'raspberry_pi_pico' include: - target-board: 'cynthion r0.2' board-major: 0 @@ -20,7 +21,6 @@ jobs: - target-board: 'cynthion r0.4' board-major: 0 board-minor: 4 - - 'raspberry_pi_pico' steps: - name: Install ARM GCC uses: carlosperate/arm-none-eabi-gcc-action@v1 From bf4450c3391393de3fb8414ede2e5c368363de84 Mon Sep 17 00:00:00 2001 From: marble Date: Tue, 11 Jun 2024 01:04:37 +0200 Subject: [PATCH 08/14] add rp2040 mcu directory --- firmware/CMakeLists.txt | 21 +++++----- .../src/boards/raspberry_pi_pico/debug_spi.c | 36 ------------------ .../src/boards/raspberry_pi_pico/fpga_adv.c | 38 ------------------- .../raspberry_pi_pico => mcu/rp2040}/dfu.c | 0 .../rp2040}/usb_descriptors.c | 0 5 files changed, 11 insertions(+), 84 deletions(-) delete mode 100644 firmware/src/boards/raspberry_pi_pico/debug_spi.c delete mode 100644 firmware/src/boards/raspberry_pi_pico/fpga_adv.c rename firmware/src/{boards/raspberry_pi_pico => mcu/rp2040}/dfu.c (100%) rename firmware/src/{boards/raspberry_pi_pico => mcu/rp2040}/usb_descriptors.c (100%) diff --git a/firmware/CMakeLists.txt b/firmware/CMakeLists.txt index afaae7f..e839333 100644 --- a/firmware/CMakeLists.txt +++ b/firmware/CMakeLists.txt @@ -22,24 +22,25 @@ add_executable(${PROJECT}) # Example source target_sources(${PROJECT} PUBLIC + # ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/dfu.c + # ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/usb_descriptors.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/fpga.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/jtag.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/led.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/spi.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/uart.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/mcu/rp2040/dfu.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/mcu/rp2040/usb_descriptors.c ${CMAKE_CURRENT_SOURCE_DIR}/src/button.c ${CMAKE_CURRENT_SOURCE_DIR}/src/console.c ${CMAKE_CURRENT_SOURCE_DIR}/src/debug_spi.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/fpga_adv.c ${CMAKE_CURRENT_SOURCE_DIR}/src/fpga.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/jtag.c ${CMAKE_CURRENT_SOURCE_DIR}/src/jtag_tap.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/jtag.c ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_switch.c ${CMAKE_CURRENT_SOURCE_DIR}/src/vendor.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/dfu.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/jtag.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/fpga_adv.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/fpga.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/debug_spi.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/spi.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/led.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/uart.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/boards/${BOARD}/usb_descriptors.c ) # Example include diff --git a/firmware/src/boards/raspberry_pi_pico/debug_spi.c b/firmware/src/boards/raspberry_pi_pico/debug_spi.c deleted file mode 100644 index 0c85a10..0000000 --- a/firmware/src/boards/raspberry_pi_pico/debug_spi.c +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Interface code for communicating with the FPGA over the Debug SPI connection. - * - * This file is part of LUNA. - * - * Copyright (c) 2020 Great Scott Gadgets - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include -#include - -#include -#include - -extern uint8_t spi_in_buffer[256 + 4]; -extern uint8_t spi_out_buffer[256 + 4]; - - -// Imported internal functions from main debug_spi.c: -void debug_spi_send(uint8_t *tx_buffer, uint8_t *rx_buffer, size_t length); - - -/** - * Request that sends a block of data over our debug SPI. - */ -bool handle_flash_spi_send(uint8_t rhport, tusb_control_request_t const* request) -{ - return false; -} - - -bool handle_flash_spi_send_complete(uint8_t rhport, tusb_control_request_t const* request) -{ - return false; -} diff --git a/firmware/src/boards/raspberry_pi_pico/fpga_adv.c b/firmware/src/boards/raspberry_pi_pico/fpga_adv.c deleted file mode 100644 index 3900456..0000000 --- a/firmware/src/boards/raspberry_pi_pico/fpga_adv.c +++ /dev/null @@ -1,38 +0,0 @@ -/** - * FPGA advertisement pin handling code. - * - * This file is part of Apollo. - * - * Copyright (c) 2023 Great Scott Gadgets - * SPDX-License-Identifier: BSD-3-Clause - */ -#include - -/** - * Initialize FPGA_ADV receive-only serial port - */ -void fpga_adv_init(void) -{ -} - -/** - * Task for things related with the advertisement pin - */ -void fpga_adv_task(void) -{ -} - -/** - * Allow FPGA takeover of the USB port - */ -void allow_fpga_takeover_usb(bool allow) -{ -} - -/** - * True if we received an advertisement message within the last time window. - */ -bool fpga_requesting_port(void) -{ - return false; -} diff --git a/firmware/src/boards/raspberry_pi_pico/dfu.c b/firmware/src/mcu/rp2040/dfu.c similarity index 100% rename from firmware/src/boards/raspberry_pi_pico/dfu.c rename to firmware/src/mcu/rp2040/dfu.c diff --git a/firmware/src/boards/raspberry_pi_pico/usb_descriptors.c b/firmware/src/mcu/rp2040/usb_descriptors.c similarity index 100% rename from firmware/src/boards/raspberry_pi_pico/usb_descriptors.c rename to firmware/src/mcu/rp2040/usb_descriptors.c From aa855bf6933f588d2fbf49d4e89f9322a0dfcc65 Mon Sep 17 00:00:00 2001 From: marble Date: Tue, 11 Jun 2024 02:00:53 +0200 Subject: [PATCH 09/14] firmware: undo changes to usb_switch.c --- .../src/boards/raspberry_pi_pico/board.mk | 2 +- firmware/src/usb_switch.c | 54 ++++++++++++++++++- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/firmware/src/boards/raspberry_pi_pico/board.mk b/firmware/src/boards/raspberry_pi_pico/board.mk index 9f92389..fcfb87d 100644 --- a/firmware/src/boards/raspberry_pi_pico/board.mk +++ b/firmware/src/boards/raspberry_pi_pico/board.mk @@ -14,4 +14,4 @@ ifeq "$(PICO_SDK_PATH)" "" CMAKE_DEFSYM += -DPICO_SDK_FETCH_FROM_GIT=1 else CMAKE_DEFSYM += -DPICO_SDK_PATH=$(PICO_SDK_PATH) -endif \ No newline at end of file +endif diff --git a/firmware/src/usb_switch.c b/firmware/src/usb_switch.c index 06b096b..e90b271 100644 --- a/firmware/src/usb_switch.c +++ b/firmware/src/usb_switch.c @@ -3,22 +3,47 @@ * * This file is part of Apollo. * - * Copyright (c) 2023 Great Scott Gadgets + * Copyright (c) 2023-2024 Great Scott Gadgets * SPDX-License-Identifier: BSD-3-Clause */ #include "usb_switch.h" #include "apollo_board.h" +#include +#include + +enum { + SWITCH_UNKNOWN = 0, + SWITCH_MCU = 1, + SWITCH_FPGA = 2, +}; + +#ifdef BOARD_HAS_SHARED_USB +static int switch_state = SWITCH_UNKNOWN; +#endif /** * Hand off shared USB port to FPGA. */ void hand_off_usb(void) { +#ifdef BOARD_HAS_SHARED_USB + if (switch_state == SWITCH_FPGA) return; + + // Disable internal pull-up resistor on D+/D- pins for a moment to force a disconnection + tud_disconnect(); + board_delay(100); + #ifdef BOARD_HAS_USB_SWITCH gpio_set_pin_level(USB_SWITCH, false); gpio_set_pin_direction(USB_SWITCH, GPIO_DIRECTION_OUT); +#else + gpio_set_pin_pull_mode(PHY_RESET, GPIO_PULL_DOWN); + gpio_set_pin_direction(PHY_RESET, GPIO_DIRECTION_IN); +#endif + + switch_state = SWITCH_FPGA; #endif } @@ -28,8 +53,35 @@ void hand_off_usb(void) */ void take_over_usb(void) { +#ifdef BOARD_HAS_SHARED_USB + if (switch_state == SWITCH_MCU) return; + #ifdef BOARD_HAS_USB_SWITCH gpio_set_pin_level(USB_SWITCH, true); gpio_set_pin_direction(USB_SWITCH, GPIO_DIRECTION_OUT); +#else + gpio_set_pin_level(PHY_RESET, false); + gpio_set_pin_direction(PHY_RESET, GPIO_DIRECTION_OUT); +#endif + + // Disable internal pull-up resistor on D+/D- pins for a moment to force a disconnection + tud_disconnect(); + board_delay(100); + tud_connect(); + + switch_state = SWITCH_MCU; +#endif +} + + +/** + * True if the USB switch handed over the port to the FPGA. + */ +bool fpga_controls_usb_port(void) +{ +#ifdef BOARD_HAS_SHARED_USB + return switch_state == SWITCH_FPGA; +#else + return false; #endif } From f5f65a815ebf554770b4e7fa2859e2690d62e6ce Mon Sep 17 00:00:00 2001 From: marble Date: Tue, 11 Jun 2024 13:48:30 +0200 Subject: [PATCH 10/14] firmware: revert changes to button.c --- firmware/src/button.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/firmware/src/button.c b/firmware/src/button.c index c4fdf90..444657c 100644 --- a/firmware/src/button.c +++ b/firmware/src/button.c @@ -1,7 +1,7 @@ /** * button handler * - * Copyright (c) 2023 Great Scott Gadgets + * Copyright (c) 2023-2024 Great Scott Gadgets * SPDX-License-Identifier: BSD-3-Clause */ @@ -10,6 +10,12 @@ #include "fpga.h" #include "apollo_board.h" +static inline void delay(int cycles) +{ + while (cycles-- != 0) + __NOP(); +} + /** * Detect button press. @@ -17,7 +23,20 @@ bool button_pressed(void) { #ifdef BOARD_HAS_PROGRAM_BUTTON + +#ifdef BOARD_HAS_SHARED_BUTTON + bool level = gpio_get_pin_level(PROGRAM_BUTTON); + gpio_set_pin_direction(PROGRAM_BUTTON, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(PROGRAM_BUTTON, GPIO_PULL_UP); + delay(50); + bool pressed = (gpio_get_pin_level(PROGRAM_BUTTON) == false); + gpio_set_pin_direction(PROGRAM_BUTTON, GPIO_DIRECTION_OUT); + gpio_set_pin_level(PROGRAM_BUTTON, level); + return pressed; +#else return (gpio_get_pin_level(PROGRAM_BUTTON) == false); +#endif + #else return false; #endif From 414a5aecf996c51008031ad7c5937a7ba6e3a40d Mon Sep 17 00:00:00 2001 From: marble Date: Tue, 11 Jun 2024 13:48:46 +0200 Subject: [PATCH 11/14] firmware: fix indentation --- firmware/src/mcu/rp2040/dfu.c | 8 +- firmware/src/mcu/rp2040/usb_descriptors.c | 193 +++++++++++----------- 2 files changed, 100 insertions(+), 101 deletions(-) diff --git a/firmware/src/mcu/rp2040/dfu.c b/firmware/src/mcu/rp2040/dfu.c index 438654a..c58945f 100644 --- a/firmware/src/mcu/rp2040/dfu.c +++ b/firmware/src/mcu/rp2040/dfu.c @@ -3,9 +3,7 @@ * * This file provides support for automatically rebooting into the DFU bootloader. * - * This file is part of LUNA. - * - * Copyright (c) 2020 Great Scott Gadgets + * Copyright (c) 2023-2024 Great Scott Gadgets * SPDX-License-Identifier: BSD-3-Clause */ @@ -17,6 +15,6 @@ */ void tud_dfu_runtime_reboot_to_dfu_cb(void) { - reset_usb_boot(0, 0); - while(1); + reset_usb_boot(0, 0); + while(1); } diff --git a/firmware/src/mcu/rp2040/usb_descriptors.c b/firmware/src/mcu/rp2040/usb_descriptors.c index d04fb19..f4be77d 100644 --- a/firmware/src/mcu/rp2040/usb_descriptors.c +++ b/firmware/src/mcu/rp2040/usb_descriptors.c @@ -1,6 +1,7 @@ /* * The MIT License (MIT) * + * Copyright (c) 2023-2024 Great Scott Gadgets * Copyright (c) 2019 Ha Thach (tinyusb.org) * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -38,42 +39,42 @@ */ #define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) #define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) + _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ tusb_desc_device_t const desc_device = { - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, - // Use Interface Association Descriptor (IAD) for CDC - // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) - .bDeviceClass = TUSB_CLASS_MISC, - .bDeviceSubClass = MISC_SUBCLASS_COMMON, - .bDeviceProtocol = MISC_PROTOCOL_IAD, + // Use Interface Association Descriptor (IAD) for CDC + // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - // These are a unique VID/PID for development LUNA boards. - .idVendor = 0x1d50, - .idProduct = 0x615c, - .bcdDevice = (_BOARD_REVISION_MAJOR_ << 8) | _BOARD_REVISION_MINOR_, + // These are a unique VID/PID for development LUNA boards. + .idVendor = 0x1d50, + .idProduct = 0x615c, + .bcdDevice = (_BOARD_REVISION_MAJOR_ << 8) | _BOARD_REVISION_MINOR_, - .iManufacturer = 0x01, - .iProduct = 0x02, - .iSerialNumber = SERIAL_NUMBER_STRING_INDEX, + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = SERIAL_NUMBER_STRING_INDEX, - .bNumConfigurations = 0x01 + .bNumConfigurations = 0x01 }; // Invoked when received GET DEVICE DESCRIPTOR // Application return pointer to descriptor uint8_t const * tud_descriptor_device_cb(void) { - return (uint8_t const *) &desc_device; + return (uint8_t const *) &desc_device; } //--------------------------------------------------------------------+ @@ -82,47 +83,47 @@ uint8_t const * tud_descriptor_device_cb(void) enum { - ITF_NUM_CDC = 0, - ITF_NUM_CDC_DATA, - ITF_NUM_DFU_RT, - ITF_NUM_TOTAL + ITF_NUM_CDC = 0, + ITF_NUM_CDC_DATA, + ITF_NUM_DFU_RT, + ITF_NUM_TOTAL }; #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_DFU_RT_DESC_LEN) #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX - // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number - // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... - #define EPNUM_CDC_NOTIF 0x81 - #define EPNUM_CDC_DATA 0x02 + // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number + // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... + #define EPNUM_CDC_NOTIF 0x81 + #define EPNUM_CDC_DATA 0x02 #else - #define EPNUM_CDC_NOTIF 0x81 - #define EPNUM_CDC_DATA 0x02 + #define EPNUM_CDC_NOTIF 0x81 + #define EPNUM_CDC_DATA 0x02 #endif uint8_t const desc_fs_configuration[] = { - // Interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // Interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), - // Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_DATA, 0x80 | EPNUM_CDC_DATA, 64), + // Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_DATA, 0x80 | EPNUM_CDC_DATA, 64), - // Interface descriptor for the DFU runtime interface. - TUD_DFU_RT_DESCRIPTOR(ITF_NUM_DFU_RT, 5, 0x0d, 500, 4096), + // Interface descriptor for the DFU runtime interface. + TUD_DFU_RT_DESCRIPTOR(ITF_NUM_DFU_RT, 5, 0x0d, 500, 4096), }; #if TUD_OPT_HIGH_SPEED uint8_t const desc_hs_configuration[] = { - // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), - // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 5, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_DATA, 0x80 | EPNUM_CDC_DATA, 512), + // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 5, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_DATA, 0x80 | EPNUM_CDC_DATA, 512), - // Interface number, string index, attributes, detach timeout, transfer size */ - TUD_DFU_RT_DESCRIPTOR(ITF_NUM_DFU_RT, 4, 0x0d, 1000, 4096), + // Interface number, string index, attributes, detach timeout, transfer size */ + TUD_DFU_RT_DESCRIPTOR(ITF_NUM_DFU_RT, 4, 0x0d, 1000, 4096), }; #endif @@ -131,12 +132,12 @@ uint8_t const desc_hs_configuration[] = // Descriptor contents must exist long enough for transfer to complete uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { - (void) index; // for multiple configurations + (void) index; // for multiple configurations #if TUD_OPT_HIGH_SPEED - // Although we are highspeed, host may be fullspeed. - return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration; + // Although we are highspeed, host may be fullspeed. + return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration; #else - return desc_fs_configuration; + return desc_fs_configuration; #endif } @@ -148,12 +149,12 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index) // array of pointer to string descriptors char const* string_desc_arr [] = { - (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) - "Great Scott Gadgets", // 1: Manufacturer - "LUNA Debug Controller", // 2: Product - NULL, // 3: Serials, should use chip ID - "UART Bridge", // 4: CDC Interface - "DFU Runtime" // 5: DFU Interface + (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) + "Great Scott Gadgets", // 1: Manufacturer + "LUNA Debug Controller", // 2: Product + NULL, // 3: Serials, should use chip ID + "UART Bridge", // 4: CDC Interface + "DFU Runtime" // 5: DFU Interface }; static uint16_t _desc_str[34]; @@ -164,68 +165,68 @@ static uint16_t _desc_str[34]; */ static uint16_t *get_serial_number_string_descriptor(void) { - static pico_unique_board_id_t uID; - static bool got_unique_board_id = false; + static pico_unique_board_id_t uID; + static bool got_unique_board_id = false; - const unsigned serial_number_chars = PICO_UNIQUE_BOARD_ID_SIZE_BYTES*2; + const unsigned serial_number_chars = PICO_UNIQUE_BOARD_ID_SIZE_BYTES*2; - int count = 0; + int count = 0; - if (!got_unique_board_id) { - pico_get_unique_board_id(&uID); - got_unique_board_id = true; - } + if (!got_unique_board_id) { + pico_get_unique_board_id(&uID); + got_unique_board_id = true; + } - // Populate the length and string type, as these are the first two bytes - // of our descriptor... - _desc_str[count++] = (TUSB_DESC_STRING << 8 ) | ((serial_number_chars * 2) + 2);; + // Populate the length and string type, as these are the first two bytes + // of our descriptor... + _desc_str[count++] = (TUSB_DESC_STRING << 8 ) | ((serial_number_chars * 2) + 2);; - // ... and convert our serial number into hex. - for (unsigned i = 0; i < serial_number_chars; ++i) { - uint8_t hexit = (uID.id[i / 2] >> (4 * (1 - (i % 2)))); - _desc_str[count++] = "0123456789abcdef"[hexit & 0xF]; - } + // ... and convert our serial number into hex. + for (unsigned i = 0; i < serial_number_chars; ++i) { + uint8_t hexit = (uID.id[i / 2] >> (4 * (1 - (i % 2)))); + _desc_str[count++] = "0123456789abcdef"[hexit & 0xF]; + } - return _desc_str; + return _desc_str; } // Invoked when received GET STRING DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) { - uint8_t chr_count; - - // If we're looking for the "supported languages" descriptor, return it directly. - if (index == 0) { - memcpy(&_desc_str[1], string_desc_arr[0], 2); - chr_count = 1; - } - // If this is a request for the serial number, return the device's unique ID> - else if (index == SERIAL_NUMBER_STRING_INDEX) { - return get_serial_number_string_descriptor(); - } - - // Otherwise, take the ASCII string provided and encode it as UTF-16. - else { - - if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) { - return NULL; + uint8_t chr_count; + + // If we're looking for the "supported languages" descriptor, return it directly. + if (index == 0) { + memcpy(&_desc_str[1], string_desc_arr[0], 2); + chr_count = 1; } + // If this is a request for the serial number, return the device's unique ID> + else if (index == SERIAL_NUMBER_STRING_INDEX) { + return get_serial_number_string_descriptor(); + } + + // Otherwise, take the ASCII string provided and encode it as UTF-16. + else { + + if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) { + return NULL; + } - const char* str = string_desc_arr[index]; + const char* str = string_desc_arr[index]; - // Cap at max char - chr_count = strlen(str); - if ( chr_count > 31 ) chr_count = 31; + // Cap at max char + chr_count = strlen(str); + if ( chr_count > 31 ) chr_count = 31; - for(uint8_t i=0; i Date: Tue, 11 Jun 2024 13:58:55 +0200 Subject: [PATCH 12/14] firmware: fix more indentation --- firmware/src/boards/raspberry_pi_pico/fpga.c | 2 +- firmware/src/boards/raspberry_pi_pico/led.c | 4 +- firmware/src/boards/raspberry_pi_pico/spi.c | 44 ++-- .../boards/raspberry_pi_pico/tusb_config.h | 22 +- firmware/src/boards/raspberry_pi_pico/uart.c | 40 ++-- firmware/src/mcu/rp2040/dfu.c | 4 +- firmware/src/mcu/rp2040/usb_descriptors.c | 190 +++++++++--------- 7 files changed, 153 insertions(+), 153 deletions(-) diff --git a/firmware/src/boards/raspberry_pi_pico/fpga.c b/firmware/src/boards/raspberry_pi_pico/fpga.c index 721e9e5..386c8ee 100644 --- a/firmware/src/boards/raspberry_pi_pico/fpga.c +++ b/firmware/src/boards/raspberry_pi_pico/fpga.c @@ -37,7 +37,7 @@ void fpga_io_init(void) */ void trigger_fpga_reconfiguration(void) { - /* + /* * If the JTAG TAP was left in certain states, pulsing PROGRAMN has no * effect, so we reset the state first. */ diff --git a/firmware/src/boards/raspberry_pi_pico/led.c b/firmware/src/boards/raspberry_pi_pico/led.c index a479919..9fb9d52 100644 --- a/firmware/src/boards/raspberry_pi_pico/led.c +++ b/firmware/src/boards/raspberry_pi_pico/led.c @@ -92,7 +92,7 @@ void leds_off(void) led_t leds[] = {LED_A}; for (unsigned i = 0; i < LED_COUNT; ++i) { - led_off(leds[i]); + led_off(leds[i]); } } @@ -105,7 +105,7 @@ static void display_led_number(uint8_t number) led_t leds[] = {LED_A}; if (number < LED_COUNT) { - led_on(leds[number]); + led_on(leds[number]); } } diff --git a/firmware/src/boards/raspberry_pi_pico/spi.c b/firmware/src/boards/raspberry_pi_pico/spi.c index 47c8b56..ff9ed9a 100644 --- a/firmware/src/boards/raspberry_pi_pico/spi.c +++ b/firmware/src/boards/raspberry_pi_pico/spi.c @@ -19,21 +19,21 @@ static const char reverse_char[0x100] = {0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, - 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, - 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, - 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, - 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, - 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, - 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, - 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, - 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, - 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, - 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, - 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, - 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, - 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, - 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, - 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF}; + 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, + 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, + 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, + 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, + 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, + 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, + 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, + 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, + 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, + 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, + 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, + 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, + 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF}; static volatile bool _lsb_first = false; @@ -109,17 +109,17 @@ void spi_initialize(spi_target_t target, bool lsb_first, bool configure_pinmux, spi_deinit(spi); // Set up clocking for the SPI peripheral. - spi_init(spi, 8 * 1000 * 1000 / (2*(baud_divider+1))); + spi_init(spi, 8 * 1000 * 1000 / (2*(baud_divider+1))); // Configure the SPI for master mode. spi_set_slave(spi, false); - // Set SPI format - spi_set_format( spi, // SPI instance - 8, // Number of bits per transfer - clock_polarity, // Polarity (CPOL) - clock_phase, // Phase (CPHA) - SPI_MSB_FIRST); + // Set SPI format + spi_set_format( spi, // SPI instance + 8, // Number of bits per transfer + clock_polarity, // Polarity (CPOL) + clock_phase, // Phase (CPHA) + SPI_MSB_FIRST); // Pinmux the relevant pins to be used for the SPI. if (configure_pinmux) { diff --git a/firmware/src/boards/raspberry_pi_pico/tusb_config.h b/firmware/src/boards/raspberry_pi_pico/tusb_config.h index 14c8ea9..da651bc 100644 --- a/firmware/src/boards/raspberry_pi_pico/tusb_config.h +++ b/firmware/src/boards/raspberry_pi_pico/tusb_config.h @@ -36,32 +36,32 @@ // defined by compiler flags for flexibility #ifndef CFG_TUSB_MCU - #error CFG_TUSB_MCU must be defined + #error CFG_TUSB_MCU must be defined #endif // RHPort number used for device can be defined by board.mk, default to port 0 #ifndef BOARD_DEVICE_RHPORT_NUM - #define BOARD_DEVICE_RHPORT_NUM 0 + #define BOARD_DEVICE_RHPORT_NUM 0 #endif // RHPort max operational speed can defined by board.mk // Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed #ifndef BOARD_DEVICE_RHPORT_SPEED - #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ - CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56) - #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED - #else - #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED - #endif + #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56) + #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED + #else + #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED + #endif #endif // Device mode with rhport and speed defined by board.mk #if BOARD_DEVICE_RHPORT_NUM == 0 - #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) + #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) #elif BOARD_DEVICE_RHPORT_NUM == 1 - #define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) + #define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) #else - #error "Incorrect RHPort configuration" + #error "Incorrect RHPort configuration" #endif // This example doesn't use an RTOS diff --git a/firmware/src/boards/raspberry_pi_pico/uart.c b/firmware/src/boards/raspberry_pi_pico/uart.c index 3d546d0..f0ff721 100644 --- a/firmware/src/boards/raspberry_pi_pico/uart.c +++ b/firmware/src/boards/raspberry_pi_pico/uart.c @@ -72,24 +72,24 @@ void uart_initialize(bool configure_pinmux, unsigned long baudrate) uart_configure_pinmux(); } - uart_init(uart_inst, baudrate); + uart_init(uart_inst, baudrate); while(!uart_is_enabled(uart_inst)); - // Turn off FIFO's - we want to do this character by character - uart_set_fifo_enabled(uart_inst, false); + // Turn off FIFO's - we want to do this character by character + uart_set_fifo_enabled(uart_inst, false); - // Set up a RX interrupt - // We need to set up the handler first - // Select correct interrupt for the UART we are using - int UART_IRQ = (uart_inst == uart0) ? UART0_IRQ : UART1_IRQ; + // Set up a RX interrupt + // We need to set up the handler first + // Select correct interrupt for the UART we are using + int UART_IRQ = (uart_inst == uart0) ? UART0_IRQ : UART1_IRQ; - // And set up and enable the interrupt handlers - irq_set_exclusive_handler(UART_IRQ, on_uart_rx); - irq_set_enabled(UART_IRQ, true); + // And set up and enable the interrupt handlers + irq_set_exclusive_handler(UART_IRQ, on_uart_rx); + irq_set_enabled(UART_IRQ, true); - // Now enable the UART to send interrupts - RX only - uart_set_irq_enables(uart_inst, true, false); + // Now enable the UART to send interrupts - RX only + uart_set_irq_enables(uart_inst, true, false); } @@ -97,7 +97,7 @@ void uart_initialize(bool configure_pinmux, unsigned long baudrate) * Callback issued when the UART recieves a new byte. */ __attribute__((weak)) void uart_byte_received_cb(uint8_t byte) { - (void) byte; // unused + (void) byte; // unused } @@ -105,10 +105,10 @@ __attribute__((weak)) void uart_byte_received_cb(uint8_t byte) { * UART interrupt handler. */ void on_uart_rx() { - while (uart_is_readable(uart_inst)) { - uint8_t ch = uart_getc(uart_inst); + while (uart_is_readable(uart_inst)) { + uint8_t ch = uart_getc(uart_inst); uart_byte_received_cb(ch); - } + } } @@ -117,7 +117,7 @@ void on_uart_rx() { */ bool uart_ready_for_write(void) { - return uart_is_writable(uart_inst); + return uart_is_writable(uart_inst); } @@ -130,8 +130,8 @@ bool uart_ready_for_write(void) void uart_nonblocking_write(uint8_t byte) { if(uart_ready_for_write()) { - uart_putc_raw(uart_inst, byte); - } + uart_putc_raw(uart_inst, byte); + } } @@ -143,5 +143,5 @@ void uart_nonblocking_write(uint8_t byte) void uart_blocking_write(uint8_t byte) { while(!uart_ready_for_write()) {} - uart_putc_raw(uart_inst, byte); + uart_putc_raw(uart_inst, byte); } diff --git a/firmware/src/mcu/rp2040/dfu.c b/firmware/src/mcu/rp2040/dfu.c index c58945f..b4437be 100644 --- a/firmware/src/mcu/rp2040/dfu.c +++ b/firmware/src/mcu/rp2040/dfu.c @@ -15,6 +15,6 @@ */ void tud_dfu_runtime_reboot_to_dfu_cb(void) { - reset_usb_boot(0, 0); - while(1); + reset_usb_boot(0, 0); + while(1); } diff --git a/firmware/src/mcu/rp2040/usb_descriptors.c b/firmware/src/mcu/rp2040/usb_descriptors.c index f4be77d..f5ccc2a 100644 --- a/firmware/src/mcu/rp2040/usb_descriptors.c +++ b/firmware/src/mcu/rp2040/usb_descriptors.c @@ -39,42 +39,42 @@ */ #define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) #define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) + _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ tusb_desc_device_t const desc_device = { - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, - // Use Interface Association Descriptor (IAD) for CDC - // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) - .bDeviceClass = TUSB_CLASS_MISC, - .bDeviceSubClass = MISC_SUBCLASS_COMMON, - .bDeviceProtocol = MISC_PROTOCOL_IAD, + // Use Interface Association Descriptor (IAD) for CDC + // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - // These are a unique VID/PID for development LUNA boards. - .idVendor = 0x1d50, - .idProduct = 0x615c, - .bcdDevice = (_BOARD_REVISION_MAJOR_ << 8) | _BOARD_REVISION_MINOR_, + // These are a unique VID/PID for development LUNA boards. + .idVendor = 0x1d50, + .idProduct = 0x615c, + .bcdDevice = (_BOARD_REVISION_MAJOR_ << 8) | _BOARD_REVISION_MINOR_, - .iManufacturer = 0x01, - .iProduct = 0x02, - .iSerialNumber = SERIAL_NUMBER_STRING_INDEX, + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = SERIAL_NUMBER_STRING_INDEX, - .bNumConfigurations = 0x01 + .bNumConfigurations = 0x01 }; // Invoked when received GET DEVICE DESCRIPTOR // Application return pointer to descriptor uint8_t const * tud_descriptor_device_cb(void) { - return (uint8_t const *) &desc_device; + return (uint8_t const *) &desc_device; } //--------------------------------------------------------------------+ @@ -83,47 +83,47 @@ uint8_t const * tud_descriptor_device_cb(void) enum { - ITF_NUM_CDC = 0, - ITF_NUM_CDC_DATA, - ITF_NUM_DFU_RT, - ITF_NUM_TOTAL + ITF_NUM_CDC = 0, + ITF_NUM_CDC_DATA, + ITF_NUM_DFU_RT, + ITF_NUM_TOTAL }; #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_DFU_RT_DESC_LEN) #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX - // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number - // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... - #define EPNUM_CDC_NOTIF 0x81 - #define EPNUM_CDC_DATA 0x02 + // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number + // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... + #define EPNUM_CDC_NOTIF 0x81 + #define EPNUM_CDC_DATA 0x02 #else - #define EPNUM_CDC_NOTIF 0x81 - #define EPNUM_CDC_DATA 0x02 + #define EPNUM_CDC_NOTIF 0x81 + #define EPNUM_CDC_DATA 0x02 #endif uint8_t const desc_fs_configuration[] = { - // Interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // Interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), - // Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_DATA, 0x80 | EPNUM_CDC_DATA, 64), + // Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_DATA, 0x80 | EPNUM_CDC_DATA, 64), - // Interface descriptor for the DFU runtime interface. - TUD_DFU_RT_DESCRIPTOR(ITF_NUM_DFU_RT, 5, 0x0d, 500, 4096), + // Interface descriptor for the DFU runtime interface. + TUD_DFU_RT_DESCRIPTOR(ITF_NUM_DFU_RT, 5, 0x0d, 500, 4096), }; #if TUD_OPT_HIGH_SPEED uint8_t const desc_hs_configuration[] = { - // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), - // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 5, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_DATA, 0x80 | EPNUM_CDC_DATA, 512), + // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 5, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_DATA, 0x80 | EPNUM_CDC_DATA, 512), - // Interface number, string index, attributes, detach timeout, transfer size */ - TUD_DFU_RT_DESCRIPTOR(ITF_NUM_DFU_RT, 4, 0x0d, 1000, 4096), + // Interface number, string index, attributes, detach timeout, transfer size */ + TUD_DFU_RT_DESCRIPTOR(ITF_NUM_DFU_RT, 4, 0x0d, 1000, 4096), }; #endif @@ -132,12 +132,12 @@ uint8_t const desc_hs_configuration[] = // Descriptor contents must exist long enough for transfer to complete uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { - (void) index; // for multiple configurations + (void) index; // for multiple configurations #if TUD_OPT_HIGH_SPEED - // Although we are highspeed, host may be fullspeed. - return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration; + // Although we are highspeed, host may be fullspeed. + return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration; #else - return desc_fs_configuration; + return desc_fs_configuration; #endif } @@ -149,12 +149,12 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index) // array of pointer to string descriptors char const* string_desc_arr [] = { - (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) - "Great Scott Gadgets", // 1: Manufacturer - "LUNA Debug Controller", // 2: Product - NULL, // 3: Serials, should use chip ID - "UART Bridge", // 4: CDC Interface - "DFU Runtime" // 5: DFU Interface + (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) + "Great Scott Gadgets", // 1: Manufacturer + "LUNA Debug Controller", // 2: Product + NULL, // 3: Serials, should use chip ID + "UART Bridge", // 4: CDC Interface + "DFU Runtime" // 5: DFU Interface }; static uint16_t _desc_str[34]; @@ -165,68 +165,68 @@ static uint16_t _desc_str[34]; */ static uint16_t *get_serial_number_string_descriptor(void) { - static pico_unique_board_id_t uID; - static bool got_unique_board_id = false; + static pico_unique_board_id_t uID; + static bool got_unique_board_id = false; - const unsigned serial_number_chars = PICO_UNIQUE_BOARD_ID_SIZE_BYTES*2; + const unsigned serial_number_chars = PICO_UNIQUE_BOARD_ID_SIZE_BYTES*2; - int count = 0; + int count = 0; - if (!got_unique_board_id) { - pico_get_unique_board_id(&uID); - got_unique_board_id = true; - } + if (!got_unique_board_id) { + pico_get_unique_board_id(&uID); + got_unique_board_id = true; + } - // Populate the length and string type, as these are the first two bytes - // of our descriptor... - _desc_str[count++] = (TUSB_DESC_STRING << 8 ) | ((serial_number_chars * 2) + 2);; + // Populate the length and string type, as these are the first two bytes + // of our descriptor... + _desc_str[count++] = (TUSB_DESC_STRING << 8 ) | ((serial_number_chars * 2) + 2);; - // ... and convert our serial number into hex. - for (unsigned i = 0; i < serial_number_chars; ++i) { - uint8_t hexit = (uID.id[i / 2] >> (4 * (1 - (i % 2)))); - _desc_str[count++] = "0123456789abcdef"[hexit & 0xF]; - } + // ... and convert our serial number into hex. + for (unsigned i = 0; i < serial_number_chars; ++i) { + uint8_t hexit = (uID.id[i / 2] >> (4 * (1 - (i % 2)))); + _desc_str[count++] = "0123456789abcdef"[hexit & 0xF]; + } - return _desc_str; + return _desc_str; } // Invoked when received GET STRING DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) { - uint8_t chr_count; + uint8_t chr_count; - // If we're looking for the "supported languages" descriptor, return it directly. - if (index == 0) { - memcpy(&_desc_str[1], string_desc_arr[0], 2); - chr_count = 1; - } - // If this is a request for the serial number, return the device's unique ID> - else if (index == SERIAL_NUMBER_STRING_INDEX) { - return get_serial_number_string_descriptor(); - } + // If we're looking for the "supported languages" descriptor, return it directly. + if (index == 0) { + memcpy(&_desc_str[1], string_desc_arr[0], 2); + chr_count = 1; + } + // If this is a request for the serial number, return the device's unique ID> + else if (index == SERIAL_NUMBER_STRING_INDEX) { + return get_serial_number_string_descriptor(); + } - // Otherwise, take the ASCII string provided and encode it as UTF-16. - else { + // Otherwise, take the ASCII string provided and encode it as UTF-16. + else { - if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) { - return NULL; - } + if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) { + return NULL; + } - const char* str = string_desc_arr[index]; + const char* str = string_desc_arr[index]; - // Cap at max char - chr_count = strlen(str); - if ( chr_count > 31 ) chr_count = 31; + // Cap at max char + chr_count = strlen(str); + if ( chr_count > 31 ) chr_count = 31; - for(uint8_t i=0; i Date: Tue, 11 Jun 2024 21:19:28 +0200 Subject: [PATCH 13/14] firmware: align copyright notice with rest of project --- firmware/src/boards/raspberry_pi_pico/apollo_board.h | 8 +++----- firmware/src/boards/raspberry_pi_pico/fpga.c | 5 ++--- firmware/src/boards/raspberry_pi_pico/jtag.c | 5 ++--- firmware/src/boards/raspberry_pi_pico/led.c | 3 ++- firmware/src/boards/raspberry_pi_pico/platform_jtag.h | 1 + firmware/src/boards/raspberry_pi_pico/spi.c | 1 + firmware/src/boards/raspberry_pi_pico/spi.h | 1 + firmware/src/boards/raspberry_pi_pico/tusb_config.h | 1 + firmware/src/boards/raspberry_pi_pico/uart.c | 1 + firmware/src/mcu/rp2040/dfu.c | 1 + firmware/src/mcu/rp2040/usb_descriptors.c | 4 +++- 11 files changed, 18 insertions(+), 13 deletions(-) diff --git a/firmware/src/boards/raspberry_pi_pico/apollo_board.h b/firmware/src/boards/raspberry_pi_pico/apollo_board.h index e113323..c4f6491 100644 --- a/firmware/src/boards/raspberry_pi_pico/apollo_board.h +++ b/firmware/src/boards/raspberry_pi_pico/apollo_board.h @@ -1,10 +1,8 @@ /** - * Apollo board definitions for Adafruit QT Py RP2040 + * Apollo board definitions for Raspberry Pi Pico * - * This file is part of LUNA. - * - * Copyright (c) 2020 Great Scott Gadgets - * Copyright (c) 2022 Markus Blechschmidt + * Copyright (c) 2020-2024 Great Scott Gadgets + * Copyright (c) 2024 Markus Blechschmidt * SPDX-License-Identifier: BSD-3-Clause */ diff --git a/firmware/src/boards/raspberry_pi_pico/fpga.c b/firmware/src/boards/raspberry_pi_pico/fpga.c index 386c8ee..1e362a1 100644 --- a/firmware/src/boards/raspberry_pi_pico/fpga.c +++ b/firmware/src/boards/raspberry_pi_pico/fpga.c @@ -1,9 +1,8 @@ /** * Code for basic FPGA interfacing. * - * This file is part of LUNA. - * - * Copyright (c) 2020 Great Scott Gadgets + * Copyright (c) 2020-2023 Great Scott Gadgets + * Copyright (c) 2024 Markus Blechschmidt * SPDX-License-Identifier: BSD-3-Clause */ diff --git a/firmware/src/boards/raspberry_pi_pico/jtag.c b/firmware/src/boards/raspberry_pi_pico/jtag.c index 48c7d88..817a6a8 100644 --- a/firmware/src/boards/raspberry_pi_pico/jtag.c +++ b/firmware/src/boards/raspberry_pi_pico/jtag.c @@ -1,7 +1,6 @@ /** - * This file is part of LUNA. - * - * Copyright (c) 2020 Great Scott Gadgets + * Copyright (c) 2020-2023 Great Scott Gadgets + * Copyright (c) 2024 Markus Blechschmidt * SPDX-License-Identifier: BSD-3-Clause */ diff --git a/firmware/src/boards/raspberry_pi_pico/led.c b/firmware/src/boards/raspberry_pi_pico/led.c index 9fb9d52..b384e02 100644 --- a/firmware/src/boards/raspberry_pi_pico/led.c +++ b/firmware/src/boards/raspberry_pi_pico/led.c @@ -3,7 +3,8 @@ * * This file is part of LUNA. * - * Copyright (c) 2020 Great Scott Gadgets + * Copyright (c) 2020-2024 Great Scott Gadgets + * Copyright (c) 2024 Markus Blechschmidt * SPDX-License-Identifier: BSD-3-Clause */ diff --git a/firmware/src/boards/raspberry_pi_pico/platform_jtag.h b/firmware/src/boards/raspberry_pi_pico/platform_jtag.h index 1c12f85..68eaeb6 100644 --- a/firmware/src/boards/raspberry_pi_pico/platform_jtag.h +++ b/firmware/src/boards/raspberry_pi_pico/platform_jtag.h @@ -3,6 +3,7 @@ * Using these rather than the raw GPIO functions allows read optimizations. * * Copyright (c) 2020 Great Scott Gadgets + * Copyright (c) 2024 Markus Blechschmidt * SPDX-License-Identifier: BSD-3-Clause */ diff --git a/firmware/src/boards/raspberry_pi_pico/spi.c b/firmware/src/boards/raspberry_pi_pico/spi.c index ff9ed9a..1d0d497 100644 --- a/firmware/src/boards/raspberry_pi_pico/spi.c +++ b/firmware/src/boards/raspberry_pi_pico/spi.c @@ -4,6 +4,7 @@ * This file is part of LUNA. * * Copyright (c) 2020 Great Scott Gadgets + * Copyright (c) 2024 Markus Blechschmidt * SPDX-License-Identifier: BSD-3-Clause */ diff --git a/firmware/src/boards/raspberry_pi_pico/spi.h b/firmware/src/boards/raspberry_pi_pico/spi.h index f1a4972..5f29896 100644 --- a/firmware/src/boards/raspberry_pi_pico/spi.h +++ b/firmware/src/boards/raspberry_pi_pico/spi.h @@ -4,6 +4,7 @@ * This file is part of LUNA. * * Copyright (c) 2020 Great Scott Gadgets + * Copyright (c) 2024 Markus Blechschmidt * SPDX-License-Identifier: BSD-3-Clause */ diff --git a/firmware/src/boards/raspberry_pi_pico/tusb_config.h b/firmware/src/boards/raspberry_pi_pico/tusb_config.h index da651bc..e922c59 100644 --- a/firmware/src/boards/raspberry_pi_pico/tusb_config.h +++ b/firmware/src/boards/raspberry_pi_pico/tusb_config.h @@ -2,6 +2,7 @@ * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) + * Copyright (c) 2024 Markus Blechschmidt * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/firmware/src/boards/raspberry_pi_pico/uart.c b/firmware/src/boards/raspberry_pi_pico/uart.c index f0ff721..585a4e4 100644 --- a/firmware/src/boards/raspberry_pi_pico/uart.c +++ b/firmware/src/boards/raspberry_pi_pico/uart.c @@ -4,6 +4,7 @@ * This file is part of LUNA. * * Copyright (c) 2020 Great Scott Gadgets + * Copyright (c) 2024 Markus Blechschmidt * SPDX-License-Identifier: BSD-3-Clause */ diff --git a/firmware/src/mcu/rp2040/dfu.c b/firmware/src/mcu/rp2040/dfu.c index b4437be..f9ef02c 100644 --- a/firmware/src/mcu/rp2040/dfu.c +++ b/firmware/src/mcu/rp2040/dfu.c @@ -4,6 +4,7 @@ * This file provides support for automatically rebooting into the DFU bootloader. * * Copyright (c) 2023-2024 Great Scott Gadgets + * Copyright (c) 2024 Markus Blechschmidt * SPDX-License-Identifier: BSD-3-Clause */ diff --git a/firmware/src/mcu/rp2040/usb_descriptors.c b/firmware/src/mcu/rp2040/usb_descriptors.c index f5ccc2a..a2118c1 100644 --- a/firmware/src/mcu/rp2040/usb_descriptors.c +++ b/firmware/src/mcu/rp2040/usb_descriptors.c @@ -1,8 +1,10 @@ /* * The MIT License (MIT) * - * Copyright (c) 2023-2024 Great Scott Gadgets + * Copyright (c) 2019 Katherine J. Temkin + * Copyright (c) 2019 Great Scott Gadgets * Copyright (c) 2019 Ha Thach (tinyusb.org) + * Copyright (c) 2024 Markus Blechschmidt * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal From 52658c4cde42ca2519ae4112e8114a4fdf31e7ea Mon Sep 17 00:00:00 2001 From: marble Date: Tue, 11 Jun 2024 22:02:54 +0200 Subject: [PATCH 14/14] firmware: add copy usb descriptor code from samd11 --- firmware/src/mcu/rp2040/usb_descriptors.c | 88 +++++++++-------------- 1 file changed, 35 insertions(+), 53 deletions(-) diff --git a/firmware/src/mcu/rp2040/usb_descriptors.c b/firmware/src/mcu/rp2040/usb_descriptors.c index a2118c1..9b66011 100644 --- a/firmware/src/mcu/rp2040/usb_descriptors.c +++ b/firmware/src/mcu/rp2040/usb_descriptors.c @@ -33,15 +33,15 @@ #define SERIAL_NUMBER_STRING_INDEX 3 -/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. - * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. - * - * Auto ProductID layout's Bitmap: - * [MSB] MIDI | HID | MSC | CDC [LSB] - */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +// /* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. +// * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. +// * +// * Auto ProductID layout's Bitmap: +// * [MSB] MIDI | HID | MSC | CDC [LSB] +// */ +// #define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) +// #define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ +// _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) //--------------------------------------------------------------------+ // Device Descriptors @@ -52,11 +52,12 @@ tusb_desc_device_t const desc_device = .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = 0x0200, - // Use Interface Association Descriptor (IAD) for CDC - // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) - .bDeviceClass = TUSB_CLASS_MISC, - .bDeviceSubClass = MISC_SUBCLASS_COMMON, - .bDeviceProtocol = MISC_PROTOCOL_IAD, + // We use bDeviceClass = 0 to indicate that we're a composite device. + // Another option is to use the Interface Association Descriptor (IAD) method, + // but this requires extra descriptors. + .bDeviceClass = 0, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, @@ -93,41 +94,19 @@ enum #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_DFU_RT_DESC_LEN) -#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX - // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number - // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... - #define EPNUM_CDC_NOTIF 0x81 - #define EPNUM_CDC_DATA 0x02 -#else - #define EPNUM_CDC_NOTIF 0x81 - #define EPNUM_CDC_DATA 0x02 -#endif - -uint8_t const desc_fs_configuration[] = + +uint8_t const desc_configuration[] = { // Interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_DATA, 0x80 | EPNUM_CDC_DATA, 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 0, 0x81, 8, 0x02, 0x83, 64), // Interface descriptor for the DFU runtime interface. - TUD_DFU_RT_DESCRIPTOR(ITF_NUM_DFU_RT, 5, 0x0d, 500, 4096), + TUD_DFU_RT_DESCRIPTOR(ITF_NUM_DFU_RT, 0, 0x0d, 500, 4096), }; -#if TUD_OPT_HIGH_SPEED -uint8_t const desc_hs_configuration[] = -{ - // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), - - // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 5, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_DATA, 0x80 | EPNUM_CDC_DATA, 512), - - // Interface number, string index, attributes, detach timeout, transfer size */ - TUD_DFU_RT_DESCRIPTOR(ITF_NUM_DFU_RT, 4, 0x0d, 1000, 4096), -}; -#endif // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor @@ -135,12 +114,7 @@ uint8_t const desc_hs_configuration[] = uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { (void) index; // for multiple configurations -#if TUD_OPT_HIGH_SPEED - // Although we are highspeed, host may be fullspeed. - return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration; -#else - return desc_fs_configuration; -#endif + return desc_configuration; } //--------------------------------------------------------------------+ @@ -153,10 +127,8 @@ char const* string_desc_arr [] = { (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) "Great Scott Gadgets", // 1: Manufacturer - "LUNA Debug Controller", // 2: Product + "Apollo Debugger", // 2: Product NULL, // 3: Serials, should use chip ID - "UART Bridge", // 4: CDC Interface - "DFU Runtime" // 5: DFU Interface }; static uint16_t _desc_str[34]; @@ -174,6 +146,10 @@ static uint16_t *get_serial_number_string_descriptor(void) int count = 0; + // + // Read and save the device serial number as hexadecimal. + // + if (!got_unique_board_id) { pico_get_unique_board_id(&uID); got_unique_board_id = true; @@ -211,11 +187,17 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) // Otherwise, take the ASCII string provided and encode it as UTF-16. else { - if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) { - return NULL; - } + const char* str; + if (index == 0xee) { + // Microsoft OS 1.0 String Descriptor + str = "MSFT100\xee"; + } else { + if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) { + return NULL; + } - const char* str = string_desc_arr[index]; + str = string_desc_arr[index]; + } // Cap at max char chr_count = strlen(str);