Fix for USB host (#1404)

Fixes the USB host not working by reverting the tinyusb and pico-pio-usb libraries to jfedor's branch. There are several issues that make these libraries not work in SDK 2.1.1, but jfedor's dev branch on pico-pio-usb fixes the issues we were having.

I2C breaks on web config in this build, but I will be investigating i2c hal implementation which reverts some of the i2c functionality. If that works, we can add that as a patch as well.
This commit is contained in:
Luke A
2025-06-22 15:52:04 -04:00
committed by GitHub
parent 0241324b8b
commit 28377cf7ae
14 changed files with 48 additions and 27 deletions

8
.gitmodules vendored
View File

@@ -1,6 +1,6 @@
[submodule "lib/pico_pio_usb"]
path = lib/pico_pio_usb
url = https://github.com/sekigon-gonnoc/Pico-PIO-USB
[submodule "lib/tinyusb"]
path = lib/tinyusb
url = https://github.com/hathach/tinyusb/
url = https://github.com/jfedor2/tinyusb.git
[submodule "lib/pico_pio_usb"]
path = lib/pico_pio_usb
url = https://github.com/jfedor2/Pico-PIO-USB.git

View File

@@ -153,7 +153,7 @@
// max device support (excluding hub device)
#define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 4 : 1) // hub typically has 4 ports
#define CFG_TUH_HID 4
#define CFG_TUH_HID 4
#define CFG_TUH_HID_EPIN_BUFSIZE 64
#define CFG_TUH_HID_EPOUT_BUFSIZE 64

View File

@@ -34,11 +34,11 @@ void NeoPico::PutPixel(uint32_t pixelData) {
}
}
void NeoPico::Setup(int ledPin, int inNumPixels, LEDFormat inFormat, PIO inPio){
void NeoPico::Setup(int ledPin, int inNumPixels, LEDFormat inFormat, PIO inPio, int inState){
format = inFormat;
pio = inPio;
numPixels = inNumPixels;
stateMachine = 0;
stateMachine = inState;
uint offset = pio_add_program(pio, &ws2812_program);
bool rgbw = (format == LED_FORMAT_GRBW) || (format == LED_FORMAT_RGBW);
ws2812_program_init(pio, stateMachine, offset, ledPin, 800000, rgbw);

View File

@@ -16,7 +16,7 @@ class NeoPico
{
public:
NeoPico();
void Setup(int ledPin, int inNumPixels, LEDFormat inFormat, PIO inPio);
void Setup(int ledPin, int inNumPixels, LEDFormat inFormat, PIO inPio, int inState);
void Show();
void Clear();
void Off();

View File

@@ -1,7 +1,14 @@
add_library(PicoPeripherals peripheral_i2c.cpp peripheral_spi.cpp peripheral_usb.cpp)
add_library(PicoPeripherals
interval_override.cpp
peripheral_i2c.cpp
peripheral_spi.cpp
peripheral_usb.cpp
)
target_include_directories(PicoPeripherals PRIVATE .)
target_include_directories(PicoPeripherals INTERFACE .)
target_link_libraries(PicoPeripherals
pico_stdlib
hardware_dma
hardware_gpio
hardware_i2c
hardware_spi

View File

@@ -0,0 +1,3 @@
#include "interval_override.h"
volatile uint8_t interval_override = 0;

View File

@@ -0,0 +1,8 @@
#ifndef _INTERVAL_OVERRIDE_H_
#define _INTERVAL_OVERRIDE_H_
#include <stdint.h>
extern volatile uint8_t interval_override;
#endif

View File

@@ -89,7 +89,11 @@ int16_t PeripheralI2C::write(uint8_t address, uint8_t *data, uint16_t len, bool
uint8_t PeripheralI2C::test(uint8_t address) {
uint8_t data;
int16_t ret = i2c_read_blocking(_I2C, address, &data, 1, false);
// TODO: Revert to i2c_read_blocking when we have I2C resolved
// int16_t ret = i2c_read_blocking(_I2C, address, &data, 1, false);
absolute_time_t test_timeout = make_timeout_time_ms(100);
int16_t ret = i2c_read_blocking_until(_I2C, address, &data, 1, false, test_timeout);
return (ret >= 0);
}

View File

@@ -29,5 +29,7 @@ void PeripheralUSB::setup() {
pio_cfg.pin_dp = _DP;
pio_cfg.pinout = (_Order == 0 ? PIO_USB_PINOUT_DPDM : PIO_USB_PINOUT_DMDP);
pio_cfg.sm_tx = 1; // Move TX to PIO0:1, NeoPico is in PIO0:0
// RX and EOP are PIO1:0, PIO1:1
}
}

View File

@@ -250,7 +250,7 @@ void NeoPicoLEDAddon::setup() {
}
// Setup NeoPico ws2812 PIO
neopico.Setup(ledOptions.dataPin, ledCount, static_cast<LEDFormat>(ledOptions.ledFormat), pio1);
neopico.Setup(ledOptions.dataPin, ledCount, static_cast<LEDFormat>(ledOptions.ledFormat), pio0, 0);
neopico.Off(); // turn off everything
// Rewrite this

View File

@@ -51,15 +51,16 @@ static absolute_time_t rebootDelayTimeout = nil_time;
void GP2040::setup() {
Storage::getInstance().init();
PeripheralManager::getInstance().initI2C();
PeripheralManager::getInstance().initSPI();
PeripheralManager::getInstance().initUSB();
// Reduce CPU if USB host is enabled
PeripheralManager::getInstance().initUSB();
if ( PeripheralManager::getInstance().isUSBEnabled(0) ) {
set_sys_clock_khz(120000, true); // Set Clock to 120MHz to avoid potential USB timing issues
}
// I2C & SPI rely on the system clock
PeripheralManager::getInstance().initSPI();
PeripheralManager::getInstance().initI2C();
Gamepad * gamepad = new Gamepad();
Gamepad * processedGamepad = new Gamepad();
Storage::getInstance().SetGamepad(gamepad);
@@ -268,6 +269,9 @@ void GP2040::run() {
// Start the TinyUSB Device functionality
tud_init(TUD_OPT_RHPORT);
// Initialize our USB manager
USBHostManager::getInstance().start();
while (1) { // LOOP
this->getReinitGamepad(gamepad);
@@ -280,6 +284,9 @@ void GP2040::run() {
checkRawState(prevState, gamepad->state);
// Process USB Host on Core0
USBHostManager::getInstance().process();
// Config Loop (Web-Config skips Core0 add-ons)
if (configMode == true) {
inputDriver->process(gamepad);
@@ -288,9 +295,6 @@ void GP2040::run() {
continue;
}
// Process USB Host on Core0
USBHostManager::getInstance().process();
// Pre-Process add-ons for MPGS
addons.PreprocessAddons();

View File

@@ -25,10 +25,6 @@ GP2040Aux::~GP2040Aux() {
// GP2040Aux will always come after GP2040 setup(), so we can rely on the
// GP2040 setup function for certain setup functions.
void GP2040Aux::setup() {
PeripheralManager::getInstance().initI2C();
PeripheralManager::getInstance().initSPI();
PeripheralManager::getInstance().initUSB();
// Initialize our input driver's auxilliary functions
inputDriver = DriverManager::getInstance().getDriver();
if ( inputDriver != nullptr ) {
@@ -50,9 +46,6 @@ void GP2040Aux::setup() {
addons.LoadAddon(new DRV8833RumbleAddon());
addons.LoadAddon(new ReactiveLEDAddon());
// Initialize our USB manager
USBHostManager::getInstance().start();
// Ready to sync Core0 and Core1
isReady = true;
}