Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix usb_cdc on rp2350 #367

Merged
merged 3 commits into from
Jan 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/raspberrypi/rp2xxx/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion examples/raspberrypi/rp2xxx/build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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" },
Expand All @@ -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);
Expand Down
1 change: 1 addition & 0 deletions port/raspberrypi/rp2xxx/build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down
47 changes: 47 additions & 0 deletions port/raspberrypi/rp2xxx/patches/rp2350.zig
Original file line number Diff line number Diff line change
@@ -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" } },
};
52 changes: 43 additions & 9 deletions port/raspberrypi/rp2xxx/src/hal/rom.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
Expand Down Expand Up @@ -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;
};
Expand All @@ -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;
};
Expand All @@ -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;
};
Expand All @@ -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;
};
Expand All @@ -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;
};
Expand All @@ -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;
};
Expand Down
4 changes: 2 additions & 2 deletions port/raspberrypi/rp2xxx/src/hal/usb.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
Loading