diff --git a/src/machine/board_feather_rp2040.go b/src/machine/board_feather_rp2040.go index 98ecd1740..ad90043c1 100644 --- a/src/machine/board_feather_rp2040.go +++ b/src/machine/board_feather_rp2040.go @@ -60,3 +60,14 @@ const ( // Default Serial In Bus 1 for SPI communications SPI1_SDI_PIN = GPIO12 // Rx ) + +// USB CDC identifiers +const ( + usb_STRING_PRODUCT = "Adafruit Feather RP2040" + usb_STRING_MANUFACTURER = "Adafruit" +) + +var ( + usb_VID uint16 = 0x239A + usb_PID uint16 = 0x80F1 +) diff --git a/src/machine/board_pico.go b/src/machine/board_pico.go index b26395497..cff5eb20d 100644 --- a/src/machine/board_pico.go +++ b/src/machine/board_pico.go @@ -64,3 +64,14 @@ const ( // Default Serial In Bus 1 for SPI communications SPI1_SDI_PIN = GPIO12 // Rx ) + +// USB CDC identifiers +const ( + usb_STRING_PRODUCT = "Raspberry Pi Pico" + usb_STRING_MANUFACTURER = "Raspberry Pi" +) + +var ( + usb_VID uint16 = 0x2E8A + usb_PID uint16 = 0x0003 +) diff --git a/src/machine/machine_rp2040_usb.go b/src/machine/machine_rp2040_usb.go new file mode 100644 index 000000000..11c6b4921 --- /dev/null +++ b/src/machine/machine_rp2040_usb.go @@ -0,0 +1,523 @@ +//go:build rp2040 +// +build rp2040 + +package machine + +import ( + "device/arm" + "device/rp" + "runtime/interrupt" + "unsafe" +) + +const ( +// these are rp2040 specific. +) + +var ( + sendOnEP0DATADONE struct { + offset int + data []byte + pid uint32 + } +) + +// Configure the USB peripheral. The config is here for compatibility with the UART interface. +func (dev *USBDevice) Configure(config UARTConfig) { + //// Clear any previous state in dpram just in case + //memset(usb_dpram, 0, sizeof(*usb_dpram)); // <1> + usbDPSRAM.clear() + + //// Enable USB interrupt at processor + //irq_set_enabled(USBCTRL_IRQ, true); + rp.USBCTRL_REGS.INTE.Set(0) + intr := interrupt.New(rp.IRQ_USBCTRL_IRQ, handleUSBIRQ) + intr.SetPriority(0x00) + intr.Enable() + irqSet(rp.IRQ_USBCTRL_IRQ, true) + + //// Mux the controller to the onboard usb phy + //usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS; + rp.USBCTRL_REGS.USB_MUXING.Set(rp.USBCTRL_REGS_USB_MUXING_TO_PHY | rp.USBCTRL_REGS_USB_MUXING_SOFTCON) + + //// Force VBUS detect so the device thinks it is plugged into a host + //usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS; + rp.USBCTRL_REGS.USB_PWR.Set(rp.USBCTRL_REGS_USB_PWR_VBUS_DETECT | rp.USBCTRL_REGS_USB_PWR_VBUS_DETECT_OVERRIDE_EN) + + //// Enable the USB controller in device mode. + //usb_hw->main_ctrl = USB_MAIN_CTRL_CONTROLLER_EN_BITS; + rp.USBCTRL_REGS.MAIN_CTRL.Set(rp.USBCTRL_REGS_MAIN_CTRL_CONTROLLER_EN) + + //// Enable an interrupt per EP0 transaction + //usb_hw->sie_ctrl = USB_SIE_CTRL_EP0_INT_1BUF_BITS; // <2> + rp.USBCTRL_REGS.SIE_CTRL.Set(rp.USBCTRL_REGS_SIE_CTRL_EP0_INT_1BUF) + + //// Enable interrupts for when a buffer is done, when the bus is reset, + //// and when a setup packet is received + //usb_hw->inte = USB_INTS_BUFF_STATUS_BITS | + // USB_INTS_BUS_RESET_BITS | + // USB_INTS_SETUP_REQ_BITS; + rp.USBCTRL_REGS.INTE.Set(rp.USBCTRL_REGS_INTE_BUFF_STATUS | + rp.USBCTRL_REGS_INTE_BUS_RESET | + rp.USBCTRL_REGS_INTE_SETUP_REQ) + + //// Set up endpoints (endpoint control registers) + //// described by device configuration + //usb_setup_endpoints(); + // void usb_setup_endpoints() { + // const struct usb_endpoint_configuration *endpoints = dev_config.endpoints; + // for (int i = 0; i < USB_NUM_ENDPOINTS; i++) { + // if (endpoints[i].descriptor && endpoints[i].handler) { + // usb_setup_endpoint(&endpoints[i]); + // } + // } + // } + // + // void usb_setup_endpoint(const struct usb_endpoint_configuration *ep) { + // printf("Set up endpoint 0x%x with buffer address 0x%p\n", ep->descriptor->bEndpointAddress, ep->data_buffer); + // + // // EP0 doesn't have one so return if that is the case + // if (!ep->endpoint_control) { + // return; + // } + // + // // Get the data buffer as an offset of the USB controller's DPRAM + // uint32_t dpram_offset = usb_buffer_offset(ep->data_buffer); + // uint32_t reg = EP_CTRL_ENABLE_BITS + // | EP_CTRL_INTERRUPT_PER_BUFFER + // | (ep->descriptor->bmAttributes << EP_CTRL_BUFFER_TYPE_LSB) + // | dpram_offset; + // *ep->endpoint_control = reg; + // } + + //// Present full speed device by enabling pull up on DP + //usb_hw_set->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS; + rp.USBCTRL_REGS.SIE_CTRL.SetBits(rp.USBCTRL_REGS_SIE_CTRL_PULLUP_EN) + + // 追加 + val := uint32(0) + val |= 0x00000400 + usbDPSRAM.EP0OutBufferControl = USBBufferControlRegister(val) +} + +func handleUSBIRQ(intr interrupt.Interrupt) { + status := rp.USBCTRL_REGS.INTS.Get() + + // setup + //rp.USBCTRL_REGS.SIE_STATUS.Set(0xFFFFFFFF) + + //if false { + // // SOF + // x := rp.USBCTRL_REGS.SOF_RD.Get() + //} + + // void isr_usbctrl(void) { + // // USB interrupt handler + // uint32_t status = usb_hw->ints; + // uint32_t handled = 0; + + // // Setup packet received + // if (status & USB_INTS_SETUP_REQ_BITS) { + // handled |= USB_INTS_SETUP_REQ_BITS; + // usb_hw_clear->sie_status = USB_SIE_STATUS_SETUP_REC_BITS; + // usb_handle_setup_packet(); + // } + // /// \end::isr_setup_packet[] + if (status & rp.USBCTRL_REGS_INTS_SETUP_REQ) > 0 { + rp.USBCTRL_REGS.SIE_STATUS.Set(rp.USBCTRL_REGS_SIE_STATUS_SETUP_REC) + setup := newUSBSetup(usbDPSRAM.Setup[:]) + + ok := false + if (setup.BmRequestType & usb_REQUEST_TYPE) == usb_REQUEST_STANDARD { + // Standard Requests + ok = handleStandardSetup(setup) + } else { + // Class Interface Requests + if setup.WIndex < uint16(len(callbackUSBSetup)) && callbackUSBSetup[setup.WIndex] != nil { + ok = callbackUSBSetup[setup.WIndex](setup) + } + } + + if ok { + // set Bank1 ready + //setEPSTATUSSET(0, sam.USB_DEVICE_ENDPOINT_EPSTATUSSET_BK1RDY) + } else { + // Stall endpoint + //setEPSTATUSSET(0, sam.USB_DEVICE_ENDPOINT_EPINTFLAG_STALL1) + } + + //if getEPINTFLAG(0)&sam.USB_DEVICE_ENDPOINT_EPINTFLAG_STALL1 > 0 { + // // ack the stall + // setEPINTFLAG(0, sam.USB_DEVICE_ENDPOINT_EPINTFLAG_STALL1) + + // // clear stall request + // setEPINTENCLR(0, sam.USB_DEVICE_ENDPOINT_EPINTENCLR_STALL1) + //} + } + + // // Buffer status, one or more buffers have completed + // if (status & USB_INTS_BUFF_STATUS_BITS) { + // handled |= USB_INTS_BUFF_STATUS_BITS; + // usb_handle_buff_status(); + // } + if (status & rp.USBCTRL_REGS_INTS_BUFF_STATUS) > 0 { + if sendOnEP0DATADONE.offset > 0 { + ep := uint32(0) + data := sendOnEP0DATADONE.data + count := len(data) - sendOnEP0DATADONE.offset + if ep == 0 && count > usbEndpointPacketSize { + count = usbEndpointPacketSize + } + sendViaEPIn(ep, data[sendOnEP0DATADONE.offset:], count, 0) + sendOnEP0DATADONE.offset += count + if sendOnEP0DATADONE.offset == len(data) { + sendOnEP0DATADONE.offset = 0 + } + } + //s2 := rp.USBCTRL_REGS.BUFF_STATUS.Get() + //if (s2 & 0x00000001) > 0 { + // // EP0_IN + //} else if (s2 & 0x00000002) > 0 { + // // EP0_OUT + // //sendUSBPacket(0, []byte{}, 0) + //} + rp.USBCTRL_REGS.BUFF_STATUS.Set(0xFFFFFFFF) + } + + // // Bus is reset + // if (status & USB_INTS_BUS_RESET_BITS) { + // printf("BUS RESET\n"); + // handled |= USB_INTS_BUS_RESET_BITS; + // usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS; + // usb_bus_reset(); + // } + // void usb_bus_reset(void) { + // // Set address back to 0 + // dev_addr = 0; + // should_set_address = false; + // usb_hw->dev_addr_ctrl = 0; + // configured = false; + // } + if (status & rp.USBCTRL_REGS_INTS_BUS_RESET) > 0 { + rp.USBCTRL_REGS.SIE_STATUS.Set(rp.USBCTRL_REGS_SIE_STATUS_BUS_RESET) + } + + // + // if (status ^ handled) { + // panic("Unhandled IRQ 0x%x\n", (uint) (status ^ handled)); + // } + // } +} + +func initEndpoint(ep, config uint32) { + if ep == 0 { + return + } + + val := uint32(0x80000000) | uint32(0x20000000) + offset := (ep-1)*64 + 0x180 + val |= offset + + switch config { + case usb_ENDPOINT_TYPE_INTERRUPT | usbEndpointIn: + val |= 0x0C000000 + // ep1 in + usbDPSRAM.EP1InControl = USBEndpointControlRegister(val) + case usb_ENDPOINT_TYPE_BULK | usbEndpointOut: + val |= 0x08000000 + // ep2 out + usbDPSRAM.EP2OutControl = USBEndpointControlRegister(val) + case usb_ENDPOINT_TYPE_INTERRUPT | usbEndpointOut: + // TODO: not really anything, seems like... + + case usb_ENDPOINT_TYPE_BULK | usbEndpointIn: + val |= 0x08000000 + usbDPSRAM.EP3InControl = USBEndpointControlRegister(val) + // ep3 in + case usb_ENDPOINT_TYPE_CONTROL: + // skip + } +} + +func handleUSBSetAddress(setup USBSetup) bool { + // setup.BmRequestType, setup.BRequest, setup.WValueL, setup.WValueH, setup.WIndex, setup.WLength) + sendUSBPacket(0, []byte{}, 0) + + // last, set the device address to that requested by host + // wait for transfer to complete + timeout := 3000 + rp.USBCTRL_REGS.SIE_STATUS.Set(rp.USBCTRL_REGS_SIE_STATUS_ACK_REC) + for (rp.USBCTRL_REGS.SIE_STATUS.Get() & rp.USBCTRL_REGS_SIE_STATUS_ACK_REC) == 0 { + timeout-- + if timeout == 0 { + return true + } + } + + rp.USBCTRL_REGS.ADDR_ENDP.Set(uint32(setup.WValueL) & rp.USBCTRL_REGS_ADDR_ENDP_ADDRESS_Msk) + + return true +} + +// SendUSBInPacket sends a packet for USB (interrupt in / bulk in). +func SendUSBInPacket(ep uint32, data []byte) bool { + sendUSBPacket(ep, data, 0) + return true +} + +//go:noinline +func sendUSBPacket(ep uint32, data []byte, maxsize uint16) { + count := len(data) + if 0 < int(maxsize) && int(maxsize) < count { + count = int(maxsize) + } + + if ep == 0 { + if count > usbEndpointPacketSize { + count = usbEndpointPacketSize + + sendOnEP0DATADONE.offset = count + sendOnEP0DATADONE.data = data + } else { + sendOnEP0DATADONE.offset = 0 + } + } + + sendViaEPIn(ep, data, count, 1) +} + +func ReceiveUSBControlPacket() ([cdcLineInfoSize]byte, error) { + var b [cdcLineInfoSize]byte + return b, nil +} + +func handleEndpointRx(ep uint32) []byte { + return nil +} + +func SendZlp() { + sendUSBPacket(0, []byte{}, 0) +} + +var ep3data0 = true + +func sendViaEPIn(ep uint32, data []byte, count int, pid int) { + // void usb_start_transfer(struct usb_endpoint_configuration *ep, uint8_t *buf, uint16_t len) { + // // We are asserting that the length is <= 64 bytes for simplicity of the example. + // // For multi packet transfers see the tinyusb port. + // assert(len <= 64); + // + // printf("Start transfer of len %d on ep addr 0x%x\n", len, ep->descriptor->bEndpointAddress); + // + // // Prepare buffer control register value + // uint32_t val = len | USB_BUF_CTRL_AVAIL; + val := uint32(count) | 0x00000400 + + // if (ep_is_tx(ep)) { + // // Need to copy the data from the user buffer to the usb memory + // memcpy((void *) ep->data_buffer, (void *) buf, len); + // DATA0 or DATA1 + if ep == 3 { + if ep3data0 { + val |= 0x00002000 + } + ep3data0 = !ep3data0 + } else if pid == 1 { + val |= 0x00002000 + } + + // // Mark as full + // val |= USB_BUF_CTRL_FULL; + val |= 0x00008000 + + // } + // // Set pid and flip for next transfer + // val |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID; + // ep->next_pid ^= 1u; + // + // *ep->buffer_control = val; + switch ep & 0x7F { + case 0: + copy(usbDPSRAM.EP0Buffer0[:], data[:count]) + usbDPSRAM.EP0InBufferControl = USBBufferControlRegister(val) + case 1: + copy(usbDPSRAM.EP1Buffer[:], data[:count]) + usbDPSRAM.EP1InBufferControl = USBBufferControlRegister(val) + case 2: + usbDPSRAM.EP2OutBufferControl = USBBufferControlRegister(val) + case 3: + copy(usbDPSRAM.EP3Buffer[:], data[:count]) + usbDPSRAM.EP3InBufferControl = USBBufferControlRegister(val) + default: + } + + // } +} + +// ResetProcessor should perform a system reset in preparation +// to switch to the bootloader to flash new firmware. +func ResetProcessor() { + arm.DisableInterrupts() + + //// Perform magic reset into bootloader, as mentioned in + //// https://github.com/arduino/ArduinoCore-samd/issues/197 + //*(*uint32)(unsafe.Pointer(uintptr(0x20000000 + HSRAM_SIZE - 4))) = RESET_MAGIC_VALUE + + arm.SystemReset() +} + +type USBDPSRAM struct { + Setup [8]byte + + EP1InControl USBEndpointControlRegister // 0x0008 + EP1OutControl USBEndpointControlRegister // 0x000c + EP2InControl USBEndpointControlRegister // 0x0010 + EP2OutControl USBEndpointControlRegister // 0x0014 + EP3InControl USBEndpointControlRegister // 0x0018 + EP3OutControl USBEndpointControlRegister // 0x001c + EP4InControl USBEndpointControlRegister // 0x0020 + EP4OutControl USBEndpointControlRegister // 0x0024 + EP5InControl USBEndpointControlRegister // 0x0028 + EP5OutControl USBEndpointControlRegister // 0x002c + EP6InControl USBEndpointControlRegister // 0x0030 + EP6OutControl USBEndpointControlRegister // 0x0034 + EP7InControl USBEndpointControlRegister // 0x0038 + EP7OutControl USBEndpointControlRegister // 0x003c + EP8InControl USBEndpointControlRegister // 0x0040 + EP8OutControl USBEndpointControlRegister // 0x0044 + EP9InControl USBEndpointControlRegister // 0x0048 + EP9OutControl USBEndpointControlRegister // 0x004c + EP10InControl USBEndpointControlRegister // 0x0050 + EP10OutControl USBEndpointControlRegister // 0x0054 + EP11InControl USBEndpointControlRegister // 0x0058 + EP11OutControl USBEndpointControlRegister // 0x005c + EP12InControl USBEndpointControlRegister // 0x0060 + EP12OutControl USBEndpointControlRegister // 0x0064 + EP13InControl USBEndpointControlRegister // 0x0068 + EP13OutControl USBEndpointControlRegister // 0x006c + EP14InControl USBEndpointControlRegister // 0x0070 + EP14OutControl USBEndpointControlRegister // 0x0074 + EP15InControl USBEndpointControlRegister // 0x0078 + EP15OutControl USBEndpointControlRegister // 0x007c + + EP0InBufferControl USBBufferControlRegister // 0x0080 + EP0OutBufferControl USBBufferControlRegister // 0x0084 + EP1InBufferControl USBBufferControlRegister // 0x0088 + EP1OutBufferControl USBBufferControlRegister // 0x008c + EP2InBufferControl USBBufferControlRegister // 0x0090 + EP2OutBufferControl USBBufferControlRegister // 0x0094 + EP3InBufferControl USBBufferControlRegister // 0x0098 + EP3OutBufferControl USBBufferControlRegister // 0x009c + EP4InBufferControl USBBufferControlRegister // 0x00a0 + EP4OutBufferControl USBBufferControlRegister // 0x00a4 + EP5InBufferControl USBBufferControlRegister // 0x00a8 + EP5OutBufferControl USBBufferControlRegister // 0x00ac + EP6InBufferControl USBBufferControlRegister // 0x00b0 + EP6OutBufferControl USBBufferControlRegister // 0x00b4 + EP7InBufferControl USBBufferControlRegister // 0x00b8 + EP7OutBufferControl USBBufferControlRegister // 0x00bc + EP8InBufferControl USBBufferControlRegister // 0x00c0 + EP8OutBufferControl USBBufferControlRegister // 0x00c4 + EP9InBufferControl USBBufferControlRegister // 0x00c8 + EP9OutBufferControl USBBufferControlRegister // 0x00cc + EP10InBufferControl USBBufferControlRegister // 0x00d0 + EP10OutBufferControl USBBufferControlRegister // 0x00d4 + EP11InBufferControl USBBufferControlRegister // 0x00d8 + EP11OutBufferControl USBBufferControlRegister // 0x00dc + EP12InBufferControl USBBufferControlRegister // 0x00e0 + EP12OutBufferControl USBBufferControlRegister // 0x00e4 + EP13InBufferControl USBBufferControlRegister // 0x00e8 + EP13OutBufferControl USBBufferControlRegister // 0x00ec + EP14InBufferControl USBBufferControlRegister // 0x00f0 + EP14OutBufferControl USBBufferControlRegister // 0x00f4 + EP15InBufferControl USBBufferControlRegister // 0x00f8 + EP15OutBufferControl USBBufferControlRegister // 0x00fc + + // offset : 0x100 + EP0Buffer0 [64]byte + EP0Buffer1 [64]byte + + // offset : 0x180 .. + EP1Buffer [64]byte + EP2Buffer [64]byte + EP3Buffer [64]byte + EP4Buffer [64]byte + EP5Buffer [64]byte + EP6Buffer [64]byte + EP7Buffer [64]byte +} + +type USBEndpointControlRegister uint32 +type USBBufferControlRegister uint32 + +var usbDPSRAM = (*USBDPSRAM)(unsafe.Pointer(uintptr(0x50100000))) + +func (d *USBDPSRAM) clear() { + for i := range d.Setup { + d.Setup[i] = 0 + } + + d.EP1InControl = 0 + d.EP1OutControl = 0 + d.EP2InControl = 0 + d.EP2OutControl = 0 + d.EP3InControl = 0 + d.EP3OutControl = 0 + d.EP4InControl = 0 + d.EP4OutControl = 0 + d.EP5InControl = 0 + d.EP5OutControl = 0 + d.EP6InControl = 0 + d.EP6OutControl = 0 + d.EP7InControl = 0 + d.EP7OutControl = 0 + d.EP8InControl = 0 + d.EP8OutControl = 0 + d.EP9InControl = 0 + d.EP9OutControl = 0 + d.EP10InControl = 0 + d.EP10OutControl = 0 + d.EP11InControl = 0 + d.EP11OutControl = 0 + d.EP12InControl = 0 + d.EP12OutControl = 0 + d.EP13InControl = 0 + d.EP13OutControl = 0 + d.EP14InControl = 0 + d.EP14OutControl = 0 + d.EP15InControl = 0 + d.EP15OutControl = 0 + + d.EP0InBufferControl = 0 + d.EP0OutBufferControl = 0 + d.EP1InBufferControl = 0 + d.EP1OutBufferControl = 0 + d.EP2InBufferControl = 0 + d.EP2OutBufferControl = 0 + d.EP3InBufferControl = 0 + d.EP3OutBufferControl = 0 + d.EP4InBufferControl = 0 + d.EP4OutBufferControl = 0 + d.EP5InBufferControl = 0 + d.EP5OutBufferControl = 0 + d.EP6InBufferControl = 0 + d.EP6OutBufferControl = 0 + d.EP7InBufferControl = 0 + d.EP7OutBufferControl = 0 + d.EP8InBufferControl = 0 + d.EP8OutBufferControl = 0 + d.EP9InBufferControl = 0 + d.EP9OutBufferControl = 0 + d.EP10InBufferControl = 0 + d.EP10OutBufferControl = 0 + d.EP11InBufferControl = 0 + d.EP11OutBufferControl = 0 + d.EP12InBufferControl = 0 + d.EP12OutBufferControl = 0 + d.EP13InBufferControl = 0 + d.EP13OutBufferControl = 0 + d.EP14InBufferControl = 0 + d.EP14OutBufferControl = 0 + d.EP15InBufferControl = 0 + d.EP15OutBufferControl = 0 +} diff --git a/src/machine/usb.go b/src/machine/usb.go index 938123d4f..ae3de5889 100644 --- a/src/machine/usb.go +++ b/src/machine/usb.go @@ -1,5 +1,5 @@ -//go:build sam || nrf52840 -// +build sam nrf52840 +//go:build sam || nrf52840 || rp2040 +// +build sam nrf52840 rp2040 package machine diff --git a/src/machine/usb_descriptor.go b/src/machine/usb_descriptor.go index c6d7ca36f..744d87039 100644 --- a/src/machine/usb_descriptor.go +++ b/src/machine/usb_descriptor.go @@ -1,5 +1,5 @@ -//go:build sam || nrf52840 -// +build sam nrf52840 +//go:build sam || nrf52840 || rp2040 +// +build sam nrf52840 rp2040 package machine diff --git a/src/runtime/runtime_rp2040.go b/src/runtime/runtime_rp2040.go index c6bc0d792..d82534b57 100644 --- a/src/runtime/runtime_rp2040.go +++ b/src/runtime/runtime_rp2040.go @@ -5,8 +5,8 @@ package runtime import ( "device/arm" - "machine" + "machine/usb/cdc" ) // machineTicks is provided by package machine. @@ -76,6 +76,8 @@ func machineInit() func init() { machineInit() + cdc.EnableUSBCDC() + machine.USB.Configure(machine.UARTConfig{}) machine.Serial.Configure(machine.UARTConfig{}) } diff --git a/targets/feather-rp2040.json b/targets/feather-rp2040.json index 955c2a887..4a795faac 100644 --- a/targets/feather-rp2040.json +++ b/targets/feather-rp2040.json @@ -2,7 +2,7 @@ "inherits": [ "rp2040" ], - "serial": "uart", + "serial-port": ["acm:239a:80f1"], "build-tags": ["feather_rp2040"], "linkerscript": "targets/feather-rp2040.ld", "extra-files": [ diff --git a/targets/pico.json b/targets/pico.json index 36e3ba30e..1cac41ee5 100644 --- a/targets/pico.json +++ b/targets/pico.json @@ -3,6 +3,7 @@ "rp2040" ], "build-tags": ["pico"], + "serial-port": ["acm:2e8a:0003"], "serial": "uart", "linkerscript": "targets/pico.ld", "extra-files": [