-
Notifications
You must be signed in to change notification settings - Fork 165
ch32 USBHD/USBHS driver implementation #893
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
base: main
Are you sure you want to change the base?
Changes from all commits
d272589
3e3b6de
b587b46
a653711
9504866
52ea727
b655989
503c998
93ce596
f210076
942aa42
340d9c3
9eabcab
870f0d6
2a79c78
f553d34
27edab3
2ed6b4d
cd4e348
0959d37
36f02ea
b7bed05
93cbc87
55921cc
f373714
bbe968f
baee980
ae7d203
a6e8c89
66f0116
f07fe5c
c40f907
b9f61f5
8dd3a7b
4c399ef
3f494d0
5079a5b
6474eab
4e00819
94c4e64
32feeb7
5fff85c
efefeae
6f6ba02
c233851
872e794
52396d6
aa8034d
7667ea7
1a1aab8
6c89d64
64d16ce
e8c6a40
8f4fdcc
d36e85c
a3673d8
321c317
59450b4
07bfc32
2bbaf5b
66e9c32
00fe33b
2011590
9865fe3
985d6e8
c337146
baed799
df4e181
dc8ec01
ad686c3
fce6646
8a0e752
57f498f
8b9704c
0049e03
01624dc
19cc7f3
493c041
02ce566
349fb6a
e0cef46
0717b51
b9892ab
0a2bde0
e322393
026395f
a4927cc
0480805
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -36,7 +36,9 @@ pub fn build(b: *std.Build) void { | |
| .{ .target = mb.ports.ch32v.chips.ch32v203x6, .name = "blinky_ch32v203", .file = "src/blinky.zig" }, | ||
| .{ .target = mb.ports.ch32v.chips.ch32v203x6, .name = "blinky_systick_ch32v203", .file = "src/blinky_systick.zig" }, | ||
| .{ .target = mb.ports.ch32v.boards.ch32v203.nano_ch32v203, .name = "nano_ch32v203_blinky", .file = "src/board_blinky.zig" }, | ||
| .{ .target = mb.ports.ch32v.boards.ch32v203.nano_ch32v203, .name = "nano_ch32v203_usb_cdc", .file = "src/usb_cdc.zig" }, | ||
| .{ .target = mb.ports.ch32v.boards.ch32v203.suzuduino_uno_v1b, .name = "suzuduino_blinky", .file = "src/board_blinky.zig" }, | ||
| .{ .target = mb.ports.ch32v.boards.ch32v203.suzuduino_uno_v1b, .name = "suzuduino_usb_cdc", .file = "src/usb_cdc.zig" }, | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this one tested? |
||
| .{ .target = mb.ports.ch32v.boards.ch32v203.lana_tny, .name = "lana_tny_dma", .file = "src/dma.zig" }, | ||
| .{ .target = mb.ports.ch32v.boards.ch32v203.lana_tny, .name = "lana_tny_ws2812", .file = "src/ws2812.zig" }, | ||
| .{ .target = mb.ports.ch32v.boards.ch32v203.lana_tny, .name = "lana_tny_uart_log", .file = "src/uart_log.zig" }, | ||
|
|
@@ -46,13 +48,15 @@ pub fn build(b: *std.Build) void { | |
| .{ .target = mb.ports.ch32v.boards.ch32v203.lana_tny, .name = "lana_tny_spi_loopback", .file = "src/spi_loopback.zig" }, | ||
| .{ .target = mb.ports.ch32v.boards.ch32v203.lana_tny, .name = "lana_tny_spi_flash_w25q", .file = "src/spi_flash_w25q.zig" }, | ||
| .{ .target = mb.ports.ch32v.boards.ch32v203.lana_tny, .name = "lana_tny_sharp_niceview", .file = "src/sharp_niceview.zig" }, | ||
| .{ .target = mb.ports.ch32v.boards.ch32v203.lana_tny, .name = "lana_tny_usb_cdc", .file = "src/usb_cdc.zig" }, | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and this one? I have this so I can test it for you. |
||
|
|
||
| // CH32V30x | ||
| .{ .target = mb.ports.ch32v.chips.ch32v303xb, .name = "empty_ch32v303", .file = "src/empty.zig" }, | ||
| .{ .target = mb.ports.ch32v.chips.ch32v303xb, .name = "blinky_ch32v303", .file = "src/blinky.zig" }, | ||
| .{ .target = mb.ports.ch32v.chips.ch32v303xb, .name = "blinky_systick_ch32v303", .file = "src/blinky_systick.zig" }, | ||
| .{ .target = mb.ports.ch32v.boards.ch32v305.nano_ch32v305, .name = "nano_ch32v305_blinky", .file = "src/board_blinky.zig" }, | ||
| .{ .target = mb.ports.ch32v.boards.ch32v307.ch32v307v_r1_1v0, .name = "ch32v307v_r1_1v0_blinky", .file = "src/blinky.zig" }, | ||
| .{ .target = mb.ports.ch32v.boards.ch32v307.ch32v307v_r1_1v0, .name = "ch32v307v_r1_1v0_usb_cdc", .file = "src/usb_cdc.zig" }, | ||
| }; | ||
|
|
||
| for (available_examples) |example| { | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,139 @@ | ||||||||||
| const std = @import("std"); | ||||||||||
| const microzig = @import("microzig"); | ||||||||||
|
|
||||||||||
| const hal = microzig.hal; | ||||||||||
| const board = microzig.board; | ||||||||||
| const time = hal.time; | ||||||||||
| const gpio = hal.gpio; | ||||||||||
| const usb = microzig.core.usb; | ||||||||||
| const USB_Serial = usb.drivers.CDC; | ||||||||||
|
|
||||||||||
| const RCC = microzig.chip.peripherals.RCC; | ||||||||||
| const AFIO = microzig.chip.peripherals.AFIO; | ||||||||||
| const PFIC = microzig.chip.peripherals.PFIC; | ||||||||||
|
|
||||||||||
| const usart = hal.usart.instance.USART1; | ||||||||||
|
|
||||||||||
| const usart_tx_pin = gpio.Pin.init(0, 9); // PA9 | ||||||||||
| const func_pin = gpio.Pin.init(0, 10); // PA10 | ||||||||||
| const tog_pin = gpio.Pin.init(0, 14); | ||||||||||
| const mco_pin = gpio.Pin.init(0, 8); | ||||||||||
|
Comment on lines
+19
to
+20
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might as well keep with the comments e.g. PA14 and PA8 |
||||||||||
|
|
||||||||||
| pub const microzig_options = microzig.Options{ | ||||||||||
| .logFn = hal.usart.log, | ||||||||||
| .log_level = .debug, | ||||||||||
| .log_scope_levels = &.{ | ||||||||||
| .{ .scope = .usb_dev, .level = .warn }, | ||||||||||
| .{ .scope = .usb_ctrl, .level = .warn }, | ||||||||||
| .{ .scope = .usb_cdc, .level = .warn }, | ||||||||||
| }, | ||||||||||
| }; | ||||||||||
|
|
||||||||||
| const USBController = usb.DeviceController(.{ | ||||||||||
Grazfather marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
| .bcd_usb = .v2_00, | ||||||||||
| .device_triple = .unspecified, | ||||||||||
| .vendor = .{ .id = 0x2E8A, .str = "MicroZig" }, | ||||||||||
| .product = .{ .id = 0x000A, .str = board.product_string }, | ||||||||||
| .bcd_device = .v1_00, | ||||||||||
| .serial = "someserial", | ||||||||||
| .max_supported_packet_size = hal.usb.max_packet_size, | ||||||||||
| .configurations = &.{.{ | ||||||||||
| .attributes = .{ .self_powered = false }, | ||||||||||
| .max_current_ma = 50, | ||||||||||
| .Drivers = struct { serial: USB_Serial }, | ||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you maybe copy some of the extra comments I added to the cdc example for rpi? |
||||||||||
| }}, | ||||||||||
| }, .{.{ | ||||||||||
| .serial = .{ .itf_notifi = "Board CDC", .itf_data = "Board CDC Data" }, | ||||||||||
| }}); | ||||||||||
|
|
||||||||||
| pub var usb_dev: hal.usb.Polled( | ||||||||||
| .{}, | ||||||||||
| ) = undefined; | ||||||||||
|
Comment on lines
+49
to
+51
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
|
|
||||||||||
| var usb_controller: USBController = .init; | ||||||||||
|
|
||||||||||
| pub fn main() !void { | ||||||||||
| // Board brings up clocks and time | ||||||||||
| microzig.board.init(); | ||||||||||
| microzig.hal.init(); | ||||||||||
| // Enable peripheral clocks for USART1 and GPIOA | ||||||||||
| RCC.APB2PCENR.modify(.{ | ||||||||||
| .IOPAEN = 1, // Enable GPIOA clock | ||||||||||
| .IOPCEN = 1, | ||||||||||
| .AFIOEN = 1, // Enable AFIO clock | ||||||||||
| .USART1EN = 1, // Enable USART1 clock | ||||||||||
| }); | ||||||||||
| // Configure TX pin as alternate function push-pull | ||||||||||
| usart_tx_pin.set_output_mode(.alternate_function_push_pull, .max_50MHz); | ||||||||||
|
|
||||||||||
| // Initialize USART1 at 115200 baud | ||||||||||
| usart.apply(.{ .baud_rate = 115200 }); | ||||||||||
|
|
||||||||||
| hal.usart.init_logger(usart); | ||||||||||
| std.log.info("UART logging initialized.", .{}); | ||||||||||
|
|
||||||||||
| std.log.info("Initializing USB device.", .{}); | ||||||||||
|
|
||||||||||
| usb_dev = .init(); | ||||||||||
|
|
||||||||||
| var i: u32 = 0; | ||||||||||
| var old: u64 = time.get_time_since_boot().to_us(); | ||||||||||
| var new: u64 = 0; | ||||||||||
|
|
||||||||||
| while (true) { | ||||||||||
| if (usb_controller.drivers()) |drivers| { | ||||||||||
| new = time.get_time_since_boot().to_us(); | ||||||||||
| if (new - old > 500000) { | ||||||||||
| old = new; | ||||||||||
| i += 1; | ||||||||||
| std.log.info("cdc test: {}", .{i}); | ||||||||||
|
|
||||||||||
| usb_cdc_write(&drivers.serial, "This is very very very long text sent from ch32 by USB CDC to your device: {}\r\n", .{i}); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // read and print host command if present | ||||||||||
| const message = usb_cdc_read(&drivers.serial); | ||||||||||
| if (message.len > 0) { | ||||||||||
| usb_cdc_write(&drivers.serial, "Your message to me was: {s}\r\n", .{message}); | ||||||||||
| } | ||||||||||
| } | ||||||||||
| usb_dev.poll(false, &usb_controller); | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| var usb_tx_buff: [1024]u8 = undefined; | ||||||||||
|
|
||||||||||
| // Transfer data to host | ||||||||||
| // NOTE: After each USB chunk transfer, we have to call the USB task so that bus TX events can be handled | ||||||||||
| pub fn usb_cdc_write(serial: *USB_Serial, comptime fmt: []const u8, args: anytype) void { | ||||||||||
| const text = std.fmt.bufPrint(&usb_tx_buff, fmt, args) catch &.{}; | ||||||||||
| var write_buff = text; | ||||||||||
| while (write_buff.len > 0) { | ||||||||||
| write_buff = write_buff[serial.write(write_buff)..]; | ||||||||||
| while (!serial.flush()) { | ||||||||||
| // pins.tog.put(0); | ||||||||||
| usb_dev.poll(false, &usb_controller); | ||||||||||
| // pins.tog.put(1); | ||||||||||
|
Comment on lines
+114
to
+116
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. gets rid of toggle pins completely or uncomment these please |
||||||||||
| } | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| var usb_rx_buff: [1024]u8 = undefined; | ||||||||||
|
|
||||||||||
| // Receive data from host | ||||||||||
| // NOTE: Read code was not tested extensively. In case of issues, try to call USB task before every read operation | ||||||||||
| pub fn usb_cdc_read( | ||||||||||
| serial: *USB_Serial, | ||||||||||
| ) []const u8 { | ||||||||||
| var total_read: usize = 0; | ||||||||||
| var read_buff: []u8 = usb_rx_buff[0..]; | ||||||||||
|
|
||||||||||
| while (true) { | ||||||||||
| const len = serial.read(read_buff); | ||||||||||
| read_buff = read_buff[len..]; | ||||||||||
| total_read += len; | ||||||||||
| if (len == 0) break; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| return usb_rx_buff[0..total_read]; | ||||||||||
| } | ||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,7 @@ pub const i2c = @import("i2c.zig"); | |
| pub const usart = @import("usart.zig"); | ||
| pub const spi = @import("spi.zig"); | ||
| pub const dma = @import("dma.zig"); | ||
| pub const usb = @import("usbfs.zig"); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add this in the test block as well |
||
|
|
||
| /// HSI (High Speed Internal) oscillator frequency | ||
| /// This is the fixed internal RC oscillator frequency for CH32V20x | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,18 +5,32 @@ pub const clocks = @import("clocks.zig"); | |
| pub const time = @import("time.zig"); | ||
| pub const i2c = @import("i2c.zig"); | ||
| pub const usart = @import("usart.zig"); | ||
| const std = @import("std"); | ||
| pub const usb = @import("usbhs.zig"); | ||
| pub const usbfs = @import("usbfs.zig"); | ||
|
|
||
| /// HSI (High Speed Internal) oscillator frequency | ||
| /// This is the fixed internal RC oscillator frequency for CH32V30x | ||
| pub const hsi_frequency: u32 = 8_000_000; // 8 MHz | ||
| pub const hse_frequency: u32 = 8_000_000; // 8 MHz | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be board level, since it's external to the chip and may not be present. |
||
|
|
||
| /// Default interrupt handlers provided by the HAL | ||
| pub const default_interrupts: microzig.cpu.InterruptOptions = .{ | ||
| .TIM2 = time.tim2_handler, | ||
| // .USBHS = usb.usbhs_interrupt_handler, | ||
| }; | ||
|
|
||
| /// Initialize HAL subsystems used by default | ||
| pub fn init() void { | ||
| // Configure TIM2 timing driver | ||
| time.init(); | ||
| clocks.init(.{ | ||
| .source = .hse, | ||
| .hse_frequency = hse_frequency, | ||
| .target_frequency = 48_000_000, | ||
| }); | ||
| clocks.enable_usbhs_clock(.{ | ||
| .ref_source_hz = hse_frequency, | ||
| .ref_source = .hse, | ||
| }); | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
woof