From 68b5ad11332bb2705f31e359cf19b6fc92986d62 Mon Sep 17 00:00:00 2001 From: patryk4815 Date: Tue, 28 Jan 2025 21:18:48 +0100 Subject: [PATCH] Fix usb_cdc on rp2350 (#367) * Fix usb_cdc on rp2350 * Fix usb-cdc readme * Fix usb-cdc readme --- examples/raspberrypi/rp2xxx/README.md | 4 +- examples/raspberrypi/rp2xxx/build.zig | 2 +- .../rp2xxx/src/{rp2040_only => }/usb_cdc.zig | 0 port/raspberrypi/rp2xxx/build.zig | 1 + port/raspberrypi/rp2xxx/patches/rp2350.zig | 47 +++++++++++++++++ port/raspberrypi/rp2xxx/src/hal/rom.zig | 52 +++++++++++++++---- port/raspberrypi/rp2xxx/src/hal/usb.zig | 4 +- 7 files changed, 96 insertions(+), 14 deletions(-) rename examples/raspberrypi/rp2xxx/src/{rp2040_only => }/usb_cdc.zig (100%) create mode 100644 port/raspberrypi/rp2xxx/patches/rp2350.zig diff --git a/examples/raspberrypi/rp2xxx/README.md b/examples/raspberrypi/rp2xxx/README.md index ae27c8f2c..a52f4dc68 100644 --- a/examples/raspberrypi/rp2xxx/README.md +++ b/examples/raspberrypi/rp2xxx/README.md @@ -21,6 +21,8 @@ examples will eventually be able to run on either chip with no changes due to th Routes the SYS clock divided by 1000 out to GPIO25. - [watchdog timer](src/watchdog_timer.zig) on the [Pico](https://www.raspberrypi.com/products/raspberry-pi-pico/) or [Pico2](https://www.raspberrypi.com/products/raspberry-pi-pico-2/) boards Enables a watchdog timer for 1 second, and demonstrates the chip resetting when the watchdog timer elapses +- [usb device](src/usb_cdc.zig) on the [Pico](https://www.raspberrypi.com/products/raspberry-pi-pico/) or [Pico2](https://www.raspberrypi.com/products/raspberry-pi-pico-2/) boards + A really basic example for a raw USB device. You can use the Python 3 script [`scripts/usb_device_loopback.py`](scripts/usb_device_loopback.py) to test the USB device. ### RP2040 Only @@ -42,8 +44,6 @@ examples will eventually be able to run on either chip with no changes due to th Showcases how to use the PIO to emit a basic square wave. - [uart](src/rp2040_only/uart.zig) on the [Pico](https://www.raspberrypi.com/products/raspberry-pi-pico/) board Showcases how to use the UART together with `std.log`. -- [usb device](src/rp2040_only/usb_cdc.zig) on the [Pico](https://www.raspberrypi.com/products/raspberry-pi-pico/) board - A really basic example for a raw USB device. You can use the Python 3 script [`scripts/usb_device_loopback.py`](scripts/usb_device_loopback.py) to test the USB device. - [usb hid](src/rp2040_only/usb_hid.zig) on the [Pico](https://www.raspberrypi.com/products/raspberry-pi-pico/) board A really basic example how to implement a USB HID device. You can use the Python 3 script [`scripts/hid_test.py`](scripts/hid_test.py) to test the HID device. - [ws2812](src/ws2812.zig) on the [Pico](https://www.raspberrypi.com/products/raspberry-pi-pico/) board diff --git a/examples/raspberrypi/rp2xxx/build.zig b/examples/raspberrypi/rp2xxx/build.zig index b2a69c564..b35685669 100644 --- a/examples/raspberrypi/rp2xxx/build.zig +++ b/examples/raspberrypi/rp2xxx/build.zig @@ -24,7 +24,6 @@ pub fn build(b: *std.Build) void { .{ .target = mb.ports.rp2xxx.boards.raspberrypi.pico, .name = "pico_uart-echo", .file = "src/rp2040_only/uart_echo.zig" }, .{ .target = mb.ports.rp2xxx.boards.raspberrypi.pico, .name = "pico_uart-log", .file = "src/rp2040_only/uart_log.zig" }, .{ .target = mb.ports.rp2xxx.boards.raspberrypi.pico, .name = "pico_usb-hid", .file = "src/rp2040_only/usb_hid.zig" }, - .{ .target = mb.ports.rp2xxx.boards.raspberrypi.pico, .name = "pico_usb-cdc", .file = "src/rp2040_only/usb_cdc.zig" }, .{ .target = mb.ports.rp2xxx.boards.raspberrypi.pico, .name = "pico_multicore", .file = "src/rp2040_only/blinky_core1.zig" }, .{ .target = mb.ports.rp2xxx.boards.raspberrypi.pico, .name = "pico_hd44780", .file = "src/rp2040_only/hd44780.zig" }, .{ .target = mb.ports.rp2xxx.boards.raspberrypi.pico, .name = "pico_pcf8574", .file = "src/rp2040_only/pcf8574.zig" }, @@ -49,6 +48,7 @@ pub fn build(b: *std.Build) void { .{ .name = "custom-clock-config", .file = "src/custom_clock_config.zig" }, .{ .name = "watchdog-timer", .file = "src/watchdog_timer.zig" }, .{ .name = "pico_stepper", .file = "src/stepper.zig" }, + .{ .name = "pico_usb-cdc", .file = "src/usb_cdc.zig" }, }; var available_examples = std.ArrayList(Example).init(b.allocator); diff --git a/examples/raspberrypi/rp2xxx/src/rp2040_only/usb_cdc.zig b/examples/raspberrypi/rp2xxx/src/usb_cdc.zig similarity index 100% rename from examples/raspberrypi/rp2xxx/src/rp2040_only/usb_cdc.zig rename to examples/raspberrypi/rp2xxx/src/usb_cdc.zig diff --git a/port/raspberrypi/rp2xxx/build.zig b/port/raspberrypi/rp2xxx/build.zig index 936a61007..fd39dd5ee 100644 --- a/port/raspberrypi/rp2xxx/build.zig +++ b/port/raspberrypi/rp2xxx/build.zig @@ -69,6 +69,7 @@ pub fn init(dep: *std.Build.Dependency) Self { .{ .kind = .flash, .offset = 0x10000000, .length = 2048 * 1024 }, .{ .kind = .ram, .offset = 0x20000000, .length = 256 * 1024 }, }, + .patches = @import("patches/rp2350.zig").patches, }, .hal = hal, .linker_script = b.path("rp2350_arm.ld"), diff --git a/port/raspberrypi/rp2xxx/patches/rp2350.zig b/port/raspberrypi/rp2xxx/patches/rp2350.zig new file mode 100644 index 000000000..ae3f66efa --- /dev/null +++ b/port/raspberrypi/rp2xxx/patches/rp2350.zig @@ -0,0 +1,47 @@ +pub const patches = &.{ + .{ + .add_enum = .{ + .parent = "types.peripherals.USB_DPRAM", + .@"enum" = .{ + .name = "EndpointType", + .bitsize = 2, + .fields = &.{ + .{ .value = 0x0, .name = "control" }, + .{ .value = 0x1, .name = "isochronous" }, + .{ .value = 0x2, .name = "bulk" }, + .{ .value = 0x3, .name = "interrupt" }, + }, + }, + }, + }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP1_IN_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP1_OUT_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP2_IN_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP2_OUT_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP3_IN_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP3_OUT_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP4_IN_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP4_OUT_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP5_IN_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP5_OUT_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP6_IN_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP6_OUT_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP7_IN_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP7_OUT_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP8_IN_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP8_OUT_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP9_IN_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP9_OUT_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP10_IN_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP10_OUT_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP11_IN_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP11_OUT_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP12_IN_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP12_OUT_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP13_IN_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP13_OUT_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP14_IN_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP14_OUT_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP15_IN_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, + .{ .set_enum_type = .{ .of = "types.peripherals.USB_DPRAM.EP15_OUT_CONTROL.ENDPOINT_TYPE", .to = "types.peripherals.USB_DPRAM.EndpointType" } }, +}; diff --git a/port/raspberrypi/rp2xxx/src/hal/rom.zig b/port/raspberrypi/rp2xxx/src/hal/rom.zig index a3980741c..b3e012b43 100644 --- a/port/raspberrypi/rp2xxx/src/hal/rom.zig +++ b/port/raspberrypi/rp2xxx/src/hal/rom.zig @@ -11,17 +11,20 @@ //! 4. Debugging Support Functions (TODO) //! 5. Miscellaneous Functions (TODO) +const std = @import("std"); +const microzig = @import("microzig"); +const chip = microzig.hal.compatibility.chip; + /// Function codes to lookup public functions that provide useful RP2040 functionality pub const Code = enum(u32) { - popcount32 = rom_table_code('P', '3'), - reverse32 = rom_table_code('R', '3'), - clz32 = rom_table_code('L', '3'), - ctz32 = rom_table_code('T', '3'), - memset = rom_table_code('M', 'S'), - memset4 = rom_table_code('S', '4'), - memcpy = rom_table_code('M', 'C'), - memcpy44 = rom_table_code('C', '4'), - reset_usb_boot = rom_table_code('U', 'B'), + popcount32 = rom_table_code('P', '3'), // Only avaiable on: RP2040 + reverse32 = rom_table_code('R', '3'), // Only avaiable on: RP2040 + clz32 = rom_table_code('L', '3'), // Only avaiable on: RP2040 + ctz32 = rom_table_code('T', '3'), // Only avaiable on: RP2040 + memset = rom_table_code('M', 'S'), // Only avaiable on: RP2040 + memset4 = rom_table_code('S', '4'), // Only avaiable on: RP2040 + memcpy = rom_table_code('M', 'C'), // Only avaiable on: RP2040 + memcpy44 = rom_table_code('C', '4'), // Only avaiable on: RP2040 connect_internal_flash = rom_table_code('I', 'F'), flash_exit_xip = rom_table_code('E', 'X'), flash_range_erase = rom_table_code('R', 'E'), @@ -136,6 +139,11 @@ pub fn rom_func_lookup(code: Code) *anyopaque { /// Return a count of the number of 1 bits in value pub fn popcount32(value: u32) u32 { + if (chip == .RP2350) { + // RP2350, supports fast assembly version + return @popCount(value); + } + const S = struct { var f: ?*signatures.popcount32 = null; }; @@ -146,6 +154,11 @@ pub fn popcount32(value: u32) u32 { /// Return a count of the number of 1 bits in value pub fn reverse32(value: u32) u32 { + if (chip == .RP2350) { + // RP2350, supports fast assembly version + return @bitReverse(value); + } + const S = struct { var f: ?*signatures.reverse32 = null; }; @@ -156,6 +169,11 @@ pub fn reverse32(value: u32) u32 { /// Return the number of consecutive high order 0 bits of value pub fn clz32(value: u32) u32 { + if (chip == .RP2350) { + // RP2350, supports fast assembly version + return @clz(value); + } + const S = struct { var f: ?*signatures.clz32 = null; }; @@ -166,6 +184,11 @@ pub fn clz32(value: u32) u32 { /// Return the number of consecutive low order 0 bits of value pub fn ctz32(value: u32) u32 { + if (chip == .RP2350) { + // RP2350, supports fast assembly version + return @ctz(value); + } + const S = struct { var f: ?*signatures.ctz32 = null; }; @@ -180,6 +203,11 @@ pub fn ctz32(value: u32) u32 { /// Sets all bytes of dest to the value c and returns ptr pub fn memset(dest: []u8, c: u8) []u8 { + if (chip == .RP2350) { + @memset(dest, c); + return dest; + } + const S = struct { var f: ?*signatures.memset = null; }; @@ -190,6 +218,12 @@ pub fn memset(dest: []u8, c: u8) []u8 { /// Copies n bytes from src to dest; The number of bytes copied is the size of the smaller slice pub fn memcpy(dest: []u8, src: []const u8) []u8 { + if (chip == .RP2350) { + // For some reason @memcpy crash chip with HardFault interrupt (UNALIGNED) + std.mem.copyForwards(u8, dest, src); + return dest; + } + const S = struct { var f: ?*signatures.memcpy = null; }; diff --git a/port/raspberrypi/rp2xxx/src/hal/usb.zig b/port/raspberrypi/rp2xxx/src/hal/usb.zig index 02412bfed..fd5b3e925 100644 --- a/port/raspberrypi/rp2xxx/src/hal/usb.zig +++ b/port/raspberrypi/rp2xxx/src/hal/usb.zig @@ -360,8 +360,8 @@ pub fn F(comptime config: UsbConfig) type { var setup_packet: [8]u8 = .{0} ** 8; const spl: u32 = peripherals.USB_DPRAM.SETUP_PACKET_LOW.raw; const sph: u32 = peripherals.USB_DPRAM.SETUP_PACKET_HIGH.raw; - _ = rom.memcpy(setup_packet[0..4], std.mem.asBytes(&spl)); - _ = rom.memcpy(setup_packet[4..8], std.mem.asBytes(&sph)); + @memcpy(setup_packet[0..4], std.mem.asBytes(&spl)); + @memcpy(setup_packet[4..8], std.mem.asBytes(&sph)); // Reinterpret as setup packet return std.mem.bytesToValue(usb.types.SetupPacket, &setup_packet); }