From 5e42f9c568a9c15fe4527997b2f75be3f25602da Mon Sep 17 00:00:00 2001 From: dark98 Date: Sun, 6 Sep 2026 16:24:00 +0100 Subject: [PATCH] Initial Commit --- .gitignore | 2 + .vscode/c_cpp_properties.json | 21 +++ .vscode/cmake-kits.json | 15 ++ .vscode/extensions.json | 9 + .vscode/launch.json | 52 ++++++ .vscode/settings.json | 46 +++++ .vscode/tasks.json | 102 +++++++++++ CMakeLists.txt | 61 +++++++ USB-Serial.cpp | 308 ++++++++++++++++++++++++++++++++++ pico_sdk_import.cmake | 121 +++++++++++++ raspberrypi-swd.cfg | 4 + tusb_config.h | 71 ++++++++ usb_descriptors.c | 0 13 files changed, 812 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/c_cpp_properties.json create mode 100644 .vscode/cmake-kits.json create mode 100644 .vscode/extensions.json create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 .vscode/tasks.json create mode 100644 CMakeLists.txt create mode 100644 USB-Serial.cpp create mode 100644 pico_sdk_import.cmake create mode 100644 raspberrypi-swd.cfg create mode 100644 tusb_config.h create mode 100644 usb_descriptors.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2435c20 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build +!.vscode/* diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..bdaed64 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,21 @@ +{ + "configurations": [ + { + "name": "Pico", + "includePath": [ + "${workspaceFolder}/**", + "${userHome}/.pico-sdk/sdk/2.3.0/**" + ], + "forcedInclude": [ + "${userHome}/.pico-sdk/sdk/2.3.0/src/common/pico_base_headers/include/pico.h" + ], + "defines": [], + "compilerPath": "${userHome}/.pico-sdk/toolchain/15_2_Rel1/bin/arm-none-eabi-gcc.exe", + "compileCommands": "${workspaceFolder}/build/compile_commands.json", + "cStandard": "c17", + "cppStandard": "c++14", + "intelliSenseMode": "linux-gcc-arm" + } + ], + "version": 4 +} diff --git a/.vscode/cmake-kits.json b/.vscode/cmake-kits.json new file mode 100644 index 0000000..b0f3815 --- /dev/null +++ b/.vscode/cmake-kits.json @@ -0,0 +1,15 @@ +[ + { + "name": "Pico", + "compilers": { + "C": "${command:raspberry-pi-pico.getCompilerPath}", + "CXX": "${command:raspberry-pi-pico.getCxxCompilerPath}" + }, + "environmentVariables": { + "PATH": "${command:raspberry-pi-pico.getEnvPath};${env:PATH}" + }, + "cmakeSettings": { + "Python3_EXECUTABLE": "${command:raspberry-pi-pico.getPythonPath}" + } + } +] \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..a940d7c --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,9 @@ +{ + "recommendations": [ + "marus25.cortex-debug", + "ms-vscode.cpptools", + "ms-vscode.cpptools-extension-pack", + "ms-vscode.vscode-serial-monitor", + "raspberry-pi.raspberry-pi-pico" + ] +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..611256e --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,52 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Pico Debug (Cortex-Debug)", + "cwd": "${userHome}/.pico-sdk/openocd/0.12.0+dev/scripts", + "executable": "${command:raspberry-pi-pico.launchTargetPath}", + "request": "launch", + "type": "cortex-debug", + "servertype": "openocd", + "serverpath": "${userHome}/.pico-sdk/openocd/0.12.0+dev/openocd.exe", + "gdbPath": "${command:raspberry-pi-pico.getGDBPath}", + "debuggerArgs": ["-ex", "set debug-file-directory /debug"], + "device": "${command:raspberry-pi-pico.getChipUppercase}", + "configFiles": [ + "raspberrypi-swd.cfg", + "target/${command:raspberry-pi-pico.getTarget}.cfg" + ], + "svdFile": "${userHome}/.pico-sdk/sdk/2.3.0/src/${command:raspberry-pi-pico.getChip}/hardware_regs/${command:raspberry-pi-pico.getChipUppercase}.svd", + "runToEntryPoint": "main", + // Fix for no_flash binaries, where monitor reset halt doesn't do what is expected + // Also works fine for flash binaries + "overrideLaunchCommands": [ + "monitor reset init", + "load \"${command:raspberry-pi-pico.launchTargetPath}\"" + ], + "openOCDLaunchCommands": [ + "adapter speed 5000" + ] + }, + { + "name": "Pico Debug (Cortex-Debug with external OpenOCD)", + "cwd": "${workspaceRoot}", + "executable": "${command:raspberry-pi-pico.launchTargetPath}", + "request": "launch", + "type": "cortex-debug", + "servertype": "external", + "gdbTarget": "localhost:3333", + "gdbPath": "${command:raspberry-pi-pico.getGDBPath}", + "debuggerArgs": ["-ex", "set debug-file-directory /debug"], + "device": "${command:raspberry-pi-pico.getChipUppercase}", + "svdFile": "${userHome}/.pico-sdk/sdk/2.3.0/src/${command:raspberry-pi-pico.getChip}/hardware_regs/${command:raspberry-pi-pico.getChipUppercase}.svd", + "runToEntryPoint": "main", + // Fix for no_flash binaries, where monitor reset halt doesn't do what is expected + // Also works fine for flash binaries + "overrideLaunchCommands": [ + "monitor reset init", + "load \"${command:raspberry-pi-pico.launchTargetPath}\"" + ] + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..ecbf7dc --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,46 @@ +{ + "cmake.showSystemKits": false, + "cmake.options.statusBarVisibility": "hidden", + "cmake.options.advanced": { + "build": { + "statusBarVisibility": "hidden" + }, + "launch": { + "statusBarVisibility": "hidden" + }, + "debug": { + "statusBarVisibility": "hidden" + }, + "variant": { + "statusBarVisibility": "hidden" + }, + "buildTarget": { + "statusBarVisibility": "hidden" + } + }, + "cmake.configureOnEdit": false, + "cmake.automaticReconfigure": false, + "cmake.configureOnOpen": false, + "cmake.generator": "Ninja", + "cmake.cmakePath": "${userHome}/.pico-sdk/cmake/v4.3.4/bin/cmake", + "C_Cpp.debugShortcut": false, + "terminal.integrated.env.windows": { + "PICO_SDK_PATH": "${env:USERPROFILE}/.pico-sdk/sdk/2.3.0", + "PICO_TOOLCHAIN_PATH": "${env:USERPROFILE}/.pico-sdk/toolchain/15_2_Rel1", + "Path": "${env:USERPROFILE}/.pico-sdk/toolchain/15_2_Rel1/bin;${env:USERPROFILE}/.pico-sdk/picotool/2.3.0/picotool;${env:USERPROFILE}/.pico-sdk/cmake/v4.3.4/bin;${env:USERPROFILE}/.pico-sdk/ninja/v1.13.2;${env:PATH}" + }, + "terminal.integrated.env.osx": { + "PICO_SDK_PATH": "${env:HOME}/.pico-sdk/sdk/2.3.0", + "PICO_TOOLCHAIN_PATH": "${env:HOME}/.pico-sdk/toolchain/15_2_Rel1", + "PATH": "${env:HOME}/.pico-sdk/toolchain/15_2_Rel1/bin:${env:HOME}/.pico-sdk/picotool/2.3.0/picotool:${env:HOME}/.pico-sdk/cmake/v4.3.4/bin:${env:HOME}/.pico-sdk/ninja/v1.13.2:${env:PATH}" + }, + "terminal.integrated.env.linux": { + "PICO_SDK_PATH": "${env:HOME}/.pico-sdk/sdk/2.3.0", + "PICO_TOOLCHAIN_PATH": "${env:HOME}/.pico-sdk/toolchain/15_2_Rel1", + "PATH": "${env:HOME}/.pico-sdk/toolchain/15_2_Rel1/bin:${env:HOME}/.pico-sdk/picotool/2.3.0/picotool:${env:HOME}/.pico-sdk/cmake/v4.3.4/bin:${env:HOME}/.pico-sdk/ninja/v1.13.2:${env:PATH}" + }, + "raspberry-pi-pico.cmakeAutoConfigure": true, + "raspberry-pi-pico.useCmakeTools": false, + "raspberry-pi-pico.cmakePath": "${HOME}/.pico-sdk/cmake/v4.3.4/bin/cmake", + "raspberry-pi-pico.ninjaPath": "${HOME}/.pico-sdk/ninja/v1.13.2/ninja" +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..71e8b17 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,102 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Compile Project", + "type": "process", + "isBuildCommand": true, + "command": "${userHome}/.pico-sdk/ninja/v1.13.2/ninja", + "args": ["-C", "${workspaceFolder}/build"], + "group": "build", + "presentation": { + "reveal": "always", + "panel": "dedicated" + }, + "problemMatcher": "$gcc", + "windows": { + "command": "${env:USERPROFILE}/.pico-sdk/ninja/v1.13.2/ninja.exe" + } + }, + { + "label": "Run Project", + "type": "process", + "command": "${env:HOME}/.pico-sdk/picotool/2.3.0/picotool/picotool", + "args": [ + "load", + "${command:raspberry-pi-pico.launchTargetPath}", + "-fx" + ], + "presentation": { + "reveal": "always", + "panel": "dedicated" + }, + "problemMatcher": [], + "windows": { + "command": "${env:USERPROFILE}/.pico-sdk/picotool/2.3.0/picotool/picotool.exe" + } + }, + { + "label": "Flash", + "type": "process", + "command": "${userHome}/.pico-sdk/openocd/0.12.0+dev/openocd.exe", + "args": [ + "-s", + "${userHome}/.pico-sdk/openocd/0.12.0+dev/scripts", + "-f", + "raspberrypi-swd.cfg", + "-f", + "target/${command:raspberry-pi-pico.getTarget}.cfg", + "-c", + "adapter speed 5000; program \"${command:raspberry-pi-pico.launchTargetPath}\" verify reset exit" + ], + "problemMatcher": [], + "windows": { + "command": "${env:USERPROFILE}/.pico-sdk/openocd/0.12.0+dev/openocd.exe" + } + }, + { + "label": "Rescue Reset", + "type": "process", + "command": "${userHome}/.pico-sdk/openocd/0.12.0+dev/openocd.exe", + "args": [ + "-s", + "${userHome}/.pico-sdk/openocd/0.12.0+dev/scripts", + "-f", + "raspberrypi-swd.cfg", + "-f", + "target/${command:raspberry-pi-pico.getChip}-rescue.cfg", + "-c", + "adapter speed 5000; reset halt; exit" + ], + "problemMatcher": [], + "windows": { + "command": "${env:USERPROFILE}/.pico-sdk/openocd/0.12.0+dev/openocd.exe" + } + }, + { + "label": "RISC-V Reset (RP2350)", + "type": "process", + "command": "${userHome}/.pico-sdk/openocd/0.12.0+dev/openocd.exe", + "args": [ + "-s", + "${userHome}/.pico-sdk/openocd/0.12.0+dev/scripts", + "-c", + "set USE_CORE { rv0 rv1 cm0 cm1 }", + "-f", + "raspberrypi-swd.cfg", + "-f", + "target/rp2350.cfg", + "-c", + "adapter speed 5000; init;", + "-c", + "write_memory 0x40120158 8 { 0x3 }; echo [format \"Info : ARCHSEL 0x%02x\" [read_memory 0x40120158 8 1]];", + "-c", + "reset halt; targets rp2350.rv0; echo [format \"Info : ARCHSEL_STATUS 0x%02x\" [read_memory 0x4012015C 8 1]]; exit" + ], + "problemMatcher": [], + "windows": { + "command": "${env:USERPROFILE}/.pico-sdk/openocd/0.12.0+dev/openocd.exe" + } + } + ] +} diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..0c20d18 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,61 @@ +# Generated Cmake Pico project file + +cmake_minimum_required(VERSION 3.13) + +set(CMAKE_C_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +# Initialise pico_sdk from installed location +if(WIN32) + set(USERHOME $ENV{USERPROFILE}) +else() + set(USERHOME $ENV{HOME}) +endif() +set(sdkVersion 2.3.0) +set(toolchainVersion 15_2_Rel1) +set(picotoolVersion 2.3.0) +set(picoVscode ${USERHOME}/.pico-sdk/cmake/pico-vscode.cmake) +if (EXISTS ${picoVscode}) + include(${picoVscode}) +endif() + +set(PICO_BOARD pico2 CACHE STRING "Board type") + +# Pull in Raspberry Pi Pico SDK +include(pico_sdk_import.cmake) + +project(USB-Serial C CXX ASM) + +# Initialise the Raspberry Pi Pico SDK +pico_sdk_init() + +# Add executable +add_executable(USB-Serial + USB-Serial.cpp +) + +pico_set_program_name(USB-Serial "RP2350 USB-UART Adapter") +pico_set_program_version(USB-Serial "1.0") + +# Disable stdio over UART/USB so it doesn't conflict with custom CDC +pico_enable_stdio_uart(USB-Serial 0) +pico_enable_stdio_usb(USB-Serial 0) + +# Add libraries to the build +target_link_libraries(USB-Serial + pico_stdlib + tinyusb_device + tinyusb_board + hardware_uart + hardware_irq + pico_unique_id + pico_bootsel_via_double_reset +) + +# Add include directories +target_include_directories(USB-Serial PRIVATE + ${CMAKE_CURRENT_LIST_DIR} +) + +pico_add_extra_outputs(USB-Serial) diff --git a/USB-Serial.cpp b/USB-Serial.cpp new file mode 100644 index 0000000..7731cd2 --- /dev/null +++ b/USB-Serial.cpp @@ -0,0 +1,308 @@ +#include +#include +#include "pico/stdlib.h" +#include "pico/unique_id.h" +#include "hardware/uart.h" +#include "hardware/irq.h" +#include "hardware/gpio.h" +#include "hardware/clocks.h" +#include "tusb.h" + +//--------------------------------------------------------------------+ +// UART Configuration +//--------------------------------------------------------------------+ +#define UART_ID uart0 +#define UART_IRQ UART0_IRQ +#define UART_TX_PIN 0 +#define UART_RX_PIN 1 +#define DEFAULT_BAUD 115200 + +// Activity / Heartbeat LED Pin +#define LED_PIN_WS 16 +#define LED_PIN_PICO 25 + +// UART RX Ring Buffer for capture +#define BUFFER_SIZE 4096 + +static volatile struct { + uint8_t buf[BUFFER_SIZE]; + volatile uint32_t head; + volatile uint32_t tail; +} uart_rx_ring; + +static inline bool ring_is_empty(void) { + return uart_rx_ring.head == uart_rx_ring.tail; +} + +static inline void ring_push(uint8_t c) { + uint32_t next = (uart_rx_ring.head + 1) % BUFFER_SIZE; + if (next != uart_rx_ring.tail) { + uart_rx_ring.buf[uart_rx_ring.head] = c; + uart_rx_ring.head = next; + } +} + +static inline uint8_t ring_pop(void) { + uint8_t c = uart_rx_ring.buf[uart_rx_ring.tail]; + uart_rx_ring.tail = (uart_rx_ring.tail + 1) % BUFFER_SIZE; + return c; +} + +//--------------------------------------------------------------------+ +// UART Interrupt Handler +//--------------------------------------------------------------------+ +static void on_uart_rx(void) { + while (uart_is_readable(UART_ID)) { + uint8_t ch = (uint8_t)uart_getc(UART_ID); + ring_push(ch); + } +} + +//--------------------------------------------------------------------+ +// Hardware UART Setup +//--------------------------------------------------------------------+ +static void setup_uart(uint32_t baudrate) { + uart_init(UART_ID, baudrate); + gpio_set_function(UART_TX_PIN, GPIO_FUNC_UART); + gpio_set_function(UART_RX_PIN, GPIO_FUNC_UART); + gpio_pull_up(UART_RX_PIN); + + uart_set_hw_flow(UART_ID, false, false); + uart_set_format(UART_ID, 8, 1, UART_PARITY_NONE); + uart_set_fifo_enabled(UART_ID, true); + + // Set up and enable the interrupt handlers + irq_set_exclusive_handler(UART_IRQ, on_uart_rx); + irq_set_enabled(UART_IRQ, true); + + // Enable UART RX interrupt + uart_set_irq_enables(UART_ID, true, false); +} + +//--------------------------------------------------------------------+ +// USB Descriptors +//--------------------------------------------------------------------+ +#define USB_VID 0x2E8A // Raspberry Pi +#define USB_PID 0x000A // Raspberry Pi Pico CDC +#define USB_BCD 0x0200 + +tusb_desc_device_t const desc_device = { + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = USB_BCD, + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .idVendor = USB_VID, + .idProduct = USB_PID, + .bcdDevice = 0x0100, + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + .bNumConfigurations = 0x01 +}; + +extern "C" uint8_t const *tud_descriptor_device_cb(void) { + return (uint8_t const *) &desc_device; +} + +enum { + ITF_NUM_CDC = 0, + ITF_NUM_CDC_DATA, + ITF_NUM_TOTAL +}; + +#define EPNUM_CDC_NOTIF 0x81 +#define EPNUM_CDC_OUT 0x02 +#define EPNUM_CDC_IN 0x82 + +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN) + +uint8_t const desc_configuration[] = { + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), +}; + +extern "C" uint8_t const *tud_descriptor_configuration_cb(uint8_t index) { + (void) index; + return desc_configuration; +} + +enum { + STRID_LANGID = 0, + STRID_MANUFACTURER, + STRID_PRODUCT, + STRID_SERIAL, + STRID_CDC_INTERFACE, +}; + +static char const *string_desc_arr[] = { + (const char[]) { 0x09, 0x04 }, + "Waveshare", + "RP2350 USB-UART Adapter", + NULL, + "RP2350 CDC UART", +}; + +static uint16_t _desc_str[64]; + +extern "C" uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { + (void) langid; + size_t chr_count = 0; + + switch (index) { + case STRID_LANGID: + memcpy(&_desc_str[1], string_desc_arr[0], 2); + chr_count = 1; + break; + + case STRID_SERIAL: { + pico_unique_board_id_t id; + pico_get_unique_board_id(&id); + char serial_str[2 * PICO_UNIQUE_BOARD_ID_SIZE_BYTES + 1]; + pico_get_unique_board_id_string(serial_str, sizeof(serial_str)); + chr_count = strlen(serial_str); + if (chr_count > 32) chr_count = 32; + for (size_t i = 0; i < chr_count; i++) { + _desc_str[1 + i] = serial_str[i]; + } + break; + } + + default: { + if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) { + return NULL; + } + const char *str = string_desc_arr[index]; + if (!str) return NULL; + + chr_count = strlen(str); + size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; + if (chr_count > max_count) chr_count = max_count; + + for (size_t i = 0; i < chr_count; i++) { + _desc_str[1 + i] = str[i]; + } + break; + } + } + + _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2)); + return _desc_str; +} + +//--------------------------------------------------------------------+ +// TinyUSB CDC Callbacks +//--------------------------------------------------------------------+ + +extern "C" void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { + (void) itf; + (void) dtr; + (void) rts; +} + +extern "C" void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding) { + (void) itf; + + if (p_line_coding->bit_rate > 0) { + uart_set_baudrate(UART_ID, p_line_coding->bit_rate); + } + + uint data_bits = (p_line_coding->data_bits >= 5 && p_line_coding->data_bits <= 8) + ? p_line_coding->data_bits : 8; + + uint stop_bits = (p_line_coding->stop_bits == 2) ? 2 : 1; + + uart_parity_t parity = UART_PARITY_NONE; + if (p_line_coding->parity == 1) { + parity = UART_PARITY_ODD; + } else if (p_line_coding->parity == 2) { + parity = UART_PARITY_EVEN; + } + + uart_set_format(UART_ID, data_bits, stop_bits, parity); +} + +//--------------------------------------------------------------------+ +// Main Bridge Task +//--------------------------------------------------------------------+ +static void cdc_uart_bridge_task(void) { + // 1. Drain any available hardware UART RX bytes directly into ring buffer + while (uart_is_readable(UART_ID)) { + ring_push((uint8_t)uart_getc(UART_ID)); + } + + // 2. Forward UART RX -> USB CDC TX + if (!ring_is_empty()) { + uint32_t available = tud_cdc_write_available(); + if (available > 0) { + uint8_t tx_buf[64]; + uint32_t count = 0; + while (count < sizeof(tx_buf) && count < available && !ring_is_empty()) { + tx_buf[count++] = ring_pop(); + } + if (count > 0) { + tud_cdc_write(tx_buf, count); + tud_cdc_write_flush(); + } + } + } + + // 3. Forward USB CDC RX -> UART TX + if (tud_cdc_available()) { + uint8_t usb_rx_buf[64]; + uint32_t count = tud_cdc_read(usb_rx_buf, sizeof(usb_rx_buf)); + if (count > 0) { + uart_write_blocking(UART_ID, usb_rx_buf, count); + } + } +} + +//--------------------------------------------------------------------+ +// Main Entry +//--------------------------------------------------------------------+ +int main(void) { + stdio_init_all(); + + // Initialize Activity LED + gpio_init(LED_PIN_WS); + gpio_set_dir(LED_PIN_WS, GPIO_OUT); + gpio_put(LED_PIN_WS, 0); + + #ifdef LED_PIN_PICO + gpio_init(LED_PIN_PICO); + gpio_set_dir(LED_PIN_PICO, GPIO_OUT); + gpio_put(LED_PIN_PICO, 0); + #endif + + // Initialize UART0 on GP0 (TX) and GP1 (RX) + setup_uart(DEFAULT_BAUD); + + // Initialize TinyUSB Device stack + tusb_init(); + + uint32_t last_blink = 0; + bool led_state = false; + + while (true) { + // Process TinyUSB device events + tud_task(); + + // Process bidirectional data transfer + cdc_uart_bridge_task(); + + // Heartbeat blink (toggle every 250ms) + uint32_t now = to_ms_since_boot(get_absolute_time()); + if (now - last_blink >= 250) { + last_blink = now; + led_state = !led_state; + gpio_put(LED_PIN_WS, led_state); + #ifdef LED_PIN_PICO + gpio_put(LED_PIN_PICO, led_state); + #endif + } + } + + return 0; +} diff --git a/pico_sdk_import.cmake b/pico_sdk_import.cmake new file mode 100644 index 0000000..d493cc2 --- /dev/null +++ b/pico_sdk_import.cmake @@ -0,0 +1,121 @@ +# This is a copy of /external/pico_sdk_import.cmake + +# This can be dropped into an external project to help locate this SDK +# It should be include()ed prior to project() + +# Copyright 2020 (c) 2020 Raspberry Pi (Trading) Ltd. +# +# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +# following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +# disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH)) + set(PICO_SDK_PATH $ENV{PICO_SDK_PATH}) + message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')") +endif () + +if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT)) + set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT}) + message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')") +endif () + +if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH)) + set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH}) + message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')") +endif () + +if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_TAG} AND (NOT PICO_SDK_FETCH_FROM_GIT_TAG)) + set(PICO_SDK_FETCH_FROM_GIT_TAG $ENV{PICO_SDK_FETCH_FROM_GIT_TAG}) + message("Using PICO_SDK_FETCH_FROM_GIT_TAG from environment ('${PICO_SDK_FETCH_FROM_GIT_TAG}')") +endif () + +if (PICO_SDK_FETCH_FROM_GIT AND NOT PICO_SDK_FETCH_FROM_GIT_TAG) + set(PICO_SDK_FETCH_FROM_GIT_TAG "master") + message("Using master as default value for PICO_SDK_FETCH_FROM_GIT_TAG") +endif() + +set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK") +set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable") +set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK") +set(PICO_SDK_FETCH_FROM_GIT_TAG "${PICO_SDK_FETCH_FROM_GIT_TAG}" CACHE FILEPATH "release tag for SDK") + +if (NOT PICO_SDK_PATH) + if (PICO_SDK_FETCH_FROM_GIT) + include(FetchContent) + set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR}) + if (PICO_SDK_FETCH_FROM_GIT_PATH) + get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") + endif () + FetchContent_Declare( + pico_sdk + GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk + GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG} + ) + + if (NOT pico_sdk) + message("Downloading Raspberry Pi Pico SDK") + # GIT_SUBMODULES_RECURSE was added in 3.17 + if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0") + FetchContent_Populate( + pico_sdk + QUIET + GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk + GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG} + GIT_SUBMODULES_RECURSE FALSE + + SOURCE_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-src + BINARY_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-build + SUBBUILD_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-subbuild + ) + else () + FetchContent_Populate( + pico_sdk + QUIET + GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk + GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG} + + SOURCE_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-src + BINARY_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-build + SUBBUILD_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-subbuild + ) + endif () + + set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR}) + endif () + set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE}) + else () + message(FATAL_ERROR + "SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git." + ) + endif () +endif () + +get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") +if (NOT EXISTS ${PICO_SDK_PATH}) + message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found") +endif () + +set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake) +if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE}) + message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK") +endif () + +set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE) + +include(${PICO_SDK_INIT_CMAKE_FILE}) diff --git a/raspberrypi-swd.cfg b/raspberrypi-swd.cfg new file mode 100644 index 0000000..e8705e1 --- /dev/null +++ b/raspberrypi-swd.cfg @@ -0,0 +1,4 @@ +adapter driver linuxgpiod + +adapter gpio swdio -chip 0 24 +adapter gpio swclk -chip 0 25 diff --git a/tusb_config.h b/tusb_config.h new file mode 100644 index 0000000..a5fec56 --- /dev/null +++ b/tusb_config.h @@ -0,0 +1,71 @@ +#ifndef _TUSB_CONFIG_H_ +#define _TUSB_CONFIG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Board Specific Configuration +//--------------------------------------------------------------------+ +#ifndef BOARD_TUD_RHPORT +#define BOARD_TUD_RHPORT 0 +#endif + +#ifndef BOARD_TUD_MAX_SPEED +#define BOARD_TUD_MAX_SPEED OPT_MODE_DEFAULT_SPEED +#endif + +//-------------------------------------------------------------------- +// Common Configuration +//-------------------------------------------------------------------- +#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_FULL_SPEED) + +#ifndef CFG_TUSB_OS +#define CFG_TUSB_OS OPT_OS_NONE +#endif + +#ifndef CFG_TUSB_DEBUG +#define CFG_TUSB_DEBUG 0 +#endif + +// Enable Device stack +#define CFG_TUD_ENABLED 1 +#define CFG_TUD_MAX_SPEED BOARD_TUD_MAX_SPEED + +// USB DMA section / alignment +#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 configurations +#define CFG_TUD_CDC 1 +#define CFG_TUD_MSC 0 +#define CFG_TUD_HID 0 +#define CFG_TUD_MIDI 0 +#define CFG_TUD_VENDOR 0 + +// CDC FIFO size of TX and RX +#define CFG_TUD_CDC_RX_BUFSIZE 1024 +#define CFG_TUD_CDC_TX_BUFSIZE 1024 + +// CDC Endpoint transfer buffer size +#define CFG_TUD_CDC_EP_BUFSIZE 64 + +#ifdef __cplusplus +} +#endif + +#endif /* _TUSB_CONFIG_H_ */ + diff --git a/usb_descriptors.c b/usb_descriptors.c new file mode 100644 index 0000000..e69de29