From a501e632867b65bbae7b668f98956672294bdcba Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Tue, 7 Jun 2022 01:18:02 -0700 Subject: [PATCH 01/74] init --- .gitignore | 2 + .gitmodules | 3 + build.zig | 51 + microzig | 1 + rp2040.ld | 58 + src/hal.zig | 20 + src/hal/clocks.zig | 438 + src/hal/gpio.zig | 153 + src/hal/pll.zig | 97 + src/raspberry_pi_pico.zig | 38 + src/rp2040.zig | 29422 ++++++++++++++++++++++++++++++++++++ 11 files changed, 30283 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 build.zig create mode 160000 microzig create mode 100644 rp2040.ld create mode 100644 src/hal.zig create mode 100644 src/hal/clocks.zig create mode 100644 src/hal/gpio.zig create mode 100644 src/hal/pll.zig create mode 100644 src/raspberry_pi_pico.zig create mode 100644 src/rp2040.zig diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4c82b07 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +zig-cache +zig-out diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..fdd0dab --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "microzig"] + path = microzig + url = git@github.com:ZigEmbeddedGroup/microzig.git diff --git a/build.zig b/build.zig new file mode 100644 index 0000000..7bf7bea --- /dev/null +++ b/build.zig @@ -0,0 +1,51 @@ +const std = @import("std"); + +const Builder = std.build.Builder; +const Pkg = std.build.Pkg; + +pub const BuildOptions = struct { + packages: ?[]const Pkg = null, +}; + +pub fn addPiPicoExecutable( + comptime microzig: type, + builder: *Builder, + name: []const u8, + source: []const u8, + options: BuildOptions, +) *std.build.LibExeObjStep { + const rp2040 = microzig.Chip{ + .name = "RP2040", + .path = root() ++ "src/rp2040.zig", + .cpu = microzig.cpus.cortex_m0plus, + .memory_regions = &.{ + .{ .kind = .flash, .offset = 0x10000100, .length = (2048 * 1024) - 256 }, + .{ .kind = .flash, .offset = 0x10000000, .length = 256 }, + .{ .kind = .ram, .offset = 0x20000000, .length = 256 * 1024 }, + }, + }; + + const raspberry_pi_pico = microzig.Board{ + .name = "Raspberry Pi Pico", + .path = root() ++ "src/raspberry_pi_pico.zig", + .chip = rp2040, + }; + + const ret = microzig.addEmbeddedExecutable( + builder, + name, + source, + .{ .board = raspberry_pi_pico }, + .{ + .packages = options.packages, + .hal_package_path = .{ .path = root() ++ "src/hal.zig" }, + }, + ) catch @panic("failed to create embedded executable"); + ret.setLinkerScriptPath(.{ .path = root() ++ "rp2040.ld" }); + + return ret; +} + +fn root() []const u8 { + return (std.fs.path.dirname(@src().file) orelse unreachable) ++ "/"; +} diff --git a/microzig b/microzig new file mode 160000 index 0000000..ac19b7d --- /dev/null +++ b/microzig @@ -0,0 +1 @@ +Subproject commit ac19b7de8eb1551e603b3ce23a4aab69c71d1216 diff --git a/rp2040.ld b/rp2040.ld new file mode 100644 index 0000000..f293543 --- /dev/null +++ b/rp2040.ld @@ -0,0 +1,58 @@ +/* + * This file was auto-generated by microzig + * + * Target CPU: ARM Cortex-M0+ + * Target Chip: RP2040 + */ + +ENTRY(microzig_main); + +MEMORY +{ + flash0 (rx!w) : ORIGIN = 0x10000000, LENGTH = 0x00200000 + ram0 (rw!x) : ORIGIN = 0x20000000, LENGTH = 0x00040000 +} + +SECTIONS +{ + .boot2 : { + __boot2_start__ = .; + KEEP (*(.boot2)) + __boot2_end__ = .; + } > flash0 + + ASSERT(__boot2_end__ - __boot2_start__ == 256, + "ERROR: Pico second stage bootloader must be 256 bytes in size") + + .text : + { + KEEP(*(microzig_flash_start)) + *(.text*) + *(.rodata*) + } > flash0 + + .ARM.exidx : { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } >flash0 + + .flash1 : + { + *(.flash1) + } > flash1 + + .data : + { + microzig_data_start = .; + *(.data*) + microzig_data_end = .; + } > ram0 AT> flash0 + + .bss (NOLOAD) : + { + microzig_bss_start = .; + *(.bss*) + microzig_bss_end = .; + } > ram0 + + microzig_data_load_start = LOADADDR(.data); +} diff --git a/src/hal.zig b/src/hal.zig new file mode 100644 index 0000000..41f4744 --- /dev/null +++ b/src/hal.zig @@ -0,0 +1,20 @@ +const microzig = @import("microzig"); +const regs = microzig.chip.regsisters; +pub const gpio = @import("hal/gpio.zig"); +pub const clocks = @import("hal/clocks.zig"); + +pub const default_clock_config = clocks.GlobalConfiguration.init(.{ + //.ref = .{ .source = .src_xosc }, + .sys = .{ + .source = .pll_sys, + .freq = 125_000_000, + }, + .usb = .{ .source = .pll_usb }, + //.adc = .{ .source = .pll_usb }, + //.rtc = .{ .source = .pll_usb }, + .peri = .{ .source = .clk_sys }, +}); + +pub fn getCpuId() u32 { + return regs.SIO.CPUID.*; +} diff --git a/src/hal/clocks.zig b/src/hal/clocks.zig new file mode 100644 index 0000000..7f266e2 --- /dev/null +++ b/src/hal/clocks.zig @@ -0,0 +1,438 @@ +const std = @import("std"); +const microzig = @import("microzig"); +const pll = @import("pll.zig"); +const assert = std.debug.assert; + +const regs = microzig.chip.registers; +const xosc_freq = microzig.board.xosc_freq; +// TODO: move to board file +/// this is only nominal, very imprecise and prone to drift over time +const rosc_freq = 6_500_000; + +comptime { + assert(xosc_freq <= 15_000_000 and xosc_freq >= 1_000_000); // xosc limits +} + +pub const xosc = struct { + const startup_delay_ms = 1; + const startup_delay_value = xosc_freq * startup_delay_ms / 1000 / 256; + + pub fn init() void { + regs.XOSC.STARTUP.modify(.{ .DELAY = startup_delay_value }); + regs.XOSC.CTRL.modify(.{ .ENABLE = 4011 }); + + // wait for xosc startup to complete: + while (regs.XOSC.STATUS.read().STABLE == 0) {} + } + + pub fn waitCycles(value: u8) void { + assert(is_enabled: { + const status = regs.XOSC.STATUS.read(); + break :is_enabled status.STABLE != 0 and status.ENABLED != 0; + }); + + regs.XOSC.COUNT.modify(value); + while (regs.XOSC.COUNT.read() != 0) {} + } +}; + +fn formatUppercase( + bytes: []const u8, + comptime fmt: []const u8, + options: std.fmt.FormatOptions, + writer: anytype, +) !void { + _ = fmt; + _ = options; + for (bytes) |c| + try writer.writeByte(std.ascii.toUpper(c)); +} + +fn uppercase(bytes: []const u8) std.fmt.Formatter(formatUppercase) { + return .{ .data = bytes }; +} + +pub const Generator = enum { + gpout0, + gpout1, + gpout2, + gpout3, + ref, + sys, + peri, + usb, + adc, + rtc, + + // source directly from register definitions + const Source = enum { + rosc_clksrc_ph, + clksrc_clk_ref_aux, + xosc_clksrc, + clk_ref, + clksrc_clk_sys_aux, + }; + + // aux sources directly from register definitions + const AuxilarySource = enum { + clksrc_pll_sys, + clksrc_gpin0, + clksrc_gpin1, + clksrc_pll_usb, + rosc_clksrc, + xosc_clksrc, + clk_sys, + clk_usb, + clk_adc, + clk_rtc, + clk_ref, + rosc_clksrc_ph, + }; + + const source_map = struct { + const ref = [_]Generator.Source{ .rosc_clksrc_ph, .clksrc_clk_ref, .xosc_clksrc }; + const sys = [_]Generator.Source{ .clk_ref, .clksrc_clk_sys_aux }; + }; + + const aux_map = struct {}; + + pub fn hasGlitchlessMux(generator: Generator) bool { + return switch (generator) { + .sys, .ref => true, + else => false, + }; + } + + pub fn enable(generator: Generator) void { + inline for (std.meta.fields(Generator)) |field| { + if (generator == @field(Generator, field.name)) { + const reg_name = comptime std.fmt.comptimePrint("CLK_{s}_CTRL", .{ + uppercase(field.name), + }); + + if (@hasField(@TypeOf(@field(regs.CLOCKS, reg_name).*).underlying_type, "ENABLE")) + @field(regs.CLOCKS, reg_name).modify(.{ .ENABLE = 1 }); + } + } + } + + pub fn setDiv(generator: Generator, div: u32) void { + inline for (std.meta.fields(Generator)) |field| { + if (generator == @field(Generator, field.name)) { + const reg_name = comptime std.fmt.comptimePrint("CLK_{s}_DIV", .{ + uppercase(field.name), + }); + + if (@hasDecl(regs.CLOCKS, reg_name)) + @field(regs.CLOCKS, reg_name).raw = div + else + assert(false); // doesn't have a divider + } + } + } + + pub fn getDiv(generator: Generator) u32 { + return inline for (std.meta.fields(Generator)) |field| { + if (generator == @field(Generator, field.name)) { + const reg_name = comptime std.fmt.comptimePrint("CLK_{s}_DIV", .{ + uppercase(field.name), + }); + + break if (@hasDecl(regs.CLOCKS, reg_name)) + @field(regs.CLOCKS, reg_name).raw + else + 1; + } + } else unreachable; + } + + // The bitfields for the *_SELECTED registers are actually a mask of which + // source is selected. While switching sources it may read as 0, and that's + // what this function is indended for: checking if the new source has + // switched over yet. + // + // Some mention that this is only for the glitchless mux, so if it is non-glitchless then return true + pub fn selected(generator: Generator) bool { + inline for (std.meta.fields(Generator)) |field| { + if (generator == @field(Generator, field.name)) { + return if (@field(Generator, field.name).hasGlitchlessMux()) ret: { + const reg_name = comptime std.fmt.comptimePrint("CLK_{s}_SELECTED", .{ + uppercase(field.name), + }); + + break :ret @field(regs.CLOCKS, reg_name).* != 0; + } else true; + } + } else unreachable; + } +}; + +pub const Source = enum { + src_rosc, + src_xosc, + src_aux, + pll_sys, + pll_usb, + clk_sys, +}; + +pub const GlobalConfiguration = struct { + xosc_configured: bool, + sys: ?Configuration, + ref: ?Configuration, + usb: ?Configuration, + adc: ?Configuration, + rtc: ?Configuration, + peri: ?Configuration, + + pll_sys: ?pll.Configuration, + pll_usb: ?pll.Configuration, + + pub const Option = struct { + source: Source, + freq: ?u32 = null, + }; + + pub const Options = struct { + sys: ?Option = null, + ref: ?Option = null, + usb: ?Option = null, + adc: ?Option = null, + rtc: ?Option = null, + peri: ?Option = null, + // TODO: allow user to configure PLLs to optimize for low-jitter, low-power, or manually specify + }; + + /// this function reasons about how to configure the clock system. It will + /// assert if the configuration is invalid + pub fn init(comptime opts: Options) GlobalConfiguration { + var xosc_configured = false; + var pll_sys: ?pll.Configuration = null; + var pll_usb: ?pll.Configuration = null; + + return GlobalConfiguration{ + // the system clock can either use rosc, xosc, or the sys PLL + .sys = if (opts.sys) |sys_opts| sys_config: { + var output_freq: ?u32 = null; + break :sys_config .{ + .generator = .sys, + .input = switch (sys_opts.source) { + .src_rosc => input: { + output_freq = sys_opts.freq orelse rosc_freq; + assert(output_freq.? <= rosc_freq); + break :input .{ + .source = .rosc, + .freq = rosc_freq, + }; + }, + .src_xosc => input: { + xosc_configured = true; + output_freq = sys_opts.freq orelse xosc_freq; + assert(output_freq.? <= xosc_freq); + break :input .{ + .source = .xosc, + .freq = xosc_freq, + }; + }, + .pll_sys => input: { + xosc_configured = true; + output_freq = sys_opts.freq orelse 125_000_000; + assert(output_freq.? <= 125_000_000); + + // TODO: proper values for 125MHz + pll_sys = .{ + .refdiv = 2, + .vco_freq = 1_440_000_000, + .postdiv1 = 6, + .postdiv2 = 5, + }; + + break :input .{ + .source = .pll_sys, + // TODO: not really sure what frequency to + // drive pll at yet, but this is an okay start + .freq = 125_000_000, + }; + }, + + else => unreachable, // not an available input + }, + .output_freq = output_freq.?, + }; + } else null, + + // to keep things simple for now, we'll make it so that the usb + // generator can only be hooked up to the usb PLL, and only have + // one configuration for the usb PLL + .usb = if (opts.usb) |usb_opts| usb_config: { + assert(pll_usb == null); + assert(usb_opts.source == .pll_usb); + + xosc_configured = true; + pll_usb = .{ + .refdiv = 1, + .vco_freq = 1_440_000_000, + .postdiv1 = 6, + .postdiv2 = 5, + }; + + break :usb_config .{ + .generator = .usb, + .input = .{ + .source = .pll_usb, + .freq = 48_000_000, + }, + .output_freq = 48_000_000, + }; + } else null, + + // I THINK that if either pll is configured here, then that means + // that the ref clock generator MUST use xosc to feed the PLLs? + .ref = if (opts.ref) |_| + unreachable // don't explicitly configure for now + else if (pll_sys != null or pll_usb != null) ref_config: { + xosc_configured = true; + break :ref_config .{ + .generator = .ref, + .input = .{ + .source = .src_xosc, + .freq = xosc_freq, + }, + .output_freq = xosc_freq, + }; + } else null, + + // for the rest of the generators we'll make it so that they can + // either use the ROSC, XOSC, or sys PLL, with whatever dividing + // they need + + .adc = if (opts.adc) |_| + unreachable // TODO + else + null, + + .rtc = if (opts.rtc) |_| + unreachable // TODO + else + null, + + .peri = if (opts.peri) |peri_opts| peri_config: { + if (peri_opts.source == .src_xosc) + xosc_configured = true; + + // TODO + break :peri_config .{ + .generator = .peri, + .input = .{ + .source = peri_opts.source, + .freq = xosc_freq, + }, + .output_freq = xosc_freq, + }; + } else null, + + .xosc_configured = xosc_configured, + .pll_sys = pll_sys, + .pll_usb = pll_usb, + }; + } + + /// this is explicitly comptime to encourage the user to have separate + /// clock configuration declarations instead of mutating them at runtime + pub fn apply(comptime config: GlobalConfiguration) !void { + + // disable resus if it has been turned on elsewhere + regs.CLOCKS.CLK_SYS_RESUS_CTRL.raw = 0; + + if (config.xosc_configured) { + regs.WATCHDOG.TICK.modify(.{ + .CYCLES = xosc_freq / 1_000_000, + .ENABLE = 1, + }); + xosc.init(); + } + + // switch sys and ref cleanly away from aux sources if they're + // configured to use/be used from PLLs + if (config.sys) |sys| switch (sys.input.source) { + .pll_usb, .pll_sys => { + regs.CLOCKS.CLK_SYS_CTRL.modify(.{ .SRC = 0 }); + while (regs.CLOCKS.CLK_SYS_SELECTED.* != 1) {} + }, + else => {}, + }; + + if (config.ref) |ref| switch (ref.input.source) { + .pll_usb, .pll_sys => { + regs.CLOCKS.CLK_REF_CTRL.modify(.{ .SRC = 0 }); + while (regs.CLOCKS.CLK_REF_SELECTED.* != 1) {} + }, + else => {}, + }; + + // initialize PLLs + if (config.pll_sys) |pll_sys_config| pll.sys.apply(pll_sys_config); + if (config.pll_usb) |pll_usb_config| pll.usb.apply(pll_usb_config); + + // initialize clock generators + if (config.ref) |ref| try ref.apply(); + if (config.usb) |usb| try usb.apply(); + if (config.adc) |adc| try adc.apply(); + if (config.rtc) |rtc| try rtc.apply(); + if (config.peri) |peri| try peri.apply(); + } + + /// returns frequency of a clock or pll, if unconfigured it returns null + pub fn getFrequency(config: GlobalConfiguration) ?u32 { + _ = config; + return null; + } +}; + +pub const Configuration = struct { + generator: Generator, + input: struct { + source: Source, + freq: u32, + }, + output_freq: u32, + + pub fn apply(config: Configuration) !void { + const generator = config.generator; + const input = config.input; + const output_freq = config.output_freq; + + // source frequency has to be faster because dividing will always reduce. + assert(input.freq >= output_freq); + if (output_freq < input.freq) + return error.InvalidArgs; + + const div = @intCast(u32, (@intCast(u64, input.freq) << 8) / 8); + + // check divisor + if (div > generator.getDiv()) + generator.setDiv(div); + + if (generator.hasGlitchlessMux() and input.source == .src_aux) { + // TODO: clear bits + while (!generator.selected()) { + // TODO: is leaving this empty good enough? pico sdk has `tight_loop_contents()` + } + } else { + // uh stuff + } + + // set aux mux first and then glitchless mex if this clock has one + if (generator.hasGlitchlessMux()) { + // write to clock ctrl + while (!generator.selected()) {} + } + + generator.enable(); + generator.setDiv(div); + // should we store global state on configured clocks? + } +}; + +//pub fn countFrequencyKhz(source: Source) u32 {} + diff --git a/src/hal/gpio.zig b/src/hal/gpio.zig new file mode 100644 index 0000000..ab0f666 --- /dev/null +++ b/src/hal/gpio.zig @@ -0,0 +1,153 @@ +//! ### Function Select Table +//! +//! GPIO | F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 +//! -------|----------|-----------|----------|--------|-----|------|------|---------------|---- +//! 0 | SPI0 RX | UART0 TX | I2C0 SDA | PWM0 A | SIO | PIO0 | PIO1 | | USB OVCUR DET +//! 1 | SPI0 CSn | UART0 RX | I2C0 SCL | PWM0 B | SIO | PIO0 | PIO1 | | USB VBUS DET +//! 2 | SPI0 SCK | UART0 CTS | I2C1 SDA | PWM1 A | SIO | PIO0 | PIO1 | | USB VBUS EN +//! 3 | SPI0 TX | UART0 RTS | I2C1 SCL | PWM1 B | SIO | PIO0 | PIO1 | | USB OVCUR DET +//! 4 | SPI0 RX | UART1 TX | I2C0 SDA | PWM2 A | SIO | PIO0 | PIO1 | | USB VBUS DET +//! 5 | SPI0 CSn | UART1 RX | I2C0 SCL | PWM2 B | SIO | PIO0 | PIO1 | | USB VBUS EN +//! 6 | SPI0 SCK | UART1 CTS | I2C1 SDA | PWM3 A | SIO | PIO0 | PIO1 | | USB OVCUR DET +//! 7 | SPI0 TX | UART1 RTS | I2C1 SCL | PWM3 B | SIO | PIO0 | PIO1 | | USB VBUS DET +//! 8 | SPI1 RX | UART1 TX | I2C0 SDA | PWM4 A | SIO | PIO0 | PIO1 | | USB VBUS EN +//! 9 | SPI1 CSn | UART1 RX | I2C0 SCL | PWM4 B | SIO | PIO0 | PIO1 | | USB OVCUR DET +//! 10 | SPI1 SCK | UART1 CTS | I2C1 SDA | PWM5 A | SIO | PIO0 | PIO1 | | USB VBUS DET +//! 11 | SPI1 TX | UART1 RTS | I2C1 SCL | PWM5 B | SIO | PIO0 | PIO1 | | USB VBUS EN +//! 12 | SPI1 RX | UART0 TX | I2C0 SDA | PWM6 A | SIO | PIO0 | PIO1 | | USB OVCUR DET +//! 13 | SPI1 CSn | UART0 RX | I2C0 SCL | PWM6 B | SIO | PIO0 | PIO1 | | USB VBUS DET +//! 14 | SPI1 SCK | UART0 CTS | I2C1 SDA | PWM7 A | SIO | PIO0 | PIO1 | | USB VBUS EN +//! 15 | SPI1 TX | UART0 RTS | I2C1 SCL | PWM7 B | SIO | PIO0 | PIO1 | | USB OVCUR DET +//! 16 | SPI0 RX | UART0 TX | I2C0 SDA | PWM0 A | SIO | PIO0 | PIO1 | | USB VBUS DET +//! 17 | SPI0 CSn | UART0 RX | I2C0 SCL | PWM0 B | SIO | PIO0 | PIO1 | | USB VBUS EN +//! 18 | SPI0 SCK | UART0 CTS | I2C1 SDA | PWM1 A | SIO | PIO0 | PIO1 | | USB OVCUR DET +//! 19 | SPI0 TX | UART0 RTS | I2C1 SCL | PWM1 B | SIO | PIO0 | PIO1 | | USB VBUS DET +//! 20 | SPI0 RX | UART1 TX | I2C0 SDA | PWM2 A | SIO | PIO0 | PIO1 | CLOCK GPIN0 | USB VBUS EN +//! 21 | SPI0 CSn | UART1 RX | I2C0 SCL | PWM2 B | SIO | PIO0 | PIO1 | CLOCK GPOUT0 | USB OVCUR DET +//! 22 | SPI0 SCK | UART1 CTS | I2C1 SDA | PWM3 A | SIO | PIO0 | PIO1 | CLOCK GPIN1 | USB VBUS DET +//! 23 | SPI0 TX | UART1 RTS | I2C1 SCL | PWM3 B | SIO | PIO0 | PIO1 | CLOCK GPOUT1 | USB VBUS EN +//! 24 | SPI1 RX | UART1 TX | I2C0 SDA | PWM4 A | SIO | PIO0 | PIO1 | CLOCK GPOUT2 | USB OVCUR DET +//! 25 | SPI1 CSn | UART1 RX | I2C0 SCL | PWM4 B | SIO | PIO0 | PIO1 | CLOCK GPOUT3 | USB VBUS DET +//! 26 | SPI1 SCK | UART1 CTS | I2C1 SDA | PWM5 A | SIO | PIO0 | PIO1 | | USB VBUS EN +//! 27 | SPI1 TX | UART1 RTS | I2C1 SCL | PWM5 B | SIO | PIO0 | PIO1 | | USB OVCUR DET +//! 28 | SPI1 RX | UART0 TX | I2C0 SDA | PWM6 A | SIO | PIO0 | PIO1 | | USB VBUS DET +//! 29 | SPI1 CSn | UART0 RX | I2C0 SCL | PWM6 B | SIO | PIO0 | PIO1 | | USB VBUS EN + +const std = @import("std"); +const microzig = @import("microzig"); +const regs = microzig.chip.registers; +const assert = std.debug.assert; + +pub const Function = enum(u5) { + xip, + spi, + uart, + i2c, + pwm, + sio, + pio0, + pio1, + gpck, + usb, + @"null" = 0x1f, +}; + +pub const Direction = enum(u1) { + in, + out, +}; + +pub const IrqLevel = enum(u2) { + low, + high, + fall, + rise, +}; + +pub const IrqCallback = fn (gpio: u32, events: u32) callconv(.C) void; + +pub const Override = enum { + normal, + invert, + low, + high, +}; + +pub const SlewRate = enum { + slow, + fast, +}; + +pub const DriveStrength = enum { + ma_2, + ma_4, + ma_8, + ma_12, +}; + +pub const Enabled = enum { + disabled, + enabled, +}; + +//const gpio_num = gpio_num: { +// // calculate max gpios using comptime parsing +//}; + +/// Initialize a GPIO, set func to SIO +pub inline fn init(comptime gpio: u32) void { + regs.SIO.GPIO_OE_CLR.raw = 1 << gpio; + regs.SIO.GPIO_OUT_CLR.raw = 1 << gpio; + setFunction(gpio, .sio); +} + +/// Reset GPIO back to null function (disables it) +pub inline fn deinit(comptime gpio: u32) void { + setFunction(gpio, .@"null"); +} + +pub inline fn setDir(comptime gpio: u32, direction: Direction) void { + switch (direction) { + .in => regs.SIO.GPIO_OE_CLR.raw |= (1 << gpio), + .out => regs.SIO.GPIO_OE_SET.raw &= (1 << gpio), + } +} + +/// Drive a single GPIO high/low +pub inline fn put(comptime gpio: u32, value: u1) void { + switch (value) { + 0 => regs.SIO.GPIO_OUT.raw &= ~@as(u32, 1 << gpio), + 1 => regs.SIO.GPIO_OUT.raw |= (1 << gpio), + } +} + +pub inline fn setFunction(comptime gpio: u32, function: Function) void { + const reg_name = comptime std.fmt.comptimePrint("GPIO{}_CTRL", .{gpio}); + @field(regs.IO_BANK0, reg_name).write(.{ + .FUNCSEL = @enumToInt(function), + .OUTOVER = 0, + .INOVER = 0, + .IRQOVER = 0, + .OEOVER = 0, + }); +} + +// setting both uplls enables a "bus keep" function, a weak pull to whatever +// is current high/low state of GPIO +//pub fn setPulls(gpio: u32, up: bool, down: bool) void {} +// +//pub fn pullUp(gpio: u32) void {} +// +//pub fn pullDown(gpio: u32) void {} +//pub fn disablePulls(gpio: u32) void {} +//pub fn setIrqOver(gpio: u32, value: u32) void {} +//pub fn setOutOver(gpio: u32, value: u32) void {} +//pub fn setInOver(gpio: u32, value: u32) void {} +//pub fn setOeOver(gpio: u32, value: u32) void {} +//pub fn setInputEnabled(gpio: u32, enabled: Enabled) void {} +//pub fn setinputHysteresisEnabled(gpio: u32, enabled: Enabled) void {} +//pub fn setSlewRate(gpio: u32, slew_rate: SlewRate) void {} +//pub fn setDriveStrength(gpio: u32, drive: DriveStrength) void {} +//pub fn setIrqEnabled(gpio: u32, events: IrqEvents) void {} +//pub fn acknowledgeIrq(gpio: u32, events: IrqEvents) void {} + diff --git a/src/hal/pll.zig b/src/hal/pll.zig new file mode 100644 index 0000000..16fb308 --- /dev/null +++ b/src/hal/pll.zig @@ -0,0 +1,97 @@ +const std = @import("std"); +const microzig = @import("microzig"); +const assert = std.debug.assert; + +const regs = microzig.chip.registers; +const xosc_freq = microzig.board.xosc_freq; + +pub const Configuration = struct { + refdiv: u6, + vco_freq: u32, + postdiv1: u3, + postdiv2: u3, +}; + +pub const sys = @intToPtr(*volatile PLL, regs.PLL_SYS.base_address); +pub const usb = @intToPtr(*volatile PLL, regs.PLL_USB.base_address); + +pub const PLL = packed struct { + cs: @TypeOf(regs.PLL_SYS.CS), + pwr: @TypeOf(regs.PLL_SYS.PWR), + fbdiv_int: @TypeOf(regs.PLL_SYS.FBDIV_INT), + prim: @TypeOf(regs.PLL_SYS.PRIM), + + comptime { + // bunch of comptime checks in here to validate the layout + assert(0 == @bitOffsetOf(PLL, "cs")); + assert(32 == @bitOffsetOf(PLL, "pwr")); + assert(64 == @bitOffsetOf(PLL, "fbdiv_int")); + assert(96 == @bitOffsetOf(PLL, "prim")); + } + + pub fn isLocked(pll: *const volatile PLL) bool { + return pll.cs.read().LOCK == 1; + } + + pub fn reset(pll: *const volatile PLL) void { + switch (pll) { + sys => { + regs.RESETS.RESET.modify(.{ .pll_sys = 1 }); + regs.RESETS.RESET.modify(.{ .pll_sys = 0 }); + while (regs.RESETS.RESET_DONE.read().pll_sys == 1) {} + }, + usb => { + regs.RESETS.RESET.modify(.{ .pll_usb = 1 }); + regs.RESETS.RESET.modify(.{ .pll_usb = 0 }); + while (regs.RESETS.RESET_DONE.read().pll_usb == 1) {} + }, + else => unreachable, + } + } + + pub fn apply(pll: *volatile PLL, comptime config: Configuration) void { + const ref_freq = xosc_freq / @as(u32, config.refdiv); + const fbdiv = @intCast(u12, config.vco_freq / ref_freq); + + assert(fbdiv >= 16 and fbdiv <= 320); + assert(config.postdiv1 >= 1 and config.postdiv1 <= 7); + assert(config.postdiv2 >= 1 and config.postdiv2 <= 7); + assert(config.postdiv2 <= config.postdiv1); + assert(ref_freq <= config.vco_freq / 16); + + // 1. program reference clock divider + // 2. program feedback divider + // 3. turn on the main power and vco + // 4. wait for vco to lock + // 5. set up post dividers and turn them on + + // do not bother a PLL which is already configured + if (pll.isLocked() and + config.refdiv == pll.cs.read().REFDIV and + fbdiv == pll.fbdiv_int.read() and + config.postdiv1 == pll.prim.read().POSTDIV1 and + config.postdiv2 == pll.prim.read().POSTDIV2) + { + return; + } + + pll.reset(); + + // load vco related dividers + pll.cs.modify(.{ .REFDIV = config.refdiv }); + pll.fbdiv_int.modify(fbdiv); + + // turn on PLL + pll.pwr.modify(.{ .PD = 0, .VCOPD = 0 }); + + // wait for PLL to lock + while (!pll.isLocked()) {} + + pll.prim.modify(.{ + .POSTDIV1 = config.postdiv1, + .POSTDIV2 = config.postdiv2, + }); + + pll.pwr.modify(.{ .POSTDIVPD = 0 }); + } +}; diff --git a/src/raspberry_pi_pico.zig b/src/raspberry_pi_pico.zig new file mode 100644 index 0000000..ca1a901 --- /dev/null +++ b/src/raspberry_pi_pico.zig @@ -0,0 +1,38 @@ +pub const xosc_freq = 12_000_000; + +// TODO: improve interface so that user can use a custom implementation and +// automatically checksum it. +pub export const _BOOT2: [256]u8 linksection(".boot2") = [_]u8{ + 0x00, 0xb5, 0x32, 0x4b, 0x21, 0x20, 0x58, 0x60, + 0x98, 0x68, 0x02, 0x21, 0x88, 0x43, 0x98, 0x60, + 0xd8, 0x60, 0x18, 0x61, 0x58, 0x61, 0x2e, 0x4b, + 0x00, 0x21, 0x99, 0x60, 0x02, 0x21, 0x59, 0x61, + 0x01, 0x21, 0xf0, 0x22, 0x99, 0x50, 0x2b, 0x49, + 0x19, 0x60, 0x01, 0x21, 0x99, 0x60, 0x35, 0x20, + 0x00, 0xf0, 0x44, 0xf8, 0x02, 0x22, 0x90, 0x42, + 0x14, 0xd0, 0x06, 0x21, 0x19, 0x66, 0x00, 0xf0, + 0x34, 0xf8, 0x19, 0x6e, 0x01, 0x21, 0x19, 0x66, + 0x00, 0x20, 0x18, 0x66, 0x1a, 0x66, 0x00, 0xf0, + 0x2c, 0xf8, 0x19, 0x6e, 0x19, 0x6e, 0x19, 0x6e, + 0x05, 0x20, 0x00, 0xf0, 0x2f, 0xf8, 0x01, 0x21, + 0x08, 0x42, 0xf9, 0xd1, 0x00, 0x21, 0x99, 0x60, + 0x1b, 0x49, 0x19, 0x60, 0x00, 0x21, 0x59, 0x60, + 0x1a, 0x49, 0x1b, 0x48, 0x01, 0x60, 0x01, 0x21, + 0x99, 0x60, 0xeb, 0x21, 0x19, 0x66, 0xa0, 0x21, + 0x19, 0x66, 0x00, 0xf0, 0x12, 0xf8, 0x00, 0x21, + 0x99, 0x60, 0x16, 0x49, 0x14, 0x48, 0x01, 0x60, + 0x01, 0x21, 0x99, 0x60, 0x01, 0xbc, 0x00, 0x28, + 0x00, 0xd0, 0x00, 0x47, 0x12, 0x48, 0x13, 0x49, + 0x08, 0x60, 0x03, 0xc8, 0x80, 0xf3, 0x08, 0x88, + 0x08, 0x47, 0x03, 0xb5, 0x99, 0x6a, 0x04, 0x20, + 0x01, 0x42, 0xfb, 0xd0, 0x01, 0x20, 0x01, 0x42, + 0xf8, 0xd1, 0x03, 0xbd, 0x02, 0xb5, 0x18, 0x66, + 0x18, 0x66, 0xff, 0xf7, 0xf2, 0xff, 0x18, 0x6e, + 0x18, 0x6e, 0x02, 0xbd, 0x00, 0x00, 0x02, 0x40, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, + 0x00, 0x03, 0x5f, 0x00, 0x21, 0x22, 0x00, 0x00, + 0xf4, 0x00, 0x00, 0x18, 0x22, 0x20, 0x00, 0xa0, + 0x00, 0x01, 0x00, 0x10, 0x08, 0xed, 0x00, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x74, 0xb2, 0x4e, 0x7a, +}; diff --git a/src/rp2040.zig b/src/rp2040.zig new file mode 100644 index 0000000..e96b901 --- /dev/null +++ b/src/rp2040.zig @@ -0,0 +1,29422 @@ +// this file was generated by regz: https://github.com/ZigEmbeddedGroup/regz +// commit: 09c331e02d8037bf2e5133eaa40b1d762637b441 +// +// vendor: Raspberry Pi +// device: RP2040 +// cpu: CM0PLUS + +pub const VectorTable = extern struct { + initial_stack_pointer: u32, + Reset: InterruptVector = unhandled, + NMI: InterruptVector = unhandled, + HardFault: InterruptVector = unhandled, + reserved0: [7]u32 = undefined, + SVCall: InterruptVector = unhandled, + reserved1: [2]u32 = undefined, + PendSV: InterruptVector = unhandled, + SysTick: InterruptVector = unhandled, + TIMER_IRQ_0: InterruptVector = unhandled, + TIMER_IRQ_1: InterruptVector = unhandled, + TIMER_IRQ_2: InterruptVector = unhandled, + TIMER_IRQ_3: InterruptVector = unhandled, + PWM_IRQ_WRAP: InterruptVector = unhandled, + USBCTRL_IRQ: InterruptVector = unhandled, + XIP_IRQ: InterruptVector = unhandled, + PIO0_IRQ_0: InterruptVector = unhandled, + PIO0_IRQ_1: InterruptVector = unhandled, + PIO1_IRQ_0: InterruptVector = unhandled, + PIO1_IRQ_1: InterruptVector = unhandled, + DMA_IRQ_0: InterruptVector = unhandled, + DMA_IRQ_1: InterruptVector = unhandled, + IO_IRQ_BANK0: InterruptVector = unhandled, + IO_IRQ_QSPI: InterruptVector = unhandled, + SIO_IRQ_PROC0: InterruptVector = unhandled, + SIO_IRQ_PROC1: InterruptVector = unhandled, + CLOCKS_IRQ: InterruptVector = unhandled, + SPI0_IRQ: InterruptVector = unhandled, + SPI1_IRQ: InterruptVector = unhandled, + UART0_IRQ: InterruptVector = unhandled, + UART1_IRQ: InterruptVector = unhandled, + ADC_IRQ_FIFO: InterruptVector = unhandled, + I2C0_IRQ: InterruptVector = unhandled, + I2C1_IRQ: InterruptVector = unhandled, + RTC_IRQ: InterruptVector = unhandled, +}; + +pub const registers = struct { + + /// System Control Space + pub const SCS = struct { + pub const base_address = 0xe000e000; + + /// System Tick Timer + pub const SysTick = struct { + + /// address: 0xe000e010 + /// SysTick Control and Status Register + pub const CTRL = @intToPtr(*volatile Mmio(32, packed struct { + ENABLE: u1, + TICKINT: u1, + CLKSOURCE: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + COUNTFLAG: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + }), base_address + 0x10); + + /// address: 0xe000e014 + /// SysTick Reload Value Register + pub const LOAD = @intToPtr(*volatile Mmio(32, packed struct { + RELOAD: u24, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x14); + + /// address: 0xe000e018 + /// SysTick Current Value Register + pub const VAL = @intToPtr(*volatile Mmio(32, packed struct { + CURRENT: u24, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x18); + + /// address: 0xe000e01c + /// SysTick Calibration Register + pub const CALIB = @intToPtr(*volatile Mmio(32, packed struct { + TENMS: u24, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + SKEW: u1, + NOREF: u1, + }), base_address + 0x1c); + }; + + /// Nested Vectored Interrupt Controller + pub const NVIC = struct { + + /// address: 0xe000e100 + /// Interrupt Set Enable Register + pub const ISER = @intToPtr(*volatile u32, base_address + 0x100); + + /// address: 0xe000e180 + /// Interrupt Clear Enable Register + pub const ICER = @intToPtr(*volatile u32, base_address + 0x180); + + /// address: 0xe000e200 + /// Interrupt Set Pending Register + pub const ISPR = @intToPtr(*volatile u32, base_address + 0x200); + + /// address: 0xe000e280 + /// Interrupt Clear Pending Register + pub const ICPR = @intToPtr(*volatile u32, base_address + 0x280); + + /// address: 0xe000e400 + /// Interrupt Priority Register + pub const IP = @intToPtr(*volatile u32, base_address + 0x400); + }; + + /// System Control Block + pub const SCB = struct { + + /// address: 0xe000ed00 + pub const CPUID = @intToPtr(*volatile Mmio(32, packed struct { + REVISION: u4, + PARTNO: u12, + ARCHITECTURE: u4, + VARIANT: u4, + IMPLEMENTER: u8, + }), base_address + 0xd00); + + /// address: 0xe000ed04 + /// Interrupt Control and State Register + pub const ICSR = @intToPtr(*volatile Mmio(32, packed struct { + VECTACTIVE: u9, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + VECTPENDING: u9, + reserved3: u1 = 0, + ISRPENDING: u1, + ISRPREEMPT: u1, + reserved4: u1 = 0, + PENDSTCLR: u1, + PENDSTSET: u1, + PENDSVCLR: u1, + PENDSVSET: u1, + reserved5: u1 = 0, + reserved6: u1 = 0, + NMIPENDSET: u1, + }), base_address + 0xd04); + + /// address: 0xe000ed0c + /// Application Interrupt and Reset Control Register + pub const AIRCR = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + VECTCLRACTIVE: u1, + SYSRESETREQ: u1, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + ENDIANESS: u1, + VECTKEY: u16, + }), base_address + 0xd0c); + + /// address: 0xe000ed10 + /// System Control Register + pub const SCR = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + SLEEPONEXIT: u1, + SLEEPDEEP: u1, + reserved1: u1 = 0, + SEVONPEND: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + }), base_address + 0xd10); + + /// address: 0xe000ed14 + /// Configuration Control Register + pub const CCR = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + UNALIGN_TRP: u1, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + STKALIGN: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + }), base_address + 0xd14); + + /// address: 0xe000ed1c + /// System Handlers Priority Registers. [0] is RESERVED + pub const SHP = @intToPtr(*volatile u32, base_address + 0xd1c); + + /// address: 0xe000ed24 + /// System Handler Control and State Register + pub const SHCSR = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + SVCALLPENDED: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + }), base_address + 0xd24); + + /// address: 0xe000ed08 + /// Vector Table Offset Register + pub const VTOR = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + TBLOFF: u24, + }), base_address + 0xd08); + }; + + /// Memory Protection Unit + pub const MPU = struct { + + /// address: 0xe000ed90 + /// MPU Type Register + pub const TYPE = @intToPtr(*volatile Mmio(32, packed struct { + SEPARATE: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + DREGION: u8, + IREGION: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0xd90); + + /// address: 0xe000ed94 + /// MPU Control Register + pub const CTRL = @intToPtr(*volatile Mmio(32, packed struct { + ENABLE: u1, + HFNMIENA: u1, + PRIVDEFENA: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + }), base_address + 0xd94); + + /// address: 0xe000ed98 + /// MPU Region RNRber Register + pub const RNR = @intToPtr(*volatile Mmio(32, packed struct { + REGION: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0xd98); + + /// address: 0xe000ed9c + /// MPU Region Base Address Register + pub const RBAR = @intToPtr(*volatile Mmio(32, packed struct { + REGION: u4, + VALID: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + ADDR: u24, + }), base_address + 0xd9c); + + /// address: 0xe000eda0 + /// MPU Region Attribute and Size Register + pub const RASR = @intToPtr(*volatile Mmio(32, packed struct { + ENABLE: u1, + SIZE: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + SRD: u8, + B: u1, + C: u1, + S: u1, + TEX: u3, + reserved2: u1 = 0, + reserved3: u1 = 0, + AP: u3, + reserved4: u1 = 0, + XN: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + }), base_address + 0xda0); + }; + }; + + /// QSPI flash execute-in-place block + pub const XIP_CTRL = struct { + pub const base_address = 0x14000000; + pub const version = "1"; + + /// address: 0x14000000 + /// Cache control + pub const CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// When 1, enable the cache. When the cache is disabled, all XIP accesses\n + /// will go straight to the flash, without querying the cache. When enabled,\n + /// cacheable XIP accesses will query the cache, and the flash will\n + /// not be accessed if the tag matches and the valid bit is set.\n\n + /// If the cache is enabled, cache-as-SRAM accesses have no effect on the\n + /// cache data RAM, and will produce a bus error response. + EN: u1, + /// When 1, writes to any alias other than 0x0 (caching, allocating)\n + /// will produce a bus fault. When 0, these writes are silently ignored.\n + /// In either case, writes to the 0x0 alias will deallocate on tag match,\n + /// as usual. + ERR_BADWRITE: u1, + reserved0: u1 = 0, + /// When 1, the cache memories are powered down. They retain state,\n + /// but can not be accessed. This reduces static power dissipation.\n + /// Writing 1 to this bit forces CTRL_EN to 0, i.e. the cache cannot\n + /// be enabled when powered down.\n + /// Cache-as-SRAM accesses will produce a bus error response when\n + /// the cache is powered down. + POWER_DOWN: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + }), base_address + 0x0); + + /// address: 0x14000004 + /// Cache Flush control + pub const FLUSH = @intToPtr(*volatile MmioInt(32, u1), base_address + 0x4); + + /// address: 0x14000008 + /// Cache Status + pub const STAT = @intToPtr(*volatile Mmio(32, packed struct { + /// Reads as 0 while a cache flush is in progress, and 1 otherwise.\n + /// The cache is flushed whenever the XIP block is reset, and also\n + /// when requested via the FLUSH register. + FLUSH_READY: u1, + /// When 1, indicates the XIP streaming FIFO is completely empty. + FIFO_EMPTY: u1, + /// When 1, indicates the XIP streaming FIFO is completely full.\n + /// The streaming FIFO is 2 entries deep, so the full and empty\n + /// flag allow its level to be ascertained. + FIFO_FULL: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + }), base_address + 0x8); + + /// address: 0x1400000c + /// Cache Hit counter\n + /// A 32 bit saturating counter that increments upon each cache hit,\n + /// i.e. when an XIP access is serviced directly from cached data.\n + /// Write any value to clear. + pub const CTR_HIT = @intToPtr(*volatile u32, base_address + 0xc); + + /// address: 0x14000010 + /// Cache Access counter\n + /// A 32 bit saturating counter that increments upon each XIP access,\n + /// whether the cache is hit or not. This includes noncacheable accesses.\n + /// Write any value to clear. + pub const CTR_ACC = @intToPtr(*volatile u32, base_address + 0x10); + + /// address: 0x14000014 + /// FIFO stream address + pub const STREAM_ADDR = @intToPtr(*volatile MmioInt(32, u30), base_address + 0x14); + + /// address: 0x14000018 + /// FIFO stream control + pub const STREAM_CTR = @intToPtr(*volatile MmioInt(32, u22), base_address + 0x18); + + /// address: 0x1400001c + /// FIFO stream data\n + /// Streamed data is buffered here, for retrieval by the system DMA.\n + /// This FIFO can also be accessed via the XIP_AUX slave, to avoid exposing\n + /// the DMA to bus stalls caused by other XIP traffic. + pub const STREAM_FIFO = @intToPtr(*volatile u32, base_address + 0x1c); + }; + + /// DW_apb_ssi has the following features:\n + /// * APB interface – Allows for easy integration into a DesignWare Synthesizable + /// Components for AMBA 2 implementation.\n + /// * APB3 and APB4 protocol support.\n + /// * Scalable APB data bus width – Supports APB data bus widths of 8, 16, and 32 + /// bits.\n + /// * Serial-master or serial-slave operation – Enables serial communication with + /// serial-master or serial-slave peripheral devices.\n + /// * Programmable Dual/Quad/Octal SPI support in Master Mode.\n + /// * Dual Data Rate (DDR) and Read Data Strobe (RDS) Support - Enables the + /// DW_apb_ssi master to perform operations with the device in DDR and RDS modes + /// when working in Dual/Quad/Octal mode of operation.\n + /// * Data Mask Support - Enables the DW_apb_ssi to selectively update the bytes in + /// the device. This feature is applicable only in enhanced SPI modes.\n + /// * eXecute-In-Place (XIP) support - Enables the DW_apb_ssi master to behave as a + /// memory mapped I/O and fetches the data from the device based on the APB read + /// request. This feature is applicable only in enhanced SPI modes.\n + /// * DMA Controller Interface – Enables the DW_apb_ssi to interface to a DMA + /// controller over the bus using a handshaking interface for transfer requests.\n + /// * Independent masking of interrupts – Master collision, transmit FIFO + /// overflow, transmit FIFO empty, receive FIFO full, receive FIFO underflow, and + /// receive FIFO overflow interrupts can all be masked independently.\n + /// * Multi-master contention detection – Informs the processor of multiple + /// serial-master accesses on the serial bus.\n + /// * Bypass of meta-stability flip-flops for synchronous clocks – When the APB + /// clock (pclk) and the DW_apb_ssi serial clock (ssi_clk) are synchronous, + /// meta-stable flip-flops are not used when transferring control signals across + /// these clock domains.\n + /// * Programmable delay on the sample time of the received serial data bit (rxd); + /// enables programmable control of routing delays resulting in higher serial + /// data-bit rates.\n + /// * Programmable features:\n + /// - Serial interface operation – Choice of Motorola SPI, Texas Instruments + /// Synchronous Serial Protocol or National Semiconductor Microwire.\n + /// - Clock bit-rate – Dynamic control of the serial bit rate of the data + /// transfer; used in only serial-master mode of operation.\n + /// - Data Item size (4 to 32 bits) – Item size of each data transfer under the + /// control of the programmer.\n + /// * Configured features:\n + /// - FIFO depth – 16 words deep. The FIFO width is fixed at 32 bits.\n + /// - 1 slave select output.\n + /// - Hardware slave-select – Dedicated hardware slave-select line.\n + /// - Combined interrupt line - one combined interrupt line from the DW_apb_ssi to + /// the interrupt controller.\n + /// - Interrupt polarity – active high interrupt lines.\n + /// - Serial clock polarity – low serial-clock polarity directly after reset.\n + /// - Serial clock phase – capture on first edge of serial-clock directly after + /// reset. + pub const XIP_SSI = struct { + pub const base_address = 0x18000000; + pub const version = "1"; + + /// address: 0x18000000 + /// Control register 0 + pub const CTRLR0 = @intToPtr(*volatile Mmio(32, packed struct { + /// Data frame size + DFS: u4, + /// Frame format + FRF: u2, + /// Serial clock phase + SCPH: u1, + /// Serial clock polarity + SCPOL: u1, + /// Transfer mode + TMOD: u2, + /// Slave output enable + SLV_OE: u1, + /// Shift register loop (test mode) + SRL: u1, + /// Control frame size\n + /// Value of n -> n+1 clocks per frame. + CFS: u4, + /// Data frame size in 32b transfer mode\n + /// Value of n -> n+1 clocks per frame. + DFS_32: u5, + /// SPI frame format + SPI_FRF: u2, + reserved0: u1 = 0, + /// Slave select toggle enable + SSTE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + }), base_address + 0x0); + + /// address: 0x18000004 + /// Master Control register 1 + pub const CTRLR1 = @intToPtr(*volatile Mmio(32, packed struct { + /// Number of data frames + NDF: u16, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + }), base_address + 0x4); + + /// address: 0x18000008 + /// SSI Enable + pub const SSIENR = @intToPtr(*volatile Mmio(32, packed struct { + /// SSI enable + SSI_EN: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x8); + + /// address: 0x1800000c + /// Microwire Control + pub const MWCR = @intToPtr(*volatile Mmio(32, packed struct { + /// Microwire transfer mode + MWMOD: u1, + /// Microwire control + MDD: u1, + /// Microwire handshaking + MHS: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + }), base_address + 0xc); + + /// address: 0x18000010 + /// Slave enable + pub const SER = @intToPtr(*volatile MmioInt(32, u1), base_address + 0x10); + + /// address: 0x18000014 + /// Baud rate + pub const BAUDR = @intToPtr(*volatile Mmio(32, packed struct { + /// SSI clock divider + SCKDV: u16, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + }), base_address + 0x14); + + /// address: 0x18000018 + /// TX FIFO threshold level + pub const TXFTLR = @intToPtr(*volatile Mmio(32, packed struct { + /// Transmit FIFO threshold + TFT: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x18); + + /// address: 0x1800001c + /// RX FIFO threshold level + pub const RXFTLR = @intToPtr(*volatile Mmio(32, packed struct { + /// Receive FIFO threshold + RFT: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x1c); + + /// address: 0x18000020 + /// TX FIFO level + pub const TXFLR = @intToPtr(*volatile Mmio(32, packed struct { + /// Transmit FIFO level + TFTFL: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x20); + + /// address: 0x18000024 + /// RX FIFO level + pub const RXFLR = @intToPtr(*volatile Mmio(32, packed struct { + /// Receive FIFO level + RXTFL: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x24); + + /// address: 0x18000028 + /// Status register + pub const SR = @intToPtr(*volatile Mmio(32, packed struct { + /// SSI busy flag + BUSY: u1, + /// Transmit FIFO not full + TFNF: u1, + /// Transmit FIFO empty + TFE: u1, + /// Receive FIFO not empty + RFNE: u1, + /// Receive FIFO full + RFF: u1, + /// Transmission error + TXE: u1, + /// Data collision error + DCOL: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + }), base_address + 0x28); + + /// address: 0x1800002c + /// Interrupt mask + pub const IMR = @intToPtr(*volatile Mmio(32, packed struct { + /// Transmit FIFO empty interrupt mask + TXEIM: u1, + /// Transmit FIFO overflow interrupt mask + TXOIM: u1, + /// Receive FIFO underflow interrupt mask + RXUIM: u1, + /// Receive FIFO overflow interrupt mask + RXOIM: u1, + /// Receive FIFO full interrupt mask + RXFIM: u1, + /// Multi-master contention interrupt mask + MSTIM: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + }), base_address + 0x2c); + + /// address: 0x18000030 + /// Interrupt status + pub const ISR = @intToPtr(*volatile Mmio(32, packed struct { + /// Transmit FIFO empty interrupt status + TXEIS: u1, + /// Transmit FIFO overflow interrupt status + TXOIS: u1, + /// Receive FIFO underflow interrupt status + RXUIS: u1, + /// Receive FIFO overflow interrupt status + RXOIS: u1, + /// Receive FIFO full interrupt status + RXFIS: u1, + /// Multi-master contention interrupt status + MSTIS: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + }), base_address + 0x30); + + /// address: 0x18000034 + /// Raw interrupt status + pub const RISR = @intToPtr(*volatile Mmio(32, packed struct { + /// Transmit FIFO empty raw interrupt status + TXEIR: u1, + /// Transmit FIFO overflow raw interrupt status + TXOIR: u1, + /// Receive FIFO underflow raw interrupt status + RXUIR: u1, + /// Receive FIFO overflow raw interrupt status + RXOIR: u1, + /// Receive FIFO full raw interrupt status + RXFIR: u1, + /// Multi-master contention raw interrupt status + MSTIR: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + }), base_address + 0x34); + + /// address: 0x18000038 + /// TX FIFO overflow interrupt clear + pub const TXOICR = @intToPtr(*volatile MmioInt(32, u1), base_address + 0x38); + + /// address: 0x1800003c + /// RX FIFO overflow interrupt clear + pub const RXOICR = @intToPtr(*volatile MmioInt(32, u1), base_address + 0x3c); + + /// address: 0x18000040 + /// RX FIFO underflow interrupt clear + pub const RXUICR = @intToPtr(*volatile MmioInt(32, u1), base_address + 0x40); + + /// address: 0x18000044 + /// Multi-master interrupt clear + pub const MSTICR = @intToPtr(*volatile MmioInt(32, u1), base_address + 0x44); + + /// address: 0x18000048 + /// Interrupt clear + pub const ICR = @intToPtr(*volatile MmioInt(32, u1), base_address + 0x48); + + /// address: 0x1800004c + /// DMA control + pub const DMACR = @intToPtr(*volatile Mmio(32, packed struct { + /// Receive DMA enable + RDMAE: u1, + /// Transmit DMA enable + TDMAE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + }), base_address + 0x4c); + + /// address: 0x18000050 + /// DMA TX data level + pub const DMATDLR = @intToPtr(*volatile Mmio(32, packed struct { + /// Transmit data watermark level + DMATDL: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x50); + + /// address: 0x18000054 + /// DMA RX data level + pub const DMARDLR = @intToPtr(*volatile Mmio(32, packed struct { + /// Receive data watermark level (DMARDLR+1) + DMARDL: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x54); + + /// address: 0x18000058 + /// Identification register + pub const IDR = @intToPtr(*volatile Mmio(32, packed struct { + /// Peripheral dentification code + IDCODE: u32, + }), base_address + 0x58); + + /// address: 0x1800005c + /// Version ID + pub const SSI_VERSION_ID = @intToPtr(*volatile Mmio(32, packed struct { + /// SNPS component version (format X.YY) + SSI_COMP_VERSION: u32, + }), base_address + 0x5c); + + /// address: 0x18000060 + /// Data Register 0 (of 36) + pub const DR0 = @intToPtr(*volatile Mmio(32, packed struct { + /// First data register of 36 + DR: u32, + }), base_address + 0x60); + + /// address: 0x180000f0 + /// RX sample delay + pub const RX_SAMPLE_DLY = @intToPtr(*volatile Mmio(32, packed struct { + /// RXD sample delay (in SCLK cycles) + RSD: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0xf0); + + /// address: 0x180000f4 + /// SPI control + pub const SPI_CTRLR0 = @intToPtr(*volatile Mmio(32, packed struct { + /// Address and instruction transfer format + TRANS_TYPE: u2, + /// Address length (0b-60b in 4b increments) + ADDR_L: u4, + reserved0: u1 = 0, + reserved1: u1 = 0, + /// Instruction length (0/4/8/16b) + INST_L: u2, + reserved2: u1 = 0, + /// Wait cycles between control frame transmit and data reception (in SCLK cycles) + WAIT_CYCLES: u5, + /// SPI DDR transfer enable + SPI_DDR_EN: u1, + /// Instruction DDR transfer enable + INST_DDR_EN: u1, + /// Read data strobe enable + SPI_RXDS_EN: u1, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// SPI Command to send in XIP mode (INST_L = 8-bit) or to append to Address (INST_L + /// = 0-bit) + XIP_CMD: u8, + }), base_address + 0xf4); + + /// address: 0x180000f8 + /// TX drive edge + pub const TXD_DRIVE_EDGE = @intToPtr(*volatile Mmio(32, packed struct { + /// TXD drive edge + TDE: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0xf8); + }; + pub const SYSINFO = struct { + pub const base_address = 0x40000000; + pub const version = "1"; + + /// address: 0x40000000 + /// JEDEC JEP-106 compliant chip identifier. + pub const CHIP_ID = @intToPtr(*volatile Mmio(32, packed struct { + MANUFACTURER: u12, + PART: u16, + REVISION: u4, + }), base_address + 0x0); + + /// address: 0x40000004 + /// Platform register. Allows software to know what environment it is running in. + pub const PLATFORM = @intToPtr(*volatile Mmio(32, packed struct { + FPGA: u1, + ASIC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + }), base_address + 0x4); + + /// address: 0x40000040 + /// Git hash of the chip source. Used to identify chip version. + pub const GITREF_RP2040 = @intToPtr(*volatile u32, base_address + 0x40); + }; + + /// Register block for various chip control signals + pub const SYSCFG = struct { + pub const base_address = 0x40004000; + pub const version = "1"; + + /// address: 0x40004000 + /// Processor core 0 NMI source mask\n + /// Set a bit high to enable NMI from that IRQ + pub const PROC0_NMI_MASK = @intToPtr(*volatile u32, base_address + 0x0); + + /// address: 0x40004004 + /// Processor core 1 NMI source mask\n + /// Set a bit high to enable NMI from that IRQ + pub const PROC1_NMI_MASK = @intToPtr(*volatile u32, base_address + 0x4); + + /// address: 0x40004008 + /// Configuration for processors + pub const PROC_CONFIG = @intToPtr(*volatile Mmio(32, packed struct { + /// Indication that proc0 has halted + PROC0_HALTED: u1, + /// Indication that proc1 has halted + PROC1_HALTED: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + reserved18: u1 = 0, + reserved19: u1 = 0, + reserved20: u1 = 0, + reserved21: u1 = 0, + /// Configure proc0 DAP instance ID.\n + /// Recommend that this is NOT changed until you require debug access in multi-chip + /// environment\n + /// WARNING: do not set to 15 as this is reserved for RescueDP + PROC0_DAP_INSTID: u4, + /// Configure proc1 DAP instance ID.\n + /// Recommend that this is NOT changed until you require debug access in multi-chip + /// environment\n + /// WARNING: do not set to 15 as this is reserved for RescueDP + PROC1_DAP_INSTID: u4, + }), base_address + 0x8); + + /// address: 0x4000400c + /// For each bit, if 1, bypass the input synchronizer between that GPIO\n + /// and the GPIO input register in the SIO. The input synchronizers should\n + /// generally be unbypassed, to avoid injecting metastabilities into processors.\n + /// If you're feeling brave, you can bypass to save two cycles of input\n + /// latency. This register applies to GPIO 0...29. + pub const PROC_IN_SYNC_BYPASS = @intToPtr(*volatile MmioInt(32, u30), base_address + 0xc); + + /// address: 0x40004010 + /// For each bit, if 1, bypass the input synchronizer between that GPIO\n + /// and the GPIO input register in the SIO. The input synchronizers should\n + /// generally be unbypassed, to avoid injecting metastabilities into processors.\n + /// If you're feeling brave, you can bypass to save two cycles of input\n + /// latency. This register applies to GPIO 30...35 (the QSPI IOs). + pub const PROC_IN_SYNC_BYPASS_HI = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x10); + + /// address: 0x40004014 + /// Directly control the SWD debug port of either processor + pub const DBGFORCE = @intToPtr(*volatile Mmio(32, packed struct { + /// Observe the value of processor 0 SWDIO output. + PROC0_SWDO: u1, + /// Directly drive processor 0 SWDIO input, if PROC0_ATTACH is set + PROC0_SWDI: u1, + /// Directly drive processor 0 SWCLK, if PROC0_ATTACH is set + PROC0_SWCLK: u1, + /// Attach processor 0 debug port to syscfg controls, and disconnect it from + /// external SWD pads. + PROC0_ATTACH: u1, + /// Observe the value of processor 1 SWDIO output. + PROC1_SWDO: u1, + /// Directly drive processor 1 SWDIO input, if PROC1_ATTACH is set + PROC1_SWDI: u1, + /// Directly drive processor 1 SWCLK, if PROC1_ATTACH is set + PROC1_SWCLK: u1, + /// Attach processor 1 debug port to syscfg controls, and disconnect it from + /// external SWD pads. + PROC1_ATTACH: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x14); + + /// address: 0x40004018 + /// Control power downs to memories. Set high to power down memories.\n + /// Use with extreme caution + pub const MEMPOWERDOWN = @intToPtr(*volatile Mmio(32, packed struct { + SRAM0: u1, + SRAM1: u1, + SRAM2: u1, + SRAM3: u1, + SRAM4: u1, + SRAM5: u1, + USB: u1, + ROM: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x18); + }; + pub const CLOCKS = struct { + pub const base_address = 0x40008000; + pub const version = "1"; + + /// address: 0x40008000 + /// Clock control, can be changed on-the-fly (except for auxsrc) + pub const CLK_GPOUT0_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + /// Selects the auxiliary clock source, will glitch when switching + AUXSRC: u4, + reserved5: u1 = 0, + /// Asynchronously kills the clock generator + KILL: u1, + /// Starts and stops the clock generator cleanly + ENABLE: u1, + /// Enables duty cycle correction for odd divisors + DC50: u1, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + /// This delays the enable signal by up to 3 cycles of the input clock\n + /// This must be set before the clock is enabled to have any effect + PHASE: u2, + reserved9: u1 = 0, + reserved10: u1 = 0, + /// An edge on this signal shifts the phase of the output by 1 cycle of the input + /// clock\n + /// This can be done at any time + NUDGE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + }), base_address + 0x0); + + /// address: 0x40008004 + /// Clock divisor, can be changed on-the-fly + pub const CLK_GPOUT0_DIV = @intToPtr(*volatile Mmio(32, packed struct { + /// Fractional component of the divisor + FRAC: u8, + /// Integer component of the divisor, 0 -> divide by 2^16 + INT: u24, + }), base_address + 0x4); + + /// address: 0x40008008 + /// Indicates which SRC is currently selected by the glitchless mux (one-hot).\n + /// This slice does not have a glitchless mux (only the AUX_SRC field is present, + /// not SRC) so this register is hardwired to 0x1. + pub const CLK_GPOUT0_SELECTED = @intToPtr(*volatile u32, base_address + 0x8); + + /// address: 0x4000800c + /// Clock control, can be changed on-the-fly (except for auxsrc) + pub const CLK_GPOUT1_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + /// Selects the auxiliary clock source, will glitch when switching + AUXSRC: u4, + reserved5: u1 = 0, + /// Asynchronously kills the clock generator + KILL: u1, + /// Starts and stops the clock generator cleanly + ENABLE: u1, + /// Enables duty cycle correction for odd divisors + DC50: u1, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + /// This delays the enable signal by up to 3 cycles of the input clock\n + /// This must be set before the clock is enabled to have any effect + PHASE: u2, + reserved9: u1 = 0, + reserved10: u1 = 0, + /// An edge on this signal shifts the phase of the output by 1 cycle of the input + /// clock\n + /// This can be done at any time + NUDGE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + }), base_address + 0xc); + + /// address: 0x40008010 + /// Clock divisor, can be changed on-the-fly + pub const CLK_GPOUT1_DIV = @intToPtr(*volatile Mmio(32, packed struct { + /// Fractional component of the divisor + FRAC: u8, + /// Integer component of the divisor, 0 -> divide by 2^16 + INT: u24, + }), base_address + 0x10); + + /// address: 0x40008014 + /// Indicates which SRC is currently selected by the glitchless mux (one-hot).\n + /// This slice does not have a glitchless mux (only the AUX_SRC field is present, + /// not SRC) so this register is hardwired to 0x1. + pub const CLK_GPOUT1_SELECTED = @intToPtr(*volatile u32, base_address + 0x14); + + /// address: 0x40008018 + /// Clock control, can be changed on-the-fly (except for auxsrc) + pub const CLK_GPOUT2_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + /// Selects the auxiliary clock source, will glitch when switching + AUXSRC: u4, + reserved5: u1 = 0, + /// Asynchronously kills the clock generator + KILL: u1, + /// Starts and stops the clock generator cleanly + ENABLE: u1, + /// Enables duty cycle correction for odd divisors + DC50: u1, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + /// This delays the enable signal by up to 3 cycles of the input clock\n + /// This must be set before the clock is enabled to have any effect + PHASE: u2, + reserved9: u1 = 0, + reserved10: u1 = 0, + /// An edge on this signal shifts the phase of the output by 1 cycle of the input + /// clock\n + /// This can be done at any time + NUDGE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + }), base_address + 0x18); + + /// address: 0x4000801c + /// Clock divisor, can be changed on-the-fly + pub const CLK_GPOUT2_DIV = @intToPtr(*volatile Mmio(32, packed struct { + /// Fractional component of the divisor + FRAC: u8, + /// Integer component of the divisor, 0 -> divide by 2^16 + INT: u24, + }), base_address + 0x1c); + + /// address: 0x40008020 + /// Indicates which SRC is currently selected by the glitchless mux (one-hot).\n + /// This slice does not have a glitchless mux (only the AUX_SRC field is present, + /// not SRC) so this register is hardwired to 0x1. + pub const CLK_GPOUT2_SELECTED = @intToPtr(*volatile u32, base_address + 0x20); + + /// address: 0x40008024 + /// Clock control, can be changed on-the-fly (except for auxsrc) + pub const CLK_GPOUT3_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + /// Selects the auxiliary clock source, will glitch when switching + AUXSRC: u4, + reserved5: u1 = 0, + /// Asynchronously kills the clock generator + KILL: u1, + /// Starts and stops the clock generator cleanly + ENABLE: u1, + /// Enables duty cycle correction for odd divisors + DC50: u1, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + /// This delays the enable signal by up to 3 cycles of the input clock\n + /// This must be set before the clock is enabled to have any effect + PHASE: u2, + reserved9: u1 = 0, + reserved10: u1 = 0, + /// An edge on this signal shifts the phase of the output by 1 cycle of the input + /// clock\n + /// This can be done at any time + NUDGE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + }), base_address + 0x24); + + /// address: 0x40008028 + /// Clock divisor, can be changed on-the-fly + pub const CLK_GPOUT3_DIV = @intToPtr(*volatile Mmio(32, packed struct { + /// Fractional component of the divisor + FRAC: u8, + /// Integer component of the divisor, 0 -> divide by 2^16 + INT: u24, + }), base_address + 0x28); + + /// address: 0x4000802c + /// Indicates which SRC is currently selected by the glitchless mux (one-hot).\n + /// This slice does not have a glitchless mux (only the AUX_SRC field is present, + /// not SRC) so this register is hardwired to 0x1. + pub const CLK_GPOUT3_SELECTED = @intToPtr(*volatile u32, base_address + 0x2c); + + /// address: 0x40008030 + /// Clock control, can be changed on-the-fly (except for auxsrc) + pub const CLK_REF_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// Selects the clock source glitchlessly, can be changed on-the-fly + SRC: u2, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + /// Selects the auxiliary clock source, will glitch when switching + AUXSRC: u2, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + }), base_address + 0x30); + + /// address: 0x40008034 + /// Clock divisor, can be changed on-the-fly + pub const CLK_REF_DIV = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// Integer component of the divisor, 0 -> divide by 2^16 + INT: u2, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + }), base_address + 0x34); + + /// address: 0x40008038 + /// Indicates which SRC is currently selected by the glitchless mux (one-hot).\n + /// The glitchless multiplexer does not switch instantaneously (to avoid glitches), + /// so software should poll this register to wait for the switch to complete. This + /// register contains one decoded bit for each of the clock sources enumerated in + /// the CTRL SRC field. At most one of these bits will be set at any time, + /// indicating that clock is currently present at the output of the glitchless mux. + /// Whilst switching is in progress, this register may briefly show all-0s. + pub const CLK_REF_SELECTED = @intToPtr(*volatile u32, base_address + 0x38); + + /// address: 0x4000803c + /// Clock control, can be changed on-the-fly (except for auxsrc) + pub const CLK_SYS_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// Selects the clock source glitchlessly, can be changed on-the-fly + SRC: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + /// Selects the auxiliary clock source, will glitch when switching + AUXSRC: u3, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x3c); + + /// address: 0x40008040 + /// Clock divisor, can be changed on-the-fly + pub const CLK_SYS_DIV = @intToPtr(*volatile Mmio(32, packed struct { + /// Fractional component of the divisor + FRAC: u8, + /// Integer component of the divisor, 0 -> divide by 2^16 + INT: u24, + }), base_address + 0x40); + + /// address: 0x40008044 + /// Indicates which SRC is currently selected by the glitchless mux (one-hot).\n + /// The glitchless multiplexer does not switch instantaneously (to avoid glitches), + /// so software should poll this register to wait for the switch to complete. This + /// register contains one decoded bit for each of the clock sources enumerated in + /// the CTRL SRC field. At most one of these bits will be set at any time, + /// indicating that clock is currently present at the output of the glitchless mux. + /// Whilst switching is in progress, this register may briefly show all-0s. + pub const CLK_SYS_SELECTED = @intToPtr(*volatile u32, base_address + 0x44); + + /// address: 0x40008048 + /// Clock control, can be changed on-the-fly (except for auxsrc) + pub const CLK_PERI_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + /// Selects the auxiliary clock source, will glitch when switching + AUXSRC: u3, + reserved5: u1 = 0, + reserved6: u1 = 0, + /// Asynchronously kills the clock generator + KILL: u1, + /// Starts and stops the clock generator cleanly + ENABLE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x48); + + /// address: 0x40008050 + /// Indicates which SRC is currently selected by the glitchless mux (one-hot).\n + /// This slice does not have a glitchless mux (only the AUX_SRC field is present, + /// not SRC) so this register is hardwired to 0x1. + pub const CLK_PERI_SELECTED = @intToPtr(*volatile u32, base_address + 0x50); + + /// address: 0x40008054 + /// Clock control, can be changed on-the-fly (except for auxsrc) + pub const CLK_USB_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + /// Selects the auxiliary clock source, will glitch when switching + AUXSRC: u3, + reserved5: u1 = 0, + reserved6: u1 = 0, + /// Asynchronously kills the clock generator + KILL: u1, + /// Starts and stops the clock generator cleanly + ENABLE: u1, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + /// This delays the enable signal by up to 3 cycles of the input clock\n + /// This must be set before the clock is enabled to have any effect + PHASE: u2, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// An edge on this signal shifts the phase of the output by 1 cycle of the input + /// clock\n + /// This can be done at any time + NUDGE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + }), base_address + 0x54); + + /// address: 0x40008058 + /// Clock divisor, can be changed on-the-fly + pub const CLK_USB_DIV = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// Integer component of the divisor, 0 -> divide by 2^16 + INT: u2, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + }), base_address + 0x58); + + /// address: 0x4000805c + /// Indicates which SRC is currently selected by the glitchless mux (one-hot).\n + /// This slice does not have a glitchless mux (only the AUX_SRC field is present, + /// not SRC) so this register is hardwired to 0x1. + pub const CLK_USB_SELECTED = @intToPtr(*volatile u32, base_address + 0x5c); + + /// address: 0x40008060 + /// Clock control, can be changed on-the-fly (except for auxsrc) + pub const CLK_ADC_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + /// Selects the auxiliary clock source, will glitch when switching + AUXSRC: u3, + reserved5: u1 = 0, + reserved6: u1 = 0, + /// Asynchronously kills the clock generator + KILL: u1, + /// Starts and stops the clock generator cleanly + ENABLE: u1, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + /// This delays the enable signal by up to 3 cycles of the input clock\n + /// This must be set before the clock is enabled to have any effect + PHASE: u2, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// An edge on this signal shifts the phase of the output by 1 cycle of the input + /// clock\n + /// This can be done at any time + NUDGE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + }), base_address + 0x60); + + /// address: 0x40008064 + /// Clock divisor, can be changed on-the-fly + pub const CLK_ADC_DIV = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// Integer component of the divisor, 0 -> divide by 2^16 + INT: u2, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + }), base_address + 0x64); + + /// address: 0x40008068 + /// Indicates which SRC is currently selected by the glitchless mux (one-hot).\n + /// This slice does not have a glitchless mux (only the AUX_SRC field is present, + /// not SRC) so this register is hardwired to 0x1. + pub const CLK_ADC_SELECTED = @intToPtr(*volatile u32, base_address + 0x68); + + /// address: 0x4000806c + /// Clock control, can be changed on-the-fly (except for auxsrc) + pub const CLK_RTC_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + /// Selects the auxiliary clock source, will glitch when switching + AUXSRC: u3, + reserved5: u1 = 0, + reserved6: u1 = 0, + /// Asynchronously kills the clock generator + KILL: u1, + /// Starts and stops the clock generator cleanly + ENABLE: u1, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + /// This delays the enable signal by up to 3 cycles of the input clock\n + /// This must be set before the clock is enabled to have any effect + PHASE: u2, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// An edge on this signal shifts the phase of the output by 1 cycle of the input + /// clock\n + /// This can be done at any time + NUDGE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + }), base_address + 0x6c); + + /// address: 0x40008070 + /// Clock divisor, can be changed on-the-fly + pub const CLK_RTC_DIV = @intToPtr(*volatile Mmio(32, packed struct { + /// Fractional component of the divisor + FRAC: u8, + /// Integer component of the divisor, 0 -> divide by 2^16 + INT: u24, + }), base_address + 0x70); + + /// address: 0x40008074 + /// Indicates which SRC is currently selected by the glitchless mux (one-hot).\n + /// This slice does not have a glitchless mux (only the AUX_SRC field is present, + /// not SRC) so this register is hardwired to 0x1. + pub const CLK_RTC_SELECTED = @intToPtr(*volatile u32, base_address + 0x74); + + /// address: 0x40008078 + pub const CLK_SYS_RESUS_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// This is expressed as a number of clk_ref cycles\n + /// and must be >= 2x clk_ref_freq/min_clk_tst_freq + TIMEOUT: u8, + /// Enable resus + ENABLE: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + /// Force a resus, for test purposes only + FRCE: u1, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + /// For clearing the resus after the fault that triggered it has been corrected + CLEAR: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + }), base_address + 0x78); + + /// address: 0x4000807c + pub const CLK_SYS_RESUS_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + /// Clock has been resuscitated, correct the error then send ctrl_clear=1 + RESUSSED: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x7c); + + /// address: 0x40008080 + /// Reference clock frequency in kHz + pub const FC0_REF_KHZ = @intToPtr(*volatile MmioInt(32, u20), base_address + 0x80); + + /// address: 0x40008084 + /// Minimum pass frequency in kHz. This is optional. Set to 0 if you are not using + /// the pass/fail flags + pub const FC0_MIN_KHZ = @intToPtr(*volatile MmioInt(32, u25), base_address + 0x84); + + /// address: 0x40008088 + /// Maximum pass frequency in kHz. This is optional. Set to 0x1ffffff if you are not + /// using the pass/fail flags + pub const FC0_MAX_KHZ = @intToPtr(*volatile MmioInt(32, u25), base_address + 0x88); + + /// address: 0x4000808c + /// Delays the start of frequency counting to allow the mux to settle\n + /// Delay is measured in multiples of the reference clock period + pub const FC0_DELAY = @intToPtr(*volatile MmioInt(32, u3), base_address + 0x8c); + + /// address: 0x40008090 + /// The test interval is 0.98us * 2**interval, but let's call it 1us * 2**interval\n + /// The default gives a test interval of 250us + pub const FC0_INTERVAL = @intToPtr(*volatile MmioInt(32, u4), base_address + 0x90); + + /// address: 0x40008094 + /// Clock sent to frequency counter, set to 0 when not required\n + /// Writing to this register initiates the frequency count + pub const FC0_SRC = @intToPtr(*volatile MmioInt(32, u8), base_address + 0x94); + + /// address: 0x40008098 + /// Frequency counter status + pub const FC0_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + /// Test passed + PASS: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + /// Test complete + DONE: u1, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + /// Test running + RUNNING: u1, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + /// Waiting for test clock to start + WAITING: u1, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + /// Test failed + FAIL: u1, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + /// Test clock slower than expected, only valid when status_done=1 + SLOW: u1, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// Test clock faster than expected, only valid when status_done=1 + FAST: u1, + reserved18: u1 = 0, + reserved19: u1 = 0, + reserved20: u1 = 0, + /// Test clock stopped during test + DIED: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + }), base_address + 0x98); + + /// address: 0x4000809c + /// Result of frequency measurement, only valid when status_done=1 + pub const FC0_RESULT = @intToPtr(*volatile Mmio(32, packed struct { + FRAC: u5, + KHZ: u25, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0x9c); + + /// address: 0x400080a0 + /// enable clock in wake mode + pub const WAKE_EN0 = @intToPtr(*volatile Mmio(32, packed struct { + clk_sys_clocks: u1, + clk_adc_adc: u1, + clk_sys_adc: u1, + clk_sys_busctrl: u1, + clk_sys_busfabric: u1, + clk_sys_dma: u1, + clk_sys_i2c0: u1, + clk_sys_i2c1: u1, + clk_sys_io: u1, + clk_sys_jtag: u1, + clk_sys_vreg_and_chip_reset: u1, + clk_sys_pads: u1, + clk_sys_pio0: u1, + clk_sys_pio1: u1, + clk_sys_pll_sys: u1, + clk_sys_pll_usb: u1, + clk_sys_psm: u1, + clk_sys_pwm: u1, + clk_sys_resets: u1, + clk_sys_rom: u1, + clk_sys_rosc: u1, + clk_rtc_rtc: u1, + clk_sys_rtc: u1, + clk_sys_sio: u1, + clk_peri_spi0: u1, + clk_sys_spi0: u1, + clk_peri_spi1: u1, + clk_sys_spi1: u1, + clk_sys_sram0: u1, + clk_sys_sram1: u1, + clk_sys_sram2: u1, + clk_sys_sram3: u1, + }), base_address + 0xa0); + + /// address: 0x400080a4 + /// enable clock in wake mode + pub const WAKE_EN1 = @intToPtr(*volatile Mmio(32, packed struct { + clk_sys_sram4: u1, + clk_sys_sram5: u1, + clk_sys_syscfg: u1, + clk_sys_sysinfo: u1, + clk_sys_tbman: u1, + clk_sys_timer: u1, + clk_peri_uart0: u1, + clk_sys_uart0: u1, + clk_peri_uart1: u1, + clk_sys_uart1: u1, + clk_sys_usbctrl: u1, + clk_usb_usbctrl: u1, + clk_sys_watchdog: u1, + clk_sys_xip: u1, + clk_sys_xosc: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + }), base_address + 0xa4); + + /// address: 0x400080a8 + /// enable clock in sleep mode + pub const SLEEP_EN0 = @intToPtr(*volatile Mmio(32, packed struct { + clk_sys_clocks: u1, + clk_adc_adc: u1, + clk_sys_adc: u1, + clk_sys_busctrl: u1, + clk_sys_busfabric: u1, + clk_sys_dma: u1, + clk_sys_i2c0: u1, + clk_sys_i2c1: u1, + clk_sys_io: u1, + clk_sys_jtag: u1, + clk_sys_vreg_and_chip_reset: u1, + clk_sys_pads: u1, + clk_sys_pio0: u1, + clk_sys_pio1: u1, + clk_sys_pll_sys: u1, + clk_sys_pll_usb: u1, + clk_sys_psm: u1, + clk_sys_pwm: u1, + clk_sys_resets: u1, + clk_sys_rom: u1, + clk_sys_rosc: u1, + clk_rtc_rtc: u1, + clk_sys_rtc: u1, + clk_sys_sio: u1, + clk_peri_spi0: u1, + clk_sys_spi0: u1, + clk_peri_spi1: u1, + clk_sys_spi1: u1, + clk_sys_sram0: u1, + clk_sys_sram1: u1, + clk_sys_sram2: u1, + clk_sys_sram3: u1, + }), base_address + 0xa8); + + /// address: 0x400080ac + /// enable clock in sleep mode + pub const SLEEP_EN1 = @intToPtr(*volatile Mmio(32, packed struct { + clk_sys_sram4: u1, + clk_sys_sram5: u1, + clk_sys_syscfg: u1, + clk_sys_sysinfo: u1, + clk_sys_tbman: u1, + clk_sys_timer: u1, + clk_peri_uart0: u1, + clk_sys_uart0: u1, + clk_peri_uart1: u1, + clk_sys_uart1: u1, + clk_sys_usbctrl: u1, + clk_usb_usbctrl: u1, + clk_sys_watchdog: u1, + clk_sys_xip: u1, + clk_sys_xosc: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + }), base_address + 0xac); + + /// address: 0x400080b0 + /// indicates the state of the clock enable + pub const ENABLED0 = @intToPtr(*volatile Mmio(32, packed struct { + clk_sys_clocks: u1, + clk_adc_adc: u1, + clk_sys_adc: u1, + clk_sys_busctrl: u1, + clk_sys_busfabric: u1, + clk_sys_dma: u1, + clk_sys_i2c0: u1, + clk_sys_i2c1: u1, + clk_sys_io: u1, + clk_sys_jtag: u1, + clk_sys_vreg_and_chip_reset: u1, + clk_sys_pads: u1, + clk_sys_pio0: u1, + clk_sys_pio1: u1, + clk_sys_pll_sys: u1, + clk_sys_pll_usb: u1, + clk_sys_psm: u1, + clk_sys_pwm: u1, + clk_sys_resets: u1, + clk_sys_rom: u1, + clk_sys_rosc: u1, + clk_rtc_rtc: u1, + clk_sys_rtc: u1, + clk_sys_sio: u1, + clk_peri_spi0: u1, + clk_sys_spi0: u1, + clk_peri_spi1: u1, + clk_sys_spi1: u1, + clk_sys_sram0: u1, + clk_sys_sram1: u1, + clk_sys_sram2: u1, + clk_sys_sram3: u1, + }), base_address + 0xb0); + + /// address: 0x400080b4 + /// indicates the state of the clock enable + pub const ENABLED1 = @intToPtr(*volatile Mmio(32, packed struct { + clk_sys_sram4: u1, + clk_sys_sram5: u1, + clk_sys_syscfg: u1, + clk_sys_sysinfo: u1, + clk_sys_tbman: u1, + clk_sys_timer: u1, + clk_peri_uart0: u1, + clk_sys_uart0: u1, + clk_peri_uart1: u1, + clk_sys_uart1: u1, + clk_sys_usbctrl: u1, + clk_usb_usbctrl: u1, + clk_sys_watchdog: u1, + clk_sys_xip: u1, + clk_sys_xosc: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + }), base_address + 0xb4); + + /// address: 0x400080b8 + /// Raw Interrupts + pub const INTR = @intToPtr(*volatile Mmio(32, packed struct { + CLK_SYS_RESUS: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0xb8); + + /// address: 0x400080bc + /// Interrupt Enable + pub const INTE = @intToPtr(*volatile Mmio(32, packed struct { + CLK_SYS_RESUS: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0xbc); + + /// address: 0x400080c0 + /// Interrupt Force + pub const INTF = @intToPtr(*volatile Mmio(32, packed struct { + CLK_SYS_RESUS: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0xc0); + + /// address: 0x400080c4 + /// Interrupt status after masking & forcing + pub const INTS = @intToPtr(*volatile Mmio(32, packed struct { + CLK_SYS_RESUS: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0xc4); + }; + pub const RESETS = struct { + pub const base_address = 0x4000c000; + pub const version = "1"; + + /// address: 0x4000c000 + /// Reset control. If a bit is set it means the peripheral is in reset. 0 means the + /// peripheral's reset is deasserted. + pub const RESET = @intToPtr(*volatile Mmio(32, packed struct { + adc: u1, + busctrl: u1, + dma: u1, + i2c0: u1, + i2c1: u1, + io_bank0: u1, + io_qspi: u1, + jtag: u1, + pads_bank0: u1, + pads_qspi: u1, + pio0: u1, + pio1: u1, + pll_sys: u1, + pll_usb: u1, + pwm: u1, + rtc: u1, + spi0: u1, + spi1: u1, + syscfg: u1, + sysinfo: u1, + tbman: u1, + timer: u1, + uart0: u1, + uart1: u1, + usbctrl: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + }), base_address + 0x0); + + /// address: 0x4000c004 + /// Watchdog select. If a bit is set then the watchdog will reset this peripheral + /// when the watchdog fires. + pub const WDSEL = @intToPtr(*volatile Mmio(32, packed struct { + adc: u1, + busctrl: u1, + dma: u1, + i2c0: u1, + i2c1: u1, + io_bank0: u1, + io_qspi: u1, + jtag: u1, + pads_bank0: u1, + pads_qspi: u1, + pio0: u1, + pio1: u1, + pll_sys: u1, + pll_usb: u1, + pwm: u1, + rtc: u1, + spi0: u1, + spi1: u1, + syscfg: u1, + sysinfo: u1, + tbman: u1, + timer: u1, + uart0: u1, + uart1: u1, + usbctrl: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + }), base_address + 0x4); + + /// address: 0x4000c008 + /// Reset done. If a bit is set then a reset done signal has been returned by the + /// peripheral. This indicates that the peripheral's registers are ready to be + /// accessed. + pub const RESET_DONE = @intToPtr(*volatile Mmio(32, packed struct { + adc: u1, + busctrl: u1, + dma: u1, + i2c0: u1, + i2c1: u1, + io_bank0: u1, + io_qspi: u1, + jtag: u1, + pads_bank0: u1, + pads_qspi: u1, + pio0: u1, + pio1: u1, + pll_sys: u1, + pll_usb: u1, + pwm: u1, + rtc: u1, + spi0: u1, + spi1: u1, + syscfg: u1, + sysinfo: u1, + tbman: u1, + timer: u1, + uart0: u1, + uart1: u1, + usbctrl: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + }), base_address + 0x8); + }; + pub const PSM = struct { + pub const base_address = 0x40010000; + pub const version = "1"; + + /// address: 0x40010000 + /// Force block out of reset (i.e. power it on) + pub const FRCE_ON = @intToPtr(*volatile Mmio(32, packed struct { + rosc: u1, + xosc: u1, + clocks: u1, + resets: u1, + busfabric: u1, + rom: u1, + sram0: u1, + sram1: u1, + sram2: u1, + sram3: u1, + sram4: u1, + sram5: u1, + xip: u1, + vreg_and_chip_reset: u1, + sio: u1, + proc0: u1, + proc1: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + }), base_address + 0x0); + + /// address: 0x40010004 + /// Force into reset (i.e. power it off) + pub const FRCE_OFF = @intToPtr(*volatile Mmio(32, packed struct { + rosc: u1, + xosc: u1, + clocks: u1, + resets: u1, + busfabric: u1, + rom: u1, + sram0: u1, + sram1: u1, + sram2: u1, + sram3: u1, + sram4: u1, + sram5: u1, + xip: u1, + vreg_and_chip_reset: u1, + sio: u1, + proc0: u1, + proc1: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + }), base_address + 0x4); + + /// address: 0x40010008 + /// Set to 1 if this peripheral should be reset when the watchdog fires. + pub const WDSEL = @intToPtr(*volatile Mmio(32, packed struct { + rosc: u1, + xosc: u1, + clocks: u1, + resets: u1, + busfabric: u1, + rom: u1, + sram0: u1, + sram1: u1, + sram2: u1, + sram3: u1, + sram4: u1, + sram5: u1, + xip: u1, + vreg_and_chip_reset: u1, + sio: u1, + proc0: u1, + proc1: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + }), base_address + 0x8); + + /// address: 0x4001000c + /// Indicates the peripheral's registers are ready to access. + pub const DONE = @intToPtr(*volatile Mmio(32, packed struct { + rosc: u1, + xosc: u1, + clocks: u1, + resets: u1, + busfabric: u1, + rom: u1, + sram0: u1, + sram1: u1, + sram2: u1, + sram3: u1, + sram4: u1, + sram5: u1, + xip: u1, + vreg_and_chip_reset: u1, + sio: u1, + proc0: u1, + proc1: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + }), base_address + 0xc); + }; + pub const IO_BANK0 = struct { + pub const base_address = 0x40014000; + pub const version = "1"; + + /// address: 0x40014000 + /// GPIO status + pub const GPIO0_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x0); + + /// address: 0x40014004 + /// GPIO control including function select and overrides. + pub const GPIO0_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0x4); + + /// address: 0x40014008 + /// GPIO status + pub const GPIO1_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x8); + + /// address: 0x4001400c + /// GPIO control including function select and overrides. + pub const GPIO1_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0xc); + + /// address: 0x40014010 + /// GPIO status + pub const GPIO2_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x10); + + /// address: 0x40014014 + /// GPIO control including function select and overrides. + pub const GPIO2_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0x14); + + /// address: 0x40014018 + /// GPIO status + pub const GPIO3_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x18); + + /// address: 0x4001401c + /// GPIO control including function select and overrides. + pub const GPIO3_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0x1c); + + /// address: 0x40014020 + /// GPIO status + pub const GPIO4_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x20); + + /// address: 0x40014024 + /// GPIO control including function select and overrides. + pub const GPIO4_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0x24); + + /// address: 0x40014028 + /// GPIO status + pub const GPIO5_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x28); + + /// address: 0x4001402c + /// GPIO control including function select and overrides. + pub const GPIO5_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0x2c); + + /// address: 0x40014030 + /// GPIO status + pub const GPIO6_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x30); + + /// address: 0x40014034 + /// GPIO control including function select and overrides. + pub const GPIO6_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0x34); + + /// address: 0x40014038 + /// GPIO status + pub const GPIO7_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x38); + + /// address: 0x4001403c + /// GPIO control including function select and overrides. + pub const GPIO7_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0x3c); + + /// address: 0x40014040 + /// GPIO status + pub const GPIO8_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x40); + + /// address: 0x40014044 + /// GPIO control including function select and overrides. + pub const GPIO8_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0x44); + + /// address: 0x40014048 + /// GPIO status + pub const GPIO9_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x48); + + /// address: 0x4001404c + /// GPIO control including function select and overrides. + pub const GPIO9_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0x4c); + + /// address: 0x40014050 + /// GPIO status + pub const GPIO10_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x50); + + /// address: 0x40014054 + /// GPIO control including function select and overrides. + pub const GPIO10_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0x54); + + /// address: 0x40014058 + /// GPIO status + pub const GPIO11_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x58); + + /// address: 0x4001405c + /// GPIO control including function select and overrides. + pub const GPIO11_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0x5c); + + /// address: 0x40014060 + /// GPIO status + pub const GPIO12_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x60); + + /// address: 0x40014064 + /// GPIO control including function select and overrides. + pub const GPIO12_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0x64); + + /// address: 0x40014068 + /// GPIO status + pub const GPIO13_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x68); + + /// address: 0x4001406c + /// GPIO control including function select and overrides. + pub const GPIO13_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0x6c); + + /// address: 0x40014070 + /// GPIO status + pub const GPIO14_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x70); + + /// address: 0x40014074 + /// GPIO control including function select and overrides. + pub const GPIO14_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0x74); + + /// address: 0x40014078 + /// GPIO status + pub const GPIO15_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x78); + + /// address: 0x4001407c + /// GPIO control including function select and overrides. + pub const GPIO15_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0x7c); + + /// address: 0x40014080 + /// GPIO status + pub const GPIO16_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x80); + + /// address: 0x40014084 + /// GPIO control including function select and overrides. + pub const GPIO16_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0x84); + + /// address: 0x40014088 + /// GPIO status + pub const GPIO17_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x88); + + /// address: 0x4001408c + /// GPIO control including function select and overrides. + pub const GPIO17_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0x8c); + + /// address: 0x40014090 + /// GPIO status + pub const GPIO18_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x90); + + /// address: 0x40014094 + /// GPIO control including function select and overrides. + pub const GPIO18_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0x94); + + /// address: 0x40014098 + /// GPIO status + pub const GPIO19_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x98); + + /// address: 0x4001409c + /// GPIO control including function select and overrides. + pub const GPIO19_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0x9c); + + /// address: 0x400140a0 + /// GPIO status + pub const GPIO20_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0xa0); + + /// address: 0x400140a4 + /// GPIO control including function select and overrides. + pub const GPIO20_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0xa4); + + /// address: 0x400140a8 + /// GPIO status + pub const GPIO21_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0xa8); + + /// address: 0x400140ac + /// GPIO control including function select and overrides. + pub const GPIO21_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0xac); + + /// address: 0x400140b0 + /// GPIO status + pub const GPIO22_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0xb0); + + /// address: 0x400140b4 + /// GPIO control including function select and overrides. + pub const GPIO22_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0xb4); + + /// address: 0x400140b8 + /// GPIO status + pub const GPIO23_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0xb8); + + /// address: 0x400140bc + /// GPIO control including function select and overrides. + pub const GPIO23_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0xbc); + + /// address: 0x400140c0 + /// GPIO status + pub const GPIO24_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0xc0); + + /// address: 0x400140c4 + /// GPIO control including function select and overrides. + pub const GPIO24_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0xc4); + + /// address: 0x400140c8 + /// GPIO status + pub const GPIO25_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0xc8); + + /// address: 0x400140cc + /// GPIO control including function select and overrides. + pub const GPIO25_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0xcc); + + /// address: 0x400140d0 + /// GPIO status + pub const GPIO26_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0xd0); + + /// address: 0x400140d4 + /// GPIO control including function select and overrides. + pub const GPIO26_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0xd4); + + /// address: 0x400140d8 + /// GPIO status + pub const GPIO27_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0xd8); + + /// address: 0x400140dc + /// GPIO control including function select and overrides. + pub const GPIO27_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0xdc); + + /// address: 0x400140e0 + /// GPIO status + pub const GPIO28_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0xe0); + + /// address: 0x400140e4 + /// GPIO control including function select and overrides. + pub const GPIO28_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0xe4); + + /// address: 0x400140e8 + /// GPIO status + pub const GPIO29_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0xe8); + + /// address: 0x400140ec + /// GPIO control including function select and overrides. + pub const GPIO29_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0xec); + + /// address: 0x400140f0 + /// Raw Interrupts + pub const INTR0 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO0_LEVEL_LOW: u1, + GPIO0_LEVEL_HIGH: u1, + GPIO0_EDGE_LOW: u1, + GPIO0_EDGE_HIGH: u1, + GPIO1_LEVEL_LOW: u1, + GPIO1_LEVEL_HIGH: u1, + GPIO1_EDGE_LOW: u1, + GPIO1_EDGE_HIGH: u1, + GPIO2_LEVEL_LOW: u1, + GPIO2_LEVEL_HIGH: u1, + GPIO2_EDGE_LOW: u1, + GPIO2_EDGE_HIGH: u1, + GPIO3_LEVEL_LOW: u1, + GPIO3_LEVEL_HIGH: u1, + GPIO3_EDGE_LOW: u1, + GPIO3_EDGE_HIGH: u1, + GPIO4_LEVEL_LOW: u1, + GPIO4_LEVEL_HIGH: u1, + GPIO4_EDGE_LOW: u1, + GPIO4_EDGE_HIGH: u1, + GPIO5_LEVEL_LOW: u1, + GPIO5_LEVEL_HIGH: u1, + GPIO5_EDGE_LOW: u1, + GPIO5_EDGE_HIGH: u1, + GPIO6_LEVEL_LOW: u1, + GPIO6_LEVEL_HIGH: u1, + GPIO6_EDGE_LOW: u1, + GPIO6_EDGE_HIGH: u1, + GPIO7_LEVEL_LOW: u1, + GPIO7_LEVEL_HIGH: u1, + GPIO7_EDGE_LOW: u1, + GPIO7_EDGE_HIGH: u1, + }), base_address + 0xf0); + + /// address: 0x400140f4 + /// Raw Interrupts + pub const INTR1 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO8_LEVEL_LOW: u1, + GPIO8_LEVEL_HIGH: u1, + GPIO8_EDGE_LOW: u1, + GPIO8_EDGE_HIGH: u1, + GPIO9_LEVEL_LOW: u1, + GPIO9_LEVEL_HIGH: u1, + GPIO9_EDGE_LOW: u1, + GPIO9_EDGE_HIGH: u1, + GPIO10_LEVEL_LOW: u1, + GPIO10_LEVEL_HIGH: u1, + GPIO10_EDGE_LOW: u1, + GPIO10_EDGE_HIGH: u1, + GPIO11_LEVEL_LOW: u1, + GPIO11_LEVEL_HIGH: u1, + GPIO11_EDGE_LOW: u1, + GPIO11_EDGE_HIGH: u1, + GPIO12_LEVEL_LOW: u1, + GPIO12_LEVEL_HIGH: u1, + GPIO12_EDGE_LOW: u1, + GPIO12_EDGE_HIGH: u1, + GPIO13_LEVEL_LOW: u1, + GPIO13_LEVEL_HIGH: u1, + GPIO13_EDGE_LOW: u1, + GPIO13_EDGE_HIGH: u1, + GPIO14_LEVEL_LOW: u1, + GPIO14_LEVEL_HIGH: u1, + GPIO14_EDGE_LOW: u1, + GPIO14_EDGE_HIGH: u1, + GPIO15_LEVEL_LOW: u1, + GPIO15_LEVEL_HIGH: u1, + GPIO15_EDGE_LOW: u1, + GPIO15_EDGE_HIGH: u1, + }), base_address + 0xf4); + + /// address: 0x400140f8 + /// Raw Interrupts + pub const INTR2 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO16_LEVEL_LOW: u1, + GPIO16_LEVEL_HIGH: u1, + GPIO16_EDGE_LOW: u1, + GPIO16_EDGE_HIGH: u1, + GPIO17_LEVEL_LOW: u1, + GPIO17_LEVEL_HIGH: u1, + GPIO17_EDGE_LOW: u1, + GPIO17_EDGE_HIGH: u1, + GPIO18_LEVEL_LOW: u1, + GPIO18_LEVEL_HIGH: u1, + GPIO18_EDGE_LOW: u1, + GPIO18_EDGE_HIGH: u1, + GPIO19_LEVEL_LOW: u1, + GPIO19_LEVEL_HIGH: u1, + GPIO19_EDGE_LOW: u1, + GPIO19_EDGE_HIGH: u1, + GPIO20_LEVEL_LOW: u1, + GPIO20_LEVEL_HIGH: u1, + GPIO20_EDGE_LOW: u1, + GPIO20_EDGE_HIGH: u1, + GPIO21_LEVEL_LOW: u1, + GPIO21_LEVEL_HIGH: u1, + GPIO21_EDGE_LOW: u1, + GPIO21_EDGE_HIGH: u1, + GPIO22_LEVEL_LOW: u1, + GPIO22_LEVEL_HIGH: u1, + GPIO22_EDGE_LOW: u1, + GPIO22_EDGE_HIGH: u1, + GPIO23_LEVEL_LOW: u1, + GPIO23_LEVEL_HIGH: u1, + GPIO23_EDGE_LOW: u1, + GPIO23_EDGE_HIGH: u1, + }), base_address + 0xf8); + + /// address: 0x400140fc + /// Raw Interrupts + pub const INTR3 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO24_LEVEL_LOW: u1, + GPIO24_LEVEL_HIGH: u1, + GPIO24_EDGE_LOW: u1, + GPIO24_EDGE_HIGH: u1, + GPIO25_LEVEL_LOW: u1, + GPIO25_LEVEL_HIGH: u1, + GPIO25_EDGE_LOW: u1, + GPIO25_EDGE_HIGH: u1, + GPIO26_LEVEL_LOW: u1, + GPIO26_LEVEL_HIGH: u1, + GPIO26_EDGE_LOW: u1, + GPIO26_EDGE_HIGH: u1, + GPIO27_LEVEL_LOW: u1, + GPIO27_LEVEL_HIGH: u1, + GPIO27_EDGE_LOW: u1, + GPIO27_EDGE_HIGH: u1, + GPIO28_LEVEL_LOW: u1, + GPIO28_LEVEL_HIGH: u1, + GPIO28_EDGE_LOW: u1, + GPIO28_EDGE_HIGH: u1, + GPIO29_LEVEL_LOW: u1, + GPIO29_LEVEL_HIGH: u1, + GPIO29_EDGE_LOW: u1, + GPIO29_EDGE_HIGH: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0xfc); + + /// address: 0x40014100 + /// Interrupt Enable for proc0 + pub const PROC0_INTE0 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO0_LEVEL_LOW: u1, + GPIO0_LEVEL_HIGH: u1, + GPIO0_EDGE_LOW: u1, + GPIO0_EDGE_HIGH: u1, + GPIO1_LEVEL_LOW: u1, + GPIO1_LEVEL_HIGH: u1, + GPIO1_EDGE_LOW: u1, + GPIO1_EDGE_HIGH: u1, + GPIO2_LEVEL_LOW: u1, + GPIO2_LEVEL_HIGH: u1, + GPIO2_EDGE_LOW: u1, + GPIO2_EDGE_HIGH: u1, + GPIO3_LEVEL_LOW: u1, + GPIO3_LEVEL_HIGH: u1, + GPIO3_EDGE_LOW: u1, + GPIO3_EDGE_HIGH: u1, + GPIO4_LEVEL_LOW: u1, + GPIO4_LEVEL_HIGH: u1, + GPIO4_EDGE_LOW: u1, + GPIO4_EDGE_HIGH: u1, + GPIO5_LEVEL_LOW: u1, + GPIO5_LEVEL_HIGH: u1, + GPIO5_EDGE_LOW: u1, + GPIO5_EDGE_HIGH: u1, + GPIO6_LEVEL_LOW: u1, + GPIO6_LEVEL_HIGH: u1, + GPIO6_EDGE_LOW: u1, + GPIO6_EDGE_HIGH: u1, + GPIO7_LEVEL_LOW: u1, + GPIO7_LEVEL_HIGH: u1, + GPIO7_EDGE_LOW: u1, + GPIO7_EDGE_HIGH: u1, + }), base_address + 0x100); + + /// address: 0x40014104 + /// Interrupt Enable for proc0 + pub const PROC0_INTE1 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO8_LEVEL_LOW: u1, + GPIO8_LEVEL_HIGH: u1, + GPIO8_EDGE_LOW: u1, + GPIO8_EDGE_HIGH: u1, + GPIO9_LEVEL_LOW: u1, + GPIO9_LEVEL_HIGH: u1, + GPIO9_EDGE_LOW: u1, + GPIO9_EDGE_HIGH: u1, + GPIO10_LEVEL_LOW: u1, + GPIO10_LEVEL_HIGH: u1, + GPIO10_EDGE_LOW: u1, + GPIO10_EDGE_HIGH: u1, + GPIO11_LEVEL_LOW: u1, + GPIO11_LEVEL_HIGH: u1, + GPIO11_EDGE_LOW: u1, + GPIO11_EDGE_HIGH: u1, + GPIO12_LEVEL_LOW: u1, + GPIO12_LEVEL_HIGH: u1, + GPIO12_EDGE_LOW: u1, + GPIO12_EDGE_HIGH: u1, + GPIO13_LEVEL_LOW: u1, + GPIO13_LEVEL_HIGH: u1, + GPIO13_EDGE_LOW: u1, + GPIO13_EDGE_HIGH: u1, + GPIO14_LEVEL_LOW: u1, + GPIO14_LEVEL_HIGH: u1, + GPIO14_EDGE_LOW: u1, + GPIO14_EDGE_HIGH: u1, + GPIO15_LEVEL_LOW: u1, + GPIO15_LEVEL_HIGH: u1, + GPIO15_EDGE_LOW: u1, + GPIO15_EDGE_HIGH: u1, + }), base_address + 0x104); + + /// address: 0x40014108 + /// Interrupt Enable for proc0 + pub const PROC0_INTE2 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO16_LEVEL_LOW: u1, + GPIO16_LEVEL_HIGH: u1, + GPIO16_EDGE_LOW: u1, + GPIO16_EDGE_HIGH: u1, + GPIO17_LEVEL_LOW: u1, + GPIO17_LEVEL_HIGH: u1, + GPIO17_EDGE_LOW: u1, + GPIO17_EDGE_HIGH: u1, + GPIO18_LEVEL_LOW: u1, + GPIO18_LEVEL_HIGH: u1, + GPIO18_EDGE_LOW: u1, + GPIO18_EDGE_HIGH: u1, + GPIO19_LEVEL_LOW: u1, + GPIO19_LEVEL_HIGH: u1, + GPIO19_EDGE_LOW: u1, + GPIO19_EDGE_HIGH: u1, + GPIO20_LEVEL_LOW: u1, + GPIO20_LEVEL_HIGH: u1, + GPIO20_EDGE_LOW: u1, + GPIO20_EDGE_HIGH: u1, + GPIO21_LEVEL_LOW: u1, + GPIO21_LEVEL_HIGH: u1, + GPIO21_EDGE_LOW: u1, + GPIO21_EDGE_HIGH: u1, + GPIO22_LEVEL_LOW: u1, + GPIO22_LEVEL_HIGH: u1, + GPIO22_EDGE_LOW: u1, + GPIO22_EDGE_HIGH: u1, + GPIO23_LEVEL_LOW: u1, + GPIO23_LEVEL_HIGH: u1, + GPIO23_EDGE_LOW: u1, + GPIO23_EDGE_HIGH: u1, + }), base_address + 0x108); + + /// address: 0x4001410c + /// Interrupt Enable for proc0 + pub const PROC0_INTE3 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO24_LEVEL_LOW: u1, + GPIO24_LEVEL_HIGH: u1, + GPIO24_EDGE_LOW: u1, + GPIO24_EDGE_HIGH: u1, + GPIO25_LEVEL_LOW: u1, + GPIO25_LEVEL_HIGH: u1, + GPIO25_EDGE_LOW: u1, + GPIO25_EDGE_HIGH: u1, + GPIO26_LEVEL_LOW: u1, + GPIO26_LEVEL_HIGH: u1, + GPIO26_EDGE_LOW: u1, + GPIO26_EDGE_HIGH: u1, + GPIO27_LEVEL_LOW: u1, + GPIO27_LEVEL_HIGH: u1, + GPIO27_EDGE_LOW: u1, + GPIO27_EDGE_HIGH: u1, + GPIO28_LEVEL_LOW: u1, + GPIO28_LEVEL_HIGH: u1, + GPIO28_EDGE_LOW: u1, + GPIO28_EDGE_HIGH: u1, + GPIO29_LEVEL_LOW: u1, + GPIO29_LEVEL_HIGH: u1, + GPIO29_EDGE_LOW: u1, + GPIO29_EDGE_HIGH: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x10c); + + /// address: 0x40014110 + /// Interrupt Force for proc0 + pub const PROC0_INTF0 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO0_LEVEL_LOW: u1, + GPIO0_LEVEL_HIGH: u1, + GPIO0_EDGE_LOW: u1, + GPIO0_EDGE_HIGH: u1, + GPIO1_LEVEL_LOW: u1, + GPIO1_LEVEL_HIGH: u1, + GPIO1_EDGE_LOW: u1, + GPIO1_EDGE_HIGH: u1, + GPIO2_LEVEL_LOW: u1, + GPIO2_LEVEL_HIGH: u1, + GPIO2_EDGE_LOW: u1, + GPIO2_EDGE_HIGH: u1, + GPIO3_LEVEL_LOW: u1, + GPIO3_LEVEL_HIGH: u1, + GPIO3_EDGE_LOW: u1, + GPIO3_EDGE_HIGH: u1, + GPIO4_LEVEL_LOW: u1, + GPIO4_LEVEL_HIGH: u1, + GPIO4_EDGE_LOW: u1, + GPIO4_EDGE_HIGH: u1, + GPIO5_LEVEL_LOW: u1, + GPIO5_LEVEL_HIGH: u1, + GPIO5_EDGE_LOW: u1, + GPIO5_EDGE_HIGH: u1, + GPIO6_LEVEL_LOW: u1, + GPIO6_LEVEL_HIGH: u1, + GPIO6_EDGE_LOW: u1, + GPIO6_EDGE_HIGH: u1, + GPIO7_LEVEL_LOW: u1, + GPIO7_LEVEL_HIGH: u1, + GPIO7_EDGE_LOW: u1, + GPIO7_EDGE_HIGH: u1, + }), base_address + 0x110); + + /// address: 0x40014114 + /// Interrupt Force for proc0 + pub const PROC0_INTF1 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO8_LEVEL_LOW: u1, + GPIO8_LEVEL_HIGH: u1, + GPIO8_EDGE_LOW: u1, + GPIO8_EDGE_HIGH: u1, + GPIO9_LEVEL_LOW: u1, + GPIO9_LEVEL_HIGH: u1, + GPIO9_EDGE_LOW: u1, + GPIO9_EDGE_HIGH: u1, + GPIO10_LEVEL_LOW: u1, + GPIO10_LEVEL_HIGH: u1, + GPIO10_EDGE_LOW: u1, + GPIO10_EDGE_HIGH: u1, + GPIO11_LEVEL_LOW: u1, + GPIO11_LEVEL_HIGH: u1, + GPIO11_EDGE_LOW: u1, + GPIO11_EDGE_HIGH: u1, + GPIO12_LEVEL_LOW: u1, + GPIO12_LEVEL_HIGH: u1, + GPIO12_EDGE_LOW: u1, + GPIO12_EDGE_HIGH: u1, + GPIO13_LEVEL_LOW: u1, + GPIO13_LEVEL_HIGH: u1, + GPIO13_EDGE_LOW: u1, + GPIO13_EDGE_HIGH: u1, + GPIO14_LEVEL_LOW: u1, + GPIO14_LEVEL_HIGH: u1, + GPIO14_EDGE_LOW: u1, + GPIO14_EDGE_HIGH: u1, + GPIO15_LEVEL_LOW: u1, + GPIO15_LEVEL_HIGH: u1, + GPIO15_EDGE_LOW: u1, + GPIO15_EDGE_HIGH: u1, + }), base_address + 0x114); + + /// address: 0x40014118 + /// Interrupt Force for proc0 + pub const PROC0_INTF2 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO16_LEVEL_LOW: u1, + GPIO16_LEVEL_HIGH: u1, + GPIO16_EDGE_LOW: u1, + GPIO16_EDGE_HIGH: u1, + GPIO17_LEVEL_LOW: u1, + GPIO17_LEVEL_HIGH: u1, + GPIO17_EDGE_LOW: u1, + GPIO17_EDGE_HIGH: u1, + GPIO18_LEVEL_LOW: u1, + GPIO18_LEVEL_HIGH: u1, + GPIO18_EDGE_LOW: u1, + GPIO18_EDGE_HIGH: u1, + GPIO19_LEVEL_LOW: u1, + GPIO19_LEVEL_HIGH: u1, + GPIO19_EDGE_LOW: u1, + GPIO19_EDGE_HIGH: u1, + GPIO20_LEVEL_LOW: u1, + GPIO20_LEVEL_HIGH: u1, + GPIO20_EDGE_LOW: u1, + GPIO20_EDGE_HIGH: u1, + GPIO21_LEVEL_LOW: u1, + GPIO21_LEVEL_HIGH: u1, + GPIO21_EDGE_LOW: u1, + GPIO21_EDGE_HIGH: u1, + GPIO22_LEVEL_LOW: u1, + GPIO22_LEVEL_HIGH: u1, + GPIO22_EDGE_LOW: u1, + GPIO22_EDGE_HIGH: u1, + GPIO23_LEVEL_LOW: u1, + GPIO23_LEVEL_HIGH: u1, + GPIO23_EDGE_LOW: u1, + GPIO23_EDGE_HIGH: u1, + }), base_address + 0x118); + + /// address: 0x4001411c + /// Interrupt Force for proc0 + pub const PROC0_INTF3 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO24_LEVEL_LOW: u1, + GPIO24_LEVEL_HIGH: u1, + GPIO24_EDGE_LOW: u1, + GPIO24_EDGE_HIGH: u1, + GPIO25_LEVEL_LOW: u1, + GPIO25_LEVEL_HIGH: u1, + GPIO25_EDGE_LOW: u1, + GPIO25_EDGE_HIGH: u1, + GPIO26_LEVEL_LOW: u1, + GPIO26_LEVEL_HIGH: u1, + GPIO26_EDGE_LOW: u1, + GPIO26_EDGE_HIGH: u1, + GPIO27_LEVEL_LOW: u1, + GPIO27_LEVEL_HIGH: u1, + GPIO27_EDGE_LOW: u1, + GPIO27_EDGE_HIGH: u1, + GPIO28_LEVEL_LOW: u1, + GPIO28_LEVEL_HIGH: u1, + GPIO28_EDGE_LOW: u1, + GPIO28_EDGE_HIGH: u1, + GPIO29_LEVEL_LOW: u1, + GPIO29_LEVEL_HIGH: u1, + GPIO29_EDGE_LOW: u1, + GPIO29_EDGE_HIGH: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x11c); + + /// address: 0x40014120 + /// Interrupt status after masking & forcing for proc0 + pub const PROC0_INTS0 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO0_LEVEL_LOW: u1, + GPIO0_LEVEL_HIGH: u1, + GPIO0_EDGE_LOW: u1, + GPIO0_EDGE_HIGH: u1, + GPIO1_LEVEL_LOW: u1, + GPIO1_LEVEL_HIGH: u1, + GPIO1_EDGE_LOW: u1, + GPIO1_EDGE_HIGH: u1, + GPIO2_LEVEL_LOW: u1, + GPIO2_LEVEL_HIGH: u1, + GPIO2_EDGE_LOW: u1, + GPIO2_EDGE_HIGH: u1, + GPIO3_LEVEL_LOW: u1, + GPIO3_LEVEL_HIGH: u1, + GPIO3_EDGE_LOW: u1, + GPIO3_EDGE_HIGH: u1, + GPIO4_LEVEL_LOW: u1, + GPIO4_LEVEL_HIGH: u1, + GPIO4_EDGE_LOW: u1, + GPIO4_EDGE_HIGH: u1, + GPIO5_LEVEL_LOW: u1, + GPIO5_LEVEL_HIGH: u1, + GPIO5_EDGE_LOW: u1, + GPIO5_EDGE_HIGH: u1, + GPIO6_LEVEL_LOW: u1, + GPIO6_LEVEL_HIGH: u1, + GPIO6_EDGE_LOW: u1, + GPIO6_EDGE_HIGH: u1, + GPIO7_LEVEL_LOW: u1, + GPIO7_LEVEL_HIGH: u1, + GPIO7_EDGE_LOW: u1, + GPIO7_EDGE_HIGH: u1, + }), base_address + 0x120); + + /// address: 0x40014124 + /// Interrupt status after masking & forcing for proc0 + pub const PROC0_INTS1 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO8_LEVEL_LOW: u1, + GPIO8_LEVEL_HIGH: u1, + GPIO8_EDGE_LOW: u1, + GPIO8_EDGE_HIGH: u1, + GPIO9_LEVEL_LOW: u1, + GPIO9_LEVEL_HIGH: u1, + GPIO9_EDGE_LOW: u1, + GPIO9_EDGE_HIGH: u1, + GPIO10_LEVEL_LOW: u1, + GPIO10_LEVEL_HIGH: u1, + GPIO10_EDGE_LOW: u1, + GPIO10_EDGE_HIGH: u1, + GPIO11_LEVEL_LOW: u1, + GPIO11_LEVEL_HIGH: u1, + GPIO11_EDGE_LOW: u1, + GPIO11_EDGE_HIGH: u1, + GPIO12_LEVEL_LOW: u1, + GPIO12_LEVEL_HIGH: u1, + GPIO12_EDGE_LOW: u1, + GPIO12_EDGE_HIGH: u1, + GPIO13_LEVEL_LOW: u1, + GPIO13_LEVEL_HIGH: u1, + GPIO13_EDGE_LOW: u1, + GPIO13_EDGE_HIGH: u1, + GPIO14_LEVEL_LOW: u1, + GPIO14_LEVEL_HIGH: u1, + GPIO14_EDGE_LOW: u1, + GPIO14_EDGE_HIGH: u1, + GPIO15_LEVEL_LOW: u1, + GPIO15_LEVEL_HIGH: u1, + GPIO15_EDGE_LOW: u1, + GPIO15_EDGE_HIGH: u1, + }), base_address + 0x124); + + /// address: 0x40014128 + /// Interrupt status after masking & forcing for proc0 + pub const PROC0_INTS2 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO16_LEVEL_LOW: u1, + GPIO16_LEVEL_HIGH: u1, + GPIO16_EDGE_LOW: u1, + GPIO16_EDGE_HIGH: u1, + GPIO17_LEVEL_LOW: u1, + GPIO17_LEVEL_HIGH: u1, + GPIO17_EDGE_LOW: u1, + GPIO17_EDGE_HIGH: u1, + GPIO18_LEVEL_LOW: u1, + GPIO18_LEVEL_HIGH: u1, + GPIO18_EDGE_LOW: u1, + GPIO18_EDGE_HIGH: u1, + GPIO19_LEVEL_LOW: u1, + GPIO19_LEVEL_HIGH: u1, + GPIO19_EDGE_LOW: u1, + GPIO19_EDGE_HIGH: u1, + GPIO20_LEVEL_LOW: u1, + GPIO20_LEVEL_HIGH: u1, + GPIO20_EDGE_LOW: u1, + GPIO20_EDGE_HIGH: u1, + GPIO21_LEVEL_LOW: u1, + GPIO21_LEVEL_HIGH: u1, + GPIO21_EDGE_LOW: u1, + GPIO21_EDGE_HIGH: u1, + GPIO22_LEVEL_LOW: u1, + GPIO22_LEVEL_HIGH: u1, + GPIO22_EDGE_LOW: u1, + GPIO22_EDGE_HIGH: u1, + GPIO23_LEVEL_LOW: u1, + GPIO23_LEVEL_HIGH: u1, + GPIO23_EDGE_LOW: u1, + GPIO23_EDGE_HIGH: u1, + }), base_address + 0x128); + + /// address: 0x4001412c + /// Interrupt status after masking & forcing for proc0 + pub const PROC0_INTS3 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO24_LEVEL_LOW: u1, + GPIO24_LEVEL_HIGH: u1, + GPIO24_EDGE_LOW: u1, + GPIO24_EDGE_HIGH: u1, + GPIO25_LEVEL_LOW: u1, + GPIO25_LEVEL_HIGH: u1, + GPIO25_EDGE_LOW: u1, + GPIO25_EDGE_HIGH: u1, + GPIO26_LEVEL_LOW: u1, + GPIO26_LEVEL_HIGH: u1, + GPIO26_EDGE_LOW: u1, + GPIO26_EDGE_HIGH: u1, + GPIO27_LEVEL_LOW: u1, + GPIO27_LEVEL_HIGH: u1, + GPIO27_EDGE_LOW: u1, + GPIO27_EDGE_HIGH: u1, + GPIO28_LEVEL_LOW: u1, + GPIO28_LEVEL_HIGH: u1, + GPIO28_EDGE_LOW: u1, + GPIO28_EDGE_HIGH: u1, + GPIO29_LEVEL_LOW: u1, + GPIO29_LEVEL_HIGH: u1, + GPIO29_EDGE_LOW: u1, + GPIO29_EDGE_HIGH: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x12c); + + /// address: 0x40014130 + /// Interrupt Enable for proc1 + pub const PROC1_INTE0 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO0_LEVEL_LOW: u1, + GPIO0_LEVEL_HIGH: u1, + GPIO0_EDGE_LOW: u1, + GPIO0_EDGE_HIGH: u1, + GPIO1_LEVEL_LOW: u1, + GPIO1_LEVEL_HIGH: u1, + GPIO1_EDGE_LOW: u1, + GPIO1_EDGE_HIGH: u1, + GPIO2_LEVEL_LOW: u1, + GPIO2_LEVEL_HIGH: u1, + GPIO2_EDGE_LOW: u1, + GPIO2_EDGE_HIGH: u1, + GPIO3_LEVEL_LOW: u1, + GPIO3_LEVEL_HIGH: u1, + GPIO3_EDGE_LOW: u1, + GPIO3_EDGE_HIGH: u1, + GPIO4_LEVEL_LOW: u1, + GPIO4_LEVEL_HIGH: u1, + GPIO4_EDGE_LOW: u1, + GPIO4_EDGE_HIGH: u1, + GPIO5_LEVEL_LOW: u1, + GPIO5_LEVEL_HIGH: u1, + GPIO5_EDGE_LOW: u1, + GPIO5_EDGE_HIGH: u1, + GPIO6_LEVEL_LOW: u1, + GPIO6_LEVEL_HIGH: u1, + GPIO6_EDGE_LOW: u1, + GPIO6_EDGE_HIGH: u1, + GPIO7_LEVEL_LOW: u1, + GPIO7_LEVEL_HIGH: u1, + GPIO7_EDGE_LOW: u1, + GPIO7_EDGE_HIGH: u1, + }), base_address + 0x130); + + /// address: 0x40014134 + /// Interrupt Enable for proc1 + pub const PROC1_INTE1 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO8_LEVEL_LOW: u1, + GPIO8_LEVEL_HIGH: u1, + GPIO8_EDGE_LOW: u1, + GPIO8_EDGE_HIGH: u1, + GPIO9_LEVEL_LOW: u1, + GPIO9_LEVEL_HIGH: u1, + GPIO9_EDGE_LOW: u1, + GPIO9_EDGE_HIGH: u1, + GPIO10_LEVEL_LOW: u1, + GPIO10_LEVEL_HIGH: u1, + GPIO10_EDGE_LOW: u1, + GPIO10_EDGE_HIGH: u1, + GPIO11_LEVEL_LOW: u1, + GPIO11_LEVEL_HIGH: u1, + GPIO11_EDGE_LOW: u1, + GPIO11_EDGE_HIGH: u1, + GPIO12_LEVEL_LOW: u1, + GPIO12_LEVEL_HIGH: u1, + GPIO12_EDGE_LOW: u1, + GPIO12_EDGE_HIGH: u1, + GPIO13_LEVEL_LOW: u1, + GPIO13_LEVEL_HIGH: u1, + GPIO13_EDGE_LOW: u1, + GPIO13_EDGE_HIGH: u1, + GPIO14_LEVEL_LOW: u1, + GPIO14_LEVEL_HIGH: u1, + GPIO14_EDGE_LOW: u1, + GPIO14_EDGE_HIGH: u1, + GPIO15_LEVEL_LOW: u1, + GPIO15_LEVEL_HIGH: u1, + GPIO15_EDGE_LOW: u1, + GPIO15_EDGE_HIGH: u1, + }), base_address + 0x134); + + /// address: 0x40014138 + /// Interrupt Enable for proc1 + pub const PROC1_INTE2 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO16_LEVEL_LOW: u1, + GPIO16_LEVEL_HIGH: u1, + GPIO16_EDGE_LOW: u1, + GPIO16_EDGE_HIGH: u1, + GPIO17_LEVEL_LOW: u1, + GPIO17_LEVEL_HIGH: u1, + GPIO17_EDGE_LOW: u1, + GPIO17_EDGE_HIGH: u1, + GPIO18_LEVEL_LOW: u1, + GPIO18_LEVEL_HIGH: u1, + GPIO18_EDGE_LOW: u1, + GPIO18_EDGE_HIGH: u1, + GPIO19_LEVEL_LOW: u1, + GPIO19_LEVEL_HIGH: u1, + GPIO19_EDGE_LOW: u1, + GPIO19_EDGE_HIGH: u1, + GPIO20_LEVEL_LOW: u1, + GPIO20_LEVEL_HIGH: u1, + GPIO20_EDGE_LOW: u1, + GPIO20_EDGE_HIGH: u1, + GPIO21_LEVEL_LOW: u1, + GPIO21_LEVEL_HIGH: u1, + GPIO21_EDGE_LOW: u1, + GPIO21_EDGE_HIGH: u1, + GPIO22_LEVEL_LOW: u1, + GPIO22_LEVEL_HIGH: u1, + GPIO22_EDGE_LOW: u1, + GPIO22_EDGE_HIGH: u1, + GPIO23_LEVEL_LOW: u1, + GPIO23_LEVEL_HIGH: u1, + GPIO23_EDGE_LOW: u1, + GPIO23_EDGE_HIGH: u1, + }), base_address + 0x138); + + /// address: 0x4001413c + /// Interrupt Enable for proc1 + pub const PROC1_INTE3 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO24_LEVEL_LOW: u1, + GPIO24_LEVEL_HIGH: u1, + GPIO24_EDGE_LOW: u1, + GPIO24_EDGE_HIGH: u1, + GPIO25_LEVEL_LOW: u1, + GPIO25_LEVEL_HIGH: u1, + GPIO25_EDGE_LOW: u1, + GPIO25_EDGE_HIGH: u1, + GPIO26_LEVEL_LOW: u1, + GPIO26_LEVEL_HIGH: u1, + GPIO26_EDGE_LOW: u1, + GPIO26_EDGE_HIGH: u1, + GPIO27_LEVEL_LOW: u1, + GPIO27_LEVEL_HIGH: u1, + GPIO27_EDGE_LOW: u1, + GPIO27_EDGE_HIGH: u1, + GPIO28_LEVEL_LOW: u1, + GPIO28_LEVEL_HIGH: u1, + GPIO28_EDGE_LOW: u1, + GPIO28_EDGE_HIGH: u1, + GPIO29_LEVEL_LOW: u1, + GPIO29_LEVEL_HIGH: u1, + GPIO29_EDGE_LOW: u1, + GPIO29_EDGE_HIGH: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x13c); + + /// address: 0x40014140 + /// Interrupt Force for proc1 + pub const PROC1_INTF0 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO0_LEVEL_LOW: u1, + GPIO0_LEVEL_HIGH: u1, + GPIO0_EDGE_LOW: u1, + GPIO0_EDGE_HIGH: u1, + GPIO1_LEVEL_LOW: u1, + GPIO1_LEVEL_HIGH: u1, + GPIO1_EDGE_LOW: u1, + GPIO1_EDGE_HIGH: u1, + GPIO2_LEVEL_LOW: u1, + GPIO2_LEVEL_HIGH: u1, + GPIO2_EDGE_LOW: u1, + GPIO2_EDGE_HIGH: u1, + GPIO3_LEVEL_LOW: u1, + GPIO3_LEVEL_HIGH: u1, + GPIO3_EDGE_LOW: u1, + GPIO3_EDGE_HIGH: u1, + GPIO4_LEVEL_LOW: u1, + GPIO4_LEVEL_HIGH: u1, + GPIO4_EDGE_LOW: u1, + GPIO4_EDGE_HIGH: u1, + GPIO5_LEVEL_LOW: u1, + GPIO5_LEVEL_HIGH: u1, + GPIO5_EDGE_LOW: u1, + GPIO5_EDGE_HIGH: u1, + GPIO6_LEVEL_LOW: u1, + GPIO6_LEVEL_HIGH: u1, + GPIO6_EDGE_LOW: u1, + GPIO6_EDGE_HIGH: u1, + GPIO7_LEVEL_LOW: u1, + GPIO7_LEVEL_HIGH: u1, + GPIO7_EDGE_LOW: u1, + GPIO7_EDGE_HIGH: u1, + }), base_address + 0x140); + + /// address: 0x40014144 + /// Interrupt Force for proc1 + pub const PROC1_INTF1 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO8_LEVEL_LOW: u1, + GPIO8_LEVEL_HIGH: u1, + GPIO8_EDGE_LOW: u1, + GPIO8_EDGE_HIGH: u1, + GPIO9_LEVEL_LOW: u1, + GPIO9_LEVEL_HIGH: u1, + GPIO9_EDGE_LOW: u1, + GPIO9_EDGE_HIGH: u1, + GPIO10_LEVEL_LOW: u1, + GPIO10_LEVEL_HIGH: u1, + GPIO10_EDGE_LOW: u1, + GPIO10_EDGE_HIGH: u1, + GPIO11_LEVEL_LOW: u1, + GPIO11_LEVEL_HIGH: u1, + GPIO11_EDGE_LOW: u1, + GPIO11_EDGE_HIGH: u1, + GPIO12_LEVEL_LOW: u1, + GPIO12_LEVEL_HIGH: u1, + GPIO12_EDGE_LOW: u1, + GPIO12_EDGE_HIGH: u1, + GPIO13_LEVEL_LOW: u1, + GPIO13_LEVEL_HIGH: u1, + GPIO13_EDGE_LOW: u1, + GPIO13_EDGE_HIGH: u1, + GPIO14_LEVEL_LOW: u1, + GPIO14_LEVEL_HIGH: u1, + GPIO14_EDGE_LOW: u1, + GPIO14_EDGE_HIGH: u1, + GPIO15_LEVEL_LOW: u1, + GPIO15_LEVEL_HIGH: u1, + GPIO15_EDGE_LOW: u1, + GPIO15_EDGE_HIGH: u1, + }), base_address + 0x144); + + /// address: 0x40014148 + /// Interrupt Force for proc1 + pub const PROC1_INTF2 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO16_LEVEL_LOW: u1, + GPIO16_LEVEL_HIGH: u1, + GPIO16_EDGE_LOW: u1, + GPIO16_EDGE_HIGH: u1, + GPIO17_LEVEL_LOW: u1, + GPIO17_LEVEL_HIGH: u1, + GPIO17_EDGE_LOW: u1, + GPIO17_EDGE_HIGH: u1, + GPIO18_LEVEL_LOW: u1, + GPIO18_LEVEL_HIGH: u1, + GPIO18_EDGE_LOW: u1, + GPIO18_EDGE_HIGH: u1, + GPIO19_LEVEL_LOW: u1, + GPIO19_LEVEL_HIGH: u1, + GPIO19_EDGE_LOW: u1, + GPIO19_EDGE_HIGH: u1, + GPIO20_LEVEL_LOW: u1, + GPIO20_LEVEL_HIGH: u1, + GPIO20_EDGE_LOW: u1, + GPIO20_EDGE_HIGH: u1, + GPIO21_LEVEL_LOW: u1, + GPIO21_LEVEL_HIGH: u1, + GPIO21_EDGE_LOW: u1, + GPIO21_EDGE_HIGH: u1, + GPIO22_LEVEL_LOW: u1, + GPIO22_LEVEL_HIGH: u1, + GPIO22_EDGE_LOW: u1, + GPIO22_EDGE_HIGH: u1, + GPIO23_LEVEL_LOW: u1, + GPIO23_LEVEL_HIGH: u1, + GPIO23_EDGE_LOW: u1, + GPIO23_EDGE_HIGH: u1, + }), base_address + 0x148); + + /// address: 0x4001414c + /// Interrupt Force for proc1 + pub const PROC1_INTF3 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO24_LEVEL_LOW: u1, + GPIO24_LEVEL_HIGH: u1, + GPIO24_EDGE_LOW: u1, + GPIO24_EDGE_HIGH: u1, + GPIO25_LEVEL_LOW: u1, + GPIO25_LEVEL_HIGH: u1, + GPIO25_EDGE_LOW: u1, + GPIO25_EDGE_HIGH: u1, + GPIO26_LEVEL_LOW: u1, + GPIO26_LEVEL_HIGH: u1, + GPIO26_EDGE_LOW: u1, + GPIO26_EDGE_HIGH: u1, + GPIO27_LEVEL_LOW: u1, + GPIO27_LEVEL_HIGH: u1, + GPIO27_EDGE_LOW: u1, + GPIO27_EDGE_HIGH: u1, + GPIO28_LEVEL_LOW: u1, + GPIO28_LEVEL_HIGH: u1, + GPIO28_EDGE_LOW: u1, + GPIO28_EDGE_HIGH: u1, + GPIO29_LEVEL_LOW: u1, + GPIO29_LEVEL_HIGH: u1, + GPIO29_EDGE_LOW: u1, + GPIO29_EDGE_HIGH: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x14c); + + /// address: 0x40014150 + /// Interrupt status after masking & forcing for proc1 + pub const PROC1_INTS0 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO0_LEVEL_LOW: u1, + GPIO0_LEVEL_HIGH: u1, + GPIO0_EDGE_LOW: u1, + GPIO0_EDGE_HIGH: u1, + GPIO1_LEVEL_LOW: u1, + GPIO1_LEVEL_HIGH: u1, + GPIO1_EDGE_LOW: u1, + GPIO1_EDGE_HIGH: u1, + GPIO2_LEVEL_LOW: u1, + GPIO2_LEVEL_HIGH: u1, + GPIO2_EDGE_LOW: u1, + GPIO2_EDGE_HIGH: u1, + GPIO3_LEVEL_LOW: u1, + GPIO3_LEVEL_HIGH: u1, + GPIO3_EDGE_LOW: u1, + GPIO3_EDGE_HIGH: u1, + GPIO4_LEVEL_LOW: u1, + GPIO4_LEVEL_HIGH: u1, + GPIO4_EDGE_LOW: u1, + GPIO4_EDGE_HIGH: u1, + GPIO5_LEVEL_LOW: u1, + GPIO5_LEVEL_HIGH: u1, + GPIO5_EDGE_LOW: u1, + GPIO5_EDGE_HIGH: u1, + GPIO6_LEVEL_LOW: u1, + GPIO6_LEVEL_HIGH: u1, + GPIO6_EDGE_LOW: u1, + GPIO6_EDGE_HIGH: u1, + GPIO7_LEVEL_LOW: u1, + GPIO7_LEVEL_HIGH: u1, + GPIO7_EDGE_LOW: u1, + GPIO7_EDGE_HIGH: u1, + }), base_address + 0x150); + + /// address: 0x40014154 + /// Interrupt status after masking & forcing for proc1 + pub const PROC1_INTS1 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO8_LEVEL_LOW: u1, + GPIO8_LEVEL_HIGH: u1, + GPIO8_EDGE_LOW: u1, + GPIO8_EDGE_HIGH: u1, + GPIO9_LEVEL_LOW: u1, + GPIO9_LEVEL_HIGH: u1, + GPIO9_EDGE_LOW: u1, + GPIO9_EDGE_HIGH: u1, + GPIO10_LEVEL_LOW: u1, + GPIO10_LEVEL_HIGH: u1, + GPIO10_EDGE_LOW: u1, + GPIO10_EDGE_HIGH: u1, + GPIO11_LEVEL_LOW: u1, + GPIO11_LEVEL_HIGH: u1, + GPIO11_EDGE_LOW: u1, + GPIO11_EDGE_HIGH: u1, + GPIO12_LEVEL_LOW: u1, + GPIO12_LEVEL_HIGH: u1, + GPIO12_EDGE_LOW: u1, + GPIO12_EDGE_HIGH: u1, + GPIO13_LEVEL_LOW: u1, + GPIO13_LEVEL_HIGH: u1, + GPIO13_EDGE_LOW: u1, + GPIO13_EDGE_HIGH: u1, + GPIO14_LEVEL_LOW: u1, + GPIO14_LEVEL_HIGH: u1, + GPIO14_EDGE_LOW: u1, + GPIO14_EDGE_HIGH: u1, + GPIO15_LEVEL_LOW: u1, + GPIO15_LEVEL_HIGH: u1, + GPIO15_EDGE_LOW: u1, + GPIO15_EDGE_HIGH: u1, + }), base_address + 0x154); + + /// address: 0x40014158 + /// Interrupt status after masking & forcing for proc1 + pub const PROC1_INTS2 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO16_LEVEL_LOW: u1, + GPIO16_LEVEL_HIGH: u1, + GPIO16_EDGE_LOW: u1, + GPIO16_EDGE_HIGH: u1, + GPIO17_LEVEL_LOW: u1, + GPIO17_LEVEL_HIGH: u1, + GPIO17_EDGE_LOW: u1, + GPIO17_EDGE_HIGH: u1, + GPIO18_LEVEL_LOW: u1, + GPIO18_LEVEL_HIGH: u1, + GPIO18_EDGE_LOW: u1, + GPIO18_EDGE_HIGH: u1, + GPIO19_LEVEL_LOW: u1, + GPIO19_LEVEL_HIGH: u1, + GPIO19_EDGE_LOW: u1, + GPIO19_EDGE_HIGH: u1, + GPIO20_LEVEL_LOW: u1, + GPIO20_LEVEL_HIGH: u1, + GPIO20_EDGE_LOW: u1, + GPIO20_EDGE_HIGH: u1, + GPIO21_LEVEL_LOW: u1, + GPIO21_LEVEL_HIGH: u1, + GPIO21_EDGE_LOW: u1, + GPIO21_EDGE_HIGH: u1, + GPIO22_LEVEL_LOW: u1, + GPIO22_LEVEL_HIGH: u1, + GPIO22_EDGE_LOW: u1, + GPIO22_EDGE_HIGH: u1, + GPIO23_LEVEL_LOW: u1, + GPIO23_LEVEL_HIGH: u1, + GPIO23_EDGE_LOW: u1, + GPIO23_EDGE_HIGH: u1, + }), base_address + 0x158); + + /// address: 0x4001415c + /// Interrupt status after masking & forcing for proc1 + pub const PROC1_INTS3 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO24_LEVEL_LOW: u1, + GPIO24_LEVEL_HIGH: u1, + GPIO24_EDGE_LOW: u1, + GPIO24_EDGE_HIGH: u1, + GPIO25_LEVEL_LOW: u1, + GPIO25_LEVEL_HIGH: u1, + GPIO25_EDGE_LOW: u1, + GPIO25_EDGE_HIGH: u1, + GPIO26_LEVEL_LOW: u1, + GPIO26_LEVEL_HIGH: u1, + GPIO26_EDGE_LOW: u1, + GPIO26_EDGE_HIGH: u1, + GPIO27_LEVEL_LOW: u1, + GPIO27_LEVEL_HIGH: u1, + GPIO27_EDGE_LOW: u1, + GPIO27_EDGE_HIGH: u1, + GPIO28_LEVEL_LOW: u1, + GPIO28_LEVEL_HIGH: u1, + GPIO28_EDGE_LOW: u1, + GPIO28_EDGE_HIGH: u1, + GPIO29_LEVEL_LOW: u1, + GPIO29_LEVEL_HIGH: u1, + GPIO29_EDGE_LOW: u1, + GPIO29_EDGE_HIGH: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x15c); + + /// address: 0x40014160 + /// Interrupt Enable for dormant_wake + pub const DORMANT_WAKE_INTE0 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO0_LEVEL_LOW: u1, + GPIO0_LEVEL_HIGH: u1, + GPIO0_EDGE_LOW: u1, + GPIO0_EDGE_HIGH: u1, + GPIO1_LEVEL_LOW: u1, + GPIO1_LEVEL_HIGH: u1, + GPIO1_EDGE_LOW: u1, + GPIO1_EDGE_HIGH: u1, + GPIO2_LEVEL_LOW: u1, + GPIO2_LEVEL_HIGH: u1, + GPIO2_EDGE_LOW: u1, + GPIO2_EDGE_HIGH: u1, + GPIO3_LEVEL_LOW: u1, + GPIO3_LEVEL_HIGH: u1, + GPIO3_EDGE_LOW: u1, + GPIO3_EDGE_HIGH: u1, + GPIO4_LEVEL_LOW: u1, + GPIO4_LEVEL_HIGH: u1, + GPIO4_EDGE_LOW: u1, + GPIO4_EDGE_HIGH: u1, + GPIO5_LEVEL_LOW: u1, + GPIO5_LEVEL_HIGH: u1, + GPIO5_EDGE_LOW: u1, + GPIO5_EDGE_HIGH: u1, + GPIO6_LEVEL_LOW: u1, + GPIO6_LEVEL_HIGH: u1, + GPIO6_EDGE_LOW: u1, + GPIO6_EDGE_HIGH: u1, + GPIO7_LEVEL_LOW: u1, + GPIO7_LEVEL_HIGH: u1, + GPIO7_EDGE_LOW: u1, + GPIO7_EDGE_HIGH: u1, + }), base_address + 0x160); + + /// address: 0x40014164 + /// Interrupt Enable for dormant_wake + pub const DORMANT_WAKE_INTE1 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO8_LEVEL_LOW: u1, + GPIO8_LEVEL_HIGH: u1, + GPIO8_EDGE_LOW: u1, + GPIO8_EDGE_HIGH: u1, + GPIO9_LEVEL_LOW: u1, + GPIO9_LEVEL_HIGH: u1, + GPIO9_EDGE_LOW: u1, + GPIO9_EDGE_HIGH: u1, + GPIO10_LEVEL_LOW: u1, + GPIO10_LEVEL_HIGH: u1, + GPIO10_EDGE_LOW: u1, + GPIO10_EDGE_HIGH: u1, + GPIO11_LEVEL_LOW: u1, + GPIO11_LEVEL_HIGH: u1, + GPIO11_EDGE_LOW: u1, + GPIO11_EDGE_HIGH: u1, + GPIO12_LEVEL_LOW: u1, + GPIO12_LEVEL_HIGH: u1, + GPIO12_EDGE_LOW: u1, + GPIO12_EDGE_HIGH: u1, + GPIO13_LEVEL_LOW: u1, + GPIO13_LEVEL_HIGH: u1, + GPIO13_EDGE_LOW: u1, + GPIO13_EDGE_HIGH: u1, + GPIO14_LEVEL_LOW: u1, + GPIO14_LEVEL_HIGH: u1, + GPIO14_EDGE_LOW: u1, + GPIO14_EDGE_HIGH: u1, + GPIO15_LEVEL_LOW: u1, + GPIO15_LEVEL_HIGH: u1, + GPIO15_EDGE_LOW: u1, + GPIO15_EDGE_HIGH: u1, + }), base_address + 0x164); + + /// address: 0x40014168 + /// Interrupt Enable for dormant_wake + pub const DORMANT_WAKE_INTE2 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO16_LEVEL_LOW: u1, + GPIO16_LEVEL_HIGH: u1, + GPIO16_EDGE_LOW: u1, + GPIO16_EDGE_HIGH: u1, + GPIO17_LEVEL_LOW: u1, + GPIO17_LEVEL_HIGH: u1, + GPIO17_EDGE_LOW: u1, + GPIO17_EDGE_HIGH: u1, + GPIO18_LEVEL_LOW: u1, + GPIO18_LEVEL_HIGH: u1, + GPIO18_EDGE_LOW: u1, + GPIO18_EDGE_HIGH: u1, + GPIO19_LEVEL_LOW: u1, + GPIO19_LEVEL_HIGH: u1, + GPIO19_EDGE_LOW: u1, + GPIO19_EDGE_HIGH: u1, + GPIO20_LEVEL_LOW: u1, + GPIO20_LEVEL_HIGH: u1, + GPIO20_EDGE_LOW: u1, + GPIO20_EDGE_HIGH: u1, + GPIO21_LEVEL_LOW: u1, + GPIO21_LEVEL_HIGH: u1, + GPIO21_EDGE_LOW: u1, + GPIO21_EDGE_HIGH: u1, + GPIO22_LEVEL_LOW: u1, + GPIO22_LEVEL_HIGH: u1, + GPIO22_EDGE_LOW: u1, + GPIO22_EDGE_HIGH: u1, + GPIO23_LEVEL_LOW: u1, + GPIO23_LEVEL_HIGH: u1, + GPIO23_EDGE_LOW: u1, + GPIO23_EDGE_HIGH: u1, + }), base_address + 0x168); + + /// address: 0x4001416c + /// Interrupt Enable for dormant_wake + pub const DORMANT_WAKE_INTE3 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO24_LEVEL_LOW: u1, + GPIO24_LEVEL_HIGH: u1, + GPIO24_EDGE_LOW: u1, + GPIO24_EDGE_HIGH: u1, + GPIO25_LEVEL_LOW: u1, + GPIO25_LEVEL_HIGH: u1, + GPIO25_EDGE_LOW: u1, + GPIO25_EDGE_HIGH: u1, + GPIO26_LEVEL_LOW: u1, + GPIO26_LEVEL_HIGH: u1, + GPIO26_EDGE_LOW: u1, + GPIO26_EDGE_HIGH: u1, + GPIO27_LEVEL_LOW: u1, + GPIO27_LEVEL_HIGH: u1, + GPIO27_EDGE_LOW: u1, + GPIO27_EDGE_HIGH: u1, + GPIO28_LEVEL_LOW: u1, + GPIO28_LEVEL_HIGH: u1, + GPIO28_EDGE_LOW: u1, + GPIO28_EDGE_HIGH: u1, + GPIO29_LEVEL_LOW: u1, + GPIO29_LEVEL_HIGH: u1, + GPIO29_EDGE_LOW: u1, + GPIO29_EDGE_HIGH: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x16c); + + /// address: 0x40014170 + /// Interrupt Force for dormant_wake + pub const DORMANT_WAKE_INTF0 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO0_LEVEL_LOW: u1, + GPIO0_LEVEL_HIGH: u1, + GPIO0_EDGE_LOW: u1, + GPIO0_EDGE_HIGH: u1, + GPIO1_LEVEL_LOW: u1, + GPIO1_LEVEL_HIGH: u1, + GPIO1_EDGE_LOW: u1, + GPIO1_EDGE_HIGH: u1, + GPIO2_LEVEL_LOW: u1, + GPIO2_LEVEL_HIGH: u1, + GPIO2_EDGE_LOW: u1, + GPIO2_EDGE_HIGH: u1, + GPIO3_LEVEL_LOW: u1, + GPIO3_LEVEL_HIGH: u1, + GPIO3_EDGE_LOW: u1, + GPIO3_EDGE_HIGH: u1, + GPIO4_LEVEL_LOW: u1, + GPIO4_LEVEL_HIGH: u1, + GPIO4_EDGE_LOW: u1, + GPIO4_EDGE_HIGH: u1, + GPIO5_LEVEL_LOW: u1, + GPIO5_LEVEL_HIGH: u1, + GPIO5_EDGE_LOW: u1, + GPIO5_EDGE_HIGH: u1, + GPIO6_LEVEL_LOW: u1, + GPIO6_LEVEL_HIGH: u1, + GPIO6_EDGE_LOW: u1, + GPIO6_EDGE_HIGH: u1, + GPIO7_LEVEL_LOW: u1, + GPIO7_LEVEL_HIGH: u1, + GPIO7_EDGE_LOW: u1, + GPIO7_EDGE_HIGH: u1, + }), base_address + 0x170); + + /// address: 0x40014174 + /// Interrupt Force for dormant_wake + pub const DORMANT_WAKE_INTF1 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO8_LEVEL_LOW: u1, + GPIO8_LEVEL_HIGH: u1, + GPIO8_EDGE_LOW: u1, + GPIO8_EDGE_HIGH: u1, + GPIO9_LEVEL_LOW: u1, + GPIO9_LEVEL_HIGH: u1, + GPIO9_EDGE_LOW: u1, + GPIO9_EDGE_HIGH: u1, + GPIO10_LEVEL_LOW: u1, + GPIO10_LEVEL_HIGH: u1, + GPIO10_EDGE_LOW: u1, + GPIO10_EDGE_HIGH: u1, + GPIO11_LEVEL_LOW: u1, + GPIO11_LEVEL_HIGH: u1, + GPIO11_EDGE_LOW: u1, + GPIO11_EDGE_HIGH: u1, + GPIO12_LEVEL_LOW: u1, + GPIO12_LEVEL_HIGH: u1, + GPIO12_EDGE_LOW: u1, + GPIO12_EDGE_HIGH: u1, + GPIO13_LEVEL_LOW: u1, + GPIO13_LEVEL_HIGH: u1, + GPIO13_EDGE_LOW: u1, + GPIO13_EDGE_HIGH: u1, + GPIO14_LEVEL_LOW: u1, + GPIO14_LEVEL_HIGH: u1, + GPIO14_EDGE_LOW: u1, + GPIO14_EDGE_HIGH: u1, + GPIO15_LEVEL_LOW: u1, + GPIO15_LEVEL_HIGH: u1, + GPIO15_EDGE_LOW: u1, + GPIO15_EDGE_HIGH: u1, + }), base_address + 0x174); + + /// address: 0x40014178 + /// Interrupt Force for dormant_wake + pub const DORMANT_WAKE_INTF2 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO16_LEVEL_LOW: u1, + GPIO16_LEVEL_HIGH: u1, + GPIO16_EDGE_LOW: u1, + GPIO16_EDGE_HIGH: u1, + GPIO17_LEVEL_LOW: u1, + GPIO17_LEVEL_HIGH: u1, + GPIO17_EDGE_LOW: u1, + GPIO17_EDGE_HIGH: u1, + GPIO18_LEVEL_LOW: u1, + GPIO18_LEVEL_HIGH: u1, + GPIO18_EDGE_LOW: u1, + GPIO18_EDGE_HIGH: u1, + GPIO19_LEVEL_LOW: u1, + GPIO19_LEVEL_HIGH: u1, + GPIO19_EDGE_LOW: u1, + GPIO19_EDGE_HIGH: u1, + GPIO20_LEVEL_LOW: u1, + GPIO20_LEVEL_HIGH: u1, + GPIO20_EDGE_LOW: u1, + GPIO20_EDGE_HIGH: u1, + GPIO21_LEVEL_LOW: u1, + GPIO21_LEVEL_HIGH: u1, + GPIO21_EDGE_LOW: u1, + GPIO21_EDGE_HIGH: u1, + GPIO22_LEVEL_LOW: u1, + GPIO22_LEVEL_HIGH: u1, + GPIO22_EDGE_LOW: u1, + GPIO22_EDGE_HIGH: u1, + GPIO23_LEVEL_LOW: u1, + GPIO23_LEVEL_HIGH: u1, + GPIO23_EDGE_LOW: u1, + GPIO23_EDGE_HIGH: u1, + }), base_address + 0x178); + + /// address: 0x4001417c + /// Interrupt Force for dormant_wake + pub const DORMANT_WAKE_INTF3 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO24_LEVEL_LOW: u1, + GPIO24_LEVEL_HIGH: u1, + GPIO24_EDGE_LOW: u1, + GPIO24_EDGE_HIGH: u1, + GPIO25_LEVEL_LOW: u1, + GPIO25_LEVEL_HIGH: u1, + GPIO25_EDGE_LOW: u1, + GPIO25_EDGE_HIGH: u1, + GPIO26_LEVEL_LOW: u1, + GPIO26_LEVEL_HIGH: u1, + GPIO26_EDGE_LOW: u1, + GPIO26_EDGE_HIGH: u1, + GPIO27_LEVEL_LOW: u1, + GPIO27_LEVEL_HIGH: u1, + GPIO27_EDGE_LOW: u1, + GPIO27_EDGE_HIGH: u1, + GPIO28_LEVEL_LOW: u1, + GPIO28_LEVEL_HIGH: u1, + GPIO28_EDGE_LOW: u1, + GPIO28_EDGE_HIGH: u1, + GPIO29_LEVEL_LOW: u1, + GPIO29_LEVEL_HIGH: u1, + GPIO29_EDGE_LOW: u1, + GPIO29_EDGE_HIGH: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x17c); + + /// address: 0x40014180 + /// Interrupt status after masking & forcing for dormant_wake + pub const DORMANT_WAKE_INTS0 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO0_LEVEL_LOW: u1, + GPIO0_LEVEL_HIGH: u1, + GPIO0_EDGE_LOW: u1, + GPIO0_EDGE_HIGH: u1, + GPIO1_LEVEL_LOW: u1, + GPIO1_LEVEL_HIGH: u1, + GPIO1_EDGE_LOW: u1, + GPIO1_EDGE_HIGH: u1, + GPIO2_LEVEL_LOW: u1, + GPIO2_LEVEL_HIGH: u1, + GPIO2_EDGE_LOW: u1, + GPIO2_EDGE_HIGH: u1, + GPIO3_LEVEL_LOW: u1, + GPIO3_LEVEL_HIGH: u1, + GPIO3_EDGE_LOW: u1, + GPIO3_EDGE_HIGH: u1, + GPIO4_LEVEL_LOW: u1, + GPIO4_LEVEL_HIGH: u1, + GPIO4_EDGE_LOW: u1, + GPIO4_EDGE_HIGH: u1, + GPIO5_LEVEL_LOW: u1, + GPIO5_LEVEL_HIGH: u1, + GPIO5_EDGE_LOW: u1, + GPIO5_EDGE_HIGH: u1, + GPIO6_LEVEL_LOW: u1, + GPIO6_LEVEL_HIGH: u1, + GPIO6_EDGE_LOW: u1, + GPIO6_EDGE_HIGH: u1, + GPIO7_LEVEL_LOW: u1, + GPIO7_LEVEL_HIGH: u1, + GPIO7_EDGE_LOW: u1, + GPIO7_EDGE_HIGH: u1, + }), base_address + 0x180); + + /// address: 0x40014184 + /// Interrupt status after masking & forcing for dormant_wake + pub const DORMANT_WAKE_INTS1 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO8_LEVEL_LOW: u1, + GPIO8_LEVEL_HIGH: u1, + GPIO8_EDGE_LOW: u1, + GPIO8_EDGE_HIGH: u1, + GPIO9_LEVEL_LOW: u1, + GPIO9_LEVEL_HIGH: u1, + GPIO9_EDGE_LOW: u1, + GPIO9_EDGE_HIGH: u1, + GPIO10_LEVEL_LOW: u1, + GPIO10_LEVEL_HIGH: u1, + GPIO10_EDGE_LOW: u1, + GPIO10_EDGE_HIGH: u1, + GPIO11_LEVEL_LOW: u1, + GPIO11_LEVEL_HIGH: u1, + GPIO11_EDGE_LOW: u1, + GPIO11_EDGE_HIGH: u1, + GPIO12_LEVEL_LOW: u1, + GPIO12_LEVEL_HIGH: u1, + GPIO12_EDGE_LOW: u1, + GPIO12_EDGE_HIGH: u1, + GPIO13_LEVEL_LOW: u1, + GPIO13_LEVEL_HIGH: u1, + GPIO13_EDGE_LOW: u1, + GPIO13_EDGE_HIGH: u1, + GPIO14_LEVEL_LOW: u1, + GPIO14_LEVEL_HIGH: u1, + GPIO14_EDGE_LOW: u1, + GPIO14_EDGE_HIGH: u1, + GPIO15_LEVEL_LOW: u1, + GPIO15_LEVEL_HIGH: u1, + GPIO15_EDGE_LOW: u1, + GPIO15_EDGE_HIGH: u1, + }), base_address + 0x184); + + /// address: 0x40014188 + /// Interrupt status after masking & forcing for dormant_wake + pub const DORMANT_WAKE_INTS2 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO16_LEVEL_LOW: u1, + GPIO16_LEVEL_HIGH: u1, + GPIO16_EDGE_LOW: u1, + GPIO16_EDGE_HIGH: u1, + GPIO17_LEVEL_LOW: u1, + GPIO17_LEVEL_HIGH: u1, + GPIO17_EDGE_LOW: u1, + GPIO17_EDGE_HIGH: u1, + GPIO18_LEVEL_LOW: u1, + GPIO18_LEVEL_HIGH: u1, + GPIO18_EDGE_LOW: u1, + GPIO18_EDGE_HIGH: u1, + GPIO19_LEVEL_LOW: u1, + GPIO19_LEVEL_HIGH: u1, + GPIO19_EDGE_LOW: u1, + GPIO19_EDGE_HIGH: u1, + GPIO20_LEVEL_LOW: u1, + GPIO20_LEVEL_HIGH: u1, + GPIO20_EDGE_LOW: u1, + GPIO20_EDGE_HIGH: u1, + GPIO21_LEVEL_LOW: u1, + GPIO21_LEVEL_HIGH: u1, + GPIO21_EDGE_LOW: u1, + GPIO21_EDGE_HIGH: u1, + GPIO22_LEVEL_LOW: u1, + GPIO22_LEVEL_HIGH: u1, + GPIO22_EDGE_LOW: u1, + GPIO22_EDGE_HIGH: u1, + GPIO23_LEVEL_LOW: u1, + GPIO23_LEVEL_HIGH: u1, + GPIO23_EDGE_LOW: u1, + GPIO23_EDGE_HIGH: u1, + }), base_address + 0x188); + + /// address: 0x4001418c + /// Interrupt status after masking & forcing for dormant_wake + pub const DORMANT_WAKE_INTS3 = @intToPtr(*volatile Mmio(32, packed struct { + GPIO24_LEVEL_LOW: u1, + GPIO24_LEVEL_HIGH: u1, + GPIO24_EDGE_LOW: u1, + GPIO24_EDGE_HIGH: u1, + GPIO25_LEVEL_LOW: u1, + GPIO25_LEVEL_HIGH: u1, + GPIO25_EDGE_LOW: u1, + GPIO25_EDGE_HIGH: u1, + GPIO26_LEVEL_LOW: u1, + GPIO26_LEVEL_HIGH: u1, + GPIO26_EDGE_LOW: u1, + GPIO26_EDGE_HIGH: u1, + GPIO27_LEVEL_LOW: u1, + GPIO27_LEVEL_HIGH: u1, + GPIO27_EDGE_LOW: u1, + GPIO27_EDGE_HIGH: u1, + GPIO28_LEVEL_LOW: u1, + GPIO28_LEVEL_HIGH: u1, + GPIO28_EDGE_LOW: u1, + GPIO28_EDGE_HIGH: u1, + GPIO29_LEVEL_LOW: u1, + GPIO29_LEVEL_HIGH: u1, + GPIO29_EDGE_LOW: u1, + GPIO29_EDGE_HIGH: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x18c); + }; + pub const IO_QSPI = struct { + pub const base_address = 0x40018000; + pub const version = "1"; + + /// address: 0x40018000 + /// GPIO status + pub const GPIO_QSPI_SCLK_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x0); + + /// address: 0x40018004 + /// GPIO control including function select and overrides. + pub const GPIO_QSPI_SCLK_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0x4); + + /// address: 0x40018008 + /// GPIO status + pub const GPIO_QSPI_SS_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x8); + + /// address: 0x4001800c + /// GPIO control including function select and overrides. + pub const GPIO_QSPI_SS_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0xc); + + /// address: 0x40018010 + /// GPIO status + pub const GPIO_QSPI_SD0_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x10); + + /// address: 0x40018014 + /// GPIO control including function select and overrides. + pub const GPIO_QSPI_SD0_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0x14); + + /// address: 0x40018018 + /// GPIO status + pub const GPIO_QSPI_SD1_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x18); + + /// address: 0x4001801c + /// GPIO control including function select and overrides. + pub const GPIO_QSPI_SD1_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0x1c); + + /// address: 0x40018020 + /// GPIO status + pub const GPIO_QSPI_SD2_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x20); + + /// address: 0x40018024 + /// GPIO control including function select and overrides. + pub const GPIO_QSPI_SD2_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0x24); + + /// address: 0x40018028 + /// GPIO status + pub const GPIO_QSPI_SD3_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved13: u1 = 0, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved18: u1 = 0, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x28); + + /// address: 0x4001802c + /// GPIO control including function select and overrides. + pub const GPIO_QSPI_SD3_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// 0-31 -> selects pin function according to the gpio table\n + /// 31 == NULL + FUNCSEL: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + OUTOVER: u2, + reserved3: u1 = 0, + reserved4: u1 = 0, + OEOVER: u2, + reserved5: u1 = 0, + reserved6: u1 = 0, + INOVER: u2, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + IRQOVER: u2, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0x2c); + + /// address: 0x40018030 + /// Raw Interrupts + pub const INTR = @intToPtr(*volatile Mmio(32, packed struct { + GPIO_QSPI_SCLK_LEVEL_LOW: u1, + GPIO_QSPI_SCLK_LEVEL_HIGH: u1, + GPIO_QSPI_SCLK_EDGE_LOW: u1, + GPIO_QSPI_SCLK_EDGE_HIGH: u1, + GPIO_QSPI_SS_LEVEL_LOW: u1, + GPIO_QSPI_SS_LEVEL_HIGH: u1, + GPIO_QSPI_SS_EDGE_LOW: u1, + GPIO_QSPI_SS_EDGE_HIGH: u1, + GPIO_QSPI_SD0_LEVEL_LOW: u1, + GPIO_QSPI_SD0_LEVEL_HIGH: u1, + GPIO_QSPI_SD0_EDGE_LOW: u1, + GPIO_QSPI_SD0_EDGE_HIGH: u1, + GPIO_QSPI_SD1_LEVEL_LOW: u1, + GPIO_QSPI_SD1_LEVEL_HIGH: u1, + GPIO_QSPI_SD1_EDGE_LOW: u1, + GPIO_QSPI_SD1_EDGE_HIGH: u1, + GPIO_QSPI_SD2_LEVEL_LOW: u1, + GPIO_QSPI_SD2_LEVEL_HIGH: u1, + GPIO_QSPI_SD2_EDGE_LOW: u1, + GPIO_QSPI_SD2_EDGE_HIGH: u1, + GPIO_QSPI_SD3_LEVEL_LOW: u1, + GPIO_QSPI_SD3_LEVEL_HIGH: u1, + GPIO_QSPI_SD3_EDGE_LOW: u1, + GPIO_QSPI_SD3_EDGE_HIGH: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x30); + + /// address: 0x40018034 + /// Interrupt Enable for proc0 + pub const PROC0_INTE = @intToPtr(*volatile Mmio(32, packed struct { + GPIO_QSPI_SCLK_LEVEL_LOW: u1, + GPIO_QSPI_SCLK_LEVEL_HIGH: u1, + GPIO_QSPI_SCLK_EDGE_LOW: u1, + GPIO_QSPI_SCLK_EDGE_HIGH: u1, + GPIO_QSPI_SS_LEVEL_LOW: u1, + GPIO_QSPI_SS_LEVEL_HIGH: u1, + GPIO_QSPI_SS_EDGE_LOW: u1, + GPIO_QSPI_SS_EDGE_HIGH: u1, + GPIO_QSPI_SD0_LEVEL_LOW: u1, + GPIO_QSPI_SD0_LEVEL_HIGH: u1, + GPIO_QSPI_SD0_EDGE_LOW: u1, + GPIO_QSPI_SD0_EDGE_HIGH: u1, + GPIO_QSPI_SD1_LEVEL_LOW: u1, + GPIO_QSPI_SD1_LEVEL_HIGH: u1, + GPIO_QSPI_SD1_EDGE_LOW: u1, + GPIO_QSPI_SD1_EDGE_HIGH: u1, + GPIO_QSPI_SD2_LEVEL_LOW: u1, + GPIO_QSPI_SD2_LEVEL_HIGH: u1, + GPIO_QSPI_SD2_EDGE_LOW: u1, + GPIO_QSPI_SD2_EDGE_HIGH: u1, + GPIO_QSPI_SD3_LEVEL_LOW: u1, + GPIO_QSPI_SD3_LEVEL_HIGH: u1, + GPIO_QSPI_SD3_EDGE_LOW: u1, + GPIO_QSPI_SD3_EDGE_HIGH: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x34); + + /// address: 0x40018038 + /// Interrupt Force for proc0 + pub const PROC0_INTF = @intToPtr(*volatile Mmio(32, packed struct { + GPIO_QSPI_SCLK_LEVEL_LOW: u1, + GPIO_QSPI_SCLK_LEVEL_HIGH: u1, + GPIO_QSPI_SCLK_EDGE_LOW: u1, + GPIO_QSPI_SCLK_EDGE_HIGH: u1, + GPIO_QSPI_SS_LEVEL_LOW: u1, + GPIO_QSPI_SS_LEVEL_HIGH: u1, + GPIO_QSPI_SS_EDGE_LOW: u1, + GPIO_QSPI_SS_EDGE_HIGH: u1, + GPIO_QSPI_SD0_LEVEL_LOW: u1, + GPIO_QSPI_SD0_LEVEL_HIGH: u1, + GPIO_QSPI_SD0_EDGE_LOW: u1, + GPIO_QSPI_SD0_EDGE_HIGH: u1, + GPIO_QSPI_SD1_LEVEL_LOW: u1, + GPIO_QSPI_SD1_LEVEL_HIGH: u1, + GPIO_QSPI_SD1_EDGE_LOW: u1, + GPIO_QSPI_SD1_EDGE_HIGH: u1, + GPIO_QSPI_SD2_LEVEL_LOW: u1, + GPIO_QSPI_SD2_LEVEL_HIGH: u1, + GPIO_QSPI_SD2_EDGE_LOW: u1, + GPIO_QSPI_SD2_EDGE_HIGH: u1, + GPIO_QSPI_SD3_LEVEL_LOW: u1, + GPIO_QSPI_SD3_LEVEL_HIGH: u1, + GPIO_QSPI_SD3_EDGE_LOW: u1, + GPIO_QSPI_SD3_EDGE_HIGH: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x38); + + /// address: 0x4001803c + /// Interrupt status after masking & forcing for proc0 + pub const PROC0_INTS = @intToPtr(*volatile Mmio(32, packed struct { + GPIO_QSPI_SCLK_LEVEL_LOW: u1, + GPIO_QSPI_SCLK_LEVEL_HIGH: u1, + GPIO_QSPI_SCLK_EDGE_LOW: u1, + GPIO_QSPI_SCLK_EDGE_HIGH: u1, + GPIO_QSPI_SS_LEVEL_LOW: u1, + GPIO_QSPI_SS_LEVEL_HIGH: u1, + GPIO_QSPI_SS_EDGE_LOW: u1, + GPIO_QSPI_SS_EDGE_HIGH: u1, + GPIO_QSPI_SD0_LEVEL_LOW: u1, + GPIO_QSPI_SD0_LEVEL_HIGH: u1, + GPIO_QSPI_SD0_EDGE_LOW: u1, + GPIO_QSPI_SD0_EDGE_HIGH: u1, + GPIO_QSPI_SD1_LEVEL_LOW: u1, + GPIO_QSPI_SD1_LEVEL_HIGH: u1, + GPIO_QSPI_SD1_EDGE_LOW: u1, + GPIO_QSPI_SD1_EDGE_HIGH: u1, + GPIO_QSPI_SD2_LEVEL_LOW: u1, + GPIO_QSPI_SD2_LEVEL_HIGH: u1, + GPIO_QSPI_SD2_EDGE_LOW: u1, + GPIO_QSPI_SD2_EDGE_HIGH: u1, + GPIO_QSPI_SD3_LEVEL_LOW: u1, + GPIO_QSPI_SD3_LEVEL_HIGH: u1, + GPIO_QSPI_SD3_EDGE_LOW: u1, + GPIO_QSPI_SD3_EDGE_HIGH: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x3c); + + /// address: 0x40018040 + /// Interrupt Enable for proc1 + pub const PROC1_INTE = @intToPtr(*volatile Mmio(32, packed struct { + GPIO_QSPI_SCLK_LEVEL_LOW: u1, + GPIO_QSPI_SCLK_LEVEL_HIGH: u1, + GPIO_QSPI_SCLK_EDGE_LOW: u1, + GPIO_QSPI_SCLK_EDGE_HIGH: u1, + GPIO_QSPI_SS_LEVEL_LOW: u1, + GPIO_QSPI_SS_LEVEL_HIGH: u1, + GPIO_QSPI_SS_EDGE_LOW: u1, + GPIO_QSPI_SS_EDGE_HIGH: u1, + GPIO_QSPI_SD0_LEVEL_LOW: u1, + GPIO_QSPI_SD0_LEVEL_HIGH: u1, + GPIO_QSPI_SD0_EDGE_LOW: u1, + GPIO_QSPI_SD0_EDGE_HIGH: u1, + GPIO_QSPI_SD1_LEVEL_LOW: u1, + GPIO_QSPI_SD1_LEVEL_HIGH: u1, + GPIO_QSPI_SD1_EDGE_LOW: u1, + GPIO_QSPI_SD1_EDGE_HIGH: u1, + GPIO_QSPI_SD2_LEVEL_LOW: u1, + GPIO_QSPI_SD2_LEVEL_HIGH: u1, + GPIO_QSPI_SD2_EDGE_LOW: u1, + GPIO_QSPI_SD2_EDGE_HIGH: u1, + GPIO_QSPI_SD3_LEVEL_LOW: u1, + GPIO_QSPI_SD3_LEVEL_HIGH: u1, + GPIO_QSPI_SD3_EDGE_LOW: u1, + GPIO_QSPI_SD3_EDGE_HIGH: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x40); + + /// address: 0x40018044 + /// Interrupt Force for proc1 + pub const PROC1_INTF = @intToPtr(*volatile Mmio(32, packed struct { + GPIO_QSPI_SCLK_LEVEL_LOW: u1, + GPIO_QSPI_SCLK_LEVEL_HIGH: u1, + GPIO_QSPI_SCLK_EDGE_LOW: u1, + GPIO_QSPI_SCLK_EDGE_HIGH: u1, + GPIO_QSPI_SS_LEVEL_LOW: u1, + GPIO_QSPI_SS_LEVEL_HIGH: u1, + GPIO_QSPI_SS_EDGE_LOW: u1, + GPIO_QSPI_SS_EDGE_HIGH: u1, + GPIO_QSPI_SD0_LEVEL_LOW: u1, + GPIO_QSPI_SD0_LEVEL_HIGH: u1, + GPIO_QSPI_SD0_EDGE_LOW: u1, + GPIO_QSPI_SD0_EDGE_HIGH: u1, + GPIO_QSPI_SD1_LEVEL_LOW: u1, + GPIO_QSPI_SD1_LEVEL_HIGH: u1, + GPIO_QSPI_SD1_EDGE_LOW: u1, + GPIO_QSPI_SD1_EDGE_HIGH: u1, + GPIO_QSPI_SD2_LEVEL_LOW: u1, + GPIO_QSPI_SD2_LEVEL_HIGH: u1, + GPIO_QSPI_SD2_EDGE_LOW: u1, + GPIO_QSPI_SD2_EDGE_HIGH: u1, + GPIO_QSPI_SD3_LEVEL_LOW: u1, + GPIO_QSPI_SD3_LEVEL_HIGH: u1, + GPIO_QSPI_SD3_EDGE_LOW: u1, + GPIO_QSPI_SD3_EDGE_HIGH: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x44); + + /// address: 0x40018048 + /// Interrupt status after masking & forcing for proc1 + pub const PROC1_INTS = @intToPtr(*volatile Mmio(32, packed struct { + GPIO_QSPI_SCLK_LEVEL_LOW: u1, + GPIO_QSPI_SCLK_LEVEL_HIGH: u1, + GPIO_QSPI_SCLK_EDGE_LOW: u1, + GPIO_QSPI_SCLK_EDGE_HIGH: u1, + GPIO_QSPI_SS_LEVEL_LOW: u1, + GPIO_QSPI_SS_LEVEL_HIGH: u1, + GPIO_QSPI_SS_EDGE_LOW: u1, + GPIO_QSPI_SS_EDGE_HIGH: u1, + GPIO_QSPI_SD0_LEVEL_LOW: u1, + GPIO_QSPI_SD0_LEVEL_HIGH: u1, + GPIO_QSPI_SD0_EDGE_LOW: u1, + GPIO_QSPI_SD0_EDGE_HIGH: u1, + GPIO_QSPI_SD1_LEVEL_LOW: u1, + GPIO_QSPI_SD1_LEVEL_HIGH: u1, + GPIO_QSPI_SD1_EDGE_LOW: u1, + GPIO_QSPI_SD1_EDGE_HIGH: u1, + GPIO_QSPI_SD2_LEVEL_LOW: u1, + GPIO_QSPI_SD2_LEVEL_HIGH: u1, + GPIO_QSPI_SD2_EDGE_LOW: u1, + GPIO_QSPI_SD2_EDGE_HIGH: u1, + GPIO_QSPI_SD3_LEVEL_LOW: u1, + GPIO_QSPI_SD3_LEVEL_HIGH: u1, + GPIO_QSPI_SD3_EDGE_LOW: u1, + GPIO_QSPI_SD3_EDGE_HIGH: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x48); + + /// address: 0x4001804c + /// Interrupt Enable for dormant_wake + pub const DORMANT_WAKE_INTE = @intToPtr(*volatile Mmio(32, packed struct { + GPIO_QSPI_SCLK_LEVEL_LOW: u1, + GPIO_QSPI_SCLK_LEVEL_HIGH: u1, + GPIO_QSPI_SCLK_EDGE_LOW: u1, + GPIO_QSPI_SCLK_EDGE_HIGH: u1, + GPIO_QSPI_SS_LEVEL_LOW: u1, + GPIO_QSPI_SS_LEVEL_HIGH: u1, + GPIO_QSPI_SS_EDGE_LOW: u1, + GPIO_QSPI_SS_EDGE_HIGH: u1, + GPIO_QSPI_SD0_LEVEL_LOW: u1, + GPIO_QSPI_SD0_LEVEL_HIGH: u1, + GPIO_QSPI_SD0_EDGE_LOW: u1, + GPIO_QSPI_SD0_EDGE_HIGH: u1, + GPIO_QSPI_SD1_LEVEL_LOW: u1, + GPIO_QSPI_SD1_LEVEL_HIGH: u1, + GPIO_QSPI_SD1_EDGE_LOW: u1, + GPIO_QSPI_SD1_EDGE_HIGH: u1, + GPIO_QSPI_SD2_LEVEL_LOW: u1, + GPIO_QSPI_SD2_LEVEL_HIGH: u1, + GPIO_QSPI_SD2_EDGE_LOW: u1, + GPIO_QSPI_SD2_EDGE_HIGH: u1, + GPIO_QSPI_SD3_LEVEL_LOW: u1, + GPIO_QSPI_SD3_LEVEL_HIGH: u1, + GPIO_QSPI_SD3_EDGE_LOW: u1, + GPIO_QSPI_SD3_EDGE_HIGH: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x4c); + + /// address: 0x40018050 + /// Interrupt Force for dormant_wake + pub const DORMANT_WAKE_INTF = @intToPtr(*volatile Mmio(32, packed struct { + GPIO_QSPI_SCLK_LEVEL_LOW: u1, + GPIO_QSPI_SCLK_LEVEL_HIGH: u1, + GPIO_QSPI_SCLK_EDGE_LOW: u1, + GPIO_QSPI_SCLK_EDGE_HIGH: u1, + GPIO_QSPI_SS_LEVEL_LOW: u1, + GPIO_QSPI_SS_LEVEL_HIGH: u1, + GPIO_QSPI_SS_EDGE_LOW: u1, + GPIO_QSPI_SS_EDGE_HIGH: u1, + GPIO_QSPI_SD0_LEVEL_LOW: u1, + GPIO_QSPI_SD0_LEVEL_HIGH: u1, + GPIO_QSPI_SD0_EDGE_LOW: u1, + GPIO_QSPI_SD0_EDGE_HIGH: u1, + GPIO_QSPI_SD1_LEVEL_LOW: u1, + GPIO_QSPI_SD1_LEVEL_HIGH: u1, + GPIO_QSPI_SD1_EDGE_LOW: u1, + GPIO_QSPI_SD1_EDGE_HIGH: u1, + GPIO_QSPI_SD2_LEVEL_LOW: u1, + GPIO_QSPI_SD2_LEVEL_HIGH: u1, + GPIO_QSPI_SD2_EDGE_LOW: u1, + GPIO_QSPI_SD2_EDGE_HIGH: u1, + GPIO_QSPI_SD3_LEVEL_LOW: u1, + GPIO_QSPI_SD3_LEVEL_HIGH: u1, + GPIO_QSPI_SD3_EDGE_LOW: u1, + GPIO_QSPI_SD3_EDGE_HIGH: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x50); + + /// address: 0x40018054 + /// Interrupt status after masking & forcing for dormant_wake + pub const DORMANT_WAKE_INTS = @intToPtr(*volatile Mmio(32, packed struct { + GPIO_QSPI_SCLK_LEVEL_LOW: u1, + GPIO_QSPI_SCLK_LEVEL_HIGH: u1, + GPIO_QSPI_SCLK_EDGE_LOW: u1, + GPIO_QSPI_SCLK_EDGE_HIGH: u1, + GPIO_QSPI_SS_LEVEL_LOW: u1, + GPIO_QSPI_SS_LEVEL_HIGH: u1, + GPIO_QSPI_SS_EDGE_LOW: u1, + GPIO_QSPI_SS_EDGE_HIGH: u1, + GPIO_QSPI_SD0_LEVEL_LOW: u1, + GPIO_QSPI_SD0_LEVEL_HIGH: u1, + GPIO_QSPI_SD0_EDGE_LOW: u1, + GPIO_QSPI_SD0_EDGE_HIGH: u1, + GPIO_QSPI_SD1_LEVEL_LOW: u1, + GPIO_QSPI_SD1_LEVEL_HIGH: u1, + GPIO_QSPI_SD1_EDGE_LOW: u1, + GPIO_QSPI_SD1_EDGE_HIGH: u1, + GPIO_QSPI_SD2_LEVEL_LOW: u1, + GPIO_QSPI_SD2_LEVEL_HIGH: u1, + GPIO_QSPI_SD2_EDGE_LOW: u1, + GPIO_QSPI_SD2_EDGE_HIGH: u1, + GPIO_QSPI_SD3_LEVEL_LOW: u1, + GPIO_QSPI_SD3_LEVEL_HIGH: u1, + GPIO_QSPI_SD3_EDGE_LOW: u1, + GPIO_QSPI_SD3_EDGE_HIGH: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x54); + }; + pub const PADS_BANK0 = struct { + pub const base_address = 0x4001c000; + pub const version = "1"; + + /// address: 0x4001c000 + /// Voltage select. Per bank control + pub const VOLTAGE_SELECT = @intToPtr(*volatile MmioInt(32, u1), base_address + 0x0); + + /// address: 0x4001c004 + /// Pad control register + pub const GPIO0 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x4); + + /// address: 0x4001c008 + /// Pad control register + pub const GPIO1 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x8); + + /// address: 0x4001c00c + /// Pad control register + pub const GPIO2 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0xc); + + /// address: 0x4001c010 + /// Pad control register + pub const GPIO3 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x10); + + /// address: 0x4001c014 + /// Pad control register + pub const GPIO4 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x14); + + /// address: 0x4001c018 + /// Pad control register + pub const GPIO5 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x18); + + /// address: 0x4001c01c + /// Pad control register + pub const GPIO6 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x1c); + + /// address: 0x4001c020 + /// Pad control register + pub const GPIO7 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x20); + + /// address: 0x4001c024 + /// Pad control register + pub const GPIO8 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x24); + + /// address: 0x4001c028 + /// Pad control register + pub const GPIO9 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x28); + + /// address: 0x4001c02c + /// Pad control register + pub const GPIO10 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x2c); + + /// address: 0x4001c030 + /// Pad control register + pub const GPIO11 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x30); + + /// address: 0x4001c034 + /// Pad control register + pub const GPIO12 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x34); + + /// address: 0x4001c038 + /// Pad control register + pub const GPIO13 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x38); + + /// address: 0x4001c03c + /// Pad control register + pub const GPIO14 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x3c); + + /// address: 0x4001c040 + /// Pad control register + pub const GPIO15 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x40); + + /// address: 0x4001c044 + /// Pad control register + pub const GPIO16 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x44); + + /// address: 0x4001c048 + /// Pad control register + pub const GPIO17 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x48); + + /// address: 0x4001c04c + /// Pad control register + pub const GPIO18 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x4c); + + /// address: 0x4001c050 + /// Pad control register + pub const GPIO19 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x50); + + /// address: 0x4001c054 + /// Pad control register + pub const GPIO20 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x54); + + /// address: 0x4001c058 + /// Pad control register + pub const GPIO21 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x58); + + /// address: 0x4001c05c + /// Pad control register + pub const GPIO22 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x5c); + + /// address: 0x4001c060 + /// Pad control register + pub const GPIO23 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x60); + + /// address: 0x4001c064 + /// Pad control register + pub const GPIO24 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x64); + + /// address: 0x4001c068 + /// Pad control register + pub const GPIO25 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x68); + + /// address: 0x4001c06c + /// Pad control register + pub const GPIO26 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x6c); + + /// address: 0x4001c070 + /// Pad control register + pub const GPIO27 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x70); + + /// address: 0x4001c074 + /// Pad control register + pub const GPIO28 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x74); + + /// address: 0x4001c078 + /// Pad control register + pub const GPIO29 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x78); + + /// address: 0x4001c07c + /// Pad control register + pub const SWCLK = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x7c); + + /// address: 0x4001c080 + /// Pad control register + pub const SWD = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x80); + }; + pub const PADS_QSPI = struct { + pub const base_address = 0x40020000; + pub const version = "1"; + + /// address: 0x40020000 + /// Voltage select. Per bank control + pub const VOLTAGE_SELECT = @intToPtr(*volatile MmioInt(32, u1), base_address + 0x0); + + /// address: 0x40020004 + /// Pad control register + pub const GPIO_QSPI_SCLK = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x4); + + /// address: 0x40020008 + /// Pad control register + pub const GPIO_QSPI_SD0 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x8); + + /// address: 0x4002000c + /// Pad control register + pub const GPIO_QSPI_SD1 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0xc); + + /// address: 0x40020010 + /// Pad control register + pub const GPIO_QSPI_SD2 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x10); + + /// address: 0x40020014 + /// Pad control register + pub const GPIO_QSPI_SD3 = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x14); + + /// address: 0x40020018 + /// Pad control register + pub const GPIO_QSPI_SS = @intToPtr(*volatile Mmio(32, packed struct { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: u2, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x18); + }; + + /// Controls the crystal oscillator + pub const XOSC = struct { + pub const base_address = 0x40024000; + pub const version = "1"; + + /// address: 0x40024000 + /// Crystal Oscillator Control + pub const CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// Frequency range. This resets to 0xAA0 and cannot be changed. + FREQ_RANGE: u12, + /// On power-up this field is initialised to DISABLE and the chip runs from the + /// ROSC.\n + /// If the chip has subsequently been programmed to run from the XOSC then setting + /// this field to DISABLE may lock-up the chip. If this is a concern then run the + /// clk_ref from the ROSC and enable the clk_sys RESUS feature.\n + /// The 12-bit code is intended to give some protection against accidental writes. + /// An invalid setting will enable the oscillator. + ENABLE: u12, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x0); + + /// address: 0x40024004 + /// Crystal Oscillator Status + pub const STATUS = @intToPtr(*volatile Mmio(32, packed struct { + /// The current frequency range setting, always reads 0 + FREQ_RANGE: u2, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + /// Oscillator is enabled but not necessarily running and stable, resets to 0 + ENABLED: u1, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + reserved18: u1 = 0, + reserved19: u1 = 0, + reserved20: u1 = 0, + /// An invalid value has been written to CTRL_ENABLE or CTRL_FREQ_RANGE or DORMANT + BADWRITE: u1, + reserved21: u1 = 0, + reserved22: u1 = 0, + reserved23: u1 = 0, + reserved24: u1 = 0, + reserved25: u1 = 0, + reserved26: u1 = 0, + /// Oscillator is running and stable + STABLE: u1, + }), base_address + 0x4); + + /// address: 0x40024008 + /// Crystal Oscillator pause control\n + /// This is used to save power by pausing the XOSC\n + /// On power-up this field is initialised to WAKE\n + /// An invalid write will also select WAKE\n + /// WARNING: stop the PLLs before selecting dormant mode\n + /// WARNING: setup the irq before selecting dormant mode + pub const DORMANT = @intToPtr(*volatile u32, base_address + 0x8); + + /// address: 0x4002400c + /// Controls the startup delay + pub const STARTUP = @intToPtr(*volatile Mmio(32, packed struct { + /// in multiples of 256*xtal_period. The reset value of 0xc4 corresponds to approx + /// 50 000 cycles. + DELAY: u14, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + /// Multiplies the startup_delay by 4. This is of little value to the user given + /// that the delay can be programmed directly. + X4: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + }), base_address + 0xc); + + /// address: 0x4002401c + /// A down counter running at the xosc frequency which counts to zero and stops.\n + /// To start the counter write a non-zero value.\n + /// Can be used for short software pauses when setting up time sensitive hardware. + pub const COUNT = @intToPtr(*volatile MmioInt(32, u8), base_address + 0x1c); + }; + pub const PLL_SYS = struct { + pub const base_address = 0x40028000; + pub const version = "1"; + + /// address: 0x40028000 + /// Control and Status\n + /// GENERAL CONSTRAINTS:\n + /// Reference clock frequency min=5MHz, max=800MHz\n + /// Feedback divider min=16, max=320\n + /// VCO frequency min=400MHz, max=1600MHz + pub const CS = @intToPtr(*volatile Mmio(32, packed struct { + /// Divides the PLL input reference clock.\n + /// Behaviour is undefined for div=0.\n + /// PLL output will be unpredictable during refdiv changes, wait for lock=1 before + /// using it. + REFDIV: u6, + reserved0: u1 = 0, + reserved1: u1 = 0, + /// Passes the reference clock to the output instead of the divided VCO. The VCO + /// continues to run so the user can switch between the reference clock and the + /// divided VCO but the output will glitch when doing so. + BYPASS: u1, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + reserved18: u1 = 0, + reserved19: u1 = 0, + reserved20: u1 = 0, + reserved21: u1 = 0, + reserved22: u1 = 0, + reserved23: u1 = 0, + /// PLL is locked + LOCK: u1, + }), base_address + 0x0); + + /// address: 0x40028004 + /// Controls the PLL power modes. + pub const PWR = @intToPtr(*volatile Mmio(32, packed struct { + /// PLL powerdown\n + /// To save power set high when PLL output not required. + PD: u1, + reserved0: u1 = 0, + /// PLL DSM powerdown\n + /// Nothing is achieved by setting this low. + DSMPD: u1, + /// PLL post divider powerdown\n + /// To save power set high when PLL output not required or bypass=1. + POSTDIVPD: u1, + reserved1: u1 = 0, + /// PLL VCO powerdown\n + /// To save power set high when PLL output not required or bypass=1. + VCOPD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + }), base_address + 0x4); + + /// address: 0x40028008 + /// Feedback divisor\n + /// (note: this PLL does not support fractional division) + pub const FBDIV_INT = @intToPtr(*volatile MmioInt(32, u12), base_address + 0x8); + + /// address: 0x4002800c + /// Controls the PLL post dividers for the primary output\n + /// (note: this PLL does not have a secondary output)\n + /// the primary output is driven from VCO divided by postdiv1*postdiv2 + pub const PRIM = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + /// divide by 1-7 + POSTDIV2: u3, + reserved12: u1 = 0, + /// divide by 1-7 + POSTDIV1: u3, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + }), base_address + 0xc); + }; + pub const PLL_USB = struct { + pub const base_address = 0x4002c000; + + /// address: 0x4002c000 + /// Control and Status\n + /// GENERAL CONSTRAINTS:\n + /// Reference clock frequency min=5MHz, max=800MHz\n + /// Feedback divider min=16, max=320\n + /// VCO frequency min=400MHz, max=1600MHz + pub const CS = @intToPtr(*volatile Mmio(32, packed struct { + /// Divides the PLL input reference clock.\n + /// Behaviour is undefined for div=0.\n + /// PLL output will be unpredictable during refdiv changes, wait for lock=1 before + /// using it. + REFDIV: u6, + reserved0: u1 = 0, + reserved1: u1 = 0, + /// Passes the reference clock to the output instead of the divided VCO. The VCO + /// continues to run so the user can switch between the reference clock and the + /// divided VCO but the output will glitch when doing so. + BYPASS: u1, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + reserved18: u1 = 0, + reserved19: u1 = 0, + reserved20: u1 = 0, + reserved21: u1 = 0, + reserved22: u1 = 0, + reserved23: u1 = 0, + /// PLL is locked + LOCK: u1, + }), base_address + 0x0); + + /// address: 0x4002c004 + /// Controls the PLL power modes. + pub const PWR = @intToPtr(*volatile Mmio(32, packed struct { + /// PLL powerdown\n + /// To save power set high when PLL output not required. + PD: u1, + reserved0: u1 = 0, + /// PLL DSM powerdown\n + /// Nothing is achieved by setting this low. + DSMPD: u1, + /// PLL post divider powerdown\n + /// To save power set high when PLL output not required or bypass=1. + POSTDIVPD: u1, + reserved1: u1 = 0, + /// PLL VCO powerdown\n + /// To save power set high when PLL output not required or bypass=1. + VCOPD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + }), base_address + 0x4); + + /// address: 0x4002c008 + /// Feedback divisor\n + /// (note: this PLL does not support fractional division) + pub const FBDIV_INT = @intToPtr(*volatile MmioInt(32, u12), base_address + 0x8); + + /// address: 0x4002c00c + /// Controls the PLL post dividers for the primary output\n + /// (note: this PLL does not have a secondary output)\n + /// the primary output is driven from VCO divided by postdiv1*postdiv2 + pub const PRIM = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + /// divide by 1-7 + POSTDIV2: u3, + reserved12: u1 = 0, + /// divide by 1-7 + POSTDIV1: u3, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + }), base_address + 0xc); + }; + + /// Register block for busfabric control signals and performance counters + pub const BUSCTRL = struct { + pub const base_address = 0x40030000; + pub const version = "1"; + + /// address: 0x40030000 + /// Set the priority of each master for bus arbitration. + pub const BUS_PRIORITY = @intToPtr(*volatile Mmio(32, packed struct { + /// 0 - low priority, 1 - high priority + PROC0: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + /// 0 - low priority, 1 - high priority + PROC1: u1, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + /// 0 - low priority, 1 - high priority + DMA_R: u1, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + /// 0 - low priority, 1 - high priority + DMA_W: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + }), base_address + 0x0); + + /// address: 0x40030004 + /// Bus priority acknowledge + pub const BUS_PRIORITY_ACK = @intToPtr(*volatile MmioInt(32, u1), base_address + 0x4); + + /// address: 0x40030008 + /// Bus fabric performance counter 0 + pub const PERFCTR0 = @intToPtr(*volatile MmioInt(32, u24), base_address + 0x8); + + /// address: 0x4003000c + /// Bus fabric performance event select for PERFCTR0 + pub const PERFSEL0 = @intToPtr(*volatile MmioInt(32, u5), base_address + 0xc); + + /// address: 0x40030010 + /// Bus fabric performance counter 1 + pub const PERFCTR1 = @intToPtr(*volatile MmioInt(32, u24), base_address + 0x10); + + /// address: 0x40030014 + /// Bus fabric performance event select for PERFCTR1 + pub const PERFSEL1 = @intToPtr(*volatile MmioInt(32, u5), base_address + 0x14); + + /// address: 0x40030018 + /// Bus fabric performance counter 2 + pub const PERFCTR2 = @intToPtr(*volatile MmioInt(32, u24), base_address + 0x18); + + /// address: 0x4003001c + /// Bus fabric performance event select for PERFCTR2 + pub const PERFSEL2 = @intToPtr(*volatile MmioInt(32, u5), base_address + 0x1c); + + /// address: 0x40030020 + /// Bus fabric performance counter 3 + pub const PERFCTR3 = @intToPtr(*volatile MmioInt(32, u24), base_address + 0x20); + + /// address: 0x40030024 + /// Bus fabric performance event select for PERFCTR3 + pub const PERFSEL3 = @intToPtr(*volatile MmioInt(32, u5), base_address + 0x24); + }; + pub const UART0 = struct { + pub const base_address = 0x40034000; + pub const version = "1"; + + /// address: 0x40034000 + /// Data Register, UARTDR + pub const UARTDR = @intToPtr(*volatile Mmio(32, packed struct { + /// Receive (read) data character. Transmit (write) data character. + DATA: u8, + /// Framing error. When set to 1, it indicates that the received character did not + /// have a valid stop bit (a valid stop bit is 1). In FIFO mode, this error is + /// associated with the character at the top of the FIFO. + FE: u1, + /// Parity error. When set to 1, it indicates that the parity of the received data + /// character does not match the parity that the EPS and SPS bits in the Line + /// Control Register, UARTLCR_H. In FIFO mode, this error is associated with the + /// character at the top of the FIFO. + PE: u1, + /// Break error. This bit is set to 1 if a break condition was detected, indicating + /// that the received data input was held LOW for longer than a full-word + /// transmission time (defined as start, data, parity and stop bits). In FIFO mode, + /// this error is associated with the character at the top of the FIFO. When a break + /// occurs, only one 0 character is loaded into the FIFO. The next character is only + /// enabled after the receive data input goes to a 1 (marking state), and the next + /// valid start bit is received. + BE: u1, + /// Overrun error. This bit is set to 1 if data is received and the receive FIFO is + /// already full. This is cleared to 0 once there is an empty space in the FIFO and + /// a new character can be written to it. + OE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x0); + + /// address: 0x40034004 + /// Receive Status Register/Error Clear Register, UARTRSR/UARTECR + pub const UARTRSR = @intToPtr(*volatile Mmio(32, packed struct { + /// Framing error. When set to 1, it indicates that the received character did not + /// have a valid stop bit (a valid stop bit is 1). This bit is cleared to 0 by a + /// write to UARTECR. In FIFO mode, this error is associated with the character at + /// the top of the FIFO. + FE: u1, + /// Parity error. When set to 1, it indicates that the parity of the received data + /// character does not match the parity that the EPS and SPS bits in the Line + /// Control Register, UARTLCR_H. This bit is cleared to 0 by a write to UARTECR. In + /// FIFO mode, this error is associated with the character at the top of the FIFO. + PE: u1, + /// Break error. This bit is set to 1 if a break condition was detected, indicating + /// that the received data input was held LOW for longer than a full-word + /// transmission time (defined as start, data, parity, and stop bits). This bit is + /// cleared to 0 after a write to UARTECR. In FIFO mode, this error is associated + /// with the character at the top of the FIFO. When a break occurs, only one 0 + /// character is loaded into the FIFO. The next character is only enabled after the + /// receive data input goes to a 1 (marking state) and the next valid start bit is + /// received. + BE: u1, + /// Overrun error. This bit is set to 1 if data is received and the FIFO is already + /// full. This bit is cleared to 0 by a write to UARTECR. The FIFO contents remain + /// valid because no more data is written when the FIFO is full, only the contents + /// of the shift register are overwritten. The CPU must now read the data, to empty + /// the FIFO. + OE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + }), base_address + 0x4); + + /// address: 0x40034018 + /// Flag Register, UARTFR + pub const UARTFR = @intToPtr(*volatile Mmio(32, packed struct { + /// Clear to send. This bit is the complement of the UART clear to send, nUARTCTS, + /// modem status input. That is, the bit is 1 when nUARTCTS is LOW. + CTS: u1, + /// Data set ready. This bit is the complement of the UART data set ready, nUARTDSR, + /// modem status input. That is, the bit is 1 when nUARTDSR is LOW. + DSR: u1, + /// Data carrier detect. This bit is the complement of the UART data carrier detect, + /// nUARTDCD, modem status input. That is, the bit is 1 when nUARTDCD is LOW. + DCD: u1, + /// UART busy. If this bit is set to 1, the UART is busy transmitting data. This bit + /// remains set until the complete byte, including all the stop bits, has been sent + /// from the shift register. This bit is set as soon as the transmit FIFO becomes + /// non-empty, regardless of whether the UART is enabled or not. + BUSY: u1, + /// Receive FIFO empty. The meaning of this bit depends on the state of the FEN bit + /// in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the + /// receive holding register is empty. If the FIFO is enabled, the RXFE bit is set + /// when the receive FIFO is empty. + RXFE: u1, + /// Transmit FIFO full. The meaning of this bit depends on the state of the FEN bit + /// in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the + /// transmit holding register is full. If the FIFO is enabled, the TXFF bit is set + /// when the transmit FIFO is full. + TXFF: u1, + /// Receive FIFO full. The meaning of this bit depends on the state of the FEN bit + /// in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the + /// receive holding register is full. If the FIFO is enabled, the RXFF bit is set + /// when the receive FIFO is full. + RXFF: u1, + /// Transmit FIFO empty. The meaning of this bit depends on the state of the FEN bit + /// in the Line Control Register, UARTLCR_H. If the FIFO is disabled, this bit is + /// set when the transmit holding register is empty. If the FIFO is enabled, the + /// TXFE bit is set when the transmit FIFO is empty. This bit does not indicate if + /// there is data in the transmit shift register. + TXFE: u1, + /// Ring indicator. This bit is the complement of the UART ring indicator, nUARTRI, + /// modem status input. That is, the bit is 1 when nUARTRI is LOW. + RI: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + }), base_address + 0x18); + + /// address: 0x40034020 + /// IrDA Low-Power Counter Register, UARTILPR + pub const UARTILPR = @intToPtr(*volatile Mmio(32, packed struct { + /// 8-bit low-power divisor value. These bits are cleared to 0 at reset. + ILPDVSR: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x20); + + /// address: 0x40034024 + /// Integer Baud Rate Register, UARTIBRD + pub const UARTIBRD = @intToPtr(*volatile Mmio(32, packed struct { + /// The integer baud rate divisor. These bits are cleared to 0 on reset. + BAUD_DIVINT: u16, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + }), base_address + 0x24); + + /// address: 0x40034028 + /// Fractional Baud Rate Register, UARTFBRD + pub const UARTFBRD = @intToPtr(*volatile Mmio(32, packed struct { + /// The fractional baud rate divisor. These bits are cleared to 0 on reset. + BAUD_DIVFRAC: u6, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + }), base_address + 0x28); + + /// address: 0x4003402c + /// Line Control Register, UARTLCR_H + pub const UARTLCR_H = @intToPtr(*volatile Mmio(32, packed struct { + /// Send break. If this bit is set to 1, a low-level is continually output on the + /// UARTTXD output, after completing transmission of the current character. For the + /// proper execution of the break command, the software must set this bit for at + /// least two complete frames. For normal use, this bit must be cleared to 0. + BRK: u1, + /// Parity enable: 0 = parity is disabled and no parity bit added to the data frame + /// 1 = parity checking and generation is enabled. + PEN: u1, + /// Even parity select. Controls the type of parity the UART uses during + /// transmission and reception: 0 = odd parity. The UART generates or checks for an + /// odd number of 1s in the data and parity bits. 1 = even parity. The UART + /// generates or checks for an even number of 1s in the data and parity bits. This + /// bit has no effect when the PEN bit disables parity checking and generation. + EPS: u1, + /// Two stop bits select. If this bit is set to 1, two stop bits are transmitted at + /// the end of the frame. The receive logic does not check for two stop bits being + /// received. + STP2: u1, + /// Enable FIFOs: 0 = FIFOs are disabled (character mode) that is, the FIFOs become + /// 1-byte-deep holding registers 1 = transmit and receive FIFO buffers are enabled + /// (FIFO mode). + FEN: u1, + /// Word length. These bits indicate the number of data bits transmitted or received + /// in a frame as follows: b11 = 8 bits b10 = 7 bits b01 = 6 bits b00 = 5 bits. + WLEN: u2, + /// Stick parity select. 0 = stick parity is disabled 1 = either: * if the EPS bit + /// is 0 then the parity bit is transmitted and checked as a 1 * if the EPS bit is 1 + /// then the parity bit is transmitted and checked as a 0. This bit has no effect + /// when the PEN bit disables parity checking and generation. + SPS: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x2c); + + /// address: 0x40034030 + /// Control Register, UARTCR + pub const UARTCR = @intToPtr(*volatile Mmio(32, packed struct { + /// UART enable: 0 = UART is disabled. If the UART is disabled in the middle of + /// transmission or reception, it completes the current character before stopping. 1 + /// = the UART is enabled. Data transmission and reception occurs for either UART + /// signals or SIR signals depending on the setting of the SIREN bit. + UARTEN: u1, + /// SIR enable: 0 = IrDA SIR ENDEC is disabled. nSIROUT remains LOW (no light pulse + /// generated), and signal transitions on SIRIN have no effect. 1 = IrDA SIR ENDEC + /// is enabled. Data is transmitted and received on nSIROUT and SIRIN. UARTTXD + /// remains HIGH, in the marking state. Signal transitions on UARTRXD or modem + /// status inputs have no effect. This bit has no effect if the UARTEN bit disables + /// the UART. + SIREN: u1, + /// SIR low-power IrDA mode. This bit selects the IrDA encoding mode. If this bit is + /// cleared to 0, low-level bits are transmitted as an active high pulse with a + /// width of 3 / 16th of the bit period. If this bit is set to 1, low-level bits are + /// transmitted with a pulse width that is 3 times the period of the IrLPBaud16 + /// input signal, regardless of the selected bit rate. Setting this bit uses less + /// power, but might reduce transmission distances. + SIRLP: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + /// Loopback enable. If this bit is set to 1 and the SIREN bit is set to 1 and the + /// SIRTEST bit in the Test Control Register, UARTTCR is set to 1, then the nSIROUT + /// path is inverted, and fed through to the SIRIN path. The SIRTEST bit in the test + /// register must be set to 1 to override the normal half-duplex SIR operation. This + /// must be the requirement for accessing the test registers during normal + /// operation, and SIRTEST must be cleared to 0 when loopback testing is finished. + /// This feature reduces the amount of external coupling required during system + /// test. If this bit is set to 1, and the SIRTEST bit is set to 0, the UARTTXD path + /// is fed through to the UARTRXD path. In either SIR mode or UART mode, when this + /// bit is set, the modem outputs are also fed through to the modem inputs. This bit + /// is cleared to 0 on reset, to disable loopback. + LBE: u1, + /// Transmit enable. If this bit is set to 1, the transmit section of the UART is + /// enabled. Data transmission occurs for either UART signals, or SIR signals + /// depending on the setting of the SIREN bit. When the UART is disabled in the + /// middle of transmission, it completes the current character before stopping. + TXE: u1, + /// Receive enable. If this bit is set to 1, the receive section of the UART is + /// enabled. Data reception occurs for either UART signals or SIR signals depending + /// on the setting of the SIREN bit. When the UART is disabled in the middle of + /// reception, it completes the current character before stopping. + RXE: u1, + /// Data transmit ready. This bit is the complement of the UART data transmit ready, + /// nUARTDTR, modem status output. That is, when the bit is programmed to a 1 then + /// nUARTDTR is LOW. + DTR: u1, + /// Request to send. This bit is the complement of the UART request to send, + /// nUARTRTS, modem status output. That is, when the bit is programmed to a 1 then + /// nUARTRTS is LOW. + RTS: u1, + /// This bit is the complement of the UART Out1 (nUARTOut1) modem status output. + /// That is, when the bit is programmed to a 1 the output is 0. For DTE this can be + /// used as Data Carrier Detect (DCD). + OUT1: u1, + /// This bit is the complement of the UART Out2 (nUARTOut2) modem status output. + /// That is, when the bit is programmed to a 1, the output is 0. For DTE this can be + /// used as Ring Indicator (RI). + OUT2: u1, + /// RTS hardware flow control enable. If this bit is set to 1, RTS hardware flow + /// control is enabled. Data is only requested when there is space in the receive + /// FIFO for it to be received. + RTSEN: u1, + /// CTS hardware flow control enable. If this bit is set to 1, CTS hardware flow + /// control is enabled. Data is only transmitted when the nUARTCTS signal is + /// asserted. + CTSEN: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + }), base_address + 0x30); + + /// address: 0x40034034 + /// Interrupt FIFO Level Select Register, UARTIFLS + pub const UARTIFLS = @intToPtr(*volatile Mmio(32, packed struct { + /// Transmit interrupt FIFO level select. The trigger points for the transmit + /// interrupt are as follows: b000 = Transmit FIFO becomes <= 1 / 8 full b001 = + /// Transmit FIFO becomes <= 1 / 4 full b010 = Transmit FIFO becomes <= 1 / 2 full + /// b011 = Transmit FIFO becomes <= 3 / 4 full b100 = Transmit FIFO becomes <= 7 / 8 + /// full b101-b111 = reserved. + TXIFLSEL: u3, + /// Receive interrupt FIFO level select. The trigger points for the receive + /// interrupt are as follows: b000 = Receive FIFO becomes >= 1 / 8 full b001 = + /// Receive FIFO becomes >= 1 / 4 full b010 = Receive FIFO becomes >= 1 / 2 full + /// b011 = Receive FIFO becomes >= 3 / 4 full b100 = Receive FIFO becomes >= 7 / 8 + /// full b101-b111 = reserved. + RXIFLSEL: u3, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + }), base_address + 0x34); + + /// address: 0x40034038 + /// Interrupt Mask Set/Clear Register, UARTIMSC + pub const UARTIMSC = @intToPtr(*volatile Mmio(32, packed struct { + /// nUARTRI modem interrupt mask. A read returns the current mask for the UARTRIINTR + /// interrupt. On a write of 1, the mask of the UARTRIINTR interrupt is set. A write + /// of 0 clears the mask. + RIMIM: u1, + /// nUARTCTS modem interrupt mask. A read returns the current mask for the + /// UARTCTSINTR interrupt. On a write of 1, the mask of the UARTCTSINTR interrupt is + /// set. A write of 0 clears the mask. + CTSMIM: u1, + /// nUARTDCD modem interrupt mask. A read returns the current mask for the + /// UARTDCDINTR interrupt. On a write of 1, the mask of the UARTDCDINTR interrupt is + /// set. A write of 0 clears the mask. + DCDMIM: u1, + /// nUARTDSR modem interrupt mask. A read returns the current mask for the + /// UARTDSRINTR interrupt. On a write of 1, the mask of the UARTDSRINTR interrupt is + /// set. A write of 0 clears the mask. + DSRMIM: u1, + /// Receive interrupt mask. A read returns the current mask for the UARTRXINTR + /// interrupt. On a write of 1, the mask of the UARTRXINTR interrupt is set. A write + /// of 0 clears the mask. + RXIM: u1, + /// Transmit interrupt mask. A read returns the current mask for the UARTTXINTR + /// interrupt. On a write of 1, the mask of the UARTTXINTR interrupt is set. A write + /// of 0 clears the mask. + TXIM: u1, + /// Receive timeout interrupt mask. A read returns the current mask for the + /// UARTRTINTR interrupt. On a write of 1, the mask of the UARTRTINTR interrupt is + /// set. A write of 0 clears the mask. + RTIM: u1, + /// Framing error interrupt mask. A read returns the current mask for the UARTFEINTR + /// interrupt. On a write of 1, the mask of the UARTFEINTR interrupt is set. A write + /// of 0 clears the mask. + FEIM: u1, + /// Parity error interrupt mask. A read returns the current mask for the UARTPEINTR + /// interrupt. On a write of 1, the mask of the UARTPEINTR interrupt is set. A write + /// of 0 clears the mask. + PEIM: u1, + /// Break error interrupt mask. A read returns the current mask for the UARTBEINTR + /// interrupt. On a write of 1, the mask of the UARTBEINTR interrupt is set. A write + /// of 0 clears the mask. + BEIM: u1, + /// Overrun error interrupt mask. A read returns the current mask for the UARTOEINTR + /// interrupt. On a write of 1, the mask of the UARTOEINTR interrupt is set. A write + /// of 0 clears the mask. + OEIM: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + }), base_address + 0x38); + + /// address: 0x4003403c + /// Raw Interrupt Status Register, UARTRIS + pub const UARTRIS = @intToPtr(*volatile Mmio(32, packed struct { + /// nUARTRI modem interrupt status. Returns the raw interrupt state of the + /// UARTRIINTR interrupt. + RIRMIS: u1, + /// nUARTCTS modem interrupt status. Returns the raw interrupt state of the + /// UARTCTSINTR interrupt. + CTSRMIS: u1, + /// nUARTDCD modem interrupt status. Returns the raw interrupt state of the + /// UARTDCDINTR interrupt. + DCDRMIS: u1, + /// nUARTDSR modem interrupt status. Returns the raw interrupt state of the + /// UARTDSRINTR interrupt. + DSRRMIS: u1, + /// Receive interrupt status. Returns the raw interrupt state of the UARTRXINTR + /// interrupt. + RXRIS: u1, + /// Transmit interrupt status. Returns the raw interrupt state of the UARTTXINTR + /// interrupt. + TXRIS: u1, + /// Receive timeout interrupt status. Returns the raw interrupt state of the + /// UARTRTINTR interrupt. a + RTRIS: u1, + /// Framing error interrupt status. Returns the raw interrupt state of the + /// UARTFEINTR interrupt. + FERIS: u1, + /// Parity error interrupt status. Returns the raw interrupt state of the UARTPEINTR + /// interrupt. + PERIS: u1, + /// Break error interrupt status. Returns the raw interrupt state of the UARTBEINTR + /// interrupt. + BERIS: u1, + /// Overrun error interrupt status. Returns the raw interrupt state of the + /// UARTOEINTR interrupt. + OERIS: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + }), base_address + 0x3c); + + /// address: 0x40034040 + /// Masked Interrupt Status Register, UARTMIS + pub const UARTMIS = @intToPtr(*volatile Mmio(32, packed struct { + /// nUARTRI modem masked interrupt status. Returns the masked interrupt state of the + /// UARTRIINTR interrupt. + RIMMIS: u1, + /// nUARTCTS modem masked interrupt status. Returns the masked interrupt state of + /// the UARTCTSINTR interrupt. + CTSMMIS: u1, + /// nUARTDCD modem masked interrupt status. Returns the masked interrupt state of + /// the UARTDCDINTR interrupt. + DCDMMIS: u1, + /// nUARTDSR modem masked interrupt status. Returns the masked interrupt state of + /// the UARTDSRINTR interrupt. + DSRMMIS: u1, + /// Receive masked interrupt status. Returns the masked interrupt state of the + /// UARTRXINTR interrupt. + RXMIS: u1, + /// Transmit masked interrupt status. Returns the masked interrupt state of the + /// UARTTXINTR interrupt. + TXMIS: u1, + /// Receive timeout masked interrupt status. Returns the masked interrupt state of + /// the UARTRTINTR interrupt. + RTMIS: u1, + /// Framing error masked interrupt status. Returns the masked interrupt state of the + /// UARTFEINTR interrupt. + FEMIS: u1, + /// Parity error masked interrupt status. Returns the masked interrupt state of the + /// UARTPEINTR interrupt. + PEMIS: u1, + /// Break error masked interrupt status. Returns the masked interrupt state of the + /// UARTBEINTR interrupt. + BEMIS: u1, + /// Overrun error masked interrupt status. Returns the masked interrupt state of the + /// UARTOEINTR interrupt. + OEMIS: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + }), base_address + 0x40); + + /// address: 0x40034044 + /// Interrupt Clear Register, UARTICR + pub const UARTICR = @intToPtr(*volatile Mmio(32, packed struct { + /// nUARTRI modem interrupt clear. Clears the UARTRIINTR interrupt. + RIMIC: u1, + /// nUARTCTS modem interrupt clear. Clears the UARTCTSINTR interrupt. + CTSMIC: u1, + /// nUARTDCD modem interrupt clear. Clears the UARTDCDINTR interrupt. + DCDMIC: u1, + /// nUARTDSR modem interrupt clear. Clears the UARTDSRINTR interrupt. + DSRMIC: u1, + /// Receive interrupt clear. Clears the UARTRXINTR interrupt. + RXIC: u1, + /// Transmit interrupt clear. Clears the UARTTXINTR interrupt. + TXIC: u1, + /// Receive timeout interrupt clear. Clears the UARTRTINTR interrupt. + RTIC: u1, + /// Framing error interrupt clear. Clears the UARTFEINTR interrupt. + FEIC: u1, + /// Parity error interrupt clear. Clears the UARTPEINTR interrupt. + PEIC: u1, + /// Break error interrupt clear. Clears the UARTBEINTR interrupt. + BEIC: u1, + /// Overrun error interrupt clear. Clears the UARTOEINTR interrupt. + OEIC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + }), base_address + 0x44); + + /// address: 0x40034048 + /// DMA Control Register, UARTDMACR + pub const UARTDMACR = @intToPtr(*volatile Mmio(32, packed struct { + /// Receive DMA enable. If this bit is set to 1, DMA for the receive FIFO is + /// enabled. + RXDMAE: u1, + /// Transmit DMA enable. If this bit is set to 1, DMA for the transmit FIFO is + /// enabled. + TXDMAE: u1, + /// DMA on error. If this bit is set to 1, the DMA receive request outputs, + /// UARTRXDMASREQ or UARTRXDMABREQ, are disabled when the UART error interrupt is + /// asserted. + DMAONERR: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + }), base_address + 0x48); + + /// address: 0x40034fe0 + /// UARTPeriphID0 Register + pub const UARTPERIPHID0 = @intToPtr(*volatile Mmio(32, packed struct { + /// These bits read back as 0x11 + PARTNUMBER0: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0xfe0); + + /// address: 0x40034fe4 + /// UARTPeriphID1 Register + pub const UARTPERIPHID1 = @intToPtr(*volatile Mmio(32, packed struct { + /// These bits read back as 0x0 + PARTNUMBER1: u4, + /// These bits read back as 0x1 + DESIGNER0: u4, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0xfe4); + + /// address: 0x40034fe8 + /// UARTPeriphID2 Register + pub const UARTPERIPHID2 = @intToPtr(*volatile Mmio(32, packed struct { + /// These bits read back as 0x4 + DESIGNER1: u4, + /// This field depends on the revision of the UART: r1p0 0x0 r1p1 0x1 r1p3 0x2 r1p4 + /// 0x2 r1p5 0x3 + REVISION: u4, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0xfe8); + + /// address: 0x40034fec + /// UARTPeriphID3 Register + pub const UARTPERIPHID3 = @intToPtr(*volatile Mmio(32, packed struct { + /// These bits read back as 0x00 + CONFIGURATION: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0xfec); + + /// address: 0x40034ff0 + /// UARTPCellID0 Register + pub const UARTPCELLID0 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xff0); + + /// address: 0x40034ff4 + /// UARTPCellID1 Register + pub const UARTPCELLID1 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xff4); + + /// address: 0x40034ff8 + /// UARTPCellID2 Register + pub const UARTPCELLID2 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xff8); + + /// address: 0x40034ffc + /// UARTPCellID3 Register + pub const UARTPCELLID3 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xffc); + }; + pub const UART1 = struct { + pub const base_address = 0x40038000; + + /// address: 0x40038000 + /// Data Register, UARTDR + pub const UARTDR = @intToPtr(*volatile Mmio(32, packed struct { + /// Receive (read) data character. Transmit (write) data character. + DATA: u8, + /// Framing error. When set to 1, it indicates that the received character did not + /// have a valid stop bit (a valid stop bit is 1). In FIFO mode, this error is + /// associated with the character at the top of the FIFO. + FE: u1, + /// Parity error. When set to 1, it indicates that the parity of the received data + /// character does not match the parity that the EPS and SPS bits in the Line + /// Control Register, UARTLCR_H. In FIFO mode, this error is associated with the + /// character at the top of the FIFO. + PE: u1, + /// Break error. This bit is set to 1 if a break condition was detected, indicating + /// that the received data input was held LOW for longer than a full-word + /// transmission time (defined as start, data, parity and stop bits). In FIFO mode, + /// this error is associated with the character at the top of the FIFO. When a break + /// occurs, only one 0 character is loaded into the FIFO. The next character is only + /// enabled after the receive data input goes to a 1 (marking state), and the next + /// valid start bit is received. + BE: u1, + /// Overrun error. This bit is set to 1 if data is received and the receive FIFO is + /// already full. This is cleared to 0 once there is an empty space in the FIFO and + /// a new character can be written to it. + OE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x0); + + /// address: 0x40038004 + /// Receive Status Register/Error Clear Register, UARTRSR/UARTECR + pub const UARTRSR = @intToPtr(*volatile Mmio(32, packed struct { + /// Framing error. When set to 1, it indicates that the received character did not + /// have a valid stop bit (a valid stop bit is 1). This bit is cleared to 0 by a + /// write to UARTECR. In FIFO mode, this error is associated with the character at + /// the top of the FIFO. + FE: u1, + /// Parity error. When set to 1, it indicates that the parity of the received data + /// character does not match the parity that the EPS and SPS bits in the Line + /// Control Register, UARTLCR_H. This bit is cleared to 0 by a write to UARTECR. In + /// FIFO mode, this error is associated with the character at the top of the FIFO. + PE: u1, + /// Break error. This bit is set to 1 if a break condition was detected, indicating + /// that the received data input was held LOW for longer than a full-word + /// transmission time (defined as start, data, parity, and stop bits). This bit is + /// cleared to 0 after a write to UARTECR. In FIFO mode, this error is associated + /// with the character at the top of the FIFO. When a break occurs, only one 0 + /// character is loaded into the FIFO. The next character is only enabled after the + /// receive data input goes to a 1 (marking state) and the next valid start bit is + /// received. + BE: u1, + /// Overrun error. This bit is set to 1 if data is received and the FIFO is already + /// full. This bit is cleared to 0 by a write to UARTECR. The FIFO contents remain + /// valid because no more data is written when the FIFO is full, only the contents + /// of the shift register are overwritten. The CPU must now read the data, to empty + /// the FIFO. + OE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + }), base_address + 0x4); + + /// address: 0x40038018 + /// Flag Register, UARTFR + pub const UARTFR = @intToPtr(*volatile Mmio(32, packed struct { + /// Clear to send. This bit is the complement of the UART clear to send, nUARTCTS, + /// modem status input. That is, the bit is 1 when nUARTCTS is LOW. + CTS: u1, + /// Data set ready. This bit is the complement of the UART data set ready, nUARTDSR, + /// modem status input. That is, the bit is 1 when nUARTDSR is LOW. + DSR: u1, + /// Data carrier detect. This bit is the complement of the UART data carrier detect, + /// nUARTDCD, modem status input. That is, the bit is 1 when nUARTDCD is LOW. + DCD: u1, + /// UART busy. If this bit is set to 1, the UART is busy transmitting data. This bit + /// remains set until the complete byte, including all the stop bits, has been sent + /// from the shift register. This bit is set as soon as the transmit FIFO becomes + /// non-empty, regardless of whether the UART is enabled or not. + BUSY: u1, + /// Receive FIFO empty. The meaning of this bit depends on the state of the FEN bit + /// in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the + /// receive holding register is empty. If the FIFO is enabled, the RXFE bit is set + /// when the receive FIFO is empty. + RXFE: u1, + /// Transmit FIFO full. The meaning of this bit depends on the state of the FEN bit + /// in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the + /// transmit holding register is full. If the FIFO is enabled, the TXFF bit is set + /// when the transmit FIFO is full. + TXFF: u1, + /// Receive FIFO full. The meaning of this bit depends on the state of the FEN bit + /// in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the + /// receive holding register is full. If the FIFO is enabled, the RXFF bit is set + /// when the receive FIFO is full. + RXFF: u1, + /// Transmit FIFO empty. The meaning of this bit depends on the state of the FEN bit + /// in the Line Control Register, UARTLCR_H. If the FIFO is disabled, this bit is + /// set when the transmit holding register is empty. If the FIFO is enabled, the + /// TXFE bit is set when the transmit FIFO is empty. This bit does not indicate if + /// there is data in the transmit shift register. + TXFE: u1, + /// Ring indicator. This bit is the complement of the UART ring indicator, nUARTRI, + /// modem status input. That is, the bit is 1 when nUARTRI is LOW. + RI: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + }), base_address + 0x18); + + /// address: 0x40038020 + /// IrDA Low-Power Counter Register, UARTILPR + pub const UARTILPR = @intToPtr(*volatile Mmio(32, packed struct { + /// 8-bit low-power divisor value. These bits are cleared to 0 at reset. + ILPDVSR: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x20); + + /// address: 0x40038024 + /// Integer Baud Rate Register, UARTIBRD + pub const UARTIBRD = @intToPtr(*volatile Mmio(32, packed struct { + /// The integer baud rate divisor. These bits are cleared to 0 on reset. + BAUD_DIVINT: u16, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + }), base_address + 0x24); + + /// address: 0x40038028 + /// Fractional Baud Rate Register, UARTFBRD + pub const UARTFBRD = @intToPtr(*volatile Mmio(32, packed struct { + /// The fractional baud rate divisor. These bits are cleared to 0 on reset. + BAUD_DIVFRAC: u6, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + }), base_address + 0x28); + + /// address: 0x4003802c + /// Line Control Register, UARTLCR_H + pub const UARTLCR_H = @intToPtr(*volatile Mmio(32, packed struct { + /// Send break. If this bit is set to 1, a low-level is continually output on the + /// UARTTXD output, after completing transmission of the current character. For the + /// proper execution of the break command, the software must set this bit for at + /// least two complete frames. For normal use, this bit must be cleared to 0. + BRK: u1, + /// Parity enable: 0 = parity is disabled and no parity bit added to the data frame + /// 1 = parity checking and generation is enabled. + PEN: u1, + /// Even parity select. Controls the type of parity the UART uses during + /// transmission and reception: 0 = odd parity. The UART generates or checks for an + /// odd number of 1s in the data and parity bits. 1 = even parity. The UART + /// generates or checks for an even number of 1s in the data and parity bits. This + /// bit has no effect when the PEN bit disables parity checking and generation. + EPS: u1, + /// Two stop bits select. If this bit is set to 1, two stop bits are transmitted at + /// the end of the frame. The receive logic does not check for two stop bits being + /// received. + STP2: u1, + /// Enable FIFOs: 0 = FIFOs are disabled (character mode) that is, the FIFOs become + /// 1-byte-deep holding registers 1 = transmit and receive FIFO buffers are enabled + /// (FIFO mode). + FEN: u1, + /// Word length. These bits indicate the number of data bits transmitted or received + /// in a frame as follows: b11 = 8 bits b10 = 7 bits b01 = 6 bits b00 = 5 bits. + WLEN: u2, + /// Stick parity select. 0 = stick parity is disabled 1 = either: * if the EPS bit + /// is 0 then the parity bit is transmitted and checked as a 1 * if the EPS bit is 1 + /// then the parity bit is transmitted and checked as a 0. This bit has no effect + /// when the PEN bit disables parity checking and generation. + SPS: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x2c); + + /// address: 0x40038030 + /// Control Register, UARTCR + pub const UARTCR = @intToPtr(*volatile Mmio(32, packed struct { + /// UART enable: 0 = UART is disabled. If the UART is disabled in the middle of + /// transmission or reception, it completes the current character before stopping. 1 + /// = the UART is enabled. Data transmission and reception occurs for either UART + /// signals or SIR signals depending on the setting of the SIREN bit. + UARTEN: u1, + /// SIR enable: 0 = IrDA SIR ENDEC is disabled. nSIROUT remains LOW (no light pulse + /// generated), and signal transitions on SIRIN have no effect. 1 = IrDA SIR ENDEC + /// is enabled. Data is transmitted and received on nSIROUT and SIRIN. UARTTXD + /// remains HIGH, in the marking state. Signal transitions on UARTRXD or modem + /// status inputs have no effect. This bit has no effect if the UARTEN bit disables + /// the UART. + SIREN: u1, + /// SIR low-power IrDA mode. This bit selects the IrDA encoding mode. If this bit is + /// cleared to 0, low-level bits are transmitted as an active high pulse with a + /// width of 3 / 16th of the bit period. If this bit is set to 1, low-level bits are + /// transmitted with a pulse width that is 3 times the period of the IrLPBaud16 + /// input signal, regardless of the selected bit rate. Setting this bit uses less + /// power, but might reduce transmission distances. + SIRLP: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + /// Loopback enable. If this bit is set to 1 and the SIREN bit is set to 1 and the + /// SIRTEST bit in the Test Control Register, UARTTCR is set to 1, then the nSIROUT + /// path is inverted, and fed through to the SIRIN path. The SIRTEST bit in the test + /// register must be set to 1 to override the normal half-duplex SIR operation. This + /// must be the requirement for accessing the test registers during normal + /// operation, and SIRTEST must be cleared to 0 when loopback testing is finished. + /// This feature reduces the amount of external coupling required during system + /// test. If this bit is set to 1, and the SIRTEST bit is set to 0, the UARTTXD path + /// is fed through to the UARTRXD path. In either SIR mode or UART mode, when this + /// bit is set, the modem outputs are also fed through to the modem inputs. This bit + /// is cleared to 0 on reset, to disable loopback. + LBE: u1, + /// Transmit enable. If this bit is set to 1, the transmit section of the UART is + /// enabled. Data transmission occurs for either UART signals, or SIR signals + /// depending on the setting of the SIREN bit. When the UART is disabled in the + /// middle of transmission, it completes the current character before stopping. + TXE: u1, + /// Receive enable. If this bit is set to 1, the receive section of the UART is + /// enabled. Data reception occurs for either UART signals or SIR signals depending + /// on the setting of the SIREN bit. When the UART is disabled in the middle of + /// reception, it completes the current character before stopping. + RXE: u1, + /// Data transmit ready. This bit is the complement of the UART data transmit ready, + /// nUARTDTR, modem status output. That is, when the bit is programmed to a 1 then + /// nUARTDTR is LOW. + DTR: u1, + /// Request to send. This bit is the complement of the UART request to send, + /// nUARTRTS, modem status output. That is, when the bit is programmed to a 1 then + /// nUARTRTS is LOW. + RTS: u1, + /// This bit is the complement of the UART Out1 (nUARTOut1) modem status output. + /// That is, when the bit is programmed to a 1 the output is 0. For DTE this can be + /// used as Data Carrier Detect (DCD). + OUT1: u1, + /// This bit is the complement of the UART Out2 (nUARTOut2) modem status output. + /// That is, when the bit is programmed to a 1, the output is 0. For DTE this can be + /// used as Ring Indicator (RI). + OUT2: u1, + /// RTS hardware flow control enable. If this bit is set to 1, RTS hardware flow + /// control is enabled. Data is only requested when there is space in the receive + /// FIFO for it to be received. + RTSEN: u1, + /// CTS hardware flow control enable. If this bit is set to 1, CTS hardware flow + /// control is enabled. Data is only transmitted when the nUARTCTS signal is + /// asserted. + CTSEN: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + }), base_address + 0x30); + + /// address: 0x40038034 + /// Interrupt FIFO Level Select Register, UARTIFLS + pub const UARTIFLS = @intToPtr(*volatile Mmio(32, packed struct { + /// Transmit interrupt FIFO level select. The trigger points for the transmit + /// interrupt are as follows: b000 = Transmit FIFO becomes <= 1 / 8 full b001 = + /// Transmit FIFO becomes <= 1 / 4 full b010 = Transmit FIFO becomes <= 1 / 2 full + /// b011 = Transmit FIFO becomes <= 3 / 4 full b100 = Transmit FIFO becomes <= 7 / 8 + /// full b101-b111 = reserved. + TXIFLSEL: u3, + /// Receive interrupt FIFO level select. The trigger points for the receive + /// interrupt are as follows: b000 = Receive FIFO becomes >= 1 / 8 full b001 = + /// Receive FIFO becomes >= 1 / 4 full b010 = Receive FIFO becomes >= 1 / 2 full + /// b011 = Receive FIFO becomes >= 3 / 4 full b100 = Receive FIFO becomes >= 7 / 8 + /// full b101-b111 = reserved. + RXIFLSEL: u3, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + }), base_address + 0x34); + + /// address: 0x40038038 + /// Interrupt Mask Set/Clear Register, UARTIMSC + pub const UARTIMSC = @intToPtr(*volatile Mmio(32, packed struct { + /// nUARTRI modem interrupt mask. A read returns the current mask for the UARTRIINTR + /// interrupt. On a write of 1, the mask of the UARTRIINTR interrupt is set. A write + /// of 0 clears the mask. + RIMIM: u1, + /// nUARTCTS modem interrupt mask. A read returns the current mask for the + /// UARTCTSINTR interrupt. On a write of 1, the mask of the UARTCTSINTR interrupt is + /// set. A write of 0 clears the mask. + CTSMIM: u1, + /// nUARTDCD modem interrupt mask. A read returns the current mask for the + /// UARTDCDINTR interrupt. On a write of 1, the mask of the UARTDCDINTR interrupt is + /// set. A write of 0 clears the mask. + DCDMIM: u1, + /// nUARTDSR modem interrupt mask. A read returns the current mask for the + /// UARTDSRINTR interrupt. On a write of 1, the mask of the UARTDSRINTR interrupt is + /// set. A write of 0 clears the mask. + DSRMIM: u1, + /// Receive interrupt mask. A read returns the current mask for the UARTRXINTR + /// interrupt. On a write of 1, the mask of the UARTRXINTR interrupt is set. A write + /// of 0 clears the mask. + RXIM: u1, + /// Transmit interrupt mask. A read returns the current mask for the UARTTXINTR + /// interrupt. On a write of 1, the mask of the UARTTXINTR interrupt is set. A write + /// of 0 clears the mask. + TXIM: u1, + /// Receive timeout interrupt mask. A read returns the current mask for the + /// UARTRTINTR interrupt. On a write of 1, the mask of the UARTRTINTR interrupt is + /// set. A write of 0 clears the mask. + RTIM: u1, + /// Framing error interrupt mask. A read returns the current mask for the UARTFEINTR + /// interrupt. On a write of 1, the mask of the UARTFEINTR interrupt is set. A write + /// of 0 clears the mask. + FEIM: u1, + /// Parity error interrupt mask. A read returns the current mask for the UARTPEINTR + /// interrupt. On a write of 1, the mask of the UARTPEINTR interrupt is set. A write + /// of 0 clears the mask. + PEIM: u1, + /// Break error interrupt mask. A read returns the current mask for the UARTBEINTR + /// interrupt. On a write of 1, the mask of the UARTBEINTR interrupt is set. A write + /// of 0 clears the mask. + BEIM: u1, + /// Overrun error interrupt mask. A read returns the current mask for the UARTOEINTR + /// interrupt. On a write of 1, the mask of the UARTOEINTR interrupt is set. A write + /// of 0 clears the mask. + OEIM: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + }), base_address + 0x38); + + /// address: 0x4003803c + /// Raw Interrupt Status Register, UARTRIS + pub const UARTRIS = @intToPtr(*volatile Mmio(32, packed struct { + /// nUARTRI modem interrupt status. Returns the raw interrupt state of the + /// UARTRIINTR interrupt. + RIRMIS: u1, + /// nUARTCTS modem interrupt status. Returns the raw interrupt state of the + /// UARTCTSINTR interrupt. + CTSRMIS: u1, + /// nUARTDCD modem interrupt status. Returns the raw interrupt state of the + /// UARTDCDINTR interrupt. + DCDRMIS: u1, + /// nUARTDSR modem interrupt status. Returns the raw interrupt state of the + /// UARTDSRINTR interrupt. + DSRRMIS: u1, + /// Receive interrupt status. Returns the raw interrupt state of the UARTRXINTR + /// interrupt. + RXRIS: u1, + /// Transmit interrupt status. Returns the raw interrupt state of the UARTTXINTR + /// interrupt. + TXRIS: u1, + /// Receive timeout interrupt status. Returns the raw interrupt state of the + /// UARTRTINTR interrupt. a + RTRIS: u1, + /// Framing error interrupt status. Returns the raw interrupt state of the + /// UARTFEINTR interrupt. + FERIS: u1, + /// Parity error interrupt status. Returns the raw interrupt state of the UARTPEINTR + /// interrupt. + PERIS: u1, + /// Break error interrupt status. Returns the raw interrupt state of the UARTBEINTR + /// interrupt. + BERIS: u1, + /// Overrun error interrupt status. Returns the raw interrupt state of the + /// UARTOEINTR interrupt. + OERIS: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + }), base_address + 0x3c); + + /// address: 0x40038040 + /// Masked Interrupt Status Register, UARTMIS + pub const UARTMIS = @intToPtr(*volatile Mmio(32, packed struct { + /// nUARTRI modem masked interrupt status. Returns the masked interrupt state of the + /// UARTRIINTR interrupt. + RIMMIS: u1, + /// nUARTCTS modem masked interrupt status. Returns the masked interrupt state of + /// the UARTCTSINTR interrupt. + CTSMMIS: u1, + /// nUARTDCD modem masked interrupt status. Returns the masked interrupt state of + /// the UARTDCDINTR interrupt. + DCDMMIS: u1, + /// nUARTDSR modem masked interrupt status. Returns the masked interrupt state of + /// the UARTDSRINTR interrupt. + DSRMMIS: u1, + /// Receive masked interrupt status. Returns the masked interrupt state of the + /// UARTRXINTR interrupt. + RXMIS: u1, + /// Transmit masked interrupt status. Returns the masked interrupt state of the + /// UARTTXINTR interrupt. + TXMIS: u1, + /// Receive timeout masked interrupt status. Returns the masked interrupt state of + /// the UARTRTINTR interrupt. + RTMIS: u1, + /// Framing error masked interrupt status. Returns the masked interrupt state of the + /// UARTFEINTR interrupt. + FEMIS: u1, + /// Parity error masked interrupt status. Returns the masked interrupt state of the + /// UARTPEINTR interrupt. + PEMIS: u1, + /// Break error masked interrupt status. Returns the masked interrupt state of the + /// UARTBEINTR interrupt. + BEMIS: u1, + /// Overrun error masked interrupt status. Returns the masked interrupt state of the + /// UARTOEINTR interrupt. + OEMIS: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + }), base_address + 0x40); + + /// address: 0x40038044 + /// Interrupt Clear Register, UARTICR + pub const UARTICR = @intToPtr(*volatile Mmio(32, packed struct { + /// nUARTRI modem interrupt clear. Clears the UARTRIINTR interrupt. + RIMIC: u1, + /// nUARTCTS modem interrupt clear. Clears the UARTCTSINTR interrupt. + CTSMIC: u1, + /// nUARTDCD modem interrupt clear. Clears the UARTDCDINTR interrupt. + DCDMIC: u1, + /// nUARTDSR modem interrupt clear. Clears the UARTDSRINTR interrupt. + DSRMIC: u1, + /// Receive interrupt clear. Clears the UARTRXINTR interrupt. + RXIC: u1, + /// Transmit interrupt clear. Clears the UARTTXINTR interrupt. + TXIC: u1, + /// Receive timeout interrupt clear. Clears the UARTRTINTR interrupt. + RTIC: u1, + /// Framing error interrupt clear. Clears the UARTFEINTR interrupt. + FEIC: u1, + /// Parity error interrupt clear. Clears the UARTPEINTR interrupt. + PEIC: u1, + /// Break error interrupt clear. Clears the UARTBEINTR interrupt. + BEIC: u1, + /// Overrun error interrupt clear. Clears the UARTOEINTR interrupt. + OEIC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + }), base_address + 0x44); + + /// address: 0x40038048 + /// DMA Control Register, UARTDMACR + pub const UARTDMACR = @intToPtr(*volatile Mmio(32, packed struct { + /// Receive DMA enable. If this bit is set to 1, DMA for the receive FIFO is + /// enabled. + RXDMAE: u1, + /// Transmit DMA enable. If this bit is set to 1, DMA for the transmit FIFO is + /// enabled. + TXDMAE: u1, + /// DMA on error. If this bit is set to 1, the DMA receive request outputs, + /// UARTRXDMASREQ or UARTRXDMABREQ, are disabled when the UART error interrupt is + /// asserted. + DMAONERR: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + }), base_address + 0x48); + + /// address: 0x40038fe0 + /// UARTPeriphID0 Register + pub const UARTPERIPHID0 = @intToPtr(*volatile Mmio(32, packed struct { + /// These bits read back as 0x11 + PARTNUMBER0: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0xfe0); + + /// address: 0x40038fe4 + /// UARTPeriphID1 Register + pub const UARTPERIPHID1 = @intToPtr(*volatile Mmio(32, packed struct { + /// These bits read back as 0x0 + PARTNUMBER1: u4, + /// These bits read back as 0x1 + DESIGNER0: u4, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0xfe4); + + /// address: 0x40038fe8 + /// UARTPeriphID2 Register + pub const UARTPERIPHID2 = @intToPtr(*volatile Mmio(32, packed struct { + /// These bits read back as 0x4 + DESIGNER1: u4, + /// This field depends on the revision of the UART: r1p0 0x0 r1p1 0x1 r1p3 0x2 r1p4 + /// 0x2 r1p5 0x3 + REVISION: u4, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0xfe8); + + /// address: 0x40038fec + /// UARTPeriphID3 Register + pub const UARTPERIPHID3 = @intToPtr(*volatile Mmio(32, packed struct { + /// These bits read back as 0x00 + CONFIGURATION: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0xfec); + + /// address: 0x40038ff0 + /// UARTPCellID0 Register + pub const UARTPCELLID0 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xff0); + + /// address: 0x40038ff4 + /// UARTPCellID1 Register + pub const UARTPCELLID1 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xff4); + + /// address: 0x40038ff8 + /// UARTPCellID2 Register + pub const UARTPCELLID2 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xff8); + + /// address: 0x40038ffc + /// UARTPCellID3 Register + pub const UARTPCELLID3 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xffc); + }; + pub const SPI0 = struct { + pub const base_address = 0x4003c000; + pub const version = "1"; + + /// address: 0x4003c000 + /// Control register 0, SSPCR0 on page 3-4 + pub const SSPCR0 = @intToPtr(*volatile Mmio(32, packed struct { + /// Data Size Select: 0000 Reserved, undefined operation. 0001 Reserved, undefined + /// operation. 0010 Reserved, undefined operation. 0011 4-bit data. 0100 5-bit data. + /// 0101 6-bit data. 0110 7-bit data. 0111 8-bit data. 1000 9-bit data. 1001 10-bit + /// data. 1010 11-bit data. 1011 12-bit data. 1100 13-bit data. 1101 14-bit data. + /// 1110 15-bit data. 1111 16-bit data. + DSS: u4, + /// Frame format: 00 Motorola SPI frame format. 01 TI synchronous serial frame + /// format. 10 National Microwire frame format. 11 Reserved, undefined operation. + FRF: u2, + /// SSPCLKOUT polarity, applicable to Motorola SPI frame format only. See Motorola + /// SPI frame format on page 2-10. + SPO: u1, + /// SSPCLKOUT phase, applicable to Motorola SPI frame format only. See Motorola SPI + /// frame format on page 2-10. + SPH: u1, + /// Serial clock rate. The value SCR is used to generate the transmit and receive + /// bit rate of the PrimeCell SSP. The bit rate is: F SSPCLK CPSDVSR x (1+SCR) where + /// CPSDVSR is an even value from 2-254, programmed through the SSPCPSR register and + /// SCR is a value from 0-255. + SCR: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + }), base_address + 0x0); + + /// address: 0x4003c004 + /// Control register 1, SSPCR1 on page 3-5 + pub const SSPCR1 = @intToPtr(*volatile Mmio(32, packed struct { + /// Loop back mode: 0 Normal serial port operation enabled. 1 Output of transmit + /// serial shifter is connected to input of receive serial shifter internally. + LBM: u1, + /// Synchronous serial port enable: 0 SSP operation disabled. 1 SSP operation + /// enabled. + SSE: u1, + /// Master or slave mode select. This bit can be modified only when the PrimeCell + /// SSP is disabled, SSE=0: 0 Device configured as master, default. 1 Device + /// configured as slave. + MS: u1, + /// Slave-mode output disable. This bit is relevant only in the slave mode, MS=1. In + /// multiple-slave systems, it is possible for an PrimeCell SSP master to broadcast + /// a message to all slaves in the system while ensuring that only one slave drives + /// data onto its serial output line. In such systems the RXD lines from multiple + /// slaves could be tied together. To operate in such systems, the SOD bit can be + /// set if the PrimeCell SSP slave is not supposed to drive the SSPTXD line: 0 SSP + /// can drive the SSPTXD output in slave mode. 1 SSP must not drive the SSPTXD + /// output in slave mode. + SOD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + }), base_address + 0x4); + + /// address: 0x4003c008 + /// Data register, SSPDR on page 3-6 + pub const SSPDR = @intToPtr(*volatile Mmio(32, packed struct { + /// Transmit/Receive FIFO: Read Receive FIFO. Write Transmit FIFO. You must + /// right-justify data when the PrimeCell SSP is programmed for a data size that is + /// less than 16 bits. Unused bits at the top are ignored by transmit logic. The + /// receive logic automatically right-justifies. + DATA: u16, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + }), base_address + 0x8); + + /// address: 0x4003c00c + /// Status register, SSPSR on page 3-7 + pub const SSPSR = @intToPtr(*volatile Mmio(32, packed struct { + /// Transmit FIFO empty, RO: 0 Transmit FIFO is not empty. 1 Transmit FIFO is empty. + TFE: u1, + /// Transmit FIFO not full, RO: 0 Transmit FIFO is full. 1 Transmit FIFO is not + /// full. + TNF: u1, + /// Receive FIFO not empty, RO: 0 Receive FIFO is empty. 1 Receive FIFO is not + /// empty. + RNE: u1, + /// Receive FIFO full, RO: 0 Receive FIFO is not full. 1 Receive FIFO is full. + RFF: u1, + /// PrimeCell SSP busy flag, RO: 0 SSP is idle. 1 SSP is currently transmitting + /// and/or receiving a frame or the transmit FIFO is not empty. + BSY: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + }), base_address + 0xc); + + /// address: 0x4003c010 + /// Clock prescale register, SSPCPSR on page 3-8 + pub const SSPCPSR = @intToPtr(*volatile Mmio(32, packed struct { + /// Clock prescale divisor. Must be an even number from 2-254, depending on the + /// frequency of SSPCLK. The least significant bit always returns zero on reads. + CPSDVSR: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x10); + + /// address: 0x4003c014 + /// Interrupt mask set or clear register, SSPIMSC on page 3-9 + pub const SSPIMSC = @intToPtr(*volatile Mmio(32, packed struct { + /// Receive overrun interrupt mask: 0 Receive FIFO written to while full condition + /// interrupt is masked. 1 Receive FIFO written to while full condition interrupt is + /// not masked. + RORIM: u1, + /// Receive timeout interrupt mask: 0 Receive FIFO not empty and no read prior to + /// timeout period interrupt is masked. 1 Receive FIFO not empty and no read prior + /// to timeout period interrupt is not masked. + RTIM: u1, + /// Receive FIFO interrupt mask: 0 Receive FIFO half full or less condition + /// interrupt is masked. 1 Receive FIFO half full or less condition interrupt is not + /// masked. + RXIM: u1, + /// Transmit FIFO interrupt mask: 0 Transmit FIFO half empty or less condition + /// interrupt is masked. 1 Transmit FIFO half empty or less condition interrupt is + /// not masked. + TXIM: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + }), base_address + 0x14); + + /// address: 0x4003c018 + /// Raw interrupt status register, SSPRIS on page 3-10 + pub const SSPRIS = @intToPtr(*volatile Mmio(32, packed struct { + /// Gives the raw interrupt state, prior to masking, of the SSPRORINTR interrupt + RORRIS: u1, + /// Gives the raw interrupt state, prior to masking, of the SSPRTINTR interrupt + RTRIS: u1, + /// Gives the raw interrupt state, prior to masking, of the SSPRXINTR interrupt + RXRIS: u1, + /// Gives the raw interrupt state, prior to masking, of the SSPTXINTR interrupt + TXRIS: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + }), base_address + 0x18); + + /// address: 0x4003c01c + /// Masked interrupt status register, SSPMIS on page 3-11 + pub const SSPMIS = @intToPtr(*volatile Mmio(32, packed struct { + /// Gives the receive over run masked interrupt status, after masking, of the + /// SSPRORINTR interrupt + RORMIS: u1, + /// Gives the receive timeout masked interrupt state, after masking, of the + /// SSPRTINTR interrupt + RTMIS: u1, + /// Gives the receive FIFO masked interrupt state, after masking, of the SSPRXINTR + /// interrupt + RXMIS: u1, + /// Gives the transmit FIFO masked interrupt state, after masking, of the SSPTXINTR + /// interrupt + TXMIS: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + }), base_address + 0x1c); + + /// address: 0x4003c020 + /// Interrupt clear register, SSPICR on page 3-11 + pub const SSPICR = @intToPtr(*volatile Mmio(32, packed struct { + /// Clears the SSPRORINTR interrupt + RORIC: u1, + /// Clears the SSPRTINTR interrupt + RTIC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + }), base_address + 0x20); + + /// address: 0x4003c024 + /// DMA control register, SSPDMACR on page 3-12 + pub const SSPDMACR = @intToPtr(*volatile Mmio(32, packed struct { + /// Receive DMA Enable. If this bit is set to 1, DMA for the receive FIFO is + /// enabled. + RXDMAE: u1, + /// Transmit DMA Enable. If this bit is set to 1, DMA for the transmit FIFO is + /// enabled. + TXDMAE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + }), base_address + 0x24); + + /// address: 0x4003cfe0 + /// Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + pub const SSPPERIPHID0 = @intToPtr(*volatile Mmio(32, packed struct { + /// These bits read back as 0x22 + PARTNUMBER0: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0xfe0); + + /// address: 0x4003cfe4 + /// Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + pub const SSPPERIPHID1 = @intToPtr(*volatile Mmio(32, packed struct { + /// These bits read back as 0x0 + PARTNUMBER1: u4, + /// These bits read back as 0x1 + DESIGNER0: u4, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0xfe4); + + /// address: 0x4003cfe8 + /// Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + pub const SSPPERIPHID2 = @intToPtr(*volatile Mmio(32, packed struct { + /// These bits read back as 0x4 + DESIGNER1: u4, + /// These bits return the peripheral revision + REVISION: u4, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0xfe8); + + /// address: 0x4003cfec + /// Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + pub const SSPPERIPHID3 = @intToPtr(*volatile Mmio(32, packed struct { + /// These bits read back as 0x00 + CONFIGURATION: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0xfec); + + /// address: 0x4003cff0 + /// PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + pub const SSPPCELLID0 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xff0); + + /// address: 0x4003cff4 + /// PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + pub const SSPPCELLID1 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xff4); + + /// address: 0x4003cff8 + /// PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + pub const SSPPCELLID2 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xff8); + + /// address: 0x4003cffc + /// PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + pub const SSPPCELLID3 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xffc); + }; + pub const SPI1 = struct { + pub const base_address = 0x40040000; + + /// address: 0x40040000 + /// Control register 0, SSPCR0 on page 3-4 + pub const SSPCR0 = @intToPtr(*volatile Mmio(32, packed struct { + /// Data Size Select: 0000 Reserved, undefined operation. 0001 Reserved, undefined + /// operation. 0010 Reserved, undefined operation. 0011 4-bit data. 0100 5-bit data. + /// 0101 6-bit data. 0110 7-bit data. 0111 8-bit data. 1000 9-bit data. 1001 10-bit + /// data. 1010 11-bit data. 1011 12-bit data. 1100 13-bit data. 1101 14-bit data. + /// 1110 15-bit data. 1111 16-bit data. + DSS: u4, + /// Frame format: 00 Motorola SPI frame format. 01 TI synchronous serial frame + /// format. 10 National Microwire frame format. 11 Reserved, undefined operation. + FRF: u2, + /// SSPCLKOUT polarity, applicable to Motorola SPI frame format only. See Motorola + /// SPI frame format on page 2-10. + SPO: u1, + /// SSPCLKOUT phase, applicable to Motorola SPI frame format only. See Motorola SPI + /// frame format on page 2-10. + SPH: u1, + /// Serial clock rate. The value SCR is used to generate the transmit and receive + /// bit rate of the PrimeCell SSP. The bit rate is: F SSPCLK CPSDVSR x (1+SCR) where + /// CPSDVSR is an even value from 2-254, programmed through the SSPCPSR register and + /// SCR is a value from 0-255. + SCR: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + }), base_address + 0x0); + + /// address: 0x40040004 + /// Control register 1, SSPCR1 on page 3-5 + pub const SSPCR1 = @intToPtr(*volatile Mmio(32, packed struct { + /// Loop back mode: 0 Normal serial port operation enabled. 1 Output of transmit + /// serial shifter is connected to input of receive serial shifter internally. + LBM: u1, + /// Synchronous serial port enable: 0 SSP operation disabled. 1 SSP operation + /// enabled. + SSE: u1, + /// Master or slave mode select. This bit can be modified only when the PrimeCell + /// SSP is disabled, SSE=0: 0 Device configured as master, default. 1 Device + /// configured as slave. + MS: u1, + /// Slave-mode output disable. This bit is relevant only in the slave mode, MS=1. In + /// multiple-slave systems, it is possible for an PrimeCell SSP master to broadcast + /// a message to all slaves in the system while ensuring that only one slave drives + /// data onto its serial output line. In such systems the RXD lines from multiple + /// slaves could be tied together. To operate in such systems, the SOD bit can be + /// set if the PrimeCell SSP slave is not supposed to drive the SSPTXD line: 0 SSP + /// can drive the SSPTXD output in slave mode. 1 SSP must not drive the SSPTXD + /// output in slave mode. + SOD: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + }), base_address + 0x4); + + /// address: 0x40040008 + /// Data register, SSPDR on page 3-6 + pub const SSPDR = @intToPtr(*volatile Mmio(32, packed struct { + /// Transmit/Receive FIFO: Read Receive FIFO. Write Transmit FIFO. You must + /// right-justify data when the PrimeCell SSP is programmed for a data size that is + /// less than 16 bits. Unused bits at the top are ignored by transmit logic. The + /// receive logic automatically right-justifies. + DATA: u16, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + }), base_address + 0x8); + + /// address: 0x4004000c + /// Status register, SSPSR on page 3-7 + pub const SSPSR = @intToPtr(*volatile Mmio(32, packed struct { + /// Transmit FIFO empty, RO: 0 Transmit FIFO is not empty. 1 Transmit FIFO is empty. + TFE: u1, + /// Transmit FIFO not full, RO: 0 Transmit FIFO is full. 1 Transmit FIFO is not + /// full. + TNF: u1, + /// Receive FIFO not empty, RO: 0 Receive FIFO is empty. 1 Receive FIFO is not + /// empty. + RNE: u1, + /// Receive FIFO full, RO: 0 Receive FIFO is not full. 1 Receive FIFO is full. + RFF: u1, + /// PrimeCell SSP busy flag, RO: 0 SSP is idle. 1 SSP is currently transmitting + /// and/or receiving a frame or the transmit FIFO is not empty. + BSY: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + }), base_address + 0xc); + + /// address: 0x40040010 + /// Clock prescale register, SSPCPSR on page 3-8 + pub const SSPCPSR = @intToPtr(*volatile Mmio(32, packed struct { + /// Clock prescale divisor. Must be an even number from 2-254, depending on the + /// frequency of SSPCLK. The least significant bit always returns zero on reads. + CPSDVSR: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x10); + + /// address: 0x40040014 + /// Interrupt mask set or clear register, SSPIMSC on page 3-9 + pub const SSPIMSC = @intToPtr(*volatile Mmio(32, packed struct { + /// Receive overrun interrupt mask: 0 Receive FIFO written to while full condition + /// interrupt is masked. 1 Receive FIFO written to while full condition interrupt is + /// not masked. + RORIM: u1, + /// Receive timeout interrupt mask: 0 Receive FIFO not empty and no read prior to + /// timeout period interrupt is masked. 1 Receive FIFO not empty and no read prior + /// to timeout period interrupt is not masked. + RTIM: u1, + /// Receive FIFO interrupt mask: 0 Receive FIFO half full or less condition + /// interrupt is masked. 1 Receive FIFO half full or less condition interrupt is not + /// masked. + RXIM: u1, + /// Transmit FIFO interrupt mask: 0 Transmit FIFO half empty or less condition + /// interrupt is masked. 1 Transmit FIFO half empty or less condition interrupt is + /// not masked. + TXIM: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + }), base_address + 0x14); + + /// address: 0x40040018 + /// Raw interrupt status register, SSPRIS on page 3-10 + pub const SSPRIS = @intToPtr(*volatile Mmio(32, packed struct { + /// Gives the raw interrupt state, prior to masking, of the SSPRORINTR interrupt + RORRIS: u1, + /// Gives the raw interrupt state, prior to masking, of the SSPRTINTR interrupt + RTRIS: u1, + /// Gives the raw interrupt state, prior to masking, of the SSPRXINTR interrupt + RXRIS: u1, + /// Gives the raw interrupt state, prior to masking, of the SSPTXINTR interrupt + TXRIS: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + }), base_address + 0x18); + + /// address: 0x4004001c + /// Masked interrupt status register, SSPMIS on page 3-11 + pub const SSPMIS = @intToPtr(*volatile Mmio(32, packed struct { + /// Gives the receive over run masked interrupt status, after masking, of the + /// SSPRORINTR interrupt + RORMIS: u1, + /// Gives the receive timeout masked interrupt state, after masking, of the + /// SSPRTINTR interrupt + RTMIS: u1, + /// Gives the receive FIFO masked interrupt state, after masking, of the SSPRXINTR + /// interrupt + RXMIS: u1, + /// Gives the transmit FIFO masked interrupt state, after masking, of the SSPTXINTR + /// interrupt + TXMIS: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + }), base_address + 0x1c); + + /// address: 0x40040020 + /// Interrupt clear register, SSPICR on page 3-11 + pub const SSPICR = @intToPtr(*volatile Mmio(32, packed struct { + /// Clears the SSPRORINTR interrupt + RORIC: u1, + /// Clears the SSPRTINTR interrupt + RTIC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + }), base_address + 0x20); + + /// address: 0x40040024 + /// DMA control register, SSPDMACR on page 3-12 + pub const SSPDMACR = @intToPtr(*volatile Mmio(32, packed struct { + /// Receive DMA Enable. If this bit is set to 1, DMA for the receive FIFO is + /// enabled. + RXDMAE: u1, + /// Transmit DMA Enable. If this bit is set to 1, DMA for the transmit FIFO is + /// enabled. + TXDMAE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + }), base_address + 0x24); + + /// address: 0x40040fe0 + /// Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + pub const SSPPERIPHID0 = @intToPtr(*volatile Mmio(32, packed struct { + /// These bits read back as 0x22 + PARTNUMBER0: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0xfe0); + + /// address: 0x40040fe4 + /// Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + pub const SSPPERIPHID1 = @intToPtr(*volatile Mmio(32, packed struct { + /// These bits read back as 0x0 + PARTNUMBER1: u4, + /// These bits read back as 0x1 + DESIGNER0: u4, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0xfe4); + + /// address: 0x40040fe8 + /// Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + pub const SSPPERIPHID2 = @intToPtr(*volatile Mmio(32, packed struct { + /// These bits read back as 0x4 + DESIGNER1: u4, + /// These bits return the peripheral revision + REVISION: u4, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0xfe8); + + /// address: 0x40040fec + /// Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + pub const SSPPERIPHID3 = @intToPtr(*volatile Mmio(32, packed struct { + /// These bits read back as 0x00 + CONFIGURATION: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0xfec); + + /// address: 0x40040ff0 + /// PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + pub const SSPPCELLID0 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xff0); + + /// address: 0x40040ff4 + /// PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + pub const SSPPCELLID1 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xff4); + + /// address: 0x40040ff8 + /// PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + pub const SSPPCELLID2 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xff8); + + /// address: 0x40040ffc + /// PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + pub const SSPPCELLID3 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xffc); + }; + + /// DW_apb_i2c address block\n\n + /// List of configuration constants for the Synopsys I2C hardware (you may see + /// references to these in I2C register header; these are *fixed* values, set at + /// hardware design time):\n\n + /// IC_ULTRA_FAST_MODE ................ 0x0\n + /// IC_UFM_TBUF_CNT_DEFAULT ........... 0x8\n + /// IC_UFM_SCL_LOW_COUNT .............. 0x0008\n + /// IC_UFM_SCL_HIGH_COUNT ............. 0x0006\n + /// IC_TX_TL .......................... 0x0\n + /// IC_TX_CMD_BLOCK ................... 0x1\n + /// IC_HAS_DMA ........................ 0x1\n + /// IC_HAS_ASYNC_FIFO ................. 0x0\n + /// IC_SMBUS_ARP ...................... 0x0\n + /// IC_FIRST_DATA_BYTE_STATUS ......... 0x1\n + /// IC_INTR_IO ........................ 0x1\n + /// IC_MASTER_MODE .................... 0x1\n + /// IC_DEFAULT_ACK_GENERAL_CALL ....... 0x1\n + /// IC_INTR_POL ....................... 0x1\n + /// IC_OPTIONAL_SAR ................... 0x0\n + /// IC_DEFAULT_TAR_SLAVE_ADDR ......... 0x055\n + /// IC_DEFAULT_SLAVE_ADDR ............. 0x055\n + /// IC_DEFAULT_HS_SPKLEN .............. 0x1\n + /// IC_FS_SCL_HIGH_COUNT .............. 0x0006\n + /// IC_HS_SCL_LOW_COUNT ............... 0x0008\n + /// IC_DEVICE_ID_VALUE ................ 0x0\n + /// IC_10BITADDR_MASTER ............... 0x0\n + /// IC_CLK_FREQ_OPTIMIZATION .......... 0x0\n + /// IC_DEFAULT_FS_SPKLEN .............. 0x7\n + /// IC_ADD_ENCODED_PARAMS ............. 0x0\n + /// IC_DEFAULT_SDA_HOLD ............... 0x000001\n + /// IC_DEFAULT_SDA_SETUP .............. 0x64\n + /// IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT . 0x0\n + /// IC_CLOCK_PERIOD ................... 100\n + /// IC_EMPTYFIFO_HOLD_MASTER_EN ....... 1\n + /// IC_RESTART_EN ..................... 0x1\n + /// IC_TX_CMD_BLOCK_DEFAULT ........... 0x0\n + /// IC_BUS_CLEAR_FEATURE .............. 0x0\n + /// IC_CAP_LOADING .................... 100\n + /// IC_FS_SCL_LOW_COUNT ............... 0x000d\n + /// APB_DATA_WIDTH .................... 32\n + /// IC_SDA_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff\n + /// IC_SLV_DATA_NACK_ONLY ............. 0x1\n + /// IC_10BITADDR_SLAVE ................ 0x0\n + /// IC_CLK_TYPE ....................... 0x0\n + /// IC_SMBUS_UDID_MSB ................. 0x0\n + /// IC_SMBUS_SUSPEND_ALERT ............ 0x0\n + /// IC_HS_SCL_HIGH_COUNT .............. 0x0006\n + /// IC_SLV_RESTART_DET_EN ............. 0x1\n + /// IC_SMBUS .......................... 0x0\n + /// IC_OPTIONAL_SAR_DEFAULT ........... 0x0\n + /// IC_PERSISTANT_SLV_ADDR_DEFAULT .... 0x0\n + /// IC_USE_COUNTS ..................... 0x0\n + /// IC_RX_BUFFER_DEPTH ................ 16\n + /// IC_SCL_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff\n + /// IC_RX_FULL_HLD_BUS_EN ............. 0x1\n + /// IC_SLAVE_DISABLE .................. 0x1\n + /// IC_RX_TL .......................... 0x0\n + /// IC_DEVICE_ID ...................... 0x0\n + /// IC_HC_COUNT_VALUES ................ 0x0\n + /// I2C_DYNAMIC_TAR_UPDATE ............ 0\n + /// IC_SMBUS_CLK_LOW_MEXT_DEFAULT ..... 0xffffffff\n + /// IC_SMBUS_CLK_LOW_SEXT_DEFAULT ..... 0xffffffff\n + /// IC_HS_MASTER_CODE ................. 0x1\n + /// IC_SMBUS_RST_IDLE_CNT_DEFAULT ..... 0xffff\n + /// IC_SMBUS_UDID_LSB_DEFAULT ......... 0xffffffff\n + /// IC_SS_SCL_HIGH_COUNT .............. 0x0028\n + /// IC_SS_SCL_LOW_COUNT ............... 0x002f\n + /// IC_MAX_SPEED_MODE ................. 0x2\n + /// IC_STAT_FOR_CLK_STRETCH ........... 0x0\n + /// IC_STOP_DET_IF_MASTER_ACTIVE ...... 0x0\n + /// IC_DEFAULT_UFM_SPKLEN ............. 0x1\n + /// IC_TX_BUFFER_DEPTH ................ 16 + pub const I2C0 = struct { + pub const base_address = 0x40044000; + pub const version = "1"; + + /// address: 0x40044000 + /// I2C Control Register. This register can be written only when the DW_apb_i2c is + /// disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes + /// at other times have no effect.\n\n + /// Read/Write Access: - bit 10 is read only. - bit 11 is read only - bit 16 is read + /// only - bit 17 is read only - bits 18 and 19 are read only. + pub const IC_CON = @intToPtr(*volatile Mmio(32, packed struct { + /// This bit controls whether the DW_apb_i2c master is enabled.\n\n + /// NOTE: Software should ensure that if this bit is written with '1' then bit 6 + /// should also be written with a '1'. + MASTER_MODE: u1, + /// These bits control at which speed the DW_apb_i2c operates; its setting is + /// relevant only if one is operating the DW_apb_i2c in master mode. Hardware + /// protects against illegal values being programmed by software. These bits must be + /// programmed appropriately for slave mode also, as it is used to capture correct + /// value of spike filter as per the speed mode.\n\n + /// This register should be programmed only with a value in the range of 1 to + /// IC_MAX_SPEED_MODE; otherwise, hardware updates this register with the value of + /// IC_MAX_SPEED_MODE.\n\n + /// 1: standard mode (100 kbit/s)\n\n + /// 2: fast mode (<=400 kbit/s) or fast mode plus (<=1000Kbit/s)\n\n + /// 3: high speed mode (3.4 Mbit/s)\n\n + /// Note: This field is not applicable when IC_ULTRA_FAST_MODE=1 + SPEED: u2, + /// When acting as a slave, this bit controls whether the DW_apb_i2c responds to 7- + /// or 10-bit addresses. - 0: 7-bit addressing. The DW_apb_i2c ignores transactions + /// that involve 10-bit addressing; for 7-bit addressing, only the lower 7 bits of + /// the IC_SAR register are compared. - 1: 10-bit addressing. The DW_apb_i2c + /// responds to only 10-bit addressing transfers that match the full 10 bits of the + /// IC_SAR register. + IC_10BITADDR_SLAVE: u1, + /// Controls whether the DW_apb_i2c starts its transfers in 7- or 10-bit addressing + /// mode when acting as a master. - 0: 7-bit addressing - 1: 10-bit addressing + IC_10BITADDR_MASTER: u1, + /// Determines whether RESTART conditions may be sent when acting as a master. Some + /// older slaves do not support handling RESTART conditions; however, RESTART + /// conditions are used in several DW_apb_i2c operations. When RESTART is disabled, + /// the master is prohibited from performing the following functions: - Sending a + /// START BYTE - Performing any high-speed mode operation - High-speed mode + /// operation - Performing direction changes in combined format mode - Performing a + /// read operation with a 10-bit address By replacing RESTART condition followed by + /// a STOP and a subsequent START condition, split operations are broken down into + /// multiple DW_apb_i2c transfers. If the above operations are performed, it will + /// result in setting bit 6 (TX_ABRT) of the IC_RAW_INTR_STAT register.\n\n + /// Reset value: ENABLED + IC_RESTART_EN: u1, + /// This bit controls whether I2C has its slave disabled, which means once the + /// presetn signal is applied, then this bit is set and the slave is disabled.\n\n + /// If this bit is set (slave is disabled), DW_apb_i2c functions only as a master + /// and does not perform any action that requires a slave.\n\n + /// NOTE: Software should ensure that if this bit is written with 0, then bit 0 + /// should also be written with a 0. + IC_SLAVE_DISABLE: u1, + /// In slave mode: - 1'b1: issues the STOP_DET interrupt only when it is addressed. + /// - 1'b0: issues the STOP_DET irrespective of whether it's addressed or not. Reset + /// value: 0x0\n\n + /// NOTE: During a general call address, this slave does not issue the STOP_DET + /// interrupt if STOP_DET_IF_ADDRESSED = 1'b1, even if the slave responds to the + /// general call address by generating ACK. The STOP_DET interrupt is generated only + /// when the transmitted address matches the slave address (SAR). + STOP_DET_IFADDRESSED: u1, + /// This bit controls the generation of the TX_EMPTY interrupt, as described in the + /// IC_RAW_INTR_STAT register.\n\n + /// Reset value: 0x0. + TX_EMPTY_CTRL: u1, + /// This bit controls whether DW_apb_i2c should hold the bus when the Rx FIFO is + /// physically full to its RX_BUFFER_DEPTH, as described in the + /// IC_RX_FULL_HLD_BUS_EN parameter.\n\n + /// Reset value: 0x0. + RX_FIFO_FULL_HLD_CTRL: u1, + /// Master issues the STOP_DET interrupt irrespective of whether master is active or + /// not + STOP_DET_IF_MASTER_ACTIVE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + }), base_address + 0x0); + + /// address: 0x40044004 + /// I2C Target Address Register\n\n + /// This register is 12 bits wide, and bits 31:12 are reserved. This register can be + /// written to only when IC_ENABLE[0] is set to 0.\n\n + /// Note: If the software or application is aware that the DW_apb_i2c is not using + /// the TAR address for the pending commands in the Tx FIFO, then it is possible to + /// update the TAR address even while the Tx FIFO has entries (IC_STATUS[2]= 0). - + /// It is not necessary to perform any write to this register if DW_apb_i2c is + /// enabled as an I2C slave only. + pub const IC_TAR = @intToPtr(*volatile Mmio(32, packed struct { + /// This is the target address for any master transaction. When transmitting a + /// General Call, these bits are ignored. To generate a START BYTE, the CPU needs to + /// write only once into these bits.\n\n + /// If the IC_TAR and IC_SAR are the same, loopback exists but the FIFOs are shared + /// between master and slave, so full loopback is not feasible. Only one direction + /// loopback mode is supported (simplex), not duplex. A master cannot transmit to + /// itself; it can transmit to only a slave. + IC_TAR: u10, + /// If bit 11 (SPECIAL) is set to 1 and bit 13(Device-ID) is set to 0, then this bit + /// indicates whether a General Call or START byte command is to be performed by the + /// DW_apb_i2c. - 0: General Call Address - after issuing a General Call, only + /// writes may be performed. Attempting to issue a read command results in setting + /// bit 6 (TX_ABRT) of the IC_RAW_INTR_STAT register. The DW_apb_i2c remains in + /// General Call mode until the SPECIAL bit value (bit 11) is cleared. - 1: START + /// BYTE Reset value: 0x0 + GC_OR_START: u1, + /// This bit indicates whether software performs a Device-ID or General Call or + /// START BYTE command. - 0: ignore bit 10 GC_OR_START and use IC_TAR normally - 1: + /// perform special I2C command as specified in Device_ID or GC_OR_START bit Reset + /// value: 0x0 + SPECIAL: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x4); + + /// address: 0x40044008 + /// I2C Slave Address Register + pub const IC_SAR = @intToPtr(*volatile MmioInt(32, u10), base_address + 0x8); + + /// address: 0x40044010 + /// I2C Rx/Tx Data Buffer and Command Register; this is the register the CPU writes + /// to when filling the TX FIFO and the CPU reads from when retrieving bytes from RX + /// FIFO.\n\n + /// The size of the register changes as follows:\n\n + /// Write: - 11 bits when IC_EMPTYFIFO_HOLD_MASTER_EN=1 - 9 bits when + /// IC_EMPTYFIFO_HOLD_MASTER_EN=0 Read: - 12 bits when IC_FIRST_DATA_BYTE_STATUS = 1 + /// - 8 bits when IC_FIRST_DATA_BYTE_STATUS = 0 Note: In order for the DW_apb_i2c to + /// continue acknowledging reads, a read command should be written for every byte + /// that is to be received; otherwise the DW_apb_i2c will stop acknowledging. + pub const IC_DATA_CMD = @intToPtr(*volatile Mmio(32, packed struct { + /// This register contains the data to be transmitted or received on the I2C bus. If + /// you are writing to this register and want to perform a read, bits 7:0 (DAT) are + /// ignored by the DW_apb_i2c. However, when you read this register, these bits + /// return the value of data received on the DW_apb_i2c interface.\n\n + /// Reset value: 0x0 + DAT: u8, + /// This bit controls whether a read or a write is performed. This bit does not + /// control the direction when the DW_apb_i2con acts as a slave. It controls only + /// the direction when it acts as a master.\n\n + /// When a command is entered in the TX FIFO, this bit distinguishes the write and + /// read commands. In slave-receiver mode, this bit is a 'don't care' because writes + /// to this register are not required. In slave-transmitter mode, a '0' indicates + /// that the data in IC_DATA_CMD is to be transmitted.\n\n + /// When programming this bit, you should remember the following: attempting to + /// perform a read operation after a General Call command has been sent results in a + /// TX_ABRT interrupt (bit 6 of the IC_RAW_INTR_STAT register), unless bit 11 + /// (SPECIAL) in the IC_TAR register has been cleared. If a '1' is written to this + /// bit after receiving a RD_REQ interrupt, then a TX_ABRT interrupt occurs.\n\n + /// Reset value: 0x0 + CMD: u1, + /// This bit controls whether a STOP is issued after the byte is sent or + /// received.\n\n + /// - 1 - STOP is issued after this byte, regardless of whether or not the Tx FIFO + /// is empty. If the Tx FIFO is not empty, the master immediately tries to start a + /// new transfer by issuing a START and arbitrating for the bus. - 0 - STOP is not + /// issued after this byte, regardless of whether or not the Tx FIFO is empty. If + /// the Tx FIFO is not empty, the master continues the current transfer by + /// sending/receiving data bytes according to the value of the CMD bit. If the Tx + /// FIFO is empty, the master holds the SCL line low and stalls the bus until a new + /// command is available in the Tx FIFO. Reset value: 0x0 + STOP: u1, + /// This bit controls whether a RESTART is issued before the byte is sent or + /// received.\n\n + /// 1 - If IC_RESTART_EN is 1, a RESTART is issued before the data is sent/received + /// (according to the value of CMD), regardless of whether or not the transfer + /// direction is changing from the previous command; if IC_RESTART_EN is 0, a STOP + /// followed by a START is issued instead.\n\n + /// 0 - If IC_RESTART_EN is 1, a RESTART is issued only if the transfer direction is + /// changing from the previous command; if IC_RESTART_EN is 0, a STOP followed by a + /// START is issued instead.\n\n + /// Reset value: 0x0 + RESTART: u1, + /// Indicates the first data byte received after the address phase for receive + /// transfer in Master receiver or Slave receiver mode.\n\n + /// Reset value : 0x0\n\n + /// NOTE: In case of APB_DATA_WIDTH=8,\n\n + /// 1. The user has to perform two APB Reads to IC_DATA_CMD in order to get status + /// on 11 bit.\n\n + /// 2. In order to read the 11 bit, the user has to perform the first data byte read + /// [7:0] (offset 0x10) and then perform the second read [15:8] (offset 0x11) in + /// order to know the status of 11 bit (whether the data received in previous read + /// is a first data byte or not).\n\n + /// 3. The 11th bit is an optional read field, user can ignore 2nd byte read [15:8] + /// (offset 0x11) if not interested in FIRST_DATA_BYTE status. + FIRST_DATA_BYTE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x10); + + /// address: 0x40044014 + /// Standard Speed I2C Clock SCL High Count Register + pub const IC_SS_SCL_HCNT = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x14); + + /// address: 0x40044018 + /// Standard Speed I2C Clock SCL Low Count Register + pub const IC_SS_SCL_LCNT = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x18); + + /// address: 0x4004401c + /// Fast Mode or Fast Mode Plus I2C Clock SCL High Count Register + pub const IC_FS_SCL_HCNT = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x1c); + + /// address: 0x40044020 + /// Fast Mode or Fast Mode Plus I2C Clock SCL Low Count Register + pub const IC_FS_SCL_LCNT = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x20); + + /// address: 0x4004402c + /// I2C Interrupt Status Register\n\n + /// Each bit in this register has a corresponding mask bit in the IC_INTR_MASK + /// register. These bits are cleared by reading the matching interrupt clear + /// register. The unmasked raw versions of these bits are available in the + /// IC_RAW_INTR_STAT register. + pub const IC_INTR_STAT = @intToPtr(*volatile Mmio(32, packed struct { + /// See IC_RAW_INTR_STAT for a detailed description of R_RX_UNDER bit.\n\n + /// Reset value: 0x0 + R_RX_UNDER: u1, + /// See IC_RAW_INTR_STAT for a detailed description of R_RX_OVER bit.\n\n + /// Reset value: 0x0 + R_RX_OVER: u1, + /// See IC_RAW_INTR_STAT for a detailed description of R_RX_FULL bit.\n\n + /// Reset value: 0x0 + R_RX_FULL: u1, + /// See IC_RAW_INTR_STAT for a detailed description of R_TX_OVER bit.\n\n + /// Reset value: 0x0 + R_TX_OVER: u1, + /// See IC_RAW_INTR_STAT for a detailed description of R_TX_EMPTY bit.\n\n + /// Reset value: 0x0 + R_TX_EMPTY: u1, + /// See IC_RAW_INTR_STAT for a detailed description of R_RD_REQ bit.\n\n + /// Reset value: 0x0 + R_RD_REQ: u1, + /// See IC_RAW_INTR_STAT for a detailed description of R_TX_ABRT bit.\n\n + /// Reset value: 0x0 + R_TX_ABRT: u1, + /// See IC_RAW_INTR_STAT for a detailed description of R_RX_DONE bit.\n\n + /// Reset value: 0x0 + R_RX_DONE: u1, + /// See IC_RAW_INTR_STAT for a detailed description of R_ACTIVITY bit.\n\n + /// Reset value: 0x0 + R_ACTIVITY: u1, + /// See IC_RAW_INTR_STAT for a detailed description of R_STOP_DET bit.\n\n + /// Reset value: 0x0 + R_STOP_DET: u1, + /// See IC_RAW_INTR_STAT for a detailed description of R_START_DET bit.\n\n + /// Reset value: 0x0 + R_START_DET: u1, + /// See IC_RAW_INTR_STAT for a detailed description of R_GEN_CALL bit.\n\n + /// Reset value: 0x0 + R_GEN_CALL: u1, + /// See IC_RAW_INTR_STAT for a detailed description of R_RESTART_DET bit.\n\n + /// Reset value: 0x0 + R_RESTART_DET: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + }), base_address + 0x2c); + + /// address: 0x40044030 + /// I2C Interrupt Mask Register.\n\n + /// These bits mask their corresponding interrupt status bits. This register is + /// active low; a value of 0 masks the interrupt, whereas a value of 1 unmasks the + /// interrupt. + pub const IC_INTR_MASK = @intToPtr(*volatile Mmio(32, packed struct { + /// This bit masks the R_RX_UNDER interrupt in IC_INTR_STAT register.\n\n + /// Reset value: 0x1 + M_RX_UNDER: u1, + /// This bit masks the R_RX_OVER interrupt in IC_INTR_STAT register.\n\n + /// Reset value: 0x1 + M_RX_OVER: u1, + /// This bit masks the R_RX_FULL interrupt in IC_INTR_STAT register.\n\n + /// Reset value: 0x1 + M_RX_FULL: u1, + /// This bit masks the R_TX_OVER interrupt in IC_INTR_STAT register.\n\n + /// Reset value: 0x1 + M_TX_OVER: u1, + /// This bit masks the R_TX_EMPTY interrupt in IC_INTR_STAT register.\n\n + /// Reset value: 0x1 + M_TX_EMPTY: u1, + /// This bit masks the R_RD_REQ interrupt in IC_INTR_STAT register.\n\n + /// Reset value: 0x1 + M_RD_REQ: u1, + /// This bit masks the R_TX_ABRT interrupt in IC_INTR_STAT register.\n\n + /// Reset value: 0x1 + M_TX_ABRT: u1, + /// This bit masks the R_RX_DONE interrupt in IC_INTR_STAT register.\n\n + /// Reset value: 0x1 + M_RX_DONE: u1, + /// This bit masks the R_ACTIVITY interrupt in IC_INTR_STAT register.\n\n + /// Reset value: 0x0 + M_ACTIVITY: u1, + /// This bit masks the R_STOP_DET interrupt in IC_INTR_STAT register.\n\n + /// Reset value: 0x0 + M_STOP_DET: u1, + /// This bit masks the R_START_DET interrupt in IC_INTR_STAT register.\n\n + /// Reset value: 0x0 + M_START_DET: u1, + /// This bit masks the R_GEN_CALL interrupt in IC_INTR_STAT register.\n\n + /// Reset value: 0x1 + M_GEN_CALL: u1, + /// This bit masks the R_RESTART_DET interrupt in IC_INTR_STAT register.\n\n + /// Reset value: 0x0 + M_RESTART_DET: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + }), base_address + 0x30); + + /// address: 0x40044034 + /// I2C Raw Interrupt Status Register\n\n + /// Unlike the IC_INTR_STAT register, these bits are not masked so they always show + /// the true status of the DW_apb_i2c. + pub const IC_RAW_INTR_STAT = @intToPtr(*volatile Mmio(32, packed struct { + /// Set if the processor attempts to read the receive buffer when it is empty by + /// reading from the IC_DATA_CMD register. If the module is disabled + /// (IC_ENABLE[0]=0), this bit keeps its level until the master or slave state + /// machines go into idle, and when ic_en goes to 0, this interrupt is cleared.\n\n + /// Reset value: 0x0 + RX_UNDER: u1, + /// Set if the receive buffer is completely filled to IC_RX_BUFFER_DEPTH and an + /// additional byte is received from an external I2C device. The DW_apb_i2c + /// acknowledges this, but any data bytes received after the FIFO is full are lost. + /// If the module is disabled (IC_ENABLE[0]=0), this bit keeps its level until the + /// master or slave state machines go into idle, and when ic_en goes to 0, this + /// interrupt is cleared.\n\n + /// Note: If bit 9 of the IC_CON register (RX_FIFO_FULL_HLD_CTRL) is programmed to + /// HIGH, then the RX_OVER interrupt never occurs, because the Rx FIFO never + /// overflows.\n\n + /// Reset value: 0x0 + RX_OVER: u1, + /// Set when the receive buffer reaches or goes above the RX_TL threshold in the + /// IC_RX_TL register. It is automatically cleared by hardware when buffer level + /// goes below the threshold. If the module is disabled (IC_ENABLE[0]=0), the RX + /// FIFO is flushed and held in reset; therefore the RX FIFO is not full. So this + /// bit is cleared once the IC_ENABLE bit 0 is programmed with a 0, regardless of + /// the activity that continues.\n\n + /// Reset value: 0x0 + RX_FULL: u1, + /// Set during transmit if the transmit buffer is filled to IC_TX_BUFFER_DEPTH and + /// the processor attempts to issue another I2C command by writing to the + /// IC_DATA_CMD register. When the module is disabled, this bit keeps its level + /// until the master or slave state machines go into idle, and when ic_en goes to 0, + /// this interrupt is cleared.\n\n + /// Reset value: 0x0 + TX_OVER: u1, + /// The behavior of the TX_EMPTY interrupt status differs based on the TX_EMPTY_CTRL + /// selection in the IC_CON register. - When TX_EMPTY_CTRL = 0: This bit is set to 1 + /// when the transmit buffer is at or below the threshold value set in the IC_TX_TL + /// register. - When TX_EMPTY_CTRL = 1: This bit is set to 1 when the transmit + /// buffer is at or below the threshold value set in the IC_TX_TL register and the + /// transmission of the address/data from the internal shift register for the most + /// recently popped command is completed. It is automatically cleared by hardware + /// when the buffer level goes above the threshold. When IC_ENABLE[0] is set to 0, + /// the TX FIFO is flushed and held in reset. There the TX FIFO looks like it has no + /// data within it, so this bit is set to 1, provided there is activity in the + /// master or slave state machines. When there is no longer any activity, then with + /// ic_en=0, this bit is set to 0.\n\n + /// Reset value: 0x0. + TX_EMPTY: u1, + /// This bit is set to 1 when DW_apb_i2c is acting as a slave and another I2C master + /// is attempting to read data from DW_apb_i2c. The DW_apb_i2c holds the I2C bus in + /// a wait state (SCL=0) until this interrupt is serviced, which means that the + /// slave has been addressed by a remote master that is asking for data to be + /// transferred. The processor must respond to this interrupt and then write the + /// requested data to the IC_DATA_CMD register. This bit is set to 0 just after the + /// processor reads the IC_CLR_RD_REQ register.\n\n + /// Reset value: 0x0 + RD_REQ: u1, + /// This bit indicates if DW_apb_i2c, as an I2C transmitter, is unable to complete + /// the intended actions on the contents of the transmit FIFO. This situation can + /// occur both as an I2C master or an I2C slave, and is referred to as a 'transmit + /// abort'. When this bit is set to 1, the IC_TX_ABRT_SOURCE register indicates the + /// reason why the transmit abort takes places.\n\n + /// Note: The DW_apb_i2c flushes/resets/empties the TX_FIFO and RX_FIFO whenever + /// there is a transmit abort caused by any of the events tracked by the + /// IC_TX_ABRT_SOURCE register. The FIFOs remains in this flushed state until the + /// register IC_CLR_TX_ABRT is read. Once this read is performed, the Tx FIFO is + /// then ready to accept more data bytes from the APB interface.\n\n + /// Reset value: 0x0 + TX_ABRT: u1, + /// When the DW_apb_i2c is acting as a slave-transmitter, this bit is set to 1 if + /// the master does not acknowledge a transmitted byte. This occurs on the last byte + /// of the transmission, indicating that the transmission is done.\n\n + /// Reset value: 0x0 + RX_DONE: u1, + /// This bit captures DW_apb_i2c activity and stays set until it is cleared. There + /// are four ways to clear it: - Disabling the DW_apb_i2c - Reading the + /// IC_CLR_ACTIVITY register - Reading the IC_CLR_INTR register - System reset Once + /// this bit is set, it stays set unless one of the four methods is used to clear + /// it. Even if the DW_apb_i2c module is idle, this bit remains set until cleared, + /// indicating that there was activity on the bus.\n\n + /// Reset value: 0x0 + ACTIVITY: u1, + /// Indicates whether a STOP condition has occurred on the I2C interface regardless + /// of whether DW_apb_i2c is operating in slave or master mode.\n\n + /// In Slave Mode: - If IC_CON[7]=1'b1 (STOP_DET_IFADDRESSED), the STOP_DET + /// interrupt will be issued only if slave is addressed. Note: During a general call + /// address, this slave does not issue a STOP_DET interrupt if + /// STOP_DET_IF_ADDRESSED=1'b1, even if the slave responds to the general call + /// address by generating ACK. The STOP_DET interrupt is generated only when the + /// transmitted address matches the slave address (SAR). - If IC_CON[7]=1'b0 + /// (STOP_DET_IFADDRESSED), the STOP_DET interrupt is issued irrespective of whether + /// it is being addressed. In Master Mode: - If IC_CON[10]=1'b1 + /// (STOP_DET_IF_MASTER_ACTIVE),the STOP_DET interrupt will be issued only if Master + /// is active. - If IC_CON[10]=1'b0 (STOP_DET_IFADDRESSED),the STOP_DET interrupt + /// will be issued irrespective of whether master is active or not. Reset value: 0x0 + STOP_DET: u1, + /// Indicates whether a START or RESTART condition has occurred on the I2C interface + /// regardless of whether DW_apb_i2c is operating in slave or master mode.\n\n + /// Reset value: 0x0 + START_DET: u1, + /// Set only when a General Call address is received and it is acknowledged. It + /// stays set until it is cleared either by disabling DW_apb_i2c or when the CPU + /// reads bit 0 of the IC_CLR_GEN_CALL register. DW_apb_i2c stores the received data + /// in the Rx buffer.\n\n + /// Reset value: 0x0 + GEN_CALL: u1, + /// Indicates whether a RESTART condition has occurred on the I2C interface when + /// DW_apb_i2c is operating in Slave mode and the slave is being addressed. Enabled + /// only when IC_SLV_RESTART_DET_EN=1.\n\n + /// Note: However, in high-speed mode or during a START BYTE transfer, the RESTART + /// comes before the address field as per the I2C protocol. In this case, the slave + /// is not the addressed slave when the RESTART is issued, therefore DW_apb_i2c does + /// not generate the RESTART_DET interrupt.\n\n + /// Reset value: 0x0 + RESTART_DET: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + }), base_address + 0x34); + + /// address: 0x40044038 + /// I2C Receive FIFO Threshold Register + pub const IC_RX_TL = @intToPtr(*volatile Mmio(32, packed struct { + /// Receive FIFO Threshold Level.\n\n + /// Controls the level of entries (or above) that triggers the RX_FULL interrupt + /// (bit 2 in IC_RAW_INTR_STAT register). The valid range is 0-255, with the + /// additional restriction that hardware does not allow this value to be set to a + /// value larger than the depth of the buffer. If an attempt is made to do that, the + /// actual value set will be the maximum depth of the buffer. A value of 0 sets the + /// threshold for 1 entry, and a value of 255 sets the threshold for 256 entries. + RX_TL: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x38); + + /// address: 0x4004403c + /// I2C Transmit FIFO Threshold Register + pub const IC_TX_TL = @intToPtr(*volatile Mmio(32, packed struct { + /// Transmit FIFO Threshold Level.\n\n + /// Controls the level of entries (or below) that trigger the TX_EMPTY interrupt + /// (bit 4 in IC_RAW_INTR_STAT register). The valid range is 0-255, with the + /// additional restriction that it may not be set to value larger than the depth of + /// the buffer. If an attempt is made to do that, the actual value set will be the + /// maximum depth of the buffer. A value of 0 sets the threshold for 0 entries, and + /// a value of 255 sets the threshold for 255 entries. + TX_TL: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x3c); + + /// address: 0x40044040 + /// Clear Combined and Individual Interrupt Register + pub const IC_CLR_INTR = @intToPtr(*volatile Mmio(32, packed struct { + /// Read this register to clear the combined interrupt, all individual interrupts, + /// and the IC_TX_ABRT_SOURCE register. This bit does not clear hardware clearable + /// interrupts but software clearable interrupts. Refer to Bit 9 of the + /// IC_TX_ABRT_SOURCE register for an exception to clearing IC_TX_ABRT_SOURCE.\n\n + /// Reset value: 0x0 + CLR_INTR: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x40); + + /// address: 0x40044044 + /// Clear RX_UNDER Interrupt Register + pub const IC_CLR_RX_UNDER = @intToPtr(*volatile Mmio(32, packed struct { + /// Read this register to clear the RX_UNDER interrupt (bit 0) of the + /// IC_RAW_INTR_STAT register.\n\n + /// Reset value: 0x0 + CLR_RX_UNDER: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x44); + + /// address: 0x40044048 + /// Clear RX_OVER Interrupt Register + pub const IC_CLR_RX_OVER = @intToPtr(*volatile Mmio(32, packed struct { + /// Read this register to clear the RX_OVER interrupt (bit 1) of the + /// IC_RAW_INTR_STAT register.\n\n + /// Reset value: 0x0 + CLR_RX_OVER: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x48); + + /// address: 0x4004404c + /// Clear TX_OVER Interrupt Register + pub const IC_CLR_TX_OVER = @intToPtr(*volatile Mmio(32, packed struct { + /// Read this register to clear the TX_OVER interrupt (bit 3) of the + /// IC_RAW_INTR_STAT register.\n\n + /// Reset value: 0x0 + CLR_TX_OVER: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x4c); + + /// address: 0x40044050 + /// Clear RD_REQ Interrupt Register + pub const IC_CLR_RD_REQ = @intToPtr(*volatile Mmio(32, packed struct { + /// Read this register to clear the RD_REQ interrupt (bit 5) of the IC_RAW_INTR_STAT + /// register.\n\n + /// Reset value: 0x0 + CLR_RD_REQ: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x50); + + /// address: 0x40044054 + /// Clear TX_ABRT Interrupt Register + pub const IC_CLR_TX_ABRT = @intToPtr(*volatile Mmio(32, packed struct { + /// Read this register to clear the TX_ABRT interrupt (bit 6) of the + /// IC_RAW_INTR_STAT register, and the IC_TX_ABRT_SOURCE register. This also + /// releases the TX FIFO from the flushed/reset state, allowing more writes to the + /// TX FIFO. Refer to Bit 9 of the IC_TX_ABRT_SOURCE register for an exception to + /// clearing IC_TX_ABRT_SOURCE.\n\n + /// Reset value: 0x0 + CLR_TX_ABRT: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x54); + + /// address: 0x40044058 + /// Clear RX_DONE Interrupt Register + pub const IC_CLR_RX_DONE = @intToPtr(*volatile Mmio(32, packed struct { + /// Read this register to clear the RX_DONE interrupt (bit 7) of the + /// IC_RAW_INTR_STAT register.\n\n + /// Reset value: 0x0 + CLR_RX_DONE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x58); + + /// address: 0x4004405c + /// Clear ACTIVITY Interrupt Register + pub const IC_CLR_ACTIVITY = @intToPtr(*volatile Mmio(32, packed struct { + /// Reading this register clears the ACTIVITY interrupt if the I2C is not active + /// anymore. If the I2C module is still active on the bus, the ACTIVITY interrupt + /// bit continues to be set. It is automatically cleared by hardware if the module + /// is disabled and if there is no further activity on the bus. The value read from + /// this register to get status of the ACTIVITY interrupt (bit 8) of the + /// IC_RAW_INTR_STAT register.\n\n + /// Reset value: 0x0 + CLR_ACTIVITY: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x5c); + + /// address: 0x40044060 + /// Clear STOP_DET Interrupt Register + pub const IC_CLR_STOP_DET = @intToPtr(*volatile Mmio(32, packed struct { + /// Read this register to clear the STOP_DET interrupt (bit 9) of the + /// IC_RAW_INTR_STAT register.\n\n + /// Reset value: 0x0 + CLR_STOP_DET: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x60); + + /// address: 0x40044064 + /// Clear START_DET Interrupt Register + pub const IC_CLR_START_DET = @intToPtr(*volatile Mmio(32, packed struct { + /// Read this register to clear the START_DET interrupt (bit 10) of the + /// IC_RAW_INTR_STAT register.\n\n + /// Reset value: 0x0 + CLR_START_DET: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x64); + + /// address: 0x40044068 + /// Clear GEN_CALL Interrupt Register + pub const IC_CLR_GEN_CALL = @intToPtr(*volatile Mmio(32, packed struct { + /// Read this register to clear the GEN_CALL interrupt (bit 11) of IC_RAW_INTR_STAT + /// register.\n\n + /// Reset value: 0x0 + CLR_GEN_CALL: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x68); + + /// address: 0x4004406c + /// I2C Enable Register + pub const IC_ENABLE = @intToPtr(*volatile Mmio(32, packed struct { + /// Controls whether the DW_apb_i2c is enabled. - 0: Disables DW_apb_i2c (TX and RX + /// FIFOs are held in an erased state) - 1: Enables DW_apb_i2c Software can disable + /// DW_apb_i2c while it is active. However, it is important that care be taken to + /// ensure that DW_apb_i2c is disabled properly. A recommended procedure is + /// described in 'Disabling DW_apb_i2c'.\n\n + /// When DW_apb_i2c is disabled, the following occurs: - The TX FIFO and RX FIFO get + /// flushed. - Status bits in the IC_INTR_STAT register are still active until + /// DW_apb_i2c goes into IDLE state. If the module is transmitting, it stops as well + /// as deletes the contents of the transmit buffer after the current transfer is + /// complete. If the module is receiving, the DW_apb_i2c stops the current transfer + /// at the end of the current byte and does not acknowledge the transfer.\n\n + /// In systems with asynchronous pclk and ic_clk when IC_CLK_TYPE parameter set to + /// asynchronous (1), there is a two ic_clk delay when enabling or disabling the + /// DW_apb_i2c. For a detailed description on how to disable DW_apb_i2c, refer to + /// 'Disabling DW_apb_i2c'\n\n + /// Reset value: 0x0 + ENABLE: u1, + /// When set, the controller initiates the transfer abort. - 0: ABORT not initiated + /// or ABORT done - 1: ABORT operation in progress The software can abort the I2C + /// transfer in master mode by setting this bit. The software can set this bit only + /// when ENABLE is already set; otherwise, the controller ignores any write to ABORT + /// bit. The software cannot clear the ABORT bit once set. In response to an ABORT, + /// the controller issues a STOP and flushes the Tx FIFO after completing the + /// current transfer, then sets the TX_ABORT interrupt after the abort operation. + /// The ABORT bit is cleared automatically after the abort operation.\n\n + /// For a detailed description on how to abort I2C transfers, refer to 'Aborting I2C + /// Transfers'.\n\n + /// Reset value: 0x0 + ABORT: u1, + /// In Master mode: - 1'b1: Blocks the transmission of data on I2C bus even if Tx + /// FIFO has data to transmit. - 1'b0: The transmission of data starts on I2C bus + /// automatically, as soon as the first data is available in the Tx FIFO. Note: To + /// block the execution of Master commands, set the TX_CMD_BLOCK bit only when Tx + /// FIFO is empty (IC_STATUS[2]==1) and Master is in Idle state (IC_STATUS[5] == 0). + /// Any further commands put in the Tx FIFO are not executed until TX_CMD_BLOCK bit + /// is unset. Reset value: IC_TX_CMD_BLOCK_DEFAULT + TX_CMD_BLOCK: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + }), base_address + 0x6c); + + /// address: 0x40044070 + /// I2C Status Register\n\n + /// This is a read-only register used to indicate the current transfer status and + /// FIFO status. The status register may be read at any time. None of the bits in + /// this register request an interrupt.\n\n + /// When the I2C is disabled by writing 0 in bit 0 of the IC_ENABLE register: - Bits + /// 1 and 2 are set to 1 - Bits 3 and 10 are set to 0 When the master or slave state + /// machines goes to idle and ic_en=0: - Bits 5 and 6 are set to 0 + pub const IC_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + /// I2C Activity Status. Reset value: 0x0 + ACTIVITY: u1, + /// Transmit FIFO Not Full. Set when the transmit FIFO contains one or more empty + /// locations, and is cleared when the FIFO is full. - 0: Transmit FIFO is full - 1: + /// Transmit FIFO is not full Reset value: 0x1 + TFNF: u1, + /// Transmit FIFO Completely Empty. When the transmit FIFO is completely empty, this + /// bit is set. When it contains one or more valid entries, this bit is cleared. + /// This bit field does not request an interrupt. - 0: Transmit FIFO is not empty - + /// 1: Transmit FIFO is empty Reset value: 0x1 + TFE: u1, + /// Receive FIFO Not Empty. This bit is set when the receive FIFO contains one or + /// more entries; it is cleared when the receive FIFO is empty. - 0: Receive FIFO is + /// empty - 1: Receive FIFO is not empty Reset value: 0x0 + RFNE: u1, + /// Receive FIFO Completely Full. When the receive FIFO is completely full, this bit + /// is set. When the receive FIFO contains one or more empty location, this bit is + /// cleared. - 0: Receive FIFO is not full - 1: Receive FIFO is full Reset value: + /// 0x0 + RFF: u1, + /// Master FSM Activity Status. When the Master Finite State Machine (FSM) is not in + /// the IDLE state, this bit is set. - 0: Master FSM is in IDLE state so the Master + /// part of DW_apb_i2c is not Active - 1: Master FSM is not in IDLE state so the + /// Master part of DW_apb_i2c is Active Note: IC_STATUS[0]-that is, ACTIVITY bit-is + /// the OR of SLV_ACTIVITY and MST_ACTIVITY bits.\n\n + /// Reset value: 0x0 + MST_ACTIVITY: u1, + /// Slave FSM Activity Status. When the Slave Finite State Machine (FSM) is not in + /// the IDLE state, this bit is set. - 0: Slave FSM is in IDLE state so the Slave + /// part of DW_apb_i2c is not Active - 1: Slave FSM is not in IDLE state so the + /// Slave part of DW_apb_i2c is Active Reset value: 0x0 + SLV_ACTIVITY: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + }), base_address + 0x70); + + /// address: 0x40044074 + /// I2C Transmit FIFO Level Register This register contains the number of valid data + /// entries in the transmit FIFO buffer. It is cleared whenever: - The I2C is + /// disabled - There is a transmit abort - that is, TX_ABRT bit is set in the + /// IC_RAW_INTR_STAT register - The slave bulk transmit mode is aborted The register + /// increments whenever data is placed into the transmit FIFO and decrements when + /// data is taken from the transmit FIFO. + pub const IC_TXFLR = @intToPtr(*volatile Mmio(32, packed struct { + /// Transmit FIFO Level. Contains the number of valid data entries in the transmit + /// FIFO.\n\n + /// Reset value: 0x0 + TXFLR: u5, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + }), base_address + 0x74); + + /// address: 0x40044078 + /// I2C Receive FIFO Level Register This register contains the number of valid data + /// entries in the receive FIFO buffer. It is cleared whenever: - The I2C is + /// disabled - Whenever there is a transmit abort caused by any of the events + /// tracked in IC_TX_ABRT_SOURCE The register increments whenever data is placed + /// into the receive FIFO and decrements when data is taken from the receive FIFO. + pub const IC_RXFLR = @intToPtr(*volatile Mmio(32, packed struct { + /// Receive FIFO Level. Contains the number of valid data entries in the receive + /// FIFO.\n\n + /// Reset value: 0x0 + RXFLR: u5, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + }), base_address + 0x78); + + /// address: 0x4004407c + /// I2C SDA Hold Time Length Register\n\n + /// The bits [15:0] of this register are used to control the hold time of SDA during + /// transmit in both slave and master mode (after SCL goes from HIGH to LOW).\n\n + /// The bits [23:16] of this register are used to extend the SDA transition (if any) + /// whenever SCL is HIGH in the receiver in either master or slave mode.\n\n + /// Writes to this register succeed only when IC_ENABLE[0]=0.\n\n + /// The values in this register are in units of ic_clk period. The value programmed + /// in IC_SDA_TX_HOLD must be greater than the minimum hold time in each mode (one + /// cycle in master mode, seven cycles in slave mode) for the value to be + /// implemented.\n\n + /// The programmed SDA hold time during transmit (IC_SDA_TX_HOLD) cannot exceed at + /// any time the duration of the low part of scl. Therefore the programmed value + /// cannot be larger than N_SCL_LOW-2, where N_SCL_LOW is the duration of the low + /// part of the scl period measured in ic_clk cycles. + pub const IC_SDA_HOLD = @intToPtr(*volatile Mmio(32, packed struct { + /// Sets the required SDA hold time in units of ic_clk period, when DW_apb_i2c acts + /// as a transmitter.\n\n + /// Reset value: IC_DEFAULT_SDA_HOLD[15:0]. + IC_SDA_TX_HOLD: u16, + /// Sets the required SDA hold time in units of ic_clk period, when DW_apb_i2c acts + /// as a receiver.\n\n + /// Reset value: IC_DEFAULT_SDA_HOLD[23:16]. + IC_SDA_RX_HOLD: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x7c); + + /// address: 0x40044080 + /// I2C Transmit Abort Source Register\n\n + /// This register has 32 bits that indicate the source of the TX_ABRT bit. Except + /// for Bit 9, this register is cleared whenever the IC_CLR_TX_ABRT register or the + /// IC_CLR_INTR register is read. To clear Bit 9, the source of the + /// ABRT_SBYTE_NORSTRT must be fixed first; RESTART must be enabled (IC_CON[5]=1), + /// the SPECIAL bit must be cleared (IC_TAR[11]), or the GC_OR_START bit must be + /// cleared (IC_TAR[10]).\n\n + /// Once the source of the ABRT_SBYTE_NORSTRT is fixed, then this bit can be cleared + /// in the same manner as other bits in this register. If the source of the + /// ABRT_SBYTE_NORSTRT is not fixed before attempting to clear this bit, Bit 9 + /// clears for one cycle and is then re-asserted. + pub const IC_TX_ABRT_SOURCE = @intToPtr(*volatile Mmio(32, packed struct { + /// This field indicates that the Master is in 7-bit addressing mode and the address + /// sent was not acknowledged by any slave.\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + ABRT_7B_ADDR_NOACK: u1, + /// This field indicates that the Master is in 10-bit address mode and the first + /// 10-bit address byte was not acknowledged by any slave.\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + ABRT_10ADDR1_NOACK: u1, + /// This field indicates that the Master is in 10-bit address mode and that the + /// second address byte of the 10-bit address was not acknowledged by any slave.\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + ABRT_10ADDR2_NOACK: u1, + /// This field indicates the master-mode only bit. When the master receives an + /// acknowledgement for the address, but when it sends data byte(s) following the + /// address, it did not receive an acknowledge from the remote slave(s).\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master-Transmitter + ABRT_TXDATA_NOACK: u1, + /// This field indicates that DW_apb_i2c in master mode has sent a General Call and + /// no slave on the bus acknowledged the General Call.\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master-Transmitter + ABRT_GCALL_NOACK: u1, + /// This field indicates that DW_apb_i2c in the master mode has sent a General Call + /// but the user programmed the byte following the General Call to be a read from + /// the bus (IC_DATA_CMD[9] is set to 1).\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master-Transmitter + ABRT_GCALL_READ: u1, + /// This field indicates that the Master is in High Speed mode and the High Speed + /// Master code was acknowledged (wrong behavior).\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master + ABRT_HS_ACKDET: u1, + /// This field indicates that the Master has sent a START Byte and the START Byte + /// was acknowledged (wrong behavior).\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master + ABRT_SBYTE_ACKDET: u1, + /// This field indicates that the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) + /// =0) and the user is trying to use the master to transfer data in High Speed + /// mode.\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + ABRT_HS_NORSTRT: u1, + /// To clear Bit 9, the source of the ABRT_SBYTE_NORSTRT must be fixed first; + /// restart must be enabled (IC_CON[5]=1), the SPECIAL bit must be cleared + /// (IC_TAR[11]), or the GC_OR_START bit must be cleared (IC_TAR[10]). Once the + /// source of the ABRT_SBYTE_NORSTRT is fixed, then this bit can be cleared in the + /// same manner as other bits in this register. If the source of the + /// ABRT_SBYTE_NORSTRT is not fixed before attempting to clear this bit, bit 9 + /// clears for one cycle and then gets reasserted. When this field is set to 1, the + /// restart is disabled (IC_RESTART_EN bit (IC_CON[5]) =0) and the user is trying to + /// send a START Byte.\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master + ABRT_SBYTE_NORSTRT: u1, + /// This field indicates that the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) + /// =0) and the master sends a read command in 10-bit addressing mode.\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master-Receiver + ABRT_10B_RD_NORSTRT: u1, + /// This field indicates that the User tries to initiate a Master operation with the + /// Master mode disabled.\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + ABRT_MASTER_DIS: u1, + /// This field specifies that the Master has lost arbitration, or if + /// IC_TX_ABRT_SOURCE[14] is also set, then the slave transmitter has lost + /// arbitration.\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master-Transmitter or Slave-Transmitter + ARB_LOST: u1, + /// This field specifies that the Slave has received a read command and some data + /// exists in the TX FIFO, so the slave issues a TX_ABRT interrupt to flush old data + /// in TX FIFO.\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Slave-Transmitter + ABRT_SLVFLUSH_TXFIFO: u1, + /// This field indicates that a Slave has lost the bus while transmitting data to a + /// remote master. IC_TX_ABRT_SOURCE[12] is set at the same time. Note: Even though + /// the slave never 'owns' the bus, something could go wrong on the bus. This is a + /// fail safe check. For instance, during a data transmission at the low-to-high + /// transition of SCL, if what is on the data bus is not what is supposed to be + /// transmitted, then DW_apb_i2c no longer own the bus.\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Slave-Transmitter + ABRT_SLV_ARBLOST: u1, + /// 1: When the processor side responds to a slave mode request for data to be + /// transmitted to a remote master and user writes a 1 in CMD (bit 8) of IC_DATA_CMD + /// register.\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Slave-Transmitter + ABRT_SLVRD_INTX: u1, + /// This is a master-mode-only bit. Master has detected the transfer abort + /// (IC_ENABLE[1])\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master-Transmitter + ABRT_USER_ABRT: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + /// This field indicates the number of Tx FIFO Data Commands which are flushed due + /// to TX_ABRT interrupt. It is cleared whenever I2C is disabled.\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master-Transmitter or Slave-Transmitter + TX_FLUSH_CNT: u9, + }), base_address + 0x80); + + /// address: 0x40044084 + /// Generate Slave Data NACK Register\n\n + /// The register is used to generate a NACK for the data part of a transfer when + /// DW_apb_i2c is acting as a slave-receiver. This register only exists when the + /// IC_SLV_DATA_NACK_ONLY parameter is set to 1. When this parameter disabled, this + /// register does not exist and writing to the register's address has no effect.\n\n + /// A write can occur on this register if both of the following conditions are met: + /// - DW_apb_i2c is disabled (IC_ENABLE[0] = 0) - Slave part is inactive + /// (IC_STATUS[6] = 0) Note: The IC_STATUS[6] is a register read-back location for + /// the internal slv_activity signal; the user should poll this before writing the + /// ic_slv_data_nack_only bit. + pub const IC_SLV_DATA_NACK_ONLY = @intToPtr(*volatile Mmio(32, packed struct { + /// Generate NACK. This NACK generation only occurs when DW_apb_i2c is a + /// slave-receiver. If this register is set to a value of 1, it can only generate a + /// NACK after a data byte is received; hence, the data transfer is aborted and the + /// data received is not pushed to the receive buffer.\n\n + /// When the register is set to a value of 0, it generates NACK/ACK, depending on + /// normal criteria. - 1: generate NACK after data byte received - 0: generate + /// NACK/ACK normally Reset value: 0x0 + NACK: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x84); + + /// address: 0x40044088 + /// DMA Control Register\n\n + /// The register is used to enable the DMA Controller interface operation. There is + /// a separate bit for transmit and receive. This can be programmed regardless of + /// the state of IC_ENABLE. + pub const IC_DMA_CR = @intToPtr(*volatile Mmio(32, packed struct { + /// Receive DMA Enable. This bit enables/disables the receive FIFO DMA channel. + /// Reset value: 0x0 + RDMAE: u1, + /// Transmit DMA Enable. This bit enables/disables the transmit FIFO DMA channel. + /// Reset value: 0x0 + TDMAE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + }), base_address + 0x88); + + /// address: 0x4004408c + /// DMA Transmit Data Level Register + pub const IC_DMA_TDLR = @intToPtr(*volatile Mmio(32, packed struct { + /// Transmit Data Level. This bit field controls the level at which a DMA request is + /// made by the transmit logic. It is equal to the watermark level; that is, the + /// dma_tx_req signal is generated when the number of valid data entries in the + /// transmit FIFO is equal to or below this field value, and TDMAE = 1.\n\n + /// Reset value: 0x0 + DMATDL: u4, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + }), base_address + 0x8c); + + /// address: 0x40044090 + /// I2C Receive Data Level Register + pub const IC_DMA_RDLR = @intToPtr(*volatile Mmio(32, packed struct { + /// Receive Data Level. This bit field controls the level at which a DMA request is + /// made by the receive logic. The watermark level = DMARDL+1; that is, dma_rx_req + /// is generated when the number of valid data entries in the receive FIFO is equal + /// to or more than this field value + 1, and RDMAE =1. For instance, when DMARDL is + /// 0, then dma_rx_req is asserted when 1 or more data entries are present in the + /// receive FIFO.\n\n + /// Reset value: 0x0 + DMARDL: u4, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + }), base_address + 0x90); + + /// address: 0x40044094 + /// I2C SDA Setup Register\n\n + /// This register controls the amount of time delay (in terms of number of ic_clk + /// clock periods) introduced in the rising edge of SCL - relative to SDA changing - + /// when DW_apb_i2c services a read request in a slave-transmitter operation. The + /// relevant I2C requirement is tSU:DAT (note 4) as detailed in the I2C Bus + /// Specification. This register must be programmed with a value equal to or greater + /// than 2.\n\n + /// Writes to this register succeed only when IC_ENABLE[0] = 0.\n\n + /// Note: The length of setup time is calculated using [(IC_SDA_SETUP - 1) * + /// (ic_clk_period)], so if the user requires 10 ic_clk periods of setup time, they + /// should program a value of 11. The IC_SDA_SETUP register is only used by the + /// DW_apb_i2c when operating as a slave transmitter. + pub const IC_SDA_SETUP = @intToPtr(*volatile Mmio(32, packed struct { + /// SDA Setup. It is recommended that if the required delay is 1000ns, then for an + /// ic_clk frequency of 10 MHz, IC_SDA_SETUP should be programmed to a value of 11. + /// IC_SDA_SETUP must be programmed with a minimum value of 2. + SDA_SETUP: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x94); + + /// address: 0x40044098 + /// I2C ACK General Call Register\n\n + /// The register controls whether DW_apb_i2c responds with a ACK or NACK when it + /// receives an I2C General Call address.\n\n + /// This register is applicable only when the DW_apb_i2c is in slave mode. + pub const IC_ACK_GENERAL_CALL = @intToPtr(*volatile Mmio(32, packed struct { + /// ACK General Call. When set to 1, DW_apb_i2c responds with a ACK (by asserting + /// ic_data_oe) when it receives a General Call. Otherwise, DW_apb_i2c responds with + /// a NACK (by negating ic_data_oe). + ACK_GEN_CALL: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x98); + + /// address: 0x4004409c + /// I2C Enable Status Register\n\n + /// The register is used to report the DW_apb_i2c hardware status when the + /// IC_ENABLE[0] register is set from 1 to 0; that is, when DW_apb_i2c is + /// disabled.\n\n + /// If IC_ENABLE[0] has been set to 1, bits 2:1 are forced to 0, and bit 0 is forced + /// to 1.\n\n + /// If IC_ENABLE[0] has been set to 0, bits 2:1 is only be valid as soon as bit 0 is + /// read as '0'.\n\n + /// Note: When IC_ENABLE[0] has been set to 0, a delay occurs for bit 0 to be read + /// as 0 because disabling the DW_apb_i2c depends on I2C bus activities. + pub const IC_ENABLE_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + /// ic_en Status. This bit always reflects the value driven on the output port + /// ic_en. - When read as 1, DW_apb_i2c is deemed to be in an enabled state. - When + /// read as 0, DW_apb_i2c is deemed completely inactive. Note: The CPU can safely + /// read this bit anytime. When this bit is read as 0, the CPU can safely read + /// SLV_RX_DATA_LOST (bit 2) and SLV_DISABLED_WHILE_BUSY (bit 1).\n\n + /// Reset value: 0x0 + IC_EN: u1, + /// Slave Disabled While Busy (Transmit, Receive). This bit indicates if a potential + /// or active Slave operation has been aborted due to the setting bit 0 of the + /// IC_ENABLE register from 1 to 0. This bit is set when the CPU writes a 0 to the + /// IC_ENABLE register while:\n\n + /// (a) DW_apb_i2c is receiving the address byte of the Slave-Transmitter operation + /// from a remote master;\n\n + /// OR,\n\n + /// (b) address and data bytes of the Slave-Receiver operation from a remote + /// master.\n\n + /// When read as 1, DW_apb_i2c is deemed to have forced a NACK during any part of an + /// I2C transfer, irrespective of whether the I2C address matches the slave address + /// set in DW_apb_i2c (IC_SAR register) OR if the transfer is completed before + /// IC_ENABLE is set to 0 but has not taken effect.\n\n + /// Note: If the remote I2C master terminates the transfer with a STOP condition + /// before the DW_apb_i2c has a chance to NACK a transfer, and IC_ENABLE[0] has been + /// set to 0, then this bit will also be set to 1.\n\n + /// When read as 0, DW_apb_i2c is deemed to have been disabled when there is master + /// activity, or when the I2C bus is idle.\n\n + /// Note: The CPU can safely read this bit when IC_EN (bit 0) is read as 0.\n\n + /// Reset value: 0x0 + SLV_DISABLED_WHILE_BUSY: u1, + /// Slave Received Data Lost. This bit indicates if a Slave-Receiver operation has + /// been aborted with at least one data byte received from an I2C transfer due to + /// the setting bit 0 of IC_ENABLE from 1 to 0. When read as 1, DW_apb_i2c is deemed + /// to have been actively engaged in an aborted I2C transfer (with matching address) + /// and the data phase of the I2C transfer has been entered, even though a data byte + /// has been responded with a NACK.\n\n + /// Note: If the remote I2C master terminates the transfer with a STOP condition + /// before the DW_apb_i2c has a chance to NACK a transfer, and IC_ENABLE[0] has been + /// set to 0, then this bit is also set to 1.\n\n + /// When read as 0, DW_apb_i2c is deemed to have been disabled without being + /// actively involved in the data phase of a Slave-Receiver transfer.\n\n + /// Note: The CPU can safely read this bit when IC_EN (bit 0) is read as 0.\n\n + /// Reset value: 0x0 + SLV_RX_DATA_LOST: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + }), base_address + 0x9c); + + /// address: 0x400440a0 + /// I2C SS, FS or FM+ spike suppression limit\n\n + /// This register is used to store the duration, measured in ic_clk cycles, of the + /// longest spike that is filtered out by the spike suppression logic when the + /// component is operating in SS, FS or FM+ modes. The relevant I2C requirement is + /// tSP (table 4) as detailed in the I2C Bus Specification. This register must be + /// programmed with a minimum value of 1. + pub const IC_FS_SPKLEN = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xa0); + + /// address: 0x400440a8 + /// Clear RESTART_DET Interrupt Register + pub const IC_CLR_RESTART_DET = @intToPtr(*volatile Mmio(32, packed struct { + /// Read this register to clear the RESTART_DET interrupt (bit 12) of + /// IC_RAW_INTR_STAT register.\n\n + /// Reset value: 0x0 + CLR_RESTART_DET: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0xa8); + + /// address: 0x400440f4 + /// Component Parameter Register 1\n\n + /// Note This register is not implemented and therefore reads as 0. If it was + /// implemented it would be a constant read-only register that contains encoded + /// information about the component's parameter settings. Fields shown below are the + /// settings for those parameters + pub const IC_COMP_PARAM_1 = @intToPtr(*volatile Mmio(32, packed struct { + /// APB data bus width is 32 bits + APB_DATA_WIDTH: u2, + /// MAX SPEED MODE = FAST MODE + MAX_SPEED_MODE: u2, + /// Programmable count values for each mode. + HC_COUNT_VALUES: u1, + /// COMBINED Interrupt outputs + INTR_IO: u1, + /// DMA handshaking signals are enabled + HAS_DMA: u1, + /// Encoded parameters not visible + ADD_ENCODED_PARAMS: u1, + /// RX Buffer Depth = 16 + RX_BUFFER_DEPTH: u8, + /// TX Buffer Depth = 16 + TX_BUFFER_DEPTH: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0xf4); + + /// address: 0x400440f8 + /// I2C Component Version Register + pub const IC_COMP_VERSION = @intToPtr(*volatile u32, base_address + 0xf8); + + /// address: 0x400440fc + /// I2C Component Type Register + pub const IC_COMP_TYPE = @intToPtr(*volatile u32, base_address + 0xfc); + }; + pub const I2C1 = struct { + pub const base_address = 0x40048000; + + /// address: 0x40048000 + /// I2C Control Register. This register can be written only when the DW_apb_i2c is + /// disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes + /// at other times have no effect.\n\n + /// Read/Write Access: - bit 10 is read only. - bit 11 is read only - bit 16 is read + /// only - bit 17 is read only - bits 18 and 19 are read only. + pub const IC_CON = @intToPtr(*volatile Mmio(32, packed struct { + /// This bit controls whether the DW_apb_i2c master is enabled.\n\n + /// NOTE: Software should ensure that if this bit is written with '1' then bit 6 + /// should also be written with a '1'. + MASTER_MODE: u1, + /// These bits control at which speed the DW_apb_i2c operates; its setting is + /// relevant only if one is operating the DW_apb_i2c in master mode. Hardware + /// protects against illegal values being programmed by software. These bits must be + /// programmed appropriately for slave mode also, as it is used to capture correct + /// value of spike filter as per the speed mode.\n\n + /// This register should be programmed only with a value in the range of 1 to + /// IC_MAX_SPEED_MODE; otherwise, hardware updates this register with the value of + /// IC_MAX_SPEED_MODE.\n\n + /// 1: standard mode (100 kbit/s)\n\n + /// 2: fast mode (<=400 kbit/s) or fast mode plus (<=1000Kbit/s)\n\n + /// 3: high speed mode (3.4 Mbit/s)\n\n + /// Note: This field is not applicable when IC_ULTRA_FAST_MODE=1 + SPEED: u2, + /// When acting as a slave, this bit controls whether the DW_apb_i2c responds to 7- + /// or 10-bit addresses. - 0: 7-bit addressing. The DW_apb_i2c ignores transactions + /// that involve 10-bit addressing; for 7-bit addressing, only the lower 7 bits of + /// the IC_SAR register are compared. - 1: 10-bit addressing. The DW_apb_i2c + /// responds to only 10-bit addressing transfers that match the full 10 bits of the + /// IC_SAR register. + IC_10BITADDR_SLAVE: u1, + /// Controls whether the DW_apb_i2c starts its transfers in 7- or 10-bit addressing + /// mode when acting as a master. - 0: 7-bit addressing - 1: 10-bit addressing + IC_10BITADDR_MASTER: u1, + /// Determines whether RESTART conditions may be sent when acting as a master. Some + /// older slaves do not support handling RESTART conditions; however, RESTART + /// conditions are used in several DW_apb_i2c operations. When RESTART is disabled, + /// the master is prohibited from performing the following functions: - Sending a + /// START BYTE - Performing any high-speed mode operation - High-speed mode + /// operation - Performing direction changes in combined format mode - Performing a + /// read operation with a 10-bit address By replacing RESTART condition followed by + /// a STOP and a subsequent START condition, split operations are broken down into + /// multiple DW_apb_i2c transfers. If the above operations are performed, it will + /// result in setting bit 6 (TX_ABRT) of the IC_RAW_INTR_STAT register.\n\n + /// Reset value: ENABLED + IC_RESTART_EN: u1, + /// This bit controls whether I2C has its slave disabled, which means once the + /// presetn signal is applied, then this bit is set and the slave is disabled.\n\n + /// If this bit is set (slave is disabled), DW_apb_i2c functions only as a master + /// and does not perform any action that requires a slave.\n\n + /// NOTE: Software should ensure that if this bit is written with 0, then bit 0 + /// should also be written with a 0. + IC_SLAVE_DISABLE: u1, + /// In slave mode: - 1'b1: issues the STOP_DET interrupt only when it is addressed. + /// - 1'b0: issues the STOP_DET irrespective of whether it's addressed or not. Reset + /// value: 0x0\n\n + /// NOTE: During a general call address, this slave does not issue the STOP_DET + /// interrupt if STOP_DET_IF_ADDRESSED = 1'b1, even if the slave responds to the + /// general call address by generating ACK. The STOP_DET interrupt is generated only + /// when the transmitted address matches the slave address (SAR). + STOP_DET_IFADDRESSED: u1, + /// This bit controls the generation of the TX_EMPTY interrupt, as described in the + /// IC_RAW_INTR_STAT register.\n\n + /// Reset value: 0x0. + TX_EMPTY_CTRL: u1, + /// This bit controls whether DW_apb_i2c should hold the bus when the Rx FIFO is + /// physically full to its RX_BUFFER_DEPTH, as described in the + /// IC_RX_FULL_HLD_BUS_EN parameter.\n\n + /// Reset value: 0x0. + RX_FIFO_FULL_HLD_CTRL: u1, + /// Master issues the STOP_DET interrupt irrespective of whether master is active or + /// not + STOP_DET_IF_MASTER_ACTIVE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + }), base_address + 0x0); + + /// address: 0x40048004 + /// I2C Target Address Register\n\n + /// This register is 12 bits wide, and bits 31:12 are reserved. This register can be + /// written to only when IC_ENABLE[0] is set to 0.\n\n + /// Note: If the software or application is aware that the DW_apb_i2c is not using + /// the TAR address for the pending commands in the Tx FIFO, then it is possible to + /// update the TAR address even while the Tx FIFO has entries (IC_STATUS[2]= 0). - + /// It is not necessary to perform any write to this register if DW_apb_i2c is + /// enabled as an I2C slave only. + pub const IC_TAR = @intToPtr(*volatile Mmio(32, packed struct { + /// This is the target address for any master transaction. When transmitting a + /// General Call, these bits are ignored. To generate a START BYTE, the CPU needs to + /// write only once into these bits.\n\n + /// If the IC_TAR and IC_SAR are the same, loopback exists but the FIFOs are shared + /// between master and slave, so full loopback is not feasible. Only one direction + /// loopback mode is supported (simplex), not duplex. A master cannot transmit to + /// itself; it can transmit to only a slave. + IC_TAR: u10, + /// If bit 11 (SPECIAL) is set to 1 and bit 13(Device-ID) is set to 0, then this bit + /// indicates whether a General Call or START byte command is to be performed by the + /// DW_apb_i2c. - 0: General Call Address - after issuing a General Call, only + /// writes may be performed. Attempting to issue a read command results in setting + /// bit 6 (TX_ABRT) of the IC_RAW_INTR_STAT register. The DW_apb_i2c remains in + /// General Call mode until the SPECIAL bit value (bit 11) is cleared. - 1: START + /// BYTE Reset value: 0x0 + GC_OR_START: u1, + /// This bit indicates whether software performs a Device-ID or General Call or + /// START BYTE command. - 0: ignore bit 10 GC_OR_START and use IC_TAR normally - 1: + /// perform special I2C command as specified in Device_ID or GC_OR_START bit Reset + /// value: 0x0 + SPECIAL: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x4); + + /// address: 0x40048008 + /// I2C Slave Address Register + pub const IC_SAR = @intToPtr(*volatile MmioInt(32, u10), base_address + 0x8); + + /// address: 0x40048010 + /// I2C Rx/Tx Data Buffer and Command Register; this is the register the CPU writes + /// to when filling the TX FIFO and the CPU reads from when retrieving bytes from RX + /// FIFO.\n\n + /// The size of the register changes as follows:\n\n + /// Write: - 11 bits when IC_EMPTYFIFO_HOLD_MASTER_EN=1 - 9 bits when + /// IC_EMPTYFIFO_HOLD_MASTER_EN=0 Read: - 12 bits when IC_FIRST_DATA_BYTE_STATUS = 1 + /// - 8 bits when IC_FIRST_DATA_BYTE_STATUS = 0 Note: In order for the DW_apb_i2c to + /// continue acknowledging reads, a read command should be written for every byte + /// that is to be received; otherwise the DW_apb_i2c will stop acknowledging. + pub const IC_DATA_CMD = @intToPtr(*volatile Mmio(32, packed struct { + /// This register contains the data to be transmitted or received on the I2C bus. If + /// you are writing to this register and want to perform a read, bits 7:0 (DAT) are + /// ignored by the DW_apb_i2c. However, when you read this register, these bits + /// return the value of data received on the DW_apb_i2c interface.\n\n + /// Reset value: 0x0 + DAT: u8, + /// This bit controls whether a read or a write is performed. This bit does not + /// control the direction when the DW_apb_i2con acts as a slave. It controls only + /// the direction when it acts as a master.\n\n + /// When a command is entered in the TX FIFO, this bit distinguishes the write and + /// read commands. In slave-receiver mode, this bit is a 'don't care' because writes + /// to this register are not required. In slave-transmitter mode, a '0' indicates + /// that the data in IC_DATA_CMD is to be transmitted.\n\n + /// When programming this bit, you should remember the following: attempting to + /// perform a read operation after a General Call command has been sent results in a + /// TX_ABRT interrupt (bit 6 of the IC_RAW_INTR_STAT register), unless bit 11 + /// (SPECIAL) in the IC_TAR register has been cleared. If a '1' is written to this + /// bit after receiving a RD_REQ interrupt, then a TX_ABRT interrupt occurs.\n\n + /// Reset value: 0x0 + CMD: u1, + /// This bit controls whether a STOP is issued after the byte is sent or + /// received.\n\n + /// - 1 - STOP is issued after this byte, regardless of whether or not the Tx FIFO + /// is empty. If the Tx FIFO is not empty, the master immediately tries to start a + /// new transfer by issuing a START and arbitrating for the bus. - 0 - STOP is not + /// issued after this byte, regardless of whether or not the Tx FIFO is empty. If + /// the Tx FIFO is not empty, the master continues the current transfer by + /// sending/receiving data bytes according to the value of the CMD bit. If the Tx + /// FIFO is empty, the master holds the SCL line low and stalls the bus until a new + /// command is available in the Tx FIFO. Reset value: 0x0 + STOP: u1, + /// This bit controls whether a RESTART is issued before the byte is sent or + /// received.\n\n + /// 1 - If IC_RESTART_EN is 1, a RESTART is issued before the data is sent/received + /// (according to the value of CMD), regardless of whether or not the transfer + /// direction is changing from the previous command; if IC_RESTART_EN is 0, a STOP + /// followed by a START is issued instead.\n\n + /// 0 - If IC_RESTART_EN is 1, a RESTART is issued only if the transfer direction is + /// changing from the previous command; if IC_RESTART_EN is 0, a STOP followed by a + /// START is issued instead.\n\n + /// Reset value: 0x0 + RESTART: u1, + /// Indicates the first data byte received after the address phase for receive + /// transfer in Master receiver or Slave receiver mode.\n\n + /// Reset value : 0x0\n\n + /// NOTE: In case of APB_DATA_WIDTH=8,\n\n + /// 1. The user has to perform two APB Reads to IC_DATA_CMD in order to get status + /// on 11 bit.\n\n + /// 2. In order to read the 11 bit, the user has to perform the first data byte read + /// [7:0] (offset 0x10) and then perform the second read [15:8] (offset 0x11) in + /// order to know the status of 11 bit (whether the data received in previous read + /// is a first data byte or not).\n\n + /// 3. The 11th bit is an optional read field, user can ignore 2nd byte read [15:8] + /// (offset 0x11) if not interested in FIRST_DATA_BYTE status. + FIRST_DATA_BYTE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x10); + + /// address: 0x40048014 + /// Standard Speed I2C Clock SCL High Count Register + pub const IC_SS_SCL_HCNT = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x14); + + /// address: 0x40048018 + /// Standard Speed I2C Clock SCL Low Count Register + pub const IC_SS_SCL_LCNT = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x18); + + /// address: 0x4004801c + /// Fast Mode or Fast Mode Plus I2C Clock SCL High Count Register + pub const IC_FS_SCL_HCNT = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x1c); + + /// address: 0x40048020 + /// Fast Mode or Fast Mode Plus I2C Clock SCL Low Count Register + pub const IC_FS_SCL_LCNT = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x20); + + /// address: 0x4004802c + /// I2C Interrupt Status Register\n\n + /// Each bit in this register has a corresponding mask bit in the IC_INTR_MASK + /// register. These bits are cleared by reading the matching interrupt clear + /// register. The unmasked raw versions of these bits are available in the + /// IC_RAW_INTR_STAT register. + pub const IC_INTR_STAT = @intToPtr(*volatile Mmio(32, packed struct { + /// See IC_RAW_INTR_STAT for a detailed description of R_RX_UNDER bit.\n\n + /// Reset value: 0x0 + R_RX_UNDER: u1, + /// See IC_RAW_INTR_STAT for a detailed description of R_RX_OVER bit.\n\n + /// Reset value: 0x0 + R_RX_OVER: u1, + /// See IC_RAW_INTR_STAT for a detailed description of R_RX_FULL bit.\n\n + /// Reset value: 0x0 + R_RX_FULL: u1, + /// See IC_RAW_INTR_STAT for a detailed description of R_TX_OVER bit.\n\n + /// Reset value: 0x0 + R_TX_OVER: u1, + /// See IC_RAW_INTR_STAT for a detailed description of R_TX_EMPTY bit.\n\n + /// Reset value: 0x0 + R_TX_EMPTY: u1, + /// See IC_RAW_INTR_STAT for a detailed description of R_RD_REQ bit.\n\n + /// Reset value: 0x0 + R_RD_REQ: u1, + /// See IC_RAW_INTR_STAT for a detailed description of R_TX_ABRT bit.\n\n + /// Reset value: 0x0 + R_TX_ABRT: u1, + /// See IC_RAW_INTR_STAT for a detailed description of R_RX_DONE bit.\n\n + /// Reset value: 0x0 + R_RX_DONE: u1, + /// See IC_RAW_INTR_STAT for a detailed description of R_ACTIVITY bit.\n\n + /// Reset value: 0x0 + R_ACTIVITY: u1, + /// See IC_RAW_INTR_STAT for a detailed description of R_STOP_DET bit.\n\n + /// Reset value: 0x0 + R_STOP_DET: u1, + /// See IC_RAW_INTR_STAT for a detailed description of R_START_DET bit.\n\n + /// Reset value: 0x0 + R_START_DET: u1, + /// See IC_RAW_INTR_STAT for a detailed description of R_GEN_CALL bit.\n\n + /// Reset value: 0x0 + R_GEN_CALL: u1, + /// See IC_RAW_INTR_STAT for a detailed description of R_RESTART_DET bit.\n\n + /// Reset value: 0x0 + R_RESTART_DET: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + }), base_address + 0x2c); + + /// address: 0x40048030 + /// I2C Interrupt Mask Register.\n\n + /// These bits mask their corresponding interrupt status bits. This register is + /// active low; a value of 0 masks the interrupt, whereas a value of 1 unmasks the + /// interrupt. + pub const IC_INTR_MASK = @intToPtr(*volatile Mmio(32, packed struct { + /// This bit masks the R_RX_UNDER interrupt in IC_INTR_STAT register.\n\n + /// Reset value: 0x1 + M_RX_UNDER: u1, + /// This bit masks the R_RX_OVER interrupt in IC_INTR_STAT register.\n\n + /// Reset value: 0x1 + M_RX_OVER: u1, + /// This bit masks the R_RX_FULL interrupt in IC_INTR_STAT register.\n\n + /// Reset value: 0x1 + M_RX_FULL: u1, + /// This bit masks the R_TX_OVER interrupt in IC_INTR_STAT register.\n\n + /// Reset value: 0x1 + M_TX_OVER: u1, + /// This bit masks the R_TX_EMPTY interrupt in IC_INTR_STAT register.\n\n + /// Reset value: 0x1 + M_TX_EMPTY: u1, + /// This bit masks the R_RD_REQ interrupt in IC_INTR_STAT register.\n\n + /// Reset value: 0x1 + M_RD_REQ: u1, + /// This bit masks the R_TX_ABRT interrupt in IC_INTR_STAT register.\n\n + /// Reset value: 0x1 + M_TX_ABRT: u1, + /// This bit masks the R_RX_DONE interrupt in IC_INTR_STAT register.\n\n + /// Reset value: 0x1 + M_RX_DONE: u1, + /// This bit masks the R_ACTIVITY interrupt in IC_INTR_STAT register.\n\n + /// Reset value: 0x0 + M_ACTIVITY: u1, + /// This bit masks the R_STOP_DET interrupt in IC_INTR_STAT register.\n\n + /// Reset value: 0x0 + M_STOP_DET: u1, + /// This bit masks the R_START_DET interrupt in IC_INTR_STAT register.\n\n + /// Reset value: 0x0 + M_START_DET: u1, + /// This bit masks the R_GEN_CALL interrupt in IC_INTR_STAT register.\n\n + /// Reset value: 0x1 + M_GEN_CALL: u1, + /// This bit masks the R_RESTART_DET interrupt in IC_INTR_STAT register.\n\n + /// Reset value: 0x0 + M_RESTART_DET: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + }), base_address + 0x30); + + /// address: 0x40048034 + /// I2C Raw Interrupt Status Register\n\n + /// Unlike the IC_INTR_STAT register, these bits are not masked so they always show + /// the true status of the DW_apb_i2c. + pub const IC_RAW_INTR_STAT = @intToPtr(*volatile Mmio(32, packed struct { + /// Set if the processor attempts to read the receive buffer when it is empty by + /// reading from the IC_DATA_CMD register. If the module is disabled + /// (IC_ENABLE[0]=0), this bit keeps its level until the master or slave state + /// machines go into idle, and when ic_en goes to 0, this interrupt is cleared.\n\n + /// Reset value: 0x0 + RX_UNDER: u1, + /// Set if the receive buffer is completely filled to IC_RX_BUFFER_DEPTH and an + /// additional byte is received from an external I2C device. The DW_apb_i2c + /// acknowledges this, but any data bytes received after the FIFO is full are lost. + /// If the module is disabled (IC_ENABLE[0]=0), this bit keeps its level until the + /// master or slave state machines go into idle, and when ic_en goes to 0, this + /// interrupt is cleared.\n\n + /// Note: If bit 9 of the IC_CON register (RX_FIFO_FULL_HLD_CTRL) is programmed to + /// HIGH, then the RX_OVER interrupt never occurs, because the Rx FIFO never + /// overflows.\n\n + /// Reset value: 0x0 + RX_OVER: u1, + /// Set when the receive buffer reaches or goes above the RX_TL threshold in the + /// IC_RX_TL register. It is automatically cleared by hardware when buffer level + /// goes below the threshold. If the module is disabled (IC_ENABLE[0]=0), the RX + /// FIFO is flushed and held in reset; therefore the RX FIFO is not full. So this + /// bit is cleared once the IC_ENABLE bit 0 is programmed with a 0, regardless of + /// the activity that continues.\n\n + /// Reset value: 0x0 + RX_FULL: u1, + /// Set during transmit if the transmit buffer is filled to IC_TX_BUFFER_DEPTH and + /// the processor attempts to issue another I2C command by writing to the + /// IC_DATA_CMD register. When the module is disabled, this bit keeps its level + /// until the master or slave state machines go into idle, and when ic_en goes to 0, + /// this interrupt is cleared.\n\n + /// Reset value: 0x0 + TX_OVER: u1, + /// The behavior of the TX_EMPTY interrupt status differs based on the TX_EMPTY_CTRL + /// selection in the IC_CON register. - When TX_EMPTY_CTRL = 0: This bit is set to 1 + /// when the transmit buffer is at or below the threshold value set in the IC_TX_TL + /// register. - When TX_EMPTY_CTRL = 1: This bit is set to 1 when the transmit + /// buffer is at or below the threshold value set in the IC_TX_TL register and the + /// transmission of the address/data from the internal shift register for the most + /// recently popped command is completed. It is automatically cleared by hardware + /// when the buffer level goes above the threshold. When IC_ENABLE[0] is set to 0, + /// the TX FIFO is flushed and held in reset. There the TX FIFO looks like it has no + /// data within it, so this bit is set to 1, provided there is activity in the + /// master or slave state machines. When there is no longer any activity, then with + /// ic_en=0, this bit is set to 0.\n\n + /// Reset value: 0x0. + TX_EMPTY: u1, + /// This bit is set to 1 when DW_apb_i2c is acting as a slave and another I2C master + /// is attempting to read data from DW_apb_i2c. The DW_apb_i2c holds the I2C bus in + /// a wait state (SCL=0) until this interrupt is serviced, which means that the + /// slave has been addressed by a remote master that is asking for data to be + /// transferred. The processor must respond to this interrupt and then write the + /// requested data to the IC_DATA_CMD register. This bit is set to 0 just after the + /// processor reads the IC_CLR_RD_REQ register.\n\n + /// Reset value: 0x0 + RD_REQ: u1, + /// This bit indicates if DW_apb_i2c, as an I2C transmitter, is unable to complete + /// the intended actions on the contents of the transmit FIFO. This situation can + /// occur both as an I2C master or an I2C slave, and is referred to as a 'transmit + /// abort'. When this bit is set to 1, the IC_TX_ABRT_SOURCE register indicates the + /// reason why the transmit abort takes places.\n\n + /// Note: The DW_apb_i2c flushes/resets/empties the TX_FIFO and RX_FIFO whenever + /// there is a transmit abort caused by any of the events tracked by the + /// IC_TX_ABRT_SOURCE register. The FIFOs remains in this flushed state until the + /// register IC_CLR_TX_ABRT is read. Once this read is performed, the Tx FIFO is + /// then ready to accept more data bytes from the APB interface.\n\n + /// Reset value: 0x0 + TX_ABRT: u1, + /// When the DW_apb_i2c is acting as a slave-transmitter, this bit is set to 1 if + /// the master does not acknowledge a transmitted byte. This occurs on the last byte + /// of the transmission, indicating that the transmission is done.\n\n + /// Reset value: 0x0 + RX_DONE: u1, + /// This bit captures DW_apb_i2c activity and stays set until it is cleared. There + /// are four ways to clear it: - Disabling the DW_apb_i2c - Reading the + /// IC_CLR_ACTIVITY register - Reading the IC_CLR_INTR register - System reset Once + /// this bit is set, it stays set unless one of the four methods is used to clear + /// it. Even if the DW_apb_i2c module is idle, this bit remains set until cleared, + /// indicating that there was activity on the bus.\n\n + /// Reset value: 0x0 + ACTIVITY: u1, + /// Indicates whether a STOP condition has occurred on the I2C interface regardless + /// of whether DW_apb_i2c is operating in slave or master mode.\n\n + /// In Slave Mode: - If IC_CON[7]=1'b1 (STOP_DET_IFADDRESSED), the STOP_DET + /// interrupt will be issued only if slave is addressed. Note: During a general call + /// address, this slave does not issue a STOP_DET interrupt if + /// STOP_DET_IF_ADDRESSED=1'b1, even if the slave responds to the general call + /// address by generating ACK. The STOP_DET interrupt is generated only when the + /// transmitted address matches the slave address (SAR). - If IC_CON[7]=1'b0 + /// (STOP_DET_IFADDRESSED), the STOP_DET interrupt is issued irrespective of whether + /// it is being addressed. In Master Mode: - If IC_CON[10]=1'b1 + /// (STOP_DET_IF_MASTER_ACTIVE),the STOP_DET interrupt will be issued only if Master + /// is active. - If IC_CON[10]=1'b0 (STOP_DET_IFADDRESSED),the STOP_DET interrupt + /// will be issued irrespective of whether master is active or not. Reset value: 0x0 + STOP_DET: u1, + /// Indicates whether a START or RESTART condition has occurred on the I2C interface + /// regardless of whether DW_apb_i2c is operating in slave or master mode.\n\n + /// Reset value: 0x0 + START_DET: u1, + /// Set only when a General Call address is received and it is acknowledged. It + /// stays set until it is cleared either by disabling DW_apb_i2c or when the CPU + /// reads bit 0 of the IC_CLR_GEN_CALL register. DW_apb_i2c stores the received data + /// in the Rx buffer.\n\n + /// Reset value: 0x0 + GEN_CALL: u1, + /// Indicates whether a RESTART condition has occurred on the I2C interface when + /// DW_apb_i2c is operating in Slave mode and the slave is being addressed. Enabled + /// only when IC_SLV_RESTART_DET_EN=1.\n\n + /// Note: However, in high-speed mode or during a START BYTE transfer, the RESTART + /// comes before the address field as per the I2C protocol. In this case, the slave + /// is not the addressed slave when the RESTART is issued, therefore DW_apb_i2c does + /// not generate the RESTART_DET interrupt.\n\n + /// Reset value: 0x0 + RESTART_DET: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + }), base_address + 0x34); + + /// address: 0x40048038 + /// I2C Receive FIFO Threshold Register + pub const IC_RX_TL = @intToPtr(*volatile Mmio(32, packed struct { + /// Receive FIFO Threshold Level.\n\n + /// Controls the level of entries (or above) that triggers the RX_FULL interrupt + /// (bit 2 in IC_RAW_INTR_STAT register). The valid range is 0-255, with the + /// additional restriction that hardware does not allow this value to be set to a + /// value larger than the depth of the buffer. If an attempt is made to do that, the + /// actual value set will be the maximum depth of the buffer. A value of 0 sets the + /// threshold for 1 entry, and a value of 255 sets the threshold for 256 entries. + RX_TL: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x38); + + /// address: 0x4004803c + /// I2C Transmit FIFO Threshold Register + pub const IC_TX_TL = @intToPtr(*volatile Mmio(32, packed struct { + /// Transmit FIFO Threshold Level.\n\n + /// Controls the level of entries (or below) that trigger the TX_EMPTY interrupt + /// (bit 4 in IC_RAW_INTR_STAT register). The valid range is 0-255, with the + /// additional restriction that it may not be set to value larger than the depth of + /// the buffer. If an attempt is made to do that, the actual value set will be the + /// maximum depth of the buffer. A value of 0 sets the threshold for 0 entries, and + /// a value of 255 sets the threshold for 255 entries. + TX_TL: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x3c); + + /// address: 0x40048040 + /// Clear Combined and Individual Interrupt Register + pub const IC_CLR_INTR = @intToPtr(*volatile Mmio(32, packed struct { + /// Read this register to clear the combined interrupt, all individual interrupts, + /// and the IC_TX_ABRT_SOURCE register. This bit does not clear hardware clearable + /// interrupts but software clearable interrupts. Refer to Bit 9 of the + /// IC_TX_ABRT_SOURCE register for an exception to clearing IC_TX_ABRT_SOURCE.\n\n + /// Reset value: 0x0 + CLR_INTR: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x40); + + /// address: 0x40048044 + /// Clear RX_UNDER Interrupt Register + pub const IC_CLR_RX_UNDER = @intToPtr(*volatile Mmio(32, packed struct { + /// Read this register to clear the RX_UNDER interrupt (bit 0) of the + /// IC_RAW_INTR_STAT register.\n\n + /// Reset value: 0x0 + CLR_RX_UNDER: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x44); + + /// address: 0x40048048 + /// Clear RX_OVER Interrupt Register + pub const IC_CLR_RX_OVER = @intToPtr(*volatile Mmio(32, packed struct { + /// Read this register to clear the RX_OVER interrupt (bit 1) of the + /// IC_RAW_INTR_STAT register.\n\n + /// Reset value: 0x0 + CLR_RX_OVER: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x48); + + /// address: 0x4004804c + /// Clear TX_OVER Interrupt Register + pub const IC_CLR_TX_OVER = @intToPtr(*volatile Mmio(32, packed struct { + /// Read this register to clear the TX_OVER interrupt (bit 3) of the + /// IC_RAW_INTR_STAT register.\n\n + /// Reset value: 0x0 + CLR_TX_OVER: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x4c); + + /// address: 0x40048050 + /// Clear RD_REQ Interrupt Register + pub const IC_CLR_RD_REQ = @intToPtr(*volatile Mmio(32, packed struct { + /// Read this register to clear the RD_REQ interrupt (bit 5) of the IC_RAW_INTR_STAT + /// register.\n\n + /// Reset value: 0x0 + CLR_RD_REQ: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x50); + + /// address: 0x40048054 + /// Clear TX_ABRT Interrupt Register + pub const IC_CLR_TX_ABRT = @intToPtr(*volatile Mmio(32, packed struct { + /// Read this register to clear the TX_ABRT interrupt (bit 6) of the + /// IC_RAW_INTR_STAT register, and the IC_TX_ABRT_SOURCE register. This also + /// releases the TX FIFO from the flushed/reset state, allowing more writes to the + /// TX FIFO. Refer to Bit 9 of the IC_TX_ABRT_SOURCE register for an exception to + /// clearing IC_TX_ABRT_SOURCE.\n\n + /// Reset value: 0x0 + CLR_TX_ABRT: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x54); + + /// address: 0x40048058 + /// Clear RX_DONE Interrupt Register + pub const IC_CLR_RX_DONE = @intToPtr(*volatile Mmio(32, packed struct { + /// Read this register to clear the RX_DONE interrupt (bit 7) of the + /// IC_RAW_INTR_STAT register.\n\n + /// Reset value: 0x0 + CLR_RX_DONE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x58); + + /// address: 0x4004805c + /// Clear ACTIVITY Interrupt Register + pub const IC_CLR_ACTIVITY = @intToPtr(*volatile Mmio(32, packed struct { + /// Reading this register clears the ACTIVITY interrupt if the I2C is not active + /// anymore. If the I2C module is still active on the bus, the ACTIVITY interrupt + /// bit continues to be set. It is automatically cleared by hardware if the module + /// is disabled and if there is no further activity on the bus. The value read from + /// this register to get status of the ACTIVITY interrupt (bit 8) of the + /// IC_RAW_INTR_STAT register.\n\n + /// Reset value: 0x0 + CLR_ACTIVITY: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x5c); + + /// address: 0x40048060 + /// Clear STOP_DET Interrupt Register + pub const IC_CLR_STOP_DET = @intToPtr(*volatile Mmio(32, packed struct { + /// Read this register to clear the STOP_DET interrupt (bit 9) of the + /// IC_RAW_INTR_STAT register.\n\n + /// Reset value: 0x0 + CLR_STOP_DET: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x60); + + /// address: 0x40048064 + /// Clear START_DET Interrupt Register + pub const IC_CLR_START_DET = @intToPtr(*volatile Mmio(32, packed struct { + /// Read this register to clear the START_DET interrupt (bit 10) of the + /// IC_RAW_INTR_STAT register.\n\n + /// Reset value: 0x0 + CLR_START_DET: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x64); + + /// address: 0x40048068 + /// Clear GEN_CALL Interrupt Register + pub const IC_CLR_GEN_CALL = @intToPtr(*volatile Mmio(32, packed struct { + /// Read this register to clear the GEN_CALL interrupt (bit 11) of IC_RAW_INTR_STAT + /// register.\n\n + /// Reset value: 0x0 + CLR_GEN_CALL: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x68); + + /// address: 0x4004806c + /// I2C Enable Register + pub const IC_ENABLE = @intToPtr(*volatile Mmio(32, packed struct { + /// Controls whether the DW_apb_i2c is enabled. - 0: Disables DW_apb_i2c (TX and RX + /// FIFOs are held in an erased state) - 1: Enables DW_apb_i2c Software can disable + /// DW_apb_i2c while it is active. However, it is important that care be taken to + /// ensure that DW_apb_i2c is disabled properly. A recommended procedure is + /// described in 'Disabling DW_apb_i2c'.\n\n + /// When DW_apb_i2c is disabled, the following occurs: - The TX FIFO and RX FIFO get + /// flushed. - Status bits in the IC_INTR_STAT register are still active until + /// DW_apb_i2c goes into IDLE state. If the module is transmitting, it stops as well + /// as deletes the contents of the transmit buffer after the current transfer is + /// complete. If the module is receiving, the DW_apb_i2c stops the current transfer + /// at the end of the current byte and does not acknowledge the transfer.\n\n + /// In systems with asynchronous pclk and ic_clk when IC_CLK_TYPE parameter set to + /// asynchronous (1), there is a two ic_clk delay when enabling or disabling the + /// DW_apb_i2c. For a detailed description on how to disable DW_apb_i2c, refer to + /// 'Disabling DW_apb_i2c'\n\n + /// Reset value: 0x0 + ENABLE: u1, + /// When set, the controller initiates the transfer abort. - 0: ABORT not initiated + /// or ABORT done - 1: ABORT operation in progress The software can abort the I2C + /// transfer in master mode by setting this bit. The software can set this bit only + /// when ENABLE is already set; otherwise, the controller ignores any write to ABORT + /// bit. The software cannot clear the ABORT bit once set. In response to an ABORT, + /// the controller issues a STOP and flushes the Tx FIFO after completing the + /// current transfer, then sets the TX_ABORT interrupt after the abort operation. + /// The ABORT bit is cleared automatically after the abort operation.\n\n + /// For a detailed description on how to abort I2C transfers, refer to 'Aborting I2C + /// Transfers'.\n\n + /// Reset value: 0x0 + ABORT: u1, + /// In Master mode: - 1'b1: Blocks the transmission of data on I2C bus even if Tx + /// FIFO has data to transmit. - 1'b0: The transmission of data starts on I2C bus + /// automatically, as soon as the first data is available in the Tx FIFO. Note: To + /// block the execution of Master commands, set the TX_CMD_BLOCK bit only when Tx + /// FIFO is empty (IC_STATUS[2]==1) and Master is in Idle state (IC_STATUS[5] == 0). + /// Any further commands put in the Tx FIFO are not executed until TX_CMD_BLOCK bit + /// is unset. Reset value: IC_TX_CMD_BLOCK_DEFAULT + TX_CMD_BLOCK: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + }), base_address + 0x6c); + + /// address: 0x40048070 + /// I2C Status Register\n\n + /// This is a read-only register used to indicate the current transfer status and + /// FIFO status. The status register may be read at any time. None of the bits in + /// this register request an interrupt.\n\n + /// When the I2C is disabled by writing 0 in bit 0 of the IC_ENABLE register: - Bits + /// 1 and 2 are set to 1 - Bits 3 and 10 are set to 0 When the master or slave state + /// machines goes to idle and ic_en=0: - Bits 5 and 6 are set to 0 + pub const IC_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + /// I2C Activity Status. Reset value: 0x0 + ACTIVITY: u1, + /// Transmit FIFO Not Full. Set when the transmit FIFO contains one or more empty + /// locations, and is cleared when the FIFO is full. - 0: Transmit FIFO is full - 1: + /// Transmit FIFO is not full Reset value: 0x1 + TFNF: u1, + /// Transmit FIFO Completely Empty. When the transmit FIFO is completely empty, this + /// bit is set. When it contains one or more valid entries, this bit is cleared. + /// This bit field does not request an interrupt. - 0: Transmit FIFO is not empty - + /// 1: Transmit FIFO is empty Reset value: 0x1 + TFE: u1, + /// Receive FIFO Not Empty. This bit is set when the receive FIFO contains one or + /// more entries; it is cleared when the receive FIFO is empty. - 0: Receive FIFO is + /// empty - 1: Receive FIFO is not empty Reset value: 0x0 + RFNE: u1, + /// Receive FIFO Completely Full. When the receive FIFO is completely full, this bit + /// is set. When the receive FIFO contains one or more empty location, this bit is + /// cleared. - 0: Receive FIFO is not full - 1: Receive FIFO is full Reset value: + /// 0x0 + RFF: u1, + /// Master FSM Activity Status. When the Master Finite State Machine (FSM) is not in + /// the IDLE state, this bit is set. - 0: Master FSM is in IDLE state so the Master + /// part of DW_apb_i2c is not Active - 1: Master FSM is not in IDLE state so the + /// Master part of DW_apb_i2c is Active Note: IC_STATUS[0]-that is, ACTIVITY bit-is + /// the OR of SLV_ACTIVITY and MST_ACTIVITY bits.\n\n + /// Reset value: 0x0 + MST_ACTIVITY: u1, + /// Slave FSM Activity Status. When the Slave Finite State Machine (FSM) is not in + /// the IDLE state, this bit is set. - 0: Slave FSM is in IDLE state so the Slave + /// part of DW_apb_i2c is not Active - 1: Slave FSM is not in IDLE state so the + /// Slave part of DW_apb_i2c is Active Reset value: 0x0 + SLV_ACTIVITY: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + }), base_address + 0x70); + + /// address: 0x40048074 + /// I2C Transmit FIFO Level Register This register contains the number of valid data + /// entries in the transmit FIFO buffer. It is cleared whenever: - The I2C is + /// disabled - There is a transmit abort - that is, TX_ABRT bit is set in the + /// IC_RAW_INTR_STAT register - The slave bulk transmit mode is aborted The register + /// increments whenever data is placed into the transmit FIFO and decrements when + /// data is taken from the transmit FIFO. + pub const IC_TXFLR = @intToPtr(*volatile Mmio(32, packed struct { + /// Transmit FIFO Level. Contains the number of valid data entries in the transmit + /// FIFO.\n\n + /// Reset value: 0x0 + TXFLR: u5, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + }), base_address + 0x74); + + /// address: 0x40048078 + /// I2C Receive FIFO Level Register This register contains the number of valid data + /// entries in the receive FIFO buffer. It is cleared whenever: - The I2C is + /// disabled - Whenever there is a transmit abort caused by any of the events + /// tracked in IC_TX_ABRT_SOURCE The register increments whenever data is placed + /// into the receive FIFO and decrements when data is taken from the receive FIFO. + pub const IC_RXFLR = @intToPtr(*volatile Mmio(32, packed struct { + /// Receive FIFO Level. Contains the number of valid data entries in the receive + /// FIFO.\n\n + /// Reset value: 0x0 + RXFLR: u5, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + }), base_address + 0x78); + + /// address: 0x4004807c + /// I2C SDA Hold Time Length Register\n\n + /// The bits [15:0] of this register are used to control the hold time of SDA during + /// transmit in both slave and master mode (after SCL goes from HIGH to LOW).\n\n + /// The bits [23:16] of this register are used to extend the SDA transition (if any) + /// whenever SCL is HIGH in the receiver in either master or slave mode.\n\n + /// Writes to this register succeed only when IC_ENABLE[0]=0.\n\n + /// The values in this register are in units of ic_clk period. The value programmed + /// in IC_SDA_TX_HOLD must be greater than the minimum hold time in each mode (one + /// cycle in master mode, seven cycles in slave mode) for the value to be + /// implemented.\n\n + /// The programmed SDA hold time during transmit (IC_SDA_TX_HOLD) cannot exceed at + /// any time the duration of the low part of scl. Therefore the programmed value + /// cannot be larger than N_SCL_LOW-2, where N_SCL_LOW is the duration of the low + /// part of the scl period measured in ic_clk cycles. + pub const IC_SDA_HOLD = @intToPtr(*volatile Mmio(32, packed struct { + /// Sets the required SDA hold time in units of ic_clk period, when DW_apb_i2c acts + /// as a transmitter.\n\n + /// Reset value: IC_DEFAULT_SDA_HOLD[15:0]. + IC_SDA_TX_HOLD: u16, + /// Sets the required SDA hold time in units of ic_clk period, when DW_apb_i2c acts + /// as a receiver.\n\n + /// Reset value: IC_DEFAULT_SDA_HOLD[23:16]. + IC_SDA_RX_HOLD: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x7c); + + /// address: 0x40048080 + /// I2C Transmit Abort Source Register\n\n + /// This register has 32 bits that indicate the source of the TX_ABRT bit. Except + /// for Bit 9, this register is cleared whenever the IC_CLR_TX_ABRT register or the + /// IC_CLR_INTR register is read. To clear Bit 9, the source of the + /// ABRT_SBYTE_NORSTRT must be fixed first; RESTART must be enabled (IC_CON[5]=1), + /// the SPECIAL bit must be cleared (IC_TAR[11]), or the GC_OR_START bit must be + /// cleared (IC_TAR[10]).\n\n + /// Once the source of the ABRT_SBYTE_NORSTRT is fixed, then this bit can be cleared + /// in the same manner as other bits in this register. If the source of the + /// ABRT_SBYTE_NORSTRT is not fixed before attempting to clear this bit, Bit 9 + /// clears for one cycle and is then re-asserted. + pub const IC_TX_ABRT_SOURCE = @intToPtr(*volatile Mmio(32, packed struct { + /// This field indicates that the Master is in 7-bit addressing mode and the address + /// sent was not acknowledged by any slave.\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + ABRT_7B_ADDR_NOACK: u1, + /// This field indicates that the Master is in 10-bit address mode and the first + /// 10-bit address byte was not acknowledged by any slave.\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + ABRT_10ADDR1_NOACK: u1, + /// This field indicates that the Master is in 10-bit address mode and that the + /// second address byte of the 10-bit address was not acknowledged by any slave.\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + ABRT_10ADDR2_NOACK: u1, + /// This field indicates the master-mode only bit. When the master receives an + /// acknowledgement for the address, but when it sends data byte(s) following the + /// address, it did not receive an acknowledge from the remote slave(s).\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master-Transmitter + ABRT_TXDATA_NOACK: u1, + /// This field indicates that DW_apb_i2c in master mode has sent a General Call and + /// no slave on the bus acknowledged the General Call.\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master-Transmitter + ABRT_GCALL_NOACK: u1, + /// This field indicates that DW_apb_i2c in the master mode has sent a General Call + /// but the user programmed the byte following the General Call to be a read from + /// the bus (IC_DATA_CMD[9] is set to 1).\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master-Transmitter + ABRT_GCALL_READ: u1, + /// This field indicates that the Master is in High Speed mode and the High Speed + /// Master code was acknowledged (wrong behavior).\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master + ABRT_HS_ACKDET: u1, + /// This field indicates that the Master has sent a START Byte and the START Byte + /// was acknowledged (wrong behavior).\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master + ABRT_SBYTE_ACKDET: u1, + /// This field indicates that the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) + /// =0) and the user is trying to use the master to transfer data in High Speed + /// mode.\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + ABRT_HS_NORSTRT: u1, + /// To clear Bit 9, the source of the ABRT_SBYTE_NORSTRT must be fixed first; + /// restart must be enabled (IC_CON[5]=1), the SPECIAL bit must be cleared + /// (IC_TAR[11]), or the GC_OR_START bit must be cleared (IC_TAR[10]). Once the + /// source of the ABRT_SBYTE_NORSTRT is fixed, then this bit can be cleared in the + /// same manner as other bits in this register. If the source of the + /// ABRT_SBYTE_NORSTRT is not fixed before attempting to clear this bit, bit 9 + /// clears for one cycle and then gets reasserted. When this field is set to 1, the + /// restart is disabled (IC_RESTART_EN bit (IC_CON[5]) =0) and the user is trying to + /// send a START Byte.\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master + ABRT_SBYTE_NORSTRT: u1, + /// This field indicates that the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) + /// =0) and the master sends a read command in 10-bit addressing mode.\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master-Receiver + ABRT_10B_RD_NORSTRT: u1, + /// This field indicates that the User tries to initiate a Master operation with the + /// Master mode disabled.\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + ABRT_MASTER_DIS: u1, + /// This field specifies that the Master has lost arbitration, or if + /// IC_TX_ABRT_SOURCE[14] is also set, then the slave transmitter has lost + /// arbitration.\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master-Transmitter or Slave-Transmitter + ARB_LOST: u1, + /// This field specifies that the Slave has received a read command and some data + /// exists in the TX FIFO, so the slave issues a TX_ABRT interrupt to flush old data + /// in TX FIFO.\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Slave-Transmitter + ABRT_SLVFLUSH_TXFIFO: u1, + /// This field indicates that a Slave has lost the bus while transmitting data to a + /// remote master. IC_TX_ABRT_SOURCE[12] is set at the same time. Note: Even though + /// the slave never 'owns' the bus, something could go wrong on the bus. This is a + /// fail safe check. For instance, during a data transmission at the low-to-high + /// transition of SCL, if what is on the data bus is not what is supposed to be + /// transmitted, then DW_apb_i2c no longer own the bus.\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Slave-Transmitter + ABRT_SLV_ARBLOST: u1, + /// 1: When the processor side responds to a slave mode request for data to be + /// transmitted to a remote master and user writes a 1 in CMD (bit 8) of IC_DATA_CMD + /// register.\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Slave-Transmitter + ABRT_SLVRD_INTX: u1, + /// This is a master-mode-only bit. Master has detected the transfer abort + /// (IC_ENABLE[1])\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master-Transmitter + ABRT_USER_ABRT: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + /// This field indicates the number of Tx FIFO Data Commands which are flushed due + /// to TX_ABRT interrupt. It is cleared whenever I2C is disabled.\n\n + /// Reset value: 0x0\n\n + /// Role of DW_apb_i2c: Master-Transmitter or Slave-Transmitter + TX_FLUSH_CNT: u9, + }), base_address + 0x80); + + /// address: 0x40048084 + /// Generate Slave Data NACK Register\n\n + /// The register is used to generate a NACK for the data part of a transfer when + /// DW_apb_i2c is acting as a slave-receiver. This register only exists when the + /// IC_SLV_DATA_NACK_ONLY parameter is set to 1. When this parameter disabled, this + /// register does not exist and writing to the register's address has no effect.\n\n + /// A write can occur on this register if both of the following conditions are met: + /// - DW_apb_i2c is disabled (IC_ENABLE[0] = 0) - Slave part is inactive + /// (IC_STATUS[6] = 0) Note: The IC_STATUS[6] is a register read-back location for + /// the internal slv_activity signal; the user should poll this before writing the + /// ic_slv_data_nack_only bit. + pub const IC_SLV_DATA_NACK_ONLY = @intToPtr(*volatile Mmio(32, packed struct { + /// Generate NACK. This NACK generation only occurs when DW_apb_i2c is a + /// slave-receiver. If this register is set to a value of 1, it can only generate a + /// NACK after a data byte is received; hence, the data transfer is aborted and the + /// data received is not pushed to the receive buffer.\n\n + /// When the register is set to a value of 0, it generates NACK/ACK, depending on + /// normal criteria. - 1: generate NACK after data byte received - 0: generate + /// NACK/ACK normally Reset value: 0x0 + NACK: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x84); + + /// address: 0x40048088 + /// DMA Control Register\n\n + /// The register is used to enable the DMA Controller interface operation. There is + /// a separate bit for transmit and receive. This can be programmed regardless of + /// the state of IC_ENABLE. + pub const IC_DMA_CR = @intToPtr(*volatile Mmio(32, packed struct { + /// Receive DMA Enable. This bit enables/disables the receive FIFO DMA channel. + /// Reset value: 0x0 + RDMAE: u1, + /// Transmit DMA Enable. This bit enables/disables the transmit FIFO DMA channel. + /// Reset value: 0x0 + TDMAE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + }), base_address + 0x88); + + /// address: 0x4004808c + /// DMA Transmit Data Level Register + pub const IC_DMA_TDLR = @intToPtr(*volatile Mmio(32, packed struct { + /// Transmit Data Level. This bit field controls the level at which a DMA request is + /// made by the transmit logic. It is equal to the watermark level; that is, the + /// dma_tx_req signal is generated when the number of valid data entries in the + /// transmit FIFO is equal to or below this field value, and TDMAE = 1.\n\n + /// Reset value: 0x0 + DMATDL: u4, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + }), base_address + 0x8c); + + /// address: 0x40048090 + /// I2C Receive Data Level Register + pub const IC_DMA_RDLR = @intToPtr(*volatile Mmio(32, packed struct { + /// Receive Data Level. This bit field controls the level at which a DMA request is + /// made by the receive logic. The watermark level = DMARDL+1; that is, dma_rx_req + /// is generated when the number of valid data entries in the receive FIFO is equal + /// to or more than this field value + 1, and RDMAE =1. For instance, when DMARDL is + /// 0, then dma_rx_req is asserted when 1 or more data entries are present in the + /// receive FIFO.\n\n + /// Reset value: 0x0 + DMARDL: u4, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + }), base_address + 0x90); + + /// address: 0x40048094 + /// I2C SDA Setup Register\n\n + /// This register controls the amount of time delay (in terms of number of ic_clk + /// clock periods) introduced in the rising edge of SCL - relative to SDA changing - + /// when DW_apb_i2c services a read request in a slave-transmitter operation. The + /// relevant I2C requirement is tSU:DAT (note 4) as detailed in the I2C Bus + /// Specification. This register must be programmed with a value equal to or greater + /// than 2.\n\n + /// Writes to this register succeed only when IC_ENABLE[0] = 0.\n\n + /// Note: The length of setup time is calculated using [(IC_SDA_SETUP - 1) * + /// (ic_clk_period)], so if the user requires 10 ic_clk periods of setup time, they + /// should program a value of 11. The IC_SDA_SETUP register is only used by the + /// DW_apb_i2c when operating as a slave transmitter. + pub const IC_SDA_SETUP = @intToPtr(*volatile Mmio(32, packed struct { + /// SDA Setup. It is recommended that if the required delay is 1000ns, then for an + /// ic_clk frequency of 10 MHz, IC_SDA_SETUP should be programmed to a value of 11. + /// IC_SDA_SETUP must be programmed with a minimum value of 2. + SDA_SETUP: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x94); + + /// address: 0x40048098 + /// I2C ACK General Call Register\n\n + /// The register controls whether DW_apb_i2c responds with a ACK or NACK when it + /// receives an I2C General Call address.\n\n + /// This register is applicable only when the DW_apb_i2c is in slave mode. + pub const IC_ACK_GENERAL_CALL = @intToPtr(*volatile Mmio(32, packed struct { + /// ACK General Call. When set to 1, DW_apb_i2c responds with a ACK (by asserting + /// ic_data_oe) when it receives a General Call. Otherwise, DW_apb_i2c responds with + /// a NACK (by negating ic_data_oe). + ACK_GEN_CALL: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x98); + + /// address: 0x4004809c + /// I2C Enable Status Register\n\n + /// The register is used to report the DW_apb_i2c hardware status when the + /// IC_ENABLE[0] register is set from 1 to 0; that is, when DW_apb_i2c is + /// disabled.\n\n + /// If IC_ENABLE[0] has been set to 1, bits 2:1 are forced to 0, and bit 0 is forced + /// to 1.\n\n + /// If IC_ENABLE[0] has been set to 0, bits 2:1 is only be valid as soon as bit 0 is + /// read as '0'.\n\n + /// Note: When IC_ENABLE[0] has been set to 0, a delay occurs for bit 0 to be read + /// as 0 because disabling the DW_apb_i2c depends on I2C bus activities. + pub const IC_ENABLE_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + /// ic_en Status. This bit always reflects the value driven on the output port + /// ic_en. - When read as 1, DW_apb_i2c is deemed to be in an enabled state. - When + /// read as 0, DW_apb_i2c is deemed completely inactive. Note: The CPU can safely + /// read this bit anytime. When this bit is read as 0, the CPU can safely read + /// SLV_RX_DATA_LOST (bit 2) and SLV_DISABLED_WHILE_BUSY (bit 1).\n\n + /// Reset value: 0x0 + IC_EN: u1, + /// Slave Disabled While Busy (Transmit, Receive). This bit indicates if a potential + /// or active Slave operation has been aborted due to the setting bit 0 of the + /// IC_ENABLE register from 1 to 0. This bit is set when the CPU writes a 0 to the + /// IC_ENABLE register while:\n\n + /// (a) DW_apb_i2c is receiving the address byte of the Slave-Transmitter operation + /// from a remote master;\n\n + /// OR,\n\n + /// (b) address and data bytes of the Slave-Receiver operation from a remote + /// master.\n\n + /// When read as 1, DW_apb_i2c is deemed to have forced a NACK during any part of an + /// I2C transfer, irrespective of whether the I2C address matches the slave address + /// set in DW_apb_i2c (IC_SAR register) OR if the transfer is completed before + /// IC_ENABLE is set to 0 but has not taken effect.\n\n + /// Note: If the remote I2C master terminates the transfer with a STOP condition + /// before the DW_apb_i2c has a chance to NACK a transfer, and IC_ENABLE[0] has been + /// set to 0, then this bit will also be set to 1.\n\n + /// When read as 0, DW_apb_i2c is deemed to have been disabled when there is master + /// activity, or when the I2C bus is idle.\n\n + /// Note: The CPU can safely read this bit when IC_EN (bit 0) is read as 0.\n\n + /// Reset value: 0x0 + SLV_DISABLED_WHILE_BUSY: u1, + /// Slave Received Data Lost. This bit indicates if a Slave-Receiver operation has + /// been aborted with at least one data byte received from an I2C transfer due to + /// the setting bit 0 of IC_ENABLE from 1 to 0. When read as 1, DW_apb_i2c is deemed + /// to have been actively engaged in an aborted I2C transfer (with matching address) + /// and the data phase of the I2C transfer has been entered, even though a data byte + /// has been responded with a NACK.\n\n + /// Note: If the remote I2C master terminates the transfer with a STOP condition + /// before the DW_apb_i2c has a chance to NACK a transfer, and IC_ENABLE[0] has been + /// set to 0, then this bit is also set to 1.\n\n + /// When read as 0, DW_apb_i2c is deemed to have been disabled without being + /// actively involved in the data phase of a Slave-Receiver transfer.\n\n + /// Note: The CPU can safely read this bit when IC_EN (bit 0) is read as 0.\n\n + /// Reset value: 0x0 + SLV_RX_DATA_LOST: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + }), base_address + 0x9c); + + /// address: 0x400480a0 + /// I2C SS, FS or FM+ spike suppression limit\n\n + /// This register is used to store the duration, measured in ic_clk cycles, of the + /// longest spike that is filtered out by the spike suppression logic when the + /// component is operating in SS, FS or FM+ modes. The relevant I2C requirement is + /// tSP (table 4) as detailed in the I2C Bus Specification. This register must be + /// programmed with a minimum value of 1. + pub const IC_FS_SPKLEN = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xa0); + + /// address: 0x400480a8 + /// Clear RESTART_DET Interrupt Register + pub const IC_CLR_RESTART_DET = @intToPtr(*volatile Mmio(32, packed struct { + /// Read this register to clear the RESTART_DET interrupt (bit 12) of + /// IC_RAW_INTR_STAT register.\n\n + /// Reset value: 0x0 + CLR_RESTART_DET: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0xa8); + + /// address: 0x400480f4 + /// Component Parameter Register 1\n\n + /// Note This register is not implemented and therefore reads as 0. If it was + /// implemented it would be a constant read-only register that contains encoded + /// information about the component's parameter settings. Fields shown below are the + /// settings for those parameters + pub const IC_COMP_PARAM_1 = @intToPtr(*volatile Mmio(32, packed struct { + /// APB data bus width is 32 bits + APB_DATA_WIDTH: u2, + /// MAX SPEED MODE = FAST MODE + MAX_SPEED_MODE: u2, + /// Programmable count values for each mode. + HC_COUNT_VALUES: u1, + /// COMBINED Interrupt outputs + INTR_IO: u1, + /// DMA handshaking signals are enabled + HAS_DMA: u1, + /// Encoded parameters not visible + ADD_ENCODED_PARAMS: u1, + /// RX Buffer Depth = 16 + RX_BUFFER_DEPTH: u8, + /// TX Buffer Depth = 16 + TX_BUFFER_DEPTH: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0xf4); + + /// address: 0x400480f8 + /// I2C Component Version Register + pub const IC_COMP_VERSION = @intToPtr(*volatile u32, base_address + 0xf8); + + /// address: 0x400480fc + /// I2C Component Type Register + pub const IC_COMP_TYPE = @intToPtr(*volatile u32, base_address + 0xfc); + }; + + /// Control and data interface to SAR ADC + pub const ADC = struct { + pub const base_address = 0x4004c000; + pub const version = "2"; + + /// address: 0x4004c000 + /// ADC Control and Status + pub const CS = @intToPtr(*volatile Mmio(32, packed struct { + /// Power on ADC and enable its clock.\n + /// 1 - enabled. 0 - disabled. + EN: u1, + /// Power on temperature sensor. 1 - enabled. 0 - disabled. + TS_EN: u1, + /// Start a single conversion. Self-clearing. Ignored if start_many is asserted. + START_ONCE: u1, + /// Continuously perform conversions whilst this bit is 1. A new conversion will + /// start immediately after the previous finishes. + START_MANY: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + /// 1 if the ADC is ready to start a new conversion. Implies any previous conversion + /// has completed.\n + /// 0 whilst conversion in progress. + READY: u1, + /// The most recent ADC conversion encountered an error; result is undefined or + /// noisy. + ERR: u1, + /// Some past ADC conversion encountered an error. Write 1 to clear. + ERR_STICKY: u1, + reserved4: u1 = 0, + /// Select analog mux input. Updated automatically in round-robin mode. + AINSEL: u3, + reserved5: u1 = 0, + /// Round-robin sampling. 1 bit per channel. Set all bits to 0 to disable.\n + /// Otherwise, the ADC will cycle through each enabled channel in a round-robin + /// fashion.\n + /// The first channel to be sampled will be the one currently indicated by AINSEL.\n + /// AINSEL will be updated after each conversion with the newly-selected channel. + RROBIN: u5, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + }), base_address + 0x0); + + /// address: 0x4004c004 + /// Result of most recent ADC conversion + pub const RESULT = @intToPtr(*volatile MmioInt(32, u12), base_address + 0x4); + + /// address: 0x4004c008 + /// FIFO control and status + pub const FCS = @intToPtr(*volatile Mmio(32, packed struct { + /// If 1: write result to the FIFO after each conversion. + EN: u1, + /// If 1: FIFO results are right-shifted to be one byte in size. Enables DMA to byte + /// buffers. + SHIFT: u1, + /// If 1: conversion error bit appears in the FIFO alongside the result + ERR: u1, + /// If 1: assert DMA requests when FIFO contains data + DREQ_EN: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + EMPTY: u1, + FULL: u1, + /// 1 if the FIFO has been underflowed. Write 1 to clear. + UNDER: u1, + /// 1 if the FIFO has been overflowed. Write 1 to clear. + OVER: u1, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// The number of conversion results currently waiting in the FIFO + LEVEL: u4, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + /// DREQ/IRQ asserted when level >= threshold + THRESH: u4, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + }), base_address + 0x8); + + /// address: 0x4004c00c + /// Conversion result FIFO + pub const FIFO = @intToPtr(*volatile Mmio(32, packed struct { + VAL: u12, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + /// 1 if this particular sample experienced a conversion error. Remains in the same + /// location if the sample is shifted. + ERR: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + }), base_address + 0xc); + + /// address: 0x4004c010 + /// Clock divider. If non-zero, CS_START_MANY will start conversions\n + /// at regular intervals rather than back-to-back.\n + /// The divider is reset when either of these fields are written.\n + /// Total period is 1 + INT + FRAC / 256 + pub const DIV = @intToPtr(*volatile Mmio(32, packed struct { + /// Fractional part of clock divisor. First-order delta-sigma. + FRAC: u8, + /// Integer part of clock divisor. + INT: u16, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x10); + + /// address: 0x4004c014 + /// Raw Interrupts + pub const INTR = @intToPtr(*volatile Mmio(32, packed struct { + /// Triggered when the sample FIFO reaches a certain level.\n + /// This level can be programmed via the FCS_THRESH field. + FIFO: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x14); + + /// address: 0x4004c018 + /// Interrupt Enable + pub const INTE = @intToPtr(*volatile Mmio(32, packed struct { + /// Triggered when the sample FIFO reaches a certain level.\n + /// This level can be programmed via the FCS_THRESH field. + FIFO: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x18); + + /// address: 0x4004c01c + /// Interrupt Force + pub const INTF = @intToPtr(*volatile Mmio(32, packed struct { + /// Triggered when the sample FIFO reaches a certain level.\n + /// This level can be programmed via the FCS_THRESH field. + FIFO: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x1c); + + /// address: 0x4004c020 + /// Interrupt status after masking & forcing + pub const INTS = @intToPtr(*volatile Mmio(32, packed struct { + /// Triggered when the sample FIFO reaches a certain level.\n + /// This level can be programmed via the FCS_THRESH field. + FIFO: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x20); + }; + + /// Simple PWM + pub const PWM = struct { + pub const base_address = 0x40050000; + pub const version = "1"; + + /// address: 0x40050000 + /// Control and status register + pub const CH0_CSR = @intToPtr(*volatile Mmio(32, packed struct { + /// Enable the PWM channel. + EN: u1, + /// 1: Enable phase-correct modulation. 0: Trailing-edge + PH_CORRECT: u1, + /// Invert output A + A_INV: u1, + /// Invert output B + B_INV: u1, + DIVMODE: u2, + /// Retard the phase of the counter by 1 count, while it is running.\n + /// Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_RET: u1, + /// Advance the phase of the counter by 1 count, while it is running.\n + /// Self-clearing. Write a 1, and poll until low. Counter must be running\n + /// at less than full speed (div_int + div_frac / 16 > 1) + PH_ADV: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x0); + + /// address: 0x40050004 + /// INT and FRAC form a fixed-point fractional number.\n + /// Counting rate is system clock frequency divided by this number.\n + /// Fractional division uses simple 1st-order sigma-delta. + pub const CH0_DIV = @intToPtr(*volatile Mmio(32, packed struct { + FRAC: u4, + INT: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x4); + + /// address: 0x40050008 + /// Direct access to the PWM counter + pub const CH0_CTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x8); + + /// address: 0x4005000c + /// Counter compare values + pub const CH0_CC = @intToPtr(*volatile Mmio(32, packed struct { + A: u16, + B: u16, + }), base_address + 0xc); + + /// address: 0x40050010 + /// Counter wrap value + pub const CH0_TOP = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x10); + + /// address: 0x40050014 + /// Control and status register + pub const CH1_CSR = @intToPtr(*volatile Mmio(32, packed struct { + /// Enable the PWM channel. + EN: u1, + /// 1: Enable phase-correct modulation. 0: Trailing-edge + PH_CORRECT: u1, + /// Invert output A + A_INV: u1, + /// Invert output B + B_INV: u1, + DIVMODE: u2, + /// Retard the phase of the counter by 1 count, while it is running.\n + /// Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_RET: u1, + /// Advance the phase of the counter by 1 count, while it is running.\n + /// Self-clearing. Write a 1, and poll until low. Counter must be running\n + /// at less than full speed (div_int + div_frac / 16 > 1) + PH_ADV: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x14); + + /// address: 0x40050018 + /// INT and FRAC form a fixed-point fractional number.\n + /// Counting rate is system clock frequency divided by this number.\n + /// Fractional division uses simple 1st-order sigma-delta. + pub const CH1_DIV = @intToPtr(*volatile Mmio(32, packed struct { + FRAC: u4, + INT: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x18); + + /// address: 0x4005001c + /// Direct access to the PWM counter + pub const CH1_CTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x1c); + + /// address: 0x40050020 + /// Counter compare values + pub const CH1_CC = @intToPtr(*volatile Mmio(32, packed struct { + A: u16, + B: u16, + }), base_address + 0x20); + + /// address: 0x40050024 + /// Counter wrap value + pub const CH1_TOP = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x24); + + /// address: 0x40050028 + /// Control and status register + pub const CH2_CSR = @intToPtr(*volatile Mmio(32, packed struct { + /// Enable the PWM channel. + EN: u1, + /// 1: Enable phase-correct modulation. 0: Trailing-edge + PH_CORRECT: u1, + /// Invert output A + A_INV: u1, + /// Invert output B + B_INV: u1, + DIVMODE: u2, + /// Retard the phase of the counter by 1 count, while it is running.\n + /// Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_RET: u1, + /// Advance the phase of the counter by 1 count, while it is running.\n + /// Self-clearing. Write a 1, and poll until low. Counter must be running\n + /// at less than full speed (div_int + div_frac / 16 > 1) + PH_ADV: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x28); + + /// address: 0x4005002c + /// INT and FRAC form a fixed-point fractional number.\n + /// Counting rate is system clock frequency divided by this number.\n + /// Fractional division uses simple 1st-order sigma-delta. + pub const CH2_DIV = @intToPtr(*volatile Mmio(32, packed struct { + FRAC: u4, + INT: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x2c); + + /// address: 0x40050030 + /// Direct access to the PWM counter + pub const CH2_CTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x30); + + /// address: 0x40050034 + /// Counter compare values + pub const CH2_CC = @intToPtr(*volatile Mmio(32, packed struct { + A: u16, + B: u16, + }), base_address + 0x34); + + /// address: 0x40050038 + /// Counter wrap value + pub const CH2_TOP = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x38); + + /// address: 0x4005003c + /// Control and status register + pub const CH3_CSR = @intToPtr(*volatile Mmio(32, packed struct { + /// Enable the PWM channel. + EN: u1, + /// 1: Enable phase-correct modulation. 0: Trailing-edge + PH_CORRECT: u1, + /// Invert output A + A_INV: u1, + /// Invert output B + B_INV: u1, + DIVMODE: u2, + /// Retard the phase of the counter by 1 count, while it is running.\n + /// Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_RET: u1, + /// Advance the phase of the counter by 1 count, while it is running.\n + /// Self-clearing. Write a 1, and poll until low. Counter must be running\n + /// at less than full speed (div_int + div_frac / 16 > 1) + PH_ADV: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x3c); + + /// address: 0x40050040 + /// INT and FRAC form a fixed-point fractional number.\n + /// Counting rate is system clock frequency divided by this number.\n + /// Fractional division uses simple 1st-order sigma-delta. + pub const CH3_DIV = @intToPtr(*volatile Mmio(32, packed struct { + FRAC: u4, + INT: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x40); + + /// address: 0x40050044 + /// Direct access to the PWM counter + pub const CH3_CTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x44); + + /// address: 0x40050048 + /// Counter compare values + pub const CH3_CC = @intToPtr(*volatile Mmio(32, packed struct { + A: u16, + B: u16, + }), base_address + 0x48); + + /// address: 0x4005004c + /// Counter wrap value + pub const CH3_TOP = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x4c); + + /// address: 0x40050050 + /// Control and status register + pub const CH4_CSR = @intToPtr(*volatile Mmio(32, packed struct { + /// Enable the PWM channel. + EN: u1, + /// 1: Enable phase-correct modulation. 0: Trailing-edge + PH_CORRECT: u1, + /// Invert output A + A_INV: u1, + /// Invert output B + B_INV: u1, + DIVMODE: u2, + /// Retard the phase of the counter by 1 count, while it is running.\n + /// Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_RET: u1, + /// Advance the phase of the counter by 1 count, while it is running.\n + /// Self-clearing. Write a 1, and poll until low. Counter must be running\n + /// at less than full speed (div_int + div_frac / 16 > 1) + PH_ADV: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x50); + + /// address: 0x40050054 + /// INT and FRAC form a fixed-point fractional number.\n + /// Counting rate is system clock frequency divided by this number.\n + /// Fractional division uses simple 1st-order sigma-delta. + pub const CH4_DIV = @intToPtr(*volatile Mmio(32, packed struct { + FRAC: u4, + INT: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x54); + + /// address: 0x40050058 + /// Direct access to the PWM counter + pub const CH4_CTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x58); + + /// address: 0x4005005c + /// Counter compare values + pub const CH4_CC = @intToPtr(*volatile Mmio(32, packed struct { + A: u16, + B: u16, + }), base_address + 0x5c); + + /// address: 0x40050060 + /// Counter wrap value + pub const CH4_TOP = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x60); + + /// address: 0x40050064 + /// Control and status register + pub const CH5_CSR = @intToPtr(*volatile Mmio(32, packed struct { + /// Enable the PWM channel. + EN: u1, + /// 1: Enable phase-correct modulation. 0: Trailing-edge + PH_CORRECT: u1, + /// Invert output A + A_INV: u1, + /// Invert output B + B_INV: u1, + DIVMODE: u2, + /// Retard the phase of the counter by 1 count, while it is running.\n + /// Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_RET: u1, + /// Advance the phase of the counter by 1 count, while it is running.\n + /// Self-clearing. Write a 1, and poll until low. Counter must be running\n + /// at less than full speed (div_int + div_frac / 16 > 1) + PH_ADV: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x64); + + /// address: 0x40050068 + /// INT and FRAC form a fixed-point fractional number.\n + /// Counting rate is system clock frequency divided by this number.\n + /// Fractional division uses simple 1st-order sigma-delta. + pub const CH5_DIV = @intToPtr(*volatile Mmio(32, packed struct { + FRAC: u4, + INT: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x68); + + /// address: 0x4005006c + /// Direct access to the PWM counter + pub const CH5_CTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x6c); + + /// address: 0x40050070 + /// Counter compare values + pub const CH5_CC = @intToPtr(*volatile Mmio(32, packed struct { + A: u16, + B: u16, + }), base_address + 0x70); + + /// address: 0x40050074 + /// Counter wrap value + pub const CH5_TOP = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x74); + + /// address: 0x40050078 + /// Control and status register + pub const CH6_CSR = @intToPtr(*volatile Mmio(32, packed struct { + /// Enable the PWM channel. + EN: u1, + /// 1: Enable phase-correct modulation. 0: Trailing-edge + PH_CORRECT: u1, + /// Invert output A + A_INV: u1, + /// Invert output B + B_INV: u1, + DIVMODE: u2, + /// Retard the phase of the counter by 1 count, while it is running.\n + /// Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_RET: u1, + /// Advance the phase of the counter by 1 count, while it is running.\n + /// Self-clearing. Write a 1, and poll until low. Counter must be running\n + /// at less than full speed (div_int + div_frac / 16 > 1) + PH_ADV: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x78); + + /// address: 0x4005007c + /// INT and FRAC form a fixed-point fractional number.\n + /// Counting rate is system clock frequency divided by this number.\n + /// Fractional division uses simple 1st-order sigma-delta. + pub const CH6_DIV = @intToPtr(*volatile Mmio(32, packed struct { + FRAC: u4, + INT: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x7c); + + /// address: 0x40050080 + /// Direct access to the PWM counter + pub const CH6_CTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x80); + + /// address: 0x40050084 + /// Counter compare values + pub const CH6_CC = @intToPtr(*volatile Mmio(32, packed struct { + A: u16, + B: u16, + }), base_address + 0x84); + + /// address: 0x40050088 + /// Counter wrap value + pub const CH6_TOP = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x88); + + /// address: 0x4005008c + /// Control and status register + pub const CH7_CSR = @intToPtr(*volatile Mmio(32, packed struct { + /// Enable the PWM channel. + EN: u1, + /// 1: Enable phase-correct modulation. 0: Trailing-edge + PH_CORRECT: u1, + /// Invert output A + A_INV: u1, + /// Invert output B + B_INV: u1, + DIVMODE: u2, + /// Retard the phase of the counter by 1 count, while it is running.\n + /// Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_RET: u1, + /// Advance the phase of the counter by 1 count, while it is running.\n + /// Self-clearing. Write a 1, and poll until low. Counter must be running\n + /// at less than full speed (div_int + div_frac / 16 > 1) + PH_ADV: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x8c); + + /// address: 0x40050090 + /// INT and FRAC form a fixed-point fractional number.\n + /// Counting rate is system clock frequency divided by this number.\n + /// Fractional division uses simple 1st-order sigma-delta. + pub const CH7_DIV = @intToPtr(*volatile Mmio(32, packed struct { + FRAC: u4, + INT: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x90); + + /// address: 0x40050094 + /// Direct access to the PWM counter + pub const CH7_CTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x94); + + /// address: 0x40050098 + /// Counter compare values + pub const CH7_CC = @intToPtr(*volatile Mmio(32, packed struct { + A: u16, + B: u16, + }), base_address + 0x98); + + /// address: 0x4005009c + /// Counter wrap value + pub const CH7_TOP = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x9c); + + /// address: 0x400500a0 + /// This register aliases the CSR_EN bits for all channels.\n + /// Writing to this register allows multiple channels to be enabled\n + /// or disabled simultaneously, so they can run in perfect sync.\n + /// For each channel, there is only one physical EN register bit,\n + /// which can be accessed through here or CHx_CSR. + pub const EN = @intToPtr(*volatile Mmio(32, packed struct { + CH0: u1, + CH1: u1, + CH2: u1, + CH3: u1, + CH4: u1, + CH5: u1, + CH6: u1, + CH7: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0xa0); + + /// address: 0x400500a4 + /// Raw Interrupts + pub const INTR = @intToPtr(*volatile Mmio(32, packed struct { + CH0: u1, + CH1: u1, + CH2: u1, + CH3: u1, + CH4: u1, + CH5: u1, + CH6: u1, + CH7: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0xa4); + + /// address: 0x400500a8 + /// Interrupt Enable + pub const INTE = @intToPtr(*volatile Mmio(32, packed struct { + CH0: u1, + CH1: u1, + CH2: u1, + CH3: u1, + CH4: u1, + CH5: u1, + CH6: u1, + CH7: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0xa8); + + /// address: 0x400500ac + /// Interrupt Force + pub const INTF = @intToPtr(*volatile Mmio(32, packed struct { + CH0: u1, + CH1: u1, + CH2: u1, + CH3: u1, + CH4: u1, + CH5: u1, + CH6: u1, + CH7: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0xac); + + /// address: 0x400500b0 + /// Interrupt status after masking & forcing + pub const INTS = @intToPtr(*volatile Mmio(32, packed struct { + CH0: u1, + CH1: u1, + CH2: u1, + CH3: u1, + CH4: u1, + CH5: u1, + CH6: u1, + CH7: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0xb0); + }; + + /// Controls time and alarms\n + /// time is a 64 bit value indicating the time in usec since power-on\n + /// timeh is the top 32 bits of time & timel is the bottom 32 bits\n + /// to change time write to timelw before timehw\n + /// to read time read from timelr before timehr\n + /// An alarm is set by setting alarm_enable and writing to the corresponding alarm + /// register\n + /// When an alarm is pending, the corresponding alarm_running signal will be high\n + /// An alarm can be cancelled before it has finished by clearing the alarm_enable\n + /// When an alarm fires, the corresponding alarm_irq is set and alarm_running is + /// cleared\n + /// To clear the interrupt write a 1 to the corresponding alarm_irq + pub const TIMER = struct { + pub const base_address = 0x40054000; + pub const version = "1"; + + /// address: 0x40054000 + /// Write to bits 63:32 of time\n + /// always write timelw before timehw + pub const TIMEHW = @intToPtr(*volatile u32, base_address + 0x0); + + /// address: 0x40054004 + /// Write to bits 31:0 of time\n + /// writes do not get copied to time until timehw is written + pub const TIMELW = @intToPtr(*volatile u32, base_address + 0x4); + + /// address: 0x40054008 + /// Read from bits 63:32 of time\n + /// always read timelr before timehr + pub const TIMEHR = @intToPtr(*volatile u32, base_address + 0x8); + + /// address: 0x4005400c + /// Read from bits 31:0 of time + pub const TIMELR = @intToPtr(*volatile u32, base_address + 0xc); + + /// address: 0x40054010 + /// Arm alarm 0, and configure the time it will fire.\n + /// Once armed, the alarm fires when TIMER_ALARM0 == TIMELR.\n + /// The alarm will disarm itself once it fires, and can\n + /// be disarmed early using the ARMED status register. + pub const ALARM0 = @intToPtr(*volatile u32, base_address + 0x10); + + /// address: 0x40054014 + /// Arm alarm 1, and configure the time it will fire.\n + /// Once armed, the alarm fires when TIMER_ALARM1 == TIMELR.\n + /// The alarm will disarm itself once it fires, and can\n + /// be disarmed early using the ARMED status register. + pub const ALARM1 = @intToPtr(*volatile u32, base_address + 0x14); + + /// address: 0x40054018 + /// Arm alarm 2, and configure the time it will fire.\n + /// Once armed, the alarm fires when TIMER_ALARM2 == TIMELR.\n + /// The alarm will disarm itself once it fires, and can\n + /// be disarmed early using the ARMED status register. + pub const ALARM2 = @intToPtr(*volatile u32, base_address + 0x18); + + /// address: 0x4005401c + /// Arm alarm 3, and configure the time it will fire.\n + /// Once armed, the alarm fires when TIMER_ALARM3 == TIMELR.\n + /// The alarm will disarm itself once it fires, and can\n + /// be disarmed early using the ARMED status register. + pub const ALARM3 = @intToPtr(*volatile u32, base_address + 0x1c); + + /// address: 0x40054020 + /// Indicates the armed/disarmed status of each alarm.\n + /// A write to the corresponding ALARMx register arms the alarm.\n + /// Alarms automatically disarm upon firing, but writing ones here\n + /// will disarm immediately without waiting to fire. + pub const ARMED = @intToPtr(*volatile MmioInt(32, u4), base_address + 0x20); + + /// address: 0x40054024 + /// Raw read from bits 63:32 of time (no side effects) + pub const TIMERAWH = @intToPtr(*volatile u32, base_address + 0x24); + + /// address: 0x40054028 + /// Raw read from bits 31:0 of time (no side effects) + pub const TIMERAWL = @intToPtr(*volatile u32, base_address + 0x28); + + /// address: 0x4005402c + /// Set bits high to enable pause when the corresponding debug ports are active + pub const DBGPAUSE = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + /// Pause when processor 0 is in debug mode + DBG0: u1, + /// Pause when processor 1 is in debug mode + DBG1: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + }), base_address + 0x2c); + + /// address: 0x40054030 + /// Set high to pause the timer + pub const PAUSE = @intToPtr(*volatile MmioInt(32, u1), base_address + 0x30); + + /// address: 0x40054034 + /// Raw Interrupts + pub const INTR = @intToPtr(*volatile Mmio(32, packed struct { + ALARM_0: u1, + ALARM_1: u1, + ALARM_2: u1, + ALARM_3: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + }), base_address + 0x34); + + /// address: 0x40054038 + /// Interrupt Enable + pub const INTE = @intToPtr(*volatile Mmio(32, packed struct { + ALARM_0: u1, + ALARM_1: u1, + ALARM_2: u1, + ALARM_3: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + }), base_address + 0x38); + + /// address: 0x4005403c + /// Interrupt Force + pub const INTF = @intToPtr(*volatile Mmio(32, packed struct { + ALARM_0: u1, + ALARM_1: u1, + ALARM_2: u1, + ALARM_3: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + }), base_address + 0x3c); + + /// address: 0x40054040 + /// Interrupt status after masking & forcing + pub const INTS = @intToPtr(*volatile Mmio(32, packed struct { + ALARM_0: u1, + ALARM_1: u1, + ALARM_2: u1, + ALARM_3: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + }), base_address + 0x40); + }; + pub const WATCHDOG = struct { + pub const base_address = 0x40058000; + pub const version = "1"; + + /// address: 0x40058000 + /// Watchdog control\n + /// The rst_wdsel register determines which subsystems are reset when the watchdog + /// is triggered.\n + /// The watchdog can be triggered in software. + pub const CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// Indicates the number of ticks / 2 (see errata RP2040-E1) before a watchdog reset + /// will be triggered + TIME: u24, + /// Pause the watchdog timer when JTAG is accessing the bus fabric + PAUSE_JTAG: u1, + /// Pause the watchdog timer when processor 0 is in debug mode + PAUSE_DBG0: u1, + /// Pause the watchdog timer when processor 1 is in debug mode + PAUSE_DBG1: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + /// When not enabled the watchdog timer is paused + ENABLE: u1, + /// Trigger a watchdog reset + TRIGGER: u1, + }), base_address + 0x0); + + /// address: 0x40058004 + /// Load the watchdog timer. The maximum setting is 0xffffff which corresponds to + /// 0xffffff / 2 ticks before triggering a watchdog reset (see errata RP2040-E1). + pub const LOAD = @intToPtr(*volatile MmioInt(32, u24), base_address + 0x4); + + /// address: 0x40058008 + /// Logs the reason for the last reset. Both bits are zero for the case of a + /// hardware reset. + pub const REASON = @intToPtr(*volatile Mmio(32, packed struct { + TIMER: u1, + FORCE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + }), base_address + 0x8); + + /// address: 0x4005800c + /// Scratch register. Information persists through soft reset of the chip. + pub const SCRATCH0 = @intToPtr(*volatile u32, base_address + 0xc); + + /// address: 0x40058010 + /// Scratch register. Information persists through soft reset of the chip. + pub const SCRATCH1 = @intToPtr(*volatile u32, base_address + 0x10); + + /// address: 0x40058014 + /// Scratch register. Information persists through soft reset of the chip. + pub const SCRATCH2 = @intToPtr(*volatile u32, base_address + 0x14); + + /// address: 0x40058018 + /// Scratch register. Information persists through soft reset of the chip. + pub const SCRATCH3 = @intToPtr(*volatile u32, base_address + 0x18); + + /// address: 0x4005801c + /// Scratch register. Information persists through soft reset of the chip. + pub const SCRATCH4 = @intToPtr(*volatile u32, base_address + 0x1c); + + /// address: 0x40058020 + /// Scratch register. Information persists through soft reset of the chip. + pub const SCRATCH5 = @intToPtr(*volatile u32, base_address + 0x20); + + /// address: 0x40058024 + /// Scratch register. Information persists through soft reset of the chip. + pub const SCRATCH6 = @intToPtr(*volatile u32, base_address + 0x24); + + /// address: 0x40058028 + /// Scratch register. Information persists through soft reset of the chip. + pub const SCRATCH7 = @intToPtr(*volatile u32, base_address + 0x28); + + /// address: 0x4005802c + /// Controls the tick generator + pub const TICK = @intToPtr(*volatile Mmio(32, packed struct { + /// Total number of clk_tick cycles before the next tick. + CYCLES: u9, + /// start / stop tick generation + ENABLE: u1, + /// Is the tick generator running? + RUNNING: u1, + /// Count down timer: the remaining number clk_tick cycles before the next tick is + /// generated. + COUNT: u9, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + }), base_address + 0x2c); + }; + + /// Register block to control RTC + pub const RTC = struct { + pub const base_address = 0x4005c000; + pub const version = "1"; + + /// address: 0x4005c000 + /// Divider minus 1 for the 1 second counter. Safe to change the value when RTC is + /// not enabled. + pub const CLKDIV_M1 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x0); + + /// address: 0x4005c004 + /// RTC setup register 0 + pub const SETUP_0 = @intToPtr(*volatile Mmio(32, packed struct { + /// Day of the month (1..31) + DAY: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + /// Month (1..12) + MONTH: u4, + /// Year + YEAR: u12, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x4); + + /// address: 0x4005c008 + /// RTC setup register 1 + pub const SETUP_1 = @intToPtr(*volatile Mmio(32, packed struct { + /// Seconds + SEC: u6, + reserved0: u1 = 0, + reserved1: u1 = 0, + /// Minutes + MIN: u6, + reserved2: u1 = 0, + reserved3: u1 = 0, + /// Hours + HOUR: u5, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + /// Day of the week: 1-Monday...0-Sunday ISO 8601 mod 7 + DOTW: u3, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x8); + + /// address: 0x4005c00c + /// RTC Control and status + pub const CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// Enable RTC + RTC_ENABLE: u1, + /// RTC enabled (running) + RTC_ACTIVE: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + /// Load RTC + LOAD: u1, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + /// If set, leapyear is forced off.\n + /// Useful for years divisible by 100 but not by 400 + FORCE_NOTLEAPYEAR: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + }), base_address + 0xc); + + /// address: 0x4005c010 + /// Interrupt setup register 0 + pub const IRQ_SETUP_0 = @intToPtr(*volatile Mmio(32, packed struct { + /// Day of the month (1..31) + DAY: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + /// Month (1..12) + MONTH: u4, + /// Year + YEAR: u12, + /// Enable day matching + DAY_ENA: u1, + /// Enable month matching + MONTH_ENA: u1, + /// Enable year matching + YEAR_ENA: u1, + reserved3: u1 = 0, + /// Global match enable. Don't change any other value while this one is enabled + MATCH_ENA: u1, + MATCH_ACTIVE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + }), base_address + 0x10); + + /// address: 0x4005c014 + /// Interrupt setup register 1 + pub const IRQ_SETUP_1 = @intToPtr(*volatile Mmio(32, packed struct { + /// Seconds + SEC: u6, + reserved0: u1 = 0, + reserved1: u1 = 0, + /// Minutes + MIN: u6, + reserved2: u1 = 0, + reserved3: u1 = 0, + /// Hours + HOUR: u5, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + /// Day of the week + DOTW: u3, + reserved7: u1 = 0, + /// Enable second matching + SEC_ENA: u1, + /// Enable minute matching + MIN_ENA: u1, + /// Enable hour matching + HOUR_ENA: u1, + /// Enable day of the week matching + DOTW_ENA: u1, + }), base_address + 0x14); + + /// address: 0x4005c018 + /// RTC register 1. + pub const RTC_1 = @intToPtr(*volatile Mmio(32, packed struct { + /// Day of the month (1..31) + DAY: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + /// Month (1..12) + MONTH: u4, + /// Year + YEAR: u12, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x18); + + /// address: 0x4005c01c + /// RTC register 0\n + /// Read this before RTC 1! + pub const RTC_0 = @intToPtr(*volatile Mmio(32, packed struct { + /// Seconds + SEC: u6, + reserved0: u1 = 0, + reserved1: u1 = 0, + /// Minutes + MIN: u6, + reserved2: u1 = 0, + reserved3: u1 = 0, + /// Hours + HOUR: u5, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + /// Day of the week + DOTW: u3, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x1c); + + /// address: 0x4005c020 + /// Raw Interrupts + pub const INTR = @intToPtr(*volatile Mmio(32, packed struct { + RTC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x20); + + /// address: 0x4005c024 + /// Interrupt Enable + pub const INTE = @intToPtr(*volatile Mmio(32, packed struct { + RTC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x24); + + /// address: 0x4005c028 + /// Interrupt Force + pub const INTF = @intToPtr(*volatile Mmio(32, packed struct { + RTC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x28); + + /// address: 0x4005c02c + /// Interrupt status after masking & forcing + pub const INTS = @intToPtr(*volatile Mmio(32, packed struct { + RTC: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + padding30: u1 = 0, + }), base_address + 0x2c); + }; + pub const ROSC = struct { + pub const base_address = 0x40060000; + pub const version = "1"; + + /// address: 0x40060000 + /// Ring Oscillator control + pub const CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// Controls the number of delay stages in the ROSC ring\n + /// LOW uses stages 0 to 7\n + /// MEDIUM uses stages 0 to 5\n + /// HIGH uses stages 0 to 3\n + /// TOOHIGH uses stages 0 to 1 and should not be used because its frequency exceeds + /// design specifications\n + /// The clock output will not glitch when changing the range up one step at a time\n + /// The clock output will glitch when changing the range down\n + /// Note: the values here are gray coded which is why HIGH comes before TOOHIGH + FREQ_RANGE: u12, + /// On power-up this field is initialised to ENABLE\n + /// The system clock must be switched to another source before setting this field to + /// DISABLE otherwise the chip will lock up\n + /// The 12-bit code is intended to give some protection against accidental writes. + /// An invalid setting will enable the oscillator. + ENABLE: u12, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x0); + + /// address: 0x40060004 + /// The FREQA & FREQB registers control the frequency by controlling the drive + /// strength of each stage\n + /// The drive strength has 4 levels determined by the number of bits set\n + /// Increasing the number of bits set increases the drive strength and increases the + /// oscillation frequency\n + /// 0 bits set is the default drive strength\n + /// 1 bit set doubles the drive strength\n + /// 2 bits set triples drive strength\n + /// 3 bits set quadruples drive strength + pub const FREQA = @intToPtr(*volatile Mmio(32, packed struct { + /// Stage 0 drive strength + DS0: u3, + reserved0: u1 = 0, + /// Stage 1 drive strength + DS1: u3, + reserved1: u1 = 0, + /// Stage 2 drive strength + DS2: u3, + reserved2: u1 = 0, + /// Stage 3 drive strength + DS3: u3, + reserved3: u1 = 0, + /// Set to 0x9696 to apply the settings\n + /// Any other value in this field will set all drive strengths to 0 + PASSWD: u16, + }), base_address + 0x4); + + /// address: 0x40060008 + /// For a detailed description see freqa register + pub const FREQB = @intToPtr(*volatile Mmio(32, packed struct { + /// Stage 4 drive strength + DS4: u3, + reserved0: u1 = 0, + /// Stage 5 drive strength + DS5: u3, + reserved1: u1 = 0, + /// Stage 6 drive strength + DS6: u3, + reserved2: u1 = 0, + /// Stage 7 drive strength + DS7: u3, + reserved3: u1 = 0, + /// Set to 0x9696 to apply the settings\n + /// Any other value in this field will set all drive strengths to 0 + PASSWD: u16, + }), base_address + 0x8); + + /// address: 0x4006000c + /// Ring Oscillator pause control\n + /// This is used to save power by pausing the ROSC\n + /// On power-up this field is initialised to WAKE\n + /// An invalid write will also select WAKE\n + /// Warning: setup the irq before selecting dormant mode + pub const DORMANT = @intToPtr(*volatile u32, base_address + 0xc); + + /// address: 0x40060010 + /// Controls the output divider + pub const DIV = @intToPtr(*volatile MmioInt(32, u12), base_address + 0x10); + + /// address: 0x40060014 + /// Controls the phase shifted output + pub const PHASE = @intToPtr(*volatile Mmio(32, packed struct { + /// phase shift the phase-shifted output by SHIFT input clocks\n + /// this can be changed on-the-fly\n + /// must be set to 0 before setting div=1 + SHIFT: u2, + /// invert the phase-shifted output\n + /// this is ignored when div=1 + FLIP: u1, + /// enable the phase-shifted output\n + /// this can be changed on-the-fly + ENABLE: u1, + /// set to 0xaa\n + /// any other value enables the output with shift=0 + PASSWD: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x14); + + /// address: 0x40060018 + /// Ring Oscillator Status + pub const STATUS = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + /// Oscillator is enabled but not necessarily running and stable\n + /// this resets to 0 but transitions to 1 during chip startup + ENABLED: u1, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + /// post-divider is running\n + /// this resets to 0 but transitions to 1 during chip startup + DIV_RUNNING: u1, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + reserved18: u1 = 0, + reserved19: u1 = 0, + reserved20: u1 = 0, + reserved21: u1 = 0, + /// An invalid value has been written to CTRL_ENABLE or CTRL_FREQ_RANGE or FREQA or + /// FREQB or DIV or PHASE or DORMANT + BADWRITE: u1, + reserved22: u1 = 0, + reserved23: u1 = 0, + reserved24: u1 = 0, + reserved25: u1 = 0, + reserved26: u1 = 0, + reserved27: u1 = 0, + /// Oscillator is running and stable + STABLE: u1, + }), base_address + 0x18); + + /// address: 0x4006001c + /// This just reads the state of the oscillator output so randomness is compromised + /// if the ring oscillator is stopped or run at a harmonic of the bus frequency + pub const RANDOMBIT = @intToPtr(*volatile MmioInt(32, u1), base_address + 0x1c); + + /// address: 0x40060020 + /// A down counter running at the ROSC frequency which counts to zero and stops.\n + /// To start the counter write a non-zero value.\n + /// Can be used for short software pauses when setting up time sensitive hardware. + pub const COUNT = @intToPtr(*volatile MmioInt(32, u8), base_address + 0x20); + }; + + /// control and status for on-chip voltage regulator and chip level reset subsystem + pub const VREG_AND_CHIP_RESET = struct { + pub const base_address = 0x40064000; + pub const version = "1"; + + /// address: 0x40064000 + /// Voltage regulator control and status + pub const VREG = @intToPtr(*volatile Mmio(32, packed struct { + /// enable\n + /// 0=not enabled, 1=enabled + EN: u1, + /// high impedance mode select\n + /// 0=not in high impedance mode, 1=in high impedance mode + HIZ: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + /// output voltage select\n + /// 0000 to 0101 - 0.80V\n + /// 0110 - 0.85V\n + /// 0111 - 0.90V\n + /// 1000 - 0.95V\n + /// 1001 - 1.00V\n + /// 1010 - 1.05V\n + /// 1011 - 1.10V (default)\n + /// 1100 - 1.15V\n + /// 1101 - 1.20V\n + /// 1110 - 1.25V\n + /// 1111 - 1.30V + VSEL: u4, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + /// regulation status\n + /// 0=not in regulation, 1=in regulation + ROK: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + }), base_address + 0x0); + + /// address: 0x40064004 + /// brown-out detection control + pub const BOD = @intToPtr(*volatile Mmio(32, packed struct { + /// enable\n + /// 0=not enabled, 1=enabled + EN: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + /// threshold select\n + /// 0000 - 0.473V\n + /// 0001 - 0.516V\n + /// 0010 - 0.559V\n + /// 0011 - 0.602V\n + /// 0100 - 0.645V\n + /// 0101 - 0.688V\n + /// 0110 - 0.731V\n + /// 0111 - 0.774V\n + /// 1000 - 0.817V\n + /// 1001 - 0.860V (default)\n + /// 1010 - 0.903V\n + /// 1011 - 0.946V\n + /// 1100 - 0.989V\n + /// 1101 - 1.032V\n + /// 1110 - 1.075V\n + /// 1111 - 1.118V + VSEL: u4, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + }), base_address + 0x4); + + /// address: 0x40064008 + /// Chip reset control and status + pub const CHIP_RESET = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// Last reset was from the power-on reset or brown-out detection blocks + HAD_POR: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + /// Last reset was from the RUN pin + HAD_RUN: u1, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// Last reset was from the debug port + HAD_PSM_RESTART: u1, + reserved18: u1 = 0, + reserved19: u1 = 0, + reserved20: u1 = 0, + /// This is set by psm_restart from the debugger.\n + /// Its purpose is to branch bootcode to a safe mode when the debugger has issued a + /// psm_restart in order to recover from a boot lock-up.\n + /// In the safe mode the debugger can repair the boot code, clear this flag then + /// reboot the processor. + PSM_RESTART_FLAG: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + }), base_address + 0x8); + }; + + /// Testbench manager. Allows the programmer to know what platform their software is + /// running on. + pub const TBMAN = struct { + pub const base_address = 0x4006c000; + pub const version = "1"; + + /// address: 0x4006c000 + /// Indicates the type of platform in use + pub const PLATFORM = @intToPtr(*volatile Mmio(32, packed struct { + /// Indicates the platform is an ASIC + ASIC: u1, + /// Indicates the platform is an FPGA + FPGA: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + }), base_address + 0x0); + }; + + /// DMA with separate read and write masters + pub const DMA = struct { + pub const base_address = 0x50000000; + pub const version = "1"; + + /// address: 0x50000000 + /// DMA Channel 0 Read Address pointer\n + /// This register updates automatically each time a read completes. The current + /// value is the next address to be read by this channel. + pub const CH0_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x0); + + /// address: 0x50000004 + /// DMA Channel 0 Write Address pointer\n + /// This register updates automatically each time a write completes. The current + /// value is the next address to be written by this channel. + pub const CH0_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x4); + + /// address: 0x50000008 + /// DMA Channel 0 Transfer Count\n + /// Program the number of bus transfers a channel will perform before halting. Note + /// that, if transfers are larger than one byte in size, this is not equal to the + /// number of bytes transferred (see CTRL_DATA_SIZE).\n\n + /// When the channel is active, reading this register shows the number of transfers + /// remaining, updating automatically each time a write transfer completes.\n\n + /// Writing this register sets the RELOAD value for the transfer counter. Each time + /// this channel is triggered, the RELOAD value is copied into the live transfer + /// counter. The channel can be started multiple times, and will perform the same + /// number of transfers each time, as programmed by most recent write.\n\n + /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a + /// trigger, the written value is used immediately as the length of the new transfer + /// sequence, as well as being written to RELOAD. + pub const CH0_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x8); + + /// address: 0x5000000c + /// DMA Channel 0 Control and Status + pub const CH0_CTRL_TRIG = @intToPtr(*volatile Mmio(32, packed struct { + /// DMA Channel Enable.\n + /// When 1, the channel will respond to triggering events, which will cause it to + /// become BUSY and start transferring data. When 0, the channel will ignore + /// triggers, stop issuing transfers, and pause the current transfer sequence (i.e. + /// BUSY will remain high if already high) + EN: u1, + /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in + /// each scheduling round, all high priority channels are considered first, and then + /// only a single low priority channel, before returning to the high priority + /// channels.\n\n + /// This only affects the order in which the DMA schedules channels. The DMA's bus + /// priority is not changed. If the DMA is not saturated then a low priority channel + /// will see no loss of throughput. + HIGH_PRIORITY: u1, + /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR + /// advance by this amount (1/2/4 bytes) with each transfer. + DATA_SIZE: u2, + /// If 1, the read address increments with each transfer. If 0, each read is + /// directed to the same, initial address.\n\n + /// Generally this should be disabled for peripheral-to-memory transfers. + INCR_READ: u1, + /// If 1, the write address increments with each transfer. If 0, each write is + /// directed to the same, initial address.\n\n + /// Generally this should be disabled for memory-to-peripheral transfers. + INCR_WRITE: u1, + /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower + /// n bits of the address will change. This wraps the address on a (1 << n) byte + /// boundary, facilitating access to naturally-aligned ring buffers.\n\n + /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read + /// or write addresses, based on value of RING_SEL. + RING_SIZE: u4, + /// Select whether RING_SIZE applies to read or write addresses.\n + /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write + /// addresses are wrapped. + RING_SEL: u1, + /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. + /// Disable by setting CHAIN_TO = _(this channel)_.\n + /// Reset value is equal to channel number (0). + CHAIN_TO: u4, + /// Select a Transfer Request signal.\n + /// The channel uses the transfer request signal to pace its data transfer rate. + /// Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request + /// from the system).\n + /// 0x0 to 0x3a -> select DREQ n as TREQ + TREQ_SEL: u6, + /// In QUIET mode, the channel does not generate IRQs at the end of every transfer + /// block. Instead, an IRQ is raised when NULL is written to a trigger register, + /// indicating the end of a control block chain.\n\n + /// This reduces the number of interrupts to be serviced by the CPU when + /// transferring a DMA chain of many small control blocks. + IRQ_QUIET: u1, + /// Apply byte-swap transformation to DMA data.\n + /// For byte data, this has no effect. For halfword data, the two bytes of each + /// halfword are swapped. For word data, the four bytes of each word are swapped to + /// reverse order. + BSWAP: u1, + /// If 1, this channel's data transfers are visible to the sniff hardware, and each + /// transfer will advance the state of the checksum. This only applies if the sniff + /// hardware is enabled, and has this channel selected.\n\n + /// This allows checksum to be enabled or disabled on a per-control- block basis. + SNIFF_EN: u1, + /// This flag goes high when the channel starts a new transfer sequence, and low + /// when the last transfer of that sequence completes. Clearing EN while BUSY is + /// high pauses the channel, and BUSY will stay high while paused.\n\n + /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + BUSY: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + /// If 1, the channel received a write bus error. Write one to clear.\n + /// WRITE_ADDR shows the approximate address where the bus error was encountered + /// (will not to be earlier, or more than 5 transfers later) + WRITE_ERROR: u1, + /// If 1, the channel received a read bus error. Write one to clear.\n + /// READ_ADDR shows the approximate address where the bus error was encountered + /// (will not to be earlier, or more than 3 transfers later) + READ_ERROR: u1, + /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it + /// encounters any bus error, and always raises its channel IRQ flag. + AHB_ERROR: u1, + }), base_address + 0xc); + + /// address: 0x50000010 + /// Alias for channel 0 CTRL register + pub const CH0_AL1_CTRL = @intToPtr(*volatile u32, base_address + 0x10); + + /// address: 0x50000014 + /// Alias for channel 0 READ_ADDR register + pub const CH0_AL1_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x14); + + /// address: 0x50000018 + /// Alias for channel 0 WRITE_ADDR register + pub const CH0_AL1_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x18); + + /// address: 0x5000001c + /// Alias for channel 0 TRANS_COUNT register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH0_AL1_TRANS_COUNT_TRIG = @intToPtr(*volatile u32, base_address + 0x1c); + + /// address: 0x50000020 + /// Alias for channel 0 CTRL register + pub const CH0_AL2_CTRL = @intToPtr(*volatile u32, base_address + 0x20); + + /// address: 0x50000024 + /// Alias for channel 0 TRANS_COUNT register + pub const CH0_AL2_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x24); + + /// address: 0x50000028 + /// Alias for channel 0 READ_ADDR register + pub const CH0_AL2_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x28); + + /// address: 0x5000002c + /// Alias for channel 0 WRITE_ADDR register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH0_AL2_WRITE_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x2c); + + /// address: 0x50000030 + /// Alias for channel 0 CTRL register + pub const CH0_AL3_CTRL = @intToPtr(*volatile u32, base_address + 0x30); + + /// address: 0x50000034 + /// Alias for channel 0 WRITE_ADDR register + pub const CH0_AL3_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x34); + + /// address: 0x50000038 + /// Alias for channel 0 TRANS_COUNT register + pub const CH0_AL3_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x38); + + /// address: 0x5000003c + /// Alias for channel 0 READ_ADDR register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH0_AL3_READ_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x3c); + + /// address: 0x50000040 + /// DMA Channel 1 Read Address pointer\n + /// This register updates automatically each time a read completes. The current + /// value is the next address to be read by this channel. + pub const CH1_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x40); + + /// address: 0x50000044 + /// DMA Channel 1 Write Address pointer\n + /// This register updates automatically each time a write completes. The current + /// value is the next address to be written by this channel. + pub const CH1_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x44); + + /// address: 0x50000048 + /// DMA Channel 1 Transfer Count\n + /// Program the number of bus transfers a channel will perform before halting. Note + /// that, if transfers are larger than one byte in size, this is not equal to the + /// number of bytes transferred (see CTRL_DATA_SIZE).\n\n + /// When the channel is active, reading this register shows the number of transfers + /// remaining, updating automatically each time a write transfer completes.\n\n + /// Writing this register sets the RELOAD value for the transfer counter. Each time + /// this channel is triggered, the RELOAD value is copied into the live transfer + /// counter. The channel can be started multiple times, and will perform the same + /// number of transfers each time, as programmed by most recent write.\n\n + /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a + /// trigger, the written value is used immediately as the length of the new transfer + /// sequence, as well as being written to RELOAD. + pub const CH1_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x48); + + /// address: 0x5000004c + /// DMA Channel 1 Control and Status + pub const CH1_CTRL_TRIG = @intToPtr(*volatile Mmio(32, packed struct { + /// DMA Channel Enable.\n + /// When 1, the channel will respond to triggering events, which will cause it to + /// become BUSY and start transferring data. When 0, the channel will ignore + /// triggers, stop issuing transfers, and pause the current transfer sequence (i.e. + /// BUSY will remain high if already high) + EN: u1, + /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in + /// each scheduling round, all high priority channels are considered first, and then + /// only a single low priority channel, before returning to the high priority + /// channels.\n\n + /// This only affects the order in which the DMA schedules channels. The DMA's bus + /// priority is not changed. If the DMA is not saturated then a low priority channel + /// will see no loss of throughput. + HIGH_PRIORITY: u1, + /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR + /// advance by this amount (1/2/4 bytes) with each transfer. + DATA_SIZE: u2, + /// If 1, the read address increments with each transfer. If 0, each read is + /// directed to the same, initial address.\n\n + /// Generally this should be disabled for peripheral-to-memory transfers. + INCR_READ: u1, + /// If 1, the write address increments with each transfer. If 0, each write is + /// directed to the same, initial address.\n\n + /// Generally this should be disabled for memory-to-peripheral transfers. + INCR_WRITE: u1, + /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower + /// n bits of the address will change. This wraps the address on a (1 << n) byte + /// boundary, facilitating access to naturally-aligned ring buffers.\n\n + /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read + /// or write addresses, based on value of RING_SEL. + RING_SIZE: u4, + /// Select whether RING_SIZE applies to read or write addresses.\n + /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write + /// addresses are wrapped. + RING_SEL: u1, + /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. + /// Disable by setting CHAIN_TO = _(this channel)_.\n + /// Reset value is equal to channel number (1). + CHAIN_TO: u4, + /// Select a Transfer Request signal.\n + /// The channel uses the transfer request signal to pace its data transfer rate. + /// Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request + /// from the system).\n + /// 0x0 to 0x3a -> select DREQ n as TREQ + TREQ_SEL: u6, + /// In QUIET mode, the channel does not generate IRQs at the end of every transfer + /// block. Instead, an IRQ is raised when NULL is written to a trigger register, + /// indicating the end of a control block chain.\n\n + /// This reduces the number of interrupts to be serviced by the CPU when + /// transferring a DMA chain of many small control blocks. + IRQ_QUIET: u1, + /// Apply byte-swap transformation to DMA data.\n + /// For byte data, this has no effect. For halfword data, the two bytes of each + /// halfword are swapped. For word data, the four bytes of each word are swapped to + /// reverse order. + BSWAP: u1, + /// If 1, this channel's data transfers are visible to the sniff hardware, and each + /// transfer will advance the state of the checksum. This only applies if the sniff + /// hardware is enabled, and has this channel selected.\n\n + /// This allows checksum to be enabled or disabled on a per-control- block basis. + SNIFF_EN: u1, + /// This flag goes high when the channel starts a new transfer sequence, and low + /// when the last transfer of that sequence completes. Clearing EN while BUSY is + /// high pauses the channel, and BUSY will stay high while paused.\n\n + /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + BUSY: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + /// If 1, the channel received a write bus error. Write one to clear.\n + /// WRITE_ADDR shows the approximate address where the bus error was encountered + /// (will not to be earlier, or more than 5 transfers later) + WRITE_ERROR: u1, + /// If 1, the channel received a read bus error. Write one to clear.\n + /// READ_ADDR shows the approximate address where the bus error was encountered + /// (will not to be earlier, or more than 3 transfers later) + READ_ERROR: u1, + /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it + /// encounters any bus error, and always raises its channel IRQ flag. + AHB_ERROR: u1, + }), base_address + 0x4c); + + /// address: 0x50000050 + /// Alias for channel 1 CTRL register + pub const CH1_AL1_CTRL = @intToPtr(*volatile u32, base_address + 0x50); + + /// address: 0x50000054 + /// Alias for channel 1 READ_ADDR register + pub const CH1_AL1_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x54); + + /// address: 0x50000058 + /// Alias for channel 1 WRITE_ADDR register + pub const CH1_AL1_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x58); + + /// address: 0x5000005c + /// Alias for channel 1 TRANS_COUNT register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH1_AL1_TRANS_COUNT_TRIG = @intToPtr(*volatile u32, base_address + 0x5c); + + /// address: 0x50000060 + /// Alias for channel 1 CTRL register + pub const CH1_AL2_CTRL = @intToPtr(*volatile u32, base_address + 0x60); + + /// address: 0x50000064 + /// Alias for channel 1 TRANS_COUNT register + pub const CH1_AL2_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x64); + + /// address: 0x50000068 + /// Alias for channel 1 READ_ADDR register + pub const CH1_AL2_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x68); + + /// address: 0x5000006c + /// Alias for channel 1 WRITE_ADDR register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH1_AL2_WRITE_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x6c); + + /// address: 0x50000070 + /// Alias for channel 1 CTRL register + pub const CH1_AL3_CTRL = @intToPtr(*volatile u32, base_address + 0x70); + + /// address: 0x50000074 + /// Alias for channel 1 WRITE_ADDR register + pub const CH1_AL3_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x74); + + /// address: 0x50000078 + /// Alias for channel 1 TRANS_COUNT register + pub const CH1_AL3_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x78); + + /// address: 0x5000007c + /// Alias for channel 1 READ_ADDR register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH1_AL3_READ_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x7c); + + /// address: 0x50000080 + /// DMA Channel 2 Read Address pointer\n + /// This register updates automatically each time a read completes. The current + /// value is the next address to be read by this channel. + pub const CH2_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x80); + + /// address: 0x50000084 + /// DMA Channel 2 Write Address pointer\n + /// This register updates automatically each time a write completes. The current + /// value is the next address to be written by this channel. + pub const CH2_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x84); + + /// address: 0x50000088 + /// DMA Channel 2 Transfer Count\n + /// Program the number of bus transfers a channel will perform before halting. Note + /// that, if transfers are larger than one byte in size, this is not equal to the + /// number of bytes transferred (see CTRL_DATA_SIZE).\n\n + /// When the channel is active, reading this register shows the number of transfers + /// remaining, updating automatically each time a write transfer completes.\n\n + /// Writing this register sets the RELOAD value for the transfer counter. Each time + /// this channel is triggered, the RELOAD value is copied into the live transfer + /// counter. The channel can be started multiple times, and will perform the same + /// number of transfers each time, as programmed by most recent write.\n\n + /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a + /// trigger, the written value is used immediately as the length of the new transfer + /// sequence, as well as being written to RELOAD. + pub const CH2_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x88); + + /// address: 0x5000008c + /// DMA Channel 2 Control and Status + pub const CH2_CTRL_TRIG = @intToPtr(*volatile Mmio(32, packed struct { + /// DMA Channel Enable.\n + /// When 1, the channel will respond to triggering events, which will cause it to + /// become BUSY and start transferring data. When 0, the channel will ignore + /// triggers, stop issuing transfers, and pause the current transfer sequence (i.e. + /// BUSY will remain high if already high) + EN: u1, + /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in + /// each scheduling round, all high priority channels are considered first, and then + /// only a single low priority channel, before returning to the high priority + /// channels.\n\n + /// This only affects the order in which the DMA schedules channels. The DMA's bus + /// priority is not changed. If the DMA is not saturated then a low priority channel + /// will see no loss of throughput. + HIGH_PRIORITY: u1, + /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR + /// advance by this amount (1/2/4 bytes) with each transfer. + DATA_SIZE: u2, + /// If 1, the read address increments with each transfer. If 0, each read is + /// directed to the same, initial address.\n\n + /// Generally this should be disabled for peripheral-to-memory transfers. + INCR_READ: u1, + /// If 1, the write address increments with each transfer. If 0, each write is + /// directed to the same, initial address.\n\n + /// Generally this should be disabled for memory-to-peripheral transfers. + INCR_WRITE: u1, + /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower + /// n bits of the address will change. This wraps the address on a (1 << n) byte + /// boundary, facilitating access to naturally-aligned ring buffers.\n\n + /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read + /// or write addresses, based on value of RING_SEL. + RING_SIZE: u4, + /// Select whether RING_SIZE applies to read or write addresses.\n + /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write + /// addresses are wrapped. + RING_SEL: u1, + /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. + /// Disable by setting CHAIN_TO = _(this channel)_.\n + /// Reset value is equal to channel number (2). + CHAIN_TO: u4, + /// Select a Transfer Request signal.\n + /// The channel uses the transfer request signal to pace its data transfer rate. + /// Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request + /// from the system).\n + /// 0x0 to 0x3a -> select DREQ n as TREQ + TREQ_SEL: u6, + /// In QUIET mode, the channel does not generate IRQs at the end of every transfer + /// block. Instead, an IRQ is raised when NULL is written to a trigger register, + /// indicating the end of a control block chain.\n\n + /// This reduces the number of interrupts to be serviced by the CPU when + /// transferring a DMA chain of many small control blocks. + IRQ_QUIET: u1, + /// Apply byte-swap transformation to DMA data.\n + /// For byte data, this has no effect. For halfword data, the two bytes of each + /// halfword are swapped. For word data, the four bytes of each word are swapped to + /// reverse order. + BSWAP: u1, + /// If 1, this channel's data transfers are visible to the sniff hardware, and each + /// transfer will advance the state of the checksum. This only applies if the sniff + /// hardware is enabled, and has this channel selected.\n\n + /// This allows checksum to be enabled or disabled on a per-control- block basis. + SNIFF_EN: u1, + /// This flag goes high when the channel starts a new transfer sequence, and low + /// when the last transfer of that sequence completes. Clearing EN while BUSY is + /// high pauses the channel, and BUSY will stay high while paused.\n\n + /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + BUSY: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + /// If 1, the channel received a write bus error. Write one to clear.\n + /// WRITE_ADDR shows the approximate address where the bus error was encountered + /// (will not to be earlier, or more than 5 transfers later) + WRITE_ERROR: u1, + /// If 1, the channel received a read bus error. Write one to clear.\n + /// READ_ADDR shows the approximate address where the bus error was encountered + /// (will not to be earlier, or more than 3 transfers later) + READ_ERROR: u1, + /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it + /// encounters any bus error, and always raises its channel IRQ flag. + AHB_ERROR: u1, + }), base_address + 0x8c); + + /// address: 0x50000090 + /// Alias for channel 2 CTRL register + pub const CH2_AL1_CTRL = @intToPtr(*volatile u32, base_address + 0x90); + + /// address: 0x50000094 + /// Alias for channel 2 READ_ADDR register + pub const CH2_AL1_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x94); + + /// address: 0x50000098 + /// Alias for channel 2 WRITE_ADDR register + pub const CH2_AL1_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x98); + + /// address: 0x5000009c + /// Alias for channel 2 TRANS_COUNT register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH2_AL1_TRANS_COUNT_TRIG = @intToPtr(*volatile u32, base_address + 0x9c); + + /// address: 0x500000a0 + /// Alias for channel 2 CTRL register + pub const CH2_AL2_CTRL = @intToPtr(*volatile u32, base_address + 0xa0); + + /// address: 0x500000a4 + /// Alias for channel 2 TRANS_COUNT register + pub const CH2_AL2_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0xa4); + + /// address: 0x500000a8 + /// Alias for channel 2 READ_ADDR register + pub const CH2_AL2_READ_ADDR = @intToPtr(*volatile u32, base_address + 0xa8); + + /// address: 0x500000ac + /// Alias for channel 2 WRITE_ADDR register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH2_AL2_WRITE_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0xac); + + /// address: 0x500000b0 + /// Alias for channel 2 CTRL register + pub const CH2_AL3_CTRL = @intToPtr(*volatile u32, base_address + 0xb0); + + /// address: 0x500000b4 + /// Alias for channel 2 WRITE_ADDR register + pub const CH2_AL3_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0xb4); + + /// address: 0x500000b8 + /// Alias for channel 2 TRANS_COUNT register + pub const CH2_AL3_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0xb8); + + /// address: 0x500000bc + /// Alias for channel 2 READ_ADDR register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH2_AL3_READ_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0xbc); + + /// address: 0x500000c0 + /// DMA Channel 3 Read Address pointer\n + /// This register updates automatically each time a read completes. The current + /// value is the next address to be read by this channel. + pub const CH3_READ_ADDR = @intToPtr(*volatile u32, base_address + 0xc0); + + /// address: 0x500000c4 + /// DMA Channel 3 Write Address pointer\n + /// This register updates automatically each time a write completes. The current + /// value is the next address to be written by this channel. + pub const CH3_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0xc4); + + /// address: 0x500000c8 + /// DMA Channel 3 Transfer Count\n + /// Program the number of bus transfers a channel will perform before halting. Note + /// that, if transfers are larger than one byte in size, this is not equal to the + /// number of bytes transferred (see CTRL_DATA_SIZE).\n\n + /// When the channel is active, reading this register shows the number of transfers + /// remaining, updating automatically each time a write transfer completes.\n\n + /// Writing this register sets the RELOAD value for the transfer counter. Each time + /// this channel is triggered, the RELOAD value is copied into the live transfer + /// counter. The channel can be started multiple times, and will perform the same + /// number of transfers each time, as programmed by most recent write.\n\n + /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a + /// trigger, the written value is used immediately as the length of the new transfer + /// sequence, as well as being written to RELOAD. + pub const CH3_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0xc8); + + /// address: 0x500000cc + /// DMA Channel 3 Control and Status + pub const CH3_CTRL_TRIG = @intToPtr(*volatile Mmio(32, packed struct { + /// DMA Channel Enable.\n + /// When 1, the channel will respond to triggering events, which will cause it to + /// become BUSY and start transferring data. When 0, the channel will ignore + /// triggers, stop issuing transfers, and pause the current transfer sequence (i.e. + /// BUSY will remain high if already high) + EN: u1, + /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in + /// each scheduling round, all high priority channels are considered first, and then + /// only a single low priority channel, before returning to the high priority + /// channels.\n\n + /// This only affects the order in which the DMA schedules channels. The DMA's bus + /// priority is not changed. If the DMA is not saturated then a low priority channel + /// will see no loss of throughput. + HIGH_PRIORITY: u1, + /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR + /// advance by this amount (1/2/4 bytes) with each transfer. + DATA_SIZE: u2, + /// If 1, the read address increments with each transfer. If 0, each read is + /// directed to the same, initial address.\n\n + /// Generally this should be disabled for peripheral-to-memory transfers. + INCR_READ: u1, + /// If 1, the write address increments with each transfer. If 0, each write is + /// directed to the same, initial address.\n\n + /// Generally this should be disabled for memory-to-peripheral transfers. + INCR_WRITE: u1, + /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower + /// n bits of the address will change. This wraps the address on a (1 << n) byte + /// boundary, facilitating access to naturally-aligned ring buffers.\n\n + /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read + /// or write addresses, based on value of RING_SEL. + RING_SIZE: u4, + /// Select whether RING_SIZE applies to read or write addresses.\n + /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write + /// addresses are wrapped. + RING_SEL: u1, + /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. + /// Disable by setting CHAIN_TO = _(this channel)_.\n + /// Reset value is equal to channel number (3). + CHAIN_TO: u4, + /// Select a Transfer Request signal.\n + /// The channel uses the transfer request signal to pace its data transfer rate. + /// Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request + /// from the system).\n + /// 0x0 to 0x3a -> select DREQ n as TREQ + TREQ_SEL: u6, + /// In QUIET mode, the channel does not generate IRQs at the end of every transfer + /// block. Instead, an IRQ is raised when NULL is written to a trigger register, + /// indicating the end of a control block chain.\n\n + /// This reduces the number of interrupts to be serviced by the CPU when + /// transferring a DMA chain of many small control blocks. + IRQ_QUIET: u1, + /// Apply byte-swap transformation to DMA data.\n + /// For byte data, this has no effect. For halfword data, the two bytes of each + /// halfword are swapped. For word data, the four bytes of each word are swapped to + /// reverse order. + BSWAP: u1, + /// If 1, this channel's data transfers are visible to the sniff hardware, and each + /// transfer will advance the state of the checksum. This only applies if the sniff + /// hardware is enabled, and has this channel selected.\n\n + /// This allows checksum to be enabled or disabled on a per-control- block basis. + SNIFF_EN: u1, + /// This flag goes high when the channel starts a new transfer sequence, and low + /// when the last transfer of that sequence completes. Clearing EN while BUSY is + /// high pauses the channel, and BUSY will stay high while paused.\n\n + /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + BUSY: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + /// If 1, the channel received a write bus error. Write one to clear.\n + /// WRITE_ADDR shows the approximate address where the bus error was encountered + /// (will not to be earlier, or more than 5 transfers later) + WRITE_ERROR: u1, + /// If 1, the channel received a read bus error. Write one to clear.\n + /// READ_ADDR shows the approximate address where the bus error was encountered + /// (will not to be earlier, or more than 3 transfers later) + READ_ERROR: u1, + /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it + /// encounters any bus error, and always raises its channel IRQ flag. + AHB_ERROR: u1, + }), base_address + 0xcc); + + /// address: 0x500000d0 + /// Alias for channel 3 CTRL register + pub const CH3_AL1_CTRL = @intToPtr(*volatile u32, base_address + 0xd0); + + /// address: 0x500000d4 + /// Alias for channel 3 READ_ADDR register + pub const CH3_AL1_READ_ADDR = @intToPtr(*volatile u32, base_address + 0xd4); + + /// address: 0x500000d8 + /// Alias for channel 3 WRITE_ADDR register + pub const CH3_AL1_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0xd8); + + /// address: 0x500000dc + /// Alias for channel 3 TRANS_COUNT register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH3_AL1_TRANS_COUNT_TRIG = @intToPtr(*volatile u32, base_address + 0xdc); + + /// address: 0x500000e0 + /// Alias for channel 3 CTRL register + pub const CH3_AL2_CTRL = @intToPtr(*volatile u32, base_address + 0xe0); + + /// address: 0x500000e4 + /// Alias for channel 3 TRANS_COUNT register + pub const CH3_AL2_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0xe4); + + /// address: 0x500000e8 + /// Alias for channel 3 READ_ADDR register + pub const CH3_AL2_READ_ADDR = @intToPtr(*volatile u32, base_address + 0xe8); + + /// address: 0x500000ec + /// Alias for channel 3 WRITE_ADDR register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH3_AL2_WRITE_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0xec); + + /// address: 0x500000f0 + /// Alias for channel 3 CTRL register + pub const CH3_AL3_CTRL = @intToPtr(*volatile u32, base_address + 0xf0); + + /// address: 0x500000f4 + /// Alias for channel 3 WRITE_ADDR register + pub const CH3_AL3_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0xf4); + + /// address: 0x500000f8 + /// Alias for channel 3 TRANS_COUNT register + pub const CH3_AL3_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0xf8); + + /// address: 0x500000fc + /// Alias for channel 3 READ_ADDR register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH3_AL3_READ_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0xfc); + + /// address: 0x50000100 + /// DMA Channel 4 Read Address pointer\n + /// This register updates automatically each time a read completes. The current + /// value is the next address to be read by this channel. + pub const CH4_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x100); + + /// address: 0x50000104 + /// DMA Channel 4 Write Address pointer\n + /// This register updates automatically each time a write completes. The current + /// value is the next address to be written by this channel. + pub const CH4_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x104); + + /// address: 0x50000108 + /// DMA Channel 4 Transfer Count\n + /// Program the number of bus transfers a channel will perform before halting. Note + /// that, if transfers are larger than one byte in size, this is not equal to the + /// number of bytes transferred (see CTRL_DATA_SIZE).\n\n + /// When the channel is active, reading this register shows the number of transfers + /// remaining, updating automatically each time a write transfer completes.\n\n + /// Writing this register sets the RELOAD value for the transfer counter. Each time + /// this channel is triggered, the RELOAD value is copied into the live transfer + /// counter. The channel can be started multiple times, and will perform the same + /// number of transfers each time, as programmed by most recent write.\n\n + /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a + /// trigger, the written value is used immediately as the length of the new transfer + /// sequence, as well as being written to RELOAD. + pub const CH4_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x108); + + /// address: 0x5000010c + /// DMA Channel 4 Control and Status + pub const CH4_CTRL_TRIG = @intToPtr(*volatile Mmio(32, packed struct { + /// DMA Channel Enable.\n + /// When 1, the channel will respond to triggering events, which will cause it to + /// become BUSY and start transferring data. When 0, the channel will ignore + /// triggers, stop issuing transfers, and pause the current transfer sequence (i.e. + /// BUSY will remain high if already high) + EN: u1, + /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in + /// each scheduling round, all high priority channels are considered first, and then + /// only a single low priority channel, before returning to the high priority + /// channels.\n\n + /// This only affects the order in which the DMA schedules channels. The DMA's bus + /// priority is not changed. If the DMA is not saturated then a low priority channel + /// will see no loss of throughput. + HIGH_PRIORITY: u1, + /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR + /// advance by this amount (1/2/4 bytes) with each transfer. + DATA_SIZE: u2, + /// If 1, the read address increments with each transfer. If 0, each read is + /// directed to the same, initial address.\n\n + /// Generally this should be disabled for peripheral-to-memory transfers. + INCR_READ: u1, + /// If 1, the write address increments with each transfer. If 0, each write is + /// directed to the same, initial address.\n\n + /// Generally this should be disabled for memory-to-peripheral transfers. + INCR_WRITE: u1, + /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower + /// n bits of the address will change. This wraps the address on a (1 << n) byte + /// boundary, facilitating access to naturally-aligned ring buffers.\n\n + /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read + /// or write addresses, based on value of RING_SEL. + RING_SIZE: u4, + /// Select whether RING_SIZE applies to read or write addresses.\n + /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write + /// addresses are wrapped. + RING_SEL: u1, + /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. + /// Disable by setting CHAIN_TO = _(this channel)_.\n + /// Reset value is equal to channel number (4). + CHAIN_TO: u4, + /// Select a Transfer Request signal.\n + /// The channel uses the transfer request signal to pace its data transfer rate. + /// Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request + /// from the system).\n + /// 0x0 to 0x3a -> select DREQ n as TREQ + TREQ_SEL: u6, + /// In QUIET mode, the channel does not generate IRQs at the end of every transfer + /// block. Instead, an IRQ is raised when NULL is written to a trigger register, + /// indicating the end of a control block chain.\n\n + /// This reduces the number of interrupts to be serviced by the CPU when + /// transferring a DMA chain of many small control blocks. + IRQ_QUIET: u1, + /// Apply byte-swap transformation to DMA data.\n + /// For byte data, this has no effect. For halfword data, the two bytes of each + /// halfword are swapped. For word data, the four bytes of each word are swapped to + /// reverse order. + BSWAP: u1, + /// If 1, this channel's data transfers are visible to the sniff hardware, and each + /// transfer will advance the state of the checksum. This only applies if the sniff + /// hardware is enabled, and has this channel selected.\n\n + /// This allows checksum to be enabled or disabled on a per-control- block basis. + SNIFF_EN: u1, + /// This flag goes high when the channel starts a new transfer sequence, and low + /// when the last transfer of that sequence completes. Clearing EN while BUSY is + /// high pauses the channel, and BUSY will stay high while paused.\n\n + /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + BUSY: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + /// If 1, the channel received a write bus error. Write one to clear.\n + /// WRITE_ADDR shows the approximate address where the bus error was encountered + /// (will not to be earlier, or more than 5 transfers later) + WRITE_ERROR: u1, + /// If 1, the channel received a read bus error. Write one to clear.\n + /// READ_ADDR shows the approximate address where the bus error was encountered + /// (will not to be earlier, or more than 3 transfers later) + READ_ERROR: u1, + /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it + /// encounters any bus error, and always raises its channel IRQ flag. + AHB_ERROR: u1, + }), base_address + 0x10c); + + /// address: 0x50000110 + /// Alias for channel 4 CTRL register + pub const CH4_AL1_CTRL = @intToPtr(*volatile u32, base_address + 0x110); + + /// address: 0x50000114 + /// Alias for channel 4 READ_ADDR register + pub const CH4_AL1_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x114); + + /// address: 0x50000118 + /// Alias for channel 4 WRITE_ADDR register + pub const CH4_AL1_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x118); + + /// address: 0x5000011c + /// Alias for channel 4 TRANS_COUNT register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH4_AL1_TRANS_COUNT_TRIG = @intToPtr(*volatile u32, base_address + 0x11c); + + /// address: 0x50000120 + /// Alias for channel 4 CTRL register + pub const CH4_AL2_CTRL = @intToPtr(*volatile u32, base_address + 0x120); + + /// address: 0x50000124 + /// Alias for channel 4 TRANS_COUNT register + pub const CH4_AL2_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x124); + + /// address: 0x50000128 + /// Alias for channel 4 READ_ADDR register + pub const CH4_AL2_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x128); + + /// address: 0x5000012c + /// Alias for channel 4 WRITE_ADDR register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH4_AL2_WRITE_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x12c); + + /// address: 0x50000130 + /// Alias for channel 4 CTRL register + pub const CH4_AL3_CTRL = @intToPtr(*volatile u32, base_address + 0x130); + + /// address: 0x50000134 + /// Alias for channel 4 WRITE_ADDR register + pub const CH4_AL3_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x134); + + /// address: 0x50000138 + /// Alias for channel 4 TRANS_COUNT register + pub const CH4_AL3_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x138); + + /// address: 0x5000013c + /// Alias for channel 4 READ_ADDR register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH4_AL3_READ_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x13c); + + /// address: 0x50000140 + /// DMA Channel 5 Read Address pointer\n + /// This register updates automatically each time a read completes. The current + /// value is the next address to be read by this channel. + pub const CH5_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x140); + + /// address: 0x50000144 + /// DMA Channel 5 Write Address pointer\n + /// This register updates automatically each time a write completes. The current + /// value is the next address to be written by this channel. + pub const CH5_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x144); + + /// address: 0x50000148 + /// DMA Channel 5 Transfer Count\n + /// Program the number of bus transfers a channel will perform before halting. Note + /// that, if transfers are larger than one byte in size, this is not equal to the + /// number of bytes transferred (see CTRL_DATA_SIZE).\n\n + /// When the channel is active, reading this register shows the number of transfers + /// remaining, updating automatically each time a write transfer completes.\n\n + /// Writing this register sets the RELOAD value for the transfer counter. Each time + /// this channel is triggered, the RELOAD value is copied into the live transfer + /// counter. The channel can be started multiple times, and will perform the same + /// number of transfers each time, as programmed by most recent write.\n\n + /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a + /// trigger, the written value is used immediately as the length of the new transfer + /// sequence, as well as being written to RELOAD. + pub const CH5_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x148); + + /// address: 0x5000014c + /// DMA Channel 5 Control and Status + pub const CH5_CTRL_TRIG = @intToPtr(*volatile Mmio(32, packed struct { + /// DMA Channel Enable.\n + /// When 1, the channel will respond to triggering events, which will cause it to + /// become BUSY and start transferring data. When 0, the channel will ignore + /// triggers, stop issuing transfers, and pause the current transfer sequence (i.e. + /// BUSY will remain high if already high) + EN: u1, + /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in + /// each scheduling round, all high priority channels are considered first, and then + /// only a single low priority channel, before returning to the high priority + /// channels.\n\n + /// This only affects the order in which the DMA schedules channels. The DMA's bus + /// priority is not changed. If the DMA is not saturated then a low priority channel + /// will see no loss of throughput. + HIGH_PRIORITY: u1, + /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR + /// advance by this amount (1/2/4 bytes) with each transfer. + DATA_SIZE: u2, + /// If 1, the read address increments with each transfer. If 0, each read is + /// directed to the same, initial address.\n\n + /// Generally this should be disabled for peripheral-to-memory transfers. + INCR_READ: u1, + /// If 1, the write address increments with each transfer. If 0, each write is + /// directed to the same, initial address.\n\n + /// Generally this should be disabled for memory-to-peripheral transfers. + INCR_WRITE: u1, + /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower + /// n bits of the address will change. This wraps the address on a (1 << n) byte + /// boundary, facilitating access to naturally-aligned ring buffers.\n\n + /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read + /// or write addresses, based on value of RING_SEL. + RING_SIZE: u4, + /// Select whether RING_SIZE applies to read or write addresses.\n + /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write + /// addresses are wrapped. + RING_SEL: u1, + /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. + /// Disable by setting CHAIN_TO = _(this channel)_.\n + /// Reset value is equal to channel number (5). + CHAIN_TO: u4, + /// Select a Transfer Request signal.\n + /// The channel uses the transfer request signal to pace its data transfer rate. + /// Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request + /// from the system).\n + /// 0x0 to 0x3a -> select DREQ n as TREQ + TREQ_SEL: u6, + /// In QUIET mode, the channel does not generate IRQs at the end of every transfer + /// block. Instead, an IRQ is raised when NULL is written to a trigger register, + /// indicating the end of a control block chain.\n\n + /// This reduces the number of interrupts to be serviced by the CPU when + /// transferring a DMA chain of many small control blocks. + IRQ_QUIET: u1, + /// Apply byte-swap transformation to DMA data.\n + /// For byte data, this has no effect. For halfword data, the two bytes of each + /// halfword are swapped. For word data, the four bytes of each word are swapped to + /// reverse order. + BSWAP: u1, + /// If 1, this channel's data transfers are visible to the sniff hardware, and each + /// transfer will advance the state of the checksum. This only applies if the sniff + /// hardware is enabled, and has this channel selected.\n\n + /// This allows checksum to be enabled or disabled on a per-control- block basis. + SNIFF_EN: u1, + /// This flag goes high when the channel starts a new transfer sequence, and low + /// when the last transfer of that sequence completes. Clearing EN while BUSY is + /// high pauses the channel, and BUSY will stay high while paused.\n\n + /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + BUSY: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + /// If 1, the channel received a write bus error. Write one to clear.\n + /// WRITE_ADDR shows the approximate address where the bus error was encountered + /// (will not to be earlier, or more than 5 transfers later) + WRITE_ERROR: u1, + /// If 1, the channel received a read bus error. Write one to clear.\n + /// READ_ADDR shows the approximate address where the bus error was encountered + /// (will not to be earlier, or more than 3 transfers later) + READ_ERROR: u1, + /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it + /// encounters any bus error, and always raises its channel IRQ flag. + AHB_ERROR: u1, + }), base_address + 0x14c); + + /// address: 0x50000150 + /// Alias for channel 5 CTRL register + pub const CH5_AL1_CTRL = @intToPtr(*volatile u32, base_address + 0x150); + + /// address: 0x50000154 + /// Alias for channel 5 READ_ADDR register + pub const CH5_AL1_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x154); + + /// address: 0x50000158 + /// Alias for channel 5 WRITE_ADDR register + pub const CH5_AL1_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x158); + + /// address: 0x5000015c + /// Alias for channel 5 TRANS_COUNT register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH5_AL1_TRANS_COUNT_TRIG = @intToPtr(*volatile u32, base_address + 0x15c); + + /// address: 0x50000160 + /// Alias for channel 5 CTRL register + pub const CH5_AL2_CTRL = @intToPtr(*volatile u32, base_address + 0x160); + + /// address: 0x50000164 + /// Alias for channel 5 TRANS_COUNT register + pub const CH5_AL2_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x164); + + /// address: 0x50000168 + /// Alias for channel 5 READ_ADDR register + pub const CH5_AL2_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x168); + + /// address: 0x5000016c + /// Alias for channel 5 WRITE_ADDR register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH5_AL2_WRITE_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x16c); + + /// address: 0x50000170 + /// Alias for channel 5 CTRL register + pub const CH5_AL3_CTRL = @intToPtr(*volatile u32, base_address + 0x170); + + /// address: 0x50000174 + /// Alias for channel 5 WRITE_ADDR register + pub const CH5_AL3_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x174); + + /// address: 0x50000178 + /// Alias for channel 5 TRANS_COUNT register + pub const CH5_AL3_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x178); + + /// address: 0x5000017c + /// Alias for channel 5 READ_ADDR register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH5_AL3_READ_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x17c); + + /// address: 0x50000180 + /// DMA Channel 6 Read Address pointer\n + /// This register updates automatically each time a read completes. The current + /// value is the next address to be read by this channel. + pub const CH6_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x180); + + /// address: 0x50000184 + /// DMA Channel 6 Write Address pointer\n + /// This register updates automatically each time a write completes. The current + /// value is the next address to be written by this channel. + pub const CH6_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x184); + + /// address: 0x50000188 + /// DMA Channel 6 Transfer Count\n + /// Program the number of bus transfers a channel will perform before halting. Note + /// that, if transfers are larger than one byte in size, this is not equal to the + /// number of bytes transferred (see CTRL_DATA_SIZE).\n\n + /// When the channel is active, reading this register shows the number of transfers + /// remaining, updating automatically each time a write transfer completes.\n\n + /// Writing this register sets the RELOAD value for the transfer counter. Each time + /// this channel is triggered, the RELOAD value is copied into the live transfer + /// counter. The channel can be started multiple times, and will perform the same + /// number of transfers each time, as programmed by most recent write.\n\n + /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a + /// trigger, the written value is used immediately as the length of the new transfer + /// sequence, as well as being written to RELOAD. + pub const CH6_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x188); + + /// address: 0x5000018c + /// DMA Channel 6 Control and Status + pub const CH6_CTRL_TRIG = @intToPtr(*volatile Mmio(32, packed struct { + /// DMA Channel Enable.\n + /// When 1, the channel will respond to triggering events, which will cause it to + /// become BUSY and start transferring data. When 0, the channel will ignore + /// triggers, stop issuing transfers, and pause the current transfer sequence (i.e. + /// BUSY will remain high if already high) + EN: u1, + /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in + /// each scheduling round, all high priority channels are considered first, and then + /// only a single low priority channel, before returning to the high priority + /// channels.\n\n + /// This only affects the order in which the DMA schedules channels. The DMA's bus + /// priority is not changed. If the DMA is not saturated then a low priority channel + /// will see no loss of throughput. + HIGH_PRIORITY: u1, + /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR + /// advance by this amount (1/2/4 bytes) with each transfer. + DATA_SIZE: u2, + /// If 1, the read address increments with each transfer. If 0, each read is + /// directed to the same, initial address.\n\n + /// Generally this should be disabled for peripheral-to-memory transfers. + INCR_READ: u1, + /// If 1, the write address increments with each transfer. If 0, each write is + /// directed to the same, initial address.\n\n + /// Generally this should be disabled for memory-to-peripheral transfers. + INCR_WRITE: u1, + /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower + /// n bits of the address will change. This wraps the address on a (1 << n) byte + /// boundary, facilitating access to naturally-aligned ring buffers.\n\n + /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read + /// or write addresses, based on value of RING_SEL. + RING_SIZE: u4, + /// Select whether RING_SIZE applies to read or write addresses.\n + /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write + /// addresses are wrapped. + RING_SEL: u1, + /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. + /// Disable by setting CHAIN_TO = _(this channel)_.\n + /// Reset value is equal to channel number (6). + CHAIN_TO: u4, + /// Select a Transfer Request signal.\n + /// The channel uses the transfer request signal to pace its data transfer rate. + /// Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request + /// from the system).\n + /// 0x0 to 0x3a -> select DREQ n as TREQ + TREQ_SEL: u6, + /// In QUIET mode, the channel does not generate IRQs at the end of every transfer + /// block. Instead, an IRQ is raised when NULL is written to a trigger register, + /// indicating the end of a control block chain.\n\n + /// This reduces the number of interrupts to be serviced by the CPU when + /// transferring a DMA chain of many small control blocks. + IRQ_QUIET: u1, + /// Apply byte-swap transformation to DMA data.\n + /// For byte data, this has no effect. For halfword data, the two bytes of each + /// halfword are swapped. For word data, the four bytes of each word are swapped to + /// reverse order. + BSWAP: u1, + /// If 1, this channel's data transfers are visible to the sniff hardware, and each + /// transfer will advance the state of the checksum. This only applies if the sniff + /// hardware is enabled, and has this channel selected.\n\n + /// This allows checksum to be enabled or disabled on a per-control- block basis. + SNIFF_EN: u1, + /// This flag goes high when the channel starts a new transfer sequence, and low + /// when the last transfer of that sequence completes. Clearing EN while BUSY is + /// high pauses the channel, and BUSY will stay high while paused.\n\n + /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + BUSY: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + /// If 1, the channel received a write bus error. Write one to clear.\n + /// WRITE_ADDR shows the approximate address where the bus error was encountered + /// (will not to be earlier, or more than 5 transfers later) + WRITE_ERROR: u1, + /// If 1, the channel received a read bus error. Write one to clear.\n + /// READ_ADDR shows the approximate address where the bus error was encountered + /// (will not to be earlier, or more than 3 transfers later) + READ_ERROR: u1, + /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it + /// encounters any bus error, and always raises its channel IRQ flag. + AHB_ERROR: u1, + }), base_address + 0x18c); + + /// address: 0x50000190 + /// Alias for channel 6 CTRL register + pub const CH6_AL1_CTRL = @intToPtr(*volatile u32, base_address + 0x190); + + /// address: 0x50000194 + /// Alias for channel 6 READ_ADDR register + pub const CH6_AL1_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x194); + + /// address: 0x50000198 + /// Alias for channel 6 WRITE_ADDR register + pub const CH6_AL1_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x198); + + /// address: 0x5000019c + /// Alias for channel 6 TRANS_COUNT register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH6_AL1_TRANS_COUNT_TRIG = @intToPtr(*volatile u32, base_address + 0x19c); + + /// address: 0x500001a0 + /// Alias for channel 6 CTRL register + pub const CH6_AL2_CTRL = @intToPtr(*volatile u32, base_address + 0x1a0); + + /// address: 0x500001a4 + /// Alias for channel 6 TRANS_COUNT register + pub const CH6_AL2_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x1a4); + + /// address: 0x500001a8 + /// Alias for channel 6 READ_ADDR register + pub const CH6_AL2_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x1a8); + + /// address: 0x500001ac + /// Alias for channel 6 WRITE_ADDR register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH6_AL2_WRITE_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x1ac); + + /// address: 0x500001b0 + /// Alias for channel 6 CTRL register + pub const CH6_AL3_CTRL = @intToPtr(*volatile u32, base_address + 0x1b0); + + /// address: 0x500001b4 + /// Alias for channel 6 WRITE_ADDR register + pub const CH6_AL3_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x1b4); + + /// address: 0x500001b8 + /// Alias for channel 6 TRANS_COUNT register + pub const CH6_AL3_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x1b8); + + /// address: 0x500001bc + /// Alias for channel 6 READ_ADDR register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH6_AL3_READ_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x1bc); + + /// address: 0x500001c0 + /// DMA Channel 7 Read Address pointer\n + /// This register updates automatically each time a read completes. The current + /// value is the next address to be read by this channel. + pub const CH7_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x1c0); + + /// address: 0x500001c4 + /// DMA Channel 7 Write Address pointer\n + /// This register updates automatically each time a write completes. The current + /// value is the next address to be written by this channel. + pub const CH7_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x1c4); + + /// address: 0x500001c8 + /// DMA Channel 7 Transfer Count\n + /// Program the number of bus transfers a channel will perform before halting. Note + /// that, if transfers are larger than one byte in size, this is not equal to the + /// number of bytes transferred (see CTRL_DATA_SIZE).\n\n + /// When the channel is active, reading this register shows the number of transfers + /// remaining, updating automatically each time a write transfer completes.\n\n + /// Writing this register sets the RELOAD value for the transfer counter. Each time + /// this channel is triggered, the RELOAD value is copied into the live transfer + /// counter. The channel can be started multiple times, and will perform the same + /// number of transfers each time, as programmed by most recent write.\n\n + /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a + /// trigger, the written value is used immediately as the length of the new transfer + /// sequence, as well as being written to RELOAD. + pub const CH7_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x1c8); + + /// address: 0x500001cc + /// DMA Channel 7 Control and Status + pub const CH7_CTRL_TRIG = @intToPtr(*volatile Mmio(32, packed struct { + /// DMA Channel Enable.\n + /// When 1, the channel will respond to triggering events, which will cause it to + /// become BUSY and start transferring data. When 0, the channel will ignore + /// triggers, stop issuing transfers, and pause the current transfer sequence (i.e. + /// BUSY will remain high if already high) + EN: u1, + /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in + /// each scheduling round, all high priority channels are considered first, and then + /// only a single low priority channel, before returning to the high priority + /// channels.\n\n + /// This only affects the order in which the DMA schedules channels. The DMA's bus + /// priority is not changed. If the DMA is not saturated then a low priority channel + /// will see no loss of throughput. + HIGH_PRIORITY: u1, + /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR + /// advance by this amount (1/2/4 bytes) with each transfer. + DATA_SIZE: u2, + /// If 1, the read address increments with each transfer. If 0, each read is + /// directed to the same, initial address.\n\n + /// Generally this should be disabled for peripheral-to-memory transfers. + INCR_READ: u1, + /// If 1, the write address increments with each transfer. If 0, each write is + /// directed to the same, initial address.\n\n + /// Generally this should be disabled for memory-to-peripheral transfers. + INCR_WRITE: u1, + /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower + /// n bits of the address will change. This wraps the address on a (1 << n) byte + /// boundary, facilitating access to naturally-aligned ring buffers.\n\n + /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read + /// or write addresses, based on value of RING_SEL. + RING_SIZE: u4, + /// Select whether RING_SIZE applies to read or write addresses.\n + /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write + /// addresses are wrapped. + RING_SEL: u1, + /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. + /// Disable by setting CHAIN_TO = _(this channel)_.\n + /// Reset value is equal to channel number (7). + CHAIN_TO: u4, + /// Select a Transfer Request signal.\n + /// The channel uses the transfer request signal to pace its data transfer rate. + /// Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request + /// from the system).\n + /// 0x0 to 0x3a -> select DREQ n as TREQ + TREQ_SEL: u6, + /// In QUIET mode, the channel does not generate IRQs at the end of every transfer + /// block. Instead, an IRQ is raised when NULL is written to a trigger register, + /// indicating the end of a control block chain.\n\n + /// This reduces the number of interrupts to be serviced by the CPU when + /// transferring a DMA chain of many small control blocks. + IRQ_QUIET: u1, + /// Apply byte-swap transformation to DMA data.\n + /// For byte data, this has no effect. For halfword data, the two bytes of each + /// halfword are swapped. For word data, the four bytes of each word are swapped to + /// reverse order. + BSWAP: u1, + /// If 1, this channel's data transfers are visible to the sniff hardware, and each + /// transfer will advance the state of the checksum. This only applies if the sniff + /// hardware is enabled, and has this channel selected.\n\n + /// This allows checksum to be enabled or disabled on a per-control- block basis. + SNIFF_EN: u1, + /// This flag goes high when the channel starts a new transfer sequence, and low + /// when the last transfer of that sequence completes. Clearing EN while BUSY is + /// high pauses the channel, and BUSY will stay high while paused.\n\n + /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + BUSY: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + /// If 1, the channel received a write bus error. Write one to clear.\n + /// WRITE_ADDR shows the approximate address where the bus error was encountered + /// (will not to be earlier, or more than 5 transfers later) + WRITE_ERROR: u1, + /// If 1, the channel received a read bus error. Write one to clear.\n + /// READ_ADDR shows the approximate address where the bus error was encountered + /// (will not to be earlier, or more than 3 transfers later) + READ_ERROR: u1, + /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it + /// encounters any bus error, and always raises its channel IRQ flag. + AHB_ERROR: u1, + }), base_address + 0x1cc); + + /// address: 0x500001d0 + /// Alias for channel 7 CTRL register + pub const CH7_AL1_CTRL = @intToPtr(*volatile u32, base_address + 0x1d0); + + /// address: 0x500001d4 + /// Alias for channel 7 READ_ADDR register + pub const CH7_AL1_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x1d4); + + /// address: 0x500001d8 + /// Alias for channel 7 WRITE_ADDR register + pub const CH7_AL1_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x1d8); + + /// address: 0x500001dc + /// Alias for channel 7 TRANS_COUNT register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH7_AL1_TRANS_COUNT_TRIG = @intToPtr(*volatile u32, base_address + 0x1dc); + + /// address: 0x500001e0 + /// Alias for channel 7 CTRL register + pub const CH7_AL2_CTRL = @intToPtr(*volatile u32, base_address + 0x1e0); + + /// address: 0x500001e4 + /// Alias for channel 7 TRANS_COUNT register + pub const CH7_AL2_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x1e4); + + /// address: 0x500001e8 + /// Alias for channel 7 READ_ADDR register + pub const CH7_AL2_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x1e8); + + /// address: 0x500001ec + /// Alias for channel 7 WRITE_ADDR register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH7_AL2_WRITE_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x1ec); + + /// address: 0x500001f0 + /// Alias for channel 7 CTRL register + pub const CH7_AL3_CTRL = @intToPtr(*volatile u32, base_address + 0x1f0); + + /// address: 0x500001f4 + /// Alias for channel 7 WRITE_ADDR register + pub const CH7_AL3_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x1f4); + + /// address: 0x500001f8 + /// Alias for channel 7 TRANS_COUNT register + pub const CH7_AL3_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x1f8); + + /// address: 0x500001fc + /// Alias for channel 7 READ_ADDR register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH7_AL3_READ_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x1fc); + + /// address: 0x50000200 + /// DMA Channel 8 Read Address pointer\n + /// This register updates automatically each time a read completes. The current + /// value is the next address to be read by this channel. + pub const CH8_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x200); + + /// address: 0x50000204 + /// DMA Channel 8 Write Address pointer\n + /// This register updates automatically each time a write completes. The current + /// value is the next address to be written by this channel. + pub const CH8_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x204); + + /// address: 0x50000208 + /// DMA Channel 8 Transfer Count\n + /// Program the number of bus transfers a channel will perform before halting. Note + /// that, if transfers are larger than one byte in size, this is not equal to the + /// number of bytes transferred (see CTRL_DATA_SIZE).\n\n + /// When the channel is active, reading this register shows the number of transfers + /// remaining, updating automatically each time a write transfer completes.\n\n + /// Writing this register sets the RELOAD value for the transfer counter. Each time + /// this channel is triggered, the RELOAD value is copied into the live transfer + /// counter. The channel can be started multiple times, and will perform the same + /// number of transfers each time, as programmed by most recent write.\n\n + /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a + /// trigger, the written value is used immediately as the length of the new transfer + /// sequence, as well as being written to RELOAD. + pub const CH8_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x208); + + /// address: 0x5000020c + /// DMA Channel 8 Control and Status + pub const CH8_CTRL_TRIG = @intToPtr(*volatile Mmio(32, packed struct { + /// DMA Channel Enable.\n + /// When 1, the channel will respond to triggering events, which will cause it to + /// become BUSY and start transferring data. When 0, the channel will ignore + /// triggers, stop issuing transfers, and pause the current transfer sequence (i.e. + /// BUSY will remain high if already high) + EN: u1, + /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in + /// each scheduling round, all high priority channels are considered first, and then + /// only a single low priority channel, before returning to the high priority + /// channels.\n\n + /// This only affects the order in which the DMA schedules channels. The DMA's bus + /// priority is not changed. If the DMA is not saturated then a low priority channel + /// will see no loss of throughput. + HIGH_PRIORITY: u1, + /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR + /// advance by this amount (1/2/4 bytes) with each transfer. + DATA_SIZE: u2, + /// If 1, the read address increments with each transfer. If 0, each read is + /// directed to the same, initial address.\n\n + /// Generally this should be disabled for peripheral-to-memory transfers. + INCR_READ: u1, + /// If 1, the write address increments with each transfer. If 0, each write is + /// directed to the same, initial address.\n\n + /// Generally this should be disabled for memory-to-peripheral transfers. + INCR_WRITE: u1, + /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower + /// n bits of the address will change. This wraps the address on a (1 << n) byte + /// boundary, facilitating access to naturally-aligned ring buffers.\n\n + /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read + /// or write addresses, based on value of RING_SEL. + RING_SIZE: u4, + /// Select whether RING_SIZE applies to read or write addresses.\n + /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write + /// addresses are wrapped. + RING_SEL: u1, + /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. + /// Disable by setting CHAIN_TO = _(this channel)_.\n + /// Reset value is equal to channel number (8). + CHAIN_TO: u4, + /// Select a Transfer Request signal.\n + /// The channel uses the transfer request signal to pace its data transfer rate. + /// Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request + /// from the system).\n + /// 0x0 to 0x3a -> select DREQ n as TREQ + TREQ_SEL: u6, + /// In QUIET mode, the channel does not generate IRQs at the end of every transfer + /// block. Instead, an IRQ is raised when NULL is written to a trigger register, + /// indicating the end of a control block chain.\n\n + /// This reduces the number of interrupts to be serviced by the CPU when + /// transferring a DMA chain of many small control blocks. + IRQ_QUIET: u1, + /// Apply byte-swap transformation to DMA data.\n + /// For byte data, this has no effect. For halfword data, the two bytes of each + /// halfword are swapped. For word data, the four bytes of each word are swapped to + /// reverse order. + BSWAP: u1, + /// If 1, this channel's data transfers are visible to the sniff hardware, and each + /// transfer will advance the state of the checksum. This only applies if the sniff + /// hardware is enabled, and has this channel selected.\n\n + /// This allows checksum to be enabled or disabled on a per-control- block basis. + SNIFF_EN: u1, + /// This flag goes high when the channel starts a new transfer sequence, and low + /// when the last transfer of that sequence completes. Clearing EN while BUSY is + /// high pauses the channel, and BUSY will stay high while paused.\n\n + /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + BUSY: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + /// If 1, the channel received a write bus error. Write one to clear.\n + /// WRITE_ADDR shows the approximate address where the bus error was encountered + /// (will not to be earlier, or more than 5 transfers later) + WRITE_ERROR: u1, + /// If 1, the channel received a read bus error. Write one to clear.\n + /// READ_ADDR shows the approximate address where the bus error was encountered + /// (will not to be earlier, or more than 3 transfers later) + READ_ERROR: u1, + /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it + /// encounters any bus error, and always raises its channel IRQ flag. + AHB_ERROR: u1, + }), base_address + 0x20c); + + /// address: 0x50000210 + /// Alias for channel 8 CTRL register + pub const CH8_AL1_CTRL = @intToPtr(*volatile u32, base_address + 0x210); + + /// address: 0x50000214 + /// Alias for channel 8 READ_ADDR register + pub const CH8_AL1_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x214); + + /// address: 0x50000218 + /// Alias for channel 8 WRITE_ADDR register + pub const CH8_AL1_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x218); + + /// address: 0x5000021c + /// Alias for channel 8 TRANS_COUNT register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH8_AL1_TRANS_COUNT_TRIG = @intToPtr(*volatile u32, base_address + 0x21c); + + /// address: 0x50000220 + /// Alias for channel 8 CTRL register + pub const CH8_AL2_CTRL = @intToPtr(*volatile u32, base_address + 0x220); + + /// address: 0x50000224 + /// Alias for channel 8 TRANS_COUNT register + pub const CH8_AL2_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x224); + + /// address: 0x50000228 + /// Alias for channel 8 READ_ADDR register + pub const CH8_AL2_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x228); + + /// address: 0x5000022c + /// Alias for channel 8 WRITE_ADDR register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH8_AL2_WRITE_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x22c); + + /// address: 0x50000230 + /// Alias for channel 8 CTRL register + pub const CH8_AL3_CTRL = @intToPtr(*volatile u32, base_address + 0x230); + + /// address: 0x50000234 + /// Alias for channel 8 WRITE_ADDR register + pub const CH8_AL3_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x234); + + /// address: 0x50000238 + /// Alias for channel 8 TRANS_COUNT register + pub const CH8_AL3_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x238); + + /// address: 0x5000023c + /// Alias for channel 8 READ_ADDR register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH8_AL3_READ_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x23c); + + /// address: 0x50000240 + /// DMA Channel 9 Read Address pointer\n + /// This register updates automatically each time a read completes. The current + /// value is the next address to be read by this channel. + pub const CH9_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x240); + + /// address: 0x50000244 + /// DMA Channel 9 Write Address pointer\n + /// This register updates automatically each time a write completes. The current + /// value is the next address to be written by this channel. + pub const CH9_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x244); + + /// address: 0x50000248 + /// DMA Channel 9 Transfer Count\n + /// Program the number of bus transfers a channel will perform before halting. Note + /// that, if transfers are larger than one byte in size, this is not equal to the + /// number of bytes transferred (see CTRL_DATA_SIZE).\n\n + /// When the channel is active, reading this register shows the number of transfers + /// remaining, updating automatically each time a write transfer completes.\n\n + /// Writing this register sets the RELOAD value for the transfer counter. Each time + /// this channel is triggered, the RELOAD value is copied into the live transfer + /// counter. The channel can be started multiple times, and will perform the same + /// number of transfers each time, as programmed by most recent write.\n\n + /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a + /// trigger, the written value is used immediately as the length of the new transfer + /// sequence, as well as being written to RELOAD. + pub const CH9_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x248); + + /// address: 0x5000024c + /// DMA Channel 9 Control and Status + pub const CH9_CTRL_TRIG = @intToPtr(*volatile Mmio(32, packed struct { + /// DMA Channel Enable.\n + /// When 1, the channel will respond to triggering events, which will cause it to + /// become BUSY and start transferring data. When 0, the channel will ignore + /// triggers, stop issuing transfers, and pause the current transfer sequence (i.e. + /// BUSY will remain high if already high) + EN: u1, + /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in + /// each scheduling round, all high priority channels are considered first, and then + /// only a single low priority channel, before returning to the high priority + /// channels.\n\n + /// This only affects the order in which the DMA schedules channels. The DMA's bus + /// priority is not changed. If the DMA is not saturated then a low priority channel + /// will see no loss of throughput. + HIGH_PRIORITY: u1, + /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR + /// advance by this amount (1/2/4 bytes) with each transfer. + DATA_SIZE: u2, + /// If 1, the read address increments with each transfer. If 0, each read is + /// directed to the same, initial address.\n\n + /// Generally this should be disabled for peripheral-to-memory transfers. + INCR_READ: u1, + /// If 1, the write address increments with each transfer. If 0, each write is + /// directed to the same, initial address.\n\n + /// Generally this should be disabled for memory-to-peripheral transfers. + INCR_WRITE: u1, + /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower + /// n bits of the address will change. This wraps the address on a (1 << n) byte + /// boundary, facilitating access to naturally-aligned ring buffers.\n\n + /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read + /// or write addresses, based on value of RING_SEL. + RING_SIZE: u4, + /// Select whether RING_SIZE applies to read or write addresses.\n + /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write + /// addresses are wrapped. + RING_SEL: u1, + /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. + /// Disable by setting CHAIN_TO = _(this channel)_.\n + /// Reset value is equal to channel number (9). + CHAIN_TO: u4, + /// Select a Transfer Request signal.\n + /// The channel uses the transfer request signal to pace its data transfer rate. + /// Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request + /// from the system).\n + /// 0x0 to 0x3a -> select DREQ n as TREQ + TREQ_SEL: u6, + /// In QUIET mode, the channel does not generate IRQs at the end of every transfer + /// block. Instead, an IRQ is raised when NULL is written to a trigger register, + /// indicating the end of a control block chain.\n\n + /// This reduces the number of interrupts to be serviced by the CPU when + /// transferring a DMA chain of many small control blocks. + IRQ_QUIET: u1, + /// Apply byte-swap transformation to DMA data.\n + /// For byte data, this has no effect. For halfword data, the two bytes of each + /// halfword are swapped. For word data, the four bytes of each word are swapped to + /// reverse order. + BSWAP: u1, + /// If 1, this channel's data transfers are visible to the sniff hardware, and each + /// transfer will advance the state of the checksum. This only applies if the sniff + /// hardware is enabled, and has this channel selected.\n\n + /// This allows checksum to be enabled or disabled on a per-control- block basis. + SNIFF_EN: u1, + /// This flag goes high when the channel starts a new transfer sequence, and low + /// when the last transfer of that sequence completes. Clearing EN while BUSY is + /// high pauses the channel, and BUSY will stay high while paused.\n\n + /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + BUSY: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + /// If 1, the channel received a write bus error. Write one to clear.\n + /// WRITE_ADDR shows the approximate address where the bus error was encountered + /// (will not to be earlier, or more than 5 transfers later) + WRITE_ERROR: u1, + /// If 1, the channel received a read bus error. Write one to clear.\n + /// READ_ADDR shows the approximate address where the bus error was encountered + /// (will not to be earlier, or more than 3 transfers later) + READ_ERROR: u1, + /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it + /// encounters any bus error, and always raises its channel IRQ flag. + AHB_ERROR: u1, + }), base_address + 0x24c); + + /// address: 0x50000250 + /// Alias for channel 9 CTRL register + pub const CH9_AL1_CTRL = @intToPtr(*volatile u32, base_address + 0x250); + + /// address: 0x50000254 + /// Alias for channel 9 READ_ADDR register + pub const CH9_AL1_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x254); + + /// address: 0x50000258 + /// Alias for channel 9 WRITE_ADDR register + pub const CH9_AL1_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x258); + + /// address: 0x5000025c + /// Alias for channel 9 TRANS_COUNT register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH9_AL1_TRANS_COUNT_TRIG = @intToPtr(*volatile u32, base_address + 0x25c); + + /// address: 0x50000260 + /// Alias for channel 9 CTRL register + pub const CH9_AL2_CTRL = @intToPtr(*volatile u32, base_address + 0x260); + + /// address: 0x50000264 + /// Alias for channel 9 TRANS_COUNT register + pub const CH9_AL2_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x264); + + /// address: 0x50000268 + /// Alias for channel 9 READ_ADDR register + pub const CH9_AL2_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x268); + + /// address: 0x5000026c + /// Alias for channel 9 WRITE_ADDR register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH9_AL2_WRITE_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x26c); + + /// address: 0x50000270 + /// Alias for channel 9 CTRL register + pub const CH9_AL3_CTRL = @intToPtr(*volatile u32, base_address + 0x270); + + /// address: 0x50000274 + /// Alias for channel 9 WRITE_ADDR register + pub const CH9_AL3_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x274); + + /// address: 0x50000278 + /// Alias for channel 9 TRANS_COUNT register + pub const CH9_AL3_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x278); + + /// address: 0x5000027c + /// Alias for channel 9 READ_ADDR register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH9_AL3_READ_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x27c); + + /// address: 0x50000280 + /// DMA Channel 10 Read Address pointer\n + /// This register updates automatically each time a read completes. The current + /// value is the next address to be read by this channel. + pub const CH10_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x280); + + /// address: 0x50000284 + /// DMA Channel 10 Write Address pointer\n + /// This register updates automatically each time a write completes. The current + /// value is the next address to be written by this channel. + pub const CH10_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x284); + + /// address: 0x50000288 + /// DMA Channel 10 Transfer Count\n + /// Program the number of bus transfers a channel will perform before halting. Note + /// that, if transfers are larger than one byte in size, this is not equal to the + /// number of bytes transferred (see CTRL_DATA_SIZE).\n\n + /// When the channel is active, reading this register shows the number of transfers + /// remaining, updating automatically each time a write transfer completes.\n\n + /// Writing this register sets the RELOAD value for the transfer counter. Each time + /// this channel is triggered, the RELOAD value is copied into the live transfer + /// counter. The channel can be started multiple times, and will perform the same + /// number of transfers each time, as programmed by most recent write.\n\n + /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a + /// trigger, the written value is used immediately as the length of the new transfer + /// sequence, as well as being written to RELOAD. + pub const CH10_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x288); + + /// address: 0x5000028c + /// DMA Channel 10 Control and Status + pub const CH10_CTRL_TRIG = @intToPtr(*volatile Mmio(32, packed struct { + /// DMA Channel Enable.\n + /// When 1, the channel will respond to triggering events, which will cause it to + /// become BUSY and start transferring data. When 0, the channel will ignore + /// triggers, stop issuing transfers, and pause the current transfer sequence (i.e. + /// BUSY will remain high if already high) + EN: u1, + /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in + /// each scheduling round, all high priority channels are considered first, and then + /// only a single low priority channel, before returning to the high priority + /// channels.\n\n + /// This only affects the order in which the DMA schedules channels. The DMA's bus + /// priority is not changed. If the DMA is not saturated then a low priority channel + /// will see no loss of throughput. + HIGH_PRIORITY: u1, + /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR + /// advance by this amount (1/2/4 bytes) with each transfer. + DATA_SIZE: u2, + /// If 1, the read address increments with each transfer. If 0, each read is + /// directed to the same, initial address.\n\n + /// Generally this should be disabled for peripheral-to-memory transfers. + INCR_READ: u1, + /// If 1, the write address increments with each transfer. If 0, each write is + /// directed to the same, initial address.\n\n + /// Generally this should be disabled for memory-to-peripheral transfers. + INCR_WRITE: u1, + /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower + /// n bits of the address will change. This wraps the address on a (1 << n) byte + /// boundary, facilitating access to naturally-aligned ring buffers.\n\n + /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read + /// or write addresses, based on value of RING_SEL. + RING_SIZE: u4, + /// Select whether RING_SIZE applies to read or write addresses.\n + /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write + /// addresses are wrapped. + RING_SEL: u1, + /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. + /// Disable by setting CHAIN_TO = _(this channel)_.\n + /// Reset value is equal to channel number (10). + CHAIN_TO: u4, + /// Select a Transfer Request signal.\n + /// The channel uses the transfer request signal to pace its data transfer rate. + /// Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request + /// from the system).\n + /// 0x0 to 0x3a -> select DREQ n as TREQ + TREQ_SEL: u6, + /// In QUIET mode, the channel does not generate IRQs at the end of every transfer + /// block. Instead, an IRQ is raised when NULL is written to a trigger register, + /// indicating the end of a control block chain.\n\n + /// This reduces the number of interrupts to be serviced by the CPU when + /// transferring a DMA chain of many small control blocks. + IRQ_QUIET: u1, + /// Apply byte-swap transformation to DMA data.\n + /// For byte data, this has no effect. For halfword data, the two bytes of each + /// halfword are swapped. For word data, the four bytes of each word are swapped to + /// reverse order. + BSWAP: u1, + /// If 1, this channel's data transfers are visible to the sniff hardware, and each + /// transfer will advance the state of the checksum. This only applies if the sniff + /// hardware is enabled, and has this channel selected.\n\n + /// This allows checksum to be enabled or disabled on a per-control- block basis. + SNIFF_EN: u1, + /// This flag goes high when the channel starts a new transfer sequence, and low + /// when the last transfer of that sequence completes. Clearing EN while BUSY is + /// high pauses the channel, and BUSY will stay high while paused.\n\n + /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + BUSY: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + /// If 1, the channel received a write bus error. Write one to clear.\n + /// WRITE_ADDR shows the approximate address where the bus error was encountered + /// (will not to be earlier, or more than 5 transfers later) + WRITE_ERROR: u1, + /// If 1, the channel received a read bus error. Write one to clear.\n + /// READ_ADDR shows the approximate address where the bus error was encountered + /// (will not to be earlier, or more than 3 transfers later) + READ_ERROR: u1, + /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it + /// encounters any bus error, and always raises its channel IRQ flag. + AHB_ERROR: u1, + }), base_address + 0x28c); + + /// address: 0x50000290 + /// Alias for channel 10 CTRL register + pub const CH10_AL1_CTRL = @intToPtr(*volatile u32, base_address + 0x290); + + /// address: 0x50000294 + /// Alias for channel 10 READ_ADDR register + pub const CH10_AL1_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x294); + + /// address: 0x50000298 + /// Alias for channel 10 WRITE_ADDR register + pub const CH10_AL1_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x298); + + /// address: 0x5000029c + /// Alias for channel 10 TRANS_COUNT register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH10_AL1_TRANS_COUNT_TRIG = @intToPtr(*volatile u32, base_address + 0x29c); + + /// address: 0x500002a0 + /// Alias for channel 10 CTRL register + pub const CH10_AL2_CTRL = @intToPtr(*volatile u32, base_address + 0x2a0); + + /// address: 0x500002a4 + /// Alias for channel 10 TRANS_COUNT register + pub const CH10_AL2_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x2a4); + + /// address: 0x500002a8 + /// Alias for channel 10 READ_ADDR register + pub const CH10_AL2_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x2a8); + + /// address: 0x500002ac + /// Alias for channel 10 WRITE_ADDR register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH10_AL2_WRITE_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x2ac); + + /// address: 0x500002b0 + /// Alias for channel 10 CTRL register + pub const CH10_AL3_CTRL = @intToPtr(*volatile u32, base_address + 0x2b0); + + /// address: 0x500002b4 + /// Alias for channel 10 WRITE_ADDR register + pub const CH10_AL3_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x2b4); + + /// address: 0x500002b8 + /// Alias for channel 10 TRANS_COUNT register + pub const CH10_AL3_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x2b8); + + /// address: 0x500002bc + /// Alias for channel 10 READ_ADDR register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH10_AL3_READ_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x2bc); + + /// address: 0x500002c0 + /// DMA Channel 11 Read Address pointer\n + /// This register updates automatically each time a read completes. The current + /// value is the next address to be read by this channel. + pub const CH11_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x2c0); + + /// address: 0x500002c4 + /// DMA Channel 11 Write Address pointer\n + /// This register updates automatically each time a write completes. The current + /// value is the next address to be written by this channel. + pub const CH11_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x2c4); + + /// address: 0x500002c8 + /// DMA Channel 11 Transfer Count\n + /// Program the number of bus transfers a channel will perform before halting. Note + /// that, if transfers are larger than one byte in size, this is not equal to the + /// number of bytes transferred (see CTRL_DATA_SIZE).\n\n + /// When the channel is active, reading this register shows the number of transfers + /// remaining, updating automatically each time a write transfer completes.\n\n + /// Writing this register sets the RELOAD value for the transfer counter. Each time + /// this channel is triggered, the RELOAD value is copied into the live transfer + /// counter. The channel can be started multiple times, and will perform the same + /// number of transfers each time, as programmed by most recent write.\n\n + /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a + /// trigger, the written value is used immediately as the length of the new transfer + /// sequence, as well as being written to RELOAD. + pub const CH11_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x2c8); + + /// address: 0x500002cc + /// DMA Channel 11 Control and Status + pub const CH11_CTRL_TRIG = @intToPtr(*volatile Mmio(32, packed struct { + /// DMA Channel Enable.\n + /// When 1, the channel will respond to triggering events, which will cause it to + /// become BUSY and start transferring data. When 0, the channel will ignore + /// triggers, stop issuing transfers, and pause the current transfer sequence (i.e. + /// BUSY will remain high if already high) + EN: u1, + /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in + /// each scheduling round, all high priority channels are considered first, and then + /// only a single low priority channel, before returning to the high priority + /// channels.\n\n + /// This only affects the order in which the DMA schedules channels. The DMA's bus + /// priority is not changed. If the DMA is not saturated then a low priority channel + /// will see no loss of throughput. + HIGH_PRIORITY: u1, + /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR + /// advance by this amount (1/2/4 bytes) with each transfer. + DATA_SIZE: u2, + /// If 1, the read address increments with each transfer. If 0, each read is + /// directed to the same, initial address.\n\n + /// Generally this should be disabled for peripheral-to-memory transfers. + INCR_READ: u1, + /// If 1, the write address increments with each transfer. If 0, each write is + /// directed to the same, initial address.\n\n + /// Generally this should be disabled for memory-to-peripheral transfers. + INCR_WRITE: u1, + /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower + /// n bits of the address will change. This wraps the address on a (1 << n) byte + /// boundary, facilitating access to naturally-aligned ring buffers.\n\n + /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read + /// or write addresses, based on value of RING_SEL. + RING_SIZE: u4, + /// Select whether RING_SIZE applies to read or write addresses.\n + /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write + /// addresses are wrapped. + RING_SEL: u1, + /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. + /// Disable by setting CHAIN_TO = _(this channel)_.\n + /// Reset value is equal to channel number (11). + CHAIN_TO: u4, + /// Select a Transfer Request signal.\n + /// The channel uses the transfer request signal to pace its data transfer rate. + /// Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request + /// from the system).\n + /// 0x0 to 0x3a -> select DREQ n as TREQ + TREQ_SEL: u6, + /// In QUIET mode, the channel does not generate IRQs at the end of every transfer + /// block. Instead, an IRQ is raised when NULL is written to a trigger register, + /// indicating the end of a control block chain.\n\n + /// This reduces the number of interrupts to be serviced by the CPU when + /// transferring a DMA chain of many small control blocks. + IRQ_QUIET: u1, + /// Apply byte-swap transformation to DMA data.\n + /// For byte data, this has no effect. For halfword data, the two bytes of each + /// halfword are swapped. For word data, the four bytes of each word are swapped to + /// reverse order. + BSWAP: u1, + /// If 1, this channel's data transfers are visible to the sniff hardware, and each + /// transfer will advance the state of the checksum. This only applies if the sniff + /// hardware is enabled, and has this channel selected.\n\n + /// This allows checksum to be enabled or disabled on a per-control- block basis. + SNIFF_EN: u1, + /// This flag goes high when the channel starts a new transfer sequence, and low + /// when the last transfer of that sequence completes. Clearing EN while BUSY is + /// high pauses the channel, and BUSY will stay high while paused.\n\n + /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + BUSY: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + /// If 1, the channel received a write bus error. Write one to clear.\n + /// WRITE_ADDR shows the approximate address where the bus error was encountered + /// (will not to be earlier, or more than 5 transfers later) + WRITE_ERROR: u1, + /// If 1, the channel received a read bus error. Write one to clear.\n + /// READ_ADDR shows the approximate address where the bus error was encountered + /// (will not to be earlier, or more than 3 transfers later) + READ_ERROR: u1, + /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it + /// encounters any bus error, and always raises its channel IRQ flag. + AHB_ERROR: u1, + }), base_address + 0x2cc); + + /// address: 0x500002d0 + /// Alias for channel 11 CTRL register + pub const CH11_AL1_CTRL = @intToPtr(*volatile u32, base_address + 0x2d0); + + /// address: 0x500002d4 + /// Alias for channel 11 READ_ADDR register + pub const CH11_AL1_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x2d4); + + /// address: 0x500002d8 + /// Alias for channel 11 WRITE_ADDR register + pub const CH11_AL1_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x2d8); + + /// address: 0x500002dc + /// Alias for channel 11 TRANS_COUNT register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH11_AL1_TRANS_COUNT_TRIG = @intToPtr(*volatile u32, base_address + 0x2dc); + + /// address: 0x500002e0 + /// Alias for channel 11 CTRL register + pub const CH11_AL2_CTRL = @intToPtr(*volatile u32, base_address + 0x2e0); + + /// address: 0x500002e4 + /// Alias for channel 11 TRANS_COUNT register + pub const CH11_AL2_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x2e4); + + /// address: 0x500002e8 + /// Alias for channel 11 READ_ADDR register + pub const CH11_AL2_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x2e8); + + /// address: 0x500002ec + /// Alias for channel 11 WRITE_ADDR register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH11_AL2_WRITE_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x2ec); + + /// address: 0x500002f0 + /// Alias for channel 11 CTRL register + pub const CH11_AL3_CTRL = @intToPtr(*volatile u32, base_address + 0x2f0); + + /// address: 0x500002f4 + /// Alias for channel 11 WRITE_ADDR register + pub const CH11_AL3_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x2f4); + + /// address: 0x500002f8 + /// Alias for channel 11 TRANS_COUNT register + pub const CH11_AL3_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x2f8); + + /// address: 0x500002fc + /// Alias for channel 11 READ_ADDR register\n + /// This is a trigger register (0xc). Writing a nonzero value will\n + /// reload the channel counter and start the channel. + pub const CH11_AL3_READ_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x2fc); + + /// address: 0x50000400 + /// Interrupt Status (raw) + pub const INTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x400); + + /// address: 0x50000404 + /// Interrupt Enables for IRQ 0 + pub const INTE0 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x404); + + /// address: 0x50000408 + /// Force Interrupts + pub const INTF0 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x408); + + /// address: 0x5000040c + /// Interrupt Status for IRQ 0 + pub const INTS0 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x40c); + + /// address: 0x50000414 + /// Interrupt Enables for IRQ 1 + pub const INTE1 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x414); + + /// address: 0x50000418 + /// Force Interrupts for IRQ 1 + pub const INTF1 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x418); + + /// address: 0x5000041c + /// Interrupt Status (masked) for IRQ 1 + pub const INTS1 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x41c); + + /// address: 0x50000420 + /// Pacing (X/Y) Fractional Timer\n + /// The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). + /// This equation is evaluated every sys_clk cycles and therefore can only generate + /// TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. + pub const TIMER0 = @intToPtr(*volatile Mmio(32, packed struct { + /// Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. + Y: u16, + /// Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. + X: u16, + }), base_address + 0x420); + + /// address: 0x50000424 + /// Pacing (X/Y) Fractional Timer\n + /// The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). + /// This equation is evaluated every sys_clk cycles and therefore can only generate + /// TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. + pub const TIMER1 = @intToPtr(*volatile Mmio(32, packed struct { + /// Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. + Y: u16, + /// Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. + X: u16, + }), base_address + 0x424); + + /// address: 0x50000428 + /// Pacing (X/Y) Fractional Timer\n + /// The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). + /// This equation is evaluated every sys_clk cycles and therefore can only generate + /// TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. + pub const TIMER2 = @intToPtr(*volatile Mmio(32, packed struct { + /// Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. + Y: u16, + /// Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. + X: u16, + }), base_address + 0x428); + + /// address: 0x5000042c + /// Pacing (X/Y) Fractional Timer\n + /// The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). + /// This equation is evaluated every sys_clk cycles and therefore can only generate + /// TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. + pub const TIMER3 = @intToPtr(*volatile Mmio(32, packed struct { + /// Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. + Y: u16, + /// Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. + X: u16, + }), base_address + 0x42c); + + /// address: 0x50000430 + /// Trigger one or more channels simultaneously + pub const MULTI_CHAN_TRIGGER = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x430); + + /// address: 0x50000434 + /// Sniffer Control + pub const SNIFF_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// Enable sniffer + EN: u1, + /// DMA channel for Sniffer to observe + DMACH: u4, + CALC: u4, + /// Locally perform a byte reverse on the sniffed data, before feeding into + /// checksum.\n\n + /// Note that the sniff hardware is downstream of the DMA channel byteswap performed + /// in the read master: if channel CTRL_BSWAP and SNIFF_CTRL_BSWAP are both enabled, + /// their effects cancel from the sniffer's point of view. + BSWAP: u1, + /// If set, the result appears bit-reversed when read. This does not affect the way + /// the checksum is calculated; the result is transformed on-the-fly between the + /// result register and the bus. + OUT_REV: u1, + /// If set, the result appears inverted (bitwise complement) when read. This does + /// not affect the way the checksum is calculated; the result is transformed + /// on-the-fly between the result register and the bus. + OUT_INV: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x434); + + /// address: 0x50000438 + /// Data accumulator for sniff hardware\n + /// Write an initial seed value here before starting a DMA transfer on the channel + /// indicated by SNIFF_CTRL_DMACH. The hardware will update this register each time + /// it observes a read from the indicated channel. Once the channel completes, the + /// final result can be read from this register. + pub const SNIFF_DATA = @intToPtr(*volatile u32, base_address + 0x438); + + /// address: 0x50000440 + /// Debug RAF, WAF, TDF levels + pub const FIFO_LEVELS = @intToPtr(*volatile Mmio(32, packed struct { + /// Current Transfer-Data-FIFO fill level + TDF_LVL: u8, + /// Current Write-Address-FIFO fill level + WAF_LVL: u8, + /// Current Read-Address-FIFO fill level + RAF_LVL: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0x440); + + /// address: 0x50000444 + /// Abort an in-progress transfer sequence on one or more channels + pub const CHAN_ABORT = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x444); + + /// address: 0x50000448 + /// The number of channels this DMA instance is equipped with. This DMA supports up + /// to 16 hardware channels, but can be configured with as few as one, to minimise + /// silicon area. + pub const N_CHANNELS = @intToPtr(*volatile MmioInt(32, u5), base_address + 0x448); + + /// address: 0x50000800 + /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can + /// perform on the peripheral without overflow/underflow. Write any value: clears + /// the counter, and cause channel to re-initiate DREQ handshake. + pub const CH0_DBG_CTDREQ = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x800); + + /// address: 0x50000804 + /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next + /// transfer + pub const CH0_DBG_TCR = @intToPtr(*volatile u32, base_address + 0x804); + + /// address: 0x50000840 + /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can + /// perform on the peripheral without overflow/underflow. Write any value: clears + /// the counter, and cause channel to re-initiate DREQ handshake. + pub const CH1_DBG_CTDREQ = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x840); + + /// address: 0x50000844 + /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next + /// transfer + pub const CH1_DBG_TCR = @intToPtr(*volatile u32, base_address + 0x844); + + /// address: 0x50000880 + /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can + /// perform on the peripheral without overflow/underflow. Write any value: clears + /// the counter, and cause channel to re-initiate DREQ handshake. + pub const CH2_DBG_CTDREQ = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x880); + + /// address: 0x50000884 + /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next + /// transfer + pub const CH2_DBG_TCR = @intToPtr(*volatile u32, base_address + 0x884); + + /// address: 0x500008c0 + /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can + /// perform on the peripheral without overflow/underflow. Write any value: clears + /// the counter, and cause channel to re-initiate DREQ handshake. + pub const CH3_DBG_CTDREQ = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x8c0); + + /// address: 0x500008c4 + /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next + /// transfer + pub const CH3_DBG_TCR = @intToPtr(*volatile u32, base_address + 0x8c4); + + /// address: 0x50000900 + /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can + /// perform on the peripheral without overflow/underflow. Write any value: clears + /// the counter, and cause channel to re-initiate DREQ handshake. + pub const CH4_DBG_CTDREQ = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x900); + + /// address: 0x50000904 + /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next + /// transfer + pub const CH4_DBG_TCR = @intToPtr(*volatile u32, base_address + 0x904); + + /// address: 0x50000940 + /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can + /// perform on the peripheral without overflow/underflow. Write any value: clears + /// the counter, and cause channel to re-initiate DREQ handshake. + pub const CH5_DBG_CTDREQ = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x940); + + /// address: 0x50000944 + /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next + /// transfer + pub const CH5_DBG_TCR = @intToPtr(*volatile u32, base_address + 0x944); + + /// address: 0x50000980 + /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can + /// perform on the peripheral without overflow/underflow. Write any value: clears + /// the counter, and cause channel to re-initiate DREQ handshake. + pub const CH6_DBG_CTDREQ = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x980); + + /// address: 0x50000984 + /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next + /// transfer + pub const CH6_DBG_TCR = @intToPtr(*volatile u32, base_address + 0x984); + + /// address: 0x500009c0 + /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can + /// perform on the peripheral without overflow/underflow. Write any value: clears + /// the counter, and cause channel to re-initiate DREQ handshake. + pub const CH7_DBG_CTDREQ = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x9c0); + + /// address: 0x500009c4 + /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next + /// transfer + pub const CH7_DBG_TCR = @intToPtr(*volatile u32, base_address + 0x9c4); + + /// address: 0x50000a00 + /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can + /// perform on the peripheral without overflow/underflow. Write any value: clears + /// the counter, and cause channel to re-initiate DREQ handshake. + pub const CH8_DBG_CTDREQ = @intToPtr(*volatile MmioInt(32, u6), base_address + 0xa00); + + /// address: 0x50000a04 + /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next + /// transfer + pub const CH8_DBG_TCR = @intToPtr(*volatile u32, base_address + 0xa04); + + /// address: 0x50000a40 + /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can + /// perform on the peripheral without overflow/underflow. Write any value: clears + /// the counter, and cause channel to re-initiate DREQ handshake. + pub const CH9_DBG_CTDREQ = @intToPtr(*volatile MmioInt(32, u6), base_address + 0xa40); + + /// address: 0x50000a44 + /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next + /// transfer + pub const CH9_DBG_TCR = @intToPtr(*volatile u32, base_address + 0xa44); + + /// address: 0x50000a80 + /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can + /// perform on the peripheral without overflow/underflow. Write any value: clears + /// the counter, and cause channel to re-initiate DREQ handshake. + pub const CH10_DBG_CTDREQ = @intToPtr(*volatile MmioInt(32, u6), base_address + 0xa80); + + /// address: 0x50000a84 + /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next + /// transfer + pub const CH10_DBG_TCR = @intToPtr(*volatile u32, base_address + 0xa84); + + /// address: 0x50000ac0 + /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can + /// perform on the peripheral without overflow/underflow. Write any value: clears + /// the counter, and cause channel to re-initiate DREQ handshake. + pub const CH11_DBG_CTDREQ = @intToPtr(*volatile MmioInt(32, u6), base_address + 0xac0); + + /// address: 0x50000ac4 + /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next + /// transfer + pub const CH11_DBG_TCR = @intToPtr(*volatile u32, base_address + 0xac4); + }; + + /// DPRAM layout for USB device. + pub const USBCTRL_DPRAM = struct { + pub const base_address = 0x50100000; + pub const version = "1"; + + /// address: 0x50100000 + /// Bytes 0-3 of the SETUP packet from the host. + pub const SETUP_PACKET_LOW = @intToPtr(*volatile Mmio(32, packed struct { + BMREQUESTTYPE: u8, + BREQUEST: u8, + WVALUE: u16, + }), base_address + 0x0); + + /// address: 0x50100004 + /// Bytes 4-7 of the setup packet from the host. + pub const SETUP_PACKET_HIGH = @intToPtr(*volatile Mmio(32, packed struct { + WINDEX: u16, + WLENGTH: u16, + }), base_address + 0x4); + + /// address: 0x50100008 + pub const EP1_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x8); + + /// address: 0x5010000c + pub const EP1_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0xc); + + /// address: 0x50100010 + pub const EP2_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x10); + + /// address: 0x50100014 + pub const EP2_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x14); + + /// address: 0x50100018 + pub const EP3_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x18); + + /// address: 0x5010001c + pub const EP3_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x1c); + + /// address: 0x50100020 + pub const EP4_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x20); + + /// address: 0x50100024 + pub const EP4_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x24); + + /// address: 0x50100028 + pub const EP5_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x28); + + /// address: 0x5010002c + pub const EP5_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x2c); + + /// address: 0x50100030 + pub const EP6_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x30); + + /// address: 0x50100034 + pub const EP6_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x34); + + /// address: 0x50100038 + pub const EP7_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x38); + + /// address: 0x5010003c + pub const EP7_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x3c); + + /// address: 0x50100040 + pub const EP8_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x40); + + /// address: 0x50100044 + pub const EP8_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x44); + + /// address: 0x50100048 + pub const EP9_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x48); + + /// address: 0x5010004c + pub const EP9_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x4c); + + /// address: 0x50100050 + pub const EP10_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x50); + + /// address: 0x50100054 + pub const EP10_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x54); + + /// address: 0x50100058 + pub const EP11_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x58); + + /// address: 0x5010005c + pub const EP11_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x5c); + + /// address: 0x50100060 + pub const EP12_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x60); + + /// address: 0x50100064 + pub const EP12_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x64); + + /// address: 0x50100068 + pub const EP13_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x68); + + /// address: 0x5010006c + pub const EP13_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x6c); + + /// address: 0x50100070 + pub const EP14_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x70); + + /// address: 0x50100074 + pub const EP14_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x74); + + /// address: 0x50100078 + pub const EP15_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x78); + + /// address: 0x5010007c + pub const EP15_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to + /// the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + ENDPOINT_TYPE: u2, + /// Trigger an interrupt each time both buffers are done. Only valid in double + /// buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint + /// if this bit is not set. + ENABLE: u1, + }), base_address + 0x7c); + + /// address: 0x50100080 + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP0_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0x80); + + /// address: 0x50100084 + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP0_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0x84); + + /// address: 0x50100088 + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP1_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0x88); + + /// address: 0x5010008c + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP1_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0x8c); + + /// address: 0x50100090 + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP2_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0x90); + + /// address: 0x50100094 + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP2_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0x94); + + /// address: 0x50100098 + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP3_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0x98); + + /// address: 0x5010009c + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP3_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0x9c); + + /// address: 0x501000a0 + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP4_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0xa0); + + /// address: 0x501000a4 + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP4_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0xa4); + + /// address: 0x501000a8 + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP5_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0xa8); + + /// address: 0x501000ac + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP5_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0xac); + + /// address: 0x501000b0 + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP6_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0xb0); + + /// address: 0x501000b4 + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP6_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0xb4); + + /// address: 0x501000b8 + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP7_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0xb8); + + /// address: 0x501000bc + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP7_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0xbc); + + /// address: 0x501000c0 + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP8_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0xc0); + + /// address: 0x501000c4 + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP8_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0xc4); + + /// address: 0x501000c8 + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP9_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0xc8); + + /// address: 0x501000cc + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP9_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0xcc); + + /// address: 0x501000d0 + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP10_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0xd0); + + /// address: 0x501000d4 + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP10_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0xd4); + + /// address: 0x501000d8 + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP11_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0xd8); + + /// address: 0x501000dc + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP11_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0xdc); + + /// address: 0x501000e0 + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP12_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0xe0); + + /// address: 0x501000e4 + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP12_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0xe4); + + /// address: 0x501000e8 + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP13_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0xe8); + + /// address: 0x501000ec + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP13_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0xec); + + /// address: 0x501000f0 + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP14_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0xf0); + + /// address: 0x501000f4 + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP14_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0xf4); + + /// address: 0x501000f8 + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP15_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0xf8); + + /// address: 0x501000fc + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for + /// buffer 1.\n + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the + /// endpoint is in double buffered mode. + pub const EP15_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the + /// controller. The controller clears the available bit when writing the status + /// back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only + /// valid in double buffered mode for an Isochronous endpoint.\n + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: u2, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate + /// the data is valid. For an OUT transfer (RX from the host) this bit should be + /// left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), base_address + 0xfc); + }; + + /// USB FS/LS controller device registers + pub const USBCTRL_REGS = struct { + pub const base_address = 0x50110000; + pub const version = "1"; + + /// address: 0x50110000 + /// Device address and endpoint control + pub const ADDR_ENDP = @intToPtr(*volatile Mmio(32, packed struct { + /// In device mode, the address that the device should respond to. Set in response + /// to a SET_ADDR setup packet from the host. In host mode set to the address of the + /// device to communicate with. + ADDRESS: u7, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + /// Device endpoint to send data to. Only valid for HOST mode. + ENDPOINT: u4, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + }), base_address + 0x0); + + /// address: 0x50110004 + /// Interrupt endpoint 1. Only valid for HOST mode. + pub const ADDR_ENDP1 = @intToPtr(*volatile Mmio(32, packed struct { + /// Device address + ADDRESS: u7, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x4); + + /// address: 0x50110008 + /// Interrupt endpoint 2. Only valid for HOST mode. + pub const ADDR_ENDP2 = @intToPtr(*volatile Mmio(32, packed struct { + /// Device address + ADDRESS: u7, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x8); + + /// address: 0x5011000c + /// Interrupt endpoint 3. Only valid for HOST mode. + pub const ADDR_ENDP3 = @intToPtr(*volatile Mmio(32, packed struct { + /// Device address + ADDRESS: u7, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0xc); + + /// address: 0x50110010 + /// Interrupt endpoint 4. Only valid for HOST mode. + pub const ADDR_ENDP4 = @intToPtr(*volatile Mmio(32, packed struct { + /// Device address + ADDRESS: u7, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x10); + + /// address: 0x50110014 + /// Interrupt endpoint 5. Only valid for HOST mode. + pub const ADDR_ENDP5 = @intToPtr(*volatile Mmio(32, packed struct { + /// Device address + ADDRESS: u7, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x14); + + /// address: 0x50110018 + /// Interrupt endpoint 6. Only valid for HOST mode. + pub const ADDR_ENDP6 = @intToPtr(*volatile Mmio(32, packed struct { + /// Device address + ADDRESS: u7, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x18); + + /// address: 0x5011001c + /// Interrupt endpoint 7. Only valid for HOST mode. + pub const ADDR_ENDP7 = @intToPtr(*volatile Mmio(32, packed struct { + /// Device address + ADDRESS: u7, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x1c); + + /// address: 0x50110020 + /// Interrupt endpoint 8. Only valid for HOST mode. + pub const ADDR_ENDP8 = @intToPtr(*volatile Mmio(32, packed struct { + /// Device address + ADDRESS: u7, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x20); + + /// address: 0x50110024 + /// Interrupt endpoint 9. Only valid for HOST mode. + pub const ADDR_ENDP9 = @intToPtr(*volatile Mmio(32, packed struct { + /// Device address + ADDRESS: u7, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x24); + + /// address: 0x50110028 + /// Interrupt endpoint 10. Only valid for HOST mode. + pub const ADDR_ENDP10 = @intToPtr(*volatile Mmio(32, packed struct { + /// Device address + ADDRESS: u7, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x28); + + /// address: 0x5011002c + /// Interrupt endpoint 11. Only valid for HOST mode. + pub const ADDR_ENDP11 = @intToPtr(*volatile Mmio(32, packed struct { + /// Device address + ADDRESS: u7, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x2c); + + /// address: 0x50110030 + /// Interrupt endpoint 12. Only valid for HOST mode. + pub const ADDR_ENDP12 = @intToPtr(*volatile Mmio(32, packed struct { + /// Device address + ADDRESS: u7, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x30); + + /// address: 0x50110034 + /// Interrupt endpoint 13. Only valid for HOST mode. + pub const ADDR_ENDP13 = @intToPtr(*volatile Mmio(32, packed struct { + /// Device address + ADDRESS: u7, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x34); + + /// address: 0x50110038 + /// Interrupt endpoint 14. Only valid for HOST mode. + pub const ADDR_ENDP14 = @intToPtr(*volatile Mmio(32, packed struct { + /// Device address + ADDRESS: u7, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x38); + + /// address: 0x5011003c + /// Interrupt endpoint 15. Only valid for HOST mode. + pub const ADDR_ENDP15 = @intToPtr(*volatile Mmio(32, packed struct { + /// Device address + ADDRESS: u7, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + }), base_address + 0x3c); + + /// address: 0x50110040 + /// Main control register + pub const MAIN_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// Enable controller + CONTROLLER_EN: u1, + /// Device mode = 0, Host mode = 1 + HOST_NDEVICE: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + reserved18: u1 = 0, + reserved19: u1 = 0, + reserved20: u1 = 0, + reserved21: u1 = 0, + reserved22: u1 = 0, + reserved23: u1 = 0, + reserved24: u1 = 0, + reserved25: u1 = 0, + reserved26: u1 = 0, + reserved27: u1 = 0, + reserved28: u1 = 0, + /// Reduced timings for simulation + SIM_TIMING: u1, + }), base_address + 0x40); + + /// address: 0x50110044 + /// Set the SOF (Start of Frame) frame number in the host controller. The SOF packet + /// is sent every 1ms and the host will increment the frame number by 1 each time. + pub const SOF_WR = @intToPtr(*volatile Mmio(32, packed struct { + COUNT: u11, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + }), base_address + 0x44); + + /// address: 0x50110048 + /// Read the last SOF (Start of Frame) frame number seen. In device mode the last + /// SOF received from the host. In host mode the last SOF sent by the host. + pub const SOF_RD = @intToPtr(*volatile Mmio(32, packed struct { + COUNT: u11, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + }), base_address + 0x48); + + /// address: 0x5011004c + /// SIE control register + pub const SIE_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// Host: Start transaction + START_TRANS: u1, + /// Host: Send Setup packet + SEND_SETUP: u1, + /// Host: Send transaction (OUT from host) + SEND_DATA: u1, + /// Host: Receive transaction (IN to host) + RECEIVE_DATA: u1, + /// Host: Stop transaction + STOP_TRANS: u1, + reserved0: u1 = 0, + /// Host: Preable enable for LS device on FS hub + PREAMBLE_EN: u1, + reserved1: u1 = 0, + /// Host: Delay packet(s) until after SOF + SOF_SYNC: u1, + /// Host: Enable SOF generation (for full speed bus) + SOF_EN: u1, + /// Host: Enable keep alive packet (for low speed bus) + KEEP_ALIVE_EN: u1, + /// Host: Enable VBUS + VBUS_EN: u1, + /// Device: Remote wakeup. Device can initiate its own resume after suspend. + RESUME: u1, + /// Host: Reset bus + RESET_BUS: u1, + reserved2: u1 = 0, + /// Host: Enable pull down resistors + PULLDOWN_EN: u1, + /// Device: Enable pull up resistor + PULLUP_EN: u1, + /// Device: Pull-up strength (0=1K2, 1=2k3) + RPU_OPT: u1, + /// Power down bus transceiver + TRANSCEIVER_PD: u1, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// Direct control of DM + DIRECT_DM: u1, + /// Direct control of DP + DIRECT_DP: u1, + /// Direct bus drive enable + DIRECT_EN: u1, + /// Device: Set bit in EP_STATUS_STALL_NAK when EP0 sends a NAK + EP0_INT_NAK: u1, + /// Device: Set bit in BUFF_STATUS for every 2 buffers completed on EP0 + EP0_INT_2BUF: u1, + /// Device: Set bit in BUFF_STATUS for every buffer completed on EP0 + EP0_INT_1BUF: u1, + /// Device: EP0 single buffered = 0, double buffered = 1 + EP0_DOUBLE_BUF: u1, + /// Device: Set bit in EP_STATUS_STALL_NAK when EP0 sends a STALL + EP0_INT_STALL: u1, + }), base_address + 0x4c); + + /// address: 0x50110050 + /// SIE status register + pub const SIE_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + /// Device: VBUS Detected + VBUS_DETECTED: u1, + reserved0: u1 = 0, + /// USB bus line state + LINE_STATE: u2, + /// Bus in suspended state. Valid for device and host. Host and device will go into + /// suspend if neither Keep Alive / SOF frames are enabled. + SUSPENDED: u1, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + /// Host: device speed. Disconnected = 00, LS = 01, FS = 10 + SPEED: u2, + /// VBUS over current detected + VBUS_OVER_CURR: u1, + /// Host: Device has initiated a remote resume. Device: host has initiated a resume. + RESUME: u1, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// Device: connected + CONNECTED: u1, + /// Device: Setup packet received + SETUP_REC: u1, + /// Transaction complete.\n\n + /// Raised by device if:\n\n + /// * An IN or OUT packet is sent with the `LAST_BUFF` bit set in the buffer control + /// register\n\n + /// Raised by host if:\n\n + /// * A setup packet is sent when no data in or data out transaction follows * An IN + /// packet is received and the `LAST_BUFF` bit is set in the buffer control register + /// * An IN packet is received with zero length * An OUT packet is sent and the + /// `LAST_BUFF` bit is set + TRANS_COMPLETE: u1, + /// Device: bus reset received + BUS_RESET: u1, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + /// CRC Error. Raised by the Serial RX engine. + CRC_ERROR: u1, + /// Bit Stuff Error. Raised by the Serial RX engine. + BIT_STUFF_ERROR: u1, + /// RX overflow is raised by the Serial RX engine if the incoming data is too fast. + RX_OVERFLOW: u1, + /// RX timeout is raised by both the host and device if an ACK is not received in + /// the maximum time specified by the USB spec. + RX_TIMEOUT: u1, + /// Host: NAK received + NAK_REC: u1, + /// Host: STALL received + STALL_REC: u1, + /// ACK received. Raised by both host and device. + ACK_REC: u1, + /// Data Sequence Error.\n\n + /// The device can raise a sequence error in the following conditions:\n\n + /// * A SETUP packet is received followed by a DATA1 packet (data phase should + /// always be DATA0) * An OUT packet is received from the host but doesn't match the + /// data pid in the buffer control register read from DPSRAM\n\n + /// The host can raise a data sequence error in the following conditions:\n\n + /// * An IN packet from the device has the wrong data PID + DATA_SEQ_ERROR: u1, + }), base_address + 0x50); + + /// address: 0x50110054 + /// interrupt endpoint control register + pub const INT_EP_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + /// Host: Enable interrupt endpoint 1 -> 15 + INT_EP_ACTIVE: u15, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + }), base_address + 0x54); + + /// address: 0x50110058 + /// Buffer status register. A bit set here indicates that a buffer has completed on + /// the endpoint (if the buffer interrupt is enabled). It is possible for 2 buffers + /// to be completed, so clearing the buffer status bit may instantly re set it on + /// the next clock cycle. + pub const BUFF_STATUS = @intToPtr(*volatile Mmio(32, packed struct { + EP0_IN: u1, + EP0_OUT: u1, + EP1_IN: u1, + EP1_OUT: u1, + EP2_IN: u1, + EP2_OUT: u1, + EP3_IN: u1, + EP3_OUT: u1, + EP4_IN: u1, + EP4_OUT: u1, + EP5_IN: u1, + EP5_OUT: u1, + EP6_IN: u1, + EP6_OUT: u1, + EP7_IN: u1, + EP7_OUT: u1, + EP8_IN: u1, + EP8_OUT: u1, + EP9_IN: u1, + EP9_OUT: u1, + EP10_IN: u1, + EP10_OUT: u1, + EP11_IN: u1, + EP11_OUT: u1, + EP12_IN: u1, + EP12_OUT: u1, + EP13_IN: u1, + EP13_OUT: u1, + EP14_IN: u1, + EP14_OUT: u1, + EP15_IN: u1, + EP15_OUT: u1, + }), base_address + 0x58); + + /// address: 0x5011005c + /// Which of the double buffers should be handled. Only valid if using an interrupt + /// per buffer (i.e. not per 2 buffers). Not valid for host interrupt endpoint + /// polling because they are only single buffered. + pub const BUFF_CPU_SHOULD_HANDLE = @intToPtr(*volatile Mmio(32, packed struct { + EP0_IN: u1, + EP0_OUT: u1, + EP1_IN: u1, + EP1_OUT: u1, + EP2_IN: u1, + EP2_OUT: u1, + EP3_IN: u1, + EP3_OUT: u1, + EP4_IN: u1, + EP4_OUT: u1, + EP5_IN: u1, + EP5_OUT: u1, + EP6_IN: u1, + EP6_OUT: u1, + EP7_IN: u1, + EP7_OUT: u1, + EP8_IN: u1, + EP8_OUT: u1, + EP9_IN: u1, + EP9_OUT: u1, + EP10_IN: u1, + EP10_OUT: u1, + EP11_IN: u1, + EP11_OUT: u1, + EP12_IN: u1, + EP12_OUT: u1, + EP13_IN: u1, + EP13_OUT: u1, + EP14_IN: u1, + EP14_OUT: u1, + EP15_IN: u1, + EP15_OUT: u1, + }), base_address + 0x5c); + + /// address: 0x50110060 + /// Device only: Can be set to ignore the buffer control register for this endpoint + /// in case you would like to revoke a buffer. A NAK will be sent for every access + /// to the endpoint until this bit is cleared. A corresponding bit in + /// `EP_ABORT_DONE` is set when it is safe to modify the buffer control register. + pub const EP_ABORT = @intToPtr(*volatile Mmio(32, packed struct { + EP0_IN: u1, + EP0_OUT: u1, + EP1_IN: u1, + EP1_OUT: u1, + EP2_IN: u1, + EP2_OUT: u1, + EP3_IN: u1, + EP3_OUT: u1, + EP4_IN: u1, + EP4_OUT: u1, + EP5_IN: u1, + EP5_OUT: u1, + EP6_IN: u1, + EP6_OUT: u1, + EP7_IN: u1, + EP7_OUT: u1, + EP8_IN: u1, + EP8_OUT: u1, + EP9_IN: u1, + EP9_OUT: u1, + EP10_IN: u1, + EP10_OUT: u1, + EP11_IN: u1, + EP11_OUT: u1, + EP12_IN: u1, + EP12_OUT: u1, + EP13_IN: u1, + EP13_OUT: u1, + EP14_IN: u1, + EP14_OUT: u1, + EP15_IN: u1, + EP15_OUT: u1, + }), base_address + 0x60); + + /// address: 0x50110064 + /// Device only: Used in conjunction with `EP_ABORT`. Set once an endpoint is idle + /// so the programmer knows it is safe to modify the buffer control register. + pub const EP_ABORT_DONE = @intToPtr(*volatile Mmio(32, packed struct { + EP0_IN: u1, + EP0_OUT: u1, + EP1_IN: u1, + EP1_OUT: u1, + EP2_IN: u1, + EP2_OUT: u1, + EP3_IN: u1, + EP3_OUT: u1, + EP4_IN: u1, + EP4_OUT: u1, + EP5_IN: u1, + EP5_OUT: u1, + EP6_IN: u1, + EP6_OUT: u1, + EP7_IN: u1, + EP7_OUT: u1, + EP8_IN: u1, + EP8_OUT: u1, + EP9_IN: u1, + EP9_OUT: u1, + EP10_IN: u1, + EP10_OUT: u1, + EP11_IN: u1, + EP11_OUT: u1, + EP12_IN: u1, + EP12_OUT: u1, + EP13_IN: u1, + EP13_OUT: u1, + EP14_IN: u1, + EP14_OUT: u1, + EP15_IN: u1, + EP15_OUT: u1, + }), base_address + 0x64); + + /// address: 0x50110068 + /// Device: this bit must be set in conjunction with the `STALL` bit in the buffer + /// control register to send a STALL on EP0. The device controller clears these bits + /// when a SETUP packet is received because the USB spec requires that a STALL + /// condition is cleared when a SETUP packet is received. + pub const EP_STALL_ARM = @intToPtr(*volatile Mmio(32, packed struct { + EP0_IN: u1, + EP0_OUT: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + }), base_address + 0x68); + + /// address: 0x5011006c + /// Used by the host controller. Sets the wait time in microseconds before trying + /// again if the device replies with a NAK. + pub const NAK_POLL = @intToPtr(*volatile Mmio(32, packed struct { + /// NAK polling interval for a low speed device + DELAY_LS: u10, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + /// NAK polling interval for a full speed device + DELAY_FS: u10, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + }), base_address + 0x6c); + + /// address: 0x50110070 + /// Device: bits are set when the `IRQ_ON_NAK` or `IRQ_ON_STALL` bits are set. For + /// EP0 this comes from `SIE_CTRL`. For all other endpoints it comes from the + /// endpoint control register. + pub const EP_STATUS_STALL_NAK = @intToPtr(*volatile Mmio(32, packed struct { + EP0_IN: u1, + EP0_OUT: u1, + EP1_IN: u1, + EP1_OUT: u1, + EP2_IN: u1, + EP2_OUT: u1, + EP3_IN: u1, + EP3_OUT: u1, + EP4_IN: u1, + EP4_OUT: u1, + EP5_IN: u1, + EP5_OUT: u1, + EP6_IN: u1, + EP6_OUT: u1, + EP7_IN: u1, + EP7_OUT: u1, + EP8_IN: u1, + EP8_OUT: u1, + EP9_IN: u1, + EP9_OUT: u1, + EP10_IN: u1, + EP10_OUT: u1, + EP11_IN: u1, + EP11_OUT: u1, + EP12_IN: u1, + EP12_OUT: u1, + EP13_IN: u1, + EP13_OUT: u1, + EP14_IN: u1, + EP14_OUT: u1, + EP15_IN: u1, + EP15_OUT: u1, + }), base_address + 0x70); + + /// address: 0x50110074 + /// Where to connect the USB controller. Should be to_phy by default. + pub const USB_MUXING = @intToPtr(*volatile Mmio(32, packed struct { + TO_PHY: u1, + TO_EXTPHY: u1, + TO_DIGITAL_PAD: u1, + SOFTCON: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + }), base_address + 0x74); + + /// address: 0x50110078 + /// Overrides for the power signals in the event that the VBUS signals are not + /// hooked up to GPIO. Set the value of the override and then the override enable to + /// switch over to the override value. + pub const USB_PWR = @intToPtr(*volatile Mmio(32, packed struct { + VBUS_EN: u1, + VBUS_EN_OVERRIDE_EN: u1, + VBUS_DETECT: u1, + VBUS_DETECT_OVERRIDE_EN: u1, + OVERCURR_DETECT: u1, + OVERCURR_DETECT_EN: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + }), base_address + 0x78); + + /// address: 0x5011007c + /// This register allows for direct control of the USB phy. Use in conjunction with + /// usbphy_direct_override register to enable each override bit. + pub const USBPHY_DIRECT = @intToPtr(*volatile Mmio(32, packed struct { + /// Enable the second DP pull up resistor. 0 - Pull = Rpu2; 1 - Pull = Rpu1 + Rpu2 + DP_PULLUP_HISEL: u1, + /// DP pull up enable + DP_PULLUP_EN: u1, + /// DP pull down enable + DP_PULLDN_EN: u1, + reserved0: u1 = 0, + /// Enable the second DM pull up resistor. 0 - Pull = Rpu2; 1 - Pull = Rpu1 + Rpu2 + DM_PULLUP_HISEL: u1, + /// DM pull up enable + DM_PULLUP_EN: u1, + /// DM pull down enable + DM_PULLDN_EN: u1, + reserved1: u1 = 0, + /// Output enable. If TX_DIFFMODE=1, OE for DPP/DPM diff pair. 0 - DPP/DPM in Hi-Z + /// state; 1 - DPP/DPM driving\n + /// If TX_DIFFMODE=0, OE for DPP only. 0 - DPP in Hi-Z state; 1 - DPP driving + TX_DP_OE: u1, + /// Output enable. If TX_DIFFMODE=1, Ignored.\n + /// If TX_DIFFMODE=0, OE for DPM only. 0 - DPM in Hi-Z state; 1 - DPM driving + TX_DM_OE: u1, + /// Output data. If TX_DIFFMODE=1, Drives DPP/DPM diff pair. TX_DP_OE=1 to enable + /// drive. DPP=TX_DP, DPM=~TX_DP\n + /// If TX_DIFFMODE=0, Drives DPP only. TX_DP_OE=1 to enable drive. DPP=TX_DP + TX_DP: u1, + /// Output data. TX_DIFFMODE=1, Ignored\n + /// TX_DIFFMODE=0, Drives DPM only. TX_DM_OE=1 to enable drive. DPM=TX_DM + TX_DM: u1, + /// RX power down override (if override enable is set). 1 = powered down. + RX_PD: u1, + /// TX power down override (if override enable is set). 1 = powered down. + TX_PD: u1, + /// TX_FSSLEW=0: Low speed slew rate\n + /// TX_FSSLEW=1: Full speed slew rate + TX_FSSLEW: u1, + /// TX_DIFFMODE=0: Single ended mode\n + /// TX_DIFFMODE=1: Differential drive mode (TX_DM, TX_DM_OE ignored) + TX_DIFFMODE: u1, + /// Differential RX + RX_DD: u1, + /// DPP pin state + RX_DP: u1, + /// DPM pin state + RX_DM: u1, + /// DP overcurrent + DP_OVCN: u1, + /// DM overcurrent + DM_OVCN: u1, + /// DP over voltage + DP_OVV: u1, + /// DM over voltage + DM_OVV: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + }), base_address + 0x7c); + + /// address: 0x50110080 + /// Override enable for each control in usbphy_direct + pub const USBPHY_DIRECT_OVERRIDE = @intToPtr(*volatile Mmio(32, packed struct { + DP_PULLUP_HISEL_OVERRIDE_EN: u1, + DM_PULLUP_HISEL_OVERRIDE_EN: u1, + DP_PULLUP_EN_OVERRIDE_EN: u1, + DP_PULLDN_EN_OVERRIDE_EN: u1, + DM_PULLDN_EN_OVERRIDE_EN: u1, + TX_DP_OE_OVERRIDE_EN: u1, + TX_DM_OE_OVERRIDE_EN: u1, + TX_DP_OVERRIDE_EN: u1, + TX_DM_OVERRIDE_EN: u1, + RX_PD_OVERRIDE_EN: u1, + TX_PD_OVERRIDE_EN: u1, + TX_FSSLEW_OVERRIDE_EN: u1, + DM_PULLUP_OVERRIDE_EN: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + TX_DIFFMODE_OVERRIDE_EN: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + }), base_address + 0x80); + + /// address: 0x50110084 + /// Used to adjust trim values of USB phy pull down resistors. + pub const USBPHY_TRIM = @intToPtr(*volatile Mmio(32, packed struct { + /// Value to drive to USB PHY\n + /// DP pulldown resistor trim control\n + /// Experimental data suggests that the reset value will work, but this register + /// allows adjustment if required + DP_PULLDN_TRIM: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + /// Value to drive to USB PHY\n + /// DM pulldown resistor trim control\n + /// Experimental data suggests that the reset value will work, but this register + /// allows adjustment if required + DM_PULLDN_TRIM: u5, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + }), base_address + 0x84); + + /// address: 0x5011008c + /// Raw Interrupts + pub const INTR = @intToPtr(*volatile Mmio(32, packed struct { + /// Host: raised when a device is connected or disconnected (i.e. when + /// SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED + HOST_CONN_DIS: u1, + /// Host: raised when a device wakes up the host. Cleared by writing to + /// SIE_STATUS.RESUME + HOST_RESUME: u1, + /// Host: raised every time the host sends a SOF (Start of Frame). Cleared by + /// reading SOF_RD + HOST_SOF: u1, + /// Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this + /// bit. + TRANS_COMPLETE: u1, + /// Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in + /// BUFF_STATUS. + BUFF_STATUS: u1, + /// Source: SIE_STATUS.DATA_SEQ_ERROR + ERROR_DATA_SEQ: u1, + /// Source: SIE_STATUS.RX_TIMEOUT + ERROR_RX_TIMEOUT: u1, + /// Source: SIE_STATUS.RX_OVERFLOW + ERROR_RX_OVERFLOW: u1, + /// Source: SIE_STATUS.BIT_STUFF_ERROR + ERROR_BIT_STUFF: u1, + /// Source: SIE_STATUS.CRC_ERROR + ERROR_CRC: u1, + /// Source: SIE_STATUS.STALL_REC + STALL: u1, + /// Source: SIE_STATUS.VBUS_DETECTED + VBUS_DETECT: u1, + /// Source: SIE_STATUS.BUS_RESET + BUS_RESET: u1, + /// Set when the device connection state changes. Cleared by writing to + /// SIE_STATUS.CONNECTED + DEV_CONN_DIS: u1, + /// Set when the device suspend state changes. Cleared by writing to + /// SIE_STATUS.SUSPENDED + DEV_SUSPEND: u1, + /// Set when the device receives a resume from the host. Cleared by writing to + /// SIE_STATUS.RESUME + DEV_RESUME_FROM_HOST: u1, + /// Device. Source: SIE_STATUS.SETUP_REC + SETUP_REQ: u1, + /// Set every time the device receives a SOF (Start of Frame) packet. Cleared by + /// reading SOF_RD + DEV_SOF: u1, + /// Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in + /// ABORT_DONE. + ABORT_DONE: u1, + /// Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in + /// EP_STATUS_STALL_NAK. + EP_STALL_NAK: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + }), base_address + 0x8c); + + /// address: 0x50110090 + /// Interrupt Enable + pub const INTE = @intToPtr(*volatile Mmio(32, packed struct { + /// Host: raised when a device is connected or disconnected (i.e. when + /// SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED + HOST_CONN_DIS: u1, + /// Host: raised when a device wakes up the host. Cleared by writing to + /// SIE_STATUS.RESUME + HOST_RESUME: u1, + /// Host: raised every time the host sends a SOF (Start of Frame). Cleared by + /// reading SOF_RD + HOST_SOF: u1, + /// Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this + /// bit. + TRANS_COMPLETE: u1, + /// Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in + /// BUFF_STATUS. + BUFF_STATUS: u1, + /// Source: SIE_STATUS.DATA_SEQ_ERROR + ERROR_DATA_SEQ: u1, + /// Source: SIE_STATUS.RX_TIMEOUT + ERROR_RX_TIMEOUT: u1, + /// Source: SIE_STATUS.RX_OVERFLOW + ERROR_RX_OVERFLOW: u1, + /// Source: SIE_STATUS.BIT_STUFF_ERROR + ERROR_BIT_STUFF: u1, + /// Source: SIE_STATUS.CRC_ERROR + ERROR_CRC: u1, + /// Source: SIE_STATUS.STALL_REC + STALL: u1, + /// Source: SIE_STATUS.VBUS_DETECTED + VBUS_DETECT: u1, + /// Source: SIE_STATUS.BUS_RESET + BUS_RESET: u1, + /// Set when the device connection state changes. Cleared by writing to + /// SIE_STATUS.CONNECTED + DEV_CONN_DIS: u1, + /// Set when the device suspend state changes. Cleared by writing to + /// SIE_STATUS.SUSPENDED + DEV_SUSPEND: u1, + /// Set when the device receives a resume from the host. Cleared by writing to + /// SIE_STATUS.RESUME + DEV_RESUME_FROM_HOST: u1, + /// Device. Source: SIE_STATUS.SETUP_REC + SETUP_REQ: u1, + /// Set every time the device receives a SOF (Start of Frame) packet. Cleared by + /// reading SOF_RD + DEV_SOF: u1, + /// Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in + /// ABORT_DONE. + ABORT_DONE: u1, + /// Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in + /// EP_STATUS_STALL_NAK. + EP_STALL_NAK: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + }), base_address + 0x90); + + /// address: 0x50110094 + /// Interrupt Force + pub const INTF = @intToPtr(*volatile Mmio(32, packed struct { + /// Host: raised when a device is connected or disconnected (i.e. when + /// SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED + HOST_CONN_DIS: u1, + /// Host: raised when a device wakes up the host. Cleared by writing to + /// SIE_STATUS.RESUME + HOST_RESUME: u1, + /// Host: raised every time the host sends a SOF (Start of Frame). Cleared by + /// reading SOF_RD + HOST_SOF: u1, + /// Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this + /// bit. + TRANS_COMPLETE: u1, + /// Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in + /// BUFF_STATUS. + BUFF_STATUS: u1, + /// Source: SIE_STATUS.DATA_SEQ_ERROR + ERROR_DATA_SEQ: u1, + /// Source: SIE_STATUS.RX_TIMEOUT + ERROR_RX_TIMEOUT: u1, + /// Source: SIE_STATUS.RX_OVERFLOW + ERROR_RX_OVERFLOW: u1, + /// Source: SIE_STATUS.BIT_STUFF_ERROR + ERROR_BIT_STUFF: u1, + /// Source: SIE_STATUS.CRC_ERROR + ERROR_CRC: u1, + /// Source: SIE_STATUS.STALL_REC + STALL: u1, + /// Source: SIE_STATUS.VBUS_DETECTED + VBUS_DETECT: u1, + /// Source: SIE_STATUS.BUS_RESET + BUS_RESET: u1, + /// Set when the device connection state changes. Cleared by writing to + /// SIE_STATUS.CONNECTED + DEV_CONN_DIS: u1, + /// Set when the device suspend state changes. Cleared by writing to + /// SIE_STATUS.SUSPENDED + DEV_SUSPEND: u1, + /// Set when the device receives a resume from the host. Cleared by writing to + /// SIE_STATUS.RESUME + DEV_RESUME_FROM_HOST: u1, + /// Device. Source: SIE_STATUS.SETUP_REC + SETUP_REQ: u1, + /// Set every time the device receives a SOF (Start of Frame) packet. Cleared by + /// reading SOF_RD + DEV_SOF: u1, + /// Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in + /// ABORT_DONE. + ABORT_DONE: u1, + /// Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in + /// EP_STATUS_STALL_NAK. + EP_STALL_NAK: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + }), base_address + 0x94); + + /// address: 0x50110098 + /// Interrupt status after masking & forcing + pub const INTS = @intToPtr(*volatile Mmio(32, packed struct { + /// Host: raised when a device is connected or disconnected (i.e. when + /// SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED + HOST_CONN_DIS: u1, + /// Host: raised when a device wakes up the host. Cleared by writing to + /// SIE_STATUS.RESUME + HOST_RESUME: u1, + /// Host: raised every time the host sends a SOF (Start of Frame). Cleared by + /// reading SOF_RD + HOST_SOF: u1, + /// Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this + /// bit. + TRANS_COMPLETE: u1, + /// Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in + /// BUFF_STATUS. + BUFF_STATUS: u1, + /// Source: SIE_STATUS.DATA_SEQ_ERROR + ERROR_DATA_SEQ: u1, + /// Source: SIE_STATUS.RX_TIMEOUT + ERROR_RX_TIMEOUT: u1, + /// Source: SIE_STATUS.RX_OVERFLOW + ERROR_RX_OVERFLOW: u1, + /// Source: SIE_STATUS.BIT_STUFF_ERROR + ERROR_BIT_STUFF: u1, + /// Source: SIE_STATUS.CRC_ERROR + ERROR_CRC: u1, + /// Source: SIE_STATUS.STALL_REC + STALL: u1, + /// Source: SIE_STATUS.VBUS_DETECTED + VBUS_DETECT: u1, + /// Source: SIE_STATUS.BUS_RESET + BUS_RESET: u1, + /// Set when the device connection state changes. Cleared by writing to + /// SIE_STATUS.CONNECTED + DEV_CONN_DIS: u1, + /// Set when the device suspend state changes. Cleared by writing to + /// SIE_STATUS.SUSPENDED + DEV_SUSPEND: u1, + /// Set when the device receives a resume from the host. Cleared by writing to + /// SIE_STATUS.RESUME + DEV_RESUME_FROM_HOST: u1, + /// Device. Source: SIE_STATUS.SETUP_REC + SETUP_REQ: u1, + /// Set every time the device receives a SOF (Start of Frame) packet. Cleared by + /// reading SOF_RD + DEV_SOF: u1, + /// Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in + /// ABORT_DONE. + ABORT_DONE: u1, + /// Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in + /// EP_STATUS_STALL_NAK. + EP_STALL_NAK: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + }), base_address + 0x98); + }; + + /// Programmable IO block + pub const PIO0 = struct { + pub const base_address = 0x50200000; + pub const version = "1"; + + /// address: 0x50200000 + /// PIO control register + pub const CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// Enable/disable each of the four state machines by writing 1/0 to each of these + /// four bits. When disabled, a state machine will cease executing instructions, + /// except those written directly to SMx_INSTR by the system. Multiple bits can be + /// set/cleared at once to run/halt multiple state machines simultaneously. + SM_ENABLE: u4, + /// Write 1 to instantly clear internal SM state which may be otherwise difficult to + /// access and will affect future execution.\n\n + /// Specifically, the following are cleared: input and output shift counters; the + /// contents of the input shift register; the delay counter; the waiting-on-IRQ + /// state; any stalled instruction written to SMx_INSTR or run by OUT/MOV EXEC; any + /// pin write left asserted due to OUT_STICKY. + SM_RESTART: u4, + /// Restart a state machine's clock divider from an initial phase of 0. Clock + /// dividers are free-running, so once started, their output (including fractional + /// jitter) is completely determined by the integer/fractional divisor configured in + /// SMx_CLKDIV. This means that, if multiple clock dividers with the same divisor + /// are restarted simultaneously, by writing multiple 1 bits to this field, the + /// execution clocks of those state machines will run in precise lockstep.\n\n + /// Note that setting/clearing SM_ENABLE does not stop the clock divider from + /// running, so once multiple state machines' clocks are synchronised, it is safe to + /// disable/reenable a state machine, whilst keeping the clock dividers in sync.\n\n + /// Note also that CLKDIV_RESTART can be written to whilst the state machine is + /// running, and this is useful to resynchronise clock dividers after the divisors + /// (SMx_CLKDIV) have been changed on-the-fly. + CLKDIV_RESTART: u4, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x0); + + /// address: 0x50200004 + /// FIFO status register + pub const FSTAT = @intToPtr(*volatile Mmio(32, packed struct { + /// State machine RX FIFO is full + RXFULL: u4, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + /// State machine RX FIFO is empty + RXEMPTY: u4, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// State machine TX FIFO is full + TXFULL: u4, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + /// State machine TX FIFO is empty + TXEMPTY: u4, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + }), base_address + 0x4); + + /// address: 0x50200008 + /// FIFO debug register + pub const FDEBUG = @intToPtr(*volatile Mmio(32, packed struct { + /// State machine has stalled on full RX FIFO during a blocking PUSH, or an IN with + /// autopush enabled. This flag is also set when a nonblocking PUSH to a full FIFO + /// took place, in which case the state machine has dropped data. Write 1 to clear. + RXSTALL: u4, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + /// RX FIFO underflow (i.e. read-on-empty by the system) has occurred. Write 1 to + /// clear. Note that read-on-empty does not perturb the state of the FIFO in any + /// way, but the data returned by reading from an empty FIFO is undefined, so this + /// flag generally only becomes set due to some kind of software error. + RXUNDER: u4, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// TX FIFO overflow (i.e. write-on-full by the system) has occurred. Write 1 to + /// clear. Note that write-on-full does not alter the state or contents of the FIFO + /// in any way, but the data that the system attempted to write is dropped, so if + /// this flag is set, your software has quite likely dropped some data on the floor. + TXOVER: u4, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + /// State machine has stalled on empty TX FIFO during a blocking PULL, or an OUT + /// with autopull enabled. Write 1 to clear. + TXSTALL: u4, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + }), base_address + 0x8); + + /// address: 0x5020000c + /// FIFO levels + pub const FLEVEL = @intToPtr(*volatile Mmio(32, packed struct { + TX0: u4, + RX0: u4, + TX1: u4, + RX1: u4, + TX2: u4, + RX2: u4, + TX3: u4, + RX3: u4, + }), base_address + 0xc); + + /// address: 0x50200010 + /// Direct write access to the TX FIFO for this state machine. Each write pushes one + /// word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO + /// state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + pub const TXF0 = @intToPtr(*volatile u32, base_address + 0x10); + + /// address: 0x50200014 + /// Direct write access to the TX FIFO for this state machine. Each write pushes one + /// word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO + /// state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + pub const TXF1 = @intToPtr(*volatile u32, base_address + 0x14); + + /// address: 0x50200018 + /// Direct write access to the TX FIFO for this state machine. Each write pushes one + /// word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO + /// state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + pub const TXF2 = @intToPtr(*volatile u32, base_address + 0x18); + + /// address: 0x5020001c + /// Direct write access to the TX FIFO for this state machine. Each write pushes one + /// word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO + /// state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + pub const TXF3 = @intToPtr(*volatile u32, base_address + 0x1c); + + /// address: 0x50200020 + /// Direct read access to the RX FIFO for this state machine. Each read pops one + /// word from the FIFO. Attempting to read from an empty FIFO has no effect on the + /// FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The + /// data returned to the system on a read from an empty FIFO is undefined. + pub const RXF0 = @intToPtr(*volatile u32, base_address + 0x20); + + /// address: 0x50200024 + /// Direct read access to the RX FIFO for this state machine. Each read pops one + /// word from the FIFO. Attempting to read from an empty FIFO has no effect on the + /// FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The + /// data returned to the system on a read from an empty FIFO is undefined. + pub const RXF1 = @intToPtr(*volatile u32, base_address + 0x24); + + /// address: 0x50200028 + /// Direct read access to the RX FIFO for this state machine. Each read pops one + /// word from the FIFO. Attempting to read from an empty FIFO has no effect on the + /// FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The + /// data returned to the system on a read from an empty FIFO is undefined. + pub const RXF2 = @intToPtr(*volatile u32, base_address + 0x28); + + /// address: 0x5020002c + /// Direct read access to the RX FIFO for this state machine. Each read pops one + /// word from the FIFO. Attempting to read from an empty FIFO has no effect on the + /// FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The + /// data returned to the system on a read from an empty FIFO is undefined. + pub const RXF3 = @intToPtr(*volatile u32, base_address + 0x2c); + + /// address: 0x50200030 + /// State machine IRQ flags register. Write 1 to clear. There are 8 state machine + /// IRQ flags, which can be set, cleared, and waited on by the state machines. + /// There's no fixed association between flags and state machines -- any state + /// machine can use any flag.\n\n + /// Any of the 8 flags can be used for timing synchronisation between state + /// machines, using IRQ and WAIT instructions. The lower four of these flags are + /// also routed out to system-level interrupt requests, alongside FIFO status + /// interrupts -- see e.g. IRQ0_INTE. + pub const IRQ = @intToPtr(*volatile MmioInt(32, u8), base_address + 0x30); + + /// address: 0x50200034 + /// Writing a 1 to each of these bits will forcibly assert the corresponding IRQ. + /// Note this is different to the INTF register: writing here affects PIO internal + /// state. INTF just asserts the processor-facing IRQ signal for testing ISRs, and + /// is not visible to the state machines. + pub const IRQ_FORCE = @intToPtr(*volatile MmioInt(32, u8), base_address + 0x34); + + /// address: 0x50200038 + /// There is a 2-flipflop synchronizer on each GPIO input, which protects PIO logic + /// from metastabilities. This increases input delay, and for fast synchronous IO + /// (e.g. SPI) these synchronizers may need to be bypassed. Each bit in this + /// register corresponds to one GPIO.\n + /// 0 -> input is synchronized (default)\n + /// 1 -> synchronizer is bypassed\n + /// If in doubt, leave this register as all zeroes. + pub const INPUT_SYNC_BYPASS = @intToPtr(*volatile u32, base_address + 0x38); + + /// address: 0x5020003c + /// Read to sample the pad output values PIO is currently driving to the GPIOs. On + /// RP2040 there are 30 GPIOs, so the two most significant bits are hardwired to 0. + pub const DBG_PADOUT = @intToPtr(*volatile u32, base_address + 0x3c); + + /// address: 0x50200040 + /// Read to sample the pad output enables (direction) PIO is currently driving to + /// the GPIOs. On RP2040 there are 30 GPIOs, so the two most significant bits are + /// hardwired to 0. + pub const DBG_PADOE = @intToPtr(*volatile u32, base_address + 0x40); + + /// address: 0x50200044 + /// The PIO hardware has some free parameters that may vary between chip products.\n + /// These should be provided in the chip datasheet, but are also exposed here. + pub const DBG_CFGINFO = @intToPtr(*volatile Mmio(32, packed struct { + /// The depth of the state machine TX/RX FIFOs, measured in words.\n + /// Joining fifos via SHIFTCTRL_FJOIN gives one FIFO with double\n + /// this depth. + FIFO_DEPTH: u6, + reserved0: u1 = 0, + reserved1: u1 = 0, + /// The number of state machines this PIO instance is equipped with. + SM_COUNT: u4, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + /// The size of the instruction memory, measured in units of one instruction + IMEM_SIZE: u6, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + }), base_address + 0x44); + + /// address: 0x50200048 + /// Write-only access to instruction memory location 0 + pub const INSTR_MEM0 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x48); + + /// address: 0x5020004c + /// Write-only access to instruction memory location 1 + pub const INSTR_MEM1 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x4c); + + /// address: 0x50200050 + /// Write-only access to instruction memory location 2 + pub const INSTR_MEM2 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x50); + + /// address: 0x50200054 + /// Write-only access to instruction memory location 3 + pub const INSTR_MEM3 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x54); + + /// address: 0x50200058 + /// Write-only access to instruction memory location 4 + pub const INSTR_MEM4 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x58); + + /// address: 0x5020005c + /// Write-only access to instruction memory location 5 + pub const INSTR_MEM5 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x5c); + + /// address: 0x50200060 + /// Write-only access to instruction memory location 6 + pub const INSTR_MEM6 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x60); + + /// address: 0x50200064 + /// Write-only access to instruction memory location 7 + pub const INSTR_MEM7 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x64); + + /// address: 0x50200068 + /// Write-only access to instruction memory location 8 + pub const INSTR_MEM8 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x68); + + /// address: 0x5020006c + /// Write-only access to instruction memory location 9 + pub const INSTR_MEM9 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x6c); + + /// address: 0x50200070 + /// Write-only access to instruction memory location 10 + pub const INSTR_MEM10 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x70); + + /// address: 0x50200074 + /// Write-only access to instruction memory location 11 + pub const INSTR_MEM11 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x74); + + /// address: 0x50200078 + /// Write-only access to instruction memory location 12 + pub const INSTR_MEM12 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x78); + + /// address: 0x5020007c + /// Write-only access to instruction memory location 13 + pub const INSTR_MEM13 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x7c); + + /// address: 0x50200080 + /// Write-only access to instruction memory location 14 + pub const INSTR_MEM14 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x80); + + /// address: 0x50200084 + /// Write-only access to instruction memory location 15 + pub const INSTR_MEM15 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x84); + + /// address: 0x50200088 + /// Write-only access to instruction memory location 16 + pub const INSTR_MEM16 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x88); + + /// address: 0x5020008c + /// Write-only access to instruction memory location 17 + pub const INSTR_MEM17 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x8c); + + /// address: 0x50200090 + /// Write-only access to instruction memory location 18 + pub const INSTR_MEM18 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x90); + + /// address: 0x50200094 + /// Write-only access to instruction memory location 19 + pub const INSTR_MEM19 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x94); + + /// address: 0x50200098 + /// Write-only access to instruction memory location 20 + pub const INSTR_MEM20 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x98); + + /// address: 0x5020009c + /// Write-only access to instruction memory location 21 + pub const INSTR_MEM21 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x9c); + + /// address: 0x502000a0 + /// Write-only access to instruction memory location 22 + pub const INSTR_MEM22 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xa0); + + /// address: 0x502000a4 + /// Write-only access to instruction memory location 23 + pub const INSTR_MEM23 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xa4); + + /// address: 0x502000a8 + /// Write-only access to instruction memory location 24 + pub const INSTR_MEM24 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xa8); + + /// address: 0x502000ac + /// Write-only access to instruction memory location 25 + pub const INSTR_MEM25 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xac); + + /// address: 0x502000b0 + /// Write-only access to instruction memory location 26 + pub const INSTR_MEM26 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xb0); + + /// address: 0x502000b4 + /// Write-only access to instruction memory location 27 + pub const INSTR_MEM27 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xb4); + + /// address: 0x502000b8 + /// Write-only access to instruction memory location 28 + pub const INSTR_MEM28 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xb8); + + /// address: 0x502000bc + /// Write-only access to instruction memory location 29 + pub const INSTR_MEM29 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xbc); + + /// address: 0x502000c0 + /// Write-only access to instruction memory location 30 + pub const INSTR_MEM30 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xc0); + + /// address: 0x502000c4 + /// Write-only access to instruction memory location 31 + pub const INSTR_MEM31 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xc4); + + /// address: 0x502000c8 + /// Clock divisor register for state machine 0\n + /// Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + pub const SM0_CLKDIV = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// Fractional part of clock divisor + FRAC: u8, + /// Effective frequency is sysclk/(int + frac/256).\n + /// Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + INT: u16, + }), base_address + 0xc8); + + /// address: 0x502000cc + /// Execution/behavioural settings for state machine 0 + pub const SM0_EXECCTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// Comparison level for the MOV x, STATUS instruction + STATUS_N: u4, + /// Comparison used for the MOV x, STATUS instruction. + STATUS_SEL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + /// After reaching wrap_top, execution is wrapped to this address. + WRAP_BOTTOM: u5, + /// After reaching this address, execution is wrapped to wrap_bottom.\n + /// If the instruction is a jump, and the jump condition is true, the jump takes + /// priority. + WRAP_TOP: u5, + /// Continuously assert the most recent OUT/SET to the pins + OUT_STICKY: u1, + /// If 1, use a bit of OUT data as an auxiliary write enable\n + /// When used in conjunction with OUT_STICKY, writes with an enable of 0 will\n + /// deassert the latest pin write. This can create useful masking/override + /// behaviour\n + /// due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + INLINE_OUT_EN: u1, + /// Which data bit to use for inline OUT enable + OUT_EN_SEL: u5, + /// The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + JMP_PIN: u5, + /// If 1, side-set data is asserted to pin directions, instead of pin values + SIDE_PINDIR: u1, + /// If 1, the MSB of the Delay/Side-set instruction field is used as side-set + /// enable, rather than a side-set data bit. This allows instructions to perform + /// side-set optionally, rather than on every instruction, but the maximum possible + /// side-set width is reduced from 5 to 4. Note that the value of + /// PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + SIDE_EN: u1, + /// If 1, an instruction written to SMx_INSTR is stalled, and latched by the state + /// machine. Will clear to 0 once this instruction completes. + EXEC_STALLED: u1, + }), base_address + 0xcc); + + /// address: 0x502000d0 + /// Control behaviour of the input/output shift registers for state machine 0 + pub const SM0_SHIFTCTRL = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + /// Push automatically when the input shift register is filled, i.e. on an IN + /// instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + AUTOPUSH: u1, + /// Pull automatically when the output shift register is emptied, i.e. on or + /// following an OUT instruction which causes the output shift counter to reach or + /// exceed PULL_THRESH. + AUTOPULL: u1, + /// 1 = shift input shift register to right (data enters from left). 0 = to left. + IN_SHIFTDIR: u1, + /// 1 = shift out of output shift register to right. 0 = to left. + OUT_SHIFTDIR: u1, + /// Number of bits shifted into ISR before autopush, or conditional push (PUSH + /// IFFULL), will take place.\n + /// Write 0 for value of 32. + PUSH_THRESH: u5, + /// Number of bits shifted out of OSR before autopull, or conditional pull (PULL + /// IFEMPTY), will take place.\n + /// Write 0 for value of 32. + PULL_THRESH: u5, + /// When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep.\n + /// RX FIFO is disabled as a result (always reads as both full and empty).\n + /// FIFOs are flushed when this bit is changed. + FJOIN_TX: u1, + /// When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep.\n + /// TX FIFO is disabled as a result (always reads as both full and empty).\n + /// FIFOs are flushed when this bit is changed. + FJOIN_RX: u1, + }), base_address + 0xd0); + + /// address: 0x502000d4 + /// Current instruction address of state machine 0 + pub const SM0_ADDR = @intToPtr(*volatile MmioInt(32, u5), base_address + 0xd4); + + /// address: 0x502000d8 + /// Read to see the instruction currently addressed by state machine 0's program + /// counter\n + /// Write to execute an instruction immediately (including jumps) and then resume + /// execution. + pub const SM0_INSTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xd8); + + /// address: 0x502000dc + /// State machine pin control + pub const SM0_PINCTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV + /// PINS instruction. The data written to this pin will always be the + /// least-significant bit of the OUT or MOV data. + OUT_BASE: u5, + /// The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS + /// instruction. The data written to this pin is the least-significant bit of the + /// SET data. + SET_BASE: u5, + /// The lowest-numbered pin that will be affected by a side-set operation. The MSBs + /// of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) + /// are used for side-set data, with the remaining LSBs used for delay. The + /// least-significant bit of the side-set portion is the bit written to this pin, + /// with more-significant bits written to higher-numbered pins. + SIDESET_BASE: u5, + /// The pin which is mapped to the least-significant bit of a state machine's IN + /// data bus. Higher-numbered pins are mapped to consecutively more-significant data + /// bits, with a modulo of 32 applied to pin number. + IN_BASE: u5, + /// The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. + /// In the range 0 to 32 inclusive. + OUT_COUNT: u6, + /// The number of pins asserted by a SET. In the range 0 to 5 inclusive. + SET_COUNT: u3, + /// The number of MSBs of the Delay/Side-set instruction field which are used for + /// side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, + /// no side-set) and maximum of 5 (all side-set, no delay). + SIDESET_COUNT: u3, + }), base_address + 0xdc); + + /// address: 0x502000e0 + /// Clock divisor register for state machine 1\n + /// Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + pub const SM1_CLKDIV = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// Fractional part of clock divisor + FRAC: u8, + /// Effective frequency is sysclk/(int + frac/256).\n + /// Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + INT: u16, + }), base_address + 0xe0); + + /// address: 0x502000e4 + /// Execution/behavioural settings for state machine 1 + pub const SM1_EXECCTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// Comparison level for the MOV x, STATUS instruction + STATUS_N: u4, + /// Comparison used for the MOV x, STATUS instruction. + STATUS_SEL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + /// After reaching wrap_top, execution is wrapped to this address. + WRAP_BOTTOM: u5, + /// After reaching this address, execution is wrapped to wrap_bottom.\n + /// If the instruction is a jump, and the jump condition is true, the jump takes + /// priority. + WRAP_TOP: u5, + /// Continuously assert the most recent OUT/SET to the pins + OUT_STICKY: u1, + /// If 1, use a bit of OUT data as an auxiliary write enable\n + /// When used in conjunction with OUT_STICKY, writes with an enable of 0 will\n + /// deassert the latest pin write. This can create useful masking/override + /// behaviour\n + /// due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + INLINE_OUT_EN: u1, + /// Which data bit to use for inline OUT enable + OUT_EN_SEL: u5, + /// The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + JMP_PIN: u5, + /// If 1, side-set data is asserted to pin directions, instead of pin values + SIDE_PINDIR: u1, + /// If 1, the MSB of the Delay/Side-set instruction field is used as side-set + /// enable, rather than a side-set data bit. This allows instructions to perform + /// side-set optionally, rather than on every instruction, but the maximum possible + /// side-set width is reduced from 5 to 4. Note that the value of + /// PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + SIDE_EN: u1, + /// If 1, an instruction written to SMx_INSTR is stalled, and latched by the state + /// machine. Will clear to 0 once this instruction completes. + EXEC_STALLED: u1, + }), base_address + 0xe4); + + /// address: 0x502000e8 + /// Control behaviour of the input/output shift registers for state machine 1 + pub const SM1_SHIFTCTRL = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + /// Push automatically when the input shift register is filled, i.e. on an IN + /// instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + AUTOPUSH: u1, + /// Pull automatically when the output shift register is emptied, i.e. on or + /// following an OUT instruction which causes the output shift counter to reach or + /// exceed PULL_THRESH. + AUTOPULL: u1, + /// 1 = shift input shift register to right (data enters from left). 0 = to left. + IN_SHIFTDIR: u1, + /// 1 = shift out of output shift register to right. 0 = to left. + OUT_SHIFTDIR: u1, + /// Number of bits shifted into ISR before autopush, or conditional push (PUSH + /// IFFULL), will take place.\n + /// Write 0 for value of 32. + PUSH_THRESH: u5, + /// Number of bits shifted out of OSR before autopull, or conditional pull (PULL + /// IFEMPTY), will take place.\n + /// Write 0 for value of 32. + PULL_THRESH: u5, + /// When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep.\n + /// RX FIFO is disabled as a result (always reads as both full and empty).\n + /// FIFOs are flushed when this bit is changed. + FJOIN_TX: u1, + /// When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep.\n + /// TX FIFO is disabled as a result (always reads as both full and empty).\n + /// FIFOs are flushed when this bit is changed. + FJOIN_RX: u1, + }), base_address + 0xe8); + + /// address: 0x502000ec + /// Current instruction address of state machine 1 + pub const SM1_ADDR = @intToPtr(*volatile MmioInt(32, u5), base_address + 0xec); + + /// address: 0x502000f0 + /// Read to see the instruction currently addressed by state machine 1's program + /// counter\n + /// Write to execute an instruction immediately (including jumps) and then resume + /// execution. + pub const SM1_INSTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xf0); + + /// address: 0x502000f4 + /// State machine pin control + pub const SM1_PINCTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV + /// PINS instruction. The data written to this pin will always be the + /// least-significant bit of the OUT or MOV data. + OUT_BASE: u5, + /// The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS + /// instruction. The data written to this pin is the least-significant bit of the + /// SET data. + SET_BASE: u5, + /// The lowest-numbered pin that will be affected by a side-set operation. The MSBs + /// of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) + /// are used for side-set data, with the remaining LSBs used for delay. The + /// least-significant bit of the side-set portion is the bit written to this pin, + /// with more-significant bits written to higher-numbered pins. + SIDESET_BASE: u5, + /// The pin which is mapped to the least-significant bit of a state machine's IN + /// data bus. Higher-numbered pins are mapped to consecutively more-significant data + /// bits, with a modulo of 32 applied to pin number. + IN_BASE: u5, + /// The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. + /// In the range 0 to 32 inclusive. + OUT_COUNT: u6, + /// The number of pins asserted by a SET. In the range 0 to 5 inclusive. + SET_COUNT: u3, + /// The number of MSBs of the Delay/Side-set instruction field which are used for + /// side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, + /// no side-set) and maximum of 5 (all side-set, no delay). + SIDESET_COUNT: u3, + }), base_address + 0xf4); + + /// address: 0x502000f8 + /// Clock divisor register for state machine 2\n + /// Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + pub const SM2_CLKDIV = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// Fractional part of clock divisor + FRAC: u8, + /// Effective frequency is sysclk/(int + frac/256).\n + /// Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + INT: u16, + }), base_address + 0xf8); + + /// address: 0x502000fc + /// Execution/behavioural settings for state machine 2 + pub const SM2_EXECCTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// Comparison level for the MOV x, STATUS instruction + STATUS_N: u4, + /// Comparison used for the MOV x, STATUS instruction. + STATUS_SEL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + /// After reaching wrap_top, execution is wrapped to this address. + WRAP_BOTTOM: u5, + /// After reaching this address, execution is wrapped to wrap_bottom.\n + /// If the instruction is a jump, and the jump condition is true, the jump takes + /// priority. + WRAP_TOP: u5, + /// Continuously assert the most recent OUT/SET to the pins + OUT_STICKY: u1, + /// If 1, use a bit of OUT data as an auxiliary write enable\n + /// When used in conjunction with OUT_STICKY, writes with an enable of 0 will\n + /// deassert the latest pin write. This can create useful masking/override + /// behaviour\n + /// due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + INLINE_OUT_EN: u1, + /// Which data bit to use for inline OUT enable + OUT_EN_SEL: u5, + /// The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + JMP_PIN: u5, + /// If 1, side-set data is asserted to pin directions, instead of pin values + SIDE_PINDIR: u1, + /// If 1, the MSB of the Delay/Side-set instruction field is used as side-set + /// enable, rather than a side-set data bit. This allows instructions to perform + /// side-set optionally, rather than on every instruction, but the maximum possible + /// side-set width is reduced from 5 to 4. Note that the value of + /// PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + SIDE_EN: u1, + /// If 1, an instruction written to SMx_INSTR is stalled, and latched by the state + /// machine. Will clear to 0 once this instruction completes. + EXEC_STALLED: u1, + }), base_address + 0xfc); + + /// address: 0x50200100 + /// Control behaviour of the input/output shift registers for state machine 2 + pub const SM2_SHIFTCTRL = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + /// Push automatically when the input shift register is filled, i.e. on an IN + /// instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + AUTOPUSH: u1, + /// Pull automatically when the output shift register is emptied, i.e. on or + /// following an OUT instruction which causes the output shift counter to reach or + /// exceed PULL_THRESH. + AUTOPULL: u1, + /// 1 = shift input shift register to right (data enters from left). 0 = to left. + IN_SHIFTDIR: u1, + /// 1 = shift out of output shift register to right. 0 = to left. + OUT_SHIFTDIR: u1, + /// Number of bits shifted into ISR before autopush, or conditional push (PUSH + /// IFFULL), will take place.\n + /// Write 0 for value of 32. + PUSH_THRESH: u5, + /// Number of bits shifted out of OSR before autopull, or conditional pull (PULL + /// IFEMPTY), will take place.\n + /// Write 0 for value of 32. + PULL_THRESH: u5, + /// When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep.\n + /// RX FIFO is disabled as a result (always reads as both full and empty).\n + /// FIFOs are flushed when this bit is changed. + FJOIN_TX: u1, + /// When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep.\n + /// TX FIFO is disabled as a result (always reads as both full and empty).\n + /// FIFOs are flushed when this bit is changed. + FJOIN_RX: u1, + }), base_address + 0x100); + + /// address: 0x50200104 + /// Current instruction address of state machine 2 + pub const SM2_ADDR = @intToPtr(*volatile MmioInt(32, u5), base_address + 0x104); + + /// address: 0x50200108 + /// Read to see the instruction currently addressed by state machine 2's program + /// counter\n + /// Write to execute an instruction immediately (including jumps) and then resume + /// execution. + pub const SM2_INSTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x108); + + /// address: 0x5020010c + /// State machine pin control + pub const SM2_PINCTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV + /// PINS instruction. The data written to this pin will always be the + /// least-significant bit of the OUT or MOV data. + OUT_BASE: u5, + /// The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS + /// instruction. The data written to this pin is the least-significant bit of the + /// SET data. + SET_BASE: u5, + /// The lowest-numbered pin that will be affected by a side-set operation. The MSBs + /// of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) + /// are used for side-set data, with the remaining LSBs used for delay. The + /// least-significant bit of the side-set portion is the bit written to this pin, + /// with more-significant bits written to higher-numbered pins. + SIDESET_BASE: u5, + /// The pin which is mapped to the least-significant bit of a state machine's IN + /// data bus. Higher-numbered pins are mapped to consecutively more-significant data + /// bits, with a modulo of 32 applied to pin number. + IN_BASE: u5, + /// The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. + /// In the range 0 to 32 inclusive. + OUT_COUNT: u6, + /// The number of pins asserted by a SET. In the range 0 to 5 inclusive. + SET_COUNT: u3, + /// The number of MSBs of the Delay/Side-set instruction field which are used for + /// side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, + /// no side-set) and maximum of 5 (all side-set, no delay). + SIDESET_COUNT: u3, + }), base_address + 0x10c); + + /// address: 0x50200110 + /// Clock divisor register for state machine 3\n + /// Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + pub const SM3_CLKDIV = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// Fractional part of clock divisor + FRAC: u8, + /// Effective frequency is sysclk/(int + frac/256).\n + /// Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + INT: u16, + }), base_address + 0x110); + + /// address: 0x50200114 + /// Execution/behavioural settings for state machine 3 + pub const SM3_EXECCTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// Comparison level for the MOV x, STATUS instruction + STATUS_N: u4, + /// Comparison used for the MOV x, STATUS instruction. + STATUS_SEL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + /// After reaching wrap_top, execution is wrapped to this address. + WRAP_BOTTOM: u5, + /// After reaching this address, execution is wrapped to wrap_bottom.\n + /// If the instruction is a jump, and the jump condition is true, the jump takes + /// priority. + WRAP_TOP: u5, + /// Continuously assert the most recent OUT/SET to the pins + OUT_STICKY: u1, + /// If 1, use a bit of OUT data as an auxiliary write enable\n + /// When used in conjunction with OUT_STICKY, writes with an enable of 0 will\n + /// deassert the latest pin write. This can create useful masking/override + /// behaviour\n + /// due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + INLINE_OUT_EN: u1, + /// Which data bit to use for inline OUT enable + OUT_EN_SEL: u5, + /// The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + JMP_PIN: u5, + /// If 1, side-set data is asserted to pin directions, instead of pin values + SIDE_PINDIR: u1, + /// If 1, the MSB of the Delay/Side-set instruction field is used as side-set + /// enable, rather than a side-set data bit. This allows instructions to perform + /// side-set optionally, rather than on every instruction, but the maximum possible + /// side-set width is reduced from 5 to 4. Note that the value of + /// PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + SIDE_EN: u1, + /// If 1, an instruction written to SMx_INSTR is stalled, and latched by the state + /// machine. Will clear to 0 once this instruction completes. + EXEC_STALLED: u1, + }), base_address + 0x114); + + /// address: 0x50200118 + /// Control behaviour of the input/output shift registers for state machine 3 + pub const SM3_SHIFTCTRL = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + /// Push automatically when the input shift register is filled, i.e. on an IN + /// instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + AUTOPUSH: u1, + /// Pull automatically when the output shift register is emptied, i.e. on or + /// following an OUT instruction which causes the output shift counter to reach or + /// exceed PULL_THRESH. + AUTOPULL: u1, + /// 1 = shift input shift register to right (data enters from left). 0 = to left. + IN_SHIFTDIR: u1, + /// 1 = shift out of output shift register to right. 0 = to left. + OUT_SHIFTDIR: u1, + /// Number of bits shifted into ISR before autopush, or conditional push (PUSH + /// IFFULL), will take place.\n + /// Write 0 for value of 32. + PUSH_THRESH: u5, + /// Number of bits shifted out of OSR before autopull, or conditional pull (PULL + /// IFEMPTY), will take place.\n + /// Write 0 for value of 32. + PULL_THRESH: u5, + /// When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep.\n + /// RX FIFO is disabled as a result (always reads as both full and empty).\n + /// FIFOs are flushed when this bit is changed. + FJOIN_TX: u1, + /// When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep.\n + /// TX FIFO is disabled as a result (always reads as both full and empty).\n + /// FIFOs are flushed when this bit is changed. + FJOIN_RX: u1, + }), base_address + 0x118); + + /// address: 0x5020011c + /// Current instruction address of state machine 3 + pub const SM3_ADDR = @intToPtr(*volatile MmioInt(32, u5), base_address + 0x11c); + + /// address: 0x50200120 + /// Read to see the instruction currently addressed by state machine 3's program + /// counter\n + /// Write to execute an instruction immediately (including jumps) and then resume + /// execution. + pub const SM3_INSTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x120); + + /// address: 0x50200124 + /// State machine pin control + pub const SM3_PINCTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV + /// PINS instruction. The data written to this pin will always be the + /// least-significant bit of the OUT or MOV data. + OUT_BASE: u5, + /// The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS + /// instruction. The data written to this pin is the least-significant bit of the + /// SET data. + SET_BASE: u5, + /// The lowest-numbered pin that will be affected by a side-set operation. The MSBs + /// of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) + /// are used for side-set data, with the remaining LSBs used for delay. The + /// least-significant bit of the side-set portion is the bit written to this pin, + /// with more-significant bits written to higher-numbered pins. + SIDESET_BASE: u5, + /// The pin which is mapped to the least-significant bit of a state machine's IN + /// data bus. Higher-numbered pins are mapped to consecutively more-significant data + /// bits, with a modulo of 32 applied to pin number. + IN_BASE: u5, + /// The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. + /// In the range 0 to 32 inclusive. + OUT_COUNT: u6, + /// The number of pins asserted by a SET. In the range 0 to 5 inclusive. + SET_COUNT: u3, + /// The number of MSBs of the Delay/Side-set instruction field which are used for + /// side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, + /// no side-set) and maximum of 5 (all side-set, no delay). + SIDESET_COUNT: u3, + }), base_address + 0x124); + + /// address: 0x50200128 + /// Raw Interrupts + pub const INTR = @intToPtr(*volatile Mmio(32, packed struct { + SM0_RXNEMPTY: u1, + SM1_RXNEMPTY: u1, + SM2_RXNEMPTY: u1, + SM3_RXNEMPTY: u1, + SM0_TXNFULL: u1, + SM1_TXNFULL: u1, + SM2_TXNFULL: u1, + SM3_TXNFULL: u1, + SM0: u1, + SM1: u1, + SM2: u1, + SM3: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x128); + + /// address: 0x5020012c + /// Interrupt Enable for irq0 + pub const IRQ0_INTE = @intToPtr(*volatile Mmio(32, packed struct { + SM0_RXNEMPTY: u1, + SM1_RXNEMPTY: u1, + SM2_RXNEMPTY: u1, + SM3_RXNEMPTY: u1, + SM0_TXNFULL: u1, + SM1_TXNFULL: u1, + SM2_TXNFULL: u1, + SM3_TXNFULL: u1, + SM0: u1, + SM1: u1, + SM2: u1, + SM3: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x12c); + + /// address: 0x50200130 + /// Interrupt Force for irq0 + pub const IRQ0_INTF = @intToPtr(*volatile Mmio(32, packed struct { + SM0_RXNEMPTY: u1, + SM1_RXNEMPTY: u1, + SM2_RXNEMPTY: u1, + SM3_RXNEMPTY: u1, + SM0_TXNFULL: u1, + SM1_TXNFULL: u1, + SM2_TXNFULL: u1, + SM3_TXNFULL: u1, + SM0: u1, + SM1: u1, + SM2: u1, + SM3: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x130); + + /// address: 0x50200134 + /// Interrupt status after masking & forcing for irq0 + pub const IRQ0_INTS = @intToPtr(*volatile Mmio(32, packed struct { + SM0_RXNEMPTY: u1, + SM1_RXNEMPTY: u1, + SM2_RXNEMPTY: u1, + SM3_RXNEMPTY: u1, + SM0_TXNFULL: u1, + SM1_TXNFULL: u1, + SM2_TXNFULL: u1, + SM3_TXNFULL: u1, + SM0: u1, + SM1: u1, + SM2: u1, + SM3: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x134); + + /// address: 0x50200138 + /// Interrupt Enable for irq1 + pub const IRQ1_INTE = @intToPtr(*volatile Mmio(32, packed struct { + SM0_RXNEMPTY: u1, + SM1_RXNEMPTY: u1, + SM2_RXNEMPTY: u1, + SM3_RXNEMPTY: u1, + SM0_TXNFULL: u1, + SM1_TXNFULL: u1, + SM2_TXNFULL: u1, + SM3_TXNFULL: u1, + SM0: u1, + SM1: u1, + SM2: u1, + SM3: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x138); + + /// address: 0x5020013c + /// Interrupt Force for irq1 + pub const IRQ1_INTF = @intToPtr(*volatile Mmio(32, packed struct { + SM0_RXNEMPTY: u1, + SM1_RXNEMPTY: u1, + SM2_RXNEMPTY: u1, + SM3_RXNEMPTY: u1, + SM0_TXNFULL: u1, + SM1_TXNFULL: u1, + SM2_TXNFULL: u1, + SM3_TXNFULL: u1, + SM0: u1, + SM1: u1, + SM2: u1, + SM3: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x13c); + + /// address: 0x50200140 + /// Interrupt status after masking & forcing for irq1 + pub const IRQ1_INTS = @intToPtr(*volatile Mmio(32, packed struct { + SM0_RXNEMPTY: u1, + SM1_RXNEMPTY: u1, + SM2_RXNEMPTY: u1, + SM3_RXNEMPTY: u1, + SM0_TXNFULL: u1, + SM1_TXNFULL: u1, + SM2_TXNFULL: u1, + SM3_TXNFULL: u1, + SM0: u1, + SM1: u1, + SM2: u1, + SM3: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x140); + }; + pub const PIO1 = struct { + pub const base_address = 0x50300000; + + /// address: 0x50300000 + /// PIO control register + pub const CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// Enable/disable each of the four state machines by writing 1/0 to each of these + /// four bits. When disabled, a state machine will cease executing instructions, + /// except those written directly to SMx_INSTR by the system. Multiple bits can be + /// set/cleared at once to run/halt multiple state machines simultaneously. + SM_ENABLE: u4, + /// Write 1 to instantly clear internal SM state which may be otherwise difficult to + /// access and will affect future execution.\n\n + /// Specifically, the following are cleared: input and output shift counters; the + /// contents of the input shift register; the delay counter; the waiting-on-IRQ + /// state; any stalled instruction written to SMx_INSTR or run by OUT/MOV EXEC; any + /// pin write left asserted due to OUT_STICKY. + SM_RESTART: u4, + /// Restart a state machine's clock divider from an initial phase of 0. Clock + /// dividers are free-running, so once started, their output (including fractional + /// jitter) is completely determined by the integer/fractional divisor configured in + /// SMx_CLKDIV. This means that, if multiple clock dividers with the same divisor + /// are restarted simultaneously, by writing multiple 1 bits to this field, the + /// execution clocks of those state machines will run in precise lockstep.\n\n + /// Note that setting/clearing SM_ENABLE does not stop the clock divider from + /// running, so once multiple state machines' clocks are synchronised, it is safe to + /// disable/reenable a state machine, whilst keeping the clock dividers in sync.\n\n + /// Note also that CLKDIV_RESTART can be written to whilst the state machine is + /// running, and this is useful to resynchronise clock dividers after the divisors + /// (SMx_CLKDIV) have been changed on-the-fly. + CLKDIV_RESTART: u4, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x0); + + /// address: 0x50300004 + /// FIFO status register + pub const FSTAT = @intToPtr(*volatile Mmio(32, packed struct { + /// State machine RX FIFO is full + RXFULL: u4, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + /// State machine RX FIFO is empty + RXEMPTY: u4, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// State machine TX FIFO is full + TXFULL: u4, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + /// State machine TX FIFO is empty + TXEMPTY: u4, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + }), base_address + 0x4); + + /// address: 0x50300008 + /// FIFO debug register + pub const FDEBUG = @intToPtr(*volatile Mmio(32, packed struct { + /// State machine has stalled on full RX FIFO during a blocking PUSH, or an IN with + /// autopush enabled. This flag is also set when a nonblocking PUSH to a full FIFO + /// took place, in which case the state machine has dropped data. Write 1 to clear. + RXSTALL: u4, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + /// RX FIFO underflow (i.e. read-on-empty by the system) has occurred. Write 1 to + /// clear. Note that read-on-empty does not perturb the state of the FIFO in any + /// way, but the data returned by reading from an empty FIFO is undefined, so this + /// flag generally only becomes set due to some kind of software error. + RXUNDER: u4, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// TX FIFO overflow (i.e. write-on-full by the system) has occurred. Write 1 to + /// clear. Note that write-on-full does not alter the state or contents of the FIFO + /// in any way, but the data that the system attempted to write is dropped, so if + /// this flag is set, your software has quite likely dropped some data on the floor. + TXOVER: u4, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + /// State machine has stalled on empty TX FIFO during a blocking PULL, or an OUT + /// with autopull enabled. Write 1 to clear. + TXSTALL: u4, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + }), base_address + 0x8); + + /// address: 0x5030000c + /// FIFO levels + pub const FLEVEL = @intToPtr(*volatile Mmio(32, packed struct { + TX0: u4, + RX0: u4, + TX1: u4, + RX1: u4, + TX2: u4, + RX2: u4, + TX3: u4, + RX3: u4, + }), base_address + 0xc); + + /// address: 0x50300010 + /// Direct write access to the TX FIFO for this state machine. Each write pushes one + /// word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO + /// state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + pub const TXF0 = @intToPtr(*volatile u32, base_address + 0x10); + + /// address: 0x50300014 + /// Direct write access to the TX FIFO for this state machine. Each write pushes one + /// word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO + /// state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + pub const TXF1 = @intToPtr(*volatile u32, base_address + 0x14); + + /// address: 0x50300018 + /// Direct write access to the TX FIFO for this state machine. Each write pushes one + /// word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO + /// state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + pub const TXF2 = @intToPtr(*volatile u32, base_address + 0x18); + + /// address: 0x5030001c + /// Direct write access to the TX FIFO for this state machine. Each write pushes one + /// word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO + /// state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + pub const TXF3 = @intToPtr(*volatile u32, base_address + 0x1c); + + /// address: 0x50300020 + /// Direct read access to the RX FIFO for this state machine. Each read pops one + /// word from the FIFO. Attempting to read from an empty FIFO has no effect on the + /// FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The + /// data returned to the system on a read from an empty FIFO is undefined. + pub const RXF0 = @intToPtr(*volatile u32, base_address + 0x20); + + /// address: 0x50300024 + /// Direct read access to the RX FIFO for this state machine. Each read pops one + /// word from the FIFO. Attempting to read from an empty FIFO has no effect on the + /// FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The + /// data returned to the system on a read from an empty FIFO is undefined. + pub const RXF1 = @intToPtr(*volatile u32, base_address + 0x24); + + /// address: 0x50300028 + /// Direct read access to the RX FIFO for this state machine. Each read pops one + /// word from the FIFO. Attempting to read from an empty FIFO has no effect on the + /// FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The + /// data returned to the system on a read from an empty FIFO is undefined. + pub const RXF2 = @intToPtr(*volatile u32, base_address + 0x28); + + /// address: 0x5030002c + /// Direct read access to the RX FIFO for this state machine. Each read pops one + /// word from the FIFO. Attempting to read from an empty FIFO has no effect on the + /// FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The + /// data returned to the system on a read from an empty FIFO is undefined. + pub const RXF3 = @intToPtr(*volatile u32, base_address + 0x2c); + + /// address: 0x50300030 + /// State machine IRQ flags register. Write 1 to clear. There are 8 state machine + /// IRQ flags, which can be set, cleared, and waited on by the state machines. + /// There's no fixed association between flags and state machines -- any state + /// machine can use any flag.\n\n + /// Any of the 8 flags can be used for timing synchronisation between state + /// machines, using IRQ and WAIT instructions. The lower four of these flags are + /// also routed out to system-level interrupt requests, alongside FIFO status + /// interrupts -- see e.g. IRQ0_INTE. + pub const IRQ = @intToPtr(*volatile MmioInt(32, u8), base_address + 0x30); + + /// address: 0x50300034 + /// Writing a 1 to each of these bits will forcibly assert the corresponding IRQ. + /// Note this is different to the INTF register: writing here affects PIO internal + /// state. INTF just asserts the processor-facing IRQ signal for testing ISRs, and + /// is not visible to the state machines. + pub const IRQ_FORCE = @intToPtr(*volatile MmioInt(32, u8), base_address + 0x34); + + /// address: 0x50300038 + /// There is a 2-flipflop synchronizer on each GPIO input, which protects PIO logic + /// from metastabilities. This increases input delay, and for fast synchronous IO + /// (e.g. SPI) these synchronizers may need to be bypassed. Each bit in this + /// register corresponds to one GPIO.\n + /// 0 -> input is synchronized (default)\n + /// 1 -> synchronizer is bypassed\n + /// If in doubt, leave this register as all zeroes. + pub const INPUT_SYNC_BYPASS = @intToPtr(*volatile u32, base_address + 0x38); + + /// address: 0x5030003c + /// Read to sample the pad output values PIO is currently driving to the GPIOs. On + /// RP2040 there are 30 GPIOs, so the two most significant bits are hardwired to 0. + pub const DBG_PADOUT = @intToPtr(*volatile u32, base_address + 0x3c); + + /// address: 0x50300040 + /// Read to sample the pad output enables (direction) PIO is currently driving to + /// the GPIOs. On RP2040 there are 30 GPIOs, so the two most significant bits are + /// hardwired to 0. + pub const DBG_PADOE = @intToPtr(*volatile u32, base_address + 0x40); + + /// address: 0x50300044 + /// The PIO hardware has some free parameters that may vary between chip products.\n + /// These should be provided in the chip datasheet, but are also exposed here. + pub const DBG_CFGINFO = @intToPtr(*volatile Mmio(32, packed struct { + /// The depth of the state machine TX/RX FIFOs, measured in words.\n + /// Joining fifos via SHIFTCTRL_FJOIN gives one FIFO with double\n + /// this depth. + FIFO_DEPTH: u6, + reserved0: u1 = 0, + reserved1: u1 = 0, + /// The number of state machines this PIO instance is equipped with. + SM_COUNT: u4, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + /// The size of the instruction memory, measured in units of one instruction + IMEM_SIZE: u6, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + }), base_address + 0x44); + + /// address: 0x50300048 + /// Write-only access to instruction memory location 0 + pub const INSTR_MEM0 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x48); + + /// address: 0x5030004c + /// Write-only access to instruction memory location 1 + pub const INSTR_MEM1 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x4c); + + /// address: 0x50300050 + /// Write-only access to instruction memory location 2 + pub const INSTR_MEM2 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x50); + + /// address: 0x50300054 + /// Write-only access to instruction memory location 3 + pub const INSTR_MEM3 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x54); + + /// address: 0x50300058 + /// Write-only access to instruction memory location 4 + pub const INSTR_MEM4 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x58); + + /// address: 0x5030005c + /// Write-only access to instruction memory location 5 + pub const INSTR_MEM5 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x5c); + + /// address: 0x50300060 + /// Write-only access to instruction memory location 6 + pub const INSTR_MEM6 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x60); + + /// address: 0x50300064 + /// Write-only access to instruction memory location 7 + pub const INSTR_MEM7 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x64); + + /// address: 0x50300068 + /// Write-only access to instruction memory location 8 + pub const INSTR_MEM8 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x68); + + /// address: 0x5030006c + /// Write-only access to instruction memory location 9 + pub const INSTR_MEM9 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x6c); + + /// address: 0x50300070 + /// Write-only access to instruction memory location 10 + pub const INSTR_MEM10 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x70); + + /// address: 0x50300074 + /// Write-only access to instruction memory location 11 + pub const INSTR_MEM11 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x74); + + /// address: 0x50300078 + /// Write-only access to instruction memory location 12 + pub const INSTR_MEM12 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x78); + + /// address: 0x5030007c + /// Write-only access to instruction memory location 13 + pub const INSTR_MEM13 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x7c); + + /// address: 0x50300080 + /// Write-only access to instruction memory location 14 + pub const INSTR_MEM14 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x80); + + /// address: 0x50300084 + /// Write-only access to instruction memory location 15 + pub const INSTR_MEM15 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x84); + + /// address: 0x50300088 + /// Write-only access to instruction memory location 16 + pub const INSTR_MEM16 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x88); + + /// address: 0x5030008c + /// Write-only access to instruction memory location 17 + pub const INSTR_MEM17 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x8c); + + /// address: 0x50300090 + /// Write-only access to instruction memory location 18 + pub const INSTR_MEM18 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x90); + + /// address: 0x50300094 + /// Write-only access to instruction memory location 19 + pub const INSTR_MEM19 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x94); + + /// address: 0x50300098 + /// Write-only access to instruction memory location 20 + pub const INSTR_MEM20 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x98); + + /// address: 0x5030009c + /// Write-only access to instruction memory location 21 + pub const INSTR_MEM21 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x9c); + + /// address: 0x503000a0 + /// Write-only access to instruction memory location 22 + pub const INSTR_MEM22 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xa0); + + /// address: 0x503000a4 + /// Write-only access to instruction memory location 23 + pub const INSTR_MEM23 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xa4); + + /// address: 0x503000a8 + /// Write-only access to instruction memory location 24 + pub const INSTR_MEM24 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xa8); + + /// address: 0x503000ac + /// Write-only access to instruction memory location 25 + pub const INSTR_MEM25 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xac); + + /// address: 0x503000b0 + /// Write-only access to instruction memory location 26 + pub const INSTR_MEM26 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xb0); + + /// address: 0x503000b4 + /// Write-only access to instruction memory location 27 + pub const INSTR_MEM27 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xb4); + + /// address: 0x503000b8 + /// Write-only access to instruction memory location 28 + pub const INSTR_MEM28 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xb8); + + /// address: 0x503000bc + /// Write-only access to instruction memory location 29 + pub const INSTR_MEM29 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xbc); + + /// address: 0x503000c0 + /// Write-only access to instruction memory location 30 + pub const INSTR_MEM30 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xc0); + + /// address: 0x503000c4 + /// Write-only access to instruction memory location 31 + pub const INSTR_MEM31 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xc4); + + /// address: 0x503000c8 + /// Clock divisor register for state machine 0\n + /// Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + pub const SM0_CLKDIV = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// Fractional part of clock divisor + FRAC: u8, + /// Effective frequency is sysclk/(int + frac/256).\n + /// Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + INT: u16, + }), base_address + 0xc8); + + /// address: 0x503000cc + /// Execution/behavioural settings for state machine 0 + pub const SM0_EXECCTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// Comparison level for the MOV x, STATUS instruction + STATUS_N: u4, + /// Comparison used for the MOV x, STATUS instruction. + STATUS_SEL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + /// After reaching wrap_top, execution is wrapped to this address. + WRAP_BOTTOM: u5, + /// After reaching this address, execution is wrapped to wrap_bottom.\n + /// If the instruction is a jump, and the jump condition is true, the jump takes + /// priority. + WRAP_TOP: u5, + /// Continuously assert the most recent OUT/SET to the pins + OUT_STICKY: u1, + /// If 1, use a bit of OUT data as an auxiliary write enable\n + /// When used in conjunction with OUT_STICKY, writes with an enable of 0 will\n + /// deassert the latest pin write. This can create useful masking/override + /// behaviour\n + /// due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + INLINE_OUT_EN: u1, + /// Which data bit to use for inline OUT enable + OUT_EN_SEL: u5, + /// The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + JMP_PIN: u5, + /// If 1, side-set data is asserted to pin directions, instead of pin values + SIDE_PINDIR: u1, + /// If 1, the MSB of the Delay/Side-set instruction field is used as side-set + /// enable, rather than a side-set data bit. This allows instructions to perform + /// side-set optionally, rather than on every instruction, but the maximum possible + /// side-set width is reduced from 5 to 4. Note that the value of + /// PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + SIDE_EN: u1, + /// If 1, an instruction written to SMx_INSTR is stalled, and latched by the state + /// machine. Will clear to 0 once this instruction completes. + EXEC_STALLED: u1, + }), base_address + 0xcc); + + /// address: 0x503000d0 + /// Control behaviour of the input/output shift registers for state machine 0 + pub const SM0_SHIFTCTRL = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + /// Push automatically when the input shift register is filled, i.e. on an IN + /// instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + AUTOPUSH: u1, + /// Pull automatically when the output shift register is emptied, i.e. on or + /// following an OUT instruction which causes the output shift counter to reach or + /// exceed PULL_THRESH. + AUTOPULL: u1, + /// 1 = shift input shift register to right (data enters from left). 0 = to left. + IN_SHIFTDIR: u1, + /// 1 = shift out of output shift register to right. 0 = to left. + OUT_SHIFTDIR: u1, + /// Number of bits shifted into ISR before autopush, or conditional push (PUSH + /// IFFULL), will take place.\n + /// Write 0 for value of 32. + PUSH_THRESH: u5, + /// Number of bits shifted out of OSR before autopull, or conditional pull (PULL + /// IFEMPTY), will take place.\n + /// Write 0 for value of 32. + PULL_THRESH: u5, + /// When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep.\n + /// RX FIFO is disabled as a result (always reads as both full and empty).\n + /// FIFOs are flushed when this bit is changed. + FJOIN_TX: u1, + /// When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep.\n + /// TX FIFO is disabled as a result (always reads as both full and empty).\n + /// FIFOs are flushed when this bit is changed. + FJOIN_RX: u1, + }), base_address + 0xd0); + + /// address: 0x503000d4 + /// Current instruction address of state machine 0 + pub const SM0_ADDR = @intToPtr(*volatile MmioInt(32, u5), base_address + 0xd4); + + /// address: 0x503000d8 + /// Read to see the instruction currently addressed by state machine 0's program + /// counter\n + /// Write to execute an instruction immediately (including jumps) and then resume + /// execution. + pub const SM0_INSTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xd8); + + /// address: 0x503000dc + /// State machine pin control + pub const SM0_PINCTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV + /// PINS instruction. The data written to this pin will always be the + /// least-significant bit of the OUT or MOV data. + OUT_BASE: u5, + /// The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS + /// instruction. The data written to this pin is the least-significant bit of the + /// SET data. + SET_BASE: u5, + /// The lowest-numbered pin that will be affected by a side-set operation. The MSBs + /// of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) + /// are used for side-set data, with the remaining LSBs used for delay. The + /// least-significant bit of the side-set portion is the bit written to this pin, + /// with more-significant bits written to higher-numbered pins. + SIDESET_BASE: u5, + /// The pin which is mapped to the least-significant bit of a state machine's IN + /// data bus. Higher-numbered pins are mapped to consecutively more-significant data + /// bits, with a modulo of 32 applied to pin number. + IN_BASE: u5, + /// The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. + /// In the range 0 to 32 inclusive. + OUT_COUNT: u6, + /// The number of pins asserted by a SET. In the range 0 to 5 inclusive. + SET_COUNT: u3, + /// The number of MSBs of the Delay/Side-set instruction field which are used for + /// side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, + /// no side-set) and maximum of 5 (all side-set, no delay). + SIDESET_COUNT: u3, + }), base_address + 0xdc); + + /// address: 0x503000e0 + /// Clock divisor register for state machine 1\n + /// Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + pub const SM1_CLKDIV = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// Fractional part of clock divisor + FRAC: u8, + /// Effective frequency is sysclk/(int + frac/256).\n + /// Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + INT: u16, + }), base_address + 0xe0); + + /// address: 0x503000e4 + /// Execution/behavioural settings for state machine 1 + pub const SM1_EXECCTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// Comparison level for the MOV x, STATUS instruction + STATUS_N: u4, + /// Comparison used for the MOV x, STATUS instruction. + STATUS_SEL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + /// After reaching wrap_top, execution is wrapped to this address. + WRAP_BOTTOM: u5, + /// After reaching this address, execution is wrapped to wrap_bottom.\n + /// If the instruction is a jump, and the jump condition is true, the jump takes + /// priority. + WRAP_TOP: u5, + /// Continuously assert the most recent OUT/SET to the pins + OUT_STICKY: u1, + /// If 1, use a bit of OUT data as an auxiliary write enable\n + /// When used in conjunction with OUT_STICKY, writes with an enable of 0 will\n + /// deassert the latest pin write. This can create useful masking/override + /// behaviour\n + /// due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + INLINE_OUT_EN: u1, + /// Which data bit to use for inline OUT enable + OUT_EN_SEL: u5, + /// The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + JMP_PIN: u5, + /// If 1, side-set data is asserted to pin directions, instead of pin values + SIDE_PINDIR: u1, + /// If 1, the MSB of the Delay/Side-set instruction field is used as side-set + /// enable, rather than a side-set data bit. This allows instructions to perform + /// side-set optionally, rather than on every instruction, but the maximum possible + /// side-set width is reduced from 5 to 4. Note that the value of + /// PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + SIDE_EN: u1, + /// If 1, an instruction written to SMx_INSTR is stalled, and latched by the state + /// machine. Will clear to 0 once this instruction completes. + EXEC_STALLED: u1, + }), base_address + 0xe4); + + /// address: 0x503000e8 + /// Control behaviour of the input/output shift registers for state machine 1 + pub const SM1_SHIFTCTRL = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + /// Push automatically when the input shift register is filled, i.e. on an IN + /// instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + AUTOPUSH: u1, + /// Pull automatically when the output shift register is emptied, i.e. on or + /// following an OUT instruction which causes the output shift counter to reach or + /// exceed PULL_THRESH. + AUTOPULL: u1, + /// 1 = shift input shift register to right (data enters from left). 0 = to left. + IN_SHIFTDIR: u1, + /// 1 = shift out of output shift register to right. 0 = to left. + OUT_SHIFTDIR: u1, + /// Number of bits shifted into ISR before autopush, or conditional push (PUSH + /// IFFULL), will take place.\n + /// Write 0 for value of 32. + PUSH_THRESH: u5, + /// Number of bits shifted out of OSR before autopull, or conditional pull (PULL + /// IFEMPTY), will take place.\n + /// Write 0 for value of 32. + PULL_THRESH: u5, + /// When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep.\n + /// RX FIFO is disabled as a result (always reads as both full and empty).\n + /// FIFOs are flushed when this bit is changed. + FJOIN_TX: u1, + /// When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep.\n + /// TX FIFO is disabled as a result (always reads as both full and empty).\n + /// FIFOs are flushed when this bit is changed. + FJOIN_RX: u1, + }), base_address + 0xe8); + + /// address: 0x503000ec + /// Current instruction address of state machine 1 + pub const SM1_ADDR = @intToPtr(*volatile MmioInt(32, u5), base_address + 0xec); + + /// address: 0x503000f0 + /// Read to see the instruction currently addressed by state machine 1's program + /// counter\n + /// Write to execute an instruction immediately (including jumps) and then resume + /// execution. + pub const SM1_INSTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xf0); + + /// address: 0x503000f4 + /// State machine pin control + pub const SM1_PINCTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV + /// PINS instruction. The data written to this pin will always be the + /// least-significant bit of the OUT or MOV data. + OUT_BASE: u5, + /// The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS + /// instruction. The data written to this pin is the least-significant bit of the + /// SET data. + SET_BASE: u5, + /// The lowest-numbered pin that will be affected by a side-set operation. The MSBs + /// of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) + /// are used for side-set data, with the remaining LSBs used for delay. The + /// least-significant bit of the side-set portion is the bit written to this pin, + /// with more-significant bits written to higher-numbered pins. + SIDESET_BASE: u5, + /// The pin which is mapped to the least-significant bit of a state machine's IN + /// data bus. Higher-numbered pins are mapped to consecutively more-significant data + /// bits, with a modulo of 32 applied to pin number. + IN_BASE: u5, + /// The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. + /// In the range 0 to 32 inclusive. + OUT_COUNT: u6, + /// The number of pins asserted by a SET. In the range 0 to 5 inclusive. + SET_COUNT: u3, + /// The number of MSBs of the Delay/Side-set instruction field which are used for + /// side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, + /// no side-set) and maximum of 5 (all side-set, no delay). + SIDESET_COUNT: u3, + }), base_address + 0xf4); + + /// address: 0x503000f8 + /// Clock divisor register for state machine 2\n + /// Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + pub const SM2_CLKDIV = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// Fractional part of clock divisor + FRAC: u8, + /// Effective frequency is sysclk/(int + frac/256).\n + /// Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + INT: u16, + }), base_address + 0xf8); + + /// address: 0x503000fc + /// Execution/behavioural settings for state machine 2 + pub const SM2_EXECCTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// Comparison level for the MOV x, STATUS instruction + STATUS_N: u4, + /// Comparison used for the MOV x, STATUS instruction. + STATUS_SEL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + /// After reaching wrap_top, execution is wrapped to this address. + WRAP_BOTTOM: u5, + /// After reaching this address, execution is wrapped to wrap_bottom.\n + /// If the instruction is a jump, and the jump condition is true, the jump takes + /// priority. + WRAP_TOP: u5, + /// Continuously assert the most recent OUT/SET to the pins + OUT_STICKY: u1, + /// If 1, use a bit of OUT data as an auxiliary write enable\n + /// When used in conjunction with OUT_STICKY, writes with an enable of 0 will\n + /// deassert the latest pin write. This can create useful masking/override + /// behaviour\n + /// due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + INLINE_OUT_EN: u1, + /// Which data bit to use for inline OUT enable + OUT_EN_SEL: u5, + /// The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + JMP_PIN: u5, + /// If 1, side-set data is asserted to pin directions, instead of pin values + SIDE_PINDIR: u1, + /// If 1, the MSB of the Delay/Side-set instruction field is used as side-set + /// enable, rather than a side-set data bit. This allows instructions to perform + /// side-set optionally, rather than on every instruction, but the maximum possible + /// side-set width is reduced from 5 to 4. Note that the value of + /// PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + SIDE_EN: u1, + /// If 1, an instruction written to SMx_INSTR is stalled, and latched by the state + /// machine. Will clear to 0 once this instruction completes. + EXEC_STALLED: u1, + }), base_address + 0xfc); + + /// address: 0x50300100 + /// Control behaviour of the input/output shift registers for state machine 2 + pub const SM2_SHIFTCTRL = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + /// Push automatically when the input shift register is filled, i.e. on an IN + /// instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + AUTOPUSH: u1, + /// Pull automatically when the output shift register is emptied, i.e. on or + /// following an OUT instruction which causes the output shift counter to reach or + /// exceed PULL_THRESH. + AUTOPULL: u1, + /// 1 = shift input shift register to right (data enters from left). 0 = to left. + IN_SHIFTDIR: u1, + /// 1 = shift out of output shift register to right. 0 = to left. + OUT_SHIFTDIR: u1, + /// Number of bits shifted into ISR before autopush, or conditional push (PUSH + /// IFFULL), will take place.\n + /// Write 0 for value of 32. + PUSH_THRESH: u5, + /// Number of bits shifted out of OSR before autopull, or conditional pull (PULL + /// IFEMPTY), will take place.\n + /// Write 0 for value of 32. + PULL_THRESH: u5, + /// When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep.\n + /// RX FIFO is disabled as a result (always reads as both full and empty).\n + /// FIFOs are flushed when this bit is changed. + FJOIN_TX: u1, + /// When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep.\n + /// TX FIFO is disabled as a result (always reads as both full and empty).\n + /// FIFOs are flushed when this bit is changed. + FJOIN_RX: u1, + }), base_address + 0x100); + + /// address: 0x50300104 + /// Current instruction address of state machine 2 + pub const SM2_ADDR = @intToPtr(*volatile MmioInt(32, u5), base_address + 0x104); + + /// address: 0x50300108 + /// Read to see the instruction currently addressed by state machine 2's program + /// counter\n + /// Write to execute an instruction immediately (including jumps) and then resume + /// execution. + pub const SM2_INSTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x108); + + /// address: 0x5030010c + /// State machine pin control + pub const SM2_PINCTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV + /// PINS instruction. The data written to this pin will always be the + /// least-significant bit of the OUT or MOV data. + OUT_BASE: u5, + /// The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS + /// instruction. The data written to this pin is the least-significant bit of the + /// SET data. + SET_BASE: u5, + /// The lowest-numbered pin that will be affected by a side-set operation. The MSBs + /// of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) + /// are used for side-set data, with the remaining LSBs used for delay. The + /// least-significant bit of the side-set portion is the bit written to this pin, + /// with more-significant bits written to higher-numbered pins. + SIDESET_BASE: u5, + /// The pin which is mapped to the least-significant bit of a state machine's IN + /// data bus. Higher-numbered pins are mapped to consecutively more-significant data + /// bits, with a modulo of 32 applied to pin number. + IN_BASE: u5, + /// The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. + /// In the range 0 to 32 inclusive. + OUT_COUNT: u6, + /// The number of pins asserted by a SET. In the range 0 to 5 inclusive. + SET_COUNT: u3, + /// The number of MSBs of the Delay/Side-set instruction field which are used for + /// side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, + /// no side-set) and maximum of 5 (all side-set, no delay). + SIDESET_COUNT: u3, + }), base_address + 0x10c); + + /// address: 0x50300110 + /// Clock divisor register for state machine 3\n + /// Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + pub const SM3_CLKDIV = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// Fractional part of clock divisor + FRAC: u8, + /// Effective frequency is sysclk/(int + frac/256).\n + /// Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + INT: u16, + }), base_address + 0x110); + + /// address: 0x50300114 + /// Execution/behavioural settings for state machine 3 + pub const SM3_EXECCTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// Comparison level for the MOV x, STATUS instruction + STATUS_N: u4, + /// Comparison used for the MOV x, STATUS instruction. + STATUS_SEL: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + /// After reaching wrap_top, execution is wrapped to this address. + WRAP_BOTTOM: u5, + /// After reaching this address, execution is wrapped to wrap_bottom.\n + /// If the instruction is a jump, and the jump condition is true, the jump takes + /// priority. + WRAP_TOP: u5, + /// Continuously assert the most recent OUT/SET to the pins + OUT_STICKY: u1, + /// If 1, use a bit of OUT data as an auxiliary write enable\n + /// When used in conjunction with OUT_STICKY, writes with an enable of 0 will\n + /// deassert the latest pin write. This can create useful masking/override + /// behaviour\n + /// due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + INLINE_OUT_EN: u1, + /// Which data bit to use for inline OUT enable + OUT_EN_SEL: u5, + /// The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + JMP_PIN: u5, + /// If 1, side-set data is asserted to pin directions, instead of pin values + SIDE_PINDIR: u1, + /// If 1, the MSB of the Delay/Side-set instruction field is used as side-set + /// enable, rather than a side-set data bit. This allows instructions to perform + /// side-set optionally, rather than on every instruction, but the maximum possible + /// side-set width is reduced from 5 to 4. Note that the value of + /// PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + SIDE_EN: u1, + /// If 1, an instruction written to SMx_INSTR is stalled, and latched by the state + /// machine. Will clear to 0 once this instruction completes. + EXEC_STALLED: u1, + }), base_address + 0x114); + + /// address: 0x50300118 + /// Control behaviour of the input/output shift registers for state machine 3 + pub const SM3_SHIFTCTRL = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + /// Push automatically when the input shift register is filled, i.e. on an IN + /// instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + AUTOPUSH: u1, + /// Pull automatically when the output shift register is emptied, i.e. on or + /// following an OUT instruction which causes the output shift counter to reach or + /// exceed PULL_THRESH. + AUTOPULL: u1, + /// 1 = shift input shift register to right (data enters from left). 0 = to left. + IN_SHIFTDIR: u1, + /// 1 = shift out of output shift register to right. 0 = to left. + OUT_SHIFTDIR: u1, + /// Number of bits shifted into ISR before autopush, or conditional push (PUSH + /// IFFULL), will take place.\n + /// Write 0 for value of 32. + PUSH_THRESH: u5, + /// Number of bits shifted out of OSR before autopull, or conditional pull (PULL + /// IFEMPTY), will take place.\n + /// Write 0 for value of 32. + PULL_THRESH: u5, + /// When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep.\n + /// RX FIFO is disabled as a result (always reads as both full and empty).\n + /// FIFOs are flushed when this bit is changed. + FJOIN_TX: u1, + /// When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep.\n + /// TX FIFO is disabled as a result (always reads as both full and empty).\n + /// FIFOs are flushed when this bit is changed. + FJOIN_RX: u1, + }), base_address + 0x118); + + /// address: 0x5030011c + /// Current instruction address of state machine 3 + pub const SM3_ADDR = @intToPtr(*volatile MmioInt(32, u5), base_address + 0x11c); + + /// address: 0x50300120 + /// Read to see the instruction currently addressed by state machine 3's program + /// counter\n + /// Write to execute an instruction immediately (including jumps) and then resume + /// execution. + pub const SM3_INSTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x120); + + /// address: 0x50300124 + /// State machine pin control + pub const SM3_PINCTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV + /// PINS instruction. The data written to this pin will always be the + /// least-significant bit of the OUT or MOV data. + OUT_BASE: u5, + /// The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS + /// instruction. The data written to this pin is the least-significant bit of the + /// SET data. + SET_BASE: u5, + /// The lowest-numbered pin that will be affected by a side-set operation. The MSBs + /// of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) + /// are used for side-set data, with the remaining LSBs used for delay. The + /// least-significant bit of the side-set portion is the bit written to this pin, + /// with more-significant bits written to higher-numbered pins. + SIDESET_BASE: u5, + /// The pin which is mapped to the least-significant bit of a state machine's IN + /// data bus. Higher-numbered pins are mapped to consecutively more-significant data + /// bits, with a modulo of 32 applied to pin number. + IN_BASE: u5, + /// The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. + /// In the range 0 to 32 inclusive. + OUT_COUNT: u6, + /// The number of pins asserted by a SET. In the range 0 to 5 inclusive. + SET_COUNT: u3, + /// The number of MSBs of the Delay/Side-set instruction field which are used for + /// side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, + /// no side-set) and maximum of 5 (all side-set, no delay). + SIDESET_COUNT: u3, + }), base_address + 0x124); + + /// address: 0x50300128 + /// Raw Interrupts + pub const INTR = @intToPtr(*volatile Mmio(32, packed struct { + SM0_RXNEMPTY: u1, + SM1_RXNEMPTY: u1, + SM2_RXNEMPTY: u1, + SM3_RXNEMPTY: u1, + SM0_TXNFULL: u1, + SM1_TXNFULL: u1, + SM2_TXNFULL: u1, + SM3_TXNFULL: u1, + SM0: u1, + SM1: u1, + SM2: u1, + SM3: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x128); + + /// address: 0x5030012c + /// Interrupt Enable for irq0 + pub const IRQ0_INTE = @intToPtr(*volatile Mmio(32, packed struct { + SM0_RXNEMPTY: u1, + SM1_RXNEMPTY: u1, + SM2_RXNEMPTY: u1, + SM3_RXNEMPTY: u1, + SM0_TXNFULL: u1, + SM1_TXNFULL: u1, + SM2_TXNFULL: u1, + SM3_TXNFULL: u1, + SM0: u1, + SM1: u1, + SM2: u1, + SM3: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x12c); + + /// address: 0x50300130 + /// Interrupt Force for irq0 + pub const IRQ0_INTF = @intToPtr(*volatile Mmio(32, packed struct { + SM0_RXNEMPTY: u1, + SM1_RXNEMPTY: u1, + SM2_RXNEMPTY: u1, + SM3_RXNEMPTY: u1, + SM0_TXNFULL: u1, + SM1_TXNFULL: u1, + SM2_TXNFULL: u1, + SM3_TXNFULL: u1, + SM0: u1, + SM1: u1, + SM2: u1, + SM3: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x130); + + /// address: 0x50300134 + /// Interrupt status after masking & forcing for irq0 + pub const IRQ0_INTS = @intToPtr(*volatile Mmio(32, packed struct { + SM0_RXNEMPTY: u1, + SM1_RXNEMPTY: u1, + SM2_RXNEMPTY: u1, + SM3_RXNEMPTY: u1, + SM0_TXNFULL: u1, + SM1_TXNFULL: u1, + SM2_TXNFULL: u1, + SM3_TXNFULL: u1, + SM0: u1, + SM1: u1, + SM2: u1, + SM3: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x134); + + /// address: 0x50300138 + /// Interrupt Enable for irq1 + pub const IRQ1_INTE = @intToPtr(*volatile Mmio(32, packed struct { + SM0_RXNEMPTY: u1, + SM1_RXNEMPTY: u1, + SM2_RXNEMPTY: u1, + SM3_RXNEMPTY: u1, + SM0_TXNFULL: u1, + SM1_TXNFULL: u1, + SM2_TXNFULL: u1, + SM3_TXNFULL: u1, + SM0: u1, + SM1: u1, + SM2: u1, + SM3: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x138); + + /// address: 0x5030013c + /// Interrupt Force for irq1 + pub const IRQ1_INTF = @intToPtr(*volatile Mmio(32, packed struct { + SM0_RXNEMPTY: u1, + SM1_RXNEMPTY: u1, + SM2_RXNEMPTY: u1, + SM3_RXNEMPTY: u1, + SM0_TXNFULL: u1, + SM1_TXNFULL: u1, + SM2_TXNFULL: u1, + SM3_TXNFULL: u1, + SM0: u1, + SM1: u1, + SM2: u1, + SM3: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x13c); + + /// address: 0x50300140 + /// Interrupt status after masking & forcing for irq1 + pub const IRQ1_INTS = @intToPtr(*volatile Mmio(32, packed struct { + SM0_RXNEMPTY: u1, + SM1_RXNEMPTY: u1, + SM2_RXNEMPTY: u1, + SM3_RXNEMPTY: u1, + SM0_TXNFULL: u1, + SM1_TXNFULL: u1, + SM2_TXNFULL: u1, + SM3_TXNFULL: u1, + SM0: u1, + SM1: u1, + SM2: u1, + SM3: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + }), base_address + 0x140); + }; + + /// Single-cycle IO block\n + /// Provides core-local and inter-core hardware for the two processors, with + /// single-cycle access. + pub const SIO = struct { + pub const base_address = 0xd0000000; + pub const version = "1"; + + /// address: 0xd0000000 + /// Processor core identifier\n + /// Value is 0 when read from processor core 0, and 1 when read from processor core + /// 1. + pub const CPUID = @intToPtr(*volatile u32, base_address + 0x0); + + /// address: 0xd0000004 + /// Input value for GPIO pins + pub const GPIO_IN = @intToPtr(*volatile MmioInt(32, u30), base_address + 0x4); + + /// address: 0xd0000008 + /// Input value for QSPI pins + pub const GPIO_HI_IN = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x8); + + /// address: 0xd0000010 + /// GPIO output value + pub const GPIO_OUT = @intToPtr(*volatile MmioInt(32, u30), base_address + 0x10); + + /// address: 0xd0000014 + /// GPIO output value set + pub const GPIO_OUT_SET = @intToPtr(*volatile MmioInt(32, u30), base_address + 0x14); + + /// address: 0xd0000018 + /// GPIO output value clear + pub const GPIO_OUT_CLR = @intToPtr(*volatile MmioInt(32, u30), base_address + 0x18); + + /// address: 0xd000001c + /// GPIO output value XOR + pub const GPIO_OUT_XOR = @intToPtr(*volatile MmioInt(32, u30), base_address + 0x1c); + + /// address: 0xd0000020 + /// GPIO output enable + pub const GPIO_OE = @intToPtr(*volatile MmioInt(32, u30), base_address + 0x20); + + /// address: 0xd0000024 + /// GPIO output enable set + pub const GPIO_OE_SET = @intToPtr(*volatile MmioInt(32, u30), base_address + 0x24); + + /// address: 0xd0000028 + /// GPIO output enable clear + pub const GPIO_OE_CLR = @intToPtr(*volatile MmioInt(32, u30), base_address + 0x28); + + /// address: 0xd000002c + /// GPIO output enable XOR + pub const GPIO_OE_XOR = @intToPtr(*volatile MmioInt(32, u30), base_address + 0x2c); + + /// address: 0xd0000030 + /// QSPI output value + pub const GPIO_HI_OUT = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x30); + + /// address: 0xd0000034 + /// QSPI output value set + pub const GPIO_HI_OUT_SET = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x34); + + /// address: 0xd0000038 + /// QSPI output value clear + pub const GPIO_HI_OUT_CLR = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x38); + + /// address: 0xd000003c + /// QSPI output value XOR + pub const GPIO_HI_OUT_XOR = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x3c); + + /// address: 0xd0000040 + /// QSPI output enable + pub const GPIO_HI_OE = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x40); + + /// address: 0xd0000044 + /// QSPI output enable set + pub const GPIO_HI_OE_SET = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x44); + + /// address: 0xd0000048 + /// QSPI output enable clear + pub const GPIO_HI_OE_CLR = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x48); + + /// address: 0xd000004c + /// QSPI output enable XOR + pub const GPIO_HI_OE_XOR = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x4c); + + /// address: 0xd0000050 + /// Status register for inter-core FIFOs (mailboxes).\n + /// There is one FIFO in the core 0 -> core 1 direction, and one core 1 -> core 0. + /// Both are 32 bits wide and 8 words deep.\n + /// Core 0 can see the read side of the 1->0 FIFO (RX), and the write side of 0->1 + /// FIFO (TX).\n + /// Core 1 can see the read side of the 0->1 FIFO (RX), and the write side of 1->0 + /// FIFO (TX).\n + /// The SIO IRQ for each core is the logical OR of the VLD, WOF and ROE fields of + /// its FIFO_ST register. + pub const FIFO_ST = @intToPtr(*volatile Mmio(32, packed struct { + /// Value is 1 if this core's RX FIFO is not empty (i.e. if FIFO_RD is valid) + VLD: u1, + /// Value is 1 if this core's TX FIFO is not full (i.e. if FIFO_WR is ready for more + /// data) + RDY: u1, + /// Sticky flag indicating the TX FIFO was written when full. This write was ignored + /// by the FIFO. + WOF: u1, + /// Sticky flag indicating the RX FIFO was read when empty. This read was ignored by + /// the FIFO. + ROE: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + }), base_address + 0x50); + + /// address: 0xd0000054 + /// Write access to this core's TX FIFO + pub const FIFO_WR = @intToPtr(*volatile u32, base_address + 0x54); + + /// address: 0xd0000058 + /// Read access to this core's RX FIFO + pub const FIFO_RD = @intToPtr(*volatile u32, base_address + 0x58); + + /// address: 0xd000005c + /// Spinlock state\n + /// A bitmap containing the state of all 32 spinlocks (1=locked).\n + /// Mainly intended for debugging. + pub const SPINLOCK_ST = @intToPtr(*volatile u32, base_address + 0x5c); + + /// address: 0xd0000060 + /// Divider unsigned dividend\n + /// Write to the DIVIDEND operand of the divider, i.e. the p in `p / q`.\n + /// Any operand write starts a new calculation. The results appear in QUOTIENT, + /// REMAINDER.\n + /// UDIVIDEND/SDIVIDEND are aliases of the same internal register. The U alias + /// starts an\n + /// unsigned calculation, and the S alias starts a signed calculation. + pub const DIV_UDIVIDEND = @intToPtr(*volatile u32, base_address + 0x60); + + /// address: 0xd0000064 + /// Divider unsigned divisor\n + /// Write to the DIVISOR operand of the divider, i.e. the q in `p / q`.\n + /// Any operand write starts a new calculation. The results appear in QUOTIENT, + /// REMAINDER.\n + /// UDIVIDEND/SDIVIDEND are aliases of the same internal register. The U alias + /// starts an\n + /// unsigned calculation, and the S alias starts a signed calculation. + pub const DIV_UDIVISOR = @intToPtr(*volatile u32, base_address + 0x64); + + /// address: 0xd0000068 + /// Divider signed dividend\n + /// The same as UDIVIDEND, but starts a signed calculation, rather than unsigned. + pub const DIV_SDIVIDEND = @intToPtr(*volatile u32, base_address + 0x68); + + /// address: 0xd000006c + /// Divider signed divisor\n + /// The same as UDIVISOR, but starts a signed calculation, rather than unsigned. + pub const DIV_SDIVISOR = @intToPtr(*volatile u32, base_address + 0x6c); + + /// address: 0xd0000070 + /// Divider result quotient\n + /// The result of `DIVIDEND / DIVISOR` (division). Contents undefined while + /// CSR_READY is low.\n + /// For signed calculations, QUOTIENT is negative when the signs of DIVIDEND and + /// DIVISOR differ.\n + /// This register can be written to directly, for context save/restore purposes. + /// This halts any\n + /// in-progress calculation and sets the CSR_READY and CSR_DIRTY flags.\n + /// Reading from QUOTIENT clears the CSR_DIRTY flag, so should read results in the + /// order\n + /// REMAINDER, QUOTIENT if CSR_DIRTY is used. + pub const DIV_QUOTIENT = @intToPtr(*volatile u32, base_address + 0x70); + + /// address: 0xd0000074 + /// Divider result remainder\n + /// The result of `DIVIDEND % DIVISOR` (modulo). Contents undefined while CSR_READY + /// is low.\n + /// For signed calculations, REMAINDER is negative only when DIVIDEND is negative.\n + /// This register can be written to directly, for context save/restore purposes. + /// This halts any\n + /// in-progress calculation and sets the CSR_READY and CSR_DIRTY flags. + pub const DIV_REMAINDER = @intToPtr(*volatile u32, base_address + 0x74); + + /// address: 0xd0000078 + /// Control and status register for divider. + pub const DIV_CSR = @intToPtr(*volatile Mmio(32, packed struct { + /// Reads as 0 when a calculation is in progress, 1 otherwise.\n + /// Writing an operand (xDIVIDEND, xDIVISOR) will immediately start a new + /// calculation, no\n + /// matter if one is already in progress.\n + /// Writing to a result register will immediately terminate any in-progress + /// calculation\n + /// and set the READY and DIRTY flags. + READY: u1, + /// Changes to 1 when any register is written, and back to 0 when QUOTIENT is + /// read.\n + /// Software can use this flag to make save/restore more efficient (skip if not + /// DIRTY).\n + /// If the flag is used in this way, it's recommended to either read QUOTIENT + /// only,\n + /// or REMAINDER and then QUOTIENT, to prevent data loss on context switch. + DIRTY: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + padding29: u1 = 0, + }), base_address + 0x78); + + /// address: 0xd0000080 + /// Read/write access to accumulator 0 + pub const INTERP0_ACCUM0 = @intToPtr(*volatile u32, base_address + 0x80); + + /// address: 0xd0000084 + /// Read/write access to accumulator 1 + pub const INTERP0_ACCUM1 = @intToPtr(*volatile u32, base_address + 0x84); + + /// address: 0xd0000088 + /// Read/write access to BASE0 register. + pub const INTERP0_BASE0 = @intToPtr(*volatile u32, base_address + 0x88); + + /// address: 0xd000008c + /// Read/write access to BASE1 register. + pub const INTERP0_BASE1 = @intToPtr(*volatile u32, base_address + 0x8c); + + /// address: 0xd0000090 + /// Read/write access to BASE2 register. + pub const INTERP0_BASE2 = @intToPtr(*volatile u32, base_address + 0x90); + + /// address: 0xd0000094 + /// Read LANE0 result, and simultaneously write lane results to both accumulators + /// (POP). + pub const INTERP0_POP_LANE0 = @intToPtr(*volatile u32, base_address + 0x94); + + /// address: 0xd0000098 + /// Read LANE1 result, and simultaneously write lane results to both accumulators + /// (POP). + pub const INTERP0_POP_LANE1 = @intToPtr(*volatile u32, base_address + 0x98); + + /// address: 0xd000009c + /// Read FULL result, and simultaneously write lane results to both accumulators + /// (POP). + pub const INTERP0_POP_FULL = @intToPtr(*volatile u32, base_address + 0x9c); + + /// address: 0xd00000a0 + /// Read LANE0 result, without altering any internal state (PEEK). + pub const INTERP0_PEEK_LANE0 = @intToPtr(*volatile u32, base_address + 0xa0); + + /// address: 0xd00000a4 + /// Read LANE1 result, without altering any internal state (PEEK). + pub const INTERP0_PEEK_LANE1 = @intToPtr(*volatile u32, base_address + 0xa4); + + /// address: 0xd00000a8 + /// Read FULL result, without altering any internal state (PEEK). + pub const INTERP0_PEEK_FULL = @intToPtr(*volatile u32, base_address + 0xa8); + + /// address: 0xd00000ac + /// Control register for lane 0 + pub const INTERP0_CTRL_LANE0 = @intToPtr(*volatile Mmio(32, packed struct { + /// Logical right-shift applied to accumulator before masking + SHIFT: u5, + /// The least-significant bit allowed to pass by the mask (inclusive) + MASK_LSB: u5, + /// The most-significant bit allowed to pass by the mask (inclusive)\n + /// Setting MSB < LSB may cause chip to turn inside-out + MASK_MSB: u5, + /// If SIGNED is set, the shifted and masked accumulator value is sign-extended to + /// 32 bits\n + /// before adding to BASE0, and LANE0 PEEK/POP appear extended to 32 bits when read + /// by processor. + SIGNED: u1, + /// If 1, feed the opposite lane's accumulator into this lane's shift + mask + /// hardware.\n + /// Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the + /// shift+mask bypass) + CROSS_INPUT: u1, + /// If 1, feed the opposite lane's result into this lane's accumulator on POP. + CROSS_RESULT: u1, + /// If 1, mask + shift is bypassed for LANE0 result. This does not affect FULL + /// result. + ADD_RAW: u1, + /// ORed into bits 29:28 of the lane result presented to the processor on the bus.\n + /// No effect on the internal 32-bit datapath. Handy for using a lane to generate + /// sequence\n + /// of pointers into flash or SRAM. + FORCE_MSB: u2, + /// Only present on INTERP0 on each core. If BLEND mode is enabled:\n + /// - LANE1 result is a linear interpolation between BASE0 and BASE1, controlled\n + /// by the 8 LSBs of lane 1 shift and mask value (a fractional number between\n + /// 0 and 255/256ths)\n + /// - LANE0 result does not have BASE0 added (yields only the 8 LSBs of lane 1 + /// shift+mask value)\n + /// - FULL result does not have lane 1 shift+mask value added (BASE2 + lane 0 + /// shift+mask)\n + /// LANE1 SIGNED flag controls whether the interpolation is signed or unsigned. + BLEND: u1, + reserved0: u1 = 0, + /// Indicates if any masked-off MSBs in ACCUM0 are set. + OVERF0: u1, + /// Indicates if any masked-off MSBs in ACCUM1 are set. + OVERF1: u1, + /// Set if either OVERF0 or OVERF1 is set. + OVERF: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + }), base_address + 0xac); + + /// address: 0xd00000b0 + /// Control register for lane 1 + pub const INTERP0_CTRL_LANE1 = @intToPtr(*volatile Mmio(32, packed struct { + /// Logical right-shift applied to accumulator before masking + SHIFT: u5, + /// The least-significant bit allowed to pass by the mask (inclusive) + MASK_LSB: u5, + /// The most-significant bit allowed to pass by the mask (inclusive)\n + /// Setting MSB < LSB may cause chip to turn inside-out + MASK_MSB: u5, + /// If SIGNED is set, the shifted and masked accumulator value is sign-extended to + /// 32 bits\n + /// before adding to BASE1, and LANE1 PEEK/POP appear extended to 32 bits when read + /// by processor. + SIGNED: u1, + /// If 1, feed the opposite lane's accumulator into this lane's shift + mask + /// hardware.\n + /// Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the + /// shift+mask bypass) + CROSS_INPUT: u1, + /// If 1, feed the opposite lane's result into this lane's accumulator on POP. + CROSS_RESULT: u1, + /// If 1, mask + shift is bypassed for LANE1 result. This does not affect FULL + /// result. + ADD_RAW: u1, + /// ORed into bits 29:28 of the lane result presented to the processor on the bus.\n + /// No effect on the internal 32-bit datapath. Handy for using a lane to generate + /// sequence\n + /// of pointers into flash or SRAM. + FORCE_MSB: u2, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + }), base_address + 0xb0); + + /// address: 0xd00000b4 + /// Values written here are atomically added to ACCUM0\n + /// Reading yields lane 0's raw shift and mask value (BASE0 not added). + pub const INTERP0_ACCUM0_ADD = @intToPtr(*volatile MmioInt(32, u24), base_address + 0xb4); + + /// address: 0xd00000b8 + /// Values written here are atomically added to ACCUM1\n + /// Reading yields lane 1's raw shift and mask value (BASE1 not added). + pub const INTERP0_ACCUM1_ADD = @intToPtr(*volatile MmioInt(32, u24), base_address + 0xb8); + + /// address: 0xd00000bc + /// On write, the lower 16 bits go to BASE0, upper bits to BASE1 simultaneously.\n + /// Each half is sign-extended to 32 bits if that lane's SIGNED flag is set. + pub const INTERP0_BASE_1AND0 = @intToPtr(*volatile u32, base_address + 0xbc); + + /// address: 0xd00000c0 + /// Read/write access to accumulator 0 + pub const INTERP1_ACCUM0 = @intToPtr(*volatile u32, base_address + 0xc0); + + /// address: 0xd00000c4 + /// Read/write access to accumulator 1 + pub const INTERP1_ACCUM1 = @intToPtr(*volatile u32, base_address + 0xc4); + + /// address: 0xd00000c8 + /// Read/write access to BASE0 register. + pub const INTERP1_BASE0 = @intToPtr(*volatile u32, base_address + 0xc8); + + /// address: 0xd00000cc + /// Read/write access to BASE1 register. + pub const INTERP1_BASE1 = @intToPtr(*volatile u32, base_address + 0xcc); + + /// address: 0xd00000d0 + /// Read/write access to BASE2 register. + pub const INTERP1_BASE2 = @intToPtr(*volatile u32, base_address + 0xd0); + + /// address: 0xd00000d4 + /// Read LANE0 result, and simultaneously write lane results to both accumulators + /// (POP). + pub const INTERP1_POP_LANE0 = @intToPtr(*volatile u32, base_address + 0xd4); + + /// address: 0xd00000d8 + /// Read LANE1 result, and simultaneously write lane results to both accumulators + /// (POP). + pub const INTERP1_POP_LANE1 = @intToPtr(*volatile u32, base_address + 0xd8); + + /// address: 0xd00000dc + /// Read FULL result, and simultaneously write lane results to both accumulators + /// (POP). + pub const INTERP1_POP_FULL = @intToPtr(*volatile u32, base_address + 0xdc); + + /// address: 0xd00000e0 + /// Read LANE0 result, without altering any internal state (PEEK). + pub const INTERP1_PEEK_LANE0 = @intToPtr(*volatile u32, base_address + 0xe0); + + /// address: 0xd00000e4 + /// Read LANE1 result, without altering any internal state (PEEK). + pub const INTERP1_PEEK_LANE1 = @intToPtr(*volatile u32, base_address + 0xe4); + + /// address: 0xd00000e8 + /// Read FULL result, without altering any internal state (PEEK). + pub const INTERP1_PEEK_FULL = @intToPtr(*volatile u32, base_address + 0xe8); + + /// address: 0xd00000ec + /// Control register for lane 0 + pub const INTERP1_CTRL_LANE0 = @intToPtr(*volatile Mmio(32, packed struct { + /// Logical right-shift applied to accumulator before masking + SHIFT: u5, + /// The least-significant bit allowed to pass by the mask (inclusive) + MASK_LSB: u5, + /// The most-significant bit allowed to pass by the mask (inclusive)\n + /// Setting MSB < LSB may cause chip to turn inside-out + MASK_MSB: u5, + /// If SIGNED is set, the shifted and masked accumulator value is sign-extended to + /// 32 bits\n + /// before adding to BASE0, and LANE0 PEEK/POP appear extended to 32 bits when read + /// by processor. + SIGNED: u1, + /// If 1, feed the opposite lane's accumulator into this lane's shift + mask + /// hardware.\n + /// Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the + /// shift+mask bypass) + CROSS_INPUT: u1, + /// If 1, feed the opposite lane's result into this lane's accumulator on POP. + CROSS_RESULT: u1, + /// If 1, mask + shift is bypassed for LANE0 result. This does not affect FULL + /// result. + ADD_RAW: u1, + /// ORed into bits 29:28 of the lane result presented to the processor on the bus.\n + /// No effect on the internal 32-bit datapath. Handy for using a lane to generate + /// sequence\n + /// of pointers into flash or SRAM. + FORCE_MSB: u2, + reserved0: u1 = 0, + /// Only present on INTERP1 on each core. If CLAMP mode is enabled:\n + /// - LANE0 result is shifted and masked ACCUM0, clamped by a lower bound of\n + /// BASE0 and an upper bound of BASE1.\n + /// - Signedness of these comparisons is determined by LANE0_CTRL_SIGNED + CLAMP: u1, + /// Indicates if any masked-off MSBs in ACCUM0 are set. + OVERF0: u1, + /// Indicates if any masked-off MSBs in ACCUM1 are set. + OVERF1: u1, + /// Set if either OVERF0 or OVERF1 is set. + OVERF: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + }), base_address + 0xec); + + /// address: 0xd00000f0 + /// Control register for lane 1 + pub const INTERP1_CTRL_LANE1 = @intToPtr(*volatile Mmio(32, packed struct { + /// Logical right-shift applied to accumulator before masking + SHIFT: u5, + /// The least-significant bit allowed to pass by the mask (inclusive) + MASK_LSB: u5, + /// The most-significant bit allowed to pass by the mask (inclusive)\n + /// Setting MSB < LSB may cause chip to turn inside-out + MASK_MSB: u5, + /// If SIGNED is set, the shifted and masked accumulator value is sign-extended to + /// 32 bits\n + /// before adding to BASE1, and LANE1 PEEK/POP appear extended to 32 bits when read + /// by processor. + SIGNED: u1, + /// If 1, feed the opposite lane's accumulator into this lane's shift + mask + /// hardware.\n + /// Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the + /// shift+mask bypass) + CROSS_INPUT: u1, + /// If 1, feed the opposite lane's result into this lane's accumulator on POP. + CROSS_RESULT: u1, + /// If 1, mask + shift is bypassed for LANE1 result. This does not affect FULL + /// result. + ADD_RAW: u1, + /// ORed into bits 29:28 of the lane result presented to the processor on the bus.\n + /// No effect on the internal 32-bit datapath. Handy for using a lane to generate + /// sequence\n + /// of pointers into flash or SRAM. + FORCE_MSB: u2, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + }), base_address + 0xf0); + + /// address: 0xd00000f4 + /// Values written here are atomically added to ACCUM0\n + /// Reading yields lane 0's raw shift and mask value (BASE0 not added). + pub const INTERP1_ACCUM0_ADD = @intToPtr(*volatile MmioInt(32, u24), base_address + 0xf4); + + /// address: 0xd00000f8 + /// Values written here are atomically added to ACCUM1\n + /// Reading yields lane 1's raw shift and mask value (BASE1 not added). + pub const INTERP1_ACCUM1_ADD = @intToPtr(*volatile MmioInt(32, u24), base_address + 0xf8); + + /// address: 0xd00000fc + /// On write, the lower 16 bits go to BASE0, upper bits to BASE1 simultaneously.\n + /// Each half is sign-extended to 32 bits if that lane's SIGNED flag is set. + pub const INTERP1_BASE_1AND0 = @intToPtr(*volatile u32, base_address + 0xfc); + + /// address: 0xd0000100 + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK0 = @intToPtr(*volatile u32, base_address + 0x100); + + /// address: 0xd0000104 + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK1 = @intToPtr(*volatile u32, base_address + 0x104); + + /// address: 0xd0000108 + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK2 = @intToPtr(*volatile u32, base_address + 0x108); + + /// address: 0xd000010c + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK3 = @intToPtr(*volatile u32, base_address + 0x10c); + + /// address: 0xd0000110 + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK4 = @intToPtr(*volatile u32, base_address + 0x110); + + /// address: 0xd0000114 + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK5 = @intToPtr(*volatile u32, base_address + 0x114); + + /// address: 0xd0000118 + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK6 = @intToPtr(*volatile u32, base_address + 0x118); + + /// address: 0xd000011c + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK7 = @intToPtr(*volatile u32, base_address + 0x11c); + + /// address: 0xd0000120 + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK8 = @intToPtr(*volatile u32, base_address + 0x120); + + /// address: 0xd0000124 + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK9 = @intToPtr(*volatile u32, base_address + 0x124); + + /// address: 0xd0000128 + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK10 = @intToPtr(*volatile u32, base_address + 0x128); + + /// address: 0xd000012c + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK11 = @intToPtr(*volatile u32, base_address + 0x12c); + + /// address: 0xd0000130 + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK12 = @intToPtr(*volatile u32, base_address + 0x130); + + /// address: 0xd0000134 + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK13 = @intToPtr(*volatile u32, base_address + 0x134); + + /// address: 0xd0000138 + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK14 = @intToPtr(*volatile u32, base_address + 0x138); + + /// address: 0xd000013c + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK15 = @intToPtr(*volatile u32, base_address + 0x13c); + + /// address: 0xd0000140 + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK16 = @intToPtr(*volatile u32, base_address + 0x140); + + /// address: 0xd0000144 + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK17 = @intToPtr(*volatile u32, base_address + 0x144); + + /// address: 0xd0000148 + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK18 = @intToPtr(*volatile u32, base_address + 0x148); + + /// address: 0xd000014c + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK19 = @intToPtr(*volatile u32, base_address + 0x14c); + + /// address: 0xd0000150 + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK20 = @intToPtr(*volatile u32, base_address + 0x150); + + /// address: 0xd0000154 + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK21 = @intToPtr(*volatile u32, base_address + 0x154); + + /// address: 0xd0000158 + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK22 = @intToPtr(*volatile u32, base_address + 0x158); + + /// address: 0xd000015c + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK23 = @intToPtr(*volatile u32, base_address + 0x15c); + + /// address: 0xd0000160 + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK24 = @intToPtr(*volatile u32, base_address + 0x160); + + /// address: 0xd0000164 + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK25 = @intToPtr(*volatile u32, base_address + 0x164); + + /// address: 0xd0000168 + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK26 = @intToPtr(*volatile u32, base_address + 0x168); + + /// address: 0xd000016c + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK27 = @intToPtr(*volatile u32, base_address + 0x16c); + + /// address: 0xd0000170 + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK28 = @intToPtr(*volatile u32, base_address + 0x170); + + /// address: 0xd0000174 + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK29 = @intToPtr(*volatile u32, base_address + 0x174); + + /// address: 0xd0000178 + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK30 = @intToPtr(*volatile u32, base_address + 0x178); + + /// address: 0xd000017c + /// Reading from a spinlock address will:\n + /// - Return 0 if lock is already locked\n + /// - Otherwise return nonzero, and simultaneously claim the lock\n\n + /// Writing (any value) releases the lock.\n + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 + /// wins.\n + /// The value returned on success is 0x1 << lock number. + pub const SPINLOCK31 = @intToPtr(*volatile u32, base_address + 0x17c); + }; + pub const PPB = struct { + pub const base_address = 0xe0000000; + pub const version = "1"; + + /// address: 0xe000e010 + /// Use the SysTick Control and Status Register to enable the SysTick features. + pub const SYST_CSR = @intToPtr(*volatile Mmio(32, packed struct { + /// Enable SysTick counter:\n + /// 0 = Counter disabled.\n + /// 1 = Counter enabled. + ENABLE: u1, + /// Enables SysTick exception request:\n + /// 0 = Counting down to zero does not assert the SysTick exception request.\n + /// 1 = Counting down to zero to asserts the SysTick exception request. + TICKINT: u1, + /// SysTick clock source. Always reads as one if SYST_CALIB reports NOREF.\n + /// Selects the SysTick timer clock source:\n + /// 0 = External reference clock.\n + /// 1 = Processor clock. + CLKSOURCE: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// Returns 1 if timer counted to 0 since last time this was read. Clears on read by + /// application or debugger. + COUNTFLAG: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + }), base_address + 0xe010); + + /// address: 0xe000e014 + /// Use the SysTick Reload Value Register to specify the start value to load into + /// the current value register when the counter reaches 0. It can be any value + /// between 0 and 0x00FFFFFF. A start value of 0 is possible, but has no effect + /// because the SysTick interrupt and COUNTFLAG are activated when counting from 1 + /// to 0. The reset value of this register is UNKNOWN.\n + /// To generate a multi-shot timer with a period of N processor clock cycles, use a + /// RELOAD value of N-1. For example, if the SysTick interrupt is required every 100 + /// clock pulses, set RELOAD to 99. + pub const SYST_RVR = @intToPtr(*volatile Mmio(32, packed struct { + /// Value to load into the SysTick Current Value Register when the counter reaches + /// 0. + RELOAD: u24, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0xe014); + + /// address: 0xe000e018 + /// Use the SysTick Current Value Register to find the current value in the + /// register. The reset value of this register is UNKNOWN. + pub const SYST_CVR = @intToPtr(*volatile Mmio(32, packed struct { + /// Reads return the current value of the SysTick counter. This register is + /// write-clear. Writing to it with any value clears the register to 0. Clearing + /// this register also clears the COUNTFLAG bit of the SysTick Control and Status + /// Register. + CURRENT: u24, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0xe018); + + /// address: 0xe000e01c + /// Use the SysTick Calibration Value Register to enable software to scale to any + /// required speed using divide and multiply. + pub const SYST_CALIB = @intToPtr(*volatile Mmio(32, packed struct { + /// An optional Reload value to be used for 10ms (100Hz) timing, subject to system + /// clock skew errors. If the value reads as 0, the calibration value is not known. + TENMS: u24, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + /// If reads as 1, the calibration value for 10ms is inexact (due to clock + /// frequency). + SKEW: u1, + /// If reads as 1, the Reference clock is not provided - the CLKSOURCE bit of the + /// SysTick Control and Status register will be forced to 1 and cannot be cleared to + /// 0. + NOREF: u1, + }), base_address + 0xe01c); + + /// address: 0xe000e100 + /// Use the Interrupt Set-Enable Register to enable interrupts and determine which + /// interrupts are currently enabled.\n + /// If a pending interrupt is enabled, the NVIC activates the interrupt based on its + /// priority. If an interrupt is not enabled, asserting its interrupt signal changes + /// the interrupt state to pending, but the NVIC never activates the interrupt, + /// regardless of its priority. + pub const NVIC_ISER = @intToPtr(*volatile Mmio(32, packed struct { + /// Interrupt set-enable bits.\n + /// Write:\n + /// 0 = No effect.\n + /// 1 = Enable interrupt.\n + /// Read:\n + /// 0 = Interrupt disabled.\n + /// 1 = Interrupt enabled. + SETENA: u32, + }), base_address + 0xe100); + + /// address: 0xe000e180 + /// Use the Interrupt Clear-Enable Registers to disable interrupts and determine + /// which interrupts are currently enabled. + pub const NVIC_ICER = @intToPtr(*volatile Mmio(32, packed struct { + /// Interrupt clear-enable bits.\n + /// Write:\n + /// 0 = No effect.\n + /// 1 = Disable interrupt.\n + /// Read:\n + /// 0 = Interrupt disabled.\n + /// 1 = Interrupt enabled. + CLRENA: u32, + }), base_address + 0xe180); + + /// address: 0xe000e200 + /// The NVIC_ISPR forces interrupts into the pending state, and shows which + /// interrupts are pending. + pub const NVIC_ISPR = @intToPtr(*volatile Mmio(32, packed struct { + /// Interrupt set-pending bits.\n + /// Write:\n + /// 0 = No effect.\n + /// 1 = Changes interrupt state to pending.\n + /// Read:\n + /// 0 = Interrupt is not pending.\n + /// 1 = Interrupt is pending.\n + /// Note: Writing 1 to the NVIC_ISPR bit corresponding to:\n + /// An interrupt that is pending has no effect.\n + /// A disabled interrupt sets the state of that interrupt to pending. + SETPEND: u32, + }), base_address + 0xe200); + + /// address: 0xe000e280 + /// Use the Interrupt Clear-Pending Register to clear pending interrupts and + /// determine which interrupts are currently pending. + pub const NVIC_ICPR = @intToPtr(*volatile Mmio(32, packed struct { + /// Interrupt clear-pending bits.\n + /// Write:\n + /// 0 = No effect.\n + /// 1 = Removes pending state and interrupt.\n + /// Read:\n + /// 0 = Interrupt is not pending.\n + /// 1 = Interrupt is pending. + CLRPEND: u32, + }), base_address + 0xe280); + + /// address: 0xe000e400 + /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of + /// the available interrupts. 0 is the highest priority, and 3 is the lowest.\n + /// Note: Writing 1 to an NVIC_ICPR bit does not affect the active state of the + /// corresponding interrupt.\n + /// These registers are only word-accessible + pub const NVIC_IPR0 = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + /// Priority of interrupt 0 + IP_0: u2, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + /// Priority of interrupt 1 + IP_1: u2, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// Priority of interrupt 2 + IP_2: u2, + reserved18: u1 = 0, + reserved19: u1 = 0, + reserved20: u1 = 0, + reserved21: u1 = 0, + reserved22: u1 = 0, + reserved23: u1 = 0, + /// Priority of interrupt 3 + IP_3: u2, + }), base_address + 0xe400); + + /// address: 0xe000e404 + /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of + /// the available interrupts. 0 is the highest priority, and 3 is the lowest. + pub const NVIC_IPR1 = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + /// Priority of interrupt 4 + IP_4: u2, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + /// Priority of interrupt 5 + IP_5: u2, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// Priority of interrupt 6 + IP_6: u2, + reserved18: u1 = 0, + reserved19: u1 = 0, + reserved20: u1 = 0, + reserved21: u1 = 0, + reserved22: u1 = 0, + reserved23: u1 = 0, + /// Priority of interrupt 7 + IP_7: u2, + }), base_address + 0xe404); + + /// address: 0xe000e408 + /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of + /// the available interrupts. 0 is the highest priority, and 3 is the lowest. + pub const NVIC_IPR2 = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + /// Priority of interrupt 8 + IP_8: u2, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + /// Priority of interrupt 9 + IP_9: u2, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// Priority of interrupt 10 + IP_10: u2, + reserved18: u1 = 0, + reserved19: u1 = 0, + reserved20: u1 = 0, + reserved21: u1 = 0, + reserved22: u1 = 0, + reserved23: u1 = 0, + /// Priority of interrupt 11 + IP_11: u2, + }), base_address + 0xe408); + + /// address: 0xe000e40c + /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of + /// the available interrupts. 0 is the highest priority, and 3 is the lowest. + pub const NVIC_IPR3 = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + /// Priority of interrupt 12 + IP_12: u2, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + /// Priority of interrupt 13 + IP_13: u2, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// Priority of interrupt 14 + IP_14: u2, + reserved18: u1 = 0, + reserved19: u1 = 0, + reserved20: u1 = 0, + reserved21: u1 = 0, + reserved22: u1 = 0, + reserved23: u1 = 0, + /// Priority of interrupt 15 + IP_15: u2, + }), base_address + 0xe40c); + + /// address: 0xe000e410 + /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of + /// the available interrupts. 0 is the highest priority, and 3 is the lowest. + pub const NVIC_IPR4 = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + /// Priority of interrupt 16 + IP_16: u2, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + /// Priority of interrupt 17 + IP_17: u2, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// Priority of interrupt 18 + IP_18: u2, + reserved18: u1 = 0, + reserved19: u1 = 0, + reserved20: u1 = 0, + reserved21: u1 = 0, + reserved22: u1 = 0, + reserved23: u1 = 0, + /// Priority of interrupt 19 + IP_19: u2, + }), base_address + 0xe410); + + /// address: 0xe000e414 + /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of + /// the available interrupts. 0 is the highest priority, and 3 is the lowest. + pub const NVIC_IPR5 = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + /// Priority of interrupt 20 + IP_20: u2, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + /// Priority of interrupt 21 + IP_21: u2, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// Priority of interrupt 22 + IP_22: u2, + reserved18: u1 = 0, + reserved19: u1 = 0, + reserved20: u1 = 0, + reserved21: u1 = 0, + reserved22: u1 = 0, + reserved23: u1 = 0, + /// Priority of interrupt 23 + IP_23: u2, + }), base_address + 0xe414); + + /// address: 0xe000e418 + /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of + /// the available interrupts. 0 is the highest priority, and 3 is the lowest. + pub const NVIC_IPR6 = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + /// Priority of interrupt 24 + IP_24: u2, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + /// Priority of interrupt 25 + IP_25: u2, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// Priority of interrupt 26 + IP_26: u2, + reserved18: u1 = 0, + reserved19: u1 = 0, + reserved20: u1 = 0, + reserved21: u1 = 0, + reserved22: u1 = 0, + reserved23: u1 = 0, + /// Priority of interrupt 27 + IP_27: u2, + }), base_address + 0xe418); + + /// address: 0xe000e41c + /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of + /// the available interrupts. 0 is the highest priority, and 3 is the lowest. + pub const NVIC_IPR7 = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + /// Priority of interrupt 28 + IP_28: u2, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + /// Priority of interrupt 29 + IP_29: u2, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + /// Priority of interrupt 30 + IP_30: u2, + reserved18: u1 = 0, + reserved19: u1 = 0, + reserved20: u1 = 0, + reserved21: u1 = 0, + reserved22: u1 = 0, + reserved23: u1 = 0, + /// Priority of interrupt 31 + IP_31: u2, + }), base_address + 0xe41c); + + /// address: 0xe000ed00 + /// Read the CPU ID Base Register to determine: the ID number of the processor core, + /// the version number of the processor core, the implementation details of the + /// processor core. + pub const CPUID = @intToPtr(*volatile Mmio(32, packed struct { + /// Minor revision number m in the rnpm revision status:\n + /// 0x1 = Patch 1. + REVISION: u4, + /// Number of processor within family: 0xC60 = Cortex-M0+ + PARTNO: u12, + /// Constant that defines the architecture of the processor:\n + /// 0xC = ARMv6-M architecture. + ARCHITECTURE: u4, + /// Major revision number n in the rnpm revision status:\n + /// 0x0 = Revision 0. + VARIANT: u4, + /// Implementor code: 0x41 = ARM + IMPLEMENTER: u8, + }), base_address + 0xed00); + + /// address: 0xe000ed04 + /// Use the Interrupt Control State Register to set a pending Non-Maskable Interrupt + /// (NMI), set or clear a pending PendSV, set or clear a pending SysTick, check for + /// pending exceptions, check the vector number of the highest priority pended + /// exception, check the vector number of the active exception. + pub const ICSR = @intToPtr(*volatile Mmio(32, packed struct { + /// Active exception number field. Reset clears the VECTACTIVE field. + VECTACTIVE: u9, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + /// Indicates the exception number for the highest priority pending exception: 0 = + /// no pending exceptions. Non zero = The pending state includes the effect of + /// memory-mapped enable and mask registers. It does not include the PRIMASK + /// special-purpose register qualifier. + VECTPENDING: u9, + reserved3: u1 = 0, + /// External interrupt pending flag + ISRPENDING: u1, + /// The system can only access this bit when the core is halted. It indicates that a + /// pending interrupt is to be taken in the next running cycle. If C_MASKINTS is + /// clear in the Debug Halting Control and Status Register, the interrupt is + /// serviced. + ISRPREEMPT: u1, + reserved4: u1 = 0, + /// SysTick exception clear-pending bit.\n + /// Write:\n + /// 0 = No effect.\n + /// 1 = Removes the pending state from the SysTick exception.\n + /// This bit is WO. On a register read its value is Unknown. + PENDSTCLR: u1, + /// SysTick exception set-pending bit.\n + /// Write:\n + /// 0 = No effect.\n + /// 1 = Changes SysTick exception state to pending.\n + /// Read:\n + /// 0 = SysTick exception is not pending.\n + /// 1 = SysTick exception is pending. + PENDSTSET: u1, + /// PendSV clear-pending bit.\n + /// Write:\n + /// 0 = No effect.\n + /// 1 = Removes the pending state from the PendSV exception. + PENDSVCLR: u1, + /// PendSV set-pending bit.\n + /// Write:\n + /// 0 = No effect.\n + /// 1 = Changes PendSV exception state to pending.\n + /// Read:\n + /// 0 = PendSV exception is not pending.\n + /// 1 = PendSV exception is pending.\n + /// Writing 1 to this bit is the only way to set the PendSV exception state to + /// pending. + PENDSVSET: u1, + reserved5: u1 = 0, + reserved6: u1 = 0, + /// Setting this bit will activate an NMI. Since NMI is the highest priority + /// exception, it will activate as soon as it is registered.\n + /// NMI set-pending bit.\n + /// Write:\n + /// 0 = No effect.\n + /// 1 = Changes NMI exception state to pending.\n + /// Read:\n + /// 0 = NMI exception is not pending.\n + /// 1 = NMI exception is pending.\n + /// Because NMI is the highest-priority exception, normally the processor enters the + /// NMI\n + /// exception handler as soon as it detects a write of 1 to this bit. Entering the + /// handler then clears\n + /// this bit to 0. This means a read of this bit by the NMI exception handler + /// returns 1 only if the\n + /// NMI signal is reasserted while the processor is executing that handler. + NMIPENDSET: u1, + }), base_address + 0xed04); + + /// address: 0xe000ed08 + /// The VTOR holds the vector table offset address. + pub const VTOR = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// Bits [31:8] of the indicate the vector table offset address. + TBLOFF: u24, + }), base_address + 0xed08); + + /// address: 0xe000ed0c + /// Use the Application Interrupt and Reset Control Register to: determine data + /// endianness, clear all active state information from debug halt mode, request a + /// system reset. + pub const AIRCR = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + /// Clears all active state information for fixed and configurable exceptions. This + /// bit: is self-clearing, can only be set by the DAP when the core is halted. When + /// set: clears all active exception status of the processor, forces a return to + /// Thread mode, forces an IPSR of 0. A debugger must re-initialize the stack. + VECTCLRACTIVE: u1, + /// Writing 1 to this bit causes the SYSRESETREQ signal to the outer system to be + /// asserted to request a reset. The intention is to force a large system reset of + /// all major components except for debug. The C_HALT bit in the DHCSR is cleared as + /// a result of the system reset requested. The debugger does not lose contact with + /// the device. + SYSRESETREQ: u1, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + /// Data endianness implemented:\n + /// 0 = Little-endian. + ENDIANESS: u1, + /// Register key:\n + /// Reads as Unknown\n + /// On writes, write 0x05FA to VECTKEY, otherwise the write is ignored. + VECTKEY: u16, + }), base_address + 0xed0c); + + /// address: 0xe000ed10 + /// System Control Register. Use the System Control Register for power-management + /// functions: signal to the system when the processor can enter a low power state, + /// control how the processor enters and exits low power states. + pub const SCR = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + /// Indicates sleep-on-exit when returning from Handler mode to Thread mode:\n + /// 0 = Do not sleep when returning to Thread mode.\n + /// 1 = Enter sleep, or deep sleep, on return from an ISR to Thread mode.\n + /// Setting this bit to 1 enables an interrupt driven application to avoid returning + /// to an empty main application. + SLEEPONEXIT: u1, + /// Controls whether the processor uses sleep or deep sleep as its low power mode:\n + /// 0 = Sleep.\n + /// 1 = Deep sleep. + SLEEPDEEP: u1, + reserved1: u1 = 0, + /// Send Event on Pending bit:\n + /// 0 = Only enabled interrupts or events can wakeup the processor, disabled + /// interrupts are excluded.\n + /// 1 = Enabled events and all interrupts, including disabled interrupts, can wakeup + /// the processor.\n + /// When an event or interrupt becomes pending, the event signal wakes up the + /// processor from WFE. If the\n + /// processor is not waiting for an event, the event is registered and affects the + /// next WFE.\n + /// The processor also wakes up on execution of an SEV instruction or an external + /// event. + SEVONPEND: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + }), base_address + 0xed10); + + /// address: 0xe000ed14 + /// The Configuration and Control Register permanently enables stack alignment and + /// causes unaligned accesses to result in a Hard Fault. + pub const CCR = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + /// Always reads as one, indicates that all unaligned accesses generate a HardFault. + UNALIGN_TRP: u1, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + /// Always reads as one, indicates 8-byte stack alignment on exception entry. On + /// exception entry, the processor uses bit[9] of the stacked PSR to indicate the + /// stack alignment. On return from the exception it uses this stacked bit to + /// restore the correct stack alignment. + STKALIGN: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + }), base_address + 0xed14); + + /// address: 0xe000ed1c + /// System handlers are a special class of exception handler that can have their + /// priority set to any of the priority levels. Use the System Handler Priority + /// Register 2 to set the priority of SVCall. + pub const SHPR2 = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + reserved18: u1 = 0, + reserved19: u1 = 0, + reserved20: u1 = 0, + reserved21: u1 = 0, + reserved22: u1 = 0, + reserved23: u1 = 0, + reserved24: u1 = 0, + reserved25: u1 = 0, + reserved26: u1 = 0, + reserved27: u1 = 0, + reserved28: u1 = 0, + reserved29: u1 = 0, + /// Priority of system handler 11, SVCall + PRI_11: u2, + }), base_address + 0xed1c); + + /// address: 0xe000ed20 + /// System handlers are a special class of exception handler that can have their + /// priority set to any of the priority levels. Use the System Handler Priority + /// Register 3 to set the priority of PendSV and SysTick. + pub const SHPR3 = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + reserved18: u1 = 0, + reserved19: u1 = 0, + reserved20: u1 = 0, + reserved21: u1 = 0, + /// Priority of system handler 14, PendSV + PRI_14: u2, + reserved22: u1 = 0, + reserved23: u1 = 0, + reserved24: u1 = 0, + reserved25: u1 = 0, + reserved26: u1 = 0, + reserved27: u1 = 0, + /// Priority of system handler 15, SysTick + PRI_15: u2, + }), base_address + 0xed20); + + /// address: 0xe000ed24 + /// Use the System Handler Control and State Register to determine or clear the + /// pending status of SVCall. + pub const SHCSR = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + /// Reads as 1 if SVCall is Pending. Write 1 to set pending SVCall, write 0 to clear + /// pending SVCall. + SVCALLPENDED: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + }), base_address + 0xed24); + + /// address: 0xe000ed90 + /// Read the MPU Type Register to determine if the processor implements an MPU, and + /// how many regions the MPU supports. + pub const MPU_TYPE = @intToPtr(*volatile Mmio(32, packed struct { + /// Indicates support for separate instruction and data address maps. Reads as 0 as + /// ARMv6-M only supports a unified MPU. + SEPARATE: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + reserved6: u1 = 0, + /// Number of regions supported by the MPU. + DREGION: u8, + /// Instruction region. Reads as zero as ARMv6-M only supports a unified MPU. + IREGION: u8, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + }), base_address + 0xed90); + + /// address: 0xe000ed94 + /// Use the MPU Control Register to enable and disable the MPU, and to control + /// whether the default memory map is enabled as a background region for privileged + /// accesses, and whether the MPU is enabled for HardFaults and NMIs. + pub const MPU_CTRL = @intToPtr(*volatile Mmio(32, packed struct { + /// Enables the MPU. If the MPU is disabled, privileged and unprivileged accesses + /// use the default memory map.\n + /// 0 = MPU disabled.\n + /// 1 = MPU enabled. + ENABLE: u1, + /// Controls the use of the MPU for HardFaults and NMIs. Setting this bit when + /// ENABLE is clear results in UNPREDICTABLE behaviour.\n + /// When the MPU is enabled:\n + /// 0 = MPU is disabled during HardFault and NMI handlers, regardless of the value + /// of the ENABLE bit.\n + /// 1 = the MPU is enabled during HardFault and NMI handlers. + HFNMIENA: u1, + /// Controls whether the default memory map is enabled as a background region for + /// privileged accesses. This bit is ignored when ENABLE is clear.\n + /// 0 = If the MPU is enabled, disables use of the default memory map. Any memory + /// access to a location not\n + /// covered by any enabled region causes a fault.\n + /// 1 = If the MPU is enabled, enables use of the default memory map as a background + /// region for privileged software accesses.\n + /// When enabled, the background region acts as if it is region number -1. Any + /// region that is defined and enabled has priority over this default map. + PRIVDEFENA: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + padding28: u1 = 0, + }), base_address + 0xed94); + + /// address: 0xe000ed98 + /// Use the MPU Region Number Register to select the region currently accessed by + /// MPU_RBAR and MPU_RASR. + pub const MPU_RNR = @intToPtr(*volatile Mmio(32, packed struct { + /// Indicates the MPU region referenced by the MPU_RBAR and MPU_RASR registers.\n + /// The MPU supports 8 memory regions, so the permitted values of this field are + /// 0-7. + REGION: u4, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + padding16: u1 = 0, + padding17: u1 = 0, + padding18: u1 = 0, + padding19: u1 = 0, + padding20: u1 = 0, + padding21: u1 = 0, + padding22: u1 = 0, + padding23: u1 = 0, + padding24: u1 = 0, + padding25: u1 = 0, + padding26: u1 = 0, + padding27: u1 = 0, + }), base_address + 0xed98); + + /// address: 0xe000ed9c + /// Read the MPU Region Base Address Register to determine the base address of the + /// region identified by MPU_RNR. Write to update the base address of said region or + /// that of a specified region, with whose number MPU_RNR will also be updated. + pub const MPU_RBAR = @intToPtr(*volatile Mmio(32, packed struct { + /// On writes, specifies the number of the region whose base address to update + /// provided VALID is set written as 1. On reads, returns bits [3:0] of MPU_RNR. + REGION: u4, + /// On writes, indicates whether the write must update the base address of the + /// region identified by the REGION field, updating the MPU_RNR to indicate this new + /// region.\n + /// Write:\n + /// 0 = MPU_RNR not changed, and the processor:\n + /// Updates the base address for the region specified in the MPU_RNR.\n + /// Ignores the value of the REGION field.\n + /// 1 = The processor:\n + /// Updates the value of the MPU_RNR to the value of the REGION field.\n + /// Updates the base address for the region specified in the REGION field.\n + /// Always reads as zero. + VALID: u1, + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + /// Base address of the region. + ADDR: u24, + }), base_address + 0xed9c); + + /// address: 0xe000eda0 + /// Use the MPU Region Attribute and Size Register to define the size, access + /// behaviour and memory type of the region identified by MPU_RNR, and enable that + /// region. + pub const MPU_RASR = @intToPtr(*volatile Mmio(32, packed struct { + /// Enables the region. + ENABLE: u1, + /// Indicates the region size. Region size in bytes = 2^(SIZE+1). The minimum + /// permitted value is 7 (b00111) = 256Bytes + SIZE: u5, + reserved0: u1 = 0, + reserved1: u1 = 0, + /// Subregion Disable. For regions of 256 bytes or larger, each bit of this field + /// controls whether one of the eight equal subregions is enabled. + SRD: u8, + /// The MPU Region Attribute field. Use to define the region attribute control.\n + /// 28 = XN: Instruction access disable bit:\n + /// 0 = Instruction fetches enabled.\n + /// 1 = Instruction fetches disabled.\n + /// 26:24 = AP: Access permission field\n + /// 18 = S: Shareable bit\n + /// 17 = C: Cacheable bit\n + /// 16 = B: Bufferable bit + ATTRS: u16, + }), base_address + 0xeda0); + }; +}; + +const std = @import("std"); + +pub fn mmio(addr: usize, comptime size: u8, comptime PackedT: type) *volatile Mmio(size, PackedT) { + return @intToPtr(*volatile Mmio(size, PackedT), addr); +} + +pub fn Mmio(comptime size: u8, comptime PackedT: type) type { + if ((size % 8) != 0) + @compileError("size must be divisible by 8!"); + + if (!std.math.isPowerOfTwo(size / 8)) + @compileError("size must encode a power of two number of bytes!"); + + const IntT = std.meta.Int(.unsigned, size); + + if (@sizeOf(PackedT) != (size / 8)) + @compileError(std.fmt.comptimePrint("IntT and PackedT must have the same size!, they are {} and {} bytes respectively", .{ size / 8, @sizeOf(PackedT) })); + + return extern struct { + const Self = @This(); + + raw: IntT, + + pub const underlying_type = PackedT; + + pub inline fn read(addr: *volatile Self) PackedT { + return @bitCast(PackedT, addr.raw); + } + + pub inline fn write(addr: *volatile Self, val: PackedT) void { + // This is a workaround for a compiler bug related to miscompilation + // If the tmp var is not used, result location will fuck things up + var tmp = @bitCast(IntT, val); + addr.raw = tmp; + } + + pub inline fn modify(addr: *volatile Self, fields: anytype) void { + var val = read(addr); + inline for (@typeInfo(@TypeOf(fields)).Struct.fields) |field| { + @field(val, field.name) = @field(fields, field.name); + } + write(addr, val); + } + + pub inline fn toggle(addr: *volatile Self, fields: anytype) void { + var val = read(addr); + inline for (@typeInfo(@TypeOf(fields)).Struct.fields) |field| { + @field(val, @tagName(field.default_value.?)) = !@field(val, @tagName(field.default_value.?)); + } + write(addr, val); + } + }; +} + +pub fn MmioInt(comptime size: u8, comptime T: type) type { + return extern struct { + const Self = @This(); + + raw: std.meta.Int(.unsigned, size), + + pub inline fn read(addr: *volatile Self) T { + return @truncate(T, addr.raw); + } + + pub inline fn modify(addr: *volatile Self, val: T) void { + const Int = std.meta.Int(.unsigned, size); + const mask = ~@as(Int, (1 << @bitSizeOf(T)) - 1); + + var tmp = addr.raw; + addr.raw = (tmp & mask) | val; + } + }; +} + +pub fn mmioInt(addr: usize, comptime size: usize, comptime T: type) *volatile MmioInt(size, T) { + return @intToPtr(*volatile MmioInt(size, T), addr); +} + +const InterruptVector = extern union { + C: fn () callconv(.C) void, + Naked: fn () callconv(.Naked) void, + // Interrupt is not supported on arm +}; + +const unhandled = InterruptVector{ + .C = struct { + fn tmp() callconv(.C) noreturn { + @panic("unhandled interrupt"); + } + }.tmp, +}; From c2a6b718e7fd8fc9d161ddfe95523e3dde602637 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Tue, 7 Jun 2022 01:20:38 -0700 Subject: [PATCH 02/74] add license remove microzig submodule remove submodule --- .gitmodules | 3 --- LICENSE | 11 +++++++++++ microzig | 1 - 3 files changed, 11 insertions(+), 4 deletions(-) delete mode 100644 .gitmodules create mode 100644 LICENSE delete mode 160000 microzig diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index fdd0dab..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "microzig"] - path = microzig - url = git@github.com:ZigEmbeddedGroup/microzig.git diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8df59b2 --- /dev/null +++ b/LICENSE @@ -0,0 +1,11 @@ +Copyright (c) 2022 Zig Embedded Group contributors + +This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source distribution. diff --git a/microzig b/microzig deleted file mode 160000 index ac19b7d..0000000 --- a/microzig +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ac19b7de8eb1551e603b3ce23a4aab69c71d1216 From 7d68b0bcbad63501235ea6a25f483d04678000f9 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Sun, 3 Jul 2022 07:52:26 -0700 Subject: [PATCH 03/74] pads bank bits set when setting gpio function --- src/hal/gpio.zig | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/hal/gpio.zig b/src/hal/gpio.zig index ab0f666..defc719 100644 --- a/src/hal/gpio.zig +++ b/src/hal/gpio.zig @@ -90,6 +90,12 @@ pub const Enabled = enum { enabled, }; +pub inline fn reset() void { + regs.RESETS.RESET.modify(.{ .io_bank0 = 1, .pads_bank0 = 1 }); + while (regs.RESETS.RESET_DONE.read().io_bank0 == 1) {} + while (regs.RESETS.RESET_DONE.read().pads_bank0 == 1) {} +} + //const gpio_num = gpio_num: { // // calculate max gpios using comptime parsing //}; @@ -122,8 +128,14 @@ pub inline fn put(comptime gpio: u32, value: u1) void { } pub inline fn setFunction(comptime gpio: u32, function: Function) void { - const reg_name = comptime std.fmt.comptimePrint("GPIO{}_CTRL", .{gpio}); - @field(regs.IO_BANK0, reg_name).write(.{ + const pad_bank_reg = comptime std.fmt.comptimePrint("GPIO{}", .{gpio}); + @field(regs.PADS_BANK0, pad_bank_reg).modify(.{ + .IE = 1, + .OD = 0, + }); + + const io_bank_reg = comptime std.fmt.comptimePrint("GPIO{}_CTRL", .{gpio}); + @field(regs.IO_BANK0, io_bank_reg).write(.{ .FUNCSEL = @enumToInt(function), .OUTOVER = 0, .INOVER = 0, From e541f966d42004acbcba9a939c0acfb604a3b4d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=27vesim=27=20Kuli=C5=84ski?= Date: Wed, 6 Jul 2022 21:29:36 +0200 Subject: [PATCH 04/74] multicore: add initial support --- src/hal.zig | 1 + src/hal/multicore.zig | 109 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 src/hal/multicore.zig diff --git a/src/hal.zig b/src/hal.zig index 41f4744..ae181da 100644 --- a/src/hal.zig +++ b/src/hal.zig @@ -2,6 +2,7 @@ const microzig = @import("microzig"); const regs = microzig.chip.regsisters; pub const gpio = @import("hal/gpio.zig"); pub const clocks = @import("hal/clocks.zig"); +pub const multicore = @import("hal/multicore.zig"); pub const default_clock_config = clocks.GlobalConfiguration.init(.{ //.ref = .{ .source = .src_xosc }, diff --git a/src/hal/multicore.zig b/src/hal/multicore.zig new file mode 100644 index 0000000..5c95c13 --- /dev/null +++ b/src/hal/multicore.zig @@ -0,0 +1,109 @@ +const std = @import("std"); +const microzig = @import("microzig"); +const regs = microzig.chip.registers; +const assert = std.debug.assert; + +pub const fifo = struct { + /// Check if the FIFO has valid data for reading. + pub fn is_read_ready() bool { + return regs.SIO.FIFO_ST.read().VLD == 1; + } + + /// Read from the FIFO + /// Will return null if it is empty. + pub fn read() ?u32 { + if (!is_read_ready()) + return null; + + return regs.SIO.FIFO_RD.*; + } + + /// Read from the FIFO, waiting for data if there is none. + pub fn read_blocking() u32 { + while (true) { + if (read()) |value| return value; + microzig.cpu.wfe(); + } + } + + /// Read from the FIFO, and throw everyting away. + pub fn drain() void { + while (read()) |_| {} + } + + /// Check if the FIFO is ready to receive data. + pub fn is_write_ready() bool { + return regs.SIO.FIFO_ST.read().RDY == 1; + } + + /// Write to the FIFO + /// You must check if there is space by calling is_write_ready + pub fn write(value: u32) void { + regs.SIO.FIFO_WR.* = value; + microzig.cpu.sev(); + } + + /// Write to the FIFO, waiting for room if it is full. + pub fn write_blocking(value: u32) void { + while (!is_write_ready()) + std.mem.doNotOptimizeAway(value); + + write(value); + } +}; + +var core1_stack: [128]u32 = undefined; + +/// Runs `entrypoint` on the second core. +pub fn launchCore1(entrypoint: fn () void) void { + launchCore1WithStack(entrypoint, &core1_stack); +} + +pub fn launchCore1WithStack(entrypoint: fn () void, stack: []u32) void { + // TODO: disable SIO interrupts + + const wrapper = struct { + fn wrapper(_: u32, _: u32, _: u32, _: u32, entry: u32, stack_base: [*]u32) callconv(.C) void { + // TODO: protect stack using MPU + _ = stack_base; + @intToPtr(fn () void, entry)(); + } + }.wrapper; + + // reset the second core + regs.PSM.FRCE_OFF.modify(.{ .proc1 = 1 }); + while (regs.PSM.FRCE_OFF.read().proc1 != 1) microzig.cpu.nop(); + regs.PSM.FRCE_OFF.modify(.{ .proc1 = 0 }); + + stack[stack.len - 2] = @ptrToInt(entrypoint); + stack[stack.len - 1] = @ptrToInt(stack.ptr); + + // calculate top of the stack + const stack_ptr: u32 = + @ptrToInt(stack.ptr) + + (stack.len - 2) * @sizeOf(u32); // pop the two elements we "pushed" above + + // after reseting core1 is waiting for this specific sequence + const cmds: [6]u32 = .{ + 0, + 0, + 1, + regs.PPB.VTOR.raw, + stack_ptr, + @ptrToInt(wrapper), + }; + + var seq: usize = 0; + while (seq < cmds.len) { + const cmd = cmds[seq]; + if (cmd == 0) { + // always drain the fifo before sending zero + fifo.drain(); + microzig.cpu.sev(); + } + + fifo.write_blocking(cmd); + // the second core should respond with the same value, if it doesnt't lets start over + seq = if (cmd == fifo.read_blocking()) seq + 1 else 0; + } +} From 0659bcd8c6296fcb10f2e0532ce9ff332ca2afbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=27vesim=27=20Kuli=C5=84ski?= Date: Thu, 7 Jul 2022 00:05:56 +0200 Subject: [PATCH 05/74] multicore: use camelCase for function names --- src/hal/multicore.zig | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/hal/multicore.zig b/src/hal/multicore.zig index 5c95c13..dd90d17 100644 --- a/src/hal/multicore.zig +++ b/src/hal/multicore.zig @@ -5,21 +5,21 @@ const assert = std.debug.assert; pub const fifo = struct { /// Check if the FIFO has valid data for reading. - pub fn is_read_ready() bool { + pub fn isReadReady() bool { return regs.SIO.FIFO_ST.read().VLD == 1; } /// Read from the FIFO /// Will return null if it is empty. pub fn read() ?u32 { - if (!is_read_ready()) + if (!isReadReady()) return null; return regs.SIO.FIFO_RD.*; } /// Read from the FIFO, waiting for data if there is none. - pub fn read_blocking() u32 { + pub fn readBloacking() u32 { while (true) { if (read()) |value| return value; microzig.cpu.wfe(); @@ -32,7 +32,7 @@ pub const fifo = struct { } /// Check if the FIFO is ready to receive data. - pub fn is_write_ready() bool { + pub fn isWriteReady() bool { return regs.SIO.FIFO_ST.read().RDY == 1; } @@ -44,8 +44,8 @@ pub const fifo = struct { } /// Write to the FIFO, waiting for room if it is full. - pub fn write_blocking(value: u32) void { - while (!is_write_ready()) + pub fn writeBlocking(value: u32) void { + while (!isWriteReady()) std.mem.doNotOptimizeAway(value); write(value); @@ -102,8 +102,8 @@ pub fn launchCore1WithStack(entrypoint: fn () void, stack: []u32) void { microzig.cpu.sev(); } - fifo.write_blocking(cmd); + fifo.writeBlocking(cmd); // the second core should respond with the same value, if it doesnt't lets start over - seq = if (cmd == fifo.read_blocking()) seq + 1 else 0; + seq = if (cmd == fifo.readBloacking()) seq + 1 else 0; } } From 303c9f183f8456edea52ab17f513f4acc8a2df4c Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Thu, 7 Jul 2022 21:38:40 -0700 Subject: [PATCH 06/74] add busy sleep functions --- src/hal.zig | 1 + src/hal/time.zig | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 src/hal/time.zig diff --git a/src/hal.zig b/src/hal.zig index ae181da..1a793b1 100644 --- a/src/hal.zig +++ b/src/hal.zig @@ -3,6 +3,7 @@ const regs = microzig.chip.regsisters; pub const gpio = @import("hal/gpio.zig"); pub const clocks = @import("hal/clocks.zig"); pub const multicore = @import("hal/multicore.zig"); +pub const time = @import("hal/time.zig"); pub const default_clock_config = clocks.GlobalConfiguration.init(.{ //.ref = .{ .source = .src_xosc }, diff --git a/src/hal/time.zig b/src/hal/time.zig new file mode 100644 index 0000000..2ed49ae --- /dev/null +++ b/src/hal/time.zig @@ -0,0 +1,44 @@ +const microzig = @import("microzig"); +const TIMER = microzig.chip.registers.TIMER; + +pub const Absolute = struct { + us_since_boot: u64, +}; + +pub fn getTimeSinceBoot() Absolute { + var high_word = TIMER.TIMERAWH.*; + + return while (true) { + var low_word = TIMER.TIMERAWL.*; + const next_high_word = TIMER.TIMERAWH.*; + if (next_high_word == high_word) + break Absolute{ + .us_since_boot = @intCast(u64, high_word) << 32 | low_word, + }; + + high_word = next_high_word; + } else unreachable; +} + +pub fn makeTimeoutUs(timeout_us: u64) Absolute { + return Absolute{ + .us_since_boot = getTimeSinceBoot().us_since_boot + timeout_us, + }; +} + +pub fn reached(time: Absolute) bool { + const now = getTimeSinceBoot(); + return now.us_since_boot >= time.us_since_boot; +} + +pub fn sleepMs(time_ms: u32) void { + sleepUs(time_ms * 1000); +} + +pub fn sleepUs(time_us: u64) void { + const end_time = Absolute{ + .us_since_boot = time_us + getTimeSinceBoot().us_since_boot, + }; + + while (!reached(end_time)) {} +} From ed05258e7ee4f0475bccd10110587e29602df9a7 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Fri, 8 Jul 2022 16:52:14 -0700 Subject: [PATCH 07/74] clean up gpios --- src/hal/gpio.zig | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/hal/gpio.zig b/src/hal/gpio.zig index defc719..416b155 100644 --- a/src/hal/gpio.zig +++ b/src/hal/gpio.zig @@ -79,10 +79,10 @@ pub const SlewRate = enum { }; pub const DriveStrength = enum { - ma_2, - ma_4, - ma_8, - ma_12, + @"2mA", + @"4mA", + @"8mA", + @"12mA", }; pub const Enabled = enum { @@ -92,18 +92,20 @@ pub const Enabled = enum { pub inline fn reset() void { regs.RESETS.RESET.modify(.{ .io_bank0 = 1, .pads_bank0 = 1 }); - while (regs.RESETS.RESET_DONE.read().io_bank0 == 1) {} - while (regs.RESETS.RESET_DONE.read().pads_bank0 == 1) {} -} + regs.RESETS.RESET.modify(.{ .io_bank0 = 0, .pads_bank0 = 0 }); -//const gpio_num = gpio_num: { -// // calculate max gpios using comptime parsing -//}; + while (true) { + const reset_done = regs.RESETS.RESET_DONE.read(); + if (reset_done.io_bank0 == 1 and reset_done.pads_bank0 == 1) + break; + } +} /// Initialize a GPIO, set func to SIO pub inline fn init(comptime gpio: u32) void { - regs.SIO.GPIO_OE_CLR.raw = 1 << gpio; - regs.SIO.GPIO_OUT_CLR.raw = 1 << gpio; + const mask = 1 << gpio; + regs.SIO.GPIO_OE_CLR.raw = mask; + regs.SIO.GPIO_OUT_CLR.raw = mask; setFunction(gpio, .sio); } @@ -113,17 +115,19 @@ pub inline fn deinit(comptime gpio: u32) void { } pub inline fn setDir(comptime gpio: u32, direction: Direction) void { + const mask = 1 << gpio; switch (direction) { - .in => regs.SIO.GPIO_OE_CLR.raw |= (1 << gpio), - .out => regs.SIO.GPIO_OE_SET.raw &= (1 << gpio), + .in => regs.SIO.GPIO_OE_CLR.raw = mask, + .out => regs.SIO.GPIO_OE_SET.raw = mask, } } /// Drive a single GPIO high/low pub inline fn put(comptime gpio: u32, value: u1) void { + const mask = 1 << gpio; switch (value) { - 0 => regs.SIO.GPIO_OUT.raw &= ~@as(u32, 1 << gpio), - 1 => regs.SIO.GPIO_OUT.raw |= (1 << gpio), + 0 => regs.SIO.GPIO_OUT_CLR.raw = mask, + 1 => regs.SIO.GPIO_OUT_SET.raw = mask, } } From 8751f6753d9a187ed6902f075914b77de6ce64e4 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Sun, 10 Jul 2022 16:26:47 -0700 Subject: [PATCH 08/74] Clock config (#5) * use array access for better codegen * frequency counter * wip * wip * refactor clock config and plls to reduce binary size --- src/hal.zig | 21 ++- src/hal/clocks.zig | 358 +++++++++++++++++++++++++++++++-------------- src/hal/pll.zig | 79 +++++----- src/hal/util.zig | 18 +++ 4 files changed, 323 insertions(+), 153 deletions(-) create mode 100644 src/hal/util.zig diff --git a/src/hal.zig b/src/hal.zig index 1a793b1..3db0677 100644 --- a/src/hal.zig +++ b/src/hal.zig @@ -5,18 +5,23 @@ pub const clocks = @import("hal/clocks.zig"); pub const multicore = @import("hal/multicore.zig"); pub const time = @import("hal/time.zig"); -pub const default_clock_config = clocks.GlobalConfiguration.init(.{ - //.ref = .{ .source = .src_xosc }, - .sys = .{ - .source = .pll_sys, - .freq = 125_000_000, - }, - .usb = .{ .source = .pll_usb }, +pub const clock_config = clocks.GlobalConfiguration.init(.{ + .sys = .{ .source = .src_xosc }, + .peri = .{ .source = .clk_sys }, + //.sys = .{ + // .source = .pll_sys, + // .freq = 125_000_000, + //}, + //.usb = .{ .source = .pll_usb }, //.adc = .{ .source = .pll_usb }, //.rtc = .{ .source = .pll_usb }, - .peri = .{ .source = .clk_sys }, + //.peri = .{ .source = .clk_sys }, }); +pub fn init() void { + clock_config.apply(); +} + pub fn getCpuId() u32 { return regs.SIO.CPUID.*; } diff --git a/src/hal/clocks.zig b/src/hal/clocks.zig index 7f266e2..fc28c19 100644 --- a/src/hal/clocks.zig +++ b/src/hal/clocks.zig @@ -1,11 +1,12 @@ const std = @import("std"); const microzig = @import("microzig"); const pll = @import("pll.zig"); +const util = @import("util.zig"); const assert = std.debug.assert; const regs = microzig.chip.registers; +const CLOCKS = regs.CLOCKS; const xosc_freq = microzig.board.xosc_freq; -// TODO: move to board file /// this is only nominal, very imprecise and prone to drift over time const rosc_freq = 6_500_000; @@ -64,37 +65,23 @@ pub const Generator = enum { adc, rtc, - // source directly from register definitions - const Source = enum { - rosc_clksrc_ph, - clksrc_clk_ref_aux, - xosc_clksrc, - clk_ref, - clksrc_clk_sys_aux, + // in some cases we can pretend the Generators are a homogenous array of + // register clusters for the sake of smaller codegen + const GeneratorRegs = packed struct { + ctrl: u32, + div: u32, + selected: u32, }; - // aux sources directly from register definitions - const AuxilarySource = enum { - clksrc_pll_sys, - clksrc_gpin0, - clksrc_gpin1, - clksrc_pll_usb, - rosc_clksrc, - xosc_clksrc, - clk_sys, - clk_usb, - clk_adc, - clk_rtc, - clk_ref, - rosc_clksrc_ph, - }; - - const source_map = struct { - const ref = [_]Generator.Source{ .rosc_clksrc_ph, .clksrc_clk_ref, .xosc_clksrc }; - const sys = [_]Generator.Source{ .clk_ref, .clksrc_clk_sys_aux }; - }; + comptime { + assert(12 == @sizeOf(GeneratorRegs)); + assert(24 == @sizeOf([2]GeneratorRegs)); + } - const aux_map = struct {}; + const generators = @intToPtr( + *volatile [9]GeneratorRegs, + regs.CLOCKS.base_address, + ); pub fn hasGlitchlessMux(generator: Generator) bool { return switch (generator) { @@ -104,46 +91,24 @@ pub const Generator = enum { } pub fn enable(generator: Generator) void { - inline for (std.meta.fields(Generator)) |field| { - if (generator == @field(Generator, field.name)) { - const reg_name = comptime std.fmt.comptimePrint("CLK_{s}_CTRL", .{ - uppercase(field.name), - }); - - if (@hasField(@TypeOf(@field(regs.CLOCKS, reg_name).*).underlying_type, "ENABLE")) - @field(regs.CLOCKS, reg_name).modify(.{ .ENABLE = 1 }); - } + switch (generator) { + .ref, .sys => {}, + else => generators[@enumToInt(generator)].ctrl |= (1 << 11), } } pub fn setDiv(generator: Generator, div: u32) void { - inline for (std.meta.fields(Generator)) |field| { - if (generator == @field(Generator, field.name)) { - const reg_name = comptime std.fmt.comptimePrint("CLK_{s}_DIV", .{ - uppercase(field.name), - }); - - if (@hasDecl(regs.CLOCKS, reg_name)) - @field(regs.CLOCKS, reg_name).raw = div - else - assert(false); // doesn't have a divider - } - } + if (generator == .peri) + return; + + generators[@enumToInt(generator)].div = div; } pub fn getDiv(generator: Generator) u32 { - return inline for (std.meta.fields(Generator)) |field| { - if (generator == @field(Generator, field.name)) { - const reg_name = comptime std.fmt.comptimePrint("CLK_{s}_DIV", .{ - uppercase(field.name), - }); - - break if (@hasDecl(regs.CLOCKS, reg_name)) - @field(regs.CLOCKS, reg_name).raw - else - 1; - } - } else unreachable; + if (generator == .peri) + return 1; + + return generators[@enumToInt(generator)].div; } // The bitfields for the *_SELECTED registers are actually a mask of which @@ -153,29 +118,151 @@ pub const Generator = enum { // // Some mention that this is only for the glitchless mux, so if it is non-glitchless then return true pub fn selected(generator: Generator) bool { - inline for (std.meta.fields(Generator)) |field| { - if (generator == @field(Generator, field.name)) { - return if (@field(Generator, field.name).hasGlitchlessMux()) ret: { - const reg_name = comptime std.fmt.comptimePrint("CLK_{s}_SELECTED", .{ - uppercase(field.name), - }); - - break :ret @field(regs.CLOCKS, reg_name).* != 0; - } else true; - } - } else unreachable; + return (0 != generators[@enumToInt(generator)].selected); + } + + pub fn clearSource(generator: Generator) void { + generators[@enumToInt(generator)].ctrl &= ~@as(u32, 0x3); + } + + pub fn disable(generator: Generator) void { + switch (generator) { + .sys, .ref => {}, + else => generators[@enumToInt(generator)].ctrl &= ~@as(u32, 1 << 11), + } + } + + pub fn isAuxSource(generator: Generator, source: Source) bool { + return switch (generator) { + .sys => switch (source) { + .clk_ref => false, + else => true, + }, + .ref => switch (source) { + .src_rosc, .src_xosc => false, + else => true, + }, + else => true, + }; + } + + pub fn setSource(generator: Generator, src: u32) void { + const mask = ~@as(u32, 0x3); + const ctrl_value = generators[@enumToInt(generator)].ctrl; + generators[@enumToInt(generator)].ctrl = (ctrl_value & mask) | src; + } + + pub fn setAuxSource(generator: Generator, auxsrc: u32) void { + const mask = ~@as(u32, 0x1e0); + const ctrl_value = generators[@enumToInt(generator)].ctrl; + generators[@enumToInt(generator)].ctrl = (ctrl_value & mask) | (auxsrc << 5); } }; pub const Source = enum { src_rosc, src_xosc, - src_aux, + src_gpin0, + src_gpin1, pll_sys, pll_usb, clk_sys, + clk_ref, + clk_usb, + clk_adc, + clk_rtc, }; +fn srcValue(generator: Generator, source: Source) u32 { + return switch (generator) { + .sys => src: { + const ret: u32 = switch (source) { + .clk_ref => 0, + else => 1, + }; + break :src ret; + }, + .ref => src: { + const ret: u32 = switch (source) { + .src_rosc => 0, + .src_xosc => 2, + else => 1, + }; + break :src ret; + }, + else => 0, + }; +} + +fn auxSrcValue(generator: Generator, source: Source) u32 { + return switch (generator) { + .sys => auxsrc: { + const ret: u32 = switch (source) { + .pll_sys => 0, + .pll_usb => 1, + .src_rosc => 2, + .src_xosc => 3, + .src_gpin0 => 4, + .src_gpin1 => 5, + else => @panic("invalid source for generator"), + }; + break :auxsrc ret; + }, + .ref => auxsrc: { + const ret: u32 = switch (source) { + // zero'd out because it is a src option + .src_xosc => 0, + .pll_sys => 0, + .src_gpin0 => 1, + .src_gpin1 => 2, + else => @panic("invalid source for generator"), + }; + break :auxsrc ret; + }, + .peri => auxsrc: { + const ret: u32 = switch (source) { + .clk_sys => 0, + .pll_sys => 1, + .pll_usb => 2, + .src_rosc => 3, + .src_xosc => 4, + .src_gpin0 => 5, + .src_gpin1 => 6, + else => @panic("invalid source for generator"), + }; + break :auxsrc ret; + }, + .usb, .adc, .rtc => auxsrc: { + const ret: u32 = switch (source) { + .pll_usb => 0, + .pll_sys => 1, + .src_rosc => 2, + .src_xosc => 3, + .src_gpin0 => 4, + .src_gpin1 => 5, + else => @panic("invalid source for generator"), + }; + break :auxsrc ret; + }, + .gpout0, .gpout1, .gpout2, .gpout3 => auxsrc: { + const ret: u32 = switch (source) { + .pll_sys => 0, + .src_gpin0 => 1, + .src_gpin1 => 2, + .pll_usb => 3, + .src_rosc => 4, + .src_xosc => 5, + .clk_sys => 6, + .clk_usb => 7, + .clk_adc => 8, + .clk_rtc => 9, + .clk_ref => 10, + }; + break :auxsrc ret; + }, + }; +} + pub const GlobalConfiguration = struct { xosc_configured: bool, sys: ?Configuration, @@ -221,8 +308,10 @@ pub const GlobalConfiguration = struct { output_freq = sys_opts.freq orelse rosc_freq; assert(output_freq.? <= rosc_freq); break :input .{ - .source = .rosc, + .source = .src_rosc, .freq = rosc_freq, + .src_value = srcValue(.sys, .src_rosc), + .auxsrc_value = auxSrcValue(.sys, .src_rosc), }; }, .src_xosc => input: { @@ -230,8 +319,10 @@ pub const GlobalConfiguration = struct { output_freq = sys_opts.freq orelse xosc_freq; assert(output_freq.? <= xosc_freq); break :input .{ - .source = .xosc, + .source = .src_xosc, .freq = xosc_freq, + .src_value = srcValue(.sys, .src_xosc), + .auxsrc_value = auxSrcValue(.sys, .src_xosc), }; }, .pll_sys => input: { @@ -252,6 +343,8 @@ pub const GlobalConfiguration = struct { // TODO: not really sure what frequency to // drive pll at yet, but this is an okay start .freq = 125_000_000, + .src_value = srcValue(.sys, .pll_sys), + .auxsrc_value = auxSrcValue(.sys, .pll_sys), }; }, @@ -281,6 +374,8 @@ pub const GlobalConfiguration = struct { .input = .{ .source = .pll_usb, .freq = 48_000_000, + .src_value = srcValue(.usb, .pll_usb), + .auxsrc_value = auxSrcValue(.usb, .pll_usb), }, .output_freq = 48_000_000, }; @@ -297,6 +392,8 @@ pub const GlobalConfiguration = struct { .input = .{ .source = .src_xosc, .freq = xosc_freq, + .src_value = srcValue(.ref, .src_xosc), + .auxsrc_value = auxSrcValue(.ref, .src_xosc), }, .output_freq = xosc_freq, }; @@ -306,10 +403,31 @@ pub const GlobalConfiguration = struct { // either use the ROSC, XOSC, or sys PLL, with whatever dividing // they need - .adc = if (opts.adc) |_| - unreachable // TODO - else - null, + // adc requires a 48MHz clock, so only ever let it get hooked up to + // the usb PLL + .adc = if (opts.adc) |adc_opts| adc_config: { + assert(adc_opts.source == .pll_usb); + xosc_configured = true; + + // TODO: some safety checks for overwriting this + pll_usb = .{ + .refdiv = 1, + .vco_freq = 1_440_000_000, + .postdiv1 = 6, + .postdiv2 = 5, + }; + + break :adc_config .{ + .generator = .usb, + .input = .{ + .source = .pll_usb, + .freq = 48_000_000, + .src_value = srcValue(.adc, .pll_usb), + .auxsrc_value = auxSrcValue(.adc, .pll_usb), + }, + .output_freq = 48_000_000, + }; + } else null, .rtc = if (opts.rtc) |_| unreachable // TODO @@ -320,12 +438,13 @@ pub const GlobalConfiguration = struct { if (peri_opts.source == .src_xosc) xosc_configured = true; - // TODO break :peri_config .{ .generator = .peri, .input = .{ .source = peri_opts.source, .freq = xosc_freq, + .src_value = srcValue(.peri, peri_opts.source), + .auxsrc_value = auxSrcValue(.peri, peri_opts.source), }, .output_freq = xosc_freq, }; @@ -339,7 +458,7 @@ pub const GlobalConfiguration = struct { /// this is explicitly comptime to encourage the user to have separate /// clock configuration declarations instead of mutating them at runtime - pub fn apply(comptime config: GlobalConfiguration) !void { + pub fn apply(comptime config: GlobalConfiguration) void { // disable resus if it has been turned on elsewhere regs.CLOCKS.CLK_SYS_RESUS_CTRL.raw = 0; @@ -357,7 +476,7 @@ pub const GlobalConfiguration = struct { if (config.sys) |sys| switch (sys.input.source) { .pll_usb, .pll_sys => { regs.CLOCKS.CLK_SYS_CTRL.modify(.{ .SRC = 0 }); - while (regs.CLOCKS.CLK_SYS_SELECTED.* != 1) {} + while (regs.CLOCKS.CLK_SYS_SELECTED.* == 0) {} }, else => {}, }; @@ -365,27 +484,21 @@ pub const GlobalConfiguration = struct { if (config.ref) |ref| switch (ref.input.source) { .pll_usb, .pll_sys => { regs.CLOCKS.CLK_REF_CTRL.modify(.{ .SRC = 0 }); - while (regs.CLOCKS.CLK_REF_SELECTED.* != 1) {} + while (regs.CLOCKS.CLK_REF_SELECTED.* == 0) {} }, else => {}, }; - // initialize PLLs - if (config.pll_sys) |pll_sys_config| pll.sys.apply(pll_sys_config); - if (config.pll_usb) |pll_usb_config| pll.usb.apply(pll_usb_config); - - // initialize clock generators - if (config.ref) |ref| try ref.apply(); - if (config.usb) |usb| try usb.apply(); - if (config.adc) |adc| try adc.apply(); - if (config.rtc) |rtc| try rtc.apply(); - if (config.peri) |peri| try peri.apply(); - } + //// initialize PLLs + if (config.pll_sys) |pll_sys_config| pll.PLL.apply(.sys, pll_sys_config); + if (config.pll_usb) |pll_usb_config| pll.PLL.apply(.usb, pll_usb_config); - /// returns frequency of a clock or pll, if unconfigured it returns null - pub fn getFrequency(config: GlobalConfiguration) ?u32 { - _ = config; - return null; + //// initialize clock generators + if (config.ref) |ref| ref.apply(config.sys); + if (config.usb) |usb| usb.apply(config.sys); + if (config.adc) |adc| adc.apply(config.sys); + if (config.rtc) |rtc| rtc.apply(config.sys); + if (config.peri) |peri| peri.apply(config.sys); } }; @@ -393,19 +506,21 @@ pub const Configuration = struct { generator: Generator, input: struct { source: Source, + src_value: u32, + auxsrc_value: u32, freq: u32, }, output_freq: u32, - pub fn apply(config: Configuration) !void { + pub fn apply(comptime config: Configuration, comptime sys_config_opt: ?Configuration) void { const generator = config.generator; const input = config.input; const output_freq = config.output_freq; + const sys_config = sys_config_opt.?; // sys clock config needs to be set! + // source frequency has to be faster because dividing will always reduce. assert(input.freq >= output_freq); - if (output_freq < input.freq) - return error.InvalidArgs; const div = @intCast(u32, (@intCast(u64, input.freq) << 8) / 8); @@ -413,26 +528,47 @@ pub const Configuration = struct { if (div > generator.getDiv()) generator.setDiv(div); - if (generator.hasGlitchlessMux() and input.source == .src_aux) { - // TODO: clear bits - while (!generator.selected()) { - // TODO: is leaving this empty good enough? pico sdk has `tight_loop_contents()` - } + // TODO what _is_ an aux source? + if (generator.hasGlitchlessMux() and input.src_value == 1) { + generator.clearSource(); + while (!generator.selected()) {} } else { - // uh stuff + generator.disable(); + var delay_cycles = sys_config.output_freq / config.output_freq + 1; + asm volatile ( + \\1: + \\subs %[cycles], #1 + \\bne 1b + : [cycles] "=r" (delay_cycles), + ); } + generator.setAuxSource(input.auxsrc_value); + // set aux mux first and then glitchless mex if this clock has one if (generator.hasGlitchlessMux()) { - // write to clock ctrl + generator.setSource(input.src_value); while (!generator.selected()) {} } generator.enable(); generator.setDiv(div); - // should we store global state on configured clocks? } }; -//pub fn countFrequencyKhz(source: Source) u32 {} +pub fn countFrequencyKhz(source: Source, comptime clock_config: GlobalConfiguration) u32 { + const ref_freq = clock_config.ref.?.output_freq; + + // wait for counter to be done + while (CLOCKS.FC0_STATUS.read().RUNNING == 1) {} + CLOCKS.FC0_REF_KHZ.* = ref_freq / 1000; + CLOCKS.FC0_INTERVAL.* = 10; + CLOCKS.FC0_MIN_KHZ.* = 0; + CLOCKS.FC0_MAX_KHZ.* = std.math.maxInt(u32); + CLOCKS.FC0_SRC.* = @enumToInt(source); + + while (CLOCKS.FC0_STATUS.read().DONE != 1) {} + + return CLOCKS.FC0_RESULT.read().KHZ; +} diff --git a/src/hal/pll.zig b/src/hal/pll.zig index 16fb308..eb16a63 100644 --- a/src/hal/pll.zig +++ b/src/hal/pll.zig @@ -12,44 +12,36 @@ pub const Configuration = struct { postdiv2: u3, }; -pub const sys = @intToPtr(*volatile PLL, regs.PLL_SYS.base_address); -pub const usb = @intToPtr(*volatile PLL, regs.PLL_USB.base_address); - -pub const PLL = packed struct { - cs: @TypeOf(regs.PLL_SYS.CS), - pwr: @TypeOf(regs.PLL_SYS.PWR), - fbdiv_int: @TypeOf(regs.PLL_SYS.FBDIV_INT), - prim: @TypeOf(regs.PLL_SYS.PRIM), - - comptime { - // bunch of comptime checks in here to validate the layout - assert(0 == @bitOffsetOf(PLL, "cs")); - assert(32 == @bitOffsetOf(PLL, "pwr")); - assert(64 == @bitOffsetOf(PLL, "fbdiv_int")); - assert(96 == @bitOffsetOf(PLL, "prim")); - } +pub const PLL = enum { + sys, + usb, - pub fn isLocked(pll: *const volatile PLL) bool { - return pll.cs.read().LOCK == 1; + fn getRegs(pll: PLL) *volatile PllRegs { + return &plls[@enumToInt(pll)]; } - pub fn reset(pll: *const volatile PLL) void { + pub fn reset(pll: PLL) void { switch (pll) { - sys => { + .sys => { regs.RESETS.RESET.modify(.{ .pll_sys = 1 }); regs.RESETS.RESET.modify(.{ .pll_sys = 0 }); - while (regs.RESETS.RESET_DONE.read().pll_sys == 1) {} + while (regs.RESETS.RESET_DONE.read().pll_sys != 1) {} }, - usb => { + .usb => { regs.RESETS.RESET.modify(.{ .pll_usb = 1 }); regs.RESETS.RESET.modify(.{ .pll_usb = 0 }); - while (regs.RESETS.RESET_DONE.read().pll_usb == 1) {} + while (regs.RESETS.RESET_DONE.read().pll_usb != 1) {} }, - else => unreachable, } } - pub fn apply(pll: *volatile PLL, comptime config: Configuration) void { + pub fn isLocked(pll: PLL) bool { + const pll_regs = pll.getRegs(); + return pll_regs.cs.read().LOCK == 1; + } + + pub fn apply(pll: PLL, comptime config: Configuration) void { + const pll_regs = pll.getRegs(); const ref_freq = xosc_freq / @as(u32, config.refdiv); const fbdiv = @intCast(u12, config.vco_freq / ref_freq); @@ -67,10 +59,10 @@ pub const PLL = packed struct { // do not bother a PLL which is already configured if (pll.isLocked() and - config.refdiv == pll.cs.read().REFDIV and - fbdiv == pll.fbdiv_int.read() and - config.postdiv1 == pll.prim.read().POSTDIV1 and - config.postdiv2 == pll.prim.read().POSTDIV2) + config.refdiv == pll_regs.cs.read().REFDIV and + fbdiv == pll_regs.fbdiv_int.read() and + config.postdiv1 == pll_regs.prim.read().POSTDIV1 and + config.postdiv2 == pll_regs.prim.read().POSTDIV2) { return; } @@ -78,20 +70,39 @@ pub const PLL = packed struct { pll.reset(); // load vco related dividers - pll.cs.modify(.{ .REFDIV = config.refdiv }); - pll.fbdiv_int.modify(fbdiv); + pll_regs.cs.modify(.{ .REFDIV = config.refdiv }); + pll_regs.fbdiv_int.modify(fbdiv); // turn on PLL - pll.pwr.modify(.{ .PD = 0, .VCOPD = 0 }); + pll_regs.pwr.modify(.{ .PD = 0, .VCOPD = 0 }); // wait for PLL to lock while (!pll.isLocked()) {} - pll.prim.modify(.{ + pll_regs.prim.modify(.{ .POSTDIV1 = config.postdiv1, .POSTDIV2 = config.postdiv2, }); - pll.pwr.modify(.{ .POSTDIVPD = 0 }); + pll_regs.pwr.modify(.{ .POSTDIVPD = 0 }); } }; + +const plls = @intToPtr(*volatile [2]PllRegs, regs.PLL_SYS.base_address); +comptime { + assert(@sizeOf(PllRegs) == (regs.PLL_USB.base_address - regs.PLL_SYS.base_address)); +} + +const CsReg = @typeInfo(@TypeOf(regs.PLL_SYS.CS)).Pointer.child; +const PwrReg = @typeInfo(@TypeOf(regs.PLL_SYS.PWR)).Pointer.child; +const FbdivIntReg = @typeInfo(@TypeOf(regs.PLL_SYS.FBDIV_INT)).Pointer.child; +const PrimReg = @typeInfo(@TypeOf(regs.PLL_SYS.PRIM)).Pointer.child; + +pub const PllRegs = extern struct { + cs: CsReg, + pwr: PwrReg, + fbdiv_int: FbdivIntReg, + prim: PrimReg, + + padding: [4092]u32, +}; diff --git a/src/hal/util.zig b/src/hal/util.zig new file mode 100644 index 0000000..9d7863c --- /dev/null +++ b/src/hal/util.zig @@ -0,0 +1,18 @@ +pub fn xorAlias(ptr: anytype) @TypeOf(ptr) { + const xor_addr = @ptrToInt(ptr) | (1 << 12); + return @ptrCast(@TypeOf(ptr), xor_addr); +} + +pub fn setAlias(ptr: anytype) @TypeOf(ptr) { + const set_addr = @ptrToInt(ptr) | (2 << 12); + return @ptrCast(@TypeOf(ptr), set_addr); +} + +pub fn clearAlias(ptr: anytype) @TypeOf(ptr) { + const clear_addr = @ptrToInt(ptr) | (3 << 12); + return @ptrCast(@TypeOf(ptr), clear_addr); +} + +pub inline fn tightLoopContents() void { + asm volatile ("" ::: "memory"); +} From 2d894103050d2f58fbd5dafcf1a741d2eed0ed72 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Sun, 10 Jul 2022 17:10:54 -0700 Subject: [PATCH 09/74] add directive to inline asm (#6) --- src/hal/clocks.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hal/clocks.zig b/src/hal/clocks.zig index fc28c19..fef6e61 100644 --- a/src/hal/clocks.zig +++ b/src/hal/clocks.zig @@ -536,6 +536,7 @@ pub const Configuration = struct { generator.disable(); var delay_cycles = sys_config.output_freq / config.output_freq + 1; asm volatile ( + \\.syntax unified \\1: \\subs %[cycles], #1 \\bne 1b From f75a019aa5e1bd915d1d9458df60f65908b156cb Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Sun, 10 Jul 2022 17:31:17 -0700 Subject: [PATCH 10/74] try lf endings to fix windows compile error (#7) --- .gitattributes | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..ef01f61 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.zig text eol=lf From f0e51f8302904877c9ebc2ef2b689e4db37491c8 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Thu, 14 Jul 2022 00:09:47 -0700 Subject: [PATCH 11/74] Uart (#8) * refined clock configuration, uart works with clk_peri at xosc frequency * fix pll_sys configuration --- src/hal.zig | 20 +-- src/hal/clocks.zig | 424 ++++++++++++++++++++++++++------------------- src/hal/gpio.zig | 4 + src/hal/pll.zig | 22 ++- src/hal/uart.zig | 212 +++++++++++++++++++++++ src/rp2040.zig | 5 - 6 files changed, 482 insertions(+), 205 deletions(-) create mode 100644 src/hal/uart.zig diff --git a/src/hal.zig b/src/hal.zig index 3db0677..92539f3 100644 --- a/src/hal.zig +++ b/src/hal.zig @@ -1,25 +1,25 @@ const microzig = @import("microzig"); -const regs = microzig.chip.regsisters; +const regs = microzig.chip.registers; + pub const gpio = @import("hal/gpio.zig"); pub const clocks = @import("hal/clocks.zig"); pub const multicore = @import("hal/multicore.zig"); pub const time = @import("hal/time.zig"); +pub const uart = @import("hal/uart.zig"); pub const clock_config = clocks.GlobalConfiguration.init(.{ - .sys = .{ .source = .src_xosc }, + .sys = .{ + .source = .pll_sys, + .freq = 125_000_000, + }, + .ref = .{ .source = .src_xosc }, .peri = .{ .source = .clk_sys }, - //.sys = .{ - // .source = .pll_sys, - // .freq = 125_000_000, - //}, - //.usb = .{ .source = .pll_usb }, - //.adc = .{ .source = .pll_usb }, - //.rtc = .{ .source = .pll_usb }, - //.peri = .{ .source = .clk_sys }, }); pub fn init() void { + // TODO: resets need to be reviewed here clock_config.apply(); + gpio.reset(); } pub fn getCpuId() u32 { diff --git a/src/hal/clocks.zig b/src/hal/clocks.zig index fef6e61..e81f1ea 100644 --- a/src/hal/clocks.zig +++ b/src/hal/clocks.zig @@ -83,6 +83,10 @@ pub const Generator = enum { regs.CLOCKS.base_address, ); + fn getRegs(generator: Generator) *volatile GeneratorRegs { + return &generators[@enumToInt(generator)]; + } + pub fn hasGlitchlessMux(generator: Generator) bool { return switch (generator) { .sys, .ref => true, @@ -93,7 +97,7 @@ pub const Generator = enum { pub fn enable(generator: Generator) void { switch (generator) { .ref, .sys => {}, - else => generators[@enumToInt(generator)].ctrl |= (1 << 11), + else => generator.getRegs().ctrl |= (1 << 11), } } @@ -101,14 +105,14 @@ pub const Generator = enum { if (generator == .peri) return; - generators[@enumToInt(generator)].div = div; + generator.getRegs().div = div; } pub fn getDiv(generator: Generator) u32 { if (generator == .peri) return 1; - return generators[@enumToInt(generator)].div; + return generator.getRegs().div; } // The bitfields for the *_SELECTED registers are actually a mask of which @@ -118,17 +122,17 @@ pub const Generator = enum { // // Some mention that this is only for the glitchless mux, so if it is non-glitchless then return true pub fn selected(generator: Generator) bool { - return (0 != generators[@enumToInt(generator)].selected); + return (0 != generator.getRegs().selected); } pub fn clearSource(generator: Generator) void { - generators[@enumToInt(generator)].ctrl &= ~@as(u32, 0x3); + generator.getRegs().ctrl &= ~@as(u32, 0x3); } pub fn disable(generator: Generator) void { switch (generator) { .sys, .ref => {}, - else => generators[@enumToInt(generator)].ctrl &= ~@as(u32, 1 << 11), + else => generator.getRegs().ctrl &= ~@as(u32, 1 << 11), } } @@ -147,15 +151,17 @@ pub const Generator = enum { } pub fn setSource(generator: Generator, src: u32) void { + const gen_regs = generator.getRegs(); const mask = ~@as(u32, 0x3); - const ctrl_value = generators[@enumToInt(generator)].ctrl; - generators[@enumToInt(generator)].ctrl = (ctrl_value & mask) | src; + const ctrl_value = gen_regs.ctrl; + gen_regs.ctrl = (ctrl_value & mask) | src; } pub fn setAuxSource(generator: Generator, auxsrc: u32) void { + const gen_regs = generator.getRegs(); const mask = ~@as(u32, 0x1e0); - const ctrl_value = generators[@enumToInt(generator)].ctrl; - generators[@enumToInt(generator)].ctrl = (ctrl_value & mask) | (auxsrc << 5); + const ctrl_value = gen_regs.ctrl; + gen_regs.ctrl = (ctrl_value & mask) | (auxsrc << 5); } }; @@ -264,16 +270,20 @@ fn auxSrcValue(generator: Generator, source: Source) u32 { } pub const GlobalConfiguration = struct { - xosc_configured: bool, - sys: ?Configuration, - ref: ?Configuration, - usb: ?Configuration, - adc: ?Configuration, - rtc: ?Configuration, - peri: ?Configuration, - - pll_sys: ?pll.Configuration, - pll_usb: ?pll.Configuration, + xosc_configured: bool = false, + sys: ?Configuration = null, + ref: ?Configuration = null, + usb: ?Configuration = null, + adc: ?Configuration = null, + rtc: ?Configuration = null, + peri: ?Configuration = null, + gpout0: ?Configuration = null, + gpout1: ?Configuration = null, + gpout2: ?Configuration = null, + gpout3: ?Configuration = null, + + pll_sys: ?pll.Configuration = null, + pll_usb: ?pll.Configuration = null, pub const Option = struct { source: Source, @@ -287,173 +297,220 @@ pub const GlobalConfiguration = struct { adc: ?Option = null, rtc: ?Option = null, peri: ?Option = null, + gpout0: ?Option = null, + gpout1: ?Option = null, + gpout2: ?Option = null, + gpout3: ?Option = null, // TODO: allow user to configure PLLs to optimize for low-jitter, low-power, or manually specify }; + pub fn getFrequency(config: GlobalConfiguration, source: Source) ?u32 { + return switch (source) { + .src_xosc => xosc_freq, + .src_rosc => rosc_freq, + .clk_sys => if (config.sys) |sys_config| sys_config.output_freq else null, + .clk_usb => if (config.usb) |usb_config| usb_config.output_freq else null, + .clk_ref => if (config.ref) |ref_config| ref_config.output_freq else null, + .pll_sys => if (config.pll_sys) |pll_sys_config| pll_sys_config.frequency() else null, + .pll_usb => if (config.pll_usb) |pll_usb_config| pll_usb_config.frequency() else null, + else => null, + }; + } + /// this function reasons about how to configure the clock system. It will /// assert if the configuration is invalid pub fn init(comptime opts: Options) GlobalConfiguration { - var xosc_configured = false; - var pll_sys: ?pll.Configuration = null; - var pll_usb: ?pll.Configuration = null; - - return GlobalConfiguration{ - // the system clock can either use rosc, xosc, or the sys PLL - .sys = if (opts.sys) |sys_opts| sys_config: { - var output_freq: ?u32 = null; - break :sys_config .{ - .generator = .sys, - .input = switch (sys_opts.source) { - .src_rosc => input: { - output_freq = sys_opts.freq orelse rosc_freq; - assert(output_freq.? <= rosc_freq); - break :input .{ - .source = .src_rosc, - .freq = rosc_freq, - .src_value = srcValue(.sys, .src_rosc), - .auxsrc_value = auxSrcValue(.sys, .src_rosc), - }; - }, - .src_xosc => input: { - xosc_configured = true; - output_freq = sys_opts.freq orelse xosc_freq; - assert(output_freq.? <= xosc_freq); - break :input .{ - .source = .src_xosc, - .freq = xosc_freq, - .src_value = srcValue(.sys, .src_xosc), - .auxsrc_value = auxSrcValue(.sys, .src_xosc), - }; - }, - .pll_sys => input: { - xosc_configured = true; - output_freq = sys_opts.freq orelse 125_000_000; - assert(output_freq.? <= 125_000_000); - - // TODO: proper values for 125MHz - pll_sys = .{ - .refdiv = 2, - .vco_freq = 1_440_000_000, - .postdiv1 = 6, - .postdiv2 = 5, - }; - - break :input .{ - .source = .pll_sys, - // TODO: not really sure what frequency to - // drive pll at yet, but this is an okay start - .freq = 125_000_000, - .src_value = srcValue(.sys, .pll_sys), - .auxsrc_value = auxSrcValue(.sys, .pll_sys), - }; - }, - - else => unreachable, // not an available input + var config = GlobalConfiguration{}; + + // I THINK that if either pll is configured here, then that means + // that the ref clock generator MUST use xosc to feed the PLLs? + config.ref = if (opts.ref) |ref_opts| ref_config: { + assert(ref_opts.source == .src_xosc); + break :ref_config .{ + .generator = .ref, + .input = .{ + .source = ref_opts.source, + .freq = config.getFrequency(ref_opts.source).?, + .src_value = srcValue(.ref, ref_opts.source), + .auxsrc_value = auxSrcValue(.ref, ref_opts.source), + }, + .output_freq = config.getFrequency(ref_opts.source).?, + }; + } else if (config.pll_sys != null or config.pll_usb != null) ref_config: { + config.xosc_configured = true; + break :ref_config .{ + .generator = .ref, + .input = .{ + .source = .src_xosc, + .freq = xosc_freq, + .src_value = srcValue(.ref, .src_xosc), + .auxsrc_value = auxSrcValue(.ref, .src_xosc), + }, + .output_freq = xosc_freq, + }; + } else null; + + // the system clock can either use rosc, xosc, or the sys PLL + config.sys = if (opts.sys) |sys_opts| sys_config: { + var output_freq: ?u32 = null; + break :sys_config .{ + .generator = .sys, + .input = switch (sys_opts.source) { + .src_rosc => input: { + output_freq = sys_opts.freq orelse rosc_freq; + assert(output_freq.? <= rosc_freq); + break :input .{ + .source = .src_rosc, + .freq = rosc_freq, + .src_value = srcValue(.sys, .src_rosc), + .auxsrc_value = auxSrcValue(.sys, .src_rosc), + }; }, - .output_freq = output_freq.?, - }; - } else null, - - // to keep things simple for now, we'll make it so that the usb - // generator can only be hooked up to the usb PLL, and only have - // one configuration for the usb PLL - .usb = if (opts.usb) |usb_opts| usb_config: { - assert(pll_usb == null); - assert(usb_opts.source == .pll_usb); - - xosc_configured = true; - pll_usb = .{ - .refdiv = 1, - .vco_freq = 1_440_000_000, - .postdiv1 = 6, - .postdiv2 = 5, - }; - - break :usb_config .{ - .generator = .usb, - .input = .{ - .source = .pll_usb, - .freq = 48_000_000, - .src_value = srcValue(.usb, .pll_usb), - .auxsrc_value = auxSrcValue(.usb, .pll_usb), + .src_xosc => input: { + config.xosc_configured = true; + output_freq = sys_opts.freq orelse xosc_freq; + assert(output_freq.? <= xosc_freq); + break :input .{ + .source = .src_xosc, + .freq = xosc_freq, + .src_value = srcValue(.sys, .src_xosc), + .auxsrc_value = auxSrcValue(.sys, .src_xosc), + }; }, - .output_freq = 48_000_000, - }; - } else null, - - // I THINK that if either pll is configured here, then that means - // that the ref clock generator MUST use xosc to feed the PLLs? - .ref = if (opts.ref) |_| - unreachable // don't explicitly configure for now - else if (pll_sys != null or pll_usb != null) ref_config: { - xosc_configured = true; - break :ref_config .{ - .generator = .ref, - .input = .{ - .source = .src_xosc, - .freq = xosc_freq, - .src_value = srcValue(.ref, .src_xosc), - .auxsrc_value = auxSrcValue(.ref, .src_xosc), + .pll_sys => input: { + config.xosc_configured = true; + output_freq = sys_opts.freq orelse 125_000_000; + assert(output_freq.? == 125_000_000); // if using pll use 125MHz for now + + // TODO: proper values for 125MHz + config.pll_sys = .{ + .refdiv = 1, + .fbdiv = 125, + .postdiv1 = 6, + .postdiv2 = 2, + }; + + break :input .{ + .source = .pll_sys, + // TODO: not really sure what frequency to + // drive pll at yet, but this is an okay start + .freq = 125_000_000, + .src_value = srcValue(.sys, .pll_sys), + .auxsrc_value = auxSrcValue(.sys, .pll_sys), + }; }, - .output_freq = xosc_freq, - }; - } else null, - - // for the rest of the generators we'll make it so that they can - // either use the ROSC, XOSC, or sys PLL, with whatever dividing - // they need - // adc requires a 48MHz clock, so only ever let it get hooked up to - // the usb PLL - .adc = if (opts.adc) |adc_opts| adc_config: { - assert(adc_opts.source == .pll_usb); - xosc_configured = true; + else => unreachable, // not an available input + }, + .output_freq = output_freq.?, + }; + } else null; + + // to keep things simple for now, we'll make it so that the usb + // generator can only be hooked up to the usb PLL, and only have + // one configuration for the usb PLL + config.usb = if (opts.usb) |usb_opts| usb_config: { + assert(config.pll_usb == null); + assert(usb_opts.source == .pll_usb); + + config.xosc_configured = true; + config.pll_usb = .{ + .refdiv = 1, + .fbdiv = 40, + .postdiv1 = 5, + .postdiv2 = 2, + }; - // TODO: some safety checks for overwriting this - pll_usb = .{ + break :usb_config .{ + .generator = .usb, + .input = .{ + .source = .pll_usb, + .freq = 48_000_000, + .src_value = srcValue(.usb, .pll_usb), + .auxsrc_value = auxSrcValue(.usb, .pll_usb), + }, + .output_freq = 48_000_000, + }; + } else null; + + // for the rest of the generators we'll make it so that they can + // either use the ROSC, XOSC, or sys PLL, with whatever dividing + // they need + + // adc requires a 48MHz clock, so only ever let it get hooked up to + // the usb PLL + config.adc = if (opts.adc) |adc_opts| adc_config: { + assert(adc_opts.source == .pll_usb); + config.xosc_configured = true; + + // TODO: some safety checks for overwriting this + if (config.pll_usb) |pll_usb| { + assert(pll_usb.refdiv == 1); + assert(pll_usb.fbdiv == 40); + assert(pll_usb.postdiv1 == 5); + assert(pll_usb.postdiv2 == 2); + } else { + config.pll_usb = .{ .refdiv = 1, - .vco_freq = 1_440_000_000, - .postdiv1 = 6, - .postdiv2 = 5, - }; - - break :adc_config .{ - .generator = .usb, - .input = .{ - .source = .pll_usb, - .freq = 48_000_000, - .src_value = srcValue(.adc, .pll_usb), - .auxsrc_value = auxSrcValue(.adc, .pll_usb), - }, - .output_freq = 48_000_000, + .fbdiv = 40, + .postdiv1 = 5, + .postdiv2 = 2, }; - } else null, - - .rtc = if (opts.rtc) |_| - unreachable // TODO + } + + break :adc_config .{ + .generator = .usb, + .input = .{ + .source = .pll_usb, + .freq = 48_000_000, + .src_value = srcValue(.adc, .pll_usb), + .auxsrc_value = auxSrcValue(.adc, .pll_usb), + }, + .output_freq = 48_000_000, + }; + } else null; + + config.rtc = if (opts.rtc) |_| + unreachable // TODO + else + null; + + config.peri = if (opts.peri) |peri_opts| peri_config: { + if (peri_opts.source == .src_xosc) + config.xosc_configured = true; + + break :peri_config .{ + .generator = .peri, + .input = .{ + .source = peri_opts.source, + .freq = config.getFrequency(peri_opts.source) orelse + @compileError("you need to configure the source: " ++ @tagName(peri_opts.source)), + .src_value = srcValue(.peri, peri_opts.source), + .auxsrc_value = auxSrcValue(.peri, peri_opts.source), + }, + .output_freq = if (peri_opts.freq) |output_freq| + output_freq + else + config.getFrequency(peri_opts.source).?, + }; + } else null; + + config.gpout0 = if (opts.gpout0) |gpout0_opts| .{ + .generator = .gpout0, + .input = .{ + .source = gpout0_opts.source, + .freq = config.getFrequency(gpout0_opts.source) orelse + @compileError("you need to configure the source: " ++ @tagName(gpout0_opts.source)), + .src_value = srcValue(.gpout0, gpout0_opts.source), + .auxsrc_value = auxSrcValue(.gpout0, gpout0_opts.source), + }, + .output_freq = if (gpout0_opts.freq) |output_freq| + output_freq else - null, - - .peri = if (opts.peri) |peri_opts| peri_config: { - if (peri_opts.source == .src_xosc) - xosc_configured = true; - - break :peri_config .{ - .generator = .peri, - .input = .{ - .source = peri_opts.source, - .freq = xosc_freq, - .src_value = srcValue(.peri, peri_opts.source), - .auxsrc_value = auxSrcValue(.peri, peri_opts.source), - }, - .output_freq = xosc_freq, - }; - } else null, + config.getFrequency(gpout0_opts.source).?, + } else null; - .xosc_configured = xosc_configured, - .pll_sys = pll_sys, - .pll_usb = pll_usb, - }; + return config; } /// this is explicitly comptime to encourage the user to have separate @@ -476,7 +533,7 @@ pub const GlobalConfiguration = struct { if (config.sys) |sys| switch (sys.input.source) { .pll_usb, .pll_sys => { regs.CLOCKS.CLK_SYS_CTRL.modify(.{ .SRC = 0 }); - while (regs.CLOCKS.CLK_SYS_SELECTED.* == 0) {} + while (!Generator.sys.selected()) {} }, else => {}, }; @@ -484,7 +541,7 @@ pub const GlobalConfiguration = struct { if (config.ref) |ref| switch (ref.input.source) { .pll_usb, .pll_sys => { regs.CLOCKS.CLK_REF_CTRL.modify(.{ .SRC = 0 }); - while (regs.CLOCKS.CLK_REF_SELECTED.* == 0) {} + while (!Generator.ref.selected()) {} }, else => {}, }; @@ -495,10 +552,15 @@ pub const GlobalConfiguration = struct { //// initialize clock generators if (config.ref) |ref| ref.apply(config.sys); + if (config.sys) |sys| sys.apply(config.sys); if (config.usb) |usb| usb.apply(config.sys); if (config.adc) |adc| adc.apply(config.sys); if (config.rtc) |rtc| rtc.apply(config.sys); if (config.peri) |peri| peri.apply(config.sys); + if (config.gpout0) |gpout0| gpout0.apply(config.sys); + if (config.gpout1) |gpout1| gpout1.apply(config.sys); + if (config.gpout2) |gpout2| gpout2.apply(config.sys); + if (config.gpout3) |gpout3| gpout3.apply(config.sys); } }; @@ -522,13 +584,12 @@ pub const Configuration = struct { // source frequency has to be faster because dividing will always reduce. assert(input.freq >= output_freq); - const div = @intCast(u32, (@intCast(u64, input.freq) << 8) / 8); + const div = @intCast(u32, (@intCast(u64, input.freq) << 8) / output_freq); // check divisor if (div > generator.getDiv()) generator.setDiv(div); - // TODO what _is_ an aux source? if (generator.hasGlitchlessMux() and input.src_value == 1) { generator.clearSource(); while (!generator.selected()) {} @@ -557,17 +618,18 @@ pub const Configuration = struct { } }; +// NOTE: untested pub fn countFrequencyKhz(source: Source, comptime clock_config: GlobalConfiguration) u32 { const ref_freq = clock_config.ref.?.output_freq; // wait for counter to be done while (CLOCKS.FC0_STATUS.read().RUNNING == 1) {} - CLOCKS.FC0_REF_KHZ.* = ref_freq / 1000; - CLOCKS.FC0_INTERVAL.* = 10; - CLOCKS.FC0_MIN_KHZ.* = 0; - CLOCKS.FC0_MAX_KHZ.* = std.math.maxInt(u32); - CLOCKS.FC0_SRC.* = @enumToInt(source); + CLOCKS.FC0_REF_KHZ.raw = ref_freq / 1000; + CLOCKS.FC0_INTERVAL.raw = 10; + CLOCKS.FC0_MIN_KHZ.raw = 0; + CLOCKS.FC0_MAX_KHZ.raw = std.math.maxInt(u32); + CLOCKS.FC0_SRC.raw = @enumToInt(source); while (CLOCKS.FC0_STATUS.read().DONE != 1) {} diff --git a/src/hal/gpio.zig b/src/hal/gpio.zig index 416b155..1aa0e6b 100644 --- a/src/hal/gpio.zig +++ b/src/hal/gpio.zig @@ -131,6 +131,10 @@ pub inline fn put(comptime gpio: u32, value: u1) void { } } +pub inline fn toggle(comptime gpio: u32) void { + regs.SIO.GPIO_OUT_XOR.raw = (1 << gpio); +} + pub inline fn setFunction(comptime gpio: u32, function: Function) void { const pad_bank_reg = comptime std.fmt.comptimePrint("GPIO{}", .{gpio}); @field(regs.PADS_BANK0, pad_bank_reg).modify(.{ diff --git a/src/hal/pll.zig b/src/hal/pll.zig index eb16a63..4481abd 100644 --- a/src/hal/pll.zig +++ b/src/hal/pll.zig @@ -7,9 +7,13 @@ const xosc_freq = microzig.board.xosc_freq; pub const Configuration = struct { refdiv: u6, - vco_freq: u32, + fbdiv: u32, postdiv1: u3, postdiv2: u3, + + pub fn frequency(config: Configuration) u32 { + return @as(u32, xosc_freq) / config.refdiv * config.fbdiv / config.postdiv1 / config.postdiv2; + } }; pub const PLL = enum { @@ -41,15 +45,15 @@ pub const PLL = enum { } pub fn apply(pll: PLL, comptime config: Configuration) void { - const pll_regs = pll.getRegs(); - const ref_freq = xosc_freq / @as(u32, config.refdiv); - const fbdiv = @intCast(u12, config.vco_freq / ref_freq); - - assert(fbdiv >= 16 and fbdiv <= 320); + assert(config.fbdiv >= 16 and config.fbdiv <= 320); assert(config.postdiv1 >= 1 and config.postdiv1 <= 7); assert(config.postdiv2 >= 1 and config.postdiv2 <= 7); assert(config.postdiv2 <= config.postdiv1); - assert(ref_freq <= config.vco_freq / 16); + + const pll_regs = pll.getRegs(); + const ref_freq = xosc_freq / @as(u32, config.refdiv); + const vco_freq = ref_freq * config.fbdiv; + assert(ref_freq <= vco_freq / 16); // 1. program reference clock divider // 2. program feedback divider @@ -60,7 +64,7 @@ pub const PLL = enum { // do not bother a PLL which is already configured if (pll.isLocked() and config.refdiv == pll_regs.cs.read().REFDIV and - fbdiv == pll_regs.fbdiv_int.read() and + config.fbdiv == pll_regs.fbdiv_int.read() and config.postdiv1 == pll_regs.prim.read().POSTDIV1 and config.postdiv2 == pll_regs.prim.read().POSTDIV2) { @@ -71,7 +75,7 @@ pub const PLL = enum { // load vco related dividers pll_regs.cs.modify(.{ .REFDIV = config.refdiv }); - pll_regs.fbdiv_int.modify(fbdiv); + pll_regs.fbdiv_int.modify(config.fbdiv); // turn on PLL pll_regs.pwr.modify(.{ .PD = 0, .VCOPD = 0 }); diff --git a/src/hal/uart.zig b/src/hal/uart.zig new file mode 100644 index 0000000..1816399 --- /dev/null +++ b/src/hal/uart.zig @@ -0,0 +1,212 @@ +const std = @import("std"); +const microzig = @import("microzig"); +const gpio = @import("gpio.zig"); +const clocks = @import("clocks.zig"); + +const assert = std.debug.assert; +const regs = microzig.chip.registers; + +pub const WordBits = enum { + five, + six, + seven, + eight, +}; + +pub const StopBits = enum { + one, + two, +}; + +pub const Parity = enum { + none, + even, + odd, +}; + +pub const Config = struct { + clock_config: clocks.GlobalConfiguration, + tx_pin: u32, + rx_pin: u32, + baud_rate: u32, + word_bits: WordBits = .eight, + stop_bits: StopBits = .one, + parity: Parity = .none, +}; + +pub const UartRegs = extern struct { + dr: u32, + rsr: u32, + reserved0: [4]u32, + fr: @typeInfo(@TypeOf(regs.UART0.UARTFR)).Pointer.child, + resertev1: [1]u32, + ilpr: u32, + ibrd: u32, + fbrd: u32, + lcr_h: @typeInfo(@TypeOf(regs.UART0.UARTLCR_H)).Pointer.child, + cr: @typeInfo(@TypeOf(regs.UART0.UARTCR)).Pointer.child, + ifls: u32, + imsc: u32, + ris: u32, + mis: u32, + icr: u32, + dmacr: @typeInfo(@TypeOf(regs.UART0.UARTDMACR)).Pointer.child, + periphid0: u32, + periphid1: u32, + periphid2: u32, + periphid3: u32, + cellid0: u32, + cellid1: u32, + cellid2: u32, + cellid3: u32, + + padding: [4069]u32, +}; + +const uarts = @intToPtr(*volatile [2]UartRegs, regs.UART0.base_address); +comptime { + assert(@sizeOf(UartRegs) == (regs.UART1.base_address - regs.UART0.base_address)); +} + +pub const UART = enum { + uart0, + uart1, + + const WriteError = error{}; + pub const Writer = std.io.Writer(UART, WriteError, write); + + pub fn writer(uart: UART) Writer { + return .{ .context = uart }; + } + + fn getRegs(uart: UART) *volatile UartRegs { + return &uarts[@enumToInt(uart)]; + } + + pub fn init(comptime id: u32, comptime config: Config) UART { + const uart: UART = switch (id) { + 0 => .uart0, + 1 => .uart1, + else => @compileError("there is only uart0 and uart1"), + }; + + assert(config.baud_rate > 0); + + uart.reset(); + + const uart_regs = uart.getRegs(); + const peri_freq = config.clock_config.peri.?.output_freq; + uart.setBaudRate(config.baud_rate, peri_freq); + uart.setFormat(config.word_bits, config.stop_bits, config.parity); + + uart_regs.cr.modify(.{ + .UARTEN = 1, + .TXE = 1, + .RXE = 1, + }); + + uart_regs.lcr_h.modify(.{ .FEN = 1 }); + + // - always enable DREQ signals -- no harm if dma isn't listening + uart_regs.dmacr.modify(.{ + .TXDMAE = 1, + .RXDMAE = 1, + }); + + // TODO comptime assertions + gpio.setFunction(config.tx_pin, .uart); + gpio.setFunction(config.rx_pin, .uart); + + return uart; + } + + pub fn isReadable(uart: UART) bool { + return (0 == uart.getRegs().fr.read().RXFE); + } + + pub fn isWritable(uart: UART) bool { + return (0 == uart.getRegs().fr.read().TXFF); + } + + // TODO: implement tx fifo + pub fn write(uart: UART, payload: []const u8) WriteError!usize { + const uart_regs = uart.getRegs(); + for (payload) |byte| { + while (!uart.isWritable()) {} + + uart_regs.dr = byte; + } + + return payload.len; + } + + pub fn readWord(uart: UART) u8 { + const uart_regs = uart.getRegs(); + while (!uart.isReadable()) {} + + return @truncate(u8, uart_regs.dr); + } + + pub fn reset(uart: UART) void { + switch (uart) { + .uart0 => { + regs.RESETS.RESET.modify(.{ .uart0 = 1 }); + regs.RESETS.RESET.modify(.{ .uart0 = 0 }); + while (regs.RESETS.RESET_DONE.read().uart0 != 1) {} + }, + .uart1 => { + regs.RESETS.RESET.modify(.{ .uart1 = 1 }); + regs.RESETS.RESET.modify(.{ .uart1 = 0 }); + while (regs.RESETS.RESET_DONE.read().uart1 != 1) {} + }, + } + } + + pub fn setFormat( + uart: UART, + word_bits: WordBits, + stop_bits: StopBits, + parity: Parity, + ) void { + const uart_regs = uart.getRegs(); + uart_regs.lcr_h.modify(.{ + .WLEN = switch (word_bits) { + .eight => @as(u2, 0b11), + .seven => @as(u2, 0b10), + .six => @as(u2, 0b01), + .five => @as(u2, 0b00), + }, + .STP2 = switch (stop_bits) { + .one => @as(u1, 0), + .two => @as(u1, 1), + }, + .PEN = if (parity != .none) @as(u1, 1) else @as(u1, 0), + .EPS = switch (parity) { + .even => @as(u1, 1), + .odd => @as(u1, 0), + else => @as(u1, 0), + }, + }); + } + + fn setBaudRate(uart: UART, baud_rate: u32, peri_freq: u32) void { + assert(baud_rate > 0); + const uart_regs = uart.getRegs(); + const baud_rate_div = (8 * peri_freq / baud_rate); + var baud_ibrd = baud_rate_div >> 7; + + const baud_fbrd = if (baud_ibrd == 0) baud_fbrd: { + baud_ibrd = 1; + break :baud_fbrd 0; + } else if (baud_ibrd >= 65535) baud_fbrd: { + baud_ibrd = 65535; + break :baud_fbrd 0; + } else ((baud_rate_div & 0x7f) + 1) / 2; + + uart_regs.ibrd = baud_ibrd; + uart_regs.fbrd = baud_fbrd; + + // just want a write, don't want to change these values + uart_regs.lcr_h.modify(.{}); + } +}; diff --git a/src/rp2040.zig b/src/rp2040.zig index e96b901..571b648 100644 --- a/src/rp2040.zig +++ b/src/rp2040.zig @@ -44,14 +44,12 @@ pub const VectorTable = extern struct { }; pub const registers = struct { - /// System Control Space pub const SCS = struct { pub const base_address = 0xe000e000; /// System Tick Timer pub const SysTick = struct { - /// address: 0xe000e010 /// SysTick Control and Status Register pub const CTRL = @intToPtr(*volatile Mmio(32, packed struct { @@ -134,7 +132,6 @@ pub const registers = struct { /// Nested Vectored Interrupt Controller pub const NVIC = struct { - /// address: 0xe000e100 /// Interrupt Set Enable Register pub const ISER = @intToPtr(*volatile u32, base_address + 0x100); @@ -158,7 +155,6 @@ pub const registers = struct { /// System Control Block pub const SCB = struct { - /// address: 0xe000ed00 pub const CPUID = @intToPtr(*volatile Mmio(32, packed struct { REVISION: u4, @@ -343,7 +339,6 @@ pub const registers = struct { /// Memory Protection Unit pub const MPU = struct { - /// address: 0xe000ed90 /// MPU Type Register pub const TYPE = @intToPtr(*volatile Mmio(32, packed struct { From 9fa748ff13982950a58fb4ce45815ac5556f1fcc Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Fri, 2 Sep 2022 14:45:21 -0700 Subject: [PATCH 12/74] Pin config (#9) * pin config * wip * wip * try some experimental pwm stuff --- build.zig | 27 +-- src/hal.zig | 9 +- src/hal/clocks.zig | 48 ++++- src/hal/gpio.zig | 45 +---- src/hal/pins.zig | 438 +++++++++++++++++++++++++++++++++++++++++++++ src/hal/pll.zig | 3 + src/hal/pwm.zig | 116 ++++++++++++ src/hal/resets.zig | 47 +++++ 8 files changed, 668 insertions(+), 65 deletions(-) create mode 100644 src/hal/pins.zig create mode 100644 src/hal/pwm.zig create mode 100644 src/hal/resets.zig diff --git a/build.zig b/build.zig index 7bf7bea..f4675dd 100644 --- a/build.zig +++ b/build.zig @@ -2,21 +2,25 @@ const std = @import("std"); const Builder = std.build.Builder; const Pkg = std.build.Pkg; +const comptimePrint = std.fmt.comptimePrint; -pub const BuildOptions = struct { - packages: ?[]const Pkg = null, -}; +const chip_path = comptimePrint("{s}/src/rp2040.zig", .{root()}); +const board_path = comptimePrint("{s}/src/raspberry_pi_pico.zig", .{root()}); +const hal_path = comptimePrint("{s}/src/hal.zig", .{root()}); +const linkerscript_path = comptimePrint("{s}/rp2040.ld", .{root()}); + +pub const BuildOptions = struct {}; pub fn addPiPicoExecutable( comptime microzig: type, builder: *Builder, name: []const u8, source: []const u8, - options: BuildOptions, -) *std.build.LibExeObjStep { + _: BuildOptions, +) microzig.EmbeddedExecutable { const rp2040 = microzig.Chip{ .name = "RP2040", - .path = root() ++ "src/rp2040.zig", + .path = chip_path, .cpu = microzig.cpus.cortex_m0plus, .memory_regions = &.{ .{ .kind = .flash, .offset = 0x10000100, .length = (2048 * 1024) - 256 }, @@ -27,7 +31,7 @@ pub fn addPiPicoExecutable( const raspberry_pi_pico = microzig.Board{ .name = "Raspberry Pi Pico", - .path = root() ++ "src/raspberry_pi_pico.zig", + .path = board_path, .chip = rp2040, }; @@ -37,15 +41,14 @@ pub fn addPiPicoExecutable( source, .{ .board = raspberry_pi_pico }, .{ - .packages = options.packages, - .hal_package_path = .{ .path = root() ++ "src/hal.zig" }, + .hal_package_path = .{ .path = hal_path }, }, - ) catch @panic("failed to create embedded executable"); - ret.setLinkerScriptPath(.{ .path = root() ++ "rp2040.ld" }); + ); + ret.inner.setLinkerScriptPath(.{ .path = linkerscript_path }); return ret; } fn root() []const u8 { - return (std.fs.path.dirname(@src().file) orelse unreachable) ++ "/"; + return std.fs.path.dirname(@src().file) orelse "."; } diff --git a/src/hal.zig b/src/hal.zig index 92539f3..1dc50e6 100644 --- a/src/hal.zig +++ b/src/hal.zig @@ -1,25 +1,28 @@ const microzig = @import("microzig"); const regs = microzig.chip.registers; +pub const pins = @import("hal/pins.zig"); pub const gpio = @import("hal/gpio.zig"); pub const clocks = @import("hal/clocks.zig"); pub const multicore = @import("hal/multicore.zig"); pub const time = @import("hal/time.zig"); pub const uart = @import("hal/uart.zig"); +pub const pwm = @import("hal/pwm.zig"); pub const clock_config = clocks.GlobalConfiguration.init(.{ + .ref = .{ .source = .src_xosc }, .sys = .{ .source = .pll_sys, .freq = 125_000_000, }, - .ref = .{ .source = .src_xosc }, .peri = .{ .source = .clk_sys }, + .usb = .{ .source = .pll_usb }, + .adc = .{ .source = .pll_usb }, + .rtc = .{ .source = .pll_usb }, }); pub fn init() void { - // TODO: resets need to be reviewed here clock_config.apply(); - gpio.reset(); } pub fn getCpuId() u32 { diff --git a/src/hal/clocks.zig b/src/hal/clocks.zig index e81f1ea..3553572 100644 --- a/src/hal/clocks.zig +++ b/src/hal/clocks.zig @@ -4,6 +4,9 @@ const pll = @import("pll.zig"); const util = @import("util.zig"); const assert = std.debug.assert; +// TODO: remove +const gpio = @import("gpio.zig"); + const regs = microzig.chip.registers; const CLOCKS = regs.CLOCKS; const xosc_freq = microzig.board.xosc_freq; @@ -470,10 +473,36 @@ pub const GlobalConfiguration = struct { }; } else null; - config.rtc = if (opts.rtc) |_| - unreachable // TODO - else - null; + config.rtc = if (opts.rtc) |rtc_opts| rtc_config: { + assert(rtc_opts.source == .pll_usb); + config.xosc_configured = true; + + // TODO: some safety checks for overwriting this + if (config.pll_usb) |pll_usb| { + assert(pll_usb.refdiv == 1); + assert(pll_usb.fbdiv == 40); + assert(pll_usb.postdiv1 == 5); + assert(pll_usb.postdiv2 == 2); + } else { + config.pll_usb = .{ + .refdiv = 1, + .fbdiv = 40, + .postdiv1 = 5, + .postdiv2 = 2, + }; + } + + break :rtc_config .{ + .generator = .usb, + .input = .{ + .source = .pll_usb, + .freq = 48_000_000, + .src_value = srcValue(.rtc, .pll_usb), + .auxsrc_value = auxSrcValue(.rtc, .pll_usb), + }, + .output_freq = 48_000_000, + }; + } else null; config.peri = if (opts.peri) |peri_opts| peri_config: { if (peri_opts.source == .src_xosc) @@ -557,6 +586,7 @@ pub const GlobalConfiguration = struct { if (config.adc) |adc| adc.apply(config.sys); if (config.rtc) |rtc| rtc.apply(config.sys); if (config.peri) |peri| peri.apply(config.sys); + if (config.gpout0) |gpout0| gpout0.apply(config.sys); if (config.gpout1) |gpout1| gpout1.apply(config.sys); if (config.gpout2) |gpout2| gpout2.apply(config.sys); @@ -592,16 +622,20 @@ pub const Configuration = struct { if (generator.hasGlitchlessMux() and input.src_value == 1) { generator.clearSource(); + while (!generator.selected()) {} } else { generator.disable(); - var delay_cycles = sys_config.output_freq / config.output_freq + 1; + const delay_cycles: u32 = sys_config.output_freq / config.output_freq + 1; asm volatile ( \\.syntax unified + \\movs r1, %[cycles] \\1: - \\subs %[cycles], #1 + \\subs r1, #1 \\bne 1b - : [cycles] "=r" (delay_cycles), + : + : [cycles] "i" (delay_cycles), + : "{r1}" ); } diff --git a/src/hal/gpio.zig b/src/hal/gpio.zig index 1aa0e6b..ec48f11 100644 --- a/src/hal/gpio.zig +++ b/src/hal/gpio.zig @@ -1,40 +1,6 @@ -//! ### Function Select Table -//! -//! GPIO | F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 -//! -------|----------|-----------|----------|--------|-----|------|------|---------------|---- -//! 0 | SPI0 RX | UART0 TX | I2C0 SDA | PWM0 A | SIO | PIO0 | PIO1 | | USB OVCUR DET -//! 1 | SPI0 CSn | UART0 RX | I2C0 SCL | PWM0 B | SIO | PIO0 | PIO1 | | USB VBUS DET -//! 2 | SPI0 SCK | UART0 CTS | I2C1 SDA | PWM1 A | SIO | PIO0 | PIO1 | | USB VBUS EN -//! 3 | SPI0 TX | UART0 RTS | I2C1 SCL | PWM1 B | SIO | PIO0 | PIO1 | | USB OVCUR DET -//! 4 | SPI0 RX | UART1 TX | I2C0 SDA | PWM2 A | SIO | PIO0 | PIO1 | | USB VBUS DET -//! 5 | SPI0 CSn | UART1 RX | I2C0 SCL | PWM2 B | SIO | PIO0 | PIO1 | | USB VBUS EN -//! 6 | SPI0 SCK | UART1 CTS | I2C1 SDA | PWM3 A | SIO | PIO0 | PIO1 | | USB OVCUR DET -//! 7 | SPI0 TX | UART1 RTS | I2C1 SCL | PWM3 B | SIO | PIO0 | PIO1 | | USB VBUS DET -//! 8 | SPI1 RX | UART1 TX | I2C0 SDA | PWM4 A | SIO | PIO0 | PIO1 | | USB VBUS EN -//! 9 | SPI1 CSn | UART1 RX | I2C0 SCL | PWM4 B | SIO | PIO0 | PIO1 | | USB OVCUR DET -//! 10 | SPI1 SCK | UART1 CTS | I2C1 SDA | PWM5 A | SIO | PIO0 | PIO1 | | USB VBUS DET -//! 11 | SPI1 TX | UART1 RTS | I2C1 SCL | PWM5 B | SIO | PIO0 | PIO1 | | USB VBUS EN -//! 12 | SPI1 RX | UART0 TX | I2C0 SDA | PWM6 A | SIO | PIO0 | PIO1 | | USB OVCUR DET -//! 13 | SPI1 CSn | UART0 RX | I2C0 SCL | PWM6 B | SIO | PIO0 | PIO1 | | USB VBUS DET -//! 14 | SPI1 SCK | UART0 CTS | I2C1 SDA | PWM7 A | SIO | PIO0 | PIO1 | | USB VBUS EN -//! 15 | SPI1 TX | UART0 RTS | I2C1 SCL | PWM7 B | SIO | PIO0 | PIO1 | | USB OVCUR DET -//! 16 | SPI0 RX | UART0 TX | I2C0 SDA | PWM0 A | SIO | PIO0 | PIO1 | | USB VBUS DET -//! 17 | SPI0 CSn | UART0 RX | I2C0 SCL | PWM0 B | SIO | PIO0 | PIO1 | | USB VBUS EN -//! 18 | SPI0 SCK | UART0 CTS | I2C1 SDA | PWM1 A | SIO | PIO0 | PIO1 | | USB OVCUR DET -//! 19 | SPI0 TX | UART0 RTS | I2C1 SCL | PWM1 B | SIO | PIO0 | PIO1 | | USB VBUS DET -//! 20 | SPI0 RX | UART1 TX | I2C0 SDA | PWM2 A | SIO | PIO0 | PIO1 | CLOCK GPIN0 | USB VBUS EN -//! 21 | SPI0 CSn | UART1 RX | I2C0 SCL | PWM2 B | SIO | PIO0 | PIO1 | CLOCK GPOUT0 | USB OVCUR DET -//! 22 | SPI0 SCK | UART1 CTS | I2C1 SDA | PWM3 A | SIO | PIO0 | PIO1 | CLOCK GPIN1 | USB VBUS DET -//! 23 | SPI0 TX | UART1 RTS | I2C1 SCL | PWM3 B | SIO | PIO0 | PIO1 | CLOCK GPOUT1 | USB VBUS EN -//! 24 | SPI1 RX | UART1 TX | I2C0 SDA | PWM4 A | SIO | PIO0 | PIO1 | CLOCK GPOUT2 | USB OVCUR DET -//! 25 | SPI1 CSn | UART1 RX | I2C0 SCL | PWM4 B | SIO | PIO0 | PIO1 | CLOCK GPOUT3 | USB VBUS DET -//! 26 | SPI1 SCK | UART1 CTS | I2C1 SDA | PWM5 A | SIO | PIO0 | PIO1 | | USB VBUS EN -//! 27 | SPI1 TX | UART1 RTS | I2C1 SCL | PWM5 B | SIO | PIO0 | PIO1 | | USB OVCUR DET -//! 28 | SPI1 RX | UART0 TX | I2C0 SDA | PWM6 A | SIO | PIO0 | PIO1 | | USB VBUS DET -//! 29 | SPI1 CSn | UART0 RX | I2C0 SCL | PWM6 B | SIO | PIO0 | PIO1 | | USB VBUS EN - const std = @import("std"); const microzig = @import("microzig"); +const resets = @import("resets.zig"); const regs = microzig.chip.registers; const assert = std.debug.assert; @@ -91,14 +57,7 @@ pub const Enabled = enum { }; pub inline fn reset() void { - regs.RESETS.RESET.modify(.{ .io_bank0 = 1, .pads_bank0 = 1 }); - regs.RESETS.RESET.modify(.{ .io_bank0 = 0, .pads_bank0 = 0 }); - - while (true) { - const reset_done = regs.RESETS.RESET_DONE.read(); - if (reset_done.io_bank0 == 1 and reset_done.pads_bank0 == 1) - break; - } + resets.reset(&.{ .io_bank0, .pads_bank0 }); } /// Initialize a GPIO, set func to SIO diff --git a/src/hal/pins.zig b/src/hal/pins.zig new file mode 100644 index 0000000..ed07594 --- /dev/null +++ b/src/hal/pins.zig @@ -0,0 +1,438 @@ +const std = @import("std"); +const gpio = @import("gpio.zig"); +const pwm = @import("pwm.zig"); +const regs = @import("microzig").chip.registers; + +const assert = std.debug.assert; +const comptimePrint = std.fmt.comptimePrint; +const StructField = std.builtin.TypeInfo.StructField; + +pub const Pin = enum { + GPIO0, + GPIO1, + GPIO2, + GPIO3, + GPIO4, + GPIO5, + GPIO6, + GPIO7, + GPIO8, + GPIO9, + GPIO10, + GPIO11, + GPIO12, + GPIO13, + GPIO14, + GPIO15, + GPIO16, + GPIO17, + GPIO18, + GPIO19, + GPIO20, + GPIO21, + GPIO22, + GPIO23, + GPIO24, + GPIO25, + GPIO26, + GPIO27, + GPIO28, + GPIO29, + + pub const Configuration = struct { + name: ?[]const u8 = null, + function: Function = .SIO, + direction: ?gpio.Direction = null, + drive_strength: ?gpio.DriveStrength = null, + pull: ?enum { up, down } = null, + slew_rate: ?gpio.SlewRate = null, + // input/output enable + // schmitt trigger + // hysteresis + + pub fn getDirection(config: Configuration) gpio.Direction { + return if (config.direction) |direction| + direction + else if (config.function.isPwm()) + .out + else + @panic("TODO"); + } + }; +}; + +pub const Function = enum { + SIO, + + PIO0, + PIO1, + + SPI0_RX, + SPI0_CSn, + SPI0_SCK, + SPI0_TX, + + SPI1_RX, + SPI1_CSn, + SPI1_SCK, + SPI1_TX, + + UART0_TX, + UART0_RX, + UART0_CTS, + UART0_RTS, + + UART1_TX, + UART1_RX, + UART1_CTS, + UART1_RTS, + + I2C0_SDA, + I2C0_SCL, + + I2C1_SDA, + I2C1_SCL, + + PWM0_A, + PWM0_B, + + PWM1_A, + PWM1_B, + + PWM2_A, + PWM2_B, + + PWM3_A, + PWM3_B, + + PWM4_A, + PWM4_B, + + PWM5_A, + PWM5_B, + + PWM6_A, + PWM6_B, + + PWM7_A, + PWM7_B, + + CLOCK_GPIN0, + CLOCK_GPIN1, + + CLOCK_GPOUT0, + CLOCK_GPOUT1, + CLOCK_GPOUT2, + CLOCK_GPOUT3, + + USB_OVCUR_DET, + USB_VBUS_DET, + USB_VBUS_EN, + + ADC0, + ADC1, + ADC2, + ADC3, + + pub fn isPwm(function: Function) bool { + return switch (function) { + .PWM0_A, + .PWM0_B, + .PWM1_A, + .PWM1_B, + .PWM2_A, + .PWM2_B, + .PWM3_A, + .PWM3_B, + .PWM4_A, + .PWM4_B, + .PWM5_A, + .PWM5_B, + .PWM6_A, + .PWM6_B, + .PWM7_A, + .PWM7_B, + => true, + else => false, + }; + } + + pub fn pwmSlice(comptime function: Function) u32 { + return switch (function) { + .PWM0_A, .PWM0_B => 0, + .PWM1_A, .PWM1_B => 1, + .PWM2_A, .PWM2_B => 2, + .PWM3_A, .PWM3_B => 3, + .PWM4_A, .PWM4_B => 4, + .PWM5_A, .PWM5_B => 5, + .PWM6_A, .PWM6_B => 6, + .PWM7_A, .PWM7_B => 7, + else => @compileError("not pwm"), + }; + } + + pub fn pwmChannel(comptime function: Function) pwm.Channel { + return switch (function) { + .PWM0_A, + .PWM1_A, + .PWM2_A, + .PWM3_A, + .PWM4_A, + .PWM5_A, + .PWM6_A, + .PWM7_A, + => .a, + .PWM0_B, + .PWM1_B, + .PWM2_B, + .PWM3_B, + .PWM4_B, + .PWM5_B, + .PWM6_B, + .PWM7_B, + => .b, + else => @compileError("not pwm"), + }; + } +}; + +fn all() [30]u1 { + var ret: [30]u1 = undefined; + for (ret) |*elem| + elem.* = 1; + + return ret; +} + +fn list(gpio_list: []const u5) [30]u1 { + var ret = std.mem.zeroes([30]u1); + for (gpio_list) |num| + ret[num] = 1; + + return ret; +} + +fn single(gpio_num: u5) [30]u1 { + var ret = std.mem.zeroes([30]u1); + ret[gpio_num] = 1; + return ret; +} + +const function_table = [@typeInfo(Function).Enum.fields.len][30]u1{ + all(), // SIO + all(), // PIO0 + all(), // PIO1 + list(&.{ 0, 4, 16, 20 }), // SPI0_RX + list(&.{ 1, 5, 17, 21 }), // SPI0_CSn + list(&.{ 2, 6, 18, 22 }), // SPI0_SCK + list(&.{ 3, 7, 19, 23 }), // SPI0_TX + list(&.{ 8, 12, 24, 28 }), // SPI1_RX + list(&.{ 9, 13, 25, 29 }), // SPI1_CSn + list(&.{ 10, 14, 26 }), // SPI1_SCK + list(&.{ 11, 15, 27 }), // SPI1_TX + list(&.{ 0, 11, 16, 28 }), // UART0_TX + list(&.{ 1, 13, 17, 29 }), // UART0_RX + list(&.{ 2, 14, 18 }), // UART0_CTS + list(&.{ 3, 15, 19 }), // UART0_RTS + list(&.{ 4, 8, 20, 24 }), // UART1_TX + list(&.{ 5, 9, 21, 25 }), // UART1_RX + list(&.{ 6, 10, 22, 26 }), // UART1_CTS + list(&.{ 7, 11, 23, 27 }), // UART1_RTS + list(&.{ 0, 4, 8, 12, 16, 20, 24, 28 }), // I2C0_SDA + list(&.{ 1, 5, 9, 13, 17, 21, 25, 29 }), // I2C0_SCL + list(&.{ 2, 6, 10, 14, 18, 22, 26 }), // I2C1_SDA + list(&.{ 3, 7, 11, 15, 19, 23, 27 }), // I2C1_SCL + list(&.{ 0, 16 }), // PWM0_A + list(&.{ 1, 17 }), // PWM0_B + list(&.{ 2, 18 }), // PWM1_A + list(&.{ 3, 19 }), // PWM1_B + list(&.{ 4, 20 }), // PWM2_A + list(&.{ 5, 21 }), // PWM2_B + list(&.{ 6, 22 }), // PWM3_A + list(&.{ 7, 23 }), // PWM3_B + list(&.{ 8, 24 }), // PWM4_A + list(&.{ 9, 25 }), // PWM4_B + list(&.{ 10, 26 }), // PWM5_A + list(&.{ 11, 27 }), // PWM5_B + list(&.{ 12, 28 }), // PWM6_A + list(&.{ 13, 29 }), // PWM6_B + single(14), // PWM7_A + single(15), // PWM7_B + single(20), // CLOCK_GPIN0 + single(22), // CLOCK_GPIN1 + single(21), // CLOCK_GPOUT0 + single(23), // CLOCK_GPOUT1 + single(24), // CLOCK_GPOUT2 + single(25), // CLOCK_GPOUT3 + list(&.{ 0, 3, 6, 9, 12, 15, 18, 21, 24, 27 }), // USB_OVCUR_DET + list(&.{ 1, 4, 7, 10, 13, 16, 19, 22, 25, 28 }), // USB_VBUS_DET + list(&.{ 2, 5, 8, 11, 14, 17, 20, 23, 26, 29 }), // USB_VBUS_EN + single(26), // ADC0 + single(27), // ADC1 + single(28), // ADC2 + single(29), // ADC3 +}; + +pub fn GPIO(comptime num: u5, comptime direction: gpio.Direction) type { + return switch (direction) { + .in => struct { + const gpio_num = num; + + pub inline fn read(self: @This()) u1 { + _ = self; + @compileError("TODO"); + } + }, + .out => struct { + const gpio_num = num; + + pub inline fn put(self: @This(), value: u1) void { + _ = self; + gpio.put(gpio_num, value); + } + + pub inline fn toggle(self: @This()) void { + _ = self; + gpio.toggle(gpio_num); + } + }, + }; +} + +pub fn Pins(comptime config: GlobalConfiguration) type { + const count = count: { + var ret: usize = 0; + inline for (@typeInfo(GlobalConfiguration).Struct.fields) |field| { + if (@field(config, field.name)) |pin_config| + if (pin_config.function == .SIO or pin_config.function.isPwm()) { + ret += 1; + }; + } + + break :count ret; + }; + + var i: usize = 0; + var fields: [count]StructField = undefined; + inline for (@typeInfo(GlobalConfiguration).Struct.fields) |field| { + if (@field(config, field.name)) |pin_config| + if (pin_config.function == .SIO) { + fields[i] = StructField{ + .name = pin_config.name orelse field.name, + .field_type = GPIO(@enumToInt(@field(Pin, field.name)), pin_config.direction orelse .in), + .is_comptime = false, + .default_value = null, + .alignment = 1, + }; + + i += 1; + } else if (pin_config.function.isPwm()) { + fields[i] = StructField{ + .name = pin_config.name orelse @tagName(pin_config.function), + .field_type = pwm.PWM(pin_config.function.pwmSlice(), pin_config.function.pwmChannel()), + .is_comptime = false, + .default_value = null, + .alignment = 1, + }; + + i += 1; + }; + } + + return @Type(.{ + .Struct = .{ + .layout = .Auto, + .is_tuple = false, + .fields = &fields, + .decls = &.{}, + }, + }); +} + +pub const GlobalConfiguration = struct { + GPIO0: ?Pin.Configuration = null, + GPIO1: ?Pin.Configuration = null, + GPIO2: ?Pin.Configuration = null, + GPIO3: ?Pin.Configuration = null, + GPIO4: ?Pin.Configuration = null, + GPIO5: ?Pin.Configuration = null, + GPIO6: ?Pin.Configuration = null, + GPIO7: ?Pin.Configuration = null, + GPIO8: ?Pin.Configuration = null, + GPIO9: ?Pin.Configuration = null, + GPIO10: ?Pin.Configuration = null, + GPIO11: ?Pin.Configuration = null, + GPIO12: ?Pin.Configuration = null, + GPIO13: ?Pin.Configuration = null, + GPIO14: ?Pin.Configuration = null, + GPIO15: ?Pin.Configuration = null, + GPIO16: ?Pin.Configuration = null, + GPIO17: ?Pin.Configuration = null, + GPIO18: ?Pin.Configuration = null, + GPIO19: ?Pin.Configuration = null, + GPIO20: ?Pin.Configuration = null, + GPIO21: ?Pin.Configuration = null, + GPIO22: ?Pin.Configuration = null, + GPIO23: ?Pin.Configuration = null, + GPIO24: ?Pin.Configuration = null, + GPIO25: ?Pin.Configuration = null, + GPIO26: ?Pin.Configuration = null, + GPIO27: ?Pin.Configuration = null, + GPIO28: ?Pin.Configuration = null, + GPIO29: ?Pin.Configuration = null, + + comptime { + const pin_field_count = @typeInfo(Pin).Enum.fields.len; + const config_field_count = @typeInfo(GlobalConfiguration).Struct.fields.len; + if (pin_field_count != config_field_count) + @compileError(comptimePrint("{} {}", .{ pin_field_count, config_field_count })); + } + + pub fn apply(comptime config: GlobalConfiguration) Pins(config) { + comptime var input_gpios: u32 = 0; + comptime var output_gpios: u32 = 0; + + // validate selected function + comptime { + inline for (@typeInfo(GlobalConfiguration).Struct.fields) |field| + if (@field(config, field.name)) |pin_config| { + const gpio_num = @enumToInt(@field(Pin, field.name)); + if (0 == function_table[@enumToInt(pin_config.function)][gpio_num]) + @compileError(comptimePrint("{s} cannot be configured for {}", .{ field.name, pin_config.function })); + + switch (pin_config.getDirection()) { + .in => input_gpios |= 1 << gpio_num, + .out => output_gpios |= 1 << gpio_num, + } + }; + } + // TODO: ensure only one instance of an input function exists + + const used_gpios = comptime input_gpios | output_gpios; + gpio.reset(); + + if (used_gpios != 0) { + regs.SIO.GPIO_OE_CLR.raw = used_gpios; + regs.SIO.GPIO_OUT_CLR.raw = used_gpios; + + comptime var i: u32 = 0; + inline while (i < 32) : (i += 1) + if (0 != used_gpios & 1 << i) + gpio.setFunction(i, .sio); + } + + if (output_gpios != 0) + regs.SIO.GPIO_OE_SET.raw = output_gpios; + + // TODO: pwm initialization + + // fields in the Pins(config) type should be zero sized, so we just + // default build them all (wasn't sure how to do that cleanly in + // `Pins()` + var ret: Pins(config) = undefined; + inline for (@typeInfo(Pins(config)).Struct.fields) |field| + @field(ret, field.name) = .{}; + + return ret; + } +}; diff --git a/src/hal/pll.zig b/src/hal/pll.zig index 4481abd..117a42c 100644 --- a/src/hal/pll.zig +++ b/src/hal/pll.zig @@ -2,6 +2,9 @@ const std = @import("std"); const microzig = @import("microzig"); const assert = std.debug.assert; +// TODO: remove +const gpio = @import("gpio.zig"); + const regs = microzig.chip.registers; const xosc_freq = microzig.board.xosc_freq; diff --git a/src/hal/pwm.zig b/src/hal/pwm.zig new file mode 100644 index 0000000..457fd2c --- /dev/null +++ b/src/hal/pwm.zig @@ -0,0 +1,116 @@ +const microzig = @import("microzig"); +const regs = microzig.chip.registers; + +pub const Config = struct {}; + +fn getRegs(comptime slice: u32) *volatile Regs { + @import("std").debug.assert(slice < 8); + return @intToPtr(*volatile Regs, regs.PWM.base_address); // + (slice * 0x14)); +} + +pub fn PWM(comptime slice_num: u32, comptime chan: Channel) type { + return struct { + pub const slice_number = slice_num; + pub const channel = chan; + + pub inline fn setLevel(_: @This(), level: u16) void { + setChannelLevel(slice_number, channel, level); + } + + pub fn slice(_: @This()) Slice(slice_number) { + return .{}; + } + }; +} + +pub fn Slice(comptime slice_num: u32) type { + return struct { + const slice_number = slice_num; + + pub inline fn setWrap(_: @This(), wrap: u16) void { + setSliceWrap(slice_number, wrap); + } + + pub inline fn enable(_: @This()) void { + getRegs(slice_number).csr.modify(.{ .EN = 1 }); + } + + pub inline fn disable(_: @This()) void { + getRegs(slice_number).csr.modify(.{ .EN = 0 }); + } + + pub inline fn setPhaseCorrect(_: @This(), phase_correct: bool) void { + setSlicePhaseCorrect(slice_number, phase_correct); + } + + pub inline fn setClkDiv(_: @This(), integer: u8, fraction: u4) void { + setSliceClkDiv(slice_number, integer, fraction); + } + }; +} + +pub const ClkDivMode = enum(u2) { + free_running, + b_high, + b_rising, + b_falling, +}; + +pub const Channel = enum(u1) { a, b }; + +const Regs = extern struct { + csr: @typeInfo(@TypeOf(regs.PWM.CH0_CSR)).Pointer.child, + div: @typeInfo(@TypeOf(regs.PWM.CH0_DIV)).Pointer.child, + ctr: @typeInfo(@TypeOf(regs.PWM.CH0_CTR)).Pointer.child, + cc: @typeInfo(@TypeOf(regs.PWM.CH0_CC)).Pointer.child, + top: @typeInfo(@TypeOf(regs.PWM.CH0_TOP)).Pointer.child, +}; + +pub inline fn setSlicePhaseCorrect(comptime slice: u32, phase_correct: bool) void { + getRegs(slice).csr.modify(.{ + .PH_CORRECT = if (phase_correct) 1 else 0, + }); +} + +pub inline fn setSliceClkDiv(comptime slice: u32, integer: u8, fraction: u4) void { + getRegs(slice).div.modify(.{ + .INT = integer, + .FRAC = fraction, + }); +} + +pub inline fn setSliceClkDivMode(comptime slice: u32, mode: ClkDivMode) void { + getRegs(slice).csr.modify(.{ + .DIVMODE = @enumToInt(mode), + }); +} + +pub inline fn setChannelInversion( + comptime slice: u32, + comptime channel: Channel, + invert: bool, +) void { + switch (channel) { + .a => getRegs(slice).csr.modify(.{ + .A_INV = if (invert) 1 else 0, + }), + .b => getRegs(slice).csr.modifi(.{ + .B_INV = if (invert) 1 else 0, + }), + } +} + +pub inline fn setSliceWrap(comptime slice: u32, wrap: u16) void { + getRegs(slice).top.raw = wrap; +} + +pub inline fn setChannelLevel( + comptime slice: u32, + comptime channel: Channel, + level: u16, +) void { + switch (channel) { + .a => getRegs(slice).cc.modify(.{ .A = level }), + .b => getRegs(slice).cc.modify(.{ .B = level }), + } +} diff --git a/src/hal/resets.zig b/src/hal/resets.zig new file mode 100644 index 0000000..0e0ea2b --- /dev/null +++ b/src/hal/resets.zig @@ -0,0 +1,47 @@ +const std = @import("std"); +const microzig = @import("microzig"); + +const regs = microzig.chip.registers; +const EnumField = std.builtin.TypeInfo.EnumField; +const Mask = @typeInfo(@TypeOf(regs.RESETS.RESET)).Pointer.child.underlying_type; + +pub const Module = enum { + adc, + busctrl, + dma, + i2c0, + i2c1, + io_bank0, + io_qspi, + jtag, + pads_bank0, + pads_qspi, + pio0, + pio1, + pll_sys, + pll_usb, + pwm, + rtc, + spi0, + spi1, + syscfg, + sysinfo, + tbman, + timer, + uart0, + uart1, + usbctrl, +}; + +pub inline fn reset(comptime modules: []const Module) void { + comptime var mask = std.mem.zeroes(Mask); + + inline for (modules) |module| + @field(mask, @tagName(module)) = 1; + + const raw_mask = @bitCast(u32, mask); + regs.RESETS.RESET.raw = raw_mask; + regs.RESETS.RESET.raw = 0; + + while (regs.RESETS.RESET_DONE.raw & raw_mask != raw_mask) {} +} From d4a74cb4f3287fa05156d3aaea049264f4597692 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Sat, 17 Sep 2022 16:54:45 -0700 Subject: [PATCH 13/74] move examples in here (#12) --- .gitmodules | 3 + build.zig | 42 +- deps/microzig | 1 + examples/blinky.zig | 20 + examples/blinky_core1.zig | 29 + examples/gpio_clk.zig | 21 + examples/pwm.zig | 23 + examples/uart.zig | 48 ++ src/hal.zig | 2 + src/hal/gpio.zig | 3 + src/hal/irq.zig | 20 + src/hal/multicore.zig | 2 +- src/hal/pwm.zig | 8 + src/hal/uart.zig | 51 +- src/rp2040.zig | 1381 ++++++++++--------------------------- 15 files changed, 635 insertions(+), 1019 deletions(-) create mode 100644 .gitmodules create mode 160000 deps/microzig create mode 100644 examples/blinky.zig create mode 100644 examples/blinky_core1.zig create mode 100644 examples/gpio_clk.zig create mode 100644 examples/pwm.zig create mode 100644 examples/uart.zig create mode 100644 src/hal/irq.zig diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..32e895c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "deps/microzig"] + path = deps/microzig + url = https://github.com/ZigEmbeddedGroup/microzig.git diff --git a/build.zig b/build.zig index f4675dd..01a26ae 100644 --- a/build.zig +++ b/build.zig @@ -1,9 +1,10 @@ const std = @import("std"); - const Builder = std.build.Builder; const Pkg = std.build.Pkg; const comptimePrint = std.fmt.comptimePrint; +const microzig = @import("deps/microzig/src/main.zig"); + const chip_path = comptimePrint("{s}/src/rp2040.zig", .{root()}); const board_path = comptimePrint("{s}/src/raspberry_pi_pico.zig", .{root()}); const hal_path = comptimePrint("{s}/src/hal.zig", .{root()}); @@ -12,7 +13,6 @@ const linkerscript_path = comptimePrint("{s}/rp2040.ld", .{root()}); pub const BuildOptions = struct {}; pub fn addPiPicoExecutable( - comptime microzig: type, builder: *Builder, name: []const u8, source: []const u8, @@ -49,6 +49,44 @@ pub fn addPiPicoExecutable( return ret; } +// this build script is mostly for testing and verification of this +// package. In an attempt to modularize -- designing for a case where a +// project requires multiple HALs, it accepts microzig as a param +pub fn build(b: *Builder) !void { + const mode = b.standardReleaseOptions(); + var examples = Examples.init(b, mode); + examples.install(); +} + fn root() []const u8 { return std.fs.path.dirname(@src().file) orelse "."; } + +pub const Examples = struct { + blinky: microzig.EmbeddedExecutable, + blinky_core1: microzig.EmbeddedExecutable, + gpio_clk: microzig.EmbeddedExecutable, + pwm: microzig.EmbeddedExecutable, + uart: microzig.EmbeddedExecutable, + //uart_pins: microzig.EmbeddedExecutable, + + pub fn init(b: *Builder, mode: std.builtin.Mode) Examples { + var ret: Examples = undefined; + inline for (@typeInfo(Examples).Struct.fields) |field| { + @field(ret, field.name) = addPiPicoExecutable( + b, + field.name, + comptime root() ++ "/examples/" ++ field.name ++ ".zig", + .{}, + ); + @field(ret, field.name).setBuildMode(mode); + } + + return ret; + } + + pub fn install(examples: *Examples) void { + inline for (@typeInfo(Examples).Struct.fields) |field| + @field(examples, field.name).install(); + } +}; diff --git a/deps/microzig b/deps/microzig new file mode 160000 index 0000000..4159581 --- /dev/null +++ b/deps/microzig @@ -0,0 +1 @@ +Subproject commit 4159581b4848bfb8bbdf91dabdebd15ecd503427 diff --git a/examples/blinky.zig b/examples/blinky.zig new file mode 100644 index 0000000..ea3f2d8 --- /dev/null +++ b/examples/blinky.zig @@ -0,0 +1,20 @@ +const std = @import("std"); +const microzig = @import("microzig"); +const rp2040 = microzig.hal; +const time = rp2040.time; + +const pin_config = rp2040.pins.GlobalConfiguration{ + .GPIO25 = .{ + .name = "led", + .direction = .out, + }, +}; + +pub fn main() !void { + const pins = pin_config.apply(); + + while (true) { + pins.led.toggle(); + time.sleepMs(250); + } +} diff --git a/examples/blinky_core1.zig b/examples/blinky_core1.zig new file mode 100644 index 0000000..a549f30 --- /dev/null +++ b/examples/blinky_core1.zig @@ -0,0 +1,29 @@ +const std = @import("std"); + +const microzig = @import("microzig"); +const rp2040 = microzig.hal; +const gpio = rp2040.gpio; +const time = rp2040.time; +const multicore = rp2040.multicore; + +const led = 25; + +fn core1() void { + while (true) { + gpio.put(led, 1); + time.sleepMs(250); + gpio.put(led, 0); + time.sleepMs(250); + } +} + +pub fn main() !void { + gpio.init(led); + gpio.setDir(led, .out); + + multicore.launchCore1(core1); + + while (true) { + microzig.cpu.wfi(); + } +} diff --git a/examples/gpio_clk.zig b/examples/gpio_clk.zig new file mode 100644 index 0000000..52280e4 --- /dev/null +++ b/examples/gpio_clk.zig @@ -0,0 +1,21 @@ +const std = @import("std"); +const microzig = @import("microzig"); +const rp2040 = microzig.hal; +const gpio = rp2040.gpio; +const clocks = rp2040.clocks; + +const gpout0_pin = 21; +const clock_config = clocks.GlobalConfiguration.init(.{ + .sys = .{ .source = .src_xosc }, + .gpout0 = .{ .source = .clk_sys }, +}); + +pub fn init() void { + clock_config.apply(); + gpio.reset(); +} + +pub fn main() !void { + gpio.setFunction(gpout0_pin, .gpck); + while (true) {} +} diff --git a/examples/pwm.zig b/examples/pwm.zig new file mode 100644 index 0000000..9eff043 --- /dev/null +++ b/examples/pwm.zig @@ -0,0 +1,23 @@ +const std = @import("std"); +const microzig = @import("microzig"); +const rp2040 = microzig.hal; +const gpio = rp2040.gpio; +const clocks = rp2040.clocks; +const time = rp2040.time; +const regs = microzig.chip.registers; +const multicore = rp2040.multicore; + +const pin_config = rp2040.pins.GlobalConfiguration{ + .GPIO25 = .{ .name = "led", .function = .PWM4_B }, +}; + +pub fn main() !void { + const pins = pin_config.apply(); + pins.led.slice().setWrap(100); + pins.led.setLevel(10); + pins.led.slice().enable(); + + while (true) { + time.sleepMs(250); + } +} diff --git a/examples/uart.zig b/examples/uart.zig new file mode 100644 index 0000000..ed29280 --- /dev/null +++ b/examples/uart.zig @@ -0,0 +1,48 @@ +const std = @import("std"); +const microzig = @import("microzig"); + +const rp2040 = microzig.hal; +const time = rp2040.time; +const gpio = rp2040.gpio; +const clocks = rp2040.clocks; + +const led = 25; +const uart_id = 0; +const baud_rate = 115200; +const uart_tx_pin = 0; +const uart_rx_pin = 1; + +pub fn panic(message: []const u8, _: ?*std.builtin.StackTrace) noreturn { + std.log.err("panic: {s}", .{message}); + @breakpoint(); + while (true) {} +} + +pub const log_level = .debug; +pub const log = rp2040.uart.log; + +pub fn main() !void { + gpio.reset(); + gpio.init(led); + gpio.setDir(led, .out); + gpio.put(led, 1); + + const uart = rp2040.uart.UART.init(uart_id, .{ + .baud_rate = baud_rate, + .tx_pin = uart_tx_pin, + .rx_pin = uart_rx_pin, + .clock_config = rp2040.clock_config, + }); + + rp2040.uart.initLogger(uart); + + var i: u32 = 0; + while (true) : (i += 1) { + gpio.put(led, 1); + std.log.info("what {}", .{i}); + time.sleepMs(500); + + gpio.put(led, 0); + time.sleepMs(500); + } +} diff --git a/src/hal.zig b/src/hal.zig index 1dc50e6..61132bd 100644 --- a/src/hal.zig +++ b/src/hal.zig @@ -8,6 +8,8 @@ pub const multicore = @import("hal/multicore.zig"); pub const time = @import("hal/time.zig"); pub const uart = @import("hal/uart.zig"); pub const pwm = @import("hal/pwm.zig"); +pub const resets = @import("hal/resets.zig"); +pub const irq = @import("hal/irq.zig"); pub const clock_config = clocks.GlobalConfiguration.init(.{ .ref = .{ .source = .src_xosc }, diff --git a/src/hal/gpio.zig b/src/hal/gpio.zig index ec48f11..18624ee 100644 --- a/src/hal/gpio.zig +++ b/src/hal/gpio.zig @@ -4,6 +4,8 @@ const resets = @import("resets.zig"); const regs = microzig.chip.registers; const assert = std.debug.assert; +const log = std.log.scoped(.gpio); + pub const Function = enum(u5) { xip, spi, @@ -83,6 +85,7 @@ pub inline fn setDir(comptime gpio: u32, direction: Direction) void { /// Drive a single GPIO high/low pub inline fn put(comptime gpio: u32, value: u1) void { + std.log.debug("GPIO{} put: {}", .{ gpio, value }); const mask = 1 << gpio; switch (value) { 0 => regs.SIO.GPIO_OUT_CLR.raw = mask, diff --git a/src/hal/irq.zig b/src/hal/irq.zig new file mode 100644 index 0000000..7d57c78 --- /dev/null +++ b/src/hal/irq.zig @@ -0,0 +1,20 @@ +const microzig = @import("microzig"); +const regs = microzig.chip.registers; + +// TODO: the register definitions are improved now, use them instead of raw +// writes/reads +fn getInterruptMask(comptime interrupt_name: []const u8) u32 { + const offset = @offsetOf(microzig.chip.VectorTable, interrupt_name); + + return (1 << ((offset / 4) - 16)); +} +pub fn enable(comptime interrupt_name: []const u8) void { + const mask = comptime getInterruptMask(interrupt_name); + regs.SCS.NVIC.ICPR.raw = mask; + regs.SCS.NVIC.ISER.raw = mask; +} + +pub fn disable(comptime interrupt_name: []const u8) void { + const mask = comptime getInterruptMask(interrupt_name); + regs.SCS.NVIC.ICER.raw = mask; +} diff --git a/src/hal/multicore.zig b/src/hal/multicore.zig index dd90d17..76811cf 100644 --- a/src/hal/multicore.zig +++ b/src/hal/multicore.zig @@ -88,7 +88,7 @@ pub fn launchCore1WithStack(entrypoint: fn () void, stack: []u32) void { 0, 0, 1, - regs.PPB.VTOR.raw, + regs.SCS.SCB.VTOR.raw, stack_ptr, @ptrToInt(wrapper), }; diff --git a/src/hal/pwm.zig b/src/hal/pwm.zig index 457fd2c..45cf90b 100644 --- a/src/hal/pwm.zig +++ b/src/hal/pwm.zig @@ -1,6 +1,9 @@ +const std = @import("std"); const microzig = @import("microzig"); const regs = microzig.chip.registers; +const log = std.log.scoped(.pwm); + pub const Config = struct {}; fn getRegs(comptime slice: u32) *volatile Regs { @@ -67,12 +70,14 @@ const Regs = extern struct { }; pub inline fn setSlicePhaseCorrect(comptime slice: u32, phase_correct: bool) void { + log.debug("PWM{} set phase correct: {}", .{ slice, phase_correct }); getRegs(slice).csr.modify(.{ .PH_CORRECT = if (phase_correct) 1 else 0, }); } pub inline fn setSliceClkDiv(comptime slice: u32, integer: u8, fraction: u4) void { + log.debug("PWM{} set clk div: {}.{}", .{ slice, integer, fraction }); getRegs(slice).div.modify(.{ .INT = integer, .FRAC = fraction, @@ -80,6 +85,7 @@ pub inline fn setSliceClkDiv(comptime slice: u32, integer: u8, fraction: u4) voi } pub inline fn setSliceClkDivMode(comptime slice: u32, mode: ClkDivMode) void { + log.debug("PWM{} set clk div mode: {}", .{ slice, mode }); getRegs(slice).csr.modify(.{ .DIVMODE = @enumToInt(mode), }); @@ -101,6 +107,7 @@ pub inline fn setChannelInversion( } pub inline fn setSliceWrap(comptime slice: u32, wrap: u16) void { + log.debug("PWM{} set wrap: {}", .{ slice, wrap }); getRegs(slice).top.raw = wrap; } @@ -109,6 +116,7 @@ pub inline fn setChannelLevel( comptime channel: Channel, level: u16, ) void { + log.debug("PWM{} {} set level: {}", .{ slice, channel, level }); switch (channel) { .a => getRegs(slice).cc.modify(.{ .A = level }), .b => getRegs(slice).cc.modify(.{ .B = level }), diff --git a/src/hal/uart.zig b/src/hal/uart.zig index 1816399..5f3f8c6 100644 --- a/src/hal/uart.zig +++ b/src/hal/uart.zig @@ -2,6 +2,8 @@ const std = @import("std"); const microzig = @import("microzig"); const gpio = @import("gpio.zig"); const clocks = @import("clocks.zig"); +const resets = @import("resets.zig"); +const time = @import("time.zig"); const assert = std.debug.assert; const regs = microzig.chip.registers; @@ -39,7 +41,7 @@ pub const UartRegs = extern struct { rsr: u32, reserved0: [4]u32, fr: @typeInfo(@TypeOf(regs.UART0.UARTFR)).Pointer.child, - resertev1: [1]u32, + reserved1: [1]u32, ilpr: u32, ibrd: u32, fbrd: u32, @@ -149,16 +151,8 @@ pub const UART = enum { pub fn reset(uart: UART) void { switch (uart) { - .uart0 => { - regs.RESETS.RESET.modify(.{ .uart0 = 1 }); - regs.RESETS.RESET.modify(.{ .uart0 = 0 }); - while (regs.RESETS.RESET_DONE.read().uart0 != 1) {} - }, - .uart1 => { - regs.RESETS.RESET.modify(.{ .uart1 = 1 }); - regs.RESETS.RESET.modify(.{ .uart1 = 0 }); - while (regs.RESETS.RESET_DONE.read().uart1 != 1) {} - }, + .uart0 => resets.reset(&.{.uart0}), + .uart1 => resets.reset(&.{.uart1}), } } @@ -180,11 +174,13 @@ pub const UART = enum { .one => @as(u1, 0), .two => @as(u1, 1), }, - .PEN = if (parity != .none) @as(u1, 1) else @as(u1, 0), + .PEN = switch (parity) { + .none => @as(u1, 0), + .even, .odd => @as(u1, 1), + }, .EPS = switch (parity) { .even => @as(u1, 1), - .odd => @as(u1, 0), - else => @as(u1, 0), + .odd, .none => @as(u1, 0), }, }); } @@ -210,3 +206,30 @@ pub const UART = enum { uart_regs.lcr_h.modify(.{}); } }; + +var uart_logger: ?UART.Writer = null; + +pub fn initLogger(uart: UART) void { + uart_logger = uart.writer(); +} + +pub fn log( + comptime level: std.log.Level, + comptime scope: @TypeOf(.EnumLiteral), + comptime format: []const u8, + args: anytype, +) void { + const level_prefix = comptime "[{}.{:0>6}] " ++ level.asText(); + const prefix = comptime level_prefix ++ switch (scope) { + .default => ": ", + else => " (" ++ @tagName(scope) ++ "): ", + }; + + if (uart_logger) |uart| { + const current_time = time.getTimeSinceBoot(); + const seconds = current_time.us_since_boot / std.time.us_per_s; + const microseconds = current_time.us_since_boot % std.time.us_per_s; + + uart.print(prefix ++ format ++ "\r\n", .{ seconds, microseconds } ++ args) catch {}; + } +} diff --git a/src/rp2040.zig b/src/rp2040.zig index 571b648..6301bf2 100644 --- a/src/rp2040.zig +++ b/src/rp2040.zig @@ -1,5 +1,5 @@ // this file was generated by regz: https://github.com/ZigEmbeddedGroup/regz -// commit: 09c331e02d8037bf2e5133eaa40b1d762637b441 +// commit: 644b9d6f61ba1e49d90e4f606f82727f3d6581f2 // // vendor: Raspberry Pi // device: RP2040 @@ -134,23 +134,388 @@ pub const registers = struct { pub const NVIC = struct { /// address: 0xe000e100 /// Interrupt Set Enable Register - pub const ISER = @intToPtr(*volatile u32, base_address + 0x100); + pub const ISER = @intToPtr(*volatile Mmio(32, packed struct { + TIMER_IRQ_0: u1, + TIMER_IRQ_1: u1, + TIMER_IRQ_2: u1, + TIMER_IRQ_3: u1, + PWM_IRQ_WRAP: u1, + USBCTRL_IRQ: u1, + XIP_IRQ: u1, + PIO0_IRQ_0: u1, + PIO0_IRQ_1: u1, + PIO1_IRQ_0: u1, + PIO1_IRQ_1: u1, + DMA_IRQ_0: u1, + DMA_IRQ_1: u1, + IO_IRQ_BANK0: u1, + IO_IRQ_QSPI: u1, + SIO_IRQ_PROC0: u1, + SIO_IRQ_PROC1: u1, + CLOCKS_IRQ: u1, + SPI0_IRQ: u1, + SPI1_IRQ: u1, + UART0_IRQ: u1, + UART1_IRQ: u1, + ADC_IRQ_FIFO: u1, + I2C0_IRQ: u1, + I2C1_IRQ: u1, + RTC_IRQ: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + }), base_address + 0x100); /// address: 0xe000e180 /// Interrupt Clear Enable Register - pub const ICER = @intToPtr(*volatile u32, base_address + 0x180); + pub const ICER = @intToPtr(*volatile Mmio(32, packed struct { + TIMER_IRQ_0: u1, + TIMER_IRQ_1: u1, + TIMER_IRQ_2: u1, + TIMER_IRQ_3: u1, + PWM_IRQ_WRAP: u1, + USBCTRL_IRQ: u1, + XIP_IRQ: u1, + PIO0_IRQ_0: u1, + PIO0_IRQ_1: u1, + PIO1_IRQ_0: u1, + PIO1_IRQ_1: u1, + DMA_IRQ_0: u1, + DMA_IRQ_1: u1, + IO_IRQ_BANK0: u1, + IO_IRQ_QSPI: u1, + SIO_IRQ_PROC0: u1, + SIO_IRQ_PROC1: u1, + CLOCKS_IRQ: u1, + SPI0_IRQ: u1, + SPI1_IRQ: u1, + UART0_IRQ: u1, + UART1_IRQ: u1, + ADC_IRQ_FIFO: u1, + I2C0_IRQ: u1, + I2C1_IRQ: u1, + RTC_IRQ: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + }), base_address + 0x180); /// address: 0xe000e200 /// Interrupt Set Pending Register - pub const ISPR = @intToPtr(*volatile u32, base_address + 0x200); + pub const ISPR = @intToPtr(*volatile Mmio(32, packed struct { + TIMER_IRQ_0: u1, + TIMER_IRQ_1: u1, + TIMER_IRQ_2: u1, + TIMER_IRQ_3: u1, + PWM_IRQ_WRAP: u1, + USBCTRL_IRQ: u1, + XIP_IRQ: u1, + PIO0_IRQ_0: u1, + PIO0_IRQ_1: u1, + PIO1_IRQ_0: u1, + PIO1_IRQ_1: u1, + DMA_IRQ_0: u1, + DMA_IRQ_1: u1, + IO_IRQ_BANK0: u1, + IO_IRQ_QSPI: u1, + SIO_IRQ_PROC0: u1, + SIO_IRQ_PROC1: u1, + CLOCKS_IRQ: u1, + SPI0_IRQ: u1, + SPI1_IRQ: u1, + UART0_IRQ: u1, + UART1_IRQ: u1, + ADC_IRQ_FIFO: u1, + I2C0_IRQ: u1, + I2C1_IRQ: u1, + RTC_IRQ: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + }), base_address + 0x200); /// address: 0xe000e280 /// Interrupt Clear Pending Register - pub const ICPR = @intToPtr(*volatile u32, base_address + 0x280); + pub const ICPR = @intToPtr(*volatile Mmio(32, packed struct { + TIMER_IRQ_0: u1, + TIMER_IRQ_1: u1, + TIMER_IRQ_2: u1, + TIMER_IRQ_3: u1, + PWM_IRQ_WRAP: u1, + USBCTRL_IRQ: u1, + XIP_IRQ: u1, + PIO0_IRQ_0: u1, + PIO0_IRQ_1: u1, + PIO1_IRQ_0: u1, + PIO1_IRQ_1: u1, + DMA_IRQ_0: u1, + DMA_IRQ_1: u1, + IO_IRQ_BANK0: u1, + IO_IRQ_QSPI: u1, + SIO_IRQ_PROC0: u1, + SIO_IRQ_PROC1: u1, + CLOCKS_IRQ: u1, + SPI0_IRQ: u1, + SPI1_IRQ: u1, + UART0_IRQ: u1, + UART1_IRQ: u1, + ADC_IRQ_FIFO: u1, + I2C0_IRQ: u1, + I2C1_IRQ: u1, + RTC_IRQ: u1, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + }), base_address + 0x280); /// address: 0xe000e400 /// Interrupt Priority Register - pub const IP = @intToPtr(*volatile u32, base_address + 0x400); + pub const IP0 = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + TIMER_IRQ_0: u2, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + TIMER_IRQ_1: u2, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + TIMER_IRQ_2: u2, + reserved18: u1 = 0, + reserved19: u1 = 0, + reserved20: u1 = 0, + reserved21: u1 = 0, + reserved22: u1 = 0, + reserved23: u1 = 0, + TIMER_IRQ_3: u2, + }), base_address + 0x400); + + /// address: 0xe000e404 + /// Interrupt Priority Register + pub const IP1 = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + PWM_IRQ_WRAP: u2, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + USBCTRL_IRQ: u2, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + XIP_IRQ: u2, + reserved18: u1 = 0, + reserved19: u1 = 0, + reserved20: u1 = 0, + reserved21: u1 = 0, + reserved22: u1 = 0, + reserved23: u1 = 0, + PIO0_IRQ_0: u2, + }), base_address + 0x404); + + /// address: 0xe000e408 + /// Interrupt Priority Register + pub const IP2 = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + PIO0_IRQ_1: u2, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + PIO1_IRQ_0: u2, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + PIO1_IRQ_1: u2, + reserved18: u1 = 0, + reserved19: u1 = 0, + reserved20: u1 = 0, + reserved21: u1 = 0, + reserved22: u1 = 0, + reserved23: u1 = 0, + DMA_IRQ_0: u2, + }), base_address + 0x408); + + /// address: 0xe000e40c + /// Interrupt Priority Register + pub const IP3 = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + DMA_IRQ_1: u2, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + IO_IRQ_BANK0: u2, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + IO_IRQ_QSPI: u2, + reserved18: u1 = 0, + reserved19: u1 = 0, + reserved20: u1 = 0, + reserved21: u1 = 0, + reserved22: u1 = 0, + reserved23: u1 = 0, + SIO_IRQ_PROC0: u2, + }), base_address + 0x40c); + + /// address: 0xe000e410 + /// Interrupt Priority Register + pub const IP4 = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + SIO_IRQ_PROC1: u2, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + CLOCKS_IRQ: u2, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + SPI0_IRQ: u2, + reserved18: u1 = 0, + reserved19: u1 = 0, + reserved20: u1 = 0, + reserved21: u1 = 0, + reserved22: u1 = 0, + reserved23: u1 = 0, + SPI1_IRQ: u2, + }), base_address + 0x410); + + /// address: 0xe000e414 + /// Interrupt Priority Register + pub const IP5 = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + UART0_IRQ: u2, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + UART1_IRQ: u2, + reserved12: u1 = 0, + reserved13: u1 = 0, + reserved14: u1 = 0, + reserved15: u1 = 0, + reserved16: u1 = 0, + reserved17: u1 = 0, + ADC_IRQ_FIFO: u2, + reserved18: u1 = 0, + reserved19: u1 = 0, + reserved20: u1 = 0, + reserved21: u1 = 0, + reserved22: u1 = 0, + reserved23: u1 = 0, + I2C0_IRQ: u2, + }), base_address + 0x414); + + /// address: 0xe000e418 + /// Interrupt Priority Register + pub const IP6 = @intToPtr(*volatile Mmio(32, packed struct { + reserved0: u1 = 0, + reserved1: u1 = 0, + reserved2: u1 = 0, + reserved3: u1 = 0, + reserved4: u1 = 0, + reserved5: u1 = 0, + I2C1_IRQ: u2, + reserved6: u1 = 0, + reserved7: u1 = 0, + reserved8: u1 = 0, + reserved9: u1 = 0, + reserved10: u1 = 0, + reserved11: u1 = 0, + RTC_IRQ: u2, + padding0: u1 = 0, + padding1: u1 = 0, + padding2: u1 = 0, + padding3: u1 = 0, + padding4: u1 = 0, + padding5: u1 = 0, + padding6: u1 = 0, + padding7: u1 = 0, + padding8: u1 = 0, + padding9: u1 = 0, + padding10: u1 = 0, + padding11: u1 = 0, + padding12: u1 = 0, + padding13: u1 = 0, + padding14: u1 = 0, + padding15: u1 = 0, + }), base_address + 0x418); + + /// address: 0xe000e41c + /// Interrupt Priority Register + pub const IP7 = @intToPtr(*volatile u32, base_address + 0x41c); }; /// System Control Block @@ -28295,806 +28660,35 @@ pub const registers = struct { pub const base_address = 0xe0000000; pub const version = "1"; - /// address: 0xe000e010 - /// Use the SysTick Control and Status Register to enable the SysTick features. - pub const SYST_CSR = @intToPtr(*volatile Mmio(32, packed struct { - /// Enable SysTick counter:\n - /// 0 = Counter disabled.\n - /// 1 = Counter enabled. - ENABLE: u1, - /// Enables SysTick exception request:\n - /// 0 = Counting down to zero does not assert the SysTick exception request.\n - /// 1 = Counting down to zero to asserts the SysTick exception request. - TICKINT: u1, - /// SysTick clock source. Always reads as one if SYST_CALIB reports NOREF.\n - /// Selects the SysTick timer clock source:\n - /// 0 = External reference clock.\n - /// 1 = Processor clock. - CLKSOURCE: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// Returns 1 if timer counted to 0 since last time this was read. Clears on read by - /// application or debugger. - COUNTFLAG: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - }), base_address + 0xe010); - - /// address: 0xe000e014 - /// Use the SysTick Reload Value Register to specify the start value to load into - /// the current value register when the counter reaches 0. It can be any value - /// between 0 and 0x00FFFFFF. A start value of 0 is possible, but has no effect - /// because the SysTick interrupt and COUNTFLAG are activated when counting from 1 - /// to 0. The reset value of this register is UNKNOWN.\n - /// To generate a multi-shot timer with a period of N processor clock cycles, use a - /// RELOAD value of N-1. For example, if the SysTick interrupt is required every 100 - /// clock pulses, set RELOAD to 99. - pub const SYST_RVR = @intToPtr(*volatile Mmio(32, packed struct { - /// Value to load into the SysTick Current Value Register when the counter reaches - /// 0. - RELOAD: u24, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0xe014); - - /// address: 0xe000e018 - /// Use the SysTick Current Value Register to find the current value in the - /// register. The reset value of this register is UNKNOWN. - pub const SYST_CVR = @intToPtr(*volatile Mmio(32, packed struct { - /// Reads return the current value of the SysTick counter. This register is - /// write-clear. Writing to it with any value clears the register to 0. Clearing - /// this register also clears the COUNTFLAG bit of the SysTick Control and Status - /// Register. - CURRENT: u24, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0xe018); - - /// address: 0xe000e01c - /// Use the SysTick Calibration Value Register to enable software to scale to any - /// required speed using divide and multiply. - pub const SYST_CALIB = @intToPtr(*volatile Mmio(32, packed struct { - /// An optional Reload value to be used for 10ms (100Hz) timing, subject to system - /// clock skew errors. If the value reads as 0, the calibration value is not known. - TENMS: u24, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - /// If reads as 1, the calibration value for 10ms is inexact (due to clock - /// frequency). - SKEW: u1, - /// If reads as 1, the Reference clock is not provided - the CLKSOURCE bit of the - /// SysTick Control and Status register will be forced to 1 and cannot be cleared to - /// 0. - NOREF: u1, - }), base_address + 0xe01c); - - /// address: 0xe000e100 - /// Use the Interrupt Set-Enable Register to enable interrupts and determine which - /// interrupts are currently enabled.\n - /// If a pending interrupt is enabled, the NVIC activates the interrupt based on its - /// priority. If an interrupt is not enabled, asserting its interrupt signal changes - /// the interrupt state to pending, but the NVIC never activates the interrupt, - /// regardless of its priority. - pub const NVIC_ISER = @intToPtr(*volatile Mmio(32, packed struct { - /// Interrupt set-enable bits.\n - /// Write:\n - /// 0 = No effect.\n - /// 1 = Enable interrupt.\n - /// Read:\n - /// 0 = Interrupt disabled.\n - /// 1 = Interrupt enabled. - SETENA: u32, - }), base_address + 0xe100); - - /// address: 0xe000e180 - /// Use the Interrupt Clear-Enable Registers to disable interrupts and determine - /// which interrupts are currently enabled. - pub const NVIC_ICER = @intToPtr(*volatile Mmio(32, packed struct { - /// Interrupt clear-enable bits.\n - /// Write:\n - /// 0 = No effect.\n - /// 1 = Disable interrupt.\n - /// Read:\n - /// 0 = Interrupt disabled.\n - /// 1 = Interrupt enabled. - CLRENA: u32, - }), base_address + 0xe180); - - /// address: 0xe000e200 - /// The NVIC_ISPR forces interrupts into the pending state, and shows which - /// interrupts are pending. - pub const NVIC_ISPR = @intToPtr(*volatile Mmio(32, packed struct { - /// Interrupt set-pending bits.\n - /// Write:\n - /// 0 = No effect.\n - /// 1 = Changes interrupt state to pending.\n - /// Read:\n - /// 0 = Interrupt is not pending.\n - /// 1 = Interrupt is pending.\n - /// Note: Writing 1 to the NVIC_ISPR bit corresponding to:\n - /// An interrupt that is pending has no effect.\n - /// A disabled interrupt sets the state of that interrupt to pending. - SETPEND: u32, - }), base_address + 0xe200); - - /// address: 0xe000e280 - /// Use the Interrupt Clear-Pending Register to clear pending interrupts and - /// determine which interrupts are currently pending. - pub const NVIC_ICPR = @intToPtr(*volatile Mmio(32, packed struct { - /// Interrupt clear-pending bits.\n - /// Write:\n - /// 0 = No effect.\n - /// 1 = Removes pending state and interrupt.\n - /// Read:\n - /// 0 = Interrupt is not pending.\n - /// 1 = Interrupt is pending. - CLRPEND: u32, - }), base_address + 0xe280); - - /// address: 0xe000e400 - /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of - /// the available interrupts. 0 is the highest priority, and 3 is the lowest.\n - /// Note: Writing 1 to an NVIC_ICPR bit does not affect the active state of the - /// corresponding interrupt.\n - /// These registers are only word-accessible - pub const NVIC_IPR0 = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - /// Priority of interrupt 0 - IP_0: u2, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - /// Priority of interrupt 1 - IP_1: u2, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// Priority of interrupt 2 - IP_2: u2, - reserved18: u1 = 0, - reserved19: u1 = 0, - reserved20: u1 = 0, - reserved21: u1 = 0, - reserved22: u1 = 0, - reserved23: u1 = 0, - /// Priority of interrupt 3 - IP_3: u2, - }), base_address + 0xe400); - - /// address: 0xe000e404 - /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of - /// the available interrupts. 0 is the highest priority, and 3 is the lowest. - pub const NVIC_IPR1 = @intToPtr(*volatile Mmio(32, packed struct { + /// address: 0xe000ed20 + /// System handlers are a special class of exception handler that can have their + /// priority set to any of the priority levels. Use the System Handler Priority + /// Register 3 to set the priority of PendSV and SysTick. + pub const SHPR3 = @intToPtr(*volatile Mmio(32, packed struct { reserved0: u1 = 0, reserved1: u1 = 0, reserved2: u1 = 0, reserved3: u1 = 0, reserved4: u1 = 0, reserved5: u1 = 0, - /// Priority of interrupt 4 - IP_4: u2, reserved6: u1 = 0, reserved7: u1 = 0, reserved8: u1 = 0, reserved9: u1 = 0, reserved10: u1 = 0, reserved11: u1 = 0, - /// Priority of interrupt 5 - IP_5: u2, reserved12: u1 = 0, reserved13: u1 = 0, reserved14: u1 = 0, reserved15: u1 = 0, reserved16: u1 = 0, reserved17: u1 = 0, - /// Priority of interrupt 6 - IP_6: u2, reserved18: u1 = 0, reserved19: u1 = 0, reserved20: u1 = 0, reserved21: u1 = 0, - reserved22: u1 = 0, - reserved23: u1 = 0, - /// Priority of interrupt 7 - IP_7: u2, - }), base_address + 0xe404); - - /// address: 0xe000e408 - /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of - /// the available interrupts. 0 is the highest priority, and 3 is the lowest. - pub const NVIC_IPR2 = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - /// Priority of interrupt 8 - IP_8: u2, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - /// Priority of interrupt 9 - IP_9: u2, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// Priority of interrupt 10 - IP_10: u2, - reserved18: u1 = 0, - reserved19: u1 = 0, - reserved20: u1 = 0, - reserved21: u1 = 0, - reserved22: u1 = 0, - reserved23: u1 = 0, - /// Priority of interrupt 11 - IP_11: u2, - }), base_address + 0xe408); - - /// address: 0xe000e40c - /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of - /// the available interrupts. 0 is the highest priority, and 3 is the lowest. - pub const NVIC_IPR3 = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - /// Priority of interrupt 12 - IP_12: u2, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - /// Priority of interrupt 13 - IP_13: u2, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// Priority of interrupt 14 - IP_14: u2, - reserved18: u1 = 0, - reserved19: u1 = 0, - reserved20: u1 = 0, - reserved21: u1 = 0, - reserved22: u1 = 0, - reserved23: u1 = 0, - /// Priority of interrupt 15 - IP_15: u2, - }), base_address + 0xe40c); - - /// address: 0xe000e410 - /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of - /// the available interrupts. 0 is the highest priority, and 3 is the lowest. - pub const NVIC_IPR4 = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - /// Priority of interrupt 16 - IP_16: u2, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - /// Priority of interrupt 17 - IP_17: u2, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// Priority of interrupt 18 - IP_18: u2, - reserved18: u1 = 0, - reserved19: u1 = 0, - reserved20: u1 = 0, - reserved21: u1 = 0, - reserved22: u1 = 0, - reserved23: u1 = 0, - /// Priority of interrupt 19 - IP_19: u2, - }), base_address + 0xe410); - - /// address: 0xe000e414 - /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of - /// the available interrupts. 0 is the highest priority, and 3 is the lowest. - pub const NVIC_IPR5 = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - /// Priority of interrupt 20 - IP_20: u2, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - /// Priority of interrupt 21 - IP_21: u2, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// Priority of interrupt 22 - IP_22: u2, - reserved18: u1 = 0, - reserved19: u1 = 0, - reserved20: u1 = 0, - reserved21: u1 = 0, - reserved22: u1 = 0, - reserved23: u1 = 0, - /// Priority of interrupt 23 - IP_23: u2, - }), base_address + 0xe414); - - /// address: 0xe000e418 - /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of - /// the available interrupts. 0 is the highest priority, and 3 is the lowest. - pub const NVIC_IPR6 = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - /// Priority of interrupt 24 - IP_24: u2, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - /// Priority of interrupt 25 - IP_25: u2, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// Priority of interrupt 26 - IP_26: u2, - reserved18: u1 = 0, - reserved19: u1 = 0, - reserved20: u1 = 0, - reserved21: u1 = 0, - reserved22: u1 = 0, - reserved23: u1 = 0, - /// Priority of interrupt 27 - IP_27: u2, - }), base_address + 0xe418); - - /// address: 0xe000e41c - /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of - /// the available interrupts. 0 is the highest priority, and 3 is the lowest. - pub const NVIC_IPR7 = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - /// Priority of interrupt 28 - IP_28: u2, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - /// Priority of interrupt 29 - IP_29: u2, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// Priority of interrupt 30 - IP_30: u2, - reserved18: u1 = 0, - reserved19: u1 = 0, - reserved20: u1 = 0, - reserved21: u1 = 0, - reserved22: u1 = 0, - reserved23: u1 = 0, - /// Priority of interrupt 31 - IP_31: u2, - }), base_address + 0xe41c); - - /// address: 0xe000ed00 - /// Read the CPU ID Base Register to determine: the ID number of the processor core, - /// the version number of the processor core, the implementation details of the - /// processor core. - pub const CPUID = @intToPtr(*volatile Mmio(32, packed struct { - /// Minor revision number m in the rnpm revision status:\n - /// 0x1 = Patch 1. - REVISION: u4, - /// Number of processor within family: 0xC60 = Cortex-M0+ - PARTNO: u12, - /// Constant that defines the architecture of the processor:\n - /// 0xC = ARMv6-M architecture. - ARCHITECTURE: u4, - /// Major revision number n in the rnpm revision status:\n - /// 0x0 = Revision 0. - VARIANT: u4, - /// Implementor code: 0x41 = ARM - IMPLEMENTER: u8, - }), base_address + 0xed00); - - /// address: 0xe000ed04 - /// Use the Interrupt Control State Register to set a pending Non-Maskable Interrupt - /// (NMI), set or clear a pending PendSV, set or clear a pending SysTick, check for - /// pending exceptions, check the vector number of the highest priority pended - /// exception, check the vector number of the active exception. - pub const ICSR = @intToPtr(*volatile Mmio(32, packed struct { - /// Active exception number field. Reset clears the VECTACTIVE field. - VECTACTIVE: u9, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - /// Indicates the exception number for the highest priority pending exception: 0 = - /// no pending exceptions. Non zero = The pending state includes the effect of - /// memory-mapped enable and mask registers. It does not include the PRIMASK - /// special-purpose register qualifier. - VECTPENDING: u9, - reserved3: u1 = 0, - /// External interrupt pending flag - ISRPENDING: u1, - /// The system can only access this bit when the core is halted. It indicates that a - /// pending interrupt is to be taken in the next running cycle. If C_MASKINTS is - /// clear in the Debug Halting Control and Status Register, the interrupt is - /// serviced. - ISRPREEMPT: u1, - reserved4: u1 = 0, - /// SysTick exception clear-pending bit.\n - /// Write:\n - /// 0 = No effect.\n - /// 1 = Removes the pending state from the SysTick exception.\n - /// This bit is WO. On a register read its value is Unknown. - PENDSTCLR: u1, - /// SysTick exception set-pending bit.\n - /// Write:\n - /// 0 = No effect.\n - /// 1 = Changes SysTick exception state to pending.\n - /// Read:\n - /// 0 = SysTick exception is not pending.\n - /// 1 = SysTick exception is pending. - PENDSTSET: u1, - /// PendSV clear-pending bit.\n - /// Write:\n - /// 0 = No effect.\n - /// 1 = Removes the pending state from the PendSV exception. - PENDSVCLR: u1, - /// PendSV set-pending bit.\n - /// Write:\n - /// 0 = No effect.\n - /// 1 = Changes PendSV exception state to pending.\n - /// Read:\n - /// 0 = PendSV exception is not pending.\n - /// 1 = PendSV exception is pending.\n - /// Writing 1 to this bit is the only way to set the PendSV exception state to - /// pending. - PENDSVSET: u1, - reserved5: u1 = 0, - reserved6: u1 = 0, - /// Setting this bit will activate an NMI. Since NMI is the highest priority - /// exception, it will activate as soon as it is registered.\n - /// NMI set-pending bit.\n - /// Write:\n - /// 0 = No effect.\n - /// 1 = Changes NMI exception state to pending.\n - /// Read:\n - /// 0 = NMI exception is not pending.\n - /// 1 = NMI exception is pending.\n - /// Because NMI is the highest-priority exception, normally the processor enters the - /// NMI\n - /// exception handler as soon as it detects a write of 1 to this bit. Entering the - /// handler then clears\n - /// this bit to 0. This means a read of this bit by the NMI exception handler - /// returns 1 only if the\n - /// NMI signal is reasserted while the processor is executing that handler. - NMIPENDSET: u1, - }), base_address + 0xed04); - - /// address: 0xe000ed08 - /// The VTOR holds the vector table offset address. - pub const VTOR = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// Bits [31:8] of the indicate the vector table offset address. - TBLOFF: u24, - }), base_address + 0xed08); - - /// address: 0xe000ed0c - /// Use the Application Interrupt and Reset Control Register to: determine data - /// endianness, clear all active state information from debug halt mode, request a - /// system reset. - pub const AIRCR = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - /// Clears all active state information for fixed and configurable exceptions. This - /// bit: is self-clearing, can only be set by the DAP when the core is halted. When - /// set: clears all active exception status of the processor, forces a return to - /// Thread mode, forces an IPSR of 0. A debugger must re-initialize the stack. - VECTCLRACTIVE: u1, - /// Writing 1 to this bit causes the SYSRESETREQ signal to the outer system to be - /// asserted to request a reset. The intention is to force a large system reset of - /// all major components except for debug. The C_HALT bit in the DHCSR is cleared as - /// a result of the system reset requested. The debugger does not lose contact with - /// the device. - SYSRESETREQ: u1, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// Data endianness implemented:\n - /// 0 = Little-endian. - ENDIANESS: u1, - /// Register key:\n - /// Reads as Unknown\n - /// On writes, write 0x05FA to VECTKEY, otherwise the write is ignored. - VECTKEY: u16, - }), base_address + 0xed0c); - - /// address: 0xe000ed10 - /// System Control Register. Use the System Control Register for power-management - /// functions: signal to the system when the processor can enter a low power state, - /// control how the processor enters and exits low power states. - pub const SCR = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - /// Indicates sleep-on-exit when returning from Handler mode to Thread mode:\n - /// 0 = Do not sleep when returning to Thread mode.\n - /// 1 = Enter sleep, or deep sleep, on return from an ISR to Thread mode.\n - /// Setting this bit to 1 enables an interrupt driven application to avoid returning - /// to an empty main application. - SLEEPONEXIT: u1, - /// Controls whether the processor uses sleep or deep sleep as its low power mode:\n - /// 0 = Sleep.\n - /// 1 = Deep sleep. - SLEEPDEEP: u1, - reserved1: u1 = 0, - /// Send Event on Pending bit:\n - /// 0 = Only enabled interrupts or events can wakeup the processor, disabled - /// interrupts are excluded.\n - /// 1 = Enabled events and all interrupts, including disabled interrupts, can wakeup - /// the processor.\n - /// When an event or interrupt becomes pending, the event signal wakes up the - /// processor from WFE. If the\n - /// processor is not waiting for an event, the event is registered and affects the - /// next WFE.\n - /// The processor also wakes up on execution of an SEV instruction or an external - /// event. - SEVONPEND: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - }), base_address + 0xed10); - - /// address: 0xe000ed14 - /// The Configuration and Control Register permanently enables stack alignment and - /// causes unaligned accesses to result in a Hard Fault. - pub const CCR = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - /// Always reads as one, indicates that all unaligned accesses generate a HardFault. - UNALIGN_TRP: u1, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// Always reads as one, indicates 8-byte stack alignment on exception entry. On - /// exception entry, the processor uses bit[9] of the stacked PSR to indicate the - /// stack alignment. On return from the exception it uses this stacked bit to - /// restore the correct stack alignment. - STKALIGN: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - }), base_address + 0xed14); - - /// address: 0xe000ed1c - /// System handlers are a special class of exception handler that can have their - /// priority set to any of the priority levels. Use the System Handler Priority - /// Register 2 to set the priority of SVCall. - pub const SHPR2 = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - reserved18: u1 = 0, - reserved19: u1 = 0, - reserved20: u1 = 0, - reserved21: u1 = 0, - reserved22: u1 = 0, - reserved23: u1 = 0, - reserved24: u1 = 0, - reserved25: u1 = 0, - reserved26: u1 = 0, - reserved27: u1 = 0, - reserved28: u1 = 0, - reserved29: u1 = 0, - /// Priority of system handler 11, SVCall - PRI_11: u2, - }), base_address + 0xed1c); - - /// address: 0xe000ed20 - /// System handlers are a special class of exception handler that can have their - /// priority set to any of the priority levels. Use the System Handler Priority - /// Register 3 to set the priority of PendSV and SysTick. - pub const SHPR3 = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - reserved18: u1 = 0, - reserved19: u1 = 0, - reserved20: u1 = 0, - reserved21: u1 = 0, - /// Priority of system handler 14, PendSV - PRI_14: u2, + /// Priority of system handler 14, PendSV + PRI_14: u2, reserved22: u1 = 0, reserved23: u1 = 0, reserved24: u1 = 0, @@ -29104,223 +28698,6 @@ pub const registers = struct { /// Priority of system handler 15, SysTick PRI_15: u2, }), base_address + 0xed20); - - /// address: 0xe000ed24 - /// Use the System Handler Control and State Register to determine or clear the - /// pending status of SVCall. - pub const SHCSR = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - /// Reads as 1 if SVCall is Pending. Write 1 to set pending SVCall, write 0 to clear - /// pending SVCall. - SVCALLPENDED: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - }), base_address + 0xed24); - - /// address: 0xe000ed90 - /// Read the MPU Type Register to determine if the processor implements an MPU, and - /// how many regions the MPU supports. - pub const MPU_TYPE = @intToPtr(*volatile Mmio(32, packed struct { - /// Indicates support for separate instruction and data address maps. Reads as 0 as - /// ARMv6-M only supports a unified MPU. - SEPARATE: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - /// Number of regions supported by the MPU. - DREGION: u8, - /// Instruction region. Reads as zero as ARMv6-M only supports a unified MPU. - IREGION: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0xed90); - - /// address: 0xe000ed94 - /// Use the MPU Control Register to enable and disable the MPU, and to control - /// whether the default memory map is enabled as a background region for privileged - /// accesses, and whether the MPU is enabled for HardFaults and NMIs. - pub const MPU_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// Enables the MPU. If the MPU is disabled, privileged and unprivileged accesses - /// use the default memory map.\n - /// 0 = MPU disabled.\n - /// 1 = MPU enabled. - ENABLE: u1, - /// Controls the use of the MPU for HardFaults and NMIs. Setting this bit when - /// ENABLE is clear results in UNPREDICTABLE behaviour.\n - /// When the MPU is enabled:\n - /// 0 = MPU is disabled during HardFault and NMI handlers, regardless of the value - /// of the ENABLE bit.\n - /// 1 = the MPU is enabled during HardFault and NMI handlers. - HFNMIENA: u1, - /// Controls whether the default memory map is enabled as a background region for - /// privileged accesses. This bit is ignored when ENABLE is clear.\n - /// 0 = If the MPU is enabled, disables use of the default memory map. Any memory - /// access to a location not\n - /// covered by any enabled region causes a fault.\n - /// 1 = If the MPU is enabled, enables use of the default memory map as a background - /// region for privileged software accesses.\n - /// When enabled, the background region acts as if it is region number -1. Any - /// region that is defined and enabled has priority over this default map. - PRIVDEFENA: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - }), base_address + 0xed94); - - /// address: 0xe000ed98 - /// Use the MPU Region Number Register to select the region currently accessed by - /// MPU_RBAR and MPU_RASR. - pub const MPU_RNR = @intToPtr(*volatile Mmio(32, packed struct { - /// Indicates the MPU region referenced by the MPU_RBAR and MPU_RASR registers.\n - /// The MPU supports 8 memory regions, so the permitted values of this field are - /// 0-7. - REGION: u4, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - }), base_address + 0xed98); - - /// address: 0xe000ed9c - /// Read the MPU Region Base Address Register to determine the base address of the - /// region identified by MPU_RNR. Write to update the base address of said region or - /// that of a specified region, with whose number MPU_RNR will also be updated. - pub const MPU_RBAR = @intToPtr(*volatile Mmio(32, packed struct { - /// On writes, specifies the number of the region whose base address to update - /// provided VALID is set written as 1. On reads, returns bits [3:0] of MPU_RNR. - REGION: u4, - /// On writes, indicates whether the write must update the base address of the - /// region identified by the REGION field, updating the MPU_RNR to indicate this new - /// region.\n - /// Write:\n - /// 0 = MPU_RNR not changed, and the processor:\n - /// Updates the base address for the region specified in the MPU_RNR.\n - /// Ignores the value of the REGION field.\n - /// 1 = The processor:\n - /// Updates the value of the MPU_RNR to the value of the REGION field.\n - /// Updates the base address for the region specified in the REGION field.\n - /// Always reads as zero. - VALID: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - /// Base address of the region. - ADDR: u24, - }), base_address + 0xed9c); - - /// address: 0xe000eda0 - /// Use the MPU Region Attribute and Size Register to define the size, access - /// behaviour and memory type of the region identified by MPU_RNR, and enable that - /// region. - pub const MPU_RASR = @intToPtr(*volatile Mmio(32, packed struct { - /// Enables the region. - ENABLE: u1, - /// Indicates the region size. Region size in bytes = 2^(SIZE+1). The minimum - /// permitted value is 7 (b00111) = 256Bytes - SIZE: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - /// Subregion Disable. For regions of 256 bytes or larger, each bit of this field - /// controls whether one of the eight equal subregions is enabled. - SRD: u8, - /// The MPU Region Attribute field. Use to define the region attribute control.\n - /// 28 = XN: Instruction access disable bit:\n - /// 0 = Instruction fetches enabled.\n - /// 1 = Instruction fetches disabled.\n - /// 26:24 = AP: Access permission field\n - /// 18 = S: Shareable bit\n - /// 17 = C: Cacheable bit\n - /// 16 = B: Bufferable bit - ATTRS: u16, - }), base_address + 0xeda0); }; }; @@ -29402,7 +28779,7 @@ pub fn mmioInt(addr: usize, comptime size: usize, comptime T: type) *volatile Mm return @intToPtr(*volatile MmioInt(size, T), addr); } -const InterruptVector = extern union { +pub const InterruptVector = extern union { C: fn () callconv(.C) void, Naked: fn () callconv(.Naked) void, // Interrupt is not supported on arm From 29aee14fd24e50f9f526d19bfdeb643a7665b509 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Quei=C3=9Fner?= Date: Fri, 30 Sep 2022 15:47:46 +0200 Subject: [PATCH 14/74] Update to latest master. (#13) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Felix "xq" Queißner --- deps/microzig | 2 +- examples/uart.zig | 2 +- src/hal/pins.zig | 2 +- src/hal/resets.zig | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/deps/microzig b/deps/microzig index 4159581..681b3b0 160000 --- a/deps/microzig +++ b/deps/microzig @@ -1 +1 @@ -Subproject commit 4159581b4848bfb8bbdf91dabdebd15ecd503427 +Subproject commit 681b3b0d7a6b2fc5d0f8918c583c790c646a31f1 diff --git a/examples/uart.zig b/examples/uart.zig index ed29280..7ccbe69 100644 --- a/examples/uart.zig +++ b/examples/uart.zig @@ -12,7 +12,7 @@ const baud_rate = 115200; const uart_tx_pin = 0; const uart_rx_pin = 1; -pub fn panic(message: []const u8, _: ?*std.builtin.StackTrace) noreturn { +pub fn panic(message: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { std.log.err("panic: {s}", .{message}); @breakpoint(); while (true) {} diff --git a/src/hal/pins.zig b/src/hal/pins.zig index ed07594..baa2479 100644 --- a/src/hal/pins.zig +++ b/src/hal/pins.zig @@ -5,7 +5,7 @@ const regs = @import("microzig").chip.registers; const assert = std.debug.assert; const comptimePrint = std.fmt.comptimePrint; -const StructField = std.builtin.TypeInfo.StructField; +const StructField = std.builtin.Type.StructField; pub const Pin = enum { GPIO0, diff --git a/src/hal/resets.zig b/src/hal/resets.zig index 0e0ea2b..5dbd81e 100644 --- a/src/hal/resets.zig +++ b/src/hal/resets.zig @@ -2,7 +2,7 @@ const std = @import("std"); const microzig = @import("microzig"); const regs = microzig.chip.registers; -const EnumField = std.builtin.TypeInfo.EnumField; +const EnumField = std.builtin.Type.EnumField; const Mask = @typeInfo(@TypeOf(regs.RESETS.RESET)).Pointer.child.underlying_type; pub const Module = enum { From 7c8d4302378be7d12f7af3f417e04c9a263de722 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Fri, 30 Sep 2022 12:27:00 -0700 Subject: [PATCH 15/74] adc bindings, mostly there but not quite (#14) --- build.zig | 1 + examples/adc.zig | 38 ++++++++++ src/hal.zig | 1 + src/hal/adc.zig | 194 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 234 insertions(+) create mode 100644 examples/adc.zig create mode 100644 src/hal/adc.zig diff --git a/build.zig b/build.zig index 01a26ae..889455d 100644 --- a/build.zig +++ b/build.zig @@ -63,6 +63,7 @@ fn root() []const u8 { } pub const Examples = struct { + adc: microzig.EmbeddedExecutable, blinky: microzig.EmbeddedExecutable, blinky_core1: microzig.EmbeddedExecutable, gpio_clk: microzig.EmbeddedExecutable, diff --git a/examples/adc.zig b/examples/adc.zig new file mode 100644 index 0000000..f8e8c66 --- /dev/null +++ b/examples/adc.zig @@ -0,0 +1,38 @@ +//! This example takes periodic samples of the temperature sensor and +//! prints it to the UART using the stdlib logging facility. +const std = @import("std"); +const microzig = @import("microzig"); +const rp2040 = microzig.hal; +const adc = rp2040.adc; +const time = rp2040.time; + +const temp_sensor: adc.Input = .temperature_sensor; +const uart_id = 0; +const baud_rate = 115200; +const uart_tx_pin = 0; +const uart_rx_pin = 1; + +pub const log = rp2040.uart.log; + +pub fn init() void { + rp2040.clock_config.apply(); + rp2040.gpio.reset(); + adc.init(); + temp_sensor.init(); + + const uart = rp2040.uart.UART.init(uart_id, .{ + .baud_rate = baud_rate, + .tx_pin = uart_tx_pin, + .rx_pin = uart_rx_pin, + .clock_config = rp2040.clock_config, + }); + + rp2040.uart.initLogger(uart); +} + +pub fn main() void { + while (true) : (time.sleepMs(1000)) { + const sample = temp_sensor.read(); + std.log.info("temp value: {}", .{sample}); + } +} diff --git a/src/hal.zig b/src/hal.zig index 61132bd..06c0cdd 100644 --- a/src/hal.zig +++ b/src/hal.zig @@ -1,6 +1,7 @@ const microzig = @import("microzig"); const regs = microzig.chip.registers; +pub const adc = @import("hal/adc.zig"); pub const pins = @import("hal/pins.zig"); pub const gpio = @import("hal/gpio.zig"); pub const clocks = @import("hal/clocks.zig"); diff --git a/src/hal/adc.zig b/src/hal/adc.zig new file mode 100644 index 0000000..a700651 --- /dev/null +++ b/src/hal/adc.zig @@ -0,0 +1,194 @@ +//! NOTE: no settling time is needed when switching analog inputs + +const std = @import("std"); +const assert = std.debug.assert; + +const microzig = @import("microzig"); +const ADC = microzig.chip.registers.ADC; +const rp2040 = microzig.hal; +const gpio = rp2040.gpio; +const resets = rp2040.resets; + +pub const temperature_sensor = struct { + pub inline fn init() void { + setTempSensorEnabled(true); + } + + pub inline fn deinit() void { + setTempSensorEnabled(false); + } + + pub inline fn readRaw() u16 { + return Input.read(.temperature_sensor); + } + + // One-shot conversion returning the temperature in Celcius + pub inline fn read(comptime T: type, comptime Vref: T) T { + // TODO: consider fixed-point + const raw = @intToFloat(T, readRaw()); + const voltage: T = Vref * raw / 0x0fff; + return (27.0 - ((voltage - 0.706) / 0.001721)); + } +}; + +pub const Input = enum(u3) { + ain0, + ain1, + ain2, + ain3, + temperature_sensor, + + /// Setup the GPIO pin as an ADC input + pub fn init(comptime input: Input) void { + switch (input) { + .temperature_sensor => setTempSensorEnabled(true), + else => { + const gpio_num = @as(u32, @enumToInt(input)) + 26; + + gpio.setFunction(gpio_num, .@"null"); + // TODO: implement these, otherwise adc isn't going to work. + //gpio.disablePulls(gpio_num); + //gpio.setInputEnabled(gpio_num, false); + }, + } + } + + /// Disables temp sensor, otherwise it does nothing if the input is + /// one of the others. + pub inline fn deinit(input: Input) void { + switch (input) { + .temperature_sensor => setTempSensorEnabled(true), + else => {}, + } + } + + /// Single-shot, blocking conversion + pub fn read(input: Input) u12 { + // TODO: not sure if setting these during the same write is + // correct + ADC.CS.modify(.{ + .AINSEL = @enumToInt(input), + .START_ONCE = 1, + }); + + // wait for the + while (ADC.CS.read().READY == 0) {} + + return ADC.RESULT.read(); + } +}; + +pub const InputMask = InputMask: { + const enum_fields = @typeInfo(Input).Enum.fields; + var fields: [enum_fields.len]std.builtin.Type.StructField = undefined; + + const default_value: u1 = 0; + for (enum_fields) |enum_field, i| + fields[i] = std.builtin.Type.StructField{ + .name = enum_field.name, + .field_type = u1, + .default_value = &default_value, + .is_comptime = false, + .alignment = 1, + }; + + break :InputMask @Type(.{ + .Struct = .{ + .layout = .Packed, + .fields = &fields, + .backing_integer = std.meta.Int(.Unsigned, enum_fields.len), + .decls = &.{}, + .is_tuple = false, + }, + }); +}; + +/// Initialize ADC hardware +pub fn init() void { + resets.reset(&.{.adc}); + ADC.CS.write(.{ + .EN = 1, + .TS_EN = 0, + .START_ONCE = 0, + .START_MANY = 0, + .READY = 0, + .ERR = 0, + .ERR_STICKY = 0, + .AINSEL = 0, + .RROBIN = 0, + }); + + while (ADC.CS.read().READY == 0) {} +} + +/// Enable/disable ADC interrupt +pub inline fn irqSetEnabled(enable: bool) void { + // TODO: check if this works + ADC.INTE.write(.{ .FIFO = if (enable) @as(u1, 1) else @as(u1, 0) }); +} + +/// Select analog input for next conversion. +pub inline fn selectInput(input: Input) void { + ADC.CS.modify(.{ .AINSEL = @enumToInt(input) }); +} + +/// Get the currently selected analog input. 0..3 are GPIO 26..29 respectively, +/// 4 is the temperature sensor. +pub inline fn getSelectedInput() Input { + // TODO: ensure that the field shouldn't have other values + return @intToEnum(Input, ADC.CS.read().AINSEL); +} + +/// Set to true to power on the temperature sensor. +pub inline fn setTempSensorEnabled(enable: bool) void { + ADC.CS.modify(.{ .TS_EN = if (enable) @as(u1, 1) else @as(u1, 0) }); +} + +/// Sets which of the inputs are to be run in round-robin mode. Setting all to +/// 0 will disable round-robin mode but `disableRoundRobin()` is provided so +/// the user may be explicit. +pub inline fn setRoundRobin(comptime enabled_inputs: InputMask) void { + ADC.CS.modify(.{ .RROBIN = @bitCast(u5, enabled_inputs) }); +} + +/// Disable round-robin sample mode. +pub inline fn disableRoundRobin() void { + ADC.CS.modify(.{ .RROBIN = 0 }); +} + +/// Enable free-running sample mode. +pub inline fn run(enable: bool) void { + ADC.CS.modify(.{ .START_MANY = if (enable) @as(u1, 1) else @as(u1, 0) }); +} + +/// TODO: implement +pub inline fn setClkDiv() void {} + +/// The fifo is 4 samples long, if a conversion is completed and the FIFO is +/// full, the result is dropped. +pub const fifo = struct { + /// TODO: implement + pub inline fn setup() void { + // There are a number of considerations wrt DMA and error detection + } + + /// TODO: implement + /// Return true if FIFO is empty. + pub inline fn isEmpty() bool {} + + /// TODO: implement + /// Read how many samples are in the FIFO. + pub inline fn getLevel() u8 {} + + /// TODO: implement + /// Pop latest result from FIFO. + pub inline fn get() u16 {} + + /// TODO: implement + /// Block until result is available in FIFO, then pop it. + pub inline fn getBlocking() u16 {} + + /// TODO: implement + /// Wait for conversion to complete then discard results in FIFO. + pub inline fn drain() void {} +}; From 5c853fd23ad400ecb748fba7acb2cc2c0a77c053 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Fri, 30 Sep 2022 12:32:37 -0700 Subject: [PATCH 16/74] use compile errors instead of comments (#15) --- src/hal/adc.zig | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/hal/adc.zig b/src/hal/adc.zig index a700651..84b99a7 100644 --- a/src/hal/adc.zig +++ b/src/hal/adc.zig @@ -161,34 +161,40 @@ pub inline fn run(enable: bool) void { ADC.CS.modify(.{ .START_MANY = if (enable) @as(u1, 1) else @as(u1, 0) }); } -/// TODO: implement -pub inline fn setClkDiv() void {} +pub inline fn setClkDiv() void { + @compileError("todo"); +} /// The fifo is 4 samples long, if a conversion is completed and the FIFO is /// full, the result is dropped. pub const fifo = struct { - /// TODO: implement pub inline fn setup() void { + @compileError("todo"); // There are a number of considerations wrt DMA and error detection } - /// TODO: implement /// Return true if FIFO is empty. - pub inline fn isEmpty() bool {} + pub inline fn isEmpty() bool { + @compileError("todo"); + } - /// TODO: implement /// Read how many samples are in the FIFO. - pub inline fn getLevel() u8 {} + pub inline fn getLevel() u8 { + @compileError("todo"); + } - /// TODO: implement /// Pop latest result from FIFO. - pub inline fn get() u16 {} + pub inline fn get() u16 { + @compileError("todo"); + } - /// TODO: implement /// Block until result is available in FIFO, then pop it. - pub inline fn getBlocking() u16 {} + pub inline fn getBlocking() u16 { + @compileError("todo"); + } - /// TODO: implement /// Wait for conversion to complete then discard results in FIFO. - pub inline fn drain() void {} + pub inline fn drain() void { + @compileError("todo"); + } }; From fe14d4f03b3f2cd5a989bcf497182cd0a140c4ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20=22xq=22=20Quei=C3=9Fner?= Date: Sat, 1 Oct 2022 14:05:57 +0200 Subject: [PATCH 17/74] Implements input, pull up/down and uart routing. --- build.zig | 2 +- src/hal/gpio.zig | 8 ++++++++ src/hal/pins.zig | 43 ++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/build.zig b/build.zig index 889455d..d00c962 100644 --- a/build.zig +++ b/build.zig @@ -3,7 +3,7 @@ const Builder = std.build.Builder; const Pkg = std.build.Pkg; const comptimePrint = std.fmt.comptimePrint; -const microzig = @import("deps/microzig/src/main.zig"); +pub const microzig = @import("deps/microzig/src/main.zig"); const chip_path = comptimePrint("{s}/src/rp2040.zig", .{root()}); const board_path = comptimePrint("{s}/src/raspberry_pi_pico.zig", .{root()}); diff --git a/src/hal/gpio.zig b/src/hal/gpio.zig index 18624ee..90e2141 100644 --- a/src/hal/gpio.zig +++ b/src/hal/gpio.zig @@ -97,6 +97,14 @@ pub inline fn toggle(comptime gpio: u32) void { regs.SIO.GPIO_OUT_XOR.raw = (1 << gpio); } +pub inline fn read(comptime gpio: u32) u1 { + const mask = 1 << gpio; + return if ((regs.SIO.GPIO_IN.raw & mask) != 0) + 1 + else + 0; +} + pub inline fn setFunction(comptime gpio: u32, function: Function) void { const pad_bank_reg = comptime std.fmt.comptimePrint("GPIO{}", .{gpio}); @field(regs.PADS_BANK0, pad_bank_reg).modify(.{ diff --git a/src/hal/pins.zig b/src/hal/pins.zig index baa2479..6980bfc 100644 --- a/src/hal/pins.zig +++ b/src/hal/pins.zig @@ -50,11 +50,15 @@ pub const Pin = enum { // schmitt trigger // hysteresis - pub fn getDirection(config: Configuration) gpio.Direction { + pub fn getDirection(comptime config: Configuration) gpio.Direction { return if (config.direction) |direction| direction - else if (config.function.isPwm()) + else if (comptime config.function.isPwm()) .out + else if (comptime config.function.isUartTx()) + .out + else if (comptime config.function.isUartRx()) + .in else @panic("TODO"); } @@ -157,6 +161,24 @@ pub const Function = enum { }; } + pub fn isUartTx(function: Function) bool { + return switch (function) { + .UART0_TX, + .UART1_TX, + => true, + else => false, + }; + } + + pub fn isUartRx(function: Function) bool { + return switch (function) { + .UART0_RX, + .UART1_RX, + => true, + else => false, + }; + } + pub fn pwmSlice(comptime function: Function) u32 { return switch (function) { .PWM0_A, .PWM0_B => 0, @@ -280,7 +302,7 @@ pub fn GPIO(comptime num: u5, comptime direction: gpio.Direction) type { pub inline fn read(self: @This()) u1 { _ = self; - @compileError("TODO"); + return gpio.read(gpio_num); } }, .out => struct { @@ -424,6 +446,21 @@ pub const GlobalConfiguration = struct { if (output_gpios != 0) regs.SIO.GPIO_OE_SET.raw = output_gpios; + if (input_gpios != 0) { + inline for (@typeInfo(GlobalConfiguration).Struct.fields) |field| + if (@field(config, field.name)) |pin_config| { + const pull = pin_config.pull orelse continue; + if (comptime pin_config.getDirection() != .in) + @compileError("Only input pins can have pull up/down enabled"); + + const gpio_regs = @field(regs.PADS_BANK0, field.name); + gpio_regs.modify(comptime .{ + .PUE = @boolToInt(pull == .up), + .PDE = @boolToInt(pull == .down), + }); + }; + } + // TODO: pwm initialization // fields in the Pins(config) type should be zero sized, so we just From a55df1b52c28a4d0f4eff6e2abfcdeddbf6e5eed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20=22xq=22=20Quei=C3=9Fner?= Date: Sat, 1 Oct 2022 21:03:21 +0200 Subject: [PATCH 18/74] Some debug logs in adc.reset() and resets.reset(), fixes some bugs with booleans. --- src/hal/adc.zig | 5 ++++- src/hal/pwm.zig | 9 +++++---- src/hal/resets.zig | 26 +++++++++++++++++++++++++- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/hal/adc.zig b/src/hal/adc.zig index 84b99a7..92869fc 100644 --- a/src/hal/adc.zig +++ b/src/hal/adc.zig @@ -105,7 +105,9 @@ pub const InputMask = InputMask: { /// Initialize ADC hardware pub fn init() void { + std.log.info("init.a", .{}); resets.reset(&.{.adc}); + std.log.info("init.b", .{}); ADC.CS.write(.{ .EN = 1, .TS_EN = 0, @@ -117,8 +119,9 @@ pub fn init() void { .AINSEL = 0, .RROBIN = 0, }); - + std.log.info("init.c", .{}); while (ADC.CS.read().READY == 0) {} + std.log.info("init.d", .{}); } /// Enable/disable ADC interrupt diff --git a/src/hal/pwm.zig b/src/hal/pwm.zig index 45cf90b..8d28573 100644 --- a/src/hal/pwm.zig +++ b/src/hal/pwm.zig @@ -8,7 +8,8 @@ pub const Config = struct {}; fn getRegs(comptime slice: u32) *volatile Regs { @import("std").debug.assert(slice < 8); - return @intToPtr(*volatile Regs, regs.PWM.base_address); // + (slice * 0x14)); + const reg_diff = comptime (@ptrToInt(regs.PWM.CH1_CSR) - @ptrToInt(regs.PWM.CH0_CSR)); + return @intToPtr(*volatile Regs, regs.PWM.base_address + reg_diff * slice); } pub fn PWM(comptime slice_num: u32, comptime chan: Channel) type { @@ -72,7 +73,7 @@ const Regs = extern struct { pub inline fn setSlicePhaseCorrect(comptime slice: u32, phase_correct: bool) void { log.debug("PWM{} set phase correct: {}", .{ slice, phase_correct }); getRegs(slice).csr.modify(.{ - .PH_CORRECT = if (phase_correct) 1 else 0, + .PH_CORRECT = @boolToInt(phase_correct), }); } @@ -98,10 +99,10 @@ pub inline fn setChannelInversion( ) void { switch (channel) { .a => getRegs(slice).csr.modify(.{ - .A_INV = if (invert) 1 else 0, + .A_INV = @boolToInt(invert), }), .b => getRegs(slice).csr.modifi(.{ - .B_INV = if (invert) 1 else 0, + .B_INV = @boolToInt(invert), }), } } diff --git a/src/hal/resets.zig b/src/hal/resets.zig index 5dbd81e..a4aae84 100644 --- a/src/hal/resets.zig +++ b/src/hal/resets.zig @@ -40,8 +40,32 @@ pub inline fn reset(comptime modules: []const Module) void { @field(mask, @tagName(module)) = 1; const raw_mask = @bitCast(u32, mask); + + // std.log.info("resets done before: {X:0>8} ", .{regs.RESETS.RESET_DONE.raw}); + + // std.log.info("reset on", .{}); regs.RESETS.RESET.raw = raw_mask; + // std.log.info("=> {X:0>8}\n", .{regs.RESETS.RESET.raw}); + // std.log.info("reset off", .{}); + asm volatile ("nop" ::: "memory"); // delay at least a bit regs.RESETS.RESET.raw = 0; + // std.log.info("=> {X:0>8}\n", .{regs.RESETS.RESET.raw}); + + // std.log.info("reset wait", .{}); + + var last: u32 = 0; + while (true) { + const raw = regs.RESETS.RESET_DONE.raw; + if (last != raw) { + // std.log.info("raw: {X:0>8} {X:0>8}", .{ raw, raw & raw_mask }); + last = raw; + } + if ((raw & raw_mask) == raw_mask) + break; + asm volatile ("" ::: "memory"); + } + + // std.log.info("resets done after: {X:0>8}", .{regs.RESETS.RESET_DONE.raw}); - while (regs.RESETS.RESET_DONE.raw & raw_mask != raw_mask) {} + // std.log.info("reset done", .{}); } From c899778c875d103ab243046c6aa64bbddd839e5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20=22xq=22=20Quei=C3=9Fner?= Date: Sun, 2 Oct 2022 00:10:13 +0200 Subject: [PATCH 19/74] Clock setup fixes. --- src/hal/clocks.zig | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/hal/clocks.zig b/src/hal/clocks.zig index 3553572..eae16a8 100644 --- a/src/hal/clocks.zig +++ b/src/hal/clocks.zig @@ -56,8 +56,8 @@ fn uppercase(bytes: []const u8) std.fmt.Formatter(formatUppercase) { return .{ .data = bytes }; } -pub const Generator = enum { - gpout0, +pub const Generator = enum(u32) { + gpout0 = 0, gpout1, gpout2, gpout3, @@ -70,7 +70,7 @@ pub const Generator = enum { // in some cases we can pretend the Generators are a homogenous array of // register clusters for the sake of smaller codegen - const GeneratorRegs = packed struct { + const GeneratorRegs = extern struct { ctrl: u32, div: u32, selected: u32, @@ -82,7 +82,7 @@ pub const Generator = enum { } const generators = @intToPtr( - *volatile [9]GeneratorRegs, + *volatile [10]GeneratorRegs, regs.CLOCKS.base_address, ); @@ -154,6 +154,7 @@ pub const Generator = enum { } pub fn setSource(generator: Generator, src: u32) void { + std.debug.assert(generator.hasGlitchlessMux()); const gen_regs = generator.getRegs(); const mask = ~@as(u32, 0x3); const ctrl_value = gen_regs.ctrl; @@ -314,9 +315,12 @@ pub const GlobalConfiguration = struct { .clk_sys => if (config.sys) |sys_config| sys_config.output_freq else null, .clk_usb => if (config.usb) |usb_config| usb_config.output_freq else null, .clk_ref => if (config.ref) |ref_config| ref_config.output_freq else null, + .clk_adc => if (config.adc) |adc_config| adc_config.output_freq else null, + .clk_rtc => if (config.rtc) |rtc_config| rtc_config.output_freq else null, .pll_sys => if (config.pll_sys) |pll_sys_config| pll_sys_config.frequency() else null, .pll_usb => if (config.pll_usb) |pll_usb_config| pll_usb_config.frequency() else null, - else => null, + + .src_gpin0, .src_gpin1 => null, }; } @@ -462,7 +466,7 @@ pub const GlobalConfiguration = struct { } break :adc_config .{ - .generator = .usb, + .generator = .adc, .input = .{ .source = .pll_usb, .freq = 48_000_000, @@ -493,7 +497,7 @@ pub const GlobalConfiguration = struct { } break :rtc_config .{ - .generator = .usb, + .generator = .rtc, .input = .{ .source = .pll_usb, .freq = 48_000_000, From 5c07800cdbf9b4369f6442482729e766a180a97b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20=22xq=22=20Quei=C3=9Fner?= Date: Sun, 2 Oct 2022 00:14:52 +0200 Subject: [PATCH 20/74] Removes debug code. --- src/hal/adc.zig | 4 ---- src/hal/resets.zig | 25 +------------------------ 2 files changed, 1 insertion(+), 28 deletions(-) diff --git a/src/hal/adc.zig b/src/hal/adc.zig index 92869fc..3cf29fa 100644 --- a/src/hal/adc.zig +++ b/src/hal/adc.zig @@ -105,9 +105,7 @@ pub const InputMask = InputMask: { /// Initialize ADC hardware pub fn init() void { - std.log.info("init.a", .{}); resets.reset(&.{.adc}); - std.log.info("init.b", .{}); ADC.CS.write(.{ .EN = 1, .TS_EN = 0, @@ -119,9 +117,7 @@ pub fn init() void { .AINSEL = 0, .RROBIN = 0, }); - std.log.info("init.c", .{}); while (ADC.CS.read().READY == 0) {} - std.log.info("init.d", .{}); } /// Enable/disable ADC interrupt diff --git a/src/hal/resets.zig b/src/hal/resets.zig index a4aae84..45b2230 100644 --- a/src/hal/resets.zig +++ b/src/hal/resets.zig @@ -41,31 +41,8 @@ pub inline fn reset(comptime modules: []const Module) void { const raw_mask = @bitCast(u32, mask); - // std.log.info("resets done before: {X:0>8} ", .{regs.RESETS.RESET_DONE.raw}); - - // std.log.info("reset on", .{}); regs.RESETS.RESET.raw = raw_mask; - // std.log.info("=> {X:0>8}\n", .{regs.RESETS.RESET.raw}); - // std.log.info("reset off", .{}); - asm volatile ("nop" ::: "memory"); // delay at least a bit regs.RESETS.RESET.raw = 0; - // std.log.info("=> {X:0>8}\n", .{regs.RESETS.RESET.raw}); - - // std.log.info("reset wait", .{}); - - var last: u32 = 0; - while (true) { - const raw = regs.RESETS.RESET_DONE.raw; - if (last != raw) { - // std.log.info("raw: {X:0>8} {X:0>8}", .{ raw, raw & raw_mask }); - last = raw; - } - if ((raw & raw_mask) == raw_mask) - break; - asm volatile ("" ::: "memory"); - } - - // std.log.info("resets done after: {X:0>8}", .{regs.RESETS.RESET_DONE.raw}); - // std.log.info("reset done", .{}); + while ((regs.RESETS.RESET_DONE.raw & raw_mask) != raw_mask) {} } From 86d383e67366dd691974f3688cb40759169f41c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20=22xq=22=20Quei=C3=9Fner?= Date: Sun, 2 Oct 2022 16:57:26 +0200 Subject: [PATCH 21/74] Implements ADC and PWM support in pin config, simplifies Pins() type. --- src/hal/gpio.zig | 2 +- src/hal/pins.zig | 180 +++++++++++++++++++++++++++++++++-------------- src/hal/uart.zig | 8 +-- 3 files changed, 134 insertions(+), 56 deletions(-) diff --git a/src/hal/gpio.zig b/src/hal/gpio.zig index 90e2141..eebb093 100644 --- a/src/hal/gpio.zig +++ b/src/hal/gpio.zig @@ -7,7 +7,7 @@ const assert = std.debug.assert; const log = std.log.scoped(.gpio); pub const Function = enum(u5) { - xip, + xip = 0, spi, uart, i2c, diff --git a/src/hal/pins.zig b/src/hal/pins.zig index 6980bfc..9194a01 100644 --- a/src/hal/pins.zig +++ b/src/hal/pins.zig @@ -1,6 +1,8 @@ const std = @import("std"); const gpio = @import("gpio.zig"); const pwm = @import("pwm.zig"); +const adc = @import("adc.zig"); +const resets = @import("resets.zig"); const regs = @import("microzig").chip.registers; const assert = std.debug.assert; @@ -59,6 +61,8 @@ pub const Pin = enum { .out else if (comptime config.function.isUartRx()) .in + else if (comptime config.function.isAdc()) + .in else @panic("TODO"); } @@ -193,6 +197,17 @@ pub const Function = enum { }; } + pub fn isAdc(function: Function) bool { + return switch (function) { + .ADC0, + .ADC1, + .ADC2, + .ADC3, + => true, + else => false, + }; + } + pub fn pwmChannel(comptime function: Function) pwm.Channel { return switch (function) { .PWM0_A, @@ -322,53 +337,66 @@ pub fn GPIO(comptime num: u5, comptime direction: gpio.Direction) type { } pub fn Pins(comptime config: GlobalConfiguration) type { - const count = count: { - var ret: usize = 0; - inline for (@typeInfo(GlobalConfiguration).Struct.fields) |field| { - if (@field(config, field.name)) |pin_config| - if (pin_config.function == .SIO or pin_config.function.isPwm()) { - ret += 1; - }; - } - - break :count ret; - }; - - var i: usize = 0; - var fields: [count]StructField = undefined; - inline for (@typeInfo(GlobalConfiguration).Struct.fields) |field| { - if (@field(config, field.name)) |pin_config| - if (pin_config.function == .SIO) { - fields[i] = StructField{ - .name = pin_config.name orelse field.name, - .field_type = GPIO(@enumToInt(@field(Pin, field.name)), pin_config.direction orelse .in), + comptime { + var fields: []const StructField = &.{}; + for (@typeInfo(GlobalConfiguration).Struct.fields) |field| { + if (@field(config, field.name)) |pin_config| { + var pin_field = StructField{ .is_comptime = false, .default_value = null, - .alignment = 1, - }; - i += 1; - } else if (pin_config.function.isPwm()) { - fields[i] = StructField{ - .name = pin_config.name orelse @tagName(pin_config.function), - .field_type = pwm.PWM(pin_config.function.pwmSlice(), pin_config.function.pwmChannel()), - .is_comptime = false, - .default_value = null, - .alignment = 1, + // initialized below: + .name = undefined, + .field_type = undefined, + .alignment = undefined, }; - i += 1; - }; - } + if (pin_config.function == .SIO) { + pin_field.name = pin_config.name orelse field.name; + pin_field.field_type = GPIO(@enumToInt(@field(Pin, field.name)), pin_config.direction orelse .in); + } else if (pin_config.function.isPwm()) { + pin_field.name = pin_config.name orelse @tagName(pin_config.function); + pin_field.field_type = pwm.PWM(pin_config.function.pwmSlice(), pin_config.function.pwmChannel()); + } else if (pin_config.function.isAdc()) { + pin_field.name = pin_config.name orelse @tagName(pin_config.function); + pin_field.field_type = adc.Input; + pin_field.default_value = @ptrCast(?*const anyopaque, switch (pin_config.function) { + .ADC0 => &adc.Input.ain0, + .ADC1 => &adc.Input.ain1, + .ADC2 => &adc.Input.ain2, + .ADC3 => &adc.Input.ain3, + else => unreachable, + }); + } else { + continue; + } + + // if (pin_field.default_value == null) { + // if (@sizeOf(pin_field.field_type) > 0) { + // pin_field.default_value = @ptrCast(?*const anyopaque, &pin_field.field_type{}); + // } else { + // const Struct = struct { + // magic_field: pin_field.field_type = .{}, + // }; + // pin_field.default_value = @typeInfo(Struct).Struct.fields[0].default_value; + // } + // } + + pin_field.alignment = @alignOf(field.field_type); + + fields = fields ++ &[_]StructField{pin_field}; + } + } - return @Type(.{ - .Struct = .{ - .layout = .Auto, - .is_tuple = false, - .fields = &fields, - .decls = &.{}, - }, - }); + return @Type(.{ + .Struct = .{ + .layout = .Auto, + .is_tuple = false, + .fields = fields, + .decls = &.{}, + }, + }); + } } pub const GlobalConfiguration = struct { @@ -413,6 +441,8 @@ pub const GlobalConfiguration = struct { pub fn apply(comptime config: GlobalConfiguration) Pins(config) { comptime var input_gpios: u32 = 0; comptime var output_gpios: u32 = 0; + comptime var has_adc = false; + comptime var has_pwm = false; // validate selected function comptime { @@ -422,12 +452,22 @@ pub const GlobalConfiguration = struct { if (0 == function_table[@enumToInt(pin_config.function)][gpio_num]) @compileError(comptimePrint("{s} cannot be configured for {}", .{ field.name, pin_config.function })); - switch (pin_config.getDirection()) { - .in => input_gpios |= 1 << gpio_num, - .out => output_gpios |= 1 << gpio_num, + if (pin_config.function == .SIO) { + switch (pin_config.getDirection()) { + .in => input_gpios |= 1 << gpio_num, + .out => output_gpios |= 1 << gpio_num, + } + } + + if (pin_config.function.isAdc()) { + has_adc = true; + } + if (pin_config.function.isPwm()) { + has_pwm = true; } }; } + // TODO: ensure only one instance of an input function exists const used_gpios = comptime input_gpios | output_gpios; @@ -436,11 +476,38 @@ pub const GlobalConfiguration = struct { if (used_gpios != 0) { regs.SIO.GPIO_OE_CLR.raw = used_gpios; regs.SIO.GPIO_OUT_CLR.raw = used_gpios; + } - comptime var i: u32 = 0; - inline while (i < 32) : (i += 1) - if (0 != used_gpios & 1 << i) - gpio.setFunction(i, .sio); + inline for (@typeInfo(GlobalConfiguration).Struct.fields) |field| { + if (@field(config, field.name)) |pin_config| { + const gpio_num = @enumToInt(@field(Pin, field.name)); + const func = pin_config.function; + + // xip = 0, + // spi, + // uart, + // i2c, + // pio0, + // pio1, + // gpck, + // usb, + // @"null" = 0x1f, + + if (func == .SIO) { + gpio.setFunction(gpio_num, .sio); + } else if (comptime func.isPwm()) { + gpio.setFunction(gpio_num, .pwm); + } else if (comptime func.isAdc()) { + gpio.setFunction(gpio_num, .@"null"); + } else if (comptime func.isUartTx() or func.isUartRx()) { + gpio.setFunction(gpio_num, .uart); + } else { + @compileError(comptime std.fmt.comptimePrint("Unimplemented pin function. Please implement setting pin function {s} for GPIO {}", .{ + @tagName(func), + gpio_num, + })); + } + } } if (output_gpios != 0) @@ -461,14 +528,25 @@ pub const GlobalConfiguration = struct { }; } - // TODO: pwm initialization + if (has_pwm) { + resets.reset(&.{.pwm}); + } + + if (has_adc) { + adc.init(); + } // fields in the Pins(config) type should be zero sized, so we just // default build them all (wasn't sure how to do that cleanly in // `Pins()` var ret: Pins(config) = undefined; - inline for (@typeInfo(Pins(config)).Struct.fields) |field| - @field(ret, field.name) = .{}; + inline for (@typeInfo(Pins(config)).Struct.fields) |field| { + if (field.default_value) |default_value| { + @field(ret, field.name) = @ptrCast(*const field.field_type, default_value).*; + } else { + @field(ret, field.name) = .{}; + } + } return ret; } diff --git a/src/hal/uart.zig b/src/hal/uart.zig index 5f3f8c6..49de5fc 100644 --- a/src/hal/uart.zig +++ b/src/hal/uart.zig @@ -28,8 +28,8 @@ pub const Parity = enum { pub const Config = struct { clock_config: clocks.GlobalConfiguration, - tx_pin: u32, - rx_pin: u32, + tx_pin: ?u32 = null, + rx_pin: ?u32 = null, baud_rate: u32, word_bits: WordBits = .eight, stop_bits: StopBits = .one, @@ -116,8 +116,8 @@ pub const UART = enum { }); // TODO comptime assertions - gpio.setFunction(config.tx_pin, .uart); - gpio.setFunction(config.rx_pin, .uart); + if (config.tx_pin) |tx_pin| gpio.setFunction(tx_pin, .uart); + if (config.rx_pin) |rx_pin| gpio.setFunction(rx_pin, .uart); return uart; } From 7b69211d4113cf2914a3e5c400357cea46b81ffa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20=22xq=22=20Quei=C3=9Fner?= Date: Mon, 3 Oct 2022 18:14:37 +0200 Subject: [PATCH 22/74] Implements gpio.setPullUpDown --- src/hal/gpio.zig | 17 +++++++++++++++++ src/hal/pins.zig | 9 +++------ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/hal/gpio.zig b/src/hal/gpio.zig index eebb093..e725d79 100644 --- a/src/hal/gpio.zig +++ b/src/hal/gpio.zig @@ -75,6 +75,23 @@ pub inline fn deinit(comptime gpio: u32) void { setFunction(gpio, .@"null"); } +pub const PullUpDown = enum { + up, + down, +}; + +pub inline fn setPullUpDown(comptime gpio: u32, mode: ?PullUpDown) void { + const gpio_name = comptime std.fmt.comptimePrint("GPIO{d}", .{gpio}); + const gpio_regs = @field(regs.PADS_BANK0, gpio_name); + + if (mode == null) { + gpio_regs.modify(.{ .PUE = 0, .PDE = 0 }); + } else switch (mode.?) { + .up => gpio_regs.modify(.{ .PUE = 1, .PDE = 0 }), + .down => gpio_regs.modify(.{ .PUE = 0, .PDE = 1 }), + } +} + pub inline fn setDir(comptime gpio: u32, direction: Direction) void { const mask = 1 << gpio; switch (direction) { diff --git a/src/hal/pins.zig b/src/hal/pins.zig index 9194a01..94f6caa 100644 --- a/src/hal/pins.zig +++ b/src/hal/pins.zig @@ -46,7 +46,7 @@ pub const Pin = enum { function: Function = .SIO, direction: ?gpio.Direction = null, drive_strength: ?gpio.DriveStrength = null, - pull: ?enum { up, down } = null, + pull: ?gpio.PullUpDown = null, slew_rate: ?gpio.SlewRate = null, // input/output enable // schmitt trigger @@ -516,15 +516,12 @@ pub const GlobalConfiguration = struct { if (input_gpios != 0) { inline for (@typeInfo(GlobalConfiguration).Struct.fields) |field| if (@field(config, field.name)) |pin_config| { + const gpio_num = @enumToInt(@field(Pin, field.name)); const pull = pin_config.pull orelse continue; if (comptime pin_config.getDirection() != .in) @compileError("Only input pins can have pull up/down enabled"); - const gpio_regs = @field(regs.PADS_BANK0, field.name); - gpio_regs.modify(comptime .{ - .PUE = @boolToInt(pull == .up), - .PDE = @boolToInt(pull == .down), - }); + gpio.setPullUpDown(gpio_num, pull); }; } From b0b90a7cf07704dfef94b17b8be2393479c68192 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20=22xq=22=20Quei=C3=9Fner?= Date: Mon, 3 Oct 2022 19:11:42 +0200 Subject: [PATCH 23/74] Implements UART.reader() --- deps/microzig | 2 +- src/hal/uart.zig | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/deps/microzig b/deps/microzig index 681b3b0..15bc1fc 160000 --- a/deps/microzig +++ b/deps/microzig @@ -1 +1 @@ -Subproject commit 681b3b0d7a6b2fc5d0f8918c583c790c646a31f1 +Subproject commit 15bc1fc06da3b6c622a21fa438e40be247d9dee1 diff --git a/src/hal/uart.zig b/src/hal/uart.zig index 49de5fc..3285249 100644 --- a/src/hal/uart.zig +++ b/src/hal/uart.zig @@ -75,12 +75,18 @@ pub const UART = enum { uart1, const WriteError = error{}; + const ReadError = error{}; pub const Writer = std.io.Writer(UART, WriteError, write); + pub const Reader = std.io.Reader(UART, ReadError, read); pub fn writer(uart: UART) Writer { return .{ .context = uart }; } + pub fn reader(uart: UART) Reader { + return .{ .context = uart }; + } + fn getRegs(uart: UART) *volatile UartRegs { return &uarts[@enumToInt(uart)]; } @@ -142,6 +148,15 @@ pub const UART = enum { return payload.len; } + pub fn read(uart: UART, buffer: []u8) ReadError!usize { + const uart_regs = uart.getRegs(); + for (buffer) |*byte| { + while (!uart.isReadable()) {} + byte.* = @truncate(u8, uart_regs.dr); + } + return buffer.len; + } + pub fn readWord(uart: UART) u8 { const uart_regs = uart.getRegs(); while (!uart.isReadable()) {} From e9af302b69a58a50b25cda9c75580702df859b5d Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Wed, 5 Oct 2022 10:58:03 +0200 Subject: [PATCH 24/74] uart improvements and improved definition of how many clock units there are (#16) --- src/hal/clocks.zig | 2 +- src/hal/uart.zig | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/hal/clocks.zig b/src/hal/clocks.zig index eae16a8..e703db4 100644 --- a/src/hal/clocks.zig +++ b/src/hal/clocks.zig @@ -82,7 +82,7 @@ pub const Generator = enum(u32) { } const generators = @intToPtr( - *volatile [10]GeneratorRegs, + *volatile [@typeInfo(Generator).Enum.fields.len]GeneratorRegs, regs.CLOCKS.base_address, ); diff --git a/src/hal/uart.zig b/src/hal/uart.zig index 3285249..6616452 100644 --- a/src/hal/uart.zig +++ b/src/hal/uart.zig @@ -226,6 +226,7 @@ var uart_logger: ?UART.Writer = null; pub fn initLogger(uart: UART) void { uart_logger = uart.writer(); + uart_logger.?.writeAll("\r\n================ STARTING NEW LOGGER ================\r\n") catch {}; } pub fn log( @@ -248,3 +249,16 @@ pub fn log( uart.print(prefix ++ format ++ "\r\n", .{ seconds, microseconds } ++ args) catch {}; } } + +pub fn panic( + message: []const u8, + _: ?*std.builtin.StackTrace, + _: ?usize, +) noreturn { + if (uart_logger) |writer| { + writer.print("PANIC: {s}\r\n", .{message}) catch {}; + } + + @breakpoint(); + while (true) {} +} From 144d557357314f25dd479e28ef1e16f157f0bb50 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Sat, 8 Oct 2022 11:41:01 +0200 Subject: [PATCH 25/74] remove hal.uart.panic --- src/hal/uart.zig | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/hal/uart.zig b/src/hal/uart.zig index 6616452..d1ca419 100644 --- a/src/hal/uart.zig +++ b/src/hal/uart.zig @@ -249,16 +249,3 @@ pub fn log( uart.print(prefix ++ format ++ "\r\n", .{ seconds, microseconds } ++ args) catch {}; } } - -pub fn panic( - message: []const u8, - _: ?*std.builtin.StackTrace, - _: ?usize, -) noreturn { - if (uart_logger) |writer| { - writer.print("PANIC: {s}\r\n", .{message}) catch {}; - } - - @breakpoint(); - while (true) {} -} From 0713809eaf2eab45b06166f9d33ad3d996601822 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Sun, 1 Jan 2023 13:00:47 -0800 Subject: [PATCH 26/74] catch up to master (#17) --- deps/microzig | 2 +- src/hal/multicore.zig | 8 ++++---- src/hal/pins.zig | 14 +++++++------- src/rp2040.zig | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/deps/microzig b/deps/microzig index 15bc1fc..4f0d252 160000 --- a/deps/microzig +++ b/deps/microzig @@ -1 +1 @@ -Subproject commit 15bc1fc06da3b6c622a21fa438e40be247d9dee1 +Subproject commit 4f0d25220ec8f0501f8e0e9f6765689eb32faa5f diff --git a/src/hal/multicore.zig b/src/hal/multicore.zig index 76811cf..f1bcfe0 100644 --- a/src/hal/multicore.zig +++ b/src/hal/multicore.zig @@ -55,18 +55,18 @@ pub const fifo = struct { var core1_stack: [128]u32 = undefined; /// Runs `entrypoint` on the second core. -pub fn launchCore1(entrypoint: fn () void) void { +pub fn launchCore1(entrypoint: *const fn () void) void { launchCore1WithStack(entrypoint, &core1_stack); } -pub fn launchCore1WithStack(entrypoint: fn () void, stack: []u32) void { +pub fn launchCore1WithStack(entrypoint: *const fn () void, stack: []u32) void { // TODO: disable SIO interrupts - const wrapper = struct { + const wrapper = &struct { fn wrapper(_: u32, _: u32, _: u32, _: u32, entry: u32, stack_base: [*]u32) callconv(.C) void { // TODO: protect stack using MPU _ = stack_base; - @intToPtr(fn () void, entry)(); + @intToPtr(*const fn () void, entry)(); } }.wrapper; diff --git a/src/hal/pins.zig b/src/hal/pins.zig index 94f6caa..dce1c24 100644 --- a/src/hal/pins.zig +++ b/src/hal/pins.zig @@ -347,19 +347,19 @@ pub fn Pins(comptime config: GlobalConfiguration) type { // initialized below: .name = undefined, - .field_type = undefined, + .type = undefined, .alignment = undefined, }; if (pin_config.function == .SIO) { pin_field.name = pin_config.name orelse field.name; - pin_field.field_type = GPIO(@enumToInt(@field(Pin, field.name)), pin_config.direction orelse .in); + pin_field.type = GPIO(@enumToInt(@field(Pin, field.name)), pin_config.direction orelse .in); } else if (pin_config.function.isPwm()) { pin_field.name = pin_config.name orelse @tagName(pin_config.function); - pin_field.field_type = pwm.PWM(pin_config.function.pwmSlice(), pin_config.function.pwmChannel()); + pin_field.type = pwm.PWM(pin_config.function.pwmSlice(), pin_config.function.pwmChannel()); } else if (pin_config.function.isAdc()) { pin_field.name = pin_config.name orelse @tagName(pin_config.function); - pin_field.field_type = adc.Input; + pin_field.type = adc.Input; pin_field.default_value = @ptrCast(?*const anyopaque, switch (pin_config.function) { .ADC0 => &adc.Input.ain0, .ADC1 => &adc.Input.ain1, @@ -382,7 +382,7 @@ pub fn Pins(comptime config: GlobalConfiguration) type { // } // } - pin_field.alignment = @alignOf(field.field_type); + pin_field.alignment = @alignOf(field.type); fields = fields ++ &[_]StructField{pin_field}; } @@ -498,11 +498,11 @@ pub const GlobalConfiguration = struct { } else if (comptime func.isPwm()) { gpio.setFunction(gpio_num, .pwm); } else if (comptime func.isAdc()) { - gpio.setFunction(gpio_num, .@"null"); + gpio.setFunction(gpio_num, .null); } else if (comptime func.isUartTx() or func.isUartRx()) { gpio.setFunction(gpio_num, .uart); } else { - @compileError(comptime std.fmt.comptimePrint("Unimplemented pin function. Please implement setting pin function {s} for GPIO {}", .{ + @compileError(std.fmt.comptimePrint("Unimplemented pin function. Please implement setting pin function {s} for GPIO {}", .{ @tagName(func), gpio_num, })); diff --git a/src/rp2040.zig b/src/rp2040.zig index 6301bf2..d3c2e18 100644 --- a/src/rp2040.zig +++ b/src/rp2040.zig @@ -28780,8 +28780,8 @@ pub fn mmioInt(addr: usize, comptime size: usize, comptime T: type) *volatile Mm } pub const InterruptVector = extern union { - C: fn () callconv(.C) void, - Naked: fn () callconv(.Naked) void, + C: *const fn () callconv(.C) void, + Naked: *const fn () callconv(.Naked) void, // Interrupt is not supported on arm }; From e3562492df5e3f564e5804eca073efe8aa68e88b Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Tue, 14 Feb 2023 21:00:04 +0200 Subject: [PATCH 27/74] update to master (#19) --- build.zig | 18 ++++++++++-------- deps/microzig | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/build.zig b/build.zig index d00c962..35bad24 100644 --- a/build.zig +++ b/build.zig @@ -10,13 +10,15 @@ const board_path = comptimePrint("{s}/src/raspberry_pi_pico.zig", .{root()}); const hal_path = comptimePrint("{s}/src/hal.zig", .{root()}); const linkerscript_path = comptimePrint("{s}/rp2040.ld", .{root()}); -pub const BuildOptions = struct {}; +pub const BuildOptions = struct { + optimize: std.builtin.OptimizeMode, +}; pub fn addPiPicoExecutable( builder: *Builder, name: []const u8, source: []const u8, - _: BuildOptions, + options: BuildOptions, ) microzig.EmbeddedExecutable { const rp2040 = microzig.Chip{ .name = "RP2040", @@ -41,7 +43,8 @@ pub fn addPiPicoExecutable( source, .{ .board = raspberry_pi_pico }, .{ - .hal_package_path = .{ .path = hal_path }, + .optimize = options.optimize, + .hal_module_path = .{ .path = hal_path }, }, ); ret.inner.setLinkerScriptPath(.{ .path = linkerscript_path }); @@ -53,8 +56,8 @@ pub fn addPiPicoExecutable( // package. In an attempt to modularize -- designing for a case where a // project requires multiple HALs, it accepts microzig as a param pub fn build(b: *Builder) !void { - const mode = b.standardReleaseOptions(); - var examples = Examples.init(b, mode); + const optimize = b.standardOptimizeOption(.{}); + var examples = Examples.init(b, optimize); examples.install(); } @@ -71,16 +74,15 @@ pub const Examples = struct { uart: microzig.EmbeddedExecutable, //uart_pins: microzig.EmbeddedExecutable, - pub fn init(b: *Builder, mode: std.builtin.Mode) Examples { + pub fn init(b: *Builder, optimize: std.builtin.OptimizeMode) Examples { var ret: Examples = undefined; inline for (@typeInfo(Examples).Struct.fields) |field| { @field(ret, field.name) = addPiPicoExecutable( b, field.name, comptime root() ++ "/examples/" ++ field.name ++ ".zig", - .{}, + .{ .optimize = optimize }, ); - @field(ret, field.name).setBuildMode(mode); } return ret; diff --git a/deps/microzig b/deps/microzig index 4f0d252..9ccde9f 160000 --- a/deps/microzig +++ b/deps/microzig @@ -1 +1 @@ -Subproject commit 4f0d25220ec8f0501f8e0e9f6765689eb32faa5f +Subproject commit 9ccde9ff371b355394f65eacb6b51c5880768505 From 7d81ecf65473cfa19ae7f8cbe9a7961dd79371d0 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Sun, 19 Feb 2023 09:39:12 -0500 Subject: [PATCH 28/74] Regz rewrite (#20) * update to new regz output * snake case * update with changes to microzig * remove symlink * add microzig submodule --- build.zig | 48 +- deps/microzig | 2 +- examples/adc.zig | 4 +- examples/blinky.zig | 2 +- examples/blinky_core1.zig | 8 +- examples/gpio_clk.zig | 2 +- examples/pwm.zig | 6 +- examples/uart.zig | 8 +- src/boards.zig | 15 + src/{ => boards}/raspberry_pi_pico.zig | 0 src/chips.zig | 25 + src/chips/RP2040.json | 43672 +++++++++++++++++++++++ src/chips/RP2040.zig | 18145 ++++++++++ src/hal.zig | 2 +- src/hal/adc.zig | 43 +- src/hal/clocks.zig | 150 +- src/hal/gpio.zig | 59 +- src/hal/irq.zig | 6 +- src/hal/multicore.zig | 46 +- src/hal/pins.zig | 66 +- src/hal/pll.zig | 78 +- src/hal/pwm.zig | 69 +- src/hal/resets.zig | 14 +- src/hal/time.zig | 24 +- src/hal/uart.zig | 121 +- src/hal/util.zig | 8 +- src/rp2040.zig | 28794 --------------- 27 files changed, 62224 insertions(+), 29193 deletions(-) create mode 100644 src/boards.zig rename src/{ => boards}/raspberry_pi_pico.zig (100%) create mode 100644 src/chips.zig create mode 100644 src/chips/RP2040.json create mode 100644 src/chips/RP2040.zig delete mode 100644 src/rp2040.zig diff --git a/build.zig b/build.zig index 35bad24..51bb874 100644 --- a/build.zig +++ b/build.zig @@ -5,10 +5,10 @@ const comptimePrint = std.fmt.comptimePrint; pub const microzig = @import("deps/microzig/src/main.zig"); -const chip_path = comptimePrint("{s}/src/rp2040.zig", .{root()}); -const board_path = comptimePrint("{s}/src/raspberry_pi_pico.zig", .{root()}); -const hal_path = comptimePrint("{s}/src/hal.zig", .{root()}); -const linkerscript_path = comptimePrint("{s}/rp2040.ld", .{root()}); +const chips = @import("src/chips.zig"); +const boards = @import("src/boards.zig"); + +const linkerscript_path = root() ++ "rp2040.ld"; pub const BuildOptions = struct { optimize: std.builtin.OptimizeMode, @@ -19,32 +19,14 @@ pub fn addPiPicoExecutable( name: []const u8, source: []const u8, options: BuildOptions, -) microzig.EmbeddedExecutable { - const rp2040 = microzig.Chip{ - .name = "RP2040", - .path = chip_path, - .cpu = microzig.cpus.cortex_m0plus, - .memory_regions = &.{ - .{ .kind = .flash, .offset = 0x10000100, .length = (2048 * 1024) - 256 }, - .{ .kind = .flash, .offset = 0x10000000, .length = 256 }, - .{ .kind = .ram, .offset = 0x20000000, .length = 256 * 1024 }, - }, - }; - - const raspberry_pi_pico = microzig.Board{ - .name = "Raspberry Pi Pico", - .path = board_path, - .chip = rp2040, - }; - +) *microzig.EmbeddedExecutable { const ret = microzig.addEmbeddedExecutable( builder, name, source, - .{ .board = raspberry_pi_pico }, + .{ .board = boards.raspberry_pi_pico }, .{ .optimize = options.optimize, - .hal_module_path = .{ .path = hal_path }, }, ); ret.inner.setLinkerScriptPath(.{ .path = linkerscript_path }); @@ -62,25 +44,27 @@ pub fn build(b: *Builder) !void { } fn root() []const u8 { - return std.fs.path.dirname(@src().file) orelse "."; + return comptime (std.fs.path.dirname(@src().file) orelse ".") ++ "/"; } pub const Examples = struct { - adc: microzig.EmbeddedExecutable, - blinky: microzig.EmbeddedExecutable, - blinky_core1: microzig.EmbeddedExecutable, - gpio_clk: microzig.EmbeddedExecutable, - pwm: microzig.EmbeddedExecutable, - uart: microzig.EmbeddedExecutable, + adc: *microzig.EmbeddedExecutable, + blinky: *microzig.EmbeddedExecutable, + blinky_core1: *microzig.EmbeddedExecutable, + gpio_clk: *microzig.EmbeddedExecutable, + pwm: *microzig.EmbeddedExecutable, + uart: *microzig.EmbeddedExecutable, //uart_pins: microzig.EmbeddedExecutable, pub fn init(b: *Builder, optimize: std.builtin.OptimizeMode) Examples { var ret: Examples = undefined; inline for (@typeInfo(Examples).Struct.fields) |field| { + const path = comptime root() ++ "examples/" ++ field.name ++ ".zig"; + @field(ret, field.name) = addPiPicoExecutable( b, field.name, - comptime root() ++ "/examples/" ++ field.name ++ ".zig", + path, .{ .optimize = optimize }, ); } diff --git a/deps/microzig b/deps/microzig index 9ccde9f..2d0ee5c 160000 --- a/deps/microzig +++ b/deps/microzig @@ -1 +1 @@ -Subproject commit 9ccde9ff371b355394f65eacb6b51c5880768505 +Subproject commit 2d0ee5c4731de1d81afb9c8e08ba4e8c2c2cfbf3 diff --git a/examples/adc.zig b/examples/adc.zig index f8e8c66..9800e91 100644 --- a/examples/adc.zig +++ b/examples/adc.zig @@ -27,11 +27,11 @@ pub fn init() void { .clock_config = rp2040.clock_config, }); - rp2040.uart.initLogger(uart); + rp2040.uart.init_logger(uart); } pub fn main() void { - while (true) : (time.sleepMs(1000)) { + while (true) : (time.sleep_ms(1000)) { const sample = temp_sensor.read(); std.log.info("temp value: {}", .{sample}); } diff --git a/examples/blinky.zig b/examples/blinky.zig index ea3f2d8..5632fe3 100644 --- a/examples/blinky.zig +++ b/examples/blinky.zig @@ -15,6 +15,6 @@ pub fn main() !void { while (true) { pins.led.toggle(); - time.sleepMs(250); + time.sleep_ms(250); } } diff --git a/examples/blinky_core1.zig b/examples/blinky_core1.zig index a549f30..b3fdd04 100644 --- a/examples/blinky_core1.zig +++ b/examples/blinky_core1.zig @@ -11,17 +11,17 @@ const led = 25; fn core1() void { while (true) { gpio.put(led, 1); - time.sleepMs(250); + time.sleep_ms(250); gpio.put(led, 0); - time.sleepMs(250); + time.sleep_ms(250); } } pub fn main() !void { gpio.init(led); - gpio.setDir(led, .out); + gpio.set_direction(led, .out); - multicore.launchCore1(core1); + multicore.launch_core1(core1); while (true) { microzig.cpu.wfi(); diff --git a/examples/gpio_clk.zig b/examples/gpio_clk.zig index 52280e4..e66761c 100644 --- a/examples/gpio_clk.zig +++ b/examples/gpio_clk.zig @@ -16,6 +16,6 @@ pub fn init() void { } pub fn main() !void { - gpio.setFunction(gpout0_pin, .gpck); + gpio.set_function(gpout0_pin, .gpck); while (true) {} } diff --git a/examples/pwm.zig b/examples/pwm.zig index 9eff043..d372ef4 100644 --- a/examples/pwm.zig +++ b/examples/pwm.zig @@ -13,11 +13,11 @@ const pin_config = rp2040.pins.GlobalConfiguration{ pub fn main() !void { const pins = pin_config.apply(); - pins.led.slice().setWrap(100); - pins.led.setLevel(10); + pins.led.slice().set_wrap(100); + pins.led.set_level(10); pins.led.slice().enable(); while (true) { - time.sleepMs(250); + time.sleep_ms(250); } } diff --git a/examples/uart.zig b/examples/uart.zig index 7ccbe69..6eb0864 100644 --- a/examples/uart.zig +++ b/examples/uart.zig @@ -24,7 +24,7 @@ pub const log = rp2040.uart.log; pub fn main() !void { gpio.reset(); gpio.init(led); - gpio.setDir(led, .out); + gpio.set_direction(led, .out); gpio.put(led, 1); const uart = rp2040.uart.UART.init(uart_id, .{ @@ -34,15 +34,15 @@ pub fn main() !void { .clock_config = rp2040.clock_config, }); - rp2040.uart.initLogger(uart); + rp2040.uart.init_logger(uart); var i: u32 = 0; while (true) : (i += 1) { gpio.put(led, 1); std.log.info("what {}", .{i}); - time.sleepMs(500); + time.sleep_ms(500); gpio.put(led, 0); - time.sleepMs(500); + time.sleep_ms(500); } } diff --git a/src/boards.zig b/src/boards.zig new file mode 100644 index 0000000..4329182 --- /dev/null +++ b/src/boards.zig @@ -0,0 +1,15 @@ +const std = @import("std"); +const microzig = @import("../deps/microzig/src/main.zig"); +const chips = @import("chips.zig"); + +fn root_dir() []const u8 { + return std.fs.path.dirname(@src().file) orelse "."; +} + +const board_path = std.fmt.comptimePrint("{s}/boards/raspberry_pi_pico.zig", .{root_dir()}); + +pub const raspberry_pi_pico = microzig.Board{ + .name = "Raspberry Pi Pico", + .source = .{ .path = board_path }, + .chip = chips.rp2040, +}; diff --git a/src/raspberry_pi_pico.zig b/src/boards/raspberry_pi_pico.zig similarity index 100% rename from src/raspberry_pi_pico.zig rename to src/boards/raspberry_pi_pico.zig diff --git a/src/chips.zig b/src/chips.zig new file mode 100644 index 0000000..5e0d39a --- /dev/null +++ b/src/chips.zig @@ -0,0 +1,25 @@ +const std = @import("std"); +const microzig = @import("../deps/microzig/src/main.zig"); + +fn root_dir() []const u8 { + return std.fs.path.dirname(@src().file) orelse "."; +} + +const chip_path = std.fmt.comptimePrint("{s}/chips/RP2040.zig", .{root_dir()}); +const hal_path = std.fmt.comptimePrint("{s}/hal.zig", .{root_dir()}); +const json_register_schema_path = std.fmt.comptimePrint("{s}/chips/RP2040.json", .{root_dir()}); + +pub const rp2040 = microzig.Chip{ + .name = "RP2040", + .source = .{ .path = chip_path }, + .hal = .{ .path = hal_path }, + .cpu = microzig.cpus.cortex_m0plus, + .memory_regions = &.{ + .{ .kind = .flash, .offset = 0x10000100, .length = (2048 * 1024) - 256 }, + .{ .kind = .flash, .offset = 0x10000000, .length = 256 }, + .{ .kind = .ram, .offset = 0x20000000, .length = 256 * 1024 }, + }, + .json_register_schema = .{ + .path = json_register_schema_path, + }, +}; diff --git a/src/chips/RP2040.json b/src/chips/RP2040.json new file mode 100644 index 0000000..6d26913 --- /dev/null +++ b/src/chips/RP2040.json @@ -0,0 +1,43672 @@ +{ + "version": "0.1.0", + "types": { + "peripherals": { + "SCS": { + "description": "System Control Space", + "children": { + "register_groups": { + "SysTick": { + "description": "System Tick Timer", + "children": { + "registers": { + "CTRL": { + "description": "SysTick Control and Status Register", + "offset": 0, + "size": 32, + "children": { + "fields": { + "ENABLE": { + "offset": 0, + "size": 1 + }, + "TICKINT": { + "offset": 1, + "size": 1 + }, + "CLKSOURCE": { + "offset": 2, + "size": 1 + }, + "COUNTFLAG": { + "offset": 16, + "size": 1 + } + } + } + }, + "LOAD": { + "description": "SysTick Reload Value Register", + "offset": 4, + "size": 32, + "children": { + "fields": { + "RELOAD": { + "offset": 0, + "size": 24 + } + } + } + }, + "VAL": { + "description": "SysTick Current Value Register", + "offset": 8, + "size": 32, + "children": { + "fields": { + "CURRENT": { + "offset": 0, + "size": 24 + } + } + } + }, + "CALIB": { + "description": "SysTick Calibration Register", + "offset": 12, + "size": 32, + "access": "read-only", + "children": { + "fields": { + "TENMS": { + "offset": 0, + "size": 24 + }, + "SKEW": { + "offset": 30, + "size": 1 + }, + "NOREF": { + "offset": 31, + "size": 1 + } + } + } + } + } + } + }, + "SCB": { + "description": "System Control Block", + "children": { + "registers": { + "CPUID": { + "offset": 0, + "size": 32, + "access": "read-only", + "children": { + "fields": { + "REVISION": { + "offset": 0, + "size": 4 + }, + "PARTNO": { + "offset": 4, + "size": 12 + }, + "ARCHITECTURE": { + "offset": 16, + "size": 4 + }, + "VARIANT": { + "offset": 20, + "size": 4 + }, + "IMPLEMENTER": { + "offset": 24, + "size": 8 + } + } + } + }, + "ICSR": { + "description": "Interrupt Control and State Register", + "offset": 4, + "size": 32, + "children": { + "fields": { + "VECTACTIVE": { + "offset": 0, + "size": 9 + }, + "VECTPENDING": { + "offset": 12, + "size": 9 + }, + "ISRPENDING": { + "offset": 22, + "size": 1 + }, + "ISRPREEMPT": { + "offset": 23, + "size": 1 + }, + "PENDSTCLR": { + "offset": 25, + "size": 1 + }, + "PENDSTSET": { + "offset": 26, + "size": 1 + }, + "PENDSVCLR": { + "offset": 27, + "size": 1 + }, + "PENDSVSET": { + "offset": 28, + "size": 1 + }, + "NMIPENDSET": { + "offset": 31, + "size": 1 + } + } + } + }, + "AIRCR": { + "description": "Application Interrupt and Reset Control Register", + "offset": 12, + "size": 32, + "children": { + "fields": { + "VECTCLRACTIVE": { + "offset": 1, + "size": 1 + }, + "SYSRESETREQ": { + "offset": 2, + "size": 1 + }, + "ENDIANESS": { + "offset": 15, + "size": 1 + }, + "VECTKEY": { + "offset": 16, + "size": 16 + } + } + } + }, + "SCR": { + "description": "System Control Register", + "offset": 16, + "size": 32, + "children": { + "fields": { + "SLEEPONEXIT": { + "offset": 1, + "size": 1 + }, + "SLEEPDEEP": { + "offset": 2, + "size": 1 + }, + "SEVONPEND": { + "offset": 4, + "size": 1 + } + } + } + }, + "CCR": { + "description": "Configuration Control Register", + "offset": 20, + "size": 32, + "children": { + "fields": { + "UNALIGN_TRP": { + "offset": 3, + "size": 1 + }, + "STKALIGN": { + "offset": 9, + "size": 1 + } + } + } + }, + "SHP": { + "description": "System Handlers Priority Registers. [0] is RESERVED", + "offset": 28, + "size": 32 + }, + "SHCSR": { + "description": "System Handler Control and State Register", + "offset": 36, + "size": 32, + "children": { + "fields": { + "SVCALLPENDED": { + "offset": 15, + "size": 1 + } + } + } + }, + "VTOR": { + "description": "Vector Table Offset Register", + "offset": 8, + "size": 32, + "children": { + "fields": { + "TBLOFF": { + "offset": 8, + "size": 24 + } + } + } + } + } + } + }, + "NVIC": { + "description": "Nested Vectored Interrupt Controller", + "children": { + "registers": { + "ISER": { + "description": "Interrupt Set Enable Register", + "offset": 0, + "size": 32, + "children": { + "fields": { + "XIP_IRQ": { + "offset": 6, + "size": 1 + }, + "CLOCKS_IRQ": { + "offset": 17, + "size": 1 + }, + "IO_IRQ_BANK0": { + "offset": 13, + "size": 1 + }, + "IO_IRQ_QSPI": { + "offset": 14, + "size": 1 + }, + "UART0_IRQ": { + "offset": 20, + "size": 1 + }, + "UART1_IRQ": { + "offset": 21, + "size": 1 + }, + "SPI0_IRQ": { + "offset": 18, + "size": 1 + }, + "SPI1_IRQ": { + "offset": 19, + "size": 1 + }, + "I2C0_IRQ": { + "offset": 23, + "size": 1 + }, + "I2C1_IRQ": { + "offset": 24, + "size": 1 + }, + "ADC_IRQ_FIFO": { + "offset": 22, + "size": 1 + }, + "PWM_IRQ_WRAP": { + "offset": 4, + "size": 1 + }, + "TIMER_IRQ_0": { + "offset": 0, + "size": 1 + }, + "TIMER_IRQ_1": { + "offset": 1, + "size": 1 + }, + "TIMER_IRQ_2": { + "offset": 2, + "size": 1 + }, + "TIMER_IRQ_3": { + "offset": 3, + "size": 1 + }, + "RTC_IRQ": { + "offset": 25, + "size": 1 + }, + "DMA_IRQ_0": { + "offset": 11, + "size": 1 + }, + "DMA_IRQ_1": { + "offset": 12, + "size": 1 + }, + "USBCTRL_IRQ": { + "offset": 5, + "size": 1 + }, + "PIO0_IRQ_0": { + "offset": 7, + "size": 1 + }, + "PIO0_IRQ_1": { + "offset": 8, + "size": 1 + }, + "PIO1_IRQ_0": { + "offset": 9, + "size": 1 + }, + "PIO1_IRQ_1": { + "offset": 10, + "size": 1 + }, + "SIO_IRQ_PROC0": { + "offset": 15, + "size": 1 + }, + "SIO_IRQ_PROC1": { + "offset": 16, + "size": 1 + } + } + } + }, + "ICER": { + "description": "Interrupt Clear Enable Register", + "offset": 128, + "size": 32, + "children": { + "fields": { + "XIP_IRQ": { + "offset": 6, + "size": 1 + }, + "CLOCKS_IRQ": { + "offset": 17, + "size": 1 + }, + "IO_IRQ_BANK0": { + "offset": 13, + "size": 1 + }, + "IO_IRQ_QSPI": { + "offset": 14, + "size": 1 + }, + "UART0_IRQ": { + "offset": 20, + "size": 1 + }, + "UART1_IRQ": { + "offset": 21, + "size": 1 + }, + "SPI0_IRQ": { + "offset": 18, + "size": 1 + }, + "SPI1_IRQ": { + "offset": 19, + "size": 1 + }, + "I2C0_IRQ": { + "offset": 23, + "size": 1 + }, + "I2C1_IRQ": { + "offset": 24, + "size": 1 + }, + "ADC_IRQ_FIFO": { + "offset": 22, + "size": 1 + }, + "PWM_IRQ_WRAP": { + "offset": 4, + "size": 1 + }, + "TIMER_IRQ_0": { + "offset": 0, + "size": 1 + }, + "TIMER_IRQ_1": { + "offset": 1, + "size": 1 + }, + "TIMER_IRQ_2": { + "offset": 2, + "size": 1 + }, + "TIMER_IRQ_3": { + "offset": 3, + "size": 1 + }, + "RTC_IRQ": { + "offset": 25, + "size": 1 + }, + "DMA_IRQ_0": { + "offset": 11, + "size": 1 + }, + "DMA_IRQ_1": { + "offset": 12, + "size": 1 + }, + "USBCTRL_IRQ": { + "offset": 5, + "size": 1 + }, + "PIO0_IRQ_0": { + "offset": 7, + "size": 1 + }, + "PIO0_IRQ_1": { + "offset": 8, + "size": 1 + }, + "PIO1_IRQ_0": { + "offset": 9, + "size": 1 + }, + "PIO1_IRQ_1": { + "offset": 10, + "size": 1 + }, + "SIO_IRQ_PROC0": { + "offset": 15, + "size": 1 + }, + "SIO_IRQ_PROC1": { + "offset": 16, + "size": 1 + } + } + } + }, + "ISPR": { + "description": "Interrupt Set Pending Register", + "offset": 256, + "size": 32, + "children": { + "fields": { + "XIP_IRQ": { + "offset": 6, + "size": 1 + }, + "CLOCKS_IRQ": { + "offset": 17, + "size": 1 + }, + "IO_IRQ_BANK0": { + "offset": 13, + "size": 1 + }, + "IO_IRQ_QSPI": { + "offset": 14, + "size": 1 + }, + "UART0_IRQ": { + "offset": 20, + "size": 1 + }, + "UART1_IRQ": { + "offset": 21, + "size": 1 + }, + "SPI0_IRQ": { + "offset": 18, + "size": 1 + }, + "SPI1_IRQ": { + "offset": 19, + "size": 1 + }, + "I2C0_IRQ": { + "offset": 23, + "size": 1 + }, + "I2C1_IRQ": { + "offset": 24, + "size": 1 + }, + "ADC_IRQ_FIFO": { + "offset": 22, + "size": 1 + }, + "PWM_IRQ_WRAP": { + "offset": 4, + "size": 1 + }, + "TIMER_IRQ_0": { + "offset": 0, + "size": 1 + }, + "TIMER_IRQ_1": { + "offset": 1, + "size": 1 + }, + "TIMER_IRQ_2": { + "offset": 2, + "size": 1 + }, + "TIMER_IRQ_3": { + "offset": 3, + "size": 1 + }, + "RTC_IRQ": { + "offset": 25, + "size": 1 + }, + "DMA_IRQ_0": { + "offset": 11, + "size": 1 + }, + "DMA_IRQ_1": { + "offset": 12, + "size": 1 + }, + "USBCTRL_IRQ": { + "offset": 5, + "size": 1 + }, + "PIO0_IRQ_0": { + "offset": 7, + "size": 1 + }, + "PIO0_IRQ_1": { + "offset": 8, + "size": 1 + }, + "PIO1_IRQ_0": { + "offset": 9, + "size": 1 + }, + "PIO1_IRQ_1": { + "offset": 10, + "size": 1 + }, + "SIO_IRQ_PROC0": { + "offset": 15, + "size": 1 + }, + "SIO_IRQ_PROC1": { + "offset": 16, + "size": 1 + } + } + } + }, + "ICPR": { + "description": "Interrupt Clear Pending Register", + "offset": 384, + "size": 32, + "children": { + "fields": { + "XIP_IRQ": { + "offset": 6, + "size": 1 + }, + "CLOCKS_IRQ": { + "offset": 17, + "size": 1 + }, + "IO_IRQ_BANK0": { + "offset": 13, + "size": 1 + }, + "IO_IRQ_QSPI": { + "offset": 14, + "size": 1 + }, + "UART0_IRQ": { + "offset": 20, + "size": 1 + }, + "UART1_IRQ": { + "offset": 21, + "size": 1 + }, + "SPI0_IRQ": { + "offset": 18, + "size": 1 + }, + "SPI1_IRQ": { + "offset": 19, + "size": 1 + }, + "I2C0_IRQ": { + "offset": 23, + "size": 1 + }, + "I2C1_IRQ": { + "offset": 24, + "size": 1 + }, + "ADC_IRQ_FIFO": { + "offset": 22, + "size": 1 + }, + "PWM_IRQ_WRAP": { + "offset": 4, + "size": 1 + }, + "TIMER_IRQ_0": { + "offset": 0, + "size": 1 + }, + "TIMER_IRQ_1": { + "offset": 1, + "size": 1 + }, + "TIMER_IRQ_2": { + "offset": 2, + "size": 1 + }, + "TIMER_IRQ_3": { + "offset": 3, + "size": 1 + }, + "RTC_IRQ": { + "offset": 25, + "size": 1 + }, + "DMA_IRQ_0": { + "offset": 11, + "size": 1 + }, + "DMA_IRQ_1": { + "offset": 12, + "size": 1 + }, + "USBCTRL_IRQ": { + "offset": 5, + "size": 1 + }, + "PIO0_IRQ_0": { + "offset": 7, + "size": 1 + }, + "PIO0_IRQ_1": { + "offset": 8, + "size": 1 + }, + "PIO1_IRQ_0": { + "offset": 9, + "size": 1 + }, + "PIO1_IRQ_1": { + "offset": 10, + "size": 1 + }, + "SIO_IRQ_PROC0": { + "offset": 15, + "size": 1 + }, + "SIO_IRQ_PROC1": { + "offset": 16, + "size": 1 + } + } + } + }, + "IPR0": { + "description": "Interrupt Priority Register", + "offset": 768, + "size": 32, + "children": { + "fields": { + "TIMER_IRQ_0": { + "offset": 6, + "size": 2 + }, + "TIMER_IRQ_1": { + "offset": 14, + "size": 2 + }, + "TIMER_IRQ_2": { + "offset": 22, + "size": 2 + }, + "TIMER_IRQ_3": { + "offset": 30, + "size": 2 + } + } + } + }, + "IPR1": { + "description": "Interrupt Priority Register", + "offset": 772, + "size": 32, + "children": { + "fields": { + "XIP_IRQ": { + "offset": 22, + "size": 2 + }, + "PWM_IRQ_WRAP": { + "offset": 6, + "size": 2 + }, + "USBCTRL_IRQ": { + "offset": 14, + "size": 2 + }, + "PIO0_IRQ_0": { + "offset": 30, + "size": 2 + } + } + } + }, + "IPR2": { + "description": "Interrupt Priority Register", + "offset": 776, + "size": 32, + "children": { + "fields": { + "DMA_IRQ_0": { + "offset": 30, + "size": 2 + }, + "PIO0_IRQ_1": { + "offset": 6, + "size": 2 + }, + "PIO1_IRQ_0": { + "offset": 14, + "size": 2 + }, + "PIO1_IRQ_1": { + "offset": 22, + "size": 2 + } + } + } + }, + "IPR3": { + "description": "Interrupt Priority Register", + "offset": 780, + "size": 32, + "children": { + "fields": { + "IO_IRQ_BANK0": { + "offset": 14, + "size": 2 + }, + "IO_IRQ_QSPI": { + "offset": 22, + "size": 2 + }, + "DMA_IRQ_1": { + "offset": 6, + "size": 2 + }, + "SIO_IRQ_PROC0": { + "offset": 30, + "size": 2 + } + } + } + }, + "IPR4": { + "description": "Interrupt Priority Register", + "offset": 784, + "size": 32, + "children": { + "fields": { + "CLOCKS_IRQ": { + "offset": 14, + "size": 2 + }, + "SPI0_IRQ": { + "offset": 22, + "size": 2 + }, + "SPI1_IRQ": { + "offset": 30, + "size": 2 + }, + "SIO_IRQ_PROC1": { + "offset": 6, + "size": 2 + } + } + } + }, + "IPR5": { + "description": "Interrupt Priority Register", + "offset": 788, + "size": 32, + "children": { + "fields": { + "UART0_IRQ": { + "offset": 6, + "size": 2 + }, + "UART1_IRQ": { + "offset": 14, + "size": 2 + }, + "I2C0_IRQ": { + "offset": 30, + "size": 2 + }, + "ADC_IRQ_FIFO": { + "offset": 22, + "size": 2 + } + } + } + }, + "IPR6": { + "description": "Interrupt Priority Register", + "offset": 792, + "size": 32, + "children": { + "fields": { + "I2C1_IRQ": { + "offset": 6, + "size": 2 + }, + "RTC_IRQ": { + "offset": 14, + "size": 2 + } + } + } + }, + "IPR7": { + "description": "Interrupt Priority Register", + "offset": 796, + "size": 32 + } + } + } + }, + "MPU": { + "description": "Memory Protection Unit", + "children": { + "registers": { + "TYPE": { + "description": "MPU Type Register", + "offset": 0, + "size": 32, + "access": "read-only", + "children": { + "fields": { + "SEPARATE": { + "offset": 0, + "size": 1 + }, + "DREGION": { + "offset": 8, + "size": 8 + }, + "IREGION": { + "offset": 16, + "size": 8 + } + } + } + }, + "CTRL": { + "description": "MPU Control Register", + "offset": 4, + "size": 32, + "children": { + "fields": { + "ENABLE": { + "offset": 0, + "size": 1 + }, + "HFNMIENA": { + "offset": 1, + "size": 1 + }, + "PRIVDEFENA": { + "offset": 2, + "size": 1 + } + } + } + }, + "RNR": { + "description": "MPU Region RNRber Register", + "offset": 8, + "size": 32, + "children": { + "fields": { + "REGION": { + "offset": 0, + "size": 8 + } + } + } + }, + "RBAR": { + "description": "MPU Region Base Address Register", + "offset": 12, + "size": 32, + "children": { + "fields": { + "REGION": { + "offset": 0, + "size": 4 + }, + "VALID": { + "offset": 4, + "size": 1 + }, + "ADDR": { + "offset": 8, + "size": 24 + } + } + } + }, + "RASR": { + "description": "MPU Region Attribute and Size Register", + "offset": 16, + "size": 32, + "children": { + "fields": { + "ENABLE": { + "offset": 0, + "size": 1 + }, + "SIZE": { + "offset": 1, + "size": 5 + }, + "SRD": { + "offset": 8, + "size": 8 + }, + "B": { + "offset": 16, + "size": 1 + }, + "C": { + "offset": 17, + "size": 1 + }, + "S": { + "offset": 18, + "size": 1 + }, + "TEX": { + "offset": 19, + "size": 3 + }, + "AP": { + "offset": 24, + "size": 3 + }, + "XN": { + "offset": 28, + "size": 1 + } + } + } + } + } + } + } + } + } + }, + "XIP_CTRL": { + "description": "QSPI flash execute-in-place block", + "children": { + "registers": { + "CTRL": { + "description": "Cache control", + "offset": 0, + "size": 32, + "reset_value": 3, + "children": { + "fields": { + "POWER_DOWN": { + "description": "When 1, the cache memories are powered down. They retain state,\\n\n but can not be accessed. This reduces static power dissipation.\\n\n Writing 1 to this bit forces CTRL_EN to 0, i.e. the cache cannot\\n\n be enabled when powered down.\\n\n Cache-as-SRAM accesses will produce a bus error response when\\n\n the cache is powered down.", + "offset": 3, + "size": 1 + }, + "ERR_BADWRITE": { + "description": "When 1, writes to any alias other than 0x0 (caching, allocating)\\n\n will produce a bus fault. When 0, these writes are silently ignored.\\n\n In either case, writes to the 0x0 alias will deallocate on tag match,\\n\n as usual.", + "offset": 1, + "size": 1 + }, + "EN": { + "description": "When 1, enable the cache. When the cache is disabled, all XIP accesses\\n\n will go straight to the flash, without querying the cache. When enabled,\\n\n cacheable XIP accesses will query the cache, and the flash will\\n\n not be accessed if the tag matches and the valid bit is set.\\n\\n\n If the cache is enabled, cache-as-SRAM accesses have no effect on the\\n\n cache data RAM, and will produce a bus error response.", + "offset": 0, + "size": 1 + } + } + } + }, + "FLUSH": { + "description": "Cache Flush control", + "offset": 4, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FLUSH": { + "description": "Write 1 to flush the cache. This clears the tag memory, but\\n\n the data memory retains its contents. (This means cache-as-SRAM\\n\n contents is not affected by flush or reset.)\\n\n Reading will hold the bus (stall the processor) until the flush\\n\n completes. Alternatively STAT can be polled until completion.", + "offset": 0, + "size": 1 + } + } + } + }, + "STAT": { + "description": "Cache Status", + "offset": 8, + "size": 32, + "reset_value": 2, + "children": { + "fields": { + "FIFO_FULL": { + "description": "When 1, indicates the XIP streaming FIFO is completely full.\\n\n The streaming FIFO is 2 entries deep, so the full and empty\\n\n flag allow its level to be ascertained.", + "offset": 2, + "size": 1, + "access": "read-only" + }, + "FIFO_EMPTY": { + "description": "When 1, indicates the XIP streaming FIFO is completely empty.", + "offset": 1, + "size": 1, + "access": "read-only" + }, + "FLUSH_READY": { + "description": "Reads as 0 while a cache flush is in progress, and 1 otherwise.\\n\n The cache is flushed whenever the XIP block is reset, and also\\n\n when requested via the FLUSH register.", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "CTR_HIT": { + "description": "Cache Hit counter\\n\n A 32 bit saturating counter that increments upon each cache hit,\\n\n i.e. when an XIP access is serviced directly from cached data.\\n\n Write any value to clear.", + "offset": 12, + "size": 32, + "reset_value": 0 + }, + "CTR_ACC": { + "description": "Cache Access counter\\n\n A 32 bit saturating counter that increments upon each XIP access,\\n\n whether the cache is hit or not. This includes noncacheable accesses.\\n\n Write any value to clear.", + "offset": 16, + "size": 32, + "reset_value": 0 + }, + "STREAM_ADDR": { + "description": "FIFO stream address", + "offset": 20, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "STREAM_ADDR": { + "description": "The address of the next word to be streamed from flash to the streaming FIFO.\\n\n Increments automatically after each flash access.\\n\n Write the initial access address here before starting a streaming read.", + "offset": 2, + "size": 30 + } + } + } + }, + "STREAM_CTR": { + "description": "FIFO stream control", + "offset": 24, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "STREAM_CTR": { + "description": "Write a nonzero value to start a streaming read. This will then\\n\n progress in the background, using flash idle cycles to transfer\\n\n a linear data block from flash to the streaming FIFO.\\n\n Decrements automatically (1 at a time) as the stream\\n\n progresses, and halts on reaching 0.\\n\n Write 0 to halt an in-progress stream, and discard any in-flight\\n\n read, so that a new stream can immediately be started (after\\n\n draining the FIFO and reinitialising STREAM_ADDR)", + "offset": 0, + "size": 22 + } + } + } + }, + "STREAM_FIFO": { + "description": "FIFO stream data\\n\n Streamed data is buffered here, for retrieval by the system DMA.\\n\n This FIFO can also be accessed via the XIP_AUX slave, to avoid exposing\\n\n the DMA to bus stalls caused by other XIP traffic.", + "offset": 28, + "size": 32, + "reset_value": 0, + "access": "read-only" + } + } + } + }, + "XIP_SSI": { + "description": "DW_apb_ssi has the following features:\\n\n * APB interface – Allows for easy integration into a DesignWare Synthesizable Components for AMBA 2 implementation.\\n\n * APB3 and APB4 protocol support.\\n\n * Scalable APB data bus width – Supports APB data bus widths of 8, 16, and 32 bits.\\n\n * Serial-master or serial-slave operation – Enables serial communication with serial-master or serial-slave peripheral devices.\\n\n * Programmable Dual/Quad/Octal SPI support in Master Mode.\\n\n * Dual Data Rate (DDR) and Read Data Strobe (RDS) Support - Enables the DW_apb_ssi master to perform operations with the device in DDR and RDS modes when working in Dual/Quad/Octal mode of operation.\\n\n * Data Mask Support - Enables the DW_apb_ssi to selectively update the bytes in the device. This feature is applicable only in enhanced SPI modes.\\n\n * eXecute-In-Place (XIP) support - Enables the DW_apb_ssi master to behave as a memory mapped I/O and fetches the data from the device based on the APB read request. This feature is applicable only in enhanced SPI modes.\\n\n * DMA Controller Interface – Enables the DW_apb_ssi to interface to a DMA controller over the bus using a handshaking interface for transfer requests.\\n\n * Independent masking of interrupts – Master collision, transmit FIFO overflow, transmit FIFO empty, receive FIFO full, receive FIFO underflow, and receive FIFO overflow interrupts can all be masked independently.\\n\n * Multi-master contention detection – Informs the processor of multiple serial-master accesses on the serial bus.\\n\n * Bypass of meta-stability flip-flops for synchronous clocks – When the APB clock (pclk) and the DW_apb_ssi serial clock (ssi_clk) are synchronous, meta-stable flip-flops are not used when transferring control signals across these clock domains.\\n\n * Programmable delay on the sample time of the received serial data bit (rxd); enables programmable control of routing delays resulting in higher serial data-bit rates.\\n\n * Programmable features:\\n\n - Serial interface operation – Choice of Motorola SPI, Texas Instruments Synchronous Serial Protocol or National Semiconductor Microwire.\\n\n - Clock bit-rate – Dynamic control of the serial bit rate of the data transfer; used in only serial-master mode of operation.\\n\n - Data Item size (4 to 32 bits) – Item size of each data transfer under the control of the programmer.\\n\n * Configured features:\\n\n - FIFO depth – 16 words deep. The FIFO width is fixed at 32 bits.\\n\n - 1 slave select output.\\n\n - Hardware slave-select – Dedicated hardware slave-select line.\\n\n - Combined interrupt line - one combined interrupt line from the DW_apb_ssi to the interrupt controller.\\n\n - Interrupt polarity – active high interrupt lines.\\n\n - Serial clock polarity – low serial-clock polarity directly after reset.\\n\n - Serial clock phase – capture on first edge of serial-clock directly after reset.", + "children": { + "registers": { + "CTRLR0": { + "description": "Control register 0", + "offset": 0, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SSTE": { + "description": "Slave select toggle enable", + "offset": 24, + "size": 1 + }, + "SPI_FRF": { + "description": "SPI frame format", + "offset": 21, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "STD": { + "description": "Standard 1-bit SPI frame format; 1 bit per SCK, full-duplex", + "value": 0 + }, + "DUAL": { + "description": "Dual-SPI frame format; two bits per SCK, half-duplex", + "value": 1 + }, + "QUAD": { + "description": "Quad-SPI frame format; four bits per SCK, half-duplex", + "value": 2 + } + } + } + } + }, + "DFS_32": { + "description": "Data frame size in 32b transfer mode\\n\n Value of n -> n+1 clocks per frame.", + "offset": 16, + "size": 5 + }, + "CFS": { + "description": "Control frame size\\n\n Value of n -> n+1 clocks per frame.", + "offset": 12, + "size": 4 + }, + "SRL": { + "description": "Shift register loop (test mode)", + "offset": 11, + "size": 1 + }, + "SLV_OE": { + "description": "Slave output enable", + "offset": 10, + "size": 1 + }, + "TMOD": { + "description": "Transfer mode", + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "TX_AND_RX": { + "description": "Both transmit and receive", + "value": 0 + }, + "TX_ONLY": { + "description": "Transmit only (not for FRF == 0, standard SPI mode)", + "value": 1 + }, + "RX_ONLY": { + "description": "Receive only (not for FRF == 0, standard SPI mode)", + "value": 2 + }, + "EEPROM_READ": { + "description": "EEPROM read mode (TX then RX; RX starts after control data TX'd)", + "value": 3 + } + } + } + } + }, + "SCPOL": { + "description": "Serial clock polarity", + "offset": 7, + "size": 1 + }, + "SCPH": { + "description": "Serial clock phase", + "offset": 6, + "size": 1 + }, + "FRF": { + "description": "Frame format", + "offset": 4, + "size": 2 + }, + "DFS": { + "description": "Data frame size", + "offset": 0, + "size": 4 + } + } + } + }, + "CTRLR1": { + "description": "Master Control register 1", + "offset": 4, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "NDF": { + "description": "Number of data frames", + "offset": 0, + "size": 16 + } + } + } + }, + "SSIENR": { + "description": "SSI Enable", + "offset": 8, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SSI_EN": { + "description": "SSI enable", + "offset": 0, + "size": 1 + } + } + } + }, + "MWCR": { + "description": "Microwire Control", + "offset": 12, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "MHS": { + "description": "Microwire handshaking", + "offset": 2, + "size": 1 + }, + "MDD": { + "description": "Microwire control", + "offset": 1, + "size": 1 + }, + "MWMOD": { + "description": "Microwire transfer mode", + "offset": 0, + "size": 1 + } + } + } + }, + "SER": { + "description": "Slave enable", + "offset": 16, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SER": { + "description": "For each bit:\\n\n 0 -> slave not selected\\n\n 1 -> slave selected", + "offset": 0, + "size": 1 + } + } + } + }, + "BAUDR": { + "description": "Baud rate", + "offset": 20, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SCKDV": { + "description": "SSI clock divider", + "offset": 0, + "size": 16 + } + } + } + }, + "TXFTLR": { + "description": "TX FIFO threshold level", + "offset": 24, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "TFT": { + "description": "Transmit FIFO threshold", + "offset": 0, + "size": 8 + } + } + } + }, + "RXFTLR": { + "description": "RX FIFO threshold level", + "offset": 28, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "RFT": { + "description": "Receive FIFO threshold", + "offset": 0, + "size": 8 + } + } + } + }, + "TXFLR": { + "description": "TX FIFO level", + "offset": 32, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "TFTFL": { + "description": "Transmit FIFO level", + "offset": 0, + "size": 8, + "access": "read-only" + } + } + } + }, + "RXFLR": { + "description": "RX FIFO level", + "offset": 36, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "RXTFL": { + "description": "Receive FIFO level", + "offset": 0, + "size": 8, + "access": "read-only" + } + } + } + }, + "SR": { + "description": "Status register", + "offset": 40, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "DCOL": { + "description": "Data collision error", + "offset": 6, + "size": 1, + "access": "read-only" + }, + "TXE": { + "description": "Transmission error", + "offset": 5, + "size": 1, + "access": "read-only" + }, + "RFF": { + "description": "Receive FIFO full", + "offset": 4, + "size": 1, + "access": "read-only" + }, + "RFNE": { + "description": "Receive FIFO not empty", + "offset": 3, + "size": 1, + "access": "read-only" + }, + "TFE": { + "description": "Transmit FIFO empty", + "offset": 2, + "size": 1, + "access": "read-only" + }, + "TFNF": { + "description": "Transmit FIFO not full", + "offset": 1, + "size": 1, + "access": "read-only" + }, + "BUSY": { + "description": "SSI busy flag", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "IMR": { + "description": "Interrupt mask", + "offset": 44, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "MSTIM": { + "description": "Multi-master contention interrupt mask", + "offset": 5, + "size": 1 + }, + "RXFIM": { + "description": "Receive FIFO full interrupt mask", + "offset": 4, + "size": 1 + }, + "RXOIM": { + "description": "Receive FIFO overflow interrupt mask", + "offset": 3, + "size": 1 + }, + "RXUIM": { + "description": "Receive FIFO underflow interrupt mask", + "offset": 2, + "size": 1 + }, + "TXOIM": { + "description": "Transmit FIFO overflow interrupt mask", + "offset": 1, + "size": 1 + }, + "TXEIM": { + "description": "Transmit FIFO empty interrupt mask", + "offset": 0, + "size": 1 + } + } + } + }, + "ISR": { + "description": "Interrupt status", + "offset": 48, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "MSTIS": { + "description": "Multi-master contention interrupt status", + "offset": 5, + "size": 1, + "access": "read-only" + }, + "RXFIS": { + "description": "Receive FIFO full interrupt status", + "offset": 4, + "size": 1, + "access": "read-only" + }, + "RXOIS": { + "description": "Receive FIFO overflow interrupt status", + "offset": 3, + "size": 1, + "access": "read-only" + }, + "RXUIS": { + "description": "Receive FIFO underflow interrupt status", + "offset": 2, + "size": 1, + "access": "read-only" + }, + "TXOIS": { + "description": "Transmit FIFO overflow interrupt status", + "offset": 1, + "size": 1, + "access": "read-only" + }, + "TXEIS": { + "description": "Transmit FIFO empty interrupt status", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "RISR": { + "description": "Raw interrupt status", + "offset": 52, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "MSTIR": { + "description": "Multi-master contention raw interrupt status", + "offset": 5, + "size": 1, + "access": "read-only" + }, + "RXFIR": { + "description": "Receive FIFO full raw interrupt status", + "offset": 4, + "size": 1, + "access": "read-only" + }, + "RXOIR": { + "description": "Receive FIFO overflow raw interrupt status", + "offset": 3, + "size": 1, + "access": "read-only" + }, + "RXUIR": { + "description": "Receive FIFO underflow raw interrupt status", + "offset": 2, + "size": 1, + "access": "read-only" + }, + "TXOIR": { + "description": "Transmit FIFO overflow raw interrupt status", + "offset": 1, + "size": 1, + "access": "read-only" + }, + "TXEIR": { + "description": "Transmit FIFO empty raw interrupt status", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "TXOICR": { + "description": "TX FIFO overflow interrupt clear", + "offset": 56, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "TXOICR": { + "description": "Clear-on-read transmit FIFO overflow interrupt", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "RXOICR": { + "description": "RX FIFO overflow interrupt clear", + "offset": 60, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "RXOICR": { + "description": "Clear-on-read receive FIFO overflow interrupt", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "RXUICR": { + "description": "RX FIFO underflow interrupt clear", + "offset": 64, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "RXUICR": { + "description": "Clear-on-read receive FIFO underflow interrupt", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "MSTICR": { + "description": "Multi-master interrupt clear", + "offset": 68, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "MSTICR": { + "description": "Clear-on-read multi-master contention interrupt", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "ICR": { + "description": "Interrupt clear", + "offset": 72, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ICR": { + "description": "Clear-on-read all active interrupts", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "DMACR": { + "description": "DMA control", + "offset": 76, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "TDMAE": { + "description": "Transmit DMA enable", + "offset": 1, + "size": 1 + }, + "RDMAE": { + "description": "Receive DMA enable", + "offset": 0, + "size": 1 + } + } + } + }, + "DMATDLR": { + "description": "DMA TX data level", + "offset": 80, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "DMATDL": { + "description": "Transmit data watermark level", + "offset": 0, + "size": 8 + } + } + } + }, + "DMARDLR": { + "description": "DMA RX data level", + "offset": 84, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "DMARDL": { + "description": "Receive data watermark level (DMARDLR+1)", + "offset": 0, + "size": 8 + } + } + } + }, + "IDR": { + "description": "Identification register", + "offset": 88, + "size": 32, + "reset_value": 1364414537, + "children": { + "fields": { + "IDCODE": { + "description": "Peripheral dentification code", + "offset": 0, + "size": 32, + "access": "read-only" + } + } + } + }, + "SSI_VERSION_ID": { + "description": "Version ID", + "offset": 92, + "size": 32, + "reset_value": 875573546, + "children": { + "fields": { + "SSI_COMP_VERSION": { + "description": "SNPS component version (format X.YY)", + "offset": 0, + "size": 32, + "access": "read-only" + } + } + } + }, + "DR0": { + "description": "Data Register 0 (of 36)", + "offset": 96, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "DR": { + "description": "First data register of 36", + "offset": 0, + "size": 32 + } + } + } + }, + "RX_SAMPLE_DLY": { + "description": "RX sample delay", + "offset": 240, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "RSD": { + "description": "RXD sample delay (in SCLK cycles)", + "offset": 0, + "size": 8 + } + } + } + }, + "SPI_CTRLR0": { + "description": "SPI control", + "offset": 244, + "size": 32, + "reset_value": 50331648, + "children": { + "fields": { + "XIP_CMD": { + "description": "SPI Command to send in XIP mode (INST_L = 8-bit) or to append to Address (INST_L = 0-bit)", + "offset": 24, + "size": 8 + }, + "SPI_RXDS_EN": { + "description": "Read data strobe enable", + "offset": 18, + "size": 1 + }, + "INST_DDR_EN": { + "description": "Instruction DDR transfer enable", + "offset": 17, + "size": 1 + }, + "SPI_DDR_EN": { + "description": "SPI DDR transfer enable", + "offset": 16, + "size": 1 + }, + "WAIT_CYCLES": { + "description": "Wait cycles between control frame transmit and data reception (in SCLK cycles)", + "offset": 11, + "size": 5 + }, + "INST_L": { + "description": "Instruction length (0/4/8/16b)", + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NONE": { + "description": "No instruction", + "value": 0 + }, + "4B": { + "description": "4-bit instruction", + "value": 1 + }, + "8B": { + "description": "8-bit instruction", + "value": 2 + }, + "16B": { + "description": "16-bit instruction", + "value": 3 + } + } + } + } + }, + "ADDR_L": { + "description": "Address length (0b-60b in 4b increments)", + "offset": 2, + "size": 4 + }, + "TRANS_TYPE": { + "description": "Address and instruction transfer format", + "offset": 0, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "1C1A": { + "description": "Command and address both in standard SPI frame format", + "value": 0 + }, + "1C2A": { + "description": "Command in standard SPI format, address in format specified by FRF", + "value": 1 + }, + "2C2A": { + "description": "Command and address both in format specified by FRF (e.g. Dual-SPI)", + "value": 2 + } + } + } + } + } + } + } + }, + "TXD_DRIVE_EDGE": { + "description": "TX drive edge", + "offset": 248, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "TDE": { + "description": "TXD drive edge", + "offset": 0, + "size": 8 + } + } + } + } + } + } + }, + "SYSINFO": { + "children": { + "registers": { + "CHIP_ID": { + "description": "JEDEC JEP-106 compliant chip identifier.", + "offset": 0, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "REVISION": { + "offset": 28, + "size": 4, + "access": "read-only" + }, + "PART": { + "offset": 12, + "size": 16, + "access": "read-only" + }, + "MANUFACTURER": { + "offset": 0, + "size": 12, + "access": "read-only" + } + } + } + }, + "PLATFORM": { + "description": "Platform register. Allows software to know what environment it is running in.", + "offset": 4, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ASIC": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "FPGA": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "GITREF_RP2040": { + "description": "Git hash of the chip source. Used to identify chip version.", + "offset": 64, + "size": 32, + "reset_value": 0, + "access": "read-only" + } + } + } + }, + "SYSCFG": { + "description": "Register block for various chip control signals", + "children": { + "registers": { + "PROC0_NMI_MASK": { + "description": "Processor core 0 NMI source mask\\n\n Set a bit high to enable NMI from that IRQ", + "offset": 0, + "size": 32, + "reset_value": 0 + }, + "PROC1_NMI_MASK": { + "description": "Processor core 1 NMI source mask\\n\n Set a bit high to enable NMI from that IRQ", + "offset": 4, + "size": 32, + "reset_value": 0 + }, + "PROC_CONFIG": { + "description": "Configuration for processors", + "offset": 8, + "size": 32, + "reset_value": 268435456, + "children": { + "fields": { + "PROC1_DAP_INSTID": { + "description": "Configure proc1 DAP instance ID.\\n\n Recommend that this is NOT changed until you require debug access in multi-chip environment\\n\n WARNING: do not set to 15 as this is reserved for RescueDP", + "offset": 28, + "size": 4 + }, + "PROC0_DAP_INSTID": { + "description": "Configure proc0 DAP instance ID.\\n\n Recommend that this is NOT changed until you require debug access in multi-chip environment\\n\n WARNING: do not set to 15 as this is reserved for RescueDP", + "offset": 24, + "size": 4 + }, + "PROC1_HALTED": { + "description": "Indication that proc1 has halted", + "offset": 1, + "size": 1, + "access": "read-only" + }, + "PROC0_HALTED": { + "description": "Indication that proc0 has halted", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "PROC_IN_SYNC_BYPASS": { + "description": "For each bit, if 1, bypass the input synchronizer between that GPIO\\n\n and the GPIO input register in the SIO. The input synchronizers should\\n\n generally be unbypassed, to avoid injecting metastabilities into processors.\\n\n If you're feeling brave, you can bypass to save two cycles of input\\n\n latency. This register applies to GPIO 0...29.", + "offset": 12, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "PROC_IN_SYNC_BYPASS": { + "offset": 0, + "size": 30 + } + } + } + }, + "PROC_IN_SYNC_BYPASS_HI": { + "description": "For each bit, if 1, bypass the input synchronizer between that GPIO\\n\n and the GPIO input register in the SIO. The input synchronizers should\\n\n generally be unbypassed, to avoid injecting metastabilities into processors.\\n\n If you're feeling brave, you can bypass to save two cycles of input\\n\n latency. This register applies to GPIO 30...35 (the QSPI IOs).", + "offset": 16, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "PROC_IN_SYNC_BYPASS_HI": { + "offset": 0, + "size": 6 + } + } + } + }, + "DBGFORCE": { + "description": "Directly control the SWD debug port of either processor", + "offset": 20, + "size": 32, + "reset_value": 102, + "children": { + "fields": { + "PROC1_ATTACH": { + "description": "Attach processor 1 debug port to syscfg controls, and disconnect it from external SWD pads.", + "offset": 7, + "size": 1 + }, + "PROC1_SWCLK": { + "description": "Directly drive processor 1 SWCLK, if PROC1_ATTACH is set", + "offset": 6, + "size": 1 + }, + "PROC1_SWDI": { + "description": "Directly drive processor 1 SWDIO input, if PROC1_ATTACH is set", + "offset": 5, + "size": 1 + }, + "PROC1_SWDO": { + "description": "Observe the value of processor 1 SWDIO output.", + "offset": 4, + "size": 1, + "access": "read-only" + }, + "PROC0_ATTACH": { + "description": "Attach processor 0 debug port to syscfg controls, and disconnect it from external SWD pads.", + "offset": 3, + "size": 1 + }, + "PROC0_SWCLK": { + "description": "Directly drive processor 0 SWCLK, if PROC0_ATTACH is set", + "offset": 2, + "size": 1 + }, + "PROC0_SWDI": { + "description": "Directly drive processor 0 SWDIO input, if PROC0_ATTACH is set", + "offset": 1, + "size": 1 + }, + "PROC0_SWDO": { + "description": "Observe the value of processor 0 SWDIO output.", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "MEMPOWERDOWN": { + "description": "Control power downs to memories. Set high to power down memories.\\n\n Use with extreme caution", + "offset": 24, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ROM": { + "offset": 7, + "size": 1 + }, + "USB": { + "offset": 6, + "size": 1 + }, + "SRAM5": { + "offset": 5, + "size": 1 + }, + "SRAM4": { + "offset": 4, + "size": 1 + }, + "SRAM3": { + "offset": 3, + "size": 1 + }, + "SRAM2": { + "offset": 2, + "size": 1 + }, + "SRAM1": { + "offset": 1, + "size": 1 + }, + "SRAM0": { + "offset": 0, + "size": 1 + } + } + } + } + } + } + }, + "CLOCKS": { + "children": { + "registers": { + "CLK_GPOUT0_CTRL": { + "description": "Clock control, can be changed on-the-fly (except for auxsrc)", + "offset": 0, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "NUDGE": { + "description": "An edge on this signal shifts the phase of the output by 1 cycle of the input clock\\n\n This can be done at any time", + "offset": 20, + "size": 1 + }, + "PHASE": { + "description": "This delays the enable signal by up to 3 cycles of the input clock\\n\n This must be set before the clock is enabled to have any effect", + "offset": 16, + "size": 2 + }, + "DC50": { + "description": "Enables duty cycle correction for odd divisors", + "offset": 12, + "size": 1 + }, + "ENABLE": { + "description": "Starts and stops the clock generator cleanly", + "offset": 11, + "size": 1 + }, + "KILL": { + "description": "Asynchronously kills the clock generator", + "offset": 10, + "size": 1 + }, + "AUXSRC": { + "description": "Selects the auxiliary clock source, will glitch when switching", + "offset": 5, + "size": 4, + "enum": { + "size": 4, + "children": { + "enum_fields": { + "clksrc_pll_sys": { + "value": 0 + }, + "clksrc_gpin0": { + "value": 1 + }, + "clksrc_gpin1": { + "value": 2 + }, + "clksrc_pll_usb": { + "value": 3 + }, + "rosc_clksrc": { + "value": 4 + }, + "xosc_clksrc": { + "value": 5 + }, + "clk_sys": { + "value": 6 + }, + "clk_usb": { + "value": 7 + }, + "clk_adc": { + "value": 8 + }, + "clk_rtc": { + "value": 9 + }, + "clk_ref": { + "value": 10 + } + } + } + } + } + } + } + }, + "CLK_GPOUT0_DIV": { + "description": "Clock divisor, can be changed on-the-fly", + "offset": 4, + "size": 32, + "reset_value": 256, + "children": { + "fields": { + "INT": { + "description": "Integer component of the divisor, 0 -> divide by 2^16", + "offset": 8, + "size": 24 + }, + "FRAC": { + "description": "Fractional component of the divisor", + "offset": 0, + "size": 8 + } + } + } + }, + "CLK_GPOUT0_SELECTED": { + "description": "Indicates which SRC is currently selected by the glitchless mux (one-hot).\\n\n This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1.", + "offset": 8, + "size": 32, + "reset_value": 1, + "access": "read-only" + }, + "CLK_GPOUT1_CTRL": { + "description": "Clock control, can be changed on-the-fly (except for auxsrc)", + "offset": 12, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "NUDGE": { + "description": "An edge on this signal shifts the phase of the output by 1 cycle of the input clock\\n\n This can be done at any time", + "offset": 20, + "size": 1 + }, + "PHASE": { + "description": "This delays the enable signal by up to 3 cycles of the input clock\\n\n This must be set before the clock is enabled to have any effect", + "offset": 16, + "size": 2 + }, + "DC50": { + "description": "Enables duty cycle correction for odd divisors", + "offset": 12, + "size": 1 + }, + "ENABLE": { + "description": "Starts and stops the clock generator cleanly", + "offset": 11, + "size": 1 + }, + "KILL": { + "description": "Asynchronously kills the clock generator", + "offset": 10, + "size": 1 + }, + "AUXSRC": { + "description": "Selects the auxiliary clock source, will glitch when switching", + "offset": 5, + "size": 4, + "enum": { + "size": 4, + "children": { + "enum_fields": { + "clksrc_pll_sys": { + "value": 0 + }, + "clksrc_gpin0": { + "value": 1 + }, + "clksrc_gpin1": { + "value": 2 + }, + "clksrc_pll_usb": { + "value": 3 + }, + "rosc_clksrc": { + "value": 4 + }, + "xosc_clksrc": { + "value": 5 + }, + "clk_sys": { + "value": 6 + }, + "clk_usb": { + "value": 7 + }, + "clk_adc": { + "value": 8 + }, + "clk_rtc": { + "value": 9 + }, + "clk_ref": { + "value": 10 + } + } + } + } + } + } + } + }, + "CLK_GPOUT1_DIV": { + "description": "Clock divisor, can be changed on-the-fly", + "offset": 16, + "size": 32, + "reset_value": 256, + "children": { + "fields": { + "INT": { + "description": "Integer component of the divisor, 0 -> divide by 2^16", + "offset": 8, + "size": 24 + }, + "FRAC": { + "description": "Fractional component of the divisor", + "offset": 0, + "size": 8 + } + } + } + }, + "CLK_GPOUT1_SELECTED": { + "description": "Indicates which SRC is currently selected by the glitchless mux (one-hot).\\n\n This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1.", + "offset": 20, + "size": 32, + "reset_value": 1, + "access": "read-only" + }, + "CLK_GPOUT2_CTRL": { + "description": "Clock control, can be changed on-the-fly (except for auxsrc)", + "offset": 24, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "NUDGE": { + "description": "An edge on this signal shifts the phase of the output by 1 cycle of the input clock\\n\n This can be done at any time", + "offset": 20, + "size": 1 + }, + "PHASE": { + "description": "This delays the enable signal by up to 3 cycles of the input clock\\n\n This must be set before the clock is enabled to have any effect", + "offset": 16, + "size": 2 + }, + "DC50": { + "description": "Enables duty cycle correction for odd divisors", + "offset": 12, + "size": 1 + }, + "ENABLE": { + "description": "Starts and stops the clock generator cleanly", + "offset": 11, + "size": 1 + }, + "KILL": { + "description": "Asynchronously kills the clock generator", + "offset": 10, + "size": 1 + }, + "AUXSRC": { + "description": "Selects the auxiliary clock source, will glitch when switching", + "offset": 5, + "size": 4, + "enum": { + "size": 4, + "children": { + "enum_fields": { + "clksrc_pll_sys": { + "value": 0 + }, + "clksrc_gpin0": { + "value": 1 + }, + "clksrc_gpin1": { + "value": 2 + }, + "clksrc_pll_usb": { + "value": 3 + }, + "rosc_clksrc_ph": { + "value": 4 + }, + "xosc_clksrc": { + "value": 5 + }, + "clk_sys": { + "value": 6 + }, + "clk_usb": { + "value": 7 + }, + "clk_adc": { + "value": 8 + }, + "clk_rtc": { + "value": 9 + }, + "clk_ref": { + "value": 10 + } + } + } + } + } + } + } + }, + "CLK_GPOUT2_DIV": { + "description": "Clock divisor, can be changed on-the-fly", + "offset": 28, + "size": 32, + "reset_value": 256, + "children": { + "fields": { + "INT": { + "description": "Integer component of the divisor, 0 -> divide by 2^16", + "offset": 8, + "size": 24 + }, + "FRAC": { + "description": "Fractional component of the divisor", + "offset": 0, + "size": 8 + } + } + } + }, + "CLK_GPOUT2_SELECTED": { + "description": "Indicates which SRC is currently selected by the glitchless mux (one-hot).\\n\n This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1.", + "offset": 32, + "size": 32, + "reset_value": 1, + "access": "read-only" + }, + "CLK_GPOUT3_CTRL": { + "description": "Clock control, can be changed on-the-fly (except for auxsrc)", + "offset": 36, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "NUDGE": { + "description": "An edge on this signal shifts the phase of the output by 1 cycle of the input clock\\n\n This can be done at any time", + "offset": 20, + "size": 1 + }, + "PHASE": { + "description": "This delays the enable signal by up to 3 cycles of the input clock\\n\n This must be set before the clock is enabled to have any effect", + "offset": 16, + "size": 2 + }, + "DC50": { + "description": "Enables duty cycle correction for odd divisors", + "offset": 12, + "size": 1 + }, + "ENABLE": { + "description": "Starts and stops the clock generator cleanly", + "offset": 11, + "size": 1 + }, + "KILL": { + "description": "Asynchronously kills the clock generator", + "offset": 10, + "size": 1 + }, + "AUXSRC": { + "description": "Selects the auxiliary clock source, will glitch when switching", + "offset": 5, + "size": 4, + "enum": { + "size": 4, + "children": { + "enum_fields": { + "clksrc_pll_sys": { + "value": 0 + }, + "clksrc_gpin0": { + "value": 1 + }, + "clksrc_gpin1": { + "value": 2 + }, + "clksrc_pll_usb": { + "value": 3 + }, + "rosc_clksrc_ph": { + "value": 4 + }, + "xosc_clksrc": { + "value": 5 + }, + "clk_sys": { + "value": 6 + }, + "clk_usb": { + "value": 7 + }, + "clk_adc": { + "value": 8 + }, + "clk_rtc": { + "value": 9 + }, + "clk_ref": { + "value": 10 + } + } + } + } + } + } + } + }, + "CLK_GPOUT3_DIV": { + "description": "Clock divisor, can be changed on-the-fly", + "offset": 40, + "size": 32, + "reset_value": 256, + "children": { + "fields": { + "INT": { + "description": "Integer component of the divisor, 0 -> divide by 2^16", + "offset": 8, + "size": 24 + }, + "FRAC": { + "description": "Fractional component of the divisor", + "offset": 0, + "size": 8 + } + } + } + }, + "CLK_GPOUT3_SELECTED": { + "description": "Indicates which SRC is currently selected by the glitchless mux (one-hot).\\n\n This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1.", + "offset": 44, + "size": 32, + "reset_value": 1, + "access": "read-only" + }, + "CLK_REF_CTRL": { + "description": "Clock control, can be changed on-the-fly (except for auxsrc)", + "offset": 48, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "AUXSRC": { + "description": "Selects the auxiliary clock source, will glitch when switching", + "offset": 5, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "clksrc_pll_usb": { + "value": 0 + }, + "clksrc_gpin0": { + "value": 1 + }, + "clksrc_gpin1": { + "value": 2 + } + } + } + } + }, + "SRC": { + "description": "Selects the clock source glitchlessly, can be changed on-the-fly", + "offset": 0, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "rosc_clksrc_ph": { + "value": 0 + }, + "clksrc_clk_ref_aux": { + "value": 1 + }, + "xosc_clksrc": { + "value": 2 + } + } + } + } + } + } + } + }, + "CLK_REF_DIV": { + "description": "Clock divisor, can be changed on-the-fly", + "offset": 52, + "size": 32, + "reset_value": 256, + "children": { + "fields": { + "INT": { + "description": "Integer component of the divisor, 0 -> divide by 2^16", + "offset": 8, + "size": 2 + } + } + } + }, + "CLK_REF_SELECTED": { + "description": "Indicates which SRC is currently selected by the glitchless mux (one-hot).\\n\n The glitchless multiplexer does not switch instantaneously (to avoid glitches), so software should poll this register to wait for the switch to complete. This register contains one decoded bit for each of the clock sources enumerated in the CTRL SRC field. At most one of these bits will be set at any time, indicating that clock is currently present at the output of the glitchless mux. Whilst switching is in progress, this register may briefly show all-0s.", + "offset": 56, + "size": 32, + "reset_value": 1, + "access": "read-only" + }, + "CLK_SYS_CTRL": { + "description": "Clock control, can be changed on-the-fly (except for auxsrc)", + "offset": 60, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "AUXSRC": { + "description": "Selects the auxiliary clock source, will glitch when switching", + "offset": 5, + "size": 3, + "enum": { + "size": 3, + "children": { + "enum_fields": { + "clksrc_pll_sys": { + "value": 0 + }, + "clksrc_pll_usb": { + "value": 1 + }, + "rosc_clksrc": { + "value": 2 + }, + "xosc_clksrc": { + "value": 3 + }, + "clksrc_gpin0": { + "value": 4 + }, + "clksrc_gpin1": { + "value": 5 + } + } + } + } + }, + "SRC": { + "description": "Selects the clock source glitchlessly, can be changed on-the-fly", + "offset": 0, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "clk_ref": { + "value": 0 + }, + "clksrc_clk_sys_aux": { + "value": 1 + } + } + } + } + } + } + } + }, + "CLK_SYS_DIV": { + "description": "Clock divisor, can be changed on-the-fly", + "offset": 64, + "size": 32, + "reset_value": 256, + "children": { + "fields": { + "INT": { + "description": "Integer component of the divisor, 0 -> divide by 2^16", + "offset": 8, + "size": 24 + }, + "FRAC": { + "description": "Fractional component of the divisor", + "offset": 0, + "size": 8 + } + } + } + }, + "CLK_SYS_SELECTED": { + "description": "Indicates which SRC is currently selected by the glitchless mux (one-hot).\\n\n The glitchless multiplexer does not switch instantaneously (to avoid glitches), so software should poll this register to wait for the switch to complete. This register contains one decoded bit for each of the clock sources enumerated in the CTRL SRC field. At most one of these bits will be set at any time, indicating that clock is currently present at the output of the glitchless mux. Whilst switching is in progress, this register may briefly show all-0s.", + "offset": 68, + "size": 32, + "reset_value": 1, + "access": "read-only" + }, + "CLK_PERI_CTRL": { + "description": "Clock control, can be changed on-the-fly (except for auxsrc)", + "offset": 72, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Starts and stops the clock generator cleanly", + "offset": 11, + "size": 1 + }, + "KILL": { + "description": "Asynchronously kills the clock generator", + "offset": 10, + "size": 1 + }, + "AUXSRC": { + "description": "Selects the auxiliary clock source, will glitch when switching", + "offset": 5, + "size": 3, + "enum": { + "size": 3, + "children": { + "enum_fields": { + "clk_sys": { + "value": 0 + }, + "clksrc_pll_sys": { + "value": 1 + }, + "clksrc_pll_usb": { + "value": 2 + }, + "rosc_clksrc_ph": { + "value": 3 + }, + "xosc_clksrc": { + "value": 4 + }, + "clksrc_gpin0": { + "value": 5 + }, + "clksrc_gpin1": { + "value": 6 + } + } + } + } + } + } + } + }, + "CLK_PERI_SELECTED": { + "description": "Indicates which SRC is currently selected by the glitchless mux (one-hot).\\n\n This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1.", + "offset": 80, + "size": 32, + "reset_value": 1, + "access": "read-only" + }, + "CLK_USB_CTRL": { + "description": "Clock control, can be changed on-the-fly (except for auxsrc)", + "offset": 84, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "NUDGE": { + "description": "An edge on this signal shifts the phase of the output by 1 cycle of the input clock\\n\n This can be done at any time", + "offset": 20, + "size": 1 + }, + "PHASE": { + "description": "This delays the enable signal by up to 3 cycles of the input clock\\n\n This must be set before the clock is enabled to have any effect", + "offset": 16, + "size": 2 + }, + "ENABLE": { + "description": "Starts and stops the clock generator cleanly", + "offset": 11, + "size": 1 + }, + "KILL": { + "description": "Asynchronously kills the clock generator", + "offset": 10, + "size": 1 + }, + "AUXSRC": { + "description": "Selects the auxiliary clock source, will glitch when switching", + "offset": 5, + "size": 3, + "enum": { + "size": 3, + "children": { + "enum_fields": { + "clksrc_pll_usb": { + "value": 0 + }, + "clksrc_pll_sys": { + "value": 1 + }, + "rosc_clksrc_ph": { + "value": 2 + }, + "xosc_clksrc": { + "value": 3 + }, + "clksrc_gpin0": { + "value": 4 + }, + "clksrc_gpin1": { + "value": 5 + } + } + } + } + } + } + } + }, + "CLK_USB_DIV": { + "description": "Clock divisor, can be changed on-the-fly", + "offset": 88, + "size": 32, + "reset_value": 256, + "children": { + "fields": { + "INT": { + "description": "Integer component of the divisor, 0 -> divide by 2^16", + "offset": 8, + "size": 2 + } + } + } + }, + "CLK_USB_SELECTED": { + "description": "Indicates which SRC is currently selected by the glitchless mux (one-hot).\\n\n This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1.", + "offset": 92, + "size": 32, + "reset_value": 1, + "access": "read-only" + }, + "CLK_ADC_CTRL": { + "description": "Clock control, can be changed on-the-fly (except for auxsrc)", + "offset": 96, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "NUDGE": { + "description": "An edge on this signal shifts the phase of the output by 1 cycle of the input clock\\n\n This can be done at any time", + "offset": 20, + "size": 1 + }, + "PHASE": { + "description": "This delays the enable signal by up to 3 cycles of the input clock\\n\n This must be set before the clock is enabled to have any effect", + "offset": 16, + "size": 2 + }, + "ENABLE": { + "description": "Starts and stops the clock generator cleanly", + "offset": 11, + "size": 1 + }, + "KILL": { + "description": "Asynchronously kills the clock generator", + "offset": 10, + "size": 1 + }, + "AUXSRC": { + "description": "Selects the auxiliary clock source, will glitch when switching", + "offset": 5, + "size": 3, + "enum": { + "size": 3, + "children": { + "enum_fields": { + "clksrc_pll_usb": { + "value": 0 + }, + "clksrc_pll_sys": { + "value": 1 + }, + "rosc_clksrc_ph": { + "value": 2 + }, + "xosc_clksrc": { + "value": 3 + }, + "clksrc_gpin0": { + "value": 4 + }, + "clksrc_gpin1": { + "value": 5 + } + } + } + } + } + } + } + }, + "CLK_ADC_DIV": { + "description": "Clock divisor, can be changed on-the-fly", + "offset": 100, + "size": 32, + "reset_value": 256, + "children": { + "fields": { + "INT": { + "description": "Integer component of the divisor, 0 -> divide by 2^16", + "offset": 8, + "size": 2 + } + } + } + }, + "CLK_ADC_SELECTED": { + "description": "Indicates which SRC is currently selected by the glitchless mux (one-hot).\\n\n This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1.", + "offset": 104, + "size": 32, + "reset_value": 1, + "access": "read-only" + }, + "CLK_RTC_CTRL": { + "description": "Clock control, can be changed on-the-fly (except for auxsrc)", + "offset": 108, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "NUDGE": { + "description": "An edge on this signal shifts the phase of the output by 1 cycle of the input clock\\n\n This can be done at any time", + "offset": 20, + "size": 1 + }, + "PHASE": { + "description": "This delays the enable signal by up to 3 cycles of the input clock\\n\n This must be set before the clock is enabled to have any effect", + "offset": 16, + "size": 2 + }, + "ENABLE": { + "description": "Starts and stops the clock generator cleanly", + "offset": 11, + "size": 1 + }, + "KILL": { + "description": "Asynchronously kills the clock generator", + "offset": 10, + "size": 1 + }, + "AUXSRC": { + "description": "Selects the auxiliary clock source, will glitch when switching", + "offset": 5, + "size": 3, + "enum": { + "size": 3, + "children": { + "enum_fields": { + "clksrc_pll_usb": { + "value": 0 + }, + "clksrc_pll_sys": { + "value": 1 + }, + "rosc_clksrc_ph": { + "value": 2 + }, + "xosc_clksrc": { + "value": 3 + }, + "clksrc_gpin0": { + "value": 4 + }, + "clksrc_gpin1": { + "value": 5 + } + } + } + } + } + } + } + }, + "CLK_RTC_DIV": { + "description": "Clock divisor, can be changed on-the-fly", + "offset": 112, + "size": 32, + "reset_value": 256, + "children": { + "fields": { + "INT": { + "description": "Integer component of the divisor, 0 -> divide by 2^16", + "offset": 8, + "size": 24 + }, + "FRAC": { + "description": "Fractional component of the divisor", + "offset": 0, + "size": 8 + } + } + } + }, + "CLK_RTC_SELECTED": { + "description": "Indicates which SRC is currently selected by the glitchless mux (one-hot).\\n\n This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1.", + "offset": 116, + "size": 32, + "reset_value": 1, + "access": "read-only" + }, + "CLK_SYS_RESUS_CTRL": { + "offset": 120, + "size": 32, + "reset_value": 255, + "children": { + "fields": { + "CLEAR": { + "description": "For clearing the resus after the fault that triggered it has been corrected", + "offset": 16, + "size": 1 + }, + "FRCE": { + "description": "Force a resus, for test purposes only", + "offset": 12, + "size": 1 + }, + "ENABLE": { + "description": "Enable resus", + "offset": 8, + "size": 1 + }, + "TIMEOUT": { + "description": "This is expressed as a number of clk_ref cycles\\n\n and must be >= 2x clk_ref_freq/min_clk_tst_freq", + "offset": 0, + "size": 8 + } + } + } + }, + "CLK_SYS_RESUS_STATUS": { + "offset": 124, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "RESUSSED": { + "description": "Clock has been resuscitated, correct the error then send ctrl_clear=1", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "FC0_REF_KHZ": { + "description": "Reference clock frequency in kHz", + "offset": 128, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FC0_REF_KHZ": { + "offset": 0, + "size": 20 + } + } + } + }, + "FC0_MIN_KHZ": { + "description": "Minimum pass frequency in kHz. This is optional. Set to 0 if you are not using the pass/fail flags", + "offset": 132, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FC0_MIN_KHZ": { + "offset": 0, + "size": 25 + } + } + } + }, + "FC0_MAX_KHZ": { + "description": "Maximum pass frequency in kHz. This is optional. Set to 0x1ffffff if you are not using the pass/fail flags", + "offset": 136, + "size": 32, + "reset_value": 33554431, + "children": { + "fields": { + "FC0_MAX_KHZ": { + "offset": 0, + "size": 25 + } + } + } + }, + "FC0_DELAY": { + "description": "Delays the start of frequency counting to allow the mux to settle\\n\n Delay is measured in multiples of the reference clock period", + "offset": 140, + "size": 32, + "reset_value": 1, + "children": { + "fields": { + "FC0_DELAY": { + "offset": 0, + "size": 3 + } + } + } + }, + "FC0_INTERVAL": { + "description": "The test interval is 0.98us * 2**interval, but let's call it 1us * 2**interval\\n\n The default gives a test interval of 250us", + "offset": 144, + "size": 32, + "reset_value": 8, + "children": { + "fields": { + "FC0_INTERVAL": { + "offset": 0, + "size": 4 + } + } + } + }, + "FC0_SRC": { + "description": "Clock sent to frequency counter, set to 0 when not required\\n\n Writing to this register initiates the frequency count", + "offset": 148, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FC0_SRC": { + "offset": 0, + "size": 8, + "enum": { + "size": 8, + "children": { + "enum_fields": { + "NULL": { + "value": 0 + }, + "pll_sys_clksrc_primary": { + "value": 1 + }, + "pll_usb_clksrc_primary": { + "value": 2 + }, + "rosc_clksrc": { + "value": 3 + }, + "rosc_clksrc_ph": { + "value": 4 + }, + "xosc_clksrc": { + "value": 5 + }, + "clksrc_gpin0": { + "value": 6 + }, + "clksrc_gpin1": { + "value": 7 + }, + "clk_ref": { + "value": 8 + }, + "clk_sys": { + "value": 9 + }, + "clk_peri": { + "value": 10 + }, + "clk_usb": { + "value": 11 + }, + "clk_adc": { + "value": 12 + }, + "clk_rtc": { + "value": 13 + } + } + } + } + } + } + } + }, + "FC0_STATUS": { + "description": "Frequency counter status", + "offset": 152, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "DIED": { + "description": "Test clock stopped during test", + "offset": 28, + "size": 1, + "access": "read-only" + }, + "FAST": { + "description": "Test clock faster than expected, only valid when status_done=1", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "SLOW": { + "description": "Test clock slower than expected, only valid when status_done=1", + "offset": 20, + "size": 1, + "access": "read-only" + }, + "FAIL": { + "description": "Test failed", + "offset": 16, + "size": 1, + "access": "read-only" + }, + "WAITING": { + "description": "Waiting for test clock to start", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "RUNNING": { + "description": "Test running", + "offset": 8, + "size": 1, + "access": "read-only" + }, + "DONE": { + "description": "Test complete", + "offset": 4, + "size": 1, + "access": "read-only" + }, + "PASS": { + "description": "Test passed", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "FC0_RESULT": { + "description": "Result of frequency measurement, only valid when status_done=1", + "offset": 156, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "KHZ": { + "offset": 5, + "size": 25, + "access": "read-only" + }, + "FRAC": { + "offset": 0, + "size": 5, + "access": "read-only" + } + } + } + }, + "WAKE_EN0": { + "description": "enable clock in wake mode", + "offset": 160, + "size": 32, + "reset_value": 4294967295, + "children": { + "fields": { + "clk_sys_sram3": { + "offset": 31, + "size": 1 + }, + "clk_sys_sram2": { + "offset": 30, + "size": 1 + }, + "clk_sys_sram1": { + "offset": 29, + "size": 1 + }, + "clk_sys_sram0": { + "offset": 28, + "size": 1 + }, + "clk_sys_spi1": { + "offset": 27, + "size": 1 + }, + "clk_peri_spi1": { + "offset": 26, + "size": 1 + }, + "clk_sys_spi0": { + "offset": 25, + "size": 1 + }, + "clk_peri_spi0": { + "offset": 24, + "size": 1 + }, + "clk_sys_sio": { + "offset": 23, + "size": 1 + }, + "clk_sys_rtc": { + "offset": 22, + "size": 1 + }, + "clk_rtc_rtc": { + "offset": 21, + "size": 1 + }, + "clk_sys_rosc": { + "offset": 20, + "size": 1 + }, + "clk_sys_rom": { + "offset": 19, + "size": 1 + }, + "clk_sys_resets": { + "offset": 18, + "size": 1 + }, + "clk_sys_pwm": { + "offset": 17, + "size": 1 + }, + "clk_sys_psm": { + "offset": 16, + "size": 1 + }, + "clk_sys_pll_usb": { + "offset": 15, + "size": 1 + }, + "clk_sys_pll_sys": { + "offset": 14, + "size": 1 + }, + "clk_sys_pio1": { + "offset": 13, + "size": 1 + }, + "clk_sys_pio0": { + "offset": 12, + "size": 1 + }, + "clk_sys_pads": { + "offset": 11, + "size": 1 + }, + "clk_sys_vreg_and_chip_reset": { + "offset": 10, + "size": 1 + }, + "clk_sys_jtag": { + "offset": 9, + "size": 1 + }, + "clk_sys_io": { + "offset": 8, + "size": 1 + }, + "clk_sys_i2c1": { + "offset": 7, + "size": 1 + }, + "clk_sys_i2c0": { + "offset": 6, + "size": 1 + }, + "clk_sys_dma": { + "offset": 5, + "size": 1 + }, + "clk_sys_busfabric": { + "offset": 4, + "size": 1 + }, + "clk_sys_busctrl": { + "offset": 3, + "size": 1 + }, + "clk_sys_adc": { + "offset": 2, + "size": 1 + }, + "clk_adc_adc": { + "offset": 1, + "size": 1 + }, + "clk_sys_clocks": { + "offset": 0, + "size": 1 + } + } + } + }, + "WAKE_EN1": { + "description": "enable clock in wake mode", + "offset": 164, + "size": 32, + "reset_value": 32767, + "children": { + "fields": { + "clk_sys_xosc": { + "offset": 14, + "size": 1 + }, + "clk_sys_xip": { + "offset": 13, + "size": 1 + }, + "clk_sys_watchdog": { + "offset": 12, + "size": 1 + }, + "clk_usb_usbctrl": { + "offset": 11, + "size": 1 + }, + "clk_sys_usbctrl": { + "offset": 10, + "size": 1 + }, + "clk_sys_uart1": { + "offset": 9, + "size": 1 + }, + "clk_peri_uart1": { + "offset": 8, + "size": 1 + }, + "clk_sys_uart0": { + "offset": 7, + "size": 1 + }, + "clk_peri_uart0": { + "offset": 6, + "size": 1 + }, + "clk_sys_timer": { + "offset": 5, + "size": 1 + }, + "clk_sys_tbman": { + "offset": 4, + "size": 1 + }, + "clk_sys_sysinfo": { + "offset": 3, + "size": 1 + }, + "clk_sys_syscfg": { + "offset": 2, + "size": 1 + }, + "clk_sys_sram5": { + "offset": 1, + "size": 1 + }, + "clk_sys_sram4": { + "offset": 0, + "size": 1 + } + } + } + }, + "SLEEP_EN0": { + "description": "enable clock in sleep mode", + "offset": 168, + "size": 32, + "reset_value": 4294967295, + "children": { + "fields": { + "clk_sys_sram3": { + "offset": 31, + "size": 1 + }, + "clk_sys_sram2": { + "offset": 30, + "size": 1 + }, + "clk_sys_sram1": { + "offset": 29, + "size": 1 + }, + "clk_sys_sram0": { + "offset": 28, + "size": 1 + }, + "clk_sys_spi1": { + "offset": 27, + "size": 1 + }, + "clk_peri_spi1": { + "offset": 26, + "size": 1 + }, + "clk_sys_spi0": { + "offset": 25, + "size": 1 + }, + "clk_peri_spi0": { + "offset": 24, + "size": 1 + }, + "clk_sys_sio": { + "offset": 23, + "size": 1 + }, + "clk_sys_rtc": { + "offset": 22, + "size": 1 + }, + "clk_rtc_rtc": { + "offset": 21, + "size": 1 + }, + "clk_sys_rosc": { + "offset": 20, + "size": 1 + }, + "clk_sys_rom": { + "offset": 19, + "size": 1 + }, + "clk_sys_resets": { + "offset": 18, + "size": 1 + }, + "clk_sys_pwm": { + "offset": 17, + "size": 1 + }, + "clk_sys_psm": { + "offset": 16, + "size": 1 + }, + "clk_sys_pll_usb": { + "offset": 15, + "size": 1 + }, + "clk_sys_pll_sys": { + "offset": 14, + "size": 1 + }, + "clk_sys_pio1": { + "offset": 13, + "size": 1 + }, + "clk_sys_pio0": { + "offset": 12, + "size": 1 + }, + "clk_sys_pads": { + "offset": 11, + "size": 1 + }, + "clk_sys_vreg_and_chip_reset": { + "offset": 10, + "size": 1 + }, + "clk_sys_jtag": { + "offset": 9, + "size": 1 + }, + "clk_sys_io": { + "offset": 8, + "size": 1 + }, + "clk_sys_i2c1": { + "offset": 7, + "size": 1 + }, + "clk_sys_i2c0": { + "offset": 6, + "size": 1 + }, + "clk_sys_dma": { + "offset": 5, + "size": 1 + }, + "clk_sys_busfabric": { + "offset": 4, + "size": 1 + }, + "clk_sys_busctrl": { + "offset": 3, + "size": 1 + }, + "clk_sys_adc": { + "offset": 2, + "size": 1 + }, + "clk_adc_adc": { + "offset": 1, + "size": 1 + }, + "clk_sys_clocks": { + "offset": 0, + "size": 1 + } + } + } + }, + "SLEEP_EN1": { + "description": "enable clock in sleep mode", + "offset": 172, + "size": 32, + "reset_value": 32767, + "children": { + "fields": { + "clk_sys_xosc": { + "offset": 14, + "size": 1 + }, + "clk_sys_xip": { + "offset": 13, + "size": 1 + }, + "clk_sys_watchdog": { + "offset": 12, + "size": 1 + }, + "clk_usb_usbctrl": { + "offset": 11, + "size": 1 + }, + "clk_sys_usbctrl": { + "offset": 10, + "size": 1 + }, + "clk_sys_uart1": { + "offset": 9, + "size": 1 + }, + "clk_peri_uart1": { + "offset": 8, + "size": 1 + }, + "clk_sys_uart0": { + "offset": 7, + "size": 1 + }, + "clk_peri_uart0": { + "offset": 6, + "size": 1 + }, + "clk_sys_timer": { + "offset": 5, + "size": 1 + }, + "clk_sys_tbman": { + "offset": 4, + "size": 1 + }, + "clk_sys_sysinfo": { + "offset": 3, + "size": 1 + }, + "clk_sys_syscfg": { + "offset": 2, + "size": 1 + }, + "clk_sys_sram5": { + "offset": 1, + "size": 1 + }, + "clk_sys_sram4": { + "offset": 0, + "size": 1 + } + } + } + }, + "ENABLED0": { + "description": "indicates the state of the clock enable", + "offset": 176, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "clk_sys_sram3": { + "offset": 31, + "size": 1, + "access": "read-only" + }, + "clk_sys_sram2": { + "offset": 30, + "size": 1, + "access": "read-only" + }, + "clk_sys_sram1": { + "offset": 29, + "size": 1, + "access": "read-only" + }, + "clk_sys_sram0": { + "offset": 28, + "size": 1, + "access": "read-only" + }, + "clk_sys_spi1": { + "offset": 27, + "size": 1, + "access": "read-only" + }, + "clk_peri_spi1": { + "offset": 26, + "size": 1, + "access": "read-only" + }, + "clk_sys_spi0": { + "offset": 25, + "size": 1, + "access": "read-only" + }, + "clk_peri_spi0": { + "offset": 24, + "size": 1, + "access": "read-only" + }, + "clk_sys_sio": { + "offset": 23, + "size": 1, + "access": "read-only" + }, + "clk_sys_rtc": { + "offset": 22, + "size": 1, + "access": "read-only" + }, + "clk_rtc_rtc": { + "offset": 21, + "size": 1, + "access": "read-only" + }, + "clk_sys_rosc": { + "offset": 20, + "size": 1, + "access": "read-only" + }, + "clk_sys_rom": { + "offset": 19, + "size": 1, + "access": "read-only" + }, + "clk_sys_resets": { + "offset": 18, + "size": 1, + "access": "read-only" + }, + "clk_sys_pwm": { + "offset": 17, + "size": 1, + "access": "read-only" + }, + "clk_sys_psm": { + "offset": 16, + "size": 1, + "access": "read-only" + }, + "clk_sys_pll_usb": { + "offset": 15, + "size": 1, + "access": "read-only" + }, + "clk_sys_pll_sys": { + "offset": 14, + "size": 1, + "access": "read-only" + }, + "clk_sys_pio1": { + "offset": 13, + "size": 1, + "access": "read-only" + }, + "clk_sys_pio0": { + "offset": 12, + "size": 1, + "access": "read-only" + }, + "clk_sys_pads": { + "offset": 11, + "size": 1, + "access": "read-only" + }, + "clk_sys_vreg_and_chip_reset": { + "offset": 10, + "size": 1, + "access": "read-only" + }, + "clk_sys_jtag": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "clk_sys_io": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "clk_sys_i2c1": { + "offset": 7, + "size": 1, + "access": "read-only" + }, + "clk_sys_i2c0": { + "offset": 6, + "size": 1, + "access": "read-only" + }, + "clk_sys_dma": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "clk_sys_busfabric": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "clk_sys_busctrl": { + "offset": 3, + "size": 1, + "access": "read-only" + }, + "clk_sys_adc": { + "offset": 2, + "size": 1, + "access": "read-only" + }, + "clk_adc_adc": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "clk_sys_clocks": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "ENABLED1": { + "description": "indicates the state of the clock enable", + "offset": 180, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "clk_sys_xosc": { + "offset": 14, + "size": 1, + "access": "read-only" + }, + "clk_sys_xip": { + "offset": 13, + "size": 1, + "access": "read-only" + }, + "clk_sys_watchdog": { + "offset": 12, + "size": 1, + "access": "read-only" + }, + "clk_usb_usbctrl": { + "offset": 11, + "size": 1, + "access": "read-only" + }, + "clk_sys_usbctrl": { + "offset": 10, + "size": 1, + "access": "read-only" + }, + "clk_sys_uart1": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "clk_peri_uart1": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "clk_sys_uart0": { + "offset": 7, + "size": 1, + "access": "read-only" + }, + "clk_peri_uart0": { + "offset": 6, + "size": 1, + "access": "read-only" + }, + "clk_sys_timer": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "clk_sys_tbman": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "clk_sys_sysinfo": { + "offset": 3, + "size": 1, + "access": "read-only" + }, + "clk_sys_syscfg": { + "offset": 2, + "size": 1, + "access": "read-only" + }, + "clk_sys_sram5": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "clk_sys_sram4": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "INTR": { + "description": "Raw Interrupts", + "offset": 184, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CLK_SYS_RESUS": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "INTE": { + "description": "Interrupt Enable", + "offset": 188, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CLK_SYS_RESUS": { + "offset": 0, + "size": 1 + } + } + } + }, + "INTF": { + "description": "Interrupt Force", + "offset": 192, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CLK_SYS_RESUS": { + "offset": 0, + "size": 1 + } + } + } + }, + "INTS": { + "description": "Interrupt status after masking & forcing", + "offset": 196, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CLK_SYS_RESUS": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + } + } + } + }, + "RESETS": { + "children": { + "registers": { + "RESET": { + "description": "Reset control. If a bit is set it means the peripheral is in reset. 0 means the peripheral's reset is deasserted.", + "offset": 0, + "size": 32, + "reset_value": 33554431, + "children": { + "fields": { + "usbctrl": { + "offset": 24, + "size": 1 + }, + "uart1": { + "offset": 23, + "size": 1 + }, + "uart0": { + "offset": 22, + "size": 1 + }, + "timer": { + "offset": 21, + "size": 1 + }, + "tbman": { + "offset": 20, + "size": 1 + }, + "sysinfo": { + "offset": 19, + "size": 1 + }, + "syscfg": { + "offset": 18, + "size": 1 + }, + "spi1": { + "offset": 17, + "size": 1 + }, + "spi0": { + "offset": 16, + "size": 1 + }, + "rtc": { + "offset": 15, + "size": 1 + }, + "pwm": { + "offset": 14, + "size": 1 + }, + "pll_usb": { + "offset": 13, + "size": 1 + }, + "pll_sys": { + "offset": 12, + "size": 1 + }, + "pio1": { + "offset": 11, + "size": 1 + }, + "pio0": { + "offset": 10, + "size": 1 + }, + "pads_qspi": { + "offset": 9, + "size": 1 + }, + "pads_bank0": { + "offset": 8, + "size": 1 + }, + "jtag": { + "offset": 7, + "size": 1 + }, + "io_qspi": { + "offset": 6, + "size": 1 + }, + "io_bank0": { + "offset": 5, + "size": 1 + }, + "i2c1": { + "offset": 4, + "size": 1 + }, + "i2c0": { + "offset": 3, + "size": 1 + }, + "dma": { + "offset": 2, + "size": 1 + }, + "busctrl": { + "offset": 1, + "size": 1 + }, + "adc": { + "offset": 0, + "size": 1 + } + } + } + }, + "WDSEL": { + "description": "Watchdog select. If a bit is set then the watchdog will reset this peripheral when the watchdog fires.", + "offset": 4, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "usbctrl": { + "offset": 24, + "size": 1 + }, + "uart1": { + "offset": 23, + "size": 1 + }, + "uart0": { + "offset": 22, + "size": 1 + }, + "timer": { + "offset": 21, + "size": 1 + }, + "tbman": { + "offset": 20, + "size": 1 + }, + "sysinfo": { + "offset": 19, + "size": 1 + }, + "syscfg": { + "offset": 18, + "size": 1 + }, + "spi1": { + "offset": 17, + "size": 1 + }, + "spi0": { + "offset": 16, + "size": 1 + }, + "rtc": { + "offset": 15, + "size": 1 + }, + "pwm": { + "offset": 14, + "size": 1 + }, + "pll_usb": { + "offset": 13, + "size": 1 + }, + "pll_sys": { + "offset": 12, + "size": 1 + }, + "pio1": { + "offset": 11, + "size": 1 + }, + "pio0": { + "offset": 10, + "size": 1 + }, + "pads_qspi": { + "offset": 9, + "size": 1 + }, + "pads_bank0": { + "offset": 8, + "size": 1 + }, + "jtag": { + "offset": 7, + "size": 1 + }, + "io_qspi": { + "offset": 6, + "size": 1 + }, + "io_bank0": { + "offset": 5, + "size": 1 + }, + "i2c1": { + "offset": 4, + "size": 1 + }, + "i2c0": { + "offset": 3, + "size": 1 + }, + "dma": { + "offset": 2, + "size": 1 + }, + "busctrl": { + "offset": 1, + "size": 1 + }, + "adc": { + "offset": 0, + "size": 1 + } + } + } + }, + "RESET_DONE": { + "description": "Reset done. If a bit is set then a reset done signal has been returned by the peripheral. This indicates that the peripheral's registers are ready to be accessed.", + "offset": 8, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "usbctrl": { + "offset": 24, + "size": 1, + "access": "read-only" + }, + "uart1": { + "offset": 23, + "size": 1, + "access": "read-only" + }, + "uart0": { + "offset": 22, + "size": 1, + "access": "read-only" + }, + "timer": { + "offset": 21, + "size": 1, + "access": "read-only" + }, + "tbman": { + "offset": 20, + "size": 1, + "access": "read-only" + }, + "sysinfo": { + "offset": 19, + "size": 1, + "access": "read-only" + }, + "syscfg": { + "offset": 18, + "size": 1, + "access": "read-only" + }, + "spi1": { + "offset": 17, + "size": 1, + "access": "read-only" + }, + "spi0": { + "offset": 16, + "size": 1, + "access": "read-only" + }, + "rtc": { + "offset": 15, + "size": 1, + "access": "read-only" + }, + "pwm": { + "offset": 14, + "size": 1, + "access": "read-only" + }, + "pll_usb": { + "offset": 13, + "size": 1, + "access": "read-only" + }, + "pll_sys": { + "offset": 12, + "size": 1, + "access": "read-only" + }, + "pio1": { + "offset": 11, + "size": 1, + "access": "read-only" + }, + "pio0": { + "offset": 10, + "size": 1, + "access": "read-only" + }, + "pads_qspi": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "pads_bank0": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "jtag": { + "offset": 7, + "size": 1, + "access": "read-only" + }, + "io_qspi": { + "offset": 6, + "size": 1, + "access": "read-only" + }, + "io_bank0": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "i2c1": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "i2c0": { + "offset": 3, + "size": 1, + "access": "read-only" + }, + "dma": { + "offset": 2, + "size": 1, + "access": "read-only" + }, + "busctrl": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "adc": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + } + } + } + }, + "PSM": { + "children": { + "registers": { + "FRCE_ON": { + "description": "Force block out of reset (i.e. power it on)", + "offset": 0, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "proc1": { + "offset": 16, + "size": 1 + }, + "proc0": { + "offset": 15, + "size": 1 + }, + "sio": { + "offset": 14, + "size": 1 + }, + "vreg_and_chip_reset": { + "offset": 13, + "size": 1 + }, + "xip": { + "offset": 12, + "size": 1 + }, + "sram5": { + "offset": 11, + "size": 1 + }, + "sram4": { + "offset": 10, + "size": 1 + }, + "sram3": { + "offset": 9, + "size": 1 + }, + "sram2": { + "offset": 8, + "size": 1 + }, + "sram1": { + "offset": 7, + "size": 1 + }, + "sram0": { + "offset": 6, + "size": 1 + }, + "rom": { + "offset": 5, + "size": 1 + }, + "busfabric": { + "offset": 4, + "size": 1 + }, + "resets": { + "offset": 3, + "size": 1 + }, + "clocks": { + "offset": 2, + "size": 1 + }, + "xosc": { + "offset": 1, + "size": 1 + }, + "rosc": { + "offset": 0, + "size": 1 + } + } + } + }, + "FRCE_OFF": { + "description": "Force into reset (i.e. power it off)", + "offset": 4, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "proc1": { + "offset": 16, + "size": 1 + }, + "proc0": { + "offset": 15, + "size": 1 + }, + "sio": { + "offset": 14, + "size": 1 + }, + "vreg_and_chip_reset": { + "offset": 13, + "size": 1 + }, + "xip": { + "offset": 12, + "size": 1 + }, + "sram5": { + "offset": 11, + "size": 1 + }, + "sram4": { + "offset": 10, + "size": 1 + }, + "sram3": { + "offset": 9, + "size": 1 + }, + "sram2": { + "offset": 8, + "size": 1 + }, + "sram1": { + "offset": 7, + "size": 1 + }, + "sram0": { + "offset": 6, + "size": 1 + }, + "rom": { + "offset": 5, + "size": 1 + }, + "busfabric": { + "offset": 4, + "size": 1 + }, + "resets": { + "offset": 3, + "size": 1 + }, + "clocks": { + "offset": 2, + "size": 1 + }, + "xosc": { + "offset": 1, + "size": 1 + }, + "rosc": { + "offset": 0, + "size": 1 + } + } + } + }, + "WDSEL": { + "description": "Set to 1 if this peripheral should be reset when the watchdog fires.", + "offset": 8, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "proc1": { + "offset": 16, + "size": 1 + }, + "proc0": { + "offset": 15, + "size": 1 + }, + "sio": { + "offset": 14, + "size": 1 + }, + "vreg_and_chip_reset": { + "offset": 13, + "size": 1 + }, + "xip": { + "offset": 12, + "size": 1 + }, + "sram5": { + "offset": 11, + "size": 1 + }, + "sram4": { + "offset": 10, + "size": 1 + }, + "sram3": { + "offset": 9, + "size": 1 + }, + "sram2": { + "offset": 8, + "size": 1 + }, + "sram1": { + "offset": 7, + "size": 1 + }, + "sram0": { + "offset": 6, + "size": 1 + }, + "rom": { + "offset": 5, + "size": 1 + }, + "busfabric": { + "offset": 4, + "size": 1 + }, + "resets": { + "offset": 3, + "size": 1 + }, + "clocks": { + "offset": 2, + "size": 1 + }, + "xosc": { + "offset": 1, + "size": 1 + }, + "rosc": { + "offset": 0, + "size": 1 + } + } + } + }, + "DONE": { + "description": "Indicates the peripheral's registers are ready to access.", + "offset": 12, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "proc1": { + "offset": 16, + "size": 1, + "access": "read-only" + }, + "proc0": { + "offset": 15, + "size": 1, + "access": "read-only" + }, + "sio": { + "offset": 14, + "size": 1, + "access": "read-only" + }, + "vreg_and_chip_reset": { + "offset": 13, + "size": 1, + "access": "read-only" + }, + "xip": { + "offset": 12, + "size": 1, + "access": "read-only" + }, + "sram5": { + "offset": 11, + "size": 1, + "access": "read-only" + }, + "sram4": { + "offset": 10, + "size": 1, + "access": "read-only" + }, + "sram3": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "sram2": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "sram1": { + "offset": 7, + "size": 1, + "access": "read-only" + }, + "sram0": { + "offset": 6, + "size": 1, + "access": "read-only" + }, + "rom": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "busfabric": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "resets": { + "offset": 3, + "size": 1, + "access": "read-only" + }, + "clocks": { + "offset": 2, + "size": 1, + "access": "read-only" + }, + "xosc": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "rosc": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + } + } + } + }, + "IO_BANK0": { + "children": { + "registers": { + "GPIO0_STATUS": { + "description": "GPIO status", + "offset": 0, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO0_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 4, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "jtag_tck": { + "value": 0 + }, + "spi0_rx": { + "value": 1 + }, + "uart0_tx": { + "value": 2 + }, + "i2c0_sda": { + "value": 3 + }, + "pwm_a_0": { + "value": 4 + }, + "sio_0": { + "value": 5 + }, + "pio0_0": { + "value": 6 + }, + "pio1_0": { + "value": 7 + }, + "usb_muxing_overcurr_detect": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO1_STATUS": { + "description": "GPIO status", + "offset": 8, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO1_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 12, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "jtag_tms": { + "value": 0 + }, + "spi0_ss_n": { + "value": 1 + }, + "uart0_rx": { + "value": 2 + }, + "i2c0_scl": { + "value": 3 + }, + "pwm_b_0": { + "value": 4 + }, + "sio_1": { + "value": 5 + }, + "pio0_1": { + "value": 6 + }, + "pio1_1": { + "value": 7 + }, + "usb_muxing_vbus_detect": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO2_STATUS": { + "description": "GPIO status", + "offset": 16, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO2_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 20, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "jtag_tdi": { + "value": 0 + }, + "spi0_sclk": { + "value": 1 + }, + "uart0_cts": { + "value": 2 + }, + "i2c1_sda": { + "value": 3 + }, + "pwm_a_1": { + "value": 4 + }, + "sio_2": { + "value": 5 + }, + "pio0_2": { + "value": 6 + }, + "pio1_2": { + "value": 7 + }, + "usb_muxing_vbus_en": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO3_STATUS": { + "description": "GPIO status", + "offset": 24, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO3_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 28, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "jtag_tdo": { + "value": 0 + }, + "spi0_tx": { + "value": 1 + }, + "uart0_rts": { + "value": 2 + }, + "i2c1_scl": { + "value": 3 + }, + "pwm_b_1": { + "value": 4 + }, + "sio_3": { + "value": 5 + }, + "pio0_3": { + "value": 6 + }, + "pio1_3": { + "value": 7 + }, + "usb_muxing_overcurr_detect": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO4_STATUS": { + "description": "GPIO status", + "offset": 32, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO4_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 36, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "spi0_rx": { + "value": 1 + }, + "uart1_tx": { + "value": 2 + }, + "i2c0_sda": { + "value": 3 + }, + "pwm_a_2": { + "value": 4 + }, + "sio_4": { + "value": 5 + }, + "pio0_4": { + "value": 6 + }, + "pio1_4": { + "value": 7 + }, + "usb_muxing_vbus_detect": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO5_STATUS": { + "description": "GPIO status", + "offset": 40, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO5_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 44, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "spi0_ss_n": { + "value": 1 + }, + "uart1_rx": { + "value": 2 + }, + "i2c0_scl": { + "value": 3 + }, + "pwm_b_2": { + "value": 4 + }, + "sio_5": { + "value": 5 + }, + "pio0_5": { + "value": 6 + }, + "pio1_5": { + "value": 7 + }, + "usb_muxing_vbus_en": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO6_STATUS": { + "description": "GPIO status", + "offset": 48, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO6_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 52, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "spi0_sclk": { + "value": 1 + }, + "uart1_cts": { + "value": 2 + }, + "i2c1_sda": { + "value": 3 + }, + "pwm_a_3": { + "value": 4 + }, + "sio_6": { + "value": 5 + }, + "pio0_6": { + "value": 6 + }, + "pio1_6": { + "value": 7 + }, + "usb_muxing_extphy_softcon": { + "value": 8 + }, + "usb_muxing_overcurr_detect": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO7_STATUS": { + "description": "GPIO status", + "offset": 56, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO7_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 60, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "spi0_tx": { + "value": 1 + }, + "uart1_rts": { + "value": 2 + }, + "i2c1_scl": { + "value": 3 + }, + "pwm_b_3": { + "value": 4 + }, + "sio_7": { + "value": 5 + }, + "pio0_7": { + "value": 6 + }, + "pio1_7": { + "value": 7 + }, + "usb_muxing_extphy_oe_n": { + "value": 8 + }, + "usb_muxing_vbus_detect": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO8_STATUS": { + "description": "GPIO status", + "offset": 64, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO8_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 68, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "spi1_rx": { + "value": 1 + }, + "uart1_tx": { + "value": 2 + }, + "i2c0_sda": { + "value": 3 + }, + "pwm_a_4": { + "value": 4 + }, + "sio_8": { + "value": 5 + }, + "pio0_8": { + "value": 6 + }, + "pio1_8": { + "value": 7 + }, + "usb_muxing_extphy_rcv": { + "value": 8 + }, + "usb_muxing_vbus_en": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO9_STATUS": { + "description": "GPIO status", + "offset": 72, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO9_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 76, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "spi1_ss_n": { + "value": 1 + }, + "uart1_rx": { + "value": 2 + }, + "i2c0_scl": { + "value": 3 + }, + "pwm_b_4": { + "value": 4 + }, + "sio_9": { + "value": 5 + }, + "pio0_9": { + "value": 6 + }, + "pio1_9": { + "value": 7 + }, + "usb_muxing_extphy_vp": { + "value": 8 + }, + "usb_muxing_overcurr_detect": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO10_STATUS": { + "description": "GPIO status", + "offset": 80, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO10_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 84, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "spi1_sclk": { + "value": 1 + }, + "uart1_cts": { + "value": 2 + }, + "i2c1_sda": { + "value": 3 + }, + "pwm_a_5": { + "value": 4 + }, + "sio_10": { + "value": 5 + }, + "pio0_10": { + "value": 6 + }, + "pio1_10": { + "value": 7 + }, + "usb_muxing_extphy_vm": { + "value": 8 + }, + "usb_muxing_vbus_detect": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO11_STATUS": { + "description": "GPIO status", + "offset": 88, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO11_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 92, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "spi1_tx": { + "value": 1 + }, + "uart1_rts": { + "value": 2 + }, + "i2c1_scl": { + "value": 3 + }, + "pwm_b_5": { + "value": 4 + }, + "sio_11": { + "value": 5 + }, + "pio0_11": { + "value": 6 + }, + "pio1_11": { + "value": 7 + }, + "usb_muxing_extphy_suspnd": { + "value": 8 + }, + "usb_muxing_vbus_en": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO12_STATUS": { + "description": "GPIO status", + "offset": 96, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO12_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 100, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "spi1_rx": { + "value": 1 + }, + "uart0_tx": { + "value": 2 + }, + "i2c0_sda": { + "value": 3 + }, + "pwm_a_6": { + "value": 4 + }, + "sio_12": { + "value": 5 + }, + "pio0_12": { + "value": 6 + }, + "pio1_12": { + "value": 7 + }, + "usb_muxing_extphy_speed": { + "value": 8 + }, + "usb_muxing_overcurr_detect": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO13_STATUS": { + "description": "GPIO status", + "offset": 104, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO13_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 108, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "spi1_ss_n": { + "value": 1 + }, + "uart0_rx": { + "value": 2 + }, + "i2c0_scl": { + "value": 3 + }, + "pwm_b_6": { + "value": 4 + }, + "sio_13": { + "value": 5 + }, + "pio0_13": { + "value": 6 + }, + "pio1_13": { + "value": 7 + }, + "usb_muxing_extphy_vpo": { + "value": 8 + }, + "usb_muxing_vbus_detect": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO14_STATUS": { + "description": "GPIO status", + "offset": 112, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO14_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 116, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "spi1_sclk": { + "value": 1 + }, + "uart0_cts": { + "value": 2 + }, + "i2c1_sda": { + "value": 3 + }, + "pwm_a_7": { + "value": 4 + }, + "sio_14": { + "value": 5 + }, + "pio0_14": { + "value": 6 + }, + "pio1_14": { + "value": 7 + }, + "usb_muxing_extphy_vmo": { + "value": 8 + }, + "usb_muxing_vbus_en": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO15_STATUS": { + "description": "GPIO status", + "offset": 120, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO15_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 124, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "spi1_tx": { + "value": 1 + }, + "uart0_rts": { + "value": 2 + }, + "i2c1_scl": { + "value": 3 + }, + "pwm_b_7": { + "value": 4 + }, + "sio_15": { + "value": 5 + }, + "pio0_15": { + "value": 6 + }, + "pio1_15": { + "value": 7 + }, + "usb_muxing_digital_dp": { + "value": 8 + }, + "usb_muxing_overcurr_detect": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO16_STATUS": { + "description": "GPIO status", + "offset": 128, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO16_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 132, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "spi0_rx": { + "value": 1 + }, + "uart0_tx": { + "value": 2 + }, + "i2c0_sda": { + "value": 3 + }, + "pwm_a_0": { + "value": 4 + }, + "sio_16": { + "value": 5 + }, + "pio0_16": { + "value": 6 + }, + "pio1_16": { + "value": 7 + }, + "usb_muxing_digital_dm": { + "value": 8 + }, + "usb_muxing_vbus_detect": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO17_STATUS": { + "description": "GPIO status", + "offset": 136, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO17_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 140, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "spi0_ss_n": { + "value": 1 + }, + "uart0_rx": { + "value": 2 + }, + "i2c0_scl": { + "value": 3 + }, + "pwm_b_0": { + "value": 4 + }, + "sio_17": { + "value": 5 + }, + "pio0_17": { + "value": 6 + }, + "pio1_17": { + "value": 7 + }, + "usb_muxing_vbus_en": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO18_STATUS": { + "description": "GPIO status", + "offset": 144, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO18_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 148, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "spi0_sclk": { + "value": 1 + }, + "uart0_cts": { + "value": 2 + }, + "i2c1_sda": { + "value": 3 + }, + "pwm_a_1": { + "value": 4 + }, + "sio_18": { + "value": 5 + }, + "pio0_18": { + "value": 6 + }, + "pio1_18": { + "value": 7 + }, + "usb_muxing_overcurr_detect": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO19_STATUS": { + "description": "GPIO status", + "offset": 152, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO19_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 156, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "spi0_tx": { + "value": 1 + }, + "uart0_rts": { + "value": 2 + }, + "i2c1_scl": { + "value": 3 + }, + "pwm_b_1": { + "value": 4 + }, + "sio_19": { + "value": 5 + }, + "pio0_19": { + "value": 6 + }, + "pio1_19": { + "value": 7 + }, + "usb_muxing_vbus_detect": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO20_STATUS": { + "description": "GPIO status", + "offset": 160, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO20_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 164, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "spi0_rx": { + "value": 1 + }, + "uart1_tx": { + "value": 2 + }, + "i2c0_sda": { + "value": 3 + }, + "pwm_a_2": { + "value": 4 + }, + "sio_20": { + "value": 5 + }, + "pio0_20": { + "value": 6 + }, + "pio1_20": { + "value": 7 + }, + "clocks_gpin_0": { + "value": 8 + }, + "usb_muxing_vbus_en": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO21_STATUS": { + "description": "GPIO status", + "offset": 168, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO21_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 172, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "spi0_ss_n": { + "value": 1 + }, + "uart1_rx": { + "value": 2 + }, + "i2c0_scl": { + "value": 3 + }, + "pwm_b_2": { + "value": 4 + }, + "sio_21": { + "value": 5 + }, + "pio0_21": { + "value": 6 + }, + "pio1_21": { + "value": 7 + }, + "clocks_gpout_0": { + "value": 8 + }, + "usb_muxing_overcurr_detect": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO22_STATUS": { + "description": "GPIO status", + "offset": 176, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO22_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 180, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "spi0_sclk": { + "value": 1 + }, + "uart1_cts": { + "value": 2 + }, + "i2c1_sda": { + "value": 3 + }, + "pwm_a_3": { + "value": 4 + }, + "sio_22": { + "value": 5 + }, + "pio0_22": { + "value": 6 + }, + "pio1_22": { + "value": 7 + }, + "clocks_gpin_1": { + "value": 8 + }, + "usb_muxing_vbus_detect": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO23_STATUS": { + "description": "GPIO status", + "offset": 184, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO23_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 188, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "spi0_tx": { + "value": 1 + }, + "uart1_rts": { + "value": 2 + }, + "i2c1_scl": { + "value": 3 + }, + "pwm_b_3": { + "value": 4 + }, + "sio_23": { + "value": 5 + }, + "pio0_23": { + "value": 6 + }, + "pio1_23": { + "value": 7 + }, + "clocks_gpout_1": { + "value": 8 + }, + "usb_muxing_vbus_en": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO24_STATUS": { + "description": "GPIO status", + "offset": 192, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO24_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 196, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "spi1_rx": { + "value": 1 + }, + "uart1_tx": { + "value": 2 + }, + "i2c0_sda": { + "value": 3 + }, + "pwm_a_4": { + "value": 4 + }, + "sio_24": { + "value": 5 + }, + "pio0_24": { + "value": 6 + }, + "pio1_24": { + "value": 7 + }, + "clocks_gpout_2": { + "value": 8 + }, + "usb_muxing_overcurr_detect": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO25_STATUS": { + "description": "GPIO status", + "offset": 200, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO25_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 204, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "spi1_ss_n": { + "value": 1 + }, + "uart1_rx": { + "value": 2 + }, + "i2c0_scl": { + "value": 3 + }, + "pwm_b_4": { + "value": 4 + }, + "sio_25": { + "value": 5 + }, + "pio0_25": { + "value": 6 + }, + "pio1_25": { + "value": 7 + }, + "clocks_gpout_3": { + "value": 8 + }, + "usb_muxing_vbus_detect": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO26_STATUS": { + "description": "GPIO status", + "offset": 208, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO26_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 212, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "spi1_sclk": { + "value": 1 + }, + "uart1_cts": { + "value": 2 + }, + "i2c1_sda": { + "value": 3 + }, + "pwm_a_5": { + "value": 4 + }, + "sio_26": { + "value": 5 + }, + "pio0_26": { + "value": 6 + }, + "pio1_26": { + "value": 7 + }, + "usb_muxing_vbus_en": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO27_STATUS": { + "description": "GPIO status", + "offset": 216, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO27_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 220, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "spi1_tx": { + "value": 1 + }, + "uart1_rts": { + "value": 2 + }, + "i2c1_scl": { + "value": 3 + }, + "pwm_b_5": { + "value": 4 + }, + "sio_27": { + "value": 5 + }, + "pio0_27": { + "value": 6 + }, + "pio1_27": { + "value": 7 + }, + "usb_muxing_overcurr_detect": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO28_STATUS": { + "description": "GPIO status", + "offset": 224, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO28_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 228, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "spi1_rx": { + "value": 1 + }, + "uart0_tx": { + "value": 2 + }, + "i2c0_sda": { + "value": 3 + }, + "pwm_a_6": { + "value": 4 + }, + "sio_28": { + "value": 5 + }, + "pio0_28": { + "value": 6 + }, + "pio1_28": { + "value": 7 + }, + "usb_muxing_vbus_detect": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO29_STATUS": { + "description": "GPIO status", + "offset": 232, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO29_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 236, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "spi1_ss_n": { + "value": 1 + }, + "uart0_rx": { + "value": 2 + }, + "i2c0_scl": { + "value": 3 + }, + "pwm_b_6": { + "value": 4 + }, + "sio_29": { + "value": 5 + }, + "pio0_29": { + "value": 6 + }, + "pio1_29": { + "value": 7 + }, + "usb_muxing_vbus_en": { + "value": 9 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "INTR0": { + "description": "Raw Interrupts", + "offset": 240, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO7_EDGE_HIGH": { + "offset": 31, + "size": 1 + }, + "GPIO7_EDGE_LOW": { + "offset": 30, + "size": 1 + }, + "GPIO7_LEVEL_HIGH": { + "offset": 29, + "size": 1, + "access": "read-only" + }, + "GPIO7_LEVEL_LOW": { + "offset": 28, + "size": 1, + "access": "read-only" + }, + "GPIO6_EDGE_HIGH": { + "offset": 27, + "size": 1 + }, + "GPIO6_EDGE_LOW": { + "offset": 26, + "size": 1 + }, + "GPIO6_LEVEL_HIGH": { + "offset": 25, + "size": 1, + "access": "read-only" + }, + "GPIO6_LEVEL_LOW": { + "offset": 24, + "size": 1, + "access": "read-only" + }, + "GPIO5_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO5_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO5_LEVEL_HIGH": { + "offset": 21, + "size": 1, + "access": "read-only" + }, + "GPIO5_LEVEL_LOW": { + "offset": 20, + "size": 1, + "access": "read-only" + }, + "GPIO4_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO4_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO4_LEVEL_HIGH": { + "offset": 17, + "size": 1, + "access": "read-only" + }, + "GPIO4_LEVEL_LOW": { + "offset": 16, + "size": 1, + "access": "read-only" + }, + "GPIO3_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO3_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO3_LEVEL_HIGH": { + "offset": 13, + "size": 1, + "access": "read-only" + }, + "GPIO3_LEVEL_LOW": { + "offset": 12, + "size": 1, + "access": "read-only" + }, + "GPIO2_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO2_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO2_LEVEL_HIGH": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "GPIO2_LEVEL_LOW": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "GPIO1_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO1_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO1_LEVEL_HIGH": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "GPIO1_LEVEL_LOW": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "GPIO0_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO0_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO0_LEVEL_HIGH": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "GPIO0_LEVEL_LOW": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "INTR1": { + "description": "Raw Interrupts", + "offset": 244, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO15_EDGE_HIGH": { + "offset": 31, + "size": 1 + }, + "GPIO15_EDGE_LOW": { + "offset": 30, + "size": 1 + }, + "GPIO15_LEVEL_HIGH": { + "offset": 29, + "size": 1, + "access": "read-only" + }, + "GPIO15_LEVEL_LOW": { + "offset": 28, + "size": 1, + "access": "read-only" + }, + "GPIO14_EDGE_HIGH": { + "offset": 27, + "size": 1 + }, + "GPIO14_EDGE_LOW": { + "offset": 26, + "size": 1 + }, + "GPIO14_LEVEL_HIGH": { + "offset": 25, + "size": 1, + "access": "read-only" + }, + "GPIO14_LEVEL_LOW": { + "offset": 24, + "size": 1, + "access": "read-only" + }, + "GPIO13_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO13_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO13_LEVEL_HIGH": { + "offset": 21, + "size": 1, + "access": "read-only" + }, + "GPIO13_LEVEL_LOW": { + "offset": 20, + "size": 1, + "access": "read-only" + }, + "GPIO12_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO12_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO12_LEVEL_HIGH": { + "offset": 17, + "size": 1, + "access": "read-only" + }, + "GPIO12_LEVEL_LOW": { + "offset": 16, + "size": 1, + "access": "read-only" + }, + "GPIO11_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO11_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO11_LEVEL_HIGH": { + "offset": 13, + "size": 1, + "access": "read-only" + }, + "GPIO11_LEVEL_LOW": { + "offset": 12, + "size": 1, + "access": "read-only" + }, + "GPIO10_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO10_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO10_LEVEL_HIGH": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "GPIO10_LEVEL_LOW": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "GPIO9_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO9_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO9_LEVEL_HIGH": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "GPIO9_LEVEL_LOW": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "GPIO8_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO8_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO8_LEVEL_HIGH": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "GPIO8_LEVEL_LOW": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "INTR2": { + "description": "Raw Interrupts", + "offset": 248, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO23_EDGE_HIGH": { + "offset": 31, + "size": 1 + }, + "GPIO23_EDGE_LOW": { + "offset": 30, + "size": 1 + }, + "GPIO23_LEVEL_HIGH": { + "offset": 29, + "size": 1, + "access": "read-only" + }, + "GPIO23_LEVEL_LOW": { + "offset": 28, + "size": 1, + "access": "read-only" + }, + "GPIO22_EDGE_HIGH": { + "offset": 27, + "size": 1 + }, + "GPIO22_EDGE_LOW": { + "offset": 26, + "size": 1 + }, + "GPIO22_LEVEL_HIGH": { + "offset": 25, + "size": 1, + "access": "read-only" + }, + "GPIO22_LEVEL_LOW": { + "offset": 24, + "size": 1, + "access": "read-only" + }, + "GPIO21_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO21_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO21_LEVEL_HIGH": { + "offset": 21, + "size": 1, + "access": "read-only" + }, + "GPIO21_LEVEL_LOW": { + "offset": 20, + "size": 1, + "access": "read-only" + }, + "GPIO20_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO20_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO20_LEVEL_HIGH": { + "offset": 17, + "size": 1, + "access": "read-only" + }, + "GPIO20_LEVEL_LOW": { + "offset": 16, + "size": 1, + "access": "read-only" + }, + "GPIO19_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO19_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO19_LEVEL_HIGH": { + "offset": 13, + "size": 1, + "access": "read-only" + }, + "GPIO19_LEVEL_LOW": { + "offset": 12, + "size": 1, + "access": "read-only" + }, + "GPIO18_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO18_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO18_LEVEL_HIGH": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "GPIO18_LEVEL_LOW": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "GPIO17_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO17_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO17_LEVEL_HIGH": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "GPIO17_LEVEL_LOW": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "GPIO16_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO16_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO16_LEVEL_HIGH": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "GPIO16_LEVEL_LOW": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "INTR3": { + "description": "Raw Interrupts", + "offset": 252, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO29_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO29_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO29_LEVEL_HIGH": { + "offset": 21, + "size": 1, + "access": "read-only" + }, + "GPIO29_LEVEL_LOW": { + "offset": 20, + "size": 1, + "access": "read-only" + }, + "GPIO28_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO28_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO28_LEVEL_HIGH": { + "offset": 17, + "size": 1, + "access": "read-only" + }, + "GPIO28_LEVEL_LOW": { + "offset": 16, + "size": 1, + "access": "read-only" + }, + "GPIO27_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO27_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO27_LEVEL_HIGH": { + "offset": 13, + "size": 1, + "access": "read-only" + }, + "GPIO27_LEVEL_LOW": { + "offset": 12, + "size": 1, + "access": "read-only" + }, + "GPIO26_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO26_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO26_LEVEL_HIGH": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "GPIO26_LEVEL_LOW": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "GPIO25_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO25_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO25_LEVEL_HIGH": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "GPIO25_LEVEL_LOW": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "GPIO24_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO24_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO24_LEVEL_HIGH": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "GPIO24_LEVEL_LOW": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "PROC0_INTE0": { + "description": "Interrupt Enable for proc0", + "offset": 256, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO7_EDGE_HIGH": { + "offset": 31, + "size": 1 + }, + "GPIO7_EDGE_LOW": { + "offset": 30, + "size": 1 + }, + "GPIO7_LEVEL_HIGH": { + "offset": 29, + "size": 1 + }, + "GPIO7_LEVEL_LOW": { + "offset": 28, + "size": 1 + }, + "GPIO6_EDGE_HIGH": { + "offset": 27, + "size": 1 + }, + "GPIO6_EDGE_LOW": { + "offset": 26, + "size": 1 + }, + "GPIO6_LEVEL_HIGH": { + "offset": 25, + "size": 1 + }, + "GPIO6_LEVEL_LOW": { + "offset": 24, + "size": 1 + }, + "GPIO5_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO5_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO5_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO5_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO4_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO4_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO4_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO4_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO3_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO3_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO3_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO3_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO2_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO2_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO2_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO2_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO1_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO1_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO1_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO1_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO0_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO0_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO0_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO0_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "PROC0_INTE1": { + "description": "Interrupt Enable for proc0", + "offset": 260, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO15_EDGE_HIGH": { + "offset": 31, + "size": 1 + }, + "GPIO15_EDGE_LOW": { + "offset": 30, + "size": 1 + }, + "GPIO15_LEVEL_HIGH": { + "offset": 29, + "size": 1 + }, + "GPIO15_LEVEL_LOW": { + "offset": 28, + "size": 1 + }, + "GPIO14_EDGE_HIGH": { + "offset": 27, + "size": 1 + }, + "GPIO14_EDGE_LOW": { + "offset": 26, + "size": 1 + }, + "GPIO14_LEVEL_HIGH": { + "offset": 25, + "size": 1 + }, + "GPIO14_LEVEL_LOW": { + "offset": 24, + "size": 1 + }, + "GPIO13_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO13_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO13_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO13_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO12_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO12_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO12_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO12_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO11_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO11_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO11_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO11_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO10_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO10_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO10_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO10_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO9_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO9_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO9_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO9_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO8_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO8_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO8_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO8_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "PROC0_INTE2": { + "description": "Interrupt Enable for proc0", + "offset": 264, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO23_EDGE_HIGH": { + "offset": 31, + "size": 1 + }, + "GPIO23_EDGE_LOW": { + "offset": 30, + "size": 1 + }, + "GPIO23_LEVEL_HIGH": { + "offset": 29, + "size": 1 + }, + "GPIO23_LEVEL_LOW": { + "offset": 28, + "size": 1 + }, + "GPIO22_EDGE_HIGH": { + "offset": 27, + "size": 1 + }, + "GPIO22_EDGE_LOW": { + "offset": 26, + "size": 1 + }, + "GPIO22_LEVEL_HIGH": { + "offset": 25, + "size": 1 + }, + "GPIO22_LEVEL_LOW": { + "offset": 24, + "size": 1 + }, + "GPIO21_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO21_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO21_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO21_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO20_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO20_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO20_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO20_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO19_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO19_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO19_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO19_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO18_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO18_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO18_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO18_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO17_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO17_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO17_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO17_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO16_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO16_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO16_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO16_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "PROC0_INTE3": { + "description": "Interrupt Enable for proc0", + "offset": 268, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO29_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO29_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO29_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO29_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO28_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO28_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO28_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO28_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO27_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO27_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO27_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO27_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO26_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO26_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO26_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO26_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO25_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO25_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO25_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO25_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO24_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO24_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO24_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO24_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "PROC0_INTF0": { + "description": "Interrupt Force for proc0", + "offset": 272, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO7_EDGE_HIGH": { + "offset": 31, + "size": 1 + }, + "GPIO7_EDGE_LOW": { + "offset": 30, + "size": 1 + }, + "GPIO7_LEVEL_HIGH": { + "offset": 29, + "size": 1 + }, + "GPIO7_LEVEL_LOW": { + "offset": 28, + "size": 1 + }, + "GPIO6_EDGE_HIGH": { + "offset": 27, + "size": 1 + }, + "GPIO6_EDGE_LOW": { + "offset": 26, + "size": 1 + }, + "GPIO6_LEVEL_HIGH": { + "offset": 25, + "size": 1 + }, + "GPIO6_LEVEL_LOW": { + "offset": 24, + "size": 1 + }, + "GPIO5_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO5_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO5_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO5_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO4_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO4_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO4_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO4_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO3_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO3_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO3_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO3_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO2_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO2_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO2_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO2_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO1_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO1_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO1_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO1_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO0_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO0_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO0_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO0_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "PROC0_INTF1": { + "description": "Interrupt Force for proc0", + "offset": 276, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO15_EDGE_HIGH": { + "offset": 31, + "size": 1 + }, + "GPIO15_EDGE_LOW": { + "offset": 30, + "size": 1 + }, + "GPIO15_LEVEL_HIGH": { + "offset": 29, + "size": 1 + }, + "GPIO15_LEVEL_LOW": { + "offset": 28, + "size": 1 + }, + "GPIO14_EDGE_HIGH": { + "offset": 27, + "size": 1 + }, + "GPIO14_EDGE_LOW": { + "offset": 26, + "size": 1 + }, + "GPIO14_LEVEL_HIGH": { + "offset": 25, + "size": 1 + }, + "GPIO14_LEVEL_LOW": { + "offset": 24, + "size": 1 + }, + "GPIO13_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO13_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO13_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO13_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO12_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO12_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO12_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO12_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO11_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO11_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO11_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO11_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO10_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO10_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO10_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO10_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO9_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO9_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO9_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO9_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO8_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO8_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO8_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO8_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "PROC0_INTF2": { + "description": "Interrupt Force for proc0", + "offset": 280, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO23_EDGE_HIGH": { + "offset": 31, + "size": 1 + }, + "GPIO23_EDGE_LOW": { + "offset": 30, + "size": 1 + }, + "GPIO23_LEVEL_HIGH": { + "offset": 29, + "size": 1 + }, + "GPIO23_LEVEL_LOW": { + "offset": 28, + "size": 1 + }, + "GPIO22_EDGE_HIGH": { + "offset": 27, + "size": 1 + }, + "GPIO22_EDGE_LOW": { + "offset": 26, + "size": 1 + }, + "GPIO22_LEVEL_HIGH": { + "offset": 25, + "size": 1 + }, + "GPIO22_LEVEL_LOW": { + "offset": 24, + "size": 1 + }, + "GPIO21_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO21_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO21_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO21_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO20_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO20_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO20_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO20_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO19_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO19_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO19_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO19_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO18_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO18_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO18_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO18_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO17_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO17_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO17_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO17_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO16_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO16_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO16_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO16_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "PROC0_INTF3": { + "description": "Interrupt Force for proc0", + "offset": 284, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO29_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO29_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO29_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO29_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO28_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO28_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO28_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO28_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO27_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO27_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO27_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO27_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO26_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO26_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO26_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO26_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO25_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO25_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO25_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO25_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO24_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO24_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO24_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO24_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "PROC0_INTS0": { + "description": "Interrupt status after masking & forcing for proc0", + "offset": 288, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO7_EDGE_HIGH": { + "offset": 31, + "size": 1, + "access": "read-only" + }, + "GPIO7_EDGE_LOW": { + "offset": 30, + "size": 1, + "access": "read-only" + }, + "GPIO7_LEVEL_HIGH": { + "offset": 29, + "size": 1, + "access": "read-only" + }, + "GPIO7_LEVEL_LOW": { + "offset": 28, + "size": 1, + "access": "read-only" + }, + "GPIO6_EDGE_HIGH": { + "offset": 27, + "size": 1, + "access": "read-only" + }, + "GPIO6_EDGE_LOW": { + "offset": 26, + "size": 1, + "access": "read-only" + }, + "GPIO6_LEVEL_HIGH": { + "offset": 25, + "size": 1, + "access": "read-only" + }, + "GPIO6_LEVEL_LOW": { + "offset": 24, + "size": 1, + "access": "read-only" + }, + "GPIO5_EDGE_HIGH": { + "offset": 23, + "size": 1, + "access": "read-only" + }, + "GPIO5_EDGE_LOW": { + "offset": 22, + "size": 1, + "access": "read-only" + }, + "GPIO5_LEVEL_HIGH": { + "offset": 21, + "size": 1, + "access": "read-only" + }, + "GPIO5_LEVEL_LOW": { + "offset": 20, + "size": 1, + "access": "read-only" + }, + "GPIO4_EDGE_HIGH": { + "offset": 19, + "size": 1, + "access": "read-only" + }, + "GPIO4_EDGE_LOW": { + "offset": 18, + "size": 1, + "access": "read-only" + }, + "GPIO4_LEVEL_HIGH": { + "offset": 17, + "size": 1, + "access": "read-only" + }, + "GPIO4_LEVEL_LOW": { + "offset": 16, + "size": 1, + "access": "read-only" + }, + "GPIO3_EDGE_HIGH": { + "offset": 15, + "size": 1, + "access": "read-only" + }, + "GPIO3_EDGE_LOW": { + "offset": 14, + "size": 1, + "access": "read-only" + }, + "GPIO3_LEVEL_HIGH": { + "offset": 13, + "size": 1, + "access": "read-only" + }, + "GPIO3_LEVEL_LOW": { + "offset": 12, + "size": 1, + "access": "read-only" + }, + "GPIO2_EDGE_HIGH": { + "offset": 11, + "size": 1, + "access": "read-only" + }, + "GPIO2_EDGE_LOW": { + "offset": 10, + "size": 1, + "access": "read-only" + }, + "GPIO2_LEVEL_HIGH": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "GPIO2_LEVEL_LOW": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "GPIO1_EDGE_HIGH": { + "offset": 7, + "size": 1, + "access": "read-only" + }, + "GPIO1_EDGE_LOW": { + "offset": 6, + "size": 1, + "access": "read-only" + }, + "GPIO1_LEVEL_HIGH": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "GPIO1_LEVEL_LOW": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "GPIO0_EDGE_HIGH": { + "offset": 3, + "size": 1, + "access": "read-only" + }, + "GPIO0_EDGE_LOW": { + "offset": 2, + "size": 1, + "access": "read-only" + }, + "GPIO0_LEVEL_HIGH": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "GPIO0_LEVEL_LOW": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "PROC0_INTS1": { + "description": "Interrupt status after masking & forcing for proc0", + "offset": 292, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO15_EDGE_HIGH": { + "offset": 31, + "size": 1, + "access": "read-only" + }, + "GPIO15_EDGE_LOW": { + "offset": 30, + "size": 1, + "access": "read-only" + }, + "GPIO15_LEVEL_HIGH": { + "offset": 29, + "size": 1, + "access": "read-only" + }, + "GPIO15_LEVEL_LOW": { + "offset": 28, + "size": 1, + "access": "read-only" + }, + "GPIO14_EDGE_HIGH": { + "offset": 27, + "size": 1, + "access": "read-only" + }, + "GPIO14_EDGE_LOW": { + "offset": 26, + "size": 1, + "access": "read-only" + }, + "GPIO14_LEVEL_HIGH": { + "offset": 25, + "size": 1, + "access": "read-only" + }, + "GPIO14_LEVEL_LOW": { + "offset": 24, + "size": 1, + "access": "read-only" + }, + "GPIO13_EDGE_HIGH": { + "offset": 23, + "size": 1, + "access": "read-only" + }, + "GPIO13_EDGE_LOW": { + "offset": 22, + "size": 1, + "access": "read-only" + }, + "GPIO13_LEVEL_HIGH": { + "offset": 21, + "size": 1, + "access": "read-only" + }, + "GPIO13_LEVEL_LOW": { + "offset": 20, + "size": 1, + "access": "read-only" + }, + "GPIO12_EDGE_HIGH": { + "offset": 19, + "size": 1, + "access": "read-only" + }, + "GPIO12_EDGE_LOW": { + "offset": 18, + "size": 1, + "access": "read-only" + }, + "GPIO12_LEVEL_HIGH": { + "offset": 17, + "size": 1, + "access": "read-only" + }, + "GPIO12_LEVEL_LOW": { + "offset": 16, + "size": 1, + "access": "read-only" + }, + "GPIO11_EDGE_HIGH": { + "offset": 15, + "size": 1, + "access": "read-only" + }, + "GPIO11_EDGE_LOW": { + "offset": 14, + "size": 1, + "access": "read-only" + }, + "GPIO11_LEVEL_HIGH": { + "offset": 13, + "size": 1, + "access": "read-only" + }, + "GPIO11_LEVEL_LOW": { + "offset": 12, + "size": 1, + "access": "read-only" + }, + "GPIO10_EDGE_HIGH": { + "offset": 11, + "size": 1, + "access": "read-only" + }, + "GPIO10_EDGE_LOW": { + "offset": 10, + "size": 1, + "access": "read-only" + }, + "GPIO10_LEVEL_HIGH": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "GPIO10_LEVEL_LOW": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "GPIO9_EDGE_HIGH": { + "offset": 7, + "size": 1, + "access": "read-only" + }, + "GPIO9_EDGE_LOW": { + "offset": 6, + "size": 1, + "access": "read-only" + }, + "GPIO9_LEVEL_HIGH": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "GPIO9_LEVEL_LOW": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "GPIO8_EDGE_HIGH": { + "offset": 3, + "size": 1, + "access": "read-only" + }, + "GPIO8_EDGE_LOW": { + "offset": 2, + "size": 1, + "access": "read-only" + }, + "GPIO8_LEVEL_HIGH": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "GPIO8_LEVEL_LOW": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "PROC0_INTS2": { + "description": "Interrupt status after masking & forcing for proc0", + "offset": 296, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO23_EDGE_HIGH": { + "offset": 31, + "size": 1, + "access": "read-only" + }, + "GPIO23_EDGE_LOW": { + "offset": 30, + "size": 1, + "access": "read-only" + }, + "GPIO23_LEVEL_HIGH": { + "offset": 29, + "size": 1, + "access": "read-only" + }, + "GPIO23_LEVEL_LOW": { + "offset": 28, + "size": 1, + "access": "read-only" + }, + "GPIO22_EDGE_HIGH": { + "offset": 27, + "size": 1, + "access": "read-only" + }, + "GPIO22_EDGE_LOW": { + "offset": 26, + "size": 1, + "access": "read-only" + }, + "GPIO22_LEVEL_HIGH": { + "offset": 25, + "size": 1, + "access": "read-only" + }, + "GPIO22_LEVEL_LOW": { + "offset": 24, + "size": 1, + "access": "read-only" + }, + "GPIO21_EDGE_HIGH": { + "offset": 23, + "size": 1, + "access": "read-only" + }, + "GPIO21_EDGE_LOW": { + "offset": 22, + "size": 1, + "access": "read-only" + }, + "GPIO21_LEVEL_HIGH": { + "offset": 21, + "size": 1, + "access": "read-only" + }, + "GPIO21_LEVEL_LOW": { + "offset": 20, + "size": 1, + "access": "read-only" + }, + "GPIO20_EDGE_HIGH": { + "offset": 19, + "size": 1, + "access": "read-only" + }, + "GPIO20_EDGE_LOW": { + "offset": 18, + "size": 1, + "access": "read-only" + }, + "GPIO20_LEVEL_HIGH": { + "offset": 17, + "size": 1, + "access": "read-only" + }, + "GPIO20_LEVEL_LOW": { + "offset": 16, + "size": 1, + "access": "read-only" + }, + "GPIO19_EDGE_HIGH": { + "offset": 15, + "size": 1, + "access": "read-only" + }, + "GPIO19_EDGE_LOW": { + "offset": 14, + "size": 1, + "access": "read-only" + }, + "GPIO19_LEVEL_HIGH": { + "offset": 13, + "size": 1, + "access": "read-only" + }, + "GPIO19_LEVEL_LOW": { + "offset": 12, + "size": 1, + "access": "read-only" + }, + "GPIO18_EDGE_HIGH": { + "offset": 11, + "size": 1, + "access": "read-only" + }, + "GPIO18_EDGE_LOW": { + "offset": 10, + "size": 1, + "access": "read-only" + }, + "GPIO18_LEVEL_HIGH": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "GPIO18_LEVEL_LOW": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "GPIO17_EDGE_HIGH": { + "offset": 7, + "size": 1, + "access": "read-only" + }, + "GPIO17_EDGE_LOW": { + "offset": 6, + "size": 1, + "access": "read-only" + }, + "GPIO17_LEVEL_HIGH": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "GPIO17_LEVEL_LOW": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "GPIO16_EDGE_HIGH": { + "offset": 3, + "size": 1, + "access": "read-only" + }, + "GPIO16_EDGE_LOW": { + "offset": 2, + "size": 1, + "access": "read-only" + }, + "GPIO16_LEVEL_HIGH": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "GPIO16_LEVEL_LOW": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "PROC0_INTS3": { + "description": "Interrupt status after masking & forcing for proc0", + "offset": 300, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO29_EDGE_HIGH": { + "offset": 23, + "size": 1, + "access": "read-only" + }, + "GPIO29_EDGE_LOW": { + "offset": 22, + "size": 1, + "access": "read-only" + }, + "GPIO29_LEVEL_HIGH": { + "offset": 21, + "size": 1, + "access": "read-only" + }, + "GPIO29_LEVEL_LOW": { + "offset": 20, + "size": 1, + "access": "read-only" + }, + "GPIO28_EDGE_HIGH": { + "offset": 19, + "size": 1, + "access": "read-only" + }, + "GPIO28_EDGE_LOW": { + "offset": 18, + "size": 1, + "access": "read-only" + }, + "GPIO28_LEVEL_HIGH": { + "offset": 17, + "size": 1, + "access": "read-only" + }, + "GPIO28_LEVEL_LOW": { + "offset": 16, + "size": 1, + "access": "read-only" + }, + "GPIO27_EDGE_HIGH": { + "offset": 15, + "size": 1, + "access": "read-only" + }, + "GPIO27_EDGE_LOW": { + "offset": 14, + "size": 1, + "access": "read-only" + }, + "GPIO27_LEVEL_HIGH": { + "offset": 13, + "size": 1, + "access": "read-only" + }, + "GPIO27_LEVEL_LOW": { + "offset": 12, + "size": 1, + "access": "read-only" + }, + "GPIO26_EDGE_HIGH": { + "offset": 11, + "size": 1, + "access": "read-only" + }, + "GPIO26_EDGE_LOW": { + "offset": 10, + "size": 1, + "access": "read-only" + }, + "GPIO26_LEVEL_HIGH": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "GPIO26_LEVEL_LOW": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "GPIO25_EDGE_HIGH": { + "offset": 7, + "size": 1, + "access": "read-only" + }, + "GPIO25_EDGE_LOW": { + "offset": 6, + "size": 1, + "access": "read-only" + }, + "GPIO25_LEVEL_HIGH": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "GPIO25_LEVEL_LOW": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "GPIO24_EDGE_HIGH": { + "offset": 3, + "size": 1, + "access": "read-only" + }, + "GPIO24_EDGE_LOW": { + "offset": 2, + "size": 1, + "access": "read-only" + }, + "GPIO24_LEVEL_HIGH": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "GPIO24_LEVEL_LOW": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "PROC1_INTE0": { + "description": "Interrupt Enable for proc1", + "offset": 304, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO7_EDGE_HIGH": { + "offset": 31, + "size": 1 + }, + "GPIO7_EDGE_LOW": { + "offset": 30, + "size": 1 + }, + "GPIO7_LEVEL_HIGH": { + "offset": 29, + "size": 1 + }, + "GPIO7_LEVEL_LOW": { + "offset": 28, + "size": 1 + }, + "GPIO6_EDGE_HIGH": { + "offset": 27, + "size": 1 + }, + "GPIO6_EDGE_LOW": { + "offset": 26, + "size": 1 + }, + "GPIO6_LEVEL_HIGH": { + "offset": 25, + "size": 1 + }, + "GPIO6_LEVEL_LOW": { + "offset": 24, + "size": 1 + }, + "GPIO5_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO5_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO5_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO5_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO4_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO4_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO4_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO4_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO3_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO3_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO3_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO3_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO2_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO2_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO2_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO2_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO1_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO1_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO1_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO1_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO0_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO0_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO0_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO0_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "PROC1_INTE1": { + "description": "Interrupt Enable for proc1", + "offset": 308, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO15_EDGE_HIGH": { + "offset": 31, + "size": 1 + }, + "GPIO15_EDGE_LOW": { + "offset": 30, + "size": 1 + }, + "GPIO15_LEVEL_HIGH": { + "offset": 29, + "size": 1 + }, + "GPIO15_LEVEL_LOW": { + "offset": 28, + "size": 1 + }, + "GPIO14_EDGE_HIGH": { + "offset": 27, + "size": 1 + }, + "GPIO14_EDGE_LOW": { + "offset": 26, + "size": 1 + }, + "GPIO14_LEVEL_HIGH": { + "offset": 25, + "size": 1 + }, + "GPIO14_LEVEL_LOW": { + "offset": 24, + "size": 1 + }, + "GPIO13_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO13_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO13_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO13_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO12_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO12_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO12_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO12_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO11_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO11_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO11_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO11_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO10_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO10_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO10_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO10_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO9_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO9_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO9_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO9_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO8_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO8_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO8_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO8_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "PROC1_INTE2": { + "description": "Interrupt Enable for proc1", + "offset": 312, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO23_EDGE_HIGH": { + "offset": 31, + "size": 1 + }, + "GPIO23_EDGE_LOW": { + "offset": 30, + "size": 1 + }, + "GPIO23_LEVEL_HIGH": { + "offset": 29, + "size": 1 + }, + "GPIO23_LEVEL_LOW": { + "offset": 28, + "size": 1 + }, + "GPIO22_EDGE_HIGH": { + "offset": 27, + "size": 1 + }, + "GPIO22_EDGE_LOW": { + "offset": 26, + "size": 1 + }, + "GPIO22_LEVEL_HIGH": { + "offset": 25, + "size": 1 + }, + "GPIO22_LEVEL_LOW": { + "offset": 24, + "size": 1 + }, + "GPIO21_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO21_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO21_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO21_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO20_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO20_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO20_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO20_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO19_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO19_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO19_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO19_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO18_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO18_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO18_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO18_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO17_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO17_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO17_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO17_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO16_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO16_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO16_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO16_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "PROC1_INTE3": { + "description": "Interrupt Enable for proc1", + "offset": 316, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO29_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO29_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO29_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO29_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO28_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO28_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO28_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO28_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO27_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO27_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO27_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO27_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO26_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO26_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO26_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO26_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO25_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO25_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO25_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO25_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO24_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO24_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO24_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO24_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "PROC1_INTF0": { + "description": "Interrupt Force for proc1", + "offset": 320, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO7_EDGE_HIGH": { + "offset": 31, + "size": 1 + }, + "GPIO7_EDGE_LOW": { + "offset": 30, + "size": 1 + }, + "GPIO7_LEVEL_HIGH": { + "offset": 29, + "size": 1 + }, + "GPIO7_LEVEL_LOW": { + "offset": 28, + "size": 1 + }, + "GPIO6_EDGE_HIGH": { + "offset": 27, + "size": 1 + }, + "GPIO6_EDGE_LOW": { + "offset": 26, + "size": 1 + }, + "GPIO6_LEVEL_HIGH": { + "offset": 25, + "size": 1 + }, + "GPIO6_LEVEL_LOW": { + "offset": 24, + "size": 1 + }, + "GPIO5_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO5_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO5_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO5_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO4_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO4_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO4_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO4_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO3_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO3_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO3_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO3_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO2_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO2_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO2_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO2_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO1_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO1_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO1_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO1_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO0_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO0_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO0_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO0_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "PROC1_INTF1": { + "description": "Interrupt Force for proc1", + "offset": 324, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO15_EDGE_HIGH": { + "offset": 31, + "size": 1 + }, + "GPIO15_EDGE_LOW": { + "offset": 30, + "size": 1 + }, + "GPIO15_LEVEL_HIGH": { + "offset": 29, + "size": 1 + }, + "GPIO15_LEVEL_LOW": { + "offset": 28, + "size": 1 + }, + "GPIO14_EDGE_HIGH": { + "offset": 27, + "size": 1 + }, + "GPIO14_EDGE_LOW": { + "offset": 26, + "size": 1 + }, + "GPIO14_LEVEL_HIGH": { + "offset": 25, + "size": 1 + }, + "GPIO14_LEVEL_LOW": { + "offset": 24, + "size": 1 + }, + "GPIO13_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO13_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO13_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO13_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO12_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO12_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO12_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO12_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO11_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO11_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO11_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO11_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO10_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO10_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO10_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO10_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO9_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO9_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO9_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO9_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO8_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO8_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO8_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO8_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "PROC1_INTF2": { + "description": "Interrupt Force for proc1", + "offset": 328, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO23_EDGE_HIGH": { + "offset": 31, + "size": 1 + }, + "GPIO23_EDGE_LOW": { + "offset": 30, + "size": 1 + }, + "GPIO23_LEVEL_HIGH": { + "offset": 29, + "size": 1 + }, + "GPIO23_LEVEL_LOW": { + "offset": 28, + "size": 1 + }, + "GPIO22_EDGE_HIGH": { + "offset": 27, + "size": 1 + }, + "GPIO22_EDGE_LOW": { + "offset": 26, + "size": 1 + }, + "GPIO22_LEVEL_HIGH": { + "offset": 25, + "size": 1 + }, + "GPIO22_LEVEL_LOW": { + "offset": 24, + "size": 1 + }, + "GPIO21_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO21_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO21_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO21_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO20_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO20_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO20_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO20_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO19_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO19_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO19_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO19_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO18_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO18_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO18_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO18_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO17_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO17_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO17_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO17_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO16_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO16_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO16_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO16_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "PROC1_INTF3": { + "description": "Interrupt Force for proc1", + "offset": 332, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO29_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO29_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO29_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO29_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO28_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO28_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO28_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO28_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO27_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO27_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO27_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO27_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO26_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO26_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO26_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO26_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO25_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO25_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO25_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO25_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO24_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO24_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO24_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO24_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "PROC1_INTS0": { + "description": "Interrupt status after masking & forcing for proc1", + "offset": 336, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO7_EDGE_HIGH": { + "offset": 31, + "size": 1, + "access": "read-only" + }, + "GPIO7_EDGE_LOW": { + "offset": 30, + "size": 1, + "access": "read-only" + }, + "GPIO7_LEVEL_HIGH": { + "offset": 29, + "size": 1, + "access": "read-only" + }, + "GPIO7_LEVEL_LOW": { + "offset": 28, + "size": 1, + "access": "read-only" + }, + "GPIO6_EDGE_HIGH": { + "offset": 27, + "size": 1, + "access": "read-only" + }, + "GPIO6_EDGE_LOW": { + "offset": 26, + "size": 1, + "access": "read-only" + }, + "GPIO6_LEVEL_HIGH": { + "offset": 25, + "size": 1, + "access": "read-only" + }, + "GPIO6_LEVEL_LOW": { + "offset": 24, + "size": 1, + "access": "read-only" + }, + "GPIO5_EDGE_HIGH": { + "offset": 23, + "size": 1, + "access": "read-only" + }, + "GPIO5_EDGE_LOW": { + "offset": 22, + "size": 1, + "access": "read-only" + }, + "GPIO5_LEVEL_HIGH": { + "offset": 21, + "size": 1, + "access": "read-only" + }, + "GPIO5_LEVEL_LOW": { + "offset": 20, + "size": 1, + "access": "read-only" + }, + "GPIO4_EDGE_HIGH": { + "offset": 19, + "size": 1, + "access": "read-only" + }, + "GPIO4_EDGE_LOW": { + "offset": 18, + "size": 1, + "access": "read-only" + }, + "GPIO4_LEVEL_HIGH": { + "offset": 17, + "size": 1, + "access": "read-only" + }, + "GPIO4_LEVEL_LOW": { + "offset": 16, + "size": 1, + "access": "read-only" + }, + "GPIO3_EDGE_HIGH": { + "offset": 15, + "size": 1, + "access": "read-only" + }, + "GPIO3_EDGE_LOW": { + "offset": 14, + "size": 1, + "access": "read-only" + }, + "GPIO3_LEVEL_HIGH": { + "offset": 13, + "size": 1, + "access": "read-only" + }, + "GPIO3_LEVEL_LOW": { + "offset": 12, + "size": 1, + "access": "read-only" + }, + "GPIO2_EDGE_HIGH": { + "offset": 11, + "size": 1, + "access": "read-only" + }, + "GPIO2_EDGE_LOW": { + "offset": 10, + "size": 1, + "access": "read-only" + }, + "GPIO2_LEVEL_HIGH": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "GPIO2_LEVEL_LOW": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "GPIO1_EDGE_HIGH": { + "offset": 7, + "size": 1, + "access": "read-only" + }, + "GPIO1_EDGE_LOW": { + "offset": 6, + "size": 1, + "access": "read-only" + }, + "GPIO1_LEVEL_HIGH": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "GPIO1_LEVEL_LOW": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "GPIO0_EDGE_HIGH": { + "offset": 3, + "size": 1, + "access": "read-only" + }, + "GPIO0_EDGE_LOW": { + "offset": 2, + "size": 1, + "access": "read-only" + }, + "GPIO0_LEVEL_HIGH": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "GPIO0_LEVEL_LOW": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "PROC1_INTS1": { + "description": "Interrupt status after masking & forcing for proc1", + "offset": 340, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO15_EDGE_HIGH": { + "offset": 31, + "size": 1, + "access": "read-only" + }, + "GPIO15_EDGE_LOW": { + "offset": 30, + "size": 1, + "access": "read-only" + }, + "GPIO15_LEVEL_HIGH": { + "offset": 29, + "size": 1, + "access": "read-only" + }, + "GPIO15_LEVEL_LOW": { + "offset": 28, + "size": 1, + "access": "read-only" + }, + "GPIO14_EDGE_HIGH": { + "offset": 27, + "size": 1, + "access": "read-only" + }, + "GPIO14_EDGE_LOW": { + "offset": 26, + "size": 1, + "access": "read-only" + }, + "GPIO14_LEVEL_HIGH": { + "offset": 25, + "size": 1, + "access": "read-only" + }, + "GPIO14_LEVEL_LOW": { + "offset": 24, + "size": 1, + "access": "read-only" + }, + "GPIO13_EDGE_HIGH": { + "offset": 23, + "size": 1, + "access": "read-only" + }, + "GPIO13_EDGE_LOW": { + "offset": 22, + "size": 1, + "access": "read-only" + }, + "GPIO13_LEVEL_HIGH": { + "offset": 21, + "size": 1, + "access": "read-only" + }, + "GPIO13_LEVEL_LOW": { + "offset": 20, + "size": 1, + "access": "read-only" + }, + "GPIO12_EDGE_HIGH": { + "offset": 19, + "size": 1, + "access": "read-only" + }, + "GPIO12_EDGE_LOW": { + "offset": 18, + "size": 1, + "access": "read-only" + }, + "GPIO12_LEVEL_HIGH": { + "offset": 17, + "size": 1, + "access": "read-only" + }, + "GPIO12_LEVEL_LOW": { + "offset": 16, + "size": 1, + "access": "read-only" + }, + "GPIO11_EDGE_HIGH": { + "offset": 15, + "size": 1, + "access": "read-only" + }, + "GPIO11_EDGE_LOW": { + "offset": 14, + "size": 1, + "access": "read-only" + }, + "GPIO11_LEVEL_HIGH": { + "offset": 13, + "size": 1, + "access": "read-only" + }, + "GPIO11_LEVEL_LOW": { + "offset": 12, + "size": 1, + "access": "read-only" + }, + "GPIO10_EDGE_HIGH": { + "offset": 11, + "size": 1, + "access": "read-only" + }, + "GPIO10_EDGE_LOW": { + "offset": 10, + "size": 1, + "access": "read-only" + }, + "GPIO10_LEVEL_HIGH": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "GPIO10_LEVEL_LOW": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "GPIO9_EDGE_HIGH": { + "offset": 7, + "size": 1, + "access": "read-only" + }, + "GPIO9_EDGE_LOW": { + "offset": 6, + "size": 1, + "access": "read-only" + }, + "GPIO9_LEVEL_HIGH": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "GPIO9_LEVEL_LOW": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "GPIO8_EDGE_HIGH": { + "offset": 3, + "size": 1, + "access": "read-only" + }, + "GPIO8_EDGE_LOW": { + "offset": 2, + "size": 1, + "access": "read-only" + }, + "GPIO8_LEVEL_HIGH": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "GPIO8_LEVEL_LOW": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "PROC1_INTS2": { + "description": "Interrupt status after masking & forcing for proc1", + "offset": 344, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO23_EDGE_HIGH": { + "offset": 31, + "size": 1, + "access": "read-only" + }, + "GPIO23_EDGE_LOW": { + "offset": 30, + "size": 1, + "access": "read-only" + }, + "GPIO23_LEVEL_HIGH": { + "offset": 29, + "size": 1, + "access": "read-only" + }, + "GPIO23_LEVEL_LOW": { + "offset": 28, + "size": 1, + "access": "read-only" + }, + "GPIO22_EDGE_HIGH": { + "offset": 27, + "size": 1, + "access": "read-only" + }, + "GPIO22_EDGE_LOW": { + "offset": 26, + "size": 1, + "access": "read-only" + }, + "GPIO22_LEVEL_HIGH": { + "offset": 25, + "size": 1, + "access": "read-only" + }, + "GPIO22_LEVEL_LOW": { + "offset": 24, + "size": 1, + "access": "read-only" + }, + "GPIO21_EDGE_HIGH": { + "offset": 23, + "size": 1, + "access": "read-only" + }, + "GPIO21_EDGE_LOW": { + "offset": 22, + "size": 1, + "access": "read-only" + }, + "GPIO21_LEVEL_HIGH": { + "offset": 21, + "size": 1, + "access": "read-only" + }, + "GPIO21_LEVEL_LOW": { + "offset": 20, + "size": 1, + "access": "read-only" + }, + "GPIO20_EDGE_HIGH": { + "offset": 19, + "size": 1, + "access": "read-only" + }, + "GPIO20_EDGE_LOW": { + "offset": 18, + "size": 1, + "access": "read-only" + }, + "GPIO20_LEVEL_HIGH": { + "offset": 17, + "size": 1, + "access": "read-only" + }, + "GPIO20_LEVEL_LOW": { + "offset": 16, + "size": 1, + "access": "read-only" + }, + "GPIO19_EDGE_HIGH": { + "offset": 15, + "size": 1, + "access": "read-only" + }, + "GPIO19_EDGE_LOW": { + "offset": 14, + "size": 1, + "access": "read-only" + }, + "GPIO19_LEVEL_HIGH": { + "offset": 13, + "size": 1, + "access": "read-only" + }, + "GPIO19_LEVEL_LOW": { + "offset": 12, + "size": 1, + "access": "read-only" + }, + "GPIO18_EDGE_HIGH": { + "offset": 11, + "size": 1, + "access": "read-only" + }, + "GPIO18_EDGE_LOW": { + "offset": 10, + "size": 1, + "access": "read-only" + }, + "GPIO18_LEVEL_HIGH": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "GPIO18_LEVEL_LOW": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "GPIO17_EDGE_HIGH": { + "offset": 7, + "size": 1, + "access": "read-only" + }, + "GPIO17_EDGE_LOW": { + "offset": 6, + "size": 1, + "access": "read-only" + }, + "GPIO17_LEVEL_HIGH": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "GPIO17_LEVEL_LOW": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "GPIO16_EDGE_HIGH": { + "offset": 3, + "size": 1, + "access": "read-only" + }, + "GPIO16_EDGE_LOW": { + "offset": 2, + "size": 1, + "access": "read-only" + }, + "GPIO16_LEVEL_HIGH": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "GPIO16_LEVEL_LOW": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "PROC1_INTS3": { + "description": "Interrupt status after masking & forcing for proc1", + "offset": 348, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO29_EDGE_HIGH": { + "offset": 23, + "size": 1, + "access": "read-only" + }, + "GPIO29_EDGE_LOW": { + "offset": 22, + "size": 1, + "access": "read-only" + }, + "GPIO29_LEVEL_HIGH": { + "offset": 21, + "size": 1, + "access": "read-only" + }, + "GPIO29_LEVEL_LOW": { + "offset": 20, + "size": 1, + "access": "read-only" + }, + "GPIO28_EDGE_HIGH": { + "offset": 19, + "size": 1, + "access": "read-only" + }, + "GPIO28_EDGE_LOW": { + "offset": 18, + "size": 1, + "access": "read-only" + }, + "GPIO28_LEVEL_HIGH": { + "offset": 17, + "size": 1, + "access": "read-only" + }, + "GPIO28_LEVEL_LOW": { + "offset": 16, + "size": 1, + "access": "read-only" + }, + "GPIO27_EDGE_HIGH": { + "offset": 15, + "size": 1, + "access": "read-only" + }, + "GPIO27_EDGE_LOW": { + "offset": 14, + "size": 1, + "access": "read-only" + }, + "GPIO27_LEVEL_HIGH": { + "offset": 13, + "size": 1, + "access": "read-only" + }, + "GPIO27_LEVEL_LOW": { + "offset": 12, + "size": 1, + "access": "read-only" + }, + "GPIO26_EDGE_HIGH": { + "offset": 11, + "size": 1, + "access": "read-only" + }, + "GPIO26_EDGE_LOW": { + "offset": 10, + "size": 1, + "access": "read-only" + }, + "GPIO26_LEVEL_HIGH": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "GPIO26_LEVEL_LOW": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "GPIO25_EDGE_HIGH": { + "offset": 7, + "size": 1, + "access": "read-only" + }, + "GPIO25_EDGE_LOW": { + "offset": 6, + "size": 1, + "access": "read-only" + }, + "GPIO25_LEVEL_HIGH": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "GPIO25_LEVEL_LOW": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "GPIO24_EDGE_HIGH": { + "offset": 3, + "size": 1, + "access": "read-only" + }, + "GPIO24_EDGE_LOW": { + "offset": 2, + "size": 1, + "access": "read-only" + }, + "GPIO24_LEVEL_HIGH": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "GPIO24_LEVEL_LOW": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "DORMANT_WAKE_INTE0": { + "description": "Interrupt Enable for dormant_wake", + "offset": 352, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO7_EDGE_HIGH": { + "offset": 31, + "size": 1 + }, + "GPIO7_EDGE_LOW": { + "offset": 30, + "size": 1 + }, + "GPIO7_LEVEL_HIGH": { + "offset": 29, + "size": 1 + }, + "GPIO7_LEVEL_LOW": { + "offset": 28, + "size": 1 + }, + "GPIO6_EDGE_HIGH": { + "offset": 27, + "size": 1 + }, + "GPIO6_EDGE_LOW": { + "offset": 26, + "size": 1 + }, + "GPIO6_LEVEL_HIGH": { + "offset": 25, + "size": 1 + }, + "GPIO6_LEVEL_LOW": { + "offset": 24, + "size": 1 + }, + "GPIO5_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO5_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO5_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO5_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO4_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO4_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO4_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO4_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO3_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO3_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO3_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO3_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO2_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO2_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO2_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO2_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO1_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO1_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO1_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO1_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO0_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO0_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO0_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO0_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "DORMANT_WAKE_INTE1": { + "description": "Interrupt Enable for dormant_wake", + "offset": 356, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO15_EDGE_HIGH": { + "offset": 31, + "size": 1 + }, + "GPIO15_EDGE_LOW": { + "offset": 30, + "size": 1 + }, + "GPIO15_LEVEL_HIGH": { + "offset": 29, + "size": 1 + }, + "GPIO15_LEVEL_LOW": { + "offset": 28, + "size": 1 + }, + "GPIO14_EDGE_HIGH": { + "offset": 27, + "size": 1 + }, + "GPIO14_EDGE_LOW": { + "offset": 26, + "size": 1 + }, + "GPIO14_LEVEL_HIGH": { + "offset": 25, + "size": 1 + }, + "GPIO14_LEVEL_LOW": { + "offset": 24, + "size": 1 + }, + "GPIO13_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO13_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO13_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO13_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO12_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO12_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO12_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO12_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO11_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO11_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO11_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO11_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO10_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO10_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO10_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO10_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO9_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO9_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO9_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO9_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO8_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO8_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO8_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO8_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "DORMANT_WAKE_INTE2": { + "description": "Interrupt Enable for dormant_wake", + "offset": 360, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO23_EDGE_HIGH": { + "offset": 31, + "size": 1 + }, + "GPIO23_EDGE_LOW": { + "offset": 30, + "size": 1 + }, + "GPIO23_LEVEL_HIGH": { + "offset": 29, + "size": 1 + }, + "GPIO23_LEVEL_LOW": { + "offset": 28, + "size": 1 + }, + "GPIO22_EDGE_HIGH": { + "offset": 27, + "size": 1 + }, + "GPIO22_EDGE_LOW": { + "offset": 26, + "size": 1 + }, + "GPIO22_LEVEL_HIGH": { + "offset": 25, + "size": 1 + }, + "GPIO22_LEVEL_LOW": { + "offset": 24, + "size": 1 + }, + "GPIO21_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO21_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO21_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO21_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO20_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO20_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO20_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO20_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO19_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO19_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO19_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO19_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO18_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO18_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO18_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO18_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO17_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO17_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO17_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO17_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO16_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO16_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO16_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO16_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "DORMANT_WAKE_INTE3": { + "description": "Interrupt Enable for dormant_wake", + "offset": 364, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO29_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO29_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO29_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO29_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO28_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO28_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO28_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO28_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO27_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO27_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO27_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO27_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO26_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO26_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO26_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO26_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO25_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO25_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO25_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO25_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO24_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO24_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO24_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO24_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "DORMANT_WAKE_INTF0": { + "description": "Interrupt Force for dormant_wake", + "offset": 368, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO7_EDGE_HIGH": { + "offset": 31, + "size": 1 + }, + "GPIO7_EDGE_LOW": { + "offset": 30, + "size": 1 + }, + "GPIO7_LEVEL_HIGH": { + "offset": 29, + "size": 1 + }, + "GPIO7_LEVEL_LOW": { + "offset": 28, + "size": 1 + }, + "GPIO6_EDGE_HIGH": { + "offset": 27, + "size": 1 + }, + "GPIO6_EDGE_LOW": { + "offset": 26, + "size": 1 + }, + "GPIO6_LEVEL_HIGH": { + "offset": 25, + "size": 1 + }, + "GPIO6_LEVEL_LOW": { + "offset": 24, + "size": 1 + }, + "GPIO5_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO5_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO5_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO5_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO4_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO4_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO4_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO4_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO3_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO3_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO3_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO3_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO2_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO2_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO2_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO2_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO1_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO1_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO1_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO1_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO0_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO0_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO0_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO0_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "DORMANT_WAKE_INTF1": { + "description": "Interrupt Force for dormant_wake", + "offset": 372, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO15_EDGE_HIGH": { + "offset": 31, + "size": 1 + }, + "GPIO15_EDGE_LOW": { + "offset": 30, + "size": 1 + }, + "GPIO15_LEVEL_HIGH": { + "offset": 29, + "size": 1 + }, + "GPIO15_LEVEL_LOW": { + "offset": 28, + "size": 1 + }, + "GPIO14_EDGE_HIGH": { + "offset": 27, + "size": 1 + }, + "GPIO14_EDGE_LOW": { + "offset": 26, + "size": 1 + }, + "GPIO14_LEVEL_HIGH": { + "offset": 25, + "size": 1 + }, + "GPIO14_LEVEL_LOW": { + "offset": 24, + "size": 1 + }, + "GPIO13_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO13_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO13_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO13_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO12_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO12_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO12_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO12_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO11_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO11_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO11_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO11_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO10_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO10_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO10_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO10_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO9_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO9_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO9_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO9_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO8_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO8_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO8_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO8_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "DORMANT_WAKE_INTF2": { + "description": "Interrupt Force for dormant_wake", + "offset": 376, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO23_EDGE_HIGH": { + "offset": 31, + "size": 1 + }, + "GPIO23_EDGE_LOW": { + "offset": 30, + "size": 1 + }, + "GPIO23_LEVEL_HIGH": { + "offset": 29, + "size": 1 + }, + "GPIO23_LEVEL_LOW": { + "offset": 28, + "size": 1 + }, + "GPIO22_EDGE_HIGH": { + "offset": 27, + "size": 1 + }, + "GPIO22_EDGE_LOW": { + "offset": 26, + "size": 1 + }, + "GPIO22_LEVEL_HIGH": { + "offset": 25, + "size": 1 + }, + "GPIO22_LEVEL_LOW": { + "offset": 24, + "size": 1 + }, + "GPIO21_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO21_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO21_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO21_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO20_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO20_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO20_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO20_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO19_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO19_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO19_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO19_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO18_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO18_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO18_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO18_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO17_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO17_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO17_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO17_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO16_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO16_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO16_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO16_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "DORMANT_WAKE_INTF3": { + "description": "Interrupt Force for dormant_wake", + "offset": 380, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO29_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO29_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO29_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO29_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO28_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO28_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO28_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO28_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO27_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO27_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO27_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO27_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO26_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO26_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO26_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO26_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO25_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO25_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO25_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO25_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO24_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO24_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO24_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO24_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "DORMANT_WAKE_INTS0": { + "description": "Interrupt status after masking & forcing for dormant_wake", + "offset": 384, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO7_EDGE_HIGH": { + "offset": 31, + "size": 1, + "access": "read-only" + }, + "GPIO7_EDGE_LOW": { + "offset": 30, + "size": 1, + "access": "read-only" + }, + "GPIO7_LEVEL_HIGH": { + "offset": 29, + "size": 1, + "access": "read-only" + }, + "GPIO7_LEVEL_LOW": { + "offset": 28, + "size": 1, + "access": "read-only" + }, + "GPIO6_EDGE_HIGH": { + "offset": 27, + "size": 1, + "access": "read-only" + }, + "GPIO6_EDGE_LOW": { + "offset": 26, + "size": 1, + "access": "read-only" + }, + "GPIO6_LEVEL_HIGH": { + "offset": 25, + "size": 1, + "access": "read-only" + }, + "GPIO6_LEVEL_LOW": { + "offset": 24, + "size": 1, + "access": "read-only" + }, + "GPIO5_EDGE_HIGH": { + "offset": 23, + "size": 1, + "access": "read-only" + }, + "GPIO5_EDGE_LOW": { + "offset": 22, + "size": 1, + "access": "read-only" + }, + "GPIO5_LEVEL_HIGH": { + "offset": 21, + "size": 1, + "access": "read-only" + }, + "GPIO5_LEVEL_LOW": { + "offset": 20, + "size": 1, + "access": "read-only" + }, + "GPIO4_EDGE_HIGH": { + "offset": 19, + "size": 1, + "access": "read-only" + }, + "GPIO4_EDGE_LOW": { + "offset": 18, + "size": 1, + "access": "read-only" + }, + "GPIO4_LEVEL_HIGH": { + "offset": 17, + "size": 1, + "access": "read-only" + }, + "GPIO4_LEVEL_LOW": { + "offset": 16, + "size": 1, + "access": "read-only" + }, + "GPIO3_EDGE_HIGH": { + "offset": 15, + "size": 1, + "access": "read-only" + }, + "GPIO3_EDGE_LOW": { + "offset": 14, + "size": 1, + "access": "read-only" + }, + "GPIO3_LEVEL_HIGH": { + "offset": 13, + "size": 1, + "access": "read-only" + }, + "GPIO3_LEVEL_LOW": { + "offset": 12, + "size": 1, + "access": "read-only" + }, + "GPIO2_EDGE_HIGH": { + "offset": 11, + "size": 1, + "access": "read-only" + }, + "GPIO2_EDGE_LOW": { + "offset": 10, + "size": 1, + "access": "read-only" + }, + "GPIO2_LEVEL_HIGH": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "GPIO2_LEVEL_LOW": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "GPIO1_EDGE_HIGH": { + "offset": 7, + "size": 1, + "access": "read-only" + }, + "GPIO1_EDGE_LOW": { + "offset": 6, + "size": 1, + "access": "read-only" + }, + "GPIO1_LEVEL_HIGH": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "GPIO1_LEVEL_LOW": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "GPIO0_EDGE_HIGH": { + "offset": 3, + "size": 1, + "access": "read-only" + }, + "GPIO0_EDGE_LOW": { + "offset": 2, + "size": 1, + "access": "read-only" + }, + "GPIO0_LEVEL_HIGH": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "GPIO0_LEVEL_LOW": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "DORMANT_WAKE_INTS1": { + "description": "Interrupt status after masking & forcing for dormant_wake", + "offset": 388, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO15_EDGE_HIGH": { + "offset": 31, + "size": 1, + "access": "read-only" + }, + "GPIO15_EDGE_LOW": { + "offset": 30, + "size": 1, + "access": "read-only" + }, + "GPIO15_LEVEL_HIGH": { + "offset": 29, + "size": 1, + "access": "read-only" + }, + "GPIO15_LEVEL_LOW": { + "offset": 28, + "size": 1, + "access": "read-only" + }, + "GPIO14_EDGE_HIGH": { + "offset": 27, + "size": 1, + "access": "read-only" + }, + "GPIO14_EDGE_LOW": { + "offset": 26, + "size": 1, + "access": "read-only" + }, + "GPIO14_LEVEL_HIGH": { + "offset": 25, + "size": 1, + "access": "read-only" + }, + "GPIO14_LEVEL_LOW": { + "offset": 24, + "size": 1, + "access": "read-only" + }, + "GPIO13_EDGE_HIGH": { + "offset": 23, + "size": 1, + "access": "read-only" + }, + "GPIO13_EDGE_LOW": { + "offset": 22, + "size": 1, + "access": "read-only" + }, + "GPIO13_LEVEL_HIGH": { + "offset": 21, + "size": 1, + "access": "read-only" + }, + "GPIO13_LEVEL_LOW": { + "offset": 20, + "size": 1, + "access": "read-only" + }, + "GPIO12_EDGE_HIGH": { + "offset": 19, + "size": 1, + "access": "read-only" + }, + "GPIO12_EDGE_LOW": { + "offset": 18, + "size": 1, + "access": "read-only" + }, + "GPIO12_LEVEL_HIGH": { + "offset": 17, + "size": 1, + "access": "read-only" + }, + "GPIO12_LEVEL_LOW": { + "offset": 16, + "size": 1, + "access": "read-only" + }, + "GPIO11_EDGE_HIGH": { + "offset": 15, + "size": 1, + "access": "read-only" + }, + "GPIO11_EDGE_LOW": { + "offset": 14, + "size": 1, + "access": "read-only" + }, + "GPIO11_LEVEL_HIGH": { + "offset": 13, + "size": 1, + "access": "read-only" + }, + "GPIO11_LEVEL_LOW": { + "offset": 12, + "size": 1, + "access": "read-only" + }, + "GPIO10_EDGE_HIGH": { + "offset": 11, + "size": 1, + "access": "read-only" + }, + "GPIO10_EDGE_LOW": { + "offset": 10, + "size": 1, + "access": "read-only" + }, + "GPIO10_LEVEL_HIGH": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "GPIO10_LEVEL_LOW": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "GPIO9_EDGE_HIGH": { + "offset": 7, + "size": 1, + "access": "read-only" + }, + "GPIO9_EDGE_LOW": { + "offset": 6, + "size": 1, + "access": "read-only" + }, + "GPIO9_LEVEL_HIGH": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "GPIO9_LEVEL_LOW": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "GPIO8_EDGE_HIGH": { + "offset": 3, + "size": 1, + "access": "read-only" + }, + "GPIO8_EDGE_LOW": { + "offset": 2, + "size": 1, + "access": "read-only" + }, + "GPIO8_LEVEL_HIGH": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "GPIO8_LEVEL_LOW": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "DORMANT_WAKE_INTS2": { + "description": "Interrupt status after masking & forcing for dormant_wake", + "offset": 392, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO23_EDGE_HIGH": { + "offset": 31, + "size": 1, + "access": "read-only" + }, + "GPIO23_EDGE_LOW": { + "offset": 30, + "size": 1, + "access": "read-only" + }, + "GPIO23_LEVEL_HIGH": { + "offset": 29, + "size": 1, + "access": "read-only" + }, + "GPIO23_LEVEL_LOW": { + "offset": 28, + "size": 1, + "access": "read-only" + }, + "GPIO22_EDGE_HIGH": { + "offset": 27, + "size": 1, + "access": "read-only" + }, + "GPIO22_EDGE_LOW": { + "offset": 26, + "size": 1, + "access": "read-only" + }, + "GPIO22_LEVEL_HIGH": { + "offset": 25, + "size": 1, + "access": "read-only" + }, + "GPIO22_LEVEL_LOW": { + "offset": 24, + "size": 1, + "access": "read-only" + }, + "GPIO21_EDGE_HIGH": { + "offset": 23, + "size": 1, + "access": "read-only" + }, + "GPIO21_EDGE_LOW": { + "offset": 22, + "size": 1, + "access": "read-only" + }, + "GPIO21_LEVEL_HIGH": { + "offset": 21, + "size": 1, + "access": "read-only" + }, + "GPIO21_LEVEL_LOW": { + "offset": 20, + "size": 1, + "access": "read-only" + }, + "GPIO20_EDGE_HIGH": { + "offset": 19, + "size": 1, + "access": "read-only" + }, + "GPIO20_EDGE_LOW": { + "offset": 18, + "size": 1, + "access": "read-only" + }, + "GPIO20_LEVEL_HIGH": { + "offset": 17, + "size": 1, + "access": "read-only" + }, + "GPIO20_LEVEL_LOW": { + "offset": 16, + "size": 1, + "access": "read-only" + }, + "GPIO19_EDGE_HIGH": { + "offset": 15, + "size": 1, + "access": "read-only" + }, + "GPIO19_EDGE_LOW": { + "offset": 14, + "size": 1, + "access": "read-only" + }, + "GPIO19_LEVEL_HIGH": { + "offset": 13, + "size": 1, + "access": "read-only" + }, + "GPIO19_LEVEL_LOW": { + "offset": 12, + "size": 1, + "access": "read-only" + }, + "GPIO18_EDGE_HIGH": { + "offset": 11, + "size": 1, + "access": "read-only" + }, + "GPIO18_EDGE_LOW": { + "offset": 10, + "size": 1, + "access": "read-only" + }, + "GPIO18_LEVEL_HIGH": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "GPIO18_LEVEL_LOW": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "GPIO17_EDGE_HIGH": { + "offset": 7, + "size": 1, + "access": "read-only" + }, + "GPIO17_EDGE_LOW": { + "offset": 6, + "size": 1, + "access": "read-only" + }, + "GPIO17_LEVEL_HIGH": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "GPIO17_LEVEL_LOW": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "GPIO16_EDGE_HIGH": { + "offset": 3, + "size": 1, + "access": "read-only" + }, + "GPIO16_EDGE_LOW": { + "offset": 2, + "size": 1, + "access": "read-only" + }, + "GPIO16_LEVEL_HIGH": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "GPIO16_LEVEL_LOW": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "DORMANT_WAKE_INTS3": { + "description": "Interrupt status after masking & forcing for dormant_wake", + "offset": 396, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO29_EDGE_HIGH": { + "offset": 23, + "size": 1, + "access": "read-only" + }, + "GPIO29_EDGE_LOW": { + "offset": 22, + "size": 1, + "access": "read-only" + }, + "GPIO29_LEVEL_HIGH": { + "offset": 21, + "size": 1, + "access": "read-only" + }, + "GPIO29_LEVEL_LOW": { + "offset": 20, + "size": 1, + "access": "read-only" + }, + "GPIO28_EDGE_HIGH": { + "offset": 19, + "size": 1, + "access": "read-only" + }, + "GPIO28_EDGE_LOW": { + "offset": 18, + "size": 1, + "access": "read-only" + }, + "GPIO28_LEVEL_HIGH": { + "offset": 17, + "size": 1, + "access": "read-only" + }, + "GPIO28_LEVEL_LOW": { + "offset": 16, + "size": 1, + "access": "read-only" + }, + "GPIO27_EDGE_HIGH": { + "offset": 15, + "size": 1, + "access": "read-only" + }, + "GPIO27_EDGE_LOW": { + "offset": 14, + "size": 1, + "access": "read-only" + }, + "GPIO27_LEVEL_HIGH": { + "offset": 13, + "size": 1, + "access": "read-only" + }, + "GPIO27_LEVEL_LOW": { + "offset": 12, + "size": 1, + "access": "read-only" + }, + "GPIO26_EDGE_HIGH": { + "offset": 11, + "size": 1, + "access": "read-only" + }, + "GPIO26_EDGE_LOW": { + "offset": 10, + "size": 1, + "access": "read-only" + }, + "GPIO26_LEVEL_HIGH": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "GPIO26_LEVEL_LOW": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "GPIO25_EDGE_HIGH": { + "offset": 7, + "size": 1, + "access": "read-only" + }, + "GPIO25_EDGE_LOW": { + "offset": 6, + "size": 1, + "access": "read-only" + }, + "GPIO25_LEVEL_HIGH": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "GPIO25_LEVEL_LOW": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "GPIO24_EDGE_HIGH": { + "offset": 3, + "size": 1, + "access": "read-only" + }, + "GPIO24_EDGE_LOW": { + "offset": 2, + "size": 1, + "access": "read-only" + }, + "GPIO24_LEVEL_HIGH": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "GPIO24_LEVEL_LOW": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + } + } + } + }, + "IO_QSPI": { + "children": { + "registers": { + "GPIO_QSPI_SCLK_STATUS": { + "description": "GPIO status", + "offset": 0, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO_QSPI_SCLK_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 4, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "xip_sclk": { + "value": 0 + }, + "sio_30": { + "value": 5 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO_QSPI_SS_STATUS": { + "description": "GPIO status", + "offset": 8, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO_QSPI_SS_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 12, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "xip_ss_n": { + "value": 0 + }, + "sio_31": { + "value": 5 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO_QSPI_SD0_STATUS": { + "description": "GPIO status", + "offset": 16, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO_QSPI_SD0_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 20, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "xip_sd0": { + "value": 0 + }, + "sio_32": { + "value": 5 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO_QSPI_SD1_STATUS": { + "description": "GPIO status", + "offset": 24, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO_QSPI_SD1_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 28, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "xip_sd1": { + "value": 0 + }, + "sio_33": { + "value": 5 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO_QSPI_SD2_STATUS": { + "description": "GPIO status", + "offset": 32, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO_QSPI_SD2_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 36, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "xip_sd2": { + "value": 0 + }, + "sio_34": { + "value": 5 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "GPIO_QSPI_SD3_STATUS": { + "description": "GPIO status", + "offset": 40, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQTOPROC": { + "description": "interrupt to processors, after override is applied", + "offset": 26, + "size": 1, + "access": "read-only" + }, + "IRQFROMPAD": { + "description": "interrupt from pad before override is applied", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "INTOPERI": { + "description": "input signal to peripheral, after override is applied", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "INFROMPAD": { + "description": "input signal from pad, before override is applied", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "OETOPAD": { + "description": "output enable to pad after register override is applied", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "OEFROMPERI": { + "description": "output enable from selected peripheral, before register override is applied", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "OUTTOPAD": { + "description": "output signal to pad after register override is applied", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "OUTFROMPERI": { + "description": "output signal from selected peripheral, before register override is applied", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + }, + "GPIO_QSPI_SD3_CTRL": { + "description": "GPIO control including function select and overrides.", + "offset": 44, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "IRQOVER": { + "offset": 28, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the interrupt", + "value": 0 + }, + "INVERT": { + "description": "invert the interrupt", + "value": 1 + }, + "LOW": { + "description": "drive interrupt low", + "value": 2 + }, + "HIGH": { + "description": "drive interrupt high", + "value": 3 + } + } + } + } + }, + "INOVER": { + "offset": 16, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "don't invert the peri input", + "value": 0 + }, + "INVERT": { + "description": "invert the peri input", + "value": 1 + }, + "LOW": { + "description": "drive peri input low", + "value": 2 + }, + "HIGH": { + "description": "drive peri input high", + "value": 3 + } + } + } + } + }, + "OEOVER": { + "offset": 12, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output enable from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output enable from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "DISABLE": { + "description": "disable output", + "value": 2 + }, + "ENABLE": { + "description": "enable output", + "value": 3 + } + } + } + } + }, + "OUTOVER": { + "offset": 8, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "NORMAL": { + "description": "drive output from peripheral signal selected by funcsel", + "value": 0 + }, + "INVERT": { + "description": "drive output from inverse of peripheral signal selected by funcsel", + "value": 1 + }, + "LOW": { + "description": "drive output low", + "value": 2 + }, + "HIGH": { + "description": "drive output high", + "value": 3 + } + } + } + } + }, + "FUNCSEL": { + "description": "0-31 -> selects pin function according to the gpio table\\n\n 31 == NULL", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "xip_sd3": { + "value": 0 + }, + "sio_35": { + "value": 5 + }, + "null": { + "value": 31 + } + } + } + } + } + } + } + }, + "INTR": { + "description": "Raw Interrupts", + "offset": 48, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_QSPI_SD3_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO_QSPI_SD3_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO_QSPI_SD3_LEVEL_HIGH": { + "offset": 21, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD3_LEVEL_LOW": { + "offset": 20, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD2_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO_QSPI_SD2_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO_QSPI_SD2_LEVEL_HIGH": { + "offset": 17, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD2_LEVEL_LOW": { + "offset": 16, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD1_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO_QSPI_SD1_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO_QSPI_SD1_LEVEL_HIGH": { + "offset": 13, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD1_LEVEL_LOW": { + "offset": 12, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD0_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO_QSPI_SD0_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO_QSPI_SD0_LEVEL_HIGH": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD0_LEVEL_LOW": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SS_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO_QSPI_SS_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO_QSPI_SS_LEVEL_HIGH": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SS_LEVEL_LOW": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SCLK_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO_QSPI_SCLK_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO_QSPI_SCLK_LEVEL_HIGH": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SCLK_LEVEL_LOW": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "PROC0_INTE": { + "description": "Interrupt Enable for proc0", + "offset": 52, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_QSPI_SD3_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO_QSPI_SD3_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO_QSPI_SD3_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO_QSPI_SD3_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO_QSPI_SD2_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO_QSPI_SD2_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO_QSPI_SD2_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO_QSPI_SD2_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO_QSPI_SD1_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO_QSPI_SD1_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO_QSPI_SD1_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO_QSPI_SD1_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO_QSPI_SD0_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO_QSPI_SD0_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO_QSPI_SD0_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO_QSPI_SD0_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO_QSPI_SS_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO_QSPI_SS_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO_QSPI_SS_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO_QSPI_SS_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO_QSPI_SCLK_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO_QSPI_SCLK_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO_QSPI_SCLK_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO_QSPI_SCLK_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "PROC0_INTF": { + "description": "Interrupt Force for proc0", + "offset": 56, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_QSPI_SD3_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO_QSPI_SD3_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO_QSPI_SD3_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO_QSPI_SD3_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO_QSPI_SD2_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO_QSPI_SD2_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO_QSPI_SD2_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO_QSPI_SD2_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO_QSPI_SD1_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO_QSPI_SD1_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO_QSPI_SD1_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO_QSPI_SD1_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO_QSPI_SD0_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO_QSPI_SD0_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO_QSPI_SD0_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO_QSPI_SD0_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO_QSPI_SS_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO_QSPI_SS_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO_QSPI_SS_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO_QSPI_SS_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO_QSPI_SCLK_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO_QSPI_SCLK_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO_QSPI_SCLK_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO_QSPI_SCLK_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "PROC0_INTS": { + "description": "Interrupt status after masking & forcing for proc0", + "offset": 60, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_QSPI_SD3_EDGE_HIGH": { + "offset": 23, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD3_EDGE_LOW": { + "offset": 22, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD3_LEVEL_HIGH": { + "offset": 21, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD3_LEVEL_LOW": { + "offset": 20, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD2_EDGE_HIGH": { + "offset": 19, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD2_EDGE_LOW": { + "offset": 18, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD2_LEVEL_HIGH": { + "offset": 17, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD2_LEVEL_LOW": { + "offset": 16, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD1_EDGE_HIGH": { + "offset": 15, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD1_EDGE_LOW": { + "offset": 14, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD1_LEVEL_HIGH": { + "offset": 13, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD1_LEVEL_LOW": { + "offset": 12, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD0_EDGE_HIGH": { + "offset": 11, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD0_EDGE_LOW": { + "offset": 10, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD0_LEVEL_HIGH": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD0_LEVEL_LOW": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SS_EDGE_HIGH": { + "offset": 7, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SS_EDGE_LOW": { + "offset": 6, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SS_LEVEL_HIGH": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SS_LEVEL_LOW": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SCLK_EDGE_HIGH": { + "offset": 3, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SCLK_EDGE_LOW": { + "offset": 2, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SCLK_LEVEL_HIGH": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SCLK_LEVEL_LOW": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "PROC1_INTE": { + "description": "Interrupt Enable for proc1", + "offset": 64, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_QSPI_SD3_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO_QSPI_SD3_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO_QSPI_SD3_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO_QSPI_SD3_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO_QSPI_SD2_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO_QSPI_SD2_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO_QSPI_SD2_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO_QSPI_SD2_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO_QSPI_SD1_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO_QSPI_SD1_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO_QSPI_SD1_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO_QSPI_SD1_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO_QSPI_SD0_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO_QSPI_SD0_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO_QSPI_SD0_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO_QSPI_SD0_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO_QSPI_SS_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO_QSPI_SS_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO_QSPI_SS_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO_QSPI_SS_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO_QSPI_SCLK_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO_QSPI_SCLK_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO_QSPI_SCLK_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO_QSPI_SCLK_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "PROC1_INTF": { + "description": "Interrupt Force for proc1", + "offset": 68, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_QSPI_SD3_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO_QSPI_SD3_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO_QSPI_SD3_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO_QSPI_SD3_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO_QSPI_SD2_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO_QSPI_SD2_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO_QSPI_SD2_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO_QSPI_SD2_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO_QSPI_SD1_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO_QSPI_SD1_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO_QSPI_SD1_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO_QSPI_SD1_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO_QSPI_SD0_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO_QSPI_SD0_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO_QSPI_SD0_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO_QSPI_SD0_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO_QSPI_SS_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO_QSPI_SS_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO_QSPI_SS_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO_QSPI_SS_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO_QSPI_SCLK_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO_QSPI_SCLK_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO_QSPI_SCLK_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO_QSPI_SCLK_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "PROC1_INTS": { + "description": "Interrupt status after masking & forcing for proc1", + "offset": 72, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_QSPI_SD3_EDGE_HIGH": { + "offset": 23, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD3_EDGE_LOW": { + "offset": 22, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD3_LEVEL_HIGH": { + "offset": 21, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD3_LEVEL_LOW": { + "offset": 20, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD2_EDGE_HIGH": { + "offset": 19, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD2_EDGE_LOW": { + "offset": 18, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD2_LEVEL_HIGH": { + "offset": 17, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD2_LEVEL_LOW": { + "offset": 16, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD1_EDGE_HIGH": { + "offset": 15, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD1_EDGE_LOW": { + "offset": 14, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD1_LEVEL_HIGH": { + "offset": 13, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD1_LEVEL_LOW": { + "offset": 12, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD0_EDGE_HIGH": { + "offset": 11, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD0_EDGE_LOW": { + "offset": 10, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD0_LEVEL_HIGH": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD0_LEVEL_LOW": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SS_EDGE_HIGH": { + "offset": 7, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SS_EDGE_LOW": { + "offset": 6, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SS_LEVEL_HIGH": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SS_LEVEL_LOW": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SCLK_EDGE_HIGH": { + "offset": 3, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SCLK_EDGE_LOW": { + "offset": 2, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SCLK_LEVEL_HIGH": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SCLK_LEVEL_LOW": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "DORMANT_WAKE_INTE": { + "description": "Interrupt Enable for dormant_wake", + "offset": 76, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_QSPI_SD3_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO_QSPI_SD3_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO_QSPI_SD3_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO_QSPI_SD3_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO_QSPI_SD2_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO_QSPI_SD2_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO_QSPI_SD2_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO_QSPI_SD2_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO_QSPI_SD1_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO_QSPI_SD1_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO_QSPI_SD1_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO_QSPI_SD1_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO_QSPI_SD0_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO_QSPI_SD0_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO_QSPI_SD0_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO_QSPI_SD0_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO_QSPI_SS_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO_QSPI_SS_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO_QSPI_SS_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO_QSPI_SS_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO_QSPI_SCLK_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO_QSPI_SCLK_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO_QSPI_SCLK_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO_QSPI_SCLK_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "DORMANT_WAKE_INTF": { + "description": "Interrupt Force for dormant_wake", + "offset": 80, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_QSPI_SD3_EDGE_HIGH": { + "offset": 23, + "size": 1 + }, + "GPIO_QSPI_SD3_EDGE_LOW": { + "offset": 22, + "size": 1 + }, + "GPIO_QSPI_SD3_LEVEL_HIGH": { + "offset": 21, + "size": 1 + }, + "GPIO_QSPI_SD3_LEVEL_LOW": { + "offset": 20, + "size": 1 + }, + "GPIO_QSPI_SD2_EDGE_HIGH": { + "offset": 19, + "size": 1 + }, + "GPIO_QSPI_SD2_EDGE_LOW": { + "offset": 18, + "size": 1 + }, + "GPIO_QSPI_SD2_LEVEL_HIGH": { + "offset": 17, + "size": 1 + }, + "GPIO_QSPI_SD2_LEVEL_LOW": { + "offset": 16, + "size": 1 + }, + "GPIO_QSPI_SD1_EDGE_HIGH": { + "offset": 15, + "size": 1 + }, + "GPIO_QSPI_SD1_EDGE_LOW": { + "offset": 14, + "size": 1 + }, + "GPIO_QSPI_SD1_LEVEL_HIGH": { + "offset": 13, + "size": 1 + }, + "GPIO_QSPI_SD1_LEVEL_LOW": { + "offset": 12, + "size": 1 + }, + "GPIO_QSPI_SD0_EDGE_HIGH": { + "offset": 11, + "size": 1 + }, + "GPIO_QSPI_SD0_EDGE_LOW": { + "offset": 10, + "size": 1 + }, + "GPIO_QSPI_SD0_LEVEL_HIGH": { + "offset": 9, + "size": 1 + }, + "GPIO_QSPI_SD0_LEVEL_LOW": { + "offset": 8, + "size": 1 + }, + "GPIO_QSPI_SS_EDGE_HIGH": { + "offset": 7, + "size": 1 + }, + "GPIO_QSPI_SS_EDGE_LOW": { + "offset": 6, + "size": 1 + }, + "GPIO_QSPI_SS_LEVEL_HIGH": { + "offset": 5, + "size": 1 + }, + "GPIO_QSPI_SS_LEVEL_LOW": { + "offset": 4, + "size": 1 + }, + "GPIO_QSPI_SCLK_EDGE_HIGH": { + "offset": 3, + "size": 1 + }, + "GPIO_QSPI_SCLK_EDGE_LOW": { + "offset": 2, + "size": 1 + }, + "GPIO_QSPI_SCLK_LEVEL_HIGH": { + "offset": 1, + "size": 1 + }, + "GPIO_QSPI_SCLK_LEVEL_LOW": { + "offset": 0, + "size": 1 + } + } + } + }, + "DORMANT_WAKE_INTS": { + "description": "Interrupt status after masking & forcing for dormant_wake", + "offset": 84, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_QSPI_SD3_EDGE_HIGH": { + "offset": 23, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD3_EDGE_LOW": { + "offset": 22, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD3_LEVEL_HIGH": { + "offset": 21, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD3_LEVEL_LOW": { + "offset": 20, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD2_EDGE_HIGH": { + "offset": 19, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD2_EDGE_LOW": { + "offset": 18, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD2_LEVEL_HIGH": { + "offset": 17, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD2_LEVEL_LOW": { + "offset": 16, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD1_EDGE_HIGH": { + "offset": 15, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD1_EDGE_LOW": { + "offset": 14, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD1_LEVEL_HIGH": { + "offset": 13, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD1_LEVEL_LOW": { + "offset": 12, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD0_EDGE_HIGH": { + "offset": 11, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD0_EDGE_LOW": { + "offset": 10, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD0_LEVEL_HIGH": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SD0_LEVEL_LOW": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SS_EDGE_HIGH": { + "offset": 7, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SS_EDGE_LOW": { + "offset": 6, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SS_LEVEL_HIGH": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SS_LEVEL_LOW": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SCLK_EDGE_HIGH": { + "offset": 3, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SCLK_EDGE_LOW": { + "offset": 2, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SCLK_LEVEL_HIGH": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "GPIO_QSPI_SCLK_LEVEL_LOW": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + } + } + } + }, + "PADS_BANK0": { + "children": { + "registers": { + "VOLTAGE_SELECT": { + "description": "Voltage select. Per bank control", + "offset": 0, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "VOLTAGE_SELECT": { + "offset": 0, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "3v3": { + "description": "Set voltage to 3.3V (DVDD >= 2V5)", + "value": 0 + }, + "1v8": { + "description": "Set voltage to 1.8V (DVDD <= 1V8)", + "value": 1 + } + } + } + } + } + } + } + }, + "GPIO0": { + "description": "Pad control register", + "offset": 4, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO1": { + "description": "Pad control register", + "offset": 8, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO2": { + "description": "Pad control register", + "offset": 12, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO3": { + "description": "Pad control register", + "offset": 16, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO4": { + "description": "Pad control register", + "offset": 20, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO5": { + "description": "Pad control register", + "offset": 24, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO6": { + "description": "Pad control register", + "offset": 28, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO7": { + "description": "Pad control register", + "offset": 32, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO8": { + "description": "Pad control register", + "offset": 36, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO9": { + "description": "Pad control register", + "offset": 40, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO10": { + "description": "Pad control register", + "offset": 44, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO11": { + "description": "Pad control register", + "offset": 48, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO12": { + "description": "Pad control register", + "offset": 52, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO13": { + "description": "Pad control register", + "offset": 56, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO14": { + "description": "Pad control register", + "offset": 60, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO15": { + "description": "Pad control register", + "offset": 64, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO16": { + "description": "Pad control register", + "offset": 68, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO17": { + "description": "Pad control register", + "offset": 72, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO18": { + "description": "Pad control register", + "offset": 76, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO19": { + "description": "Pad control register", + "offset": 80, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO20": { + "description": "Pad control register", + "offset": 84, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO21": { + "description": "Pad control register", + "offset": 88, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO22": { + "description": "Pad control register", + "offset": 92, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO23": { + "description": "Pad control register", + "offset": 96, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO24": { + "description": "Pad control register", + "offset": 100, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO25": { + "description": "Pad control register", + "offset": 104, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO26": { + "description": "Pad control register", + "offset": 108, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO27": { + "description": "Pad control register", + "offset": 112, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO28": { + "description": "Pad control register", + "offset": 116, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO29": { + "description": "Pad control register", + "offset": 120, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "SWCLK": { + "description": "Pad control register", + "offset": 124, + "size": 32, + "reset_value": 218, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "SWD": { + "description": "Pad control register", + "offset": 128, + "size": 32, + "reset_value": 90, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + } + } + } + }, + "PADS_QSPI": { + "children": { + "registers": { + "VOLTAGE_SELECT": { + "description": "Voltage select. Per bank control", + "offset": 0, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "VOLTAGE_SELECT": { + "offset": 0, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "3v3": { + "description": "Set voltage to 3.3V (DVDD >= 2V5)", + "value": 0 + }, + "1v8": { + "description": "Set voltage to 1.8V (DVDD <= 1V8)", + "value": 1 + } + } + } + } + } + } + } + }, + "GPIO_QSPI_SCLK": { + "description": "Pad control register", + "offset": 4, + "size": 32, + "reset_value": 86, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO_QSPI_SD0": { + "description": "Pad control register", + "offset": 8, + "size": 32, + "reset_value": 82, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO_QSPI_SD1": { + "description": "Pad control register", + "offset": 12, + "size": 32, + "reset_value": 82, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO_QSPI_SD2": { + "description": "Pad control register", + "offset": 16, + "size": 32, + "reset_value": 82, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO_QSPI_SD3": { + "description": "Pad control register", + "offset": 20, + "size": 32, + "reset_value": 82, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + }, + "GPIO_QSPI_SS": { + "description": "Pad control register", + "offset": 24, + "size": 32, + "reset_value": 90, + "children": { + "fields": { + "OD": { + "description": "Output disable. Has priority over output enable from peripherals", + "offset": 7, + "size": 1 + }, + "IE": { + "description": "Input enable", + "offset": 6, + "size": 1 + }, + "DRIVE": { + "description": "Drive strength.", + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "2mA": { + "value": 0 + }, + "4mA": { + "value": 1 + }, + "8mA": { + "value": 2 + }, + "12mA": { + "value": 3 + } + } + } + } + }, + "PUE": { + "description": "Pull up enable", + "offset": 3, + "size": 1 + }, + "PDE": { + "description": "Pull down enable", + "offset": 2, + "size": 1 + }, + "SCHMITT": { + "description": "Enable schmitt trigger", + "offset": 1, + "size": 1 + }, + "SLEWFAST": { + "description": "Slew rate control. 1 = Fast, 0 = Slow", + "offset": 0, + "size": 1 + } + } + } + } + } + } + }, + "XOSC": { + "description": "Controls the crystal oscillator", + "children": { + "registers": { + "CTRL": { + "description": "Crystal Oscillator Control", + "offset": 0, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "On power-up this field is initialised to DISABLE and the chip runs from the ROSC.\\n\n If the chip has subsequently been programmed to run from the XOSC then setting this field to DISABLE may lock-up the chip. If this is a concern then run the clk_ref from the ROSC and enable the clk_sys RESUS feature.\\n\n The 12-bit code is intended to give some protection against accidental writes. An invalid setting will enable the oscillator.", + "offset": 12, + "size": 12, + "enum": { + "size": 12, + "children": { + "enum_fields": { + "DISABLE": { + "value": 3358 + }, + "ENABLE": { + "value": 4011 + } + } + } + } + }, + "FREQ_RANGE": { + "description": "Frequency range. This resets to 0xAA0 and cannot be changed.", + "offset": 0, + "size": 12, + "enum": { + "size": 12, + "children": { + "enum_fields": { + "1_15MHZ": { + "value": 2720 + }, + "RESERVED_1": { + "value": 2721 + }, + "RESERVED_2": { + "value": 2722 + }, + "RESERVED_3": { + "value": 2723 + } + } + } + } + } + } + } + }, + "STATUS": { + "description": "Crystal Oscillator Status", + "offset": 4, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "STABLE": { + "description": "Oscillator is running and stable", + "offset": 31, + "size": 1, + "access": "read-only" + }, + "BADWRITE": { + "description": "An invalid value has been written to CTRL_ENABLE or CTRL_FREQ_RANGE or DORMANT", + "offset": 24, + "size": 1 + }, + "ENABLED": { + "description": "Oscillator is enabled but not necessarily running and stable, resets to 0", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "FREQ_RANGE": { + "description": "The current frequency range setting, always reads 0", + "offset": 0, + "size": 2, + "access": "read-only", + "enum": { + "size": 2, + "children": { + "enum_fields": { + "1_15MHZ": { + "value": 0 + }, + "RESERVED_1": { + "value": 1 + }, + "RESERVED_2": { + "value": 2 + }, + "RESERVED_3": { + "value": 3 + } + } + } + } + } + } + } + }, + "DORMANT": { + "description": "Crystal Oscillator pause control\\n\n This is used to save power by pausing the XOSC\\n\n On power-up this field is initialised to WAKE\\n\n An invalid write will also select WAKE\\n\n WARNING: stop the PLLs before selecting dormant mode\\n\n WARNING: setup the irq before selecting dormant mode", + "offset": 8, + "size": 32, + "reset_value": 0 + }, + "STARTUP": { + "description": "Controls the startup delay", + "offset": 12, + "size": 32, + "reset_value": 196, + "children": { + "fields": { + "X4": { + "description": "Multiplies the startup_delay by 4. This is of little value to the user given that the delay can be programmed directly.", + "offset": 20, + "size": 1 + }, + "DELAY": { + "description": "in multiples of 256*xtal_period. The reset value of 0xc4 corresponds to approx 50 000 cycles.", + "offset": 0, + "size": 14 + } + } + } + }, + "COUNT": { + "description": "A down counter running at the xosc frequency which counts to zero and stops.\\n\n To start the counter write a non-zero value.\\n\n Can be used for short software pauses when setting up time sensitive hardware.", + "offset": 28, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "COUNT": { + "offset": 0, + "size": 8 + } + } + } + } + } + } + }, + "PLL_SYS": { + "children": { + "registers": { + "CS": { + "description": "Control and Status\\n\n GENERAL CONSTRAINTS:\\n\n Reference clock frequency min=5MHz, max=800MHz\\n\n Feedback divider min=16, max=320\\n\n VCO frequency min=400MHz, max=1600MHz", + "offset": 0, + "size": 32, + "reset_value": 1, + "children": { + "fields": { + "LOCK": { + "description": "PLL is locked", + "offset": 31, + "size": 1, + "access": "read-only" + }, + "BYPASS": { + "description": "Passes the reference clock to the output instead of the divided VCO. The VCO continues to run so the user can switch between the reference clock and the divided VCO but the output will glitch when doing so.", + "offset": 8, + "size": 1 + }, + "REFDIV": { + "description": "Divides the PLL input reference clock.\\n\n Behaviour is undefined for div=0.\\n\n PLL output will be unpredictable during refdiv changes, wait for lock=1 before using it.", + "offset": 0, + "size": 6 + } + } + } + }, + "PWR": { + "description": "Controls the PLL power modes.", + "offset": 4, + "size": 32, + "reset_value": 45, + "children": { + "fields": { + "VCOPD": { + "description": "PLL VCO powerdown\\n\n To save power set high when PLL output not required or bypass=1.", + "offset": 5, + "size": 1 + }, + "POSTDIVPD": { + "description": "PLL post divider powerdown\\n\n To save power set high when PLL output not required or bypass=1.", + "offset": 3, + "size": 1 + }, + "DSMPD": { + "description": "PLL DSM powerdown\\n\n Nothing is achieved by setting this low.", + "offset": 2, + "size": 1 + }, + "PD": { + "description": "PLL powerdown\\n\n To save power set high when PLL output not required.", + "offset": 0, + "size": 1 + } + } + } + }, + "FBDIV_INT": { + "description": "Feedback divisor\\n\n (note: this PLL does not support fractional division)", + "offset": 8, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FBDIV_INT": { + "description": "see ctrl reg description for constraints", + "offset": 0, + "size": 12 + } + } + } + }, + "PRIM": { + "description": "Controls the PLL post dividers for the primary output\\n\n (note: this PLL does not have a secondary output)\\n\n the primary output is driven from VCO divided by postdiv1*postdiv2", + "offset": 12, + "size": 32, + "reset_value": 487424, + "children": { + "fields": { + "POSTDIV1": { + "description": "divide by 1-7", + "offset": 16, + "size": 3 + }, + "POSTDIV2": { + "description": "divide by 1-7", + "offset": 12, + "size": 3 + } + } + } + } + } + } + }, + "PPB": { + "children": { + "registers": { + "SYST_CSR": { + "description": "Use the SysTick Control and Status Register to enable the SysTick features.", + "offset": 57360, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "COUNTFLAG": { + "description": "Returns 1 if timer counted to 0 since last time this was read. Clears on read by application or debugger.", + "offset": 16, + "size": 1, + "access": "read-only" + }, + "CLKSOURCE": { + "description": "SysTick clock source. Always reads as one if SYST_CALIB reports NOREF.\\n\n Selects the SysTick timer clock source:\\n\n 0 = External reference clock.\\n\n 1 = Processor clock.", + "offset": 2, + "size": 1 + }, + "TICKINT": { + "description": "Enables SysTick exception request:\\n\n 0 = Counting down to zero does not assert the SysTick exception request.\\n\n 1 = Counting down to zero to asserts the SysTick exception request.", + "offset": 1, + "size": 1 + }, + "ENABLE": { + "description": "Enable SysTick counter:\\n\n 0 = Counter disabled.\\n\n 1 = Counter enabled.", + "offset": 0, + "size": 1 + } + } + } + }, + "SYST_RVR": { + "description": "Use the SysTick Reload Value Register to specify the start value to load into the current value register when the counter reaches 0. It can be any value between 0 and 0x00FFFFFF. A start value of 0 is possible, but has no effect because the SysTick interrupt and COUNTFLAG are activated when counting from 1 to 0. The reset value of this register is UNKNOWN.\\n\n To generate a multi-shot timer with a period of N processor clock cycles, use a RELOAD value of N-1. For example, if the SysTick interrupt is required every 100 clock pulses, set RELOAD to 99.", + "offset": 57364, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "RELOAD": { + "description": "Value to load into the SysTick Current Value Register when the counter reaches 0.", + "offset": 0, + "size": 24 + } + } + } + }, + "SYST_CVR": { + "description": "Use the SysTick Current Value Register to find the current value in the register. The reset value of this register is UNKNOWN.", + "offset": 57368, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CURRENT": { + "description": "Reads return the current value of the SysTick counter. This register is write-clear. Writing to it with any value clears the register to 0. Clearing this register also clears the COUNTFLAG bit of the SysTick Control and Status Register.", + "offset": 0, + "size": 24 + } + } + } + }, + "SYST_CALIB": { + "description": "Use the SysTick Calibration Value Register to enable software to scale to any required speed using divide and multiply.", + "offset": 57372, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "NOREF": { + "description": "If reads as 1, the Reference clock is not provided - the CLKSOURCE bit of the SysTick Control and Status register will be forced to 1 and cannot be cleared to 0.", + "offset": 31, + "size": 1, + "access": "read-only" + }, + "SKEW": { + "description": "If reads as 1, the calibration value for 10ms is inexact (due to clock frequency).", + "offset": 30, + "size": 1, + "access": "read-only" + }, + "TENMS": { + "description": "An optional Reload value to be used for 10ms (100Hz) timing, subject to system clock skew errors. If the value reads as 0, the calibration value is not known.", + "offset": 0, + "size": 24, + "access": "read-only" + } + } + } + }, + "NVIC_ISER": { + "description": "Use the Interrupt Set-Enable Register to enable interrupts and determine which interrupts are currently enabled.\\n\n If a pending interrupt is enabled, the NVIC activates the interrupt based on its priority. If an interrupt is not enabled, asserting its interrupt signal changes the interrupt state to pending, but the NVIC never activates the interrupt, regardless of its priority.", + "offset": 57600, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SETENA": { + "description": "Interrupt set-enable bits.\\n\n Write:\\n\n 0 = No effect.\\n\n 1 = Enable interrupt.\\n\n Read:\\n\n 0 = Interrupt disabled.\\n\n 1 = Interrupt enabled.", + "offset": 0, + "size": 32 + } + } + } + }, + "NVIC_ICER": { + "description": "Use the Interrupt Clear-Enable Registers to disable interrupts and determine which interrupts are currently enabled.", + "offset": 57728, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CLRENA": { + "description": "Interrupt clear-enable bits.\\n\n Write:\\n\n 0 = No effect.\\n\n 1 = Disable interrupt.\\n\n Read:\\n\n 0 = Interrupt disabled.\\n\n 1 = Interrupt enabled.", + "offset": 0, + "size": 32 + } + } + } + }, + "NVIC_ISPR": { + "description": "The NVIC_ISPR forces interrupts into the pending state, and shows which interrupts are pending.", + "offset": 57856, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SETPEND": { + "description": "Interrupt set-pending bits.\\n\n Write:\\n\n 0 = No effect.\\n\n 1 = Changes interrupt state to pending.\\n\n Read:\\n\n 0 = Interrupt is not pending.\\n\n 1 = Interrupt is pending.\\n\n Note: Writing 1 to the NVIC_ISPR bit corresponding to:\\n\n An interrupt that is pending has no effect.\\n\n A disabled interrupt sets the state of that interrupt to pending.", + "offset": 0, + "size": 32 + } + } + } + }, + "NVIC_ICPR": { + "description": "Use the Interrupt Clear-Pending Register to clear pending interrupts and determine which interrupts are currently pending.", + "offset": 57984, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CLRPEND": { + "description": "Interrupt clear-pending bits.\\n\n Write:\\n\n 0 = No effect.\\n\n 1 = Removes pending state and interrupt.\\n\n Read:\\n\n 0 = Interrupt is not pending.\\n\n 1 = Interrupt is pending.", + "offset": 0, + "size": 32 + } + } + } + }, + "NVIC_IPR0": { + "description": "Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest.\\n\n Note: Writing 1 to an NVIC_ICPR bit does not affect the active state of the corresponding interrupt.\\n\n These registers are only word-accessible", + "offset": 58368, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IP_3": { + "description": "Priority of interrupt 3", + "offset": 30, + "size": 2 + }, + "IP_2": { + "description": "Priority of interrupt 2", + "offset": 22, + "size": 2 + }, + "IP_1": { + "description": "Priority of interrupt 1", + "offset": 14, + "size": 2 + }, + "IP_0": { + "description": "Priority of interrupt 0", + "offset": 6, + "size": 2 + } + } + } + }, + "NVIC_IPR1": { + "description": "Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest.", + "offset": 58372, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IP_7": { + "description": "Priority of interrupt 7", + "offset": 30, + "size": 2 + }, + "IP_6": { + "description": "Priority of interrupt 6", + "offset": 22, + "size": 2 + }, + "IP_5": { + "description": "Priority of interrupt 5", + "offset": 14, + "size": 2 + }, + "IP_4": { + "description": "Priority of interrupt 4", + "offset": 6, + "size": 2 + } + } + } + }, + "NVIC_IPR2": { + "description": "Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest.", + "offset": 58376, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IP_11": { + "description": "Priority of interrupt 11", + "offset": 30, + "size": 2 + }, + "IP_10": { + "description": "Priority of interrupt 10", + "offset": 22, + "size": 2 + }, + "IP_9": { + "description": "Priority of interrupt 9", + "offset": 14, + "size": 2 + }, + "IP_8": { + "description": "Priority of interrupt 8", + "offset": 6, + "size": 2 + } + } + } + }, + "NVIC_IPR3": { + "description": "Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest.", + "offset": 58380, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IP_15": { + "description": "Priority of interrupt 15", + "offset": 30, + "size": 2 + }, + "IP_14": { + "description": "Priority of interrupt 14", + "offset": 22, + "size": 2 + }, + "IP_13": { + "description": "Priority of interrupt 13", + "offset": 14, + "size": 2 + }, + "IP_12": { + "description": "Priority of interrupt 12", + "offset": 6, + "size": 2 + } + } + } + }, + "NVIC_IPR4": { + "description": "Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest.", + "offset": 58384, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IP_19": { + "description": "Priority of interrupt 19", + "offset": 30, + "size": 2 + }, + "IP_18": { + "description": "Priority of interrupt 18", + "offset": 22, + "size": 2 + }, + "IP_17": { + "description": "Priority of interrupt 17", + "offset": 14, + "size": 2 + }, + "IP_16": { + "description": "Priority of interrupt 16", + "offset": 6, + "size": 2 + } + } + } + }, + "NVIC_IPR5": { + "description": "Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest.", + "offset": 58388, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IP_23": { + "description": "Priority of interrupt 23", + "offset": 30, + "size": 2 + }, + "IP_22": { + "description": "Priority of interrupt 22", + "offset": 22, + "size": 2 + }, + "IP_21": { + "description": "Priority of interrupt 21", + "offset": 14, + "size": 2 + }, + "IP_20": { + "description": "Priority of interrupt 20", + "offset": 6, + "size": 2 + } + } + } + }, + "NVIC_IPR6": { + "description": "Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest.", + "offset": 58392, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IP_27": { + "description": "Priority of interrupt 27", + "offset": 30, + "size": 2 + }, + "IP_26": { + "description": "Priority of interrupt 26", + "offset": 22, + "size": 2 + }, + "IP_25": { + "description": "Priority of interrupt 25", + "offset": 14, + "size": 2 + }, + "IP_24": { + "description": "Priority of interrupt 24", + "offset": 6, + "size": 2 + } + } + } + }, + "NVIC_IPR7": { + "description": "Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest.", + "offset": 58396, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IP_31": { + "description": "Priority of interrupt 31", + "offset": 30, + "size": 2 + }, + "IP_30": { + "description": "Priority of interrupt 30", + "offset": 22, + "size": 2 + }, + "IP_29": { + "description": "Priority of interrupt 29", + "offset": 14, + "size": 2 + }, + "IP_28": { + "description": "Priority of interrupt 28", + "offset": 6, + "size": 2 + } + } + } + }, + "CPUID": { + "description": "Read the CPU ID Base Register to determine: the ID number of the processor core, the version number of the processor core, the implementation details of the processor core.", + "offset": 60672, + "size": 32, + "reset_value": 1091356161, + "children": { + "fields": { + "IMPLEMENTER": { + "description": "Implementor code: 0x41 = ARM", + "offset": 24, + "size": 8, + "access": "read-only" + }, + "VARIANT": { + "description": "Major revision number n in the rnpm revision status:\\n\n 0x0 = Revision 0.", + "offset": 20, + "size": 4, + "access": "read-only" + }, + "ARCHITECTURE": { + "description": "Constant that defines the architecture of the processor:\\n\n 0xC = ARMv6-M architecture.", + "offset": 16, + "size": 4, + "access": "read-only" + }, + "PARTNO": { + "description": "Number of processor within family: 0xC60 = Cortex-M0+", + "offset": 4, + "size": 12, + "access": "read-only" + }, + "REVISION": { + "description": "Minor revision number m in the rnpm revision status:\\n\n 0x1 = Patch 1.", + "offset": 0, + "size": 4, + "access": "read-only" + } + } + } + }, + "ICSR": { + "description": "Use the Interrupt Control State Register to set a pending Non-Maskable Interrupt (NMI), set or clear a pending PendSV, set or clear a pending SysTick, check for pending exceptions, check the vector number of the highest priority pended exception, check the vector number of the active exception.", + "offset": 60676, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "NMIPENDSET": { + "description": "Setting this bit will activate an NMI. Since NMI is the highest priority exception, it will activate as soon as it is registered.\\n\n NMI set-pending bit.\\n\n Write:\\n\n 0 = No effect.\\n\n 1 = Changes NMI exception state to pending.\\n\n Read:\\n\n 0 = NMI exception is not pending.\\n\n 1 = NMI exception is pending.\\n\n Because NMI is the highest-priority exception, normally the processor enters the NMI\\n\n exception handler as soon as it detects a write of 1 to this bit. Entering the handler then clears\\n\n this bit to 0. This means a read of this bit by the NMI exception handler returns 1 only if the\\n\n NMI signal is reasserted while the processor is executing that handler.", + "offset": 31, + "size": 1 + }, + "PENDSVSET": { + "description": "PendSV set-pending bit.\\n\n Write:\\n\n 0 = No effect.\\n\n 1 = Changes PendSV exception state to pending.\\n\n Read:\\n\n 0 = PendSV exception is not pending.\\n\n 1 = PendSV exception is pending.\\n\n Writing 1 to this bit is the only way to set the PendSV exception state to pending.", + "offset": 28, + "size": 1 + }, + "PENDSVCLR": { + "description": "PendSV clear-pending bit.\\n\n Write:\\n\n 0 = No effect.\\n\n 1 = Removes the pending state from the PendSV exception.", + "offset": 27, + "size": 1 + }, + "PENDSTSET": { + "description": "SysTick exception set-pending bit.\\n\n Write:\\n\n 0 = No effect.\\n\n 1 = Changes SysTick exception state to pending.\\n\n Read:\\n\n 0 = SysTick exception is not pending.\\n\n 1 = SysTick exception is pending.", + "offset": 26, + "size": 1 + }, + "PENDSTCLR": { + "description": "SysTick exception clear-pending bit.\\n\n Write:\\n\n 0 = No effect.\\n\n 1 = Removes the pending state from the SysTick exception.\\n\n This bit is WO. On a register read its value is Unknown.", + "offset": 25, + "size": 1 + }, + "ISRPREEMPT": { + "description": "The system can only access this bit when the core is halted. It indicates that a pending interrupt is to be taken in the next running cycle. If C_MASKINTS is clear in the Debug Halting Control and Status Register, the interrupt is serviced.", + "offset": 23, + "size": 1, + "access": "read-only" + }, + "ISRPENDING": { + "description": "External interrupt pending flag", + "offset": 22, + "size": 1, + "access": "read-only" + }, + "VECTPENDING": { + "description": "Indicates the exception number for the highest priority pending exception: 0 = no pending exceptions. Non zero = The pending state includes the effect of memory-mapped enable and mask registers. It does not include the PRIMASK special-purpose register qualifier.", + "offset": 12, + "size": 9, + "access": "read-only" + }, + "VECTACTIVE": { + "description": "Active exception number field. Reset clears the VECTACTIVE field.", + "offset": 0, + "size": 9, + "access": "read-only" + } + } + } + }, + "VTOR": { + "description": "The VTOR holds the vector table offset address.", + "offset": 60680, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "TBLOFF": { + "description": "Bits [31:8] of the indicate the vector table offset address.", + "offset": 8, + "size": 24 + } + } + } + }, + "AIRCR": { + "description": "Use the Application Interrupt and Reset Control Register to: determine data endianness, clear all active state information from debug halt mode, request a system reset.", + "offset": 60684, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "VECTKEY": { + "description": "Register key:\\n\n Reads as Unknown\\n\n On writes, write 0x05FA to VECTKEY, otherwise the write is ignored.", + "offset": 16, + "size": 16 + }, + "ENDIANESS": { + "description": "Data endianness implemented:\\n\n 0 = Little-endian.", + "offset": 15, + "size": 1, + "access": "read-only" + }, + "SYSRESETREQ": { + "description": "Writing 1 to this bit causes the SYSRESETREQ signal to the outer system to be asserted to request a reset. The intention is to force a large system reset of all major components except for debug. The C_HALT bit in the DHCSR is cleared as a result of the system reset requested. The debugger does not lose contact with the device.", + "offset": 2, + "size": 1 + }, + "VECTCLRACTIVE": { + "description": "Clears all active state information for fixed and configurable exceptions. This bit: is self-clearing, can only be set by the DAP when the core is halted. When set: clears all active exception status of the processor, forces a return to Thread mode, forces an IPSR of 0. A debugger must re-initialize the stack.", + "offset": 1, + "size": 1 + } + } + } + }, + "SCR": { + "description": "System Control Register. Use the System Control Register for power-management functions: signal to the system when the processor can enter a low power state, control how the processor enters and exits low power states.", + "offset": 60688, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SEVONPEND": { + "description": "Send Event on Pending bit:\\n\n 0 = Only enabled interrupts or events can wakeup the processor, disabled interrupts are excluded.\\n\n 1 = Enabled events and all interrupts, including disabled interrupts, can wakeup the processor.\\n\n When an event or interrupt becomes pending, the event signal wakes up the processor from WFE. If the\\n\n processor is not waiting for an event, the event is registered and affects the next WFE.\\n\n The processor also wakes up on execution of an SEV instruction or an external event.", + "offset": 4, + "size": 1 + }, + "SLEEPDEEP": { + "description": "Controls whether the processor uses sleep or deep sleep as its low power mode:\\n\n 0 = Sleep.\\n\n 1 = Deep sleep.", + "offset": 2, + "size": 1 + }, + "SLEEPONEXIT": { + "description": "Indicates sleep-on-exit when returning from Handler mode to Thread mode:\\n\n 0 = Do not sleep when returning to Thread mode.\\n\n 1 = Enter sleep, or deep sleep, on return from an ISR to Thread mode.\\n\n Setting this bit to 1 enables an interrupt driven application to avoid returning to an empty main application.", + "offset": 1, + "size": 1 + } + } + } + }, + "CCR": { + "description": "The Configuration and Control Register permanently enables stack alignment and causes unaligned accesses to result in a Hard Fault.", + "offset": 60692, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "STKALIGN": { + "description": "Always reads as one, indicates 8-byte stack alignment on exception entry. On exception entry, the processor uses bit[9] of the stacked PSR to indicate the stack alignment. On return from the exception it uses this stacked bit to restore the correct stack alignment.", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "UNALIGN_TRP": { + "description": "Always reads as one, indicates that all unaligned accesses generate a HardFault.", + "offset": 3, + "size": 1, + "access": "read-only" + } + } + } + }, + "SHPR2": { + "description": "System handlers are a special class of exception handler that can have their priority set to any of the priority levels. Use the System Handler Priority Register 2 to set the priority of SVCall.", + "offset": 60700, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "PRI_11": { + "description": "Priority of system handler 11, SVCall", + "offset": 30, + "size": 2 + } + } + } + }, + "SHPR3": { + "description": "System handlers are a special class of exception handler that can have their priority set to any of the priority levels. Use the System Handler Priority Register 3 to set the priority of PendSV and SysTick.", + "offset": 60704, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "PRI_15": { + "description": "Priority of system handler 15, SysTick", + "offset": 30, + "size": 2 + }, + "PRI_14": { + "description": "Priority of system handler 14, PendSV", + "offset": 22, + "size": 2 + } + } + } + }, + "SHCSR": { + "description": "Use the System Handler Control and State Register to determine or clear the pending status of SVCall.", + "offset": 60708, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SVCALLPENDED": { + "description": "Reads as 1 if SVCall is Pending. Write 1 to set pending SVCall, write 0 to clear pending SVCall.", + "offset": 15, + "size": 1 + } + } + } + }, + "MPU_TYPE": { + "description": "Read the MPU Type Register to determine if the processor implements an MPU, and how many regions the MPU supports.", + "offset": 60816, + "size": 32, + "reset_value": 2048, + "children": { + "fields": { + "IREGION": { + "description": "Instruction region. Reads as zero as ARMv6-M only supports a unified MPU.", + "offset": 16, + "size": 8, + "access": "read-only" + }, + "DREGION": { + "description": "Number of regions supported by the MPU.", + "offset": 8, + "size": 8, + "access": "read-only" + }, + "SEPARATE": { + "description": "Indicates support for separate instruction and data address maps. Reads as 0 as ARMv6-M only supports a unified MPU.", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "MPU_CTRL": { + "description": "Use the MPU Control Register to enable and disable the MPU, and to control whether the default memory map is enabled as a background region for privileged accesses, and whether the MPU is enabled for HardFaults and NMIs.", + "offset": 60820, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "PRIVDEFENA": { + "description": "Controls whether the default memory map is enabled as a background region for privileged accesses. This bit is ignored when ENABLE is clear.\\n\n 0 = If the MPU is enabled, disables use of the default memory map. Any memory access to a location not\\n\n covered by any enabled region causes a fault.\\n\n 1 = If the MPU is enabled, enables use of the default memory map as a background region for privileged software accesses.\\n\n When enabled, the background region acts as if it is region number -1. Any region that is defined and enabled has priority over this default map.", + "offset": 2, + "size": 1 + }, + "HFNMIENA": { + "description": "Controls the use of the MPU for HardFaults and NMIs. Setting this bit when ENABLE is clear results in UNPREDICTABLE behaviour.\\n\n When the MPU is enabled:\\n\n 0 = MPU is disabled during HardFault and NMI handlers, regardless of the value of the ENABLE bit.\\n\n 1 = the MPU is enabled during HardFault and NMI handlers.", + "offset": 1, + "size": 1 + }, + "ENABLE": { + "description": "Enables the MPU. If the MPU is disabled, privileged and unprivileged accesses use the default memory map.\\n\n 0 = MPU disabled.\\n\n 1 = MPU enabled.", + "offset": 0, + "size": 1 + } + } + } + }, + "MPU_RNR": { + "description": "Use the MPU Region Number Register to select the region currently accessed by MPU_RBAR and MPU_RASR.", + "offset": 60824, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "REGION": { + "description": "Indicates the MPU region referenced by the MPU_RBAR and MPU_RASR registers.\\n\n The MPU supports 8 memory regions, so the permitted values of this field are 0-7.", + "offset": 0, + "size": 4 + } + } + } + }, + "MPU_RBAR": { + "description": "Read the MPU Region Base Address Register to determine the base address of the region identified by MPU_RNR. Write to update the base address of said region or that of a specified region, with whose number MPU_RNR will also be updated.", + "offset": 60828, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ADDR": { + "description": "Base address of the region.", + "offset": 8, + "size": 24 + }, + "VALID": { + "description": "On writes, indicates whether the write must update the base address of the region identified by the REGION field, updating the MPU_RNR to indicate this new region.\\n\n Write:\\n\n 0 = MPU_RNR not changed, and the processor:\\n\n Updates the base address for the region specified in the MPU_RNR.\\n\n Ignores the value of the REGION field.\\n\n 1 = The processor:\\n\n Updates the value of the MPU_RNR to the value of the REGION field.\\n\n Updates the base address for the region specified in the REGION field.\\n\n Always reads as zero.", + "offset": 4, + "size": 1 + }, + "REGION": { + "description": "On writes, specifies the number of the region whose base address to update provided VALID is set written as 1. On reads, returns bits [3:0] of MPU_RNR.", + "offset": 0, + "size": 4 + } + } + } + }, + "MPU_RASR": { + "description": "Use the MPU Region Attribute and Size Register to define the size, access behaviour and memory type of the region identified by MPU_RNR, and enable that region.", + "offset": 60832, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ATTRS": { + "description": "The MPU Region Attribute field. Use to define the region attribute control.\\n\n 28 = XN: Instruction access disable bit:\\n\n 0 = Instruction fetches enabled.\\n\n 1 = Instruction fetches disabled.\\n\n 26:24 = AP: Access permission field\\n\n 18 = S: Shareable bit\\n\n 17 = C: Cacheable bit\\n\n 16 = B: Bufferable bit", + "offset": 16, + "size": 16 + }, + "SRD": { + "description": "Subregion Disable. For regions of 256 bytes or larger, each bit of this field controls whether one of the eight equal subregions is enabled.", + "offset": 8, + "size": 8 + }, + "SIZE": { + "description": "Indicates the region size. Region size in bytes = 2^(SIZE+1). The minimum permitted value is 7 (b00111) = 256Bytes", + "offset": 1, + "size": 5 + }, + "ENABLE": { + "description": "Enables the region.", + "offset": 0, + "size": 1 + } + } + } + } + } + } + }, + "BUSCTRL": { + "description": "Register block for busfabric control signals and performance counters", + "children": { + "registers": { + "BUS_PRIORITY": { + "description": "Set the priority of each master for bus arbitration.", + "offset": 0, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "DMA_W": { + "description": "0 - low priority, 1 - high priority", + "offset": 12, + "size": 1 + }, + "DMA_R": { + "description": "0 - low priority, 1 - high priority", + "offset": 8, + "size": 1 + }, + "PROC1": { + "description": "0 - low priority, 1 - high priority", + "offset": 4, + "size": 1 + }, + "PROC0": { + "description": "0 - low priority, 1 - high priority", + "offset": 0, + "size": 1 + } + } + } + }, + "BUS_PRIORITY_ACK": { + "description": "Bus priority acknowledge", + "offset": 4, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "BUS_PRIORITY_ACK": { + "description": "Goes to 1 once all arbiters have registered the new global priority levels.\\n\n Arbiters update their local priority when servicing a new nonsequential access.\\n\n In normal circumstances this will happen almost immediately.", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "PERFCTR0": { + "description": "Bus fabric performance counter 0", + "offset": 8, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "PERFCTR0": { + "description": "Busfabric saturating performance counter 0\\n\n Count some event signal from the busfabric arbiters.\\n\n Write any value to clear. Select an event to count using PERFSEL0", + "offset": 0, + "size": 24 + } + } + } + }, + "PERFSEL0": { + "description": "Bus fabric performance event select for PERFCTR0", + "offset": 12, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "PERFSEL0": { + "description": "Select an event for PERFCTR0. Count either contested accesses, or all accesses, on a downstream port of the main crossbar.", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "apb_contested": { + "value": 0 + }, + "apb": { + "value": 1 + }, + "fastperi_contested": { + "value": 2 + }, + "fastperi": { + "value": 3 + }, + "sram5_contested": { + "value": 4 + }, + "sram5": { + "value": 5 + }, + "sram4_contested": { + "value": 6 + }, + "sram4": { + "value": 7 + }, + "sram3_contested": { + "value": 8 + }, + "sram3": { + "value": 9 + }, + "sram2_contested": { + "value": 10 + }, + "sram2": { + "value": 11 + }, + "sram1_contested": { + "value": 12 + }, + "sram1": { + "value": 13 + }, + "sram0_contested": { + "value": 14 + }, + "sram0": { + "value": 15 + }, + "xip_main_contested": { + "value": 16 + }, + "xip_main": { + "value": 17 + }, + "rom_contested": { + "value": 18 + }, + "rom": { + "value": 19 + } + } + } + } + } + } + } + }, + "PERFCTR1": { + "description": "Bus fabric performance counter 1", + "offset": 16, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "PERFCTR1": { + "description": "Busfabric saturating performance counter 1\\n\n Count some event signal from the busfabric arbiters.\\n\n Write any value to clear. Select an event to count using PERFSEL1", + "offset": 0, + "size": 24 + } + } + } + }, + "PERFSEL1": { + "description": "Bus fabric performance event select for PERFCTR1", + "offset": 20, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "PERFSEL1": { + "description": "Select an event for PERFCTR1. Count either contested accesses, or all accesses, on a downstream port of the main crossbar.", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "apb_contested": { + "value": 0 + }, + "apb": { + "value": 1 + }, + "fastperi_contested": { + "value": 2 + }, + "fastperi": { + "value": 3 + }, + "sram5_contested": { + "value": 4 + }, + "sram5": { + "value": 5 + }, + "sram4_contested": { + "value": 6 + }, + "sram4": { + "value": 7 + }, + "sram3_contested": { + "value": 8 + }, + "sram3": { + "value": 9 + }, + "sram2_contested": { + "value": 10 + }, + "sram2": { + "value": 11 + }, + "sram1_contested": { + "value": 12 + }, + "sram1": { + "value": 13 + }, + "sram0_contested": { + "value": 14 + }, + "sram0": { + "value": 15 + }, + "xip_main_contested": { + "value": 16 + }, + "xip_main": { + "value": 17 + }, + "rom_contested": { + "value": 18 + }, + "rom": { + "value": 19 + } + } + } + } + } + } + } + }, + "PERFCTR2": { + "description": "Bus fabric performance counter 2", + "offset": 24, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "PERFCTR2": { + "description": "Busfabric saturating performance counter 2\\n\n Count some event signal from the busfabric arbiters.\\n\n Write any value to clear. Select an event to count using PERFSEL2", + "offset": 0, + "size": 24 + } + } + } + }, + "PERFSEL2": { + "description": "Bus fabric performance event select for PERFCTR2", + "offset": 28, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "PERFSEL2": { + "description": "Select an event for PERFCTR2. Count either contested accesses, or all accesses, on a downstream port of the main crossbar.", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "apb_contested": { + "value": 0 + }, + "apb": { + "value": 1 + }, + "fastperi_contested": { + "value": 2 + }, + "fastperi": { + "value": 3 + }, + "sram5_contested": { + "value": 4 + }, + "sram5": { + "value": 5 + }, + "sram4_contested": { + "value": 6 + }, + "sram4": { + "value": 7 + }, + "sram3_contested": { + "value": 8 + }, + "sram3": { + "value": 9 + }, + "sram2_contested": { + "value": 10 + }, + "sram2": { + "value": 11 + }, + "sram1_contested": { + "value": 12 + }, + "sram1": { + "value": 13 + }, + "sram0_contested": { + "value": 14 + }, + "sram0": { + "value": 15 + }, + "xip_main_contested": { + "value": 16 + }, + "xip_main": { + "value": 17 + }, + "rom_contested": { + "value": 18 + }, + "rom": { + "value": 19 + } + } + } + } + } + } + } + }, + "PERFCTR3": { + "description": "Bus fabric performance counter 3", + "offset": 32, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "PERFCTR3": { + "description": "Busfabric saturating performance counter 3\\n\n Count some event signal from the busfabric arbiters.\\n\n Write any value to clear. Select an event to count using PERFSEL3", + "offset": 0, + "size": 24 + } + } + } + }, + "PERFSEL3": { + "description": "Bus fabric performance event select for PERFCTR3", + "offset": 36, + "size": 32, + "reset_value": 31, + "children": { + "fields": { + "PERFSEL3": { + "description": "Select an event for PERFCTR3. Count either contested accesses, or all accesses, on a downstream port of the main crossbar.", + "offset": 0, + "size": 5, + "enum": { + "size": 5, + "children": { + "enum_fields": { + "apb_contested": { + "value": 0 + }, + "apb": { + "value": 1 + }, + "fastperi_contested": { + "value": 2 + }, + "fastperi": { + "value": 3 + }, + "sram5_contested": { + "value": 4 + }, + "sram5": { + "value": 5 + }, + "sram4_contested": { + "value": 6 + }, + "sram4": { + "value": 7 + }, + "sram3_contested": { + "value": 8 + }, + "sram3": { + "value": 9 + }, + "sram2_contested": { + "value": 10 + }, + "sram2": { + "value": 11 + }, + "sram1_contested": { + "value": 12 + }, + "sram1": { + "value": 13 + }, + "sram0_contested": { + "value": 14 + }, + "sram0": { + "value": 15 + }, + "xip_main_contested": { + "value": 16 + }, + "xip_main": { + "value": 17 + }, + "rom_contested": { + "value": 18 + }, + "rom": { + "value": 19 + } + } + } + } + } + } + } + } + } + } + }, + "UART0": { + "children": { + "registers": { + "UARTDR": { + "description": "Data Register, UARTDR", + "offset": 0, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "OE": { + "description": "Overrun error. This bit is set to 1 if data is received and the receive FIFO is already full. This is cleared to 0 once there is an empty space in the FIFO and a new character can be written to it.", + "offset": 11, + "size": 1, + "access": "read-only" + }, + "BE": { + "description": "Break error. This bit is set to 1 if a break condition was detected, indicating that the received data input was held LOW for longer than a full-word transmission time (defined as start, data, parity and stop bits). In FIFO mode, this error is associated with the character at the top of the FIFO. When a break occurs, only one 0 character is loaded into the FIFO. The next character is only enabled after the receive data input goes to a 1 (marking state), and the next valid start bit is received.", + "offset": 10, + "size": 1, + "access": "read-only" + }, + "PE": { + "description": "Parity error. When set to 1, it indicates that the parity of the received data character does not match the parity that the EPS and SPS bits in the Line Control Register, UARTLCR_H. In FIFO mode, this error is associated with the character at the top of the FIFO.", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "FE": { + "description": "Framing error. When set to 1, it indicates that the received character did not have a valid stop bit (a valid stop bit is 1). In FIFO mode, this error is associated with the character at the top of the FIFO.", + "offset": 8, + "size": 1, + "access": "read-only" + }, + "DATA": { + "description": "Receive (read) data character. Transmit (write) data character.", + "offset": 0, + "size": 8 + } + } + } + }, + "UARTRSR": { + "description": "Receive Status Register/Error Clear Register, UARTRSR/UARTECR", + "offset": 4, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "OE": { + "description": "Overrun error. This bit is set to 1 if data is received and the FIFO is already full. This bit is cleared to 0 by a write to UARTECR. The FIFO contents remain valid because no more data is written when the FIFO is full, only the contents of the shift register are overwritten. The CPU must now read the data, to empty the FIFO.", + "offset": 3, + "size": 1 + }, + "BE": { + "description": "Break error. This bit is set to 1 if a break condition was detected, indicating that the received data input was held LOW for longer than a full-word transmission time (defined as start, data, parity, and stop bits). This bit is cleared to 0 after a write to UARTECR. In FIFO mode, this error is associated with the character at the top of the FIFO. When a break occurs, only one 0 character is loaded into the FIFO. The next character is only enabled after the receive data input goes to a 1 (marking state) and the next valid start bit is received.", + "offset": 2, + "size": 1 + }, + "PE": { + "description": "Parity error. When set to 1, it indicates that the parity of the received data character does not match the parity that the EPS and SPS bits in the Line Control Register, UARTLCR_H. This bit is cleared to 0 by a write to UARTECR. In FIFO mode, this error is associated with the character at the top of the FIFO.", + "offset": 1, + "size": 1 + }, + "FE": { + "description": "Framing error. When set to 1, it indicates that the received character did not have a valid stop bit (a valid stop bit is 1). This bit is cleared to 0 by a write to UARTECR. In FIFO mode, this error is associated with the character at the top of the FIFO.", + "offset": 0, + "size": 1 + } + } + } + }, + "UARTFR": { + "description": "Flag Register, UARTFR", + "offset": 24, + "size": 32, + "reset_value": 144, + "children": { + "fields": { + "RI": { + "description": "Ring indicator. This bit is the complement of the UART ring indicator, nUARTRI, modem status input. That is, the bit is 1 when nUARTRI is LOW.", + "offset": 8, + "size": 1, + "access": "read-only" + }, + "TXFE": { + "description": "Transmit FIFO empty. The meaning of this bit depends on the state of the FEN bit in the Line Control Register, UARTLCR_H. If the FIFO is disabled, this bit is set when the transmit holding register is empty. If the FIFO is enabled, the TXFE bit is set when the transmit FIFO is empty. This bit does not indicate if there is data in the transmit shift register.", + "offset": 7, + "size": 1, + "access": "read-only" + }, + "RXFF": { + "description": "Receive FIFO full. The meaning of this bit depends on the state of the FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the receive holding register is full. If the FIFO is enabled, the RXFF bit is set when the receive FIFO is full.", + "offset": 6, + "size": 1, + "access": "read-only" + }, + "TXFF": { + "description": "Transmit FIFO full. The meaning of this bit depends on the state of the FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the transmit holding register is full. If the FIFO is enabled, the TXFF bit is set when the transmit FIFO is full.", + "offset": 5, + "size": 1, + "access": "read-only" + }, + "RXFE": { + "description": "Receive FIFO empty. The meaning of this bit depends on the state of the FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the receive holding register is empty. If the FIFO is enabled, the RXFE bit is set when the receive FIFO is empty.", + "offset": 4, + "size": 1, + "access": "read-only" + }, + "BUSY": { + "description": "UART busy. If this bit is set to 1, the UART is busy transmitting data. This bit remains set until the complete byte, including all the stop bits, has been sent from the shift register. This bit is set as soon as the transmit FIFO becomes non-empty, regardless of whether the UART is enabled or not.", + "offset": 3, + "size": 1, + "access": "read-only" + }, + "DCD": { + "description": "Data carrier detect. This bit is the complement of the UART data carrier detect, nUARTDCD, modem status input. That is, the bit is 1 when nUARTDCD is LOW.", + "offset": 2, + "size": 1, + "access": "read-only" + }, + "DSR": { + "description": "Data set ready. This bit is the complement of the UART data set ready, nUARTDSR, modem status input. That is, the bit is 1 when nUARTDSR is LOW.", + "offset": 1, + "size": 1, + "access": "read-only" + }, + "CTS": { + "description": "Clear to send. This bit is the complement of the UART clear to send, nUARTCTS, modem status input. That is, the bit is 1 when nUARTCTS is LOW.", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "UARTILPR": { + "description": "IrDA Low-Power Counter Register, UARTILPR", + "offset": 32, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ILPDVSR": { + "description": "8-bit low-power divisor value. These bits are cleared to 0 at reset.", + "offset": 0, + "size": 8 + } + } + } + }, + "UARTIBRD": { + "description": "Integer Baud Rate Register, UARTIBRD", + "offset": 36, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "BAUD_DIVINT": { + "description": "The integer baud rate divisor. These bits are cleared to 0 on reset.", + "offset": 0, + "size": 16 + } + } + } + }, + "UARTFBRD": { + "description": "Fractional Baud Rate Register, UARTFBRD", + "offset": 40, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "BAUD_DIVFRAC": { + "description": "The fractional baud rate divisor. These bits are cleared to 0 on reset.", + "offset": 0, + "size": 6 + } + } + } + }, + "UARTLCR_H": { + "description": "Line Control Register, UARTLCR_H", + "offset": 44, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SPS": { + "description": "Stick parity select. 0 = stick parity is disabled 1 = either: * if the EPS bit is 0 then the parity bit is transmitted and checked as a 1 * if the EPS bit is 1 then the parity bit is transmitted and checked as a 0. This bit has no effect when the PEN bit disables parity checking and generation.", + "offset": 7, + "size": 1 + }, + "WLEN": { + "description": "Word length. These bits indicate the number of data bits transmitted or received in a frame as follows: b11 = 8 bits b10 = 7 bits b01 = 6 bits b00 = 5 bits.", + "offset": 5, + "size": 2 + }, + "FEN": { + "description": "Enable FIFOs: 0 = FIFOs are disabled (character mode) that is, the FIFOs become 1-byte-deep holding registers 1 = transmit and receive FIFO buffers are enabled (FIFO mode).", + "offset": 4, + "size": 1 + }, + "STP2": { + "description": "Two stop bits select. If this bit is set to 1, two stop bits are transmitted at the end of the frame. The receive logic does not check for two stop bits being received.", + "offset": 3, + "size": 1 + }, + "EPS": { + "description": "Even parity select. Controls the type of parity the UART uses during transmission and reception: 0 = odd parity. The UART generates or checks for an odd number of 1s in the data and parity bits. 1 = even parity. The UART generates or checks for an even number of 1s in the data and parity bits. This bit has no effect when the PEN bit disables parity checking and generation.", + "offset": 2, + "size": 1 + }, + "PEN": { + "description": "Parity enable: 0 = parity is disabled and no parity bit added to the data frame 1 = parity checking and generation is enabled.", + "offset": 1, + "size": 1 + }, + "BRK": { + "description": "Send break. If this bit is set to 1, a low-level is continually output on the UARTTXD output, after completing transmission of the current character. For the proper execution of the break command, the software must set this bit for at least two complete frames. For normal use, this bit must be cleared to 0.", + "offset": 0, + "size": 1 + } + } + } + }, + "UARTCR": { + "description": "Control Register, UARTCR", + "offset": 48, + "size": 32, + "reset_value": 768, + "children": { + "fields": { + "CTSEN": { + "description": "CTS hardware flow control enable. If this bit is set to 1, CTS hardware flow control is enabled. Data is only transmitted when the nUARTCTS signal is asserted.", + "offset": 15, + "size": 1 + }, + "RTSEN": { + "description": "RTS hardware flow control enable. If this bit is set to 1, RTS hardware flow control is enabled. Data is only requested when there is space in the receive FIFO for it to be received.", + "offset": 14, + "size": 1 + }, + "OUT2": { + "description": "This bit is the complement of the UART Out2 (nUARTOut2) modem status output. That is, when the bit is programmed to a 1, the output is 0. For DTE this can be used as Ring Indicator (RI).", + "offset": 13, + "size": 1 + }, + "OUT1": { + "description": "This bit is the complement of the UART Out1 (nUARTOut1) modem status output. That is, when the bit is programmed to a 1 the output is 0. For DTE this can be used as Data Carrier Detect (DCD).", + "offset": 12, + "size": 1 + }, + "RTS": { + "description": "Request to send. This bit is the complement of the UART request to send, nUARTRTS, modem status output. That is, when the bit is programmed to a 1 then nUARTRTS is LOW.", + "offset": 11, + "size": 1 + }, + "DTR": { + "description": "Data transmit ready. This bit is the complement of the UART data transmit ready, nUARTDTR, modem status output. That is, when the bit is programmed to a 1 then nUARTDTR is LOW.", + "offset": 10, + "size": 1 + }, + "RXE": { + "description": "Receive enable. If this bit is set to 1, the receive section of the UART is enabled. Data reception occurs for either UART signals or SIR signals depending on the setting of the SIREN bit. When the UART is disabled in the middle of reception, it completes the current character before stopping.", + "offset": 9, + "size": 1 + }, + "TXE": { + "description": "Transmit enable. If this bit is set to 1, the transmit section of the UART is enabled. Data transmission occurs for either UART signals, or SIR signals depending on the setting of the SIREN bit. When the UART is disabled in the middle of transmission, it completes the current character before stopping.", + "offset": 8, + "size": 1 + }, + "LBE": { + "description": "Loopback enable. If this bit is set to 1 and the SIREN bit is set to 1 and the SIRTEST bit in the Test Control Register, UARTTCR is set to 1, then the nSIROUT path is inverted, and fed through to the SIRIN path. The SIRTEST bit in the test register must be set to 1 to override the normal half-duplex SIR operation. This must be the requirement for accessing the test registers during normal operation, and SIRTEST must be cleared to 0 when loopback testing is finished. This feature reduces the amount of external coupling required during system test. If this bit is set to 1, and the SIRTEST bit is set to 0, the UARTTXD path is fed through to the UARTRXD path. In either SIR mode or UART mode, when this bit is set, the modem outputs are also fed through to the modem inputs. This bit is cleared to 0 on reset, to disable loopback.", + "offset": 7, + "size": 1 + }, + "SIRLP": { + "description": "SIR low-power IrDA mode. This bit selects the IrDA encoding mode. If this bit is cleared to 0, low-level bits are transmitted as an active high pulse with a width of 3 / 16th of the bit period. If this bit is set to 1, low-level bits are transmitted with a pulse width that is 3 times the period of the IrLPBaud16 input signal, regardless of the selected bit rate. Setting this bit uses less power, but might reduce transmission distances.", + "offset": 2, + "size": 1 + }, + "SIREN": { + "description": "SIR enable: 0 = IrDA SIR ENDEC is disabled. nSIROUT remains LOW (no light pulse generated), and signal transitions on SIRIN have no effect. 1 = IrDA SIR ENDEC is enabled. Data is transmitted and received on nSIROUT and SIRIN. UARTTXD remains HIGH, in the marking state. Signal transitions on UARTRXD or modem status inputs have no effect. This bit has no effect if the UARTEN bit disables the UART.", + "offset": 1, + "size": 1 + }, + "UARTEN": { + "description": "UART enable: 0 = UART is disabled. If the UART is disabled in the middle of transmission or reception, it completes the current character before stopping. 1 = the UART is enabled. Data transmission and reception occurs for either UART signals or SIR signals depending on the setting of the SIREN bit.", + "offset": 0, + "size": 1 + } + } + } + }, + "UARTIFLS": { + "description": "Interrupt FIFO Level Select Register, UARTIFLS", + "offset": 52, + "size": 32, + "reset_value": 18, + "children": { + "fields": { + "RXIFLSEL": { + "description": "Receive interrupt FIFO level select. The trigger points for the receive interrupt are as follows: b000 = Receive FIFO becomes >= 1 / 8 full b001 = Receive FIFO becomes >= 1 / 4 full b010 = Receive FIFO becomes >= 1 / 2 full b011 = Receive FIFO becomes >= 3 / 4 full b100 = Receive FIFO becomes >= 7 / 8 full b101-b111 = reserved.", + "offset": 3, + "size": 3 + }, + "TXIFLSEL": { + "description": "Transmit interrupt FIFO level select. The trigger points for the transmit interrupt are as follows: b000 = Transmit FIFO becomes <= 1 / 8 full b001 = Transmit FIFO becomes <= 1 / 4 full b010 = Transmit FIFO becomes <= 1 / 2 full b011 = Transmit FIFO becomes <= 3 / 4 full b100 = Transmit FIFO becomes <= 7 / 8 full b101-b111 = reserved.", + "offset": 0, + "size": 3 + } + } + } + }, + "UARTIMSC": { + "description": "Interrupt Mask Set/Clear Register, UARTIMSC", + "offset": 56, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "OEIM": { + "description": "Overrun error interrupt mask. A read returns the current mask for the UARTOEINTR interrupt. On a write of 1, the mask of the UARTOEINTR interrupt is set. A write of 0 clears the mask.", + "offset": 10, + "size": 1 + }, + "BEIM": { + "description": "Break error interrupt mask. A read returns the current mask for the UARTBEINTR interrupt. On a write of 1, the mask of the UARTBEINTR interrupt is set. A write of 0 clears the mask.", + "offset": 9, + "size": 1 + }, + "PEIM": { + "description": "Parity error interrupt mask. A read returns the current mask for the UARTPEINTR interrupt. On a write of 1, the mask of the UARTPEINTR interrupt is set. A write of 0 clears the mask.", + "offset": 8, + "size": 1 + }, + "FEIM": { + "description": "Framing error interrupt mask. A read returns the current mask for the UARTFEINTR interrupt. On a write of 1, the mask of the UARTFEINTR interrupt is set. A write of 0 clears the mask.", + "offset": 7, + "size": 1 + }, + "RTIM": { + "description": "Receive timeout interrupt mask. A read returns the current mask for the UARTRTINTR interrupt. On a write of 1, the mask of the UARTRTINTR interrupt is set. A write of 0 clears the mask.", + "offset": 6, + "size": 1 + }, + "TXIM": { + "description": "Transmit interrupt mask. A read returns the current mask for the UARTTXINTR interrupt. On a write of 1, the mask of the UARTTXINTR interrupt is set. A write of 0 clears the mask.", + "offset": 5, + "size": 1 + }, + "RXIM": { + "description": "Receive interrupt mask. A read returns the current mask for the UARTRXINTR interrupt. On a write of 1, the mask of the UARTRXINTR interrupt is set. A write of 0 clears the mask.", + "offset": 4, + "size": 1 + }, + "DSRMIM": { + "description": "nUARTDSR modem interrupt mask. A read returns the current mask for the UARTDSRINTR interrupt. On a write of 1, the mask of the UARTDSRINTR interrupt is set. A write of 0 clears the mask.", + "offset": 3, + "size": 1 + }, + "DCDMIM": { + "description": "nUARTDCD modem interrupt mask. A read returns the current mask for the UARTDCDINTR interrupt. On a write of 1, the mask of the UARTDCDINTR interrupt is set. A write of 0 clears the mask.", + "offset": 2, + "size": 1 + }, + "CTSMIM": { + "description": "nUARTCTS modem interrupt mask. A read returns the current mask for the UARTCTSINTR interrupt. On a write of 1, the mask of the UARTCTSINTR interrupt is set. A write of 0 clears the mask.", + "offset": 1, + "size": 1 + }, + "RIMIM": { + "description": "nUARTRI modem interrupt mask. A read returns the current mask for the UARTRIINTR interrupt. On a write of 1, the mask of the UARTRIINTR interrupt is set. A write of 0 clears the mask.", + "offset": 0, + "size": 1 + } + } + } + }, + "UARTRIS": { + "description": "Raw Interrupt Status Register, UARTRIS", + "offset": 60, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "OERIS": { + "description": "Overrun error interrupt status. Returns the raw interrupt state of the UARTOEINTR interrupt.", + "offset": 10, + "size": 1, + "access": "read-only" + }, + "BERIS": { + "description": "Break error interrupt status. Returns the raw interrupt state of the UARTBEINTR interrupt.", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "PERIS": { + "description": "Parity error interrupt status. Returns the raw interrupt state of the UARTPEINTR interrupt.", + "offset": 8, + "size": 1, + "access": "read-only" + }, + "FERIS": { + "description": "Framing error interrupt status. Returns the raw interrupt state of the UARTFEINTR interrupt.", + "offset": 7, + "size": 1, + "access": "read-only" + }, + "RTRIS": { + "description": "Receive timeout interrupt status. Returns the raw interrupt state of the UARTRTINTR interrupt. a", + "offset": 6, + "size": 1, + "access": "read-only" + }, + "TXRIS": { + "description": "Transmit interrupt status. Returns the raw interrupt state of the UARTTXINTR interrupt.", + "offset": 5, + "size": 1, + "access": "read-only" + }, + "RXRIS": { + "description": "Receive interrupt status. Returns the raw interrupt state of the UARTRXINTR interrupt.", + "offset": 4, + "size": 1, + "access": "read-only" + }, + "DSRRMIS": { + "description": "nUARTDSR modem interrupt status. Returns the raw interrupt state of the UARTDSRINTR interrupt.", + "offset": 3, + "size": 1, + "access": "read-only" + }, + "DCDRMIS": { + "description": "nUARTDCD modem interrupt status. Returns the raw interrupt state of the UARTDCDINTR interrupt.", + "offset": 2, + "size": 1, + "access": "read-only" + }, + "CTSRMIS": { + "description": "nUARTCTS modem interrupt status. Returns the raw interrupt state of the UARTCTSINTR interrupt.", + "offset": 1, + "size": 1, + "access": "read-only" + }, + "RIRMIS": { + "description": "nUARTRI modem interrupt status. Returns the raw interrupt state of the UARTRIINTR interrupt.", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "UARTMIS": { + "description": "Masked Interrupt Status Register, UARTMIS", + "offset": 64, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "OEMIS": { + "description": "Overrun error masked interrupt status. Returns the masked interrupt state of the UARTOEINTR interrupt.", + "offset": 10, + "size": 1, + "access": "read-only" + }, + "BEMIS": { + "description": "Break error masked interrupt status. Returns the masked interrupt state of the UARTBEINTR interrupt.", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "PEMIS": { + "description": "Parity error masked interrupt status. Returns the masked interrupt state of the UARTPEINTR interrupt.", + "offset": 8, + "size": 1, + "access": "read-only" + }, + "FEMIS": { + "description": "Framing error masked interrupt status. Returns the masked interrupt state of the UARTFEINTR interrupt.", + "offset": 7, + "size": 1, + "access": "read-only" + }, + "RTMIS": { + "description": "Receive timeout masked interrupt status. Returns the masked interrupt state of the UARTRTINTR interrupt.", + "offset": 6, + "size": 1, + "access": "read-only" + }, + "TXMIS": { + "description": "Transmit masked interrupt status. Returns the masked interrupt state of the UARTTXINTR interrupt.", + "offset": 5, + "size": 1, + "access": "read-only" + }, + "RXMIS": { + "description": "Receive masked interrupt status. Returns the masked interrupt state of the UARTRXINTR interrupt.", + "offset": 4, + "size": 1, + "access": "read-only" + }, + "DSRMMIS": { + "description": "nUARTDSR modem masked interrupt status. Returns the masked interrupt state of the UARTDSRINTR interrupt.", + "offset": 3, + "size": 1, + "access": "read-only" + }, + "DCDMMIS": { + "description": "nUARTDCD modem masked interrupt status. Returns the masked interrupt state of the UARTDCDINTR interrupt.", + "offset": 2, + "size": 1, + "access": "read-only" + }, + "CTSMMIS": { + "description": "nUARTCTS modem masked interrupt status. Returns the masked interrupt state of the UARTCTSINTR interrupt.", + "offset": 1, + "size": 1, + "access": "read-only" + }, + "RIMMIS": { + "description": "nUARTRI modem masked interrupt status. Returns the masked interrupt state of the UARTRIINTR interrupt.", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "UARTICR": { + "description": "Interrupt Clear Register, UARTICR", + "offset": 68, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "OEIC": { + "description": "Overrun error interrupt clear. Clears the UARTOEINTR interrupt.", + "offset": 10, + "size": 1 + }, + "BEIC": { + "description": "Break error interrupt clear. Clears the UARTBEINTR interrupt.", + "offset": 9, + "size": 1 + }, + "PEIC": { + "description": "Parity error interrupt clear. Clears the UARTPEINTR interrupt.", + "offset": 8, + "size": 1 + }, + "FEIC": { + "description": "Framing error interrupt clear. Clears the UARTFEINTR interrupt.", + "offset": 7, + "size": 1 + }, + "RTIC": { + "description": "Receive timeout interrupt clear. Clears the UARTRTINTR interrupt.", + "offset": 6, + "size": 1 + }, + "TXIC": { + "description": "Transmit interrupt clear. Clears the UARTTXINTR interrupt.", + "offset": 5, + "size": 1 + }, + "RXIC": { + "description": "Receive interrupt clear. Clears the UARTRXINTR interrupt.", + "offset": 4, + "size": 1 + }, + "DSRMIC": { + "description": "nUARTDSR modem interrupt clear. Clears the UARTDSRINTR interrupt.", + "offset": 3, + "size": 1 + }, + "DCDMIC": { + "description": "nUARTDCD modem interrupt clear. Clears the UARTDCDINTR interrupt.", + "offset": 2, + "size": 1 + }, + "CTSMIC": { + "description": "nUARTCTS modem interrupt clear. Clears the UARTCTSINTR interrupt.", + "offset": 1, + "size": 1 + }, + "RIMIC": { + "description": "nUARTRI modem interrupt clear. Clears the UARTRIINTR interrupt.", + "offset": 0, + "size": 1 + } + } + } + }, + "UARTDMACR": { + "description": "DMA Control Register, UARTDMACR", + "offset": 72, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "DMAONERR": { + "description": "DMA on error. If this bit is set to 1, the DMA receive request outputs, UARTRXDMASREQ or UARTRXDMABREQ, are disabled when the UART error interrupt is asserted.", + "offset": 2, + "size": 1 + }, + "TXDMAE": { + "description": "Transmit DMA enable. If this bit is set to 1, DMA for the transmit FIFO is enabled.", + "offset": 1, + "size": 1 + }, + "RXDMAE": { + "description": "Receive DMA enable. If this bit is set to 1, DMA for the receive FIFO is enabled.", + "offset": 0, + "size": 1 + } + } + } + }, + "UARTPERIPHID0": { + "description": "UARTPeriphID0 Register", + "offset": 4064, + "size": 32, + "reset_value": 17, + "children": { + "fields": { + "PARTNUMBER0": { + "description": "These bits read back as 0x11", + "offset": 0, + "size": 8, + "access": "read-only" + } + } + } + }, + "UARTPERIPHID1": { + "description": "UARTPeriphID1 Register", + "offset": 4068, + "size": 32, + "reset_value": 16, + "children": { + "fields": { + "DESIGNER0": { + "description": "These bits read back as 0x1", + "offset": 4, + "size": 4, + "access": "read-only" + }, + "PARTNUMBER1": { + "description": "These bits read back as 0x0", + "offset": 0, + "size": 4, + "access": "read-only" + } + } + } + }, + "UARTPERIPHID2": { + "description": "UARTPeriphID2 Register", + "offset": 4072, + "size": 32, + "reset_value": 52, + "children": { + "fields": { + "REVISION": { + "description": "This field depends on the revision of the UART: r1p0 0x0 r1p1 0x1 r1p3 0x2 r1p4 0x2 r1p5 0x3", + "offset": 4, + "size": 4, + "access": "read-only" + }, + "DESIGNER1": { + "description": "These bits read back as 0x4", + "offset": 0, + "size": 4, + "access": "read-only" + } + } + } + }, + "UARTPERIPHID3": { + "description": "UARTPeriphID3 Register", + "offset": 4076, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CONFIGURATION": { + "description": "These bits read back as 0x00", + "offset": 0, + "size": 8, + "access": "read-only" + } + } + } + }, + "UARTPCELLID0": { + "description": "UARTPCellID0 Register", + "offset": 4080, + "size": 32, + "reset_value": 13, + "children": { + "fields": { + "UARTPCELLID0": { + "description": "These bits read back as 0x0D", + "offset": 0, + "size": 8, + "access": "read-only" + } + } + } + }, + "UARTPCELLID1": { + "description": "UARTPCellID1 Register", + "offset": 4084, + "size": 32, + "reset_value": 240, + "children": { + "fields": { + "UARTPCELLID1": { + "description": "These bits read back as 0xF0", + "offset": 0, + "size": 8, + "access": "read-only" + } + } + } + }, + "UARTPCELLID2": { + "description": "UARTPCellID2 Register", + "offset": 4088, + "size": 32, + "reset_value": 5, + "children": { + "fields": { + "UARTPCELLID2": { + "description": "These bits read back as 0x05", + "offset": 0, + "size": 8, + "access": "read-only" + } + } + } + }, + "UARTPCELLID3": { + "description": "UARTPCellID3 Register", + "offset": 4092, + "size": 32, + "reset_value": 177, + "children": { + "fields": { + "UARTPCELLID3": { + "description": "These bits read back as 0xB1", + "offset": 0, + "size": 8, + "access": "read-only" + } + } + } + } + } + } + }, + "SIO": { + "description": "Single-cycle IO block\\n\n Provides core-local and inter-core hardware for the two processors, with single-cycle access.", + "children": { + "registers": { + "CPUID": { + "description": "Processor core identifier\\n\n Value is 0 when read from processor core 0, and 1 when read from processor core 1.", + "offset": 0, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "GPIO_IN": { + "description": "Input value for GPIO pins", + "offset": 4, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_IN": { + "description": "Input value for GPIO0...29", + "offset": 0, + "size": 30, + "access": "read-only" + } + } + } + }, + "GPIO_HI_IN": { + "description": "Input value for QSPI pins", + "offset": 8, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_HI_IN": { + "description": "Input value on QSPI IO in order 0..5: SCLK, SSn, SD0, SD1, SD2, SD3", + "offset": 0, + "size": 6, + "access": "read-only" + } + } + } + }, + "GPIO_OUT": { + "description": "GPIO output value", + "offset": 16, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_OUT": { + "description": "Set output level (1/0 -> high/low) for GPIO0...29.\\n\n Reading back gives the last value written, NOT the input value from the pins.\\n\n If core 0 and core 1 both write to GPIO_OUT simultaneously (or to a SET/CLR/XOR alias),\\n\n the result is as though the write from core 0 took place first,\\n\n and the write from core 1 was then applied to that intermediate result.", + "offset": 0, + "size": 30 + } + } + } + }, + "GPIO_OUT_SET": { + "description": "GPIO output value set", + "offset": 20, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_OUT_SET": { + "description": "Perform an atomic bit-set on GPIO_OUT, i.e. `GPIO_OUT |= wdata`", + "offset": 0, + "size": 30, + "access": "write-only" + } + } + } + }, + "GPIO_OUT_CLR": { + "description": "GPIO output value clear", + "offset": 24, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_OUT_CLR": { + "description": "Perform an atomic bit-clear on GPIO_OUT, i.e. `GPIO_OUT &= ~wdata`", + "offset": 0, + "size": 30, + "access": "write-only" + } + } + } + }, + "GPIO_OUT_XOR": { + "description": "GPIO output value XOR", + "offset": 28, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_OUT_XOR": { + "description": "Perform an atomic bitwise XOR on GPIO_OUT, i.e. `GPIO_OUT ^= wdata`", + "offset": 0, + "size": 30, + "access": "write-only" + } + } + } + }, + "GPIO_OE": { + "description": "GPIO output enable", + "offset": 32, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_OE": { + "description": "Set output enable (1/0 -> output/input) for GPIO0...29.\\n\n Reading back gives the last value written.\\n\n If core 0 and core 1 both write to GPIO_OE simultaneously (or to a SET/CLR/XOR alias),\\n\n the result is as though the write from core 0 took place first,\\n\n and the write from core 1 was then applied to that intermediate result.", + "offset": 0, + "size": 30 + } + } + } + }, + "GPIO_OE_SET": { + "description": "GPIO output enable set", + "offset": 36, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_OE_SET": { + "description": "Perform an atomic bit-set on GPIO_OE, i.e. `GPIO_OE |= wdata`", + "offset": 0, + "size": 30, + "access": "write-only" + } + } + } + }, + "GPIO_OE_CLR": { + "description": "GPIO output enable clear", + "offset": 40, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_OE_CLR": { + "description": "Perform an atomic bit-clear on GPIO_OE, i.e. `GPIO_OE &= ~wdata`", + "offset": 0, + "size": 30, + "access": "write-only" + } + } + } + }, + "GPIO_OE_XOR": { + "description": "GPIO output enable XOR", + "offset": 44, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_OE_XOR": { + "description": "Perform an atomic bitwise XOR on GPIO_OE, i.e. `GPIO_OE ^= wdata`", + "offset": 0, + "size": 30, + "access": "write-only" + } + } + } + }, + "GPIO_HI_OUT": { + "description": "QSPI output value", + "offset": 48, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_HI_OUT": { + "description": "Set output level (1/0 -> high/low) for QSPI IO0...5.\\n\n Reading back gives the last value written, NOT the input value from the pins.\\n\n If core 0 and core 1 both write to GPIO_HI_OUT simultaneously (or to a SET/CLR/XOR alias),\\n\n the result is as though the write from core 0 took place first,\\n\n and the write from core 1 was then applied to that intermediate result.", + "offset": 0, + "size": 6 + } + } + } + }, + "GPIO_HI_OUT_SET": { + "description": "QSPI output value set", + "offset": 52, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_HI_OUT_SET": { + "description": "Perform an atomic bit-set on GPIO_HI_OUT, i.e. `GPIO_HI_OUT |= wdata`", + "offset": 0, + "size": 6, + "access": "write-only" + } + } + } + }, + "GPIO_HI_OUT_CLR": { + "description": "QSPI output value clear", + "offset": 56, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_HI_OUT_CLR": { + "description": "Perform an atomic bit-clear on GPIO_HI_OUT, i.e. `GPIO_HI_OUT &= ~wdata`", + "offset": 0, + "size": 6, + "access": "write-only" + } + } + } + }, + "GPIO_HI_OUT_XOR": { + "description": "QSPI output value XOR", + "offset": 60, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_HI_OUT_XOR": { + "description": "Perform an atomic bitwise XOR on GPIO_HI_OUT, i.e. `GPIO_HI_OUT ^= wdata`", + "offset": 0, + "size": 6, + "access": "write-only" + } + } + } + }, + "GPIO_HI_OE": { + "description": "QSPI output enable", + "offset": 64, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_HI_OE": { + "description": "Set output enable (1/0 -> output/input) for QSPI IO0...5.\\n\n Reading back gives the last value written.\\n\n If core 0 and core 1 both write to GPIO_HI_OE simultaneously (or to a SET/CLR/XOR alias),\\n\n the result is as though the write from core 0 took place first,\\n\n and the write from core 1 was then applied to that intermediate result.", + "offset": 0, + "size": 6 + } + } + } + }, + "GPIO_HI_OE_SET": { + "description": "QSPI output enable set", + "offset": 68, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_HI_OE_SET": { + "description": "Perform an atomic bit-set on GPIO_HI_OE, i.e. `GPIO_HI_OE |= wdata`", + "offset": 0, + "size": 6, + "access": "write-only" + } + } + } + }, + "GPIO_HI_OE_CLR": { + "description": "QSPI output enable clear", + "offset": 72, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_HI_OE_CLR": { + "description": "Perform an atomic bit-clear on GPIO_HI_OE, i.e. `GPIO_HI_OE &= ~wdata`", + "offset": 0, + "size": 6, + "access": "write-only" + } + } + } + }, + "GPIO_HI_OE_XOR": { + "description": "QSPI output enable XOR", + "offset": 76, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "GPIO_HI_OE_XOR": { + "description": "Perform an atomic bitwise XOR on GPIO_HI_OE, i.e. `GPIO_HI_OE ^= wdata`", + "offset": 0, + "size": 6, + "access": "write-only" + } + } + } + }, + "FIFO_ST": { + "description": "Status register for inter-core FIFOs (mailboxes).\\n\n There is one FIFO in the core 0 -> core 1 direction, and one core 1 -> core 0. Both are 32 bits wide and 8 words deep.\\n\n Core 0 can see the read side of the 1->0 FIFO (RX), and the write side of 0->1 FIFO (TX).\\n\n Core 1 can see the read side of the 0->1 FIFO (RX), and the write side of 1->0 FIFO (TX).\\n\n The SIO IRQ for each core is the logical OR of the VLD, WOF and ROE fields of its FIFO_ST register.", + "offset": 80, + "size": 32, + "reset_value": 2, + "children": { + "fields": { + "ROE": { + "description": "Sticky flag indicating the RX FIFO was read when empty. This read was ignored by the FIFO.", + "offset": 3, + "size": 1 + }, + "WOF": { + "description": "Sticky flag indicating the TX FIFO was written when full. This write was ignored by the FIFO.", + "offset": 2, + "size": 1 + }, + "RDY": { + "description": "Value is 1 if this core's TX FIFO is not full (i.e. if FIFO_WR is ready for more data)", + "offset": 1, + "size": 1, + "access": "read-only" + }, + "VLD": { + "description": "Value is 1 if this core's RX FIFO is not empty (i.e. if FIFO_RD is valid)", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "FIFO_WR": { + "description": "Write access to this core's TX FIFO", + "offset": 84, + "size": 32, + "reset_value": 0, + "access": "write-only" + }, + "FIFO_RD": { + "description": "Read access to this core's RX FIFO", + "offset": 88, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "SPINLOCK_ST": { + "description": "Spinlock state\\n\n A bitmap containing the state of all 32 spinlocks (1=locked).\\n\n Mainly intended for debugging.", + "offset": 92, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "DIV_UDIVIDEND": { + "description": "Divider unsigned dividend\\n\n Write to the DIVIDEND operand of the divider, i.e. the p in `p / q`.\\n\n Any operand write starts a new calculation. The results appear in QUOTIENT, REMAINDER.\\n\n UDIVIDEND/SDIVIDEND are aliases of the same internal register. The U alias starts an\\n\n unsigned calculation, and the S alias starts a signed calculation.", + "offset": 96, + "size": 32, + "reset_value": 0 + }, + "DIV_UDIVISOR": { + "description": "Divider unsigned divisor\\n\n Write to the DIVISOR operand of the divider, i.e. the q in `p / q`.\\n\n Any operand write starts a new calculation. The results appear in QUOTIENT, REMAINDER.\\n\n UDIVISOR/SDIVISOR are aliases of the same internal register. The U alias starts an\\n\n unsigned calculation, and the S alias starts a signed calculation.", + "offset": 100, + "size": 32, + "reset_value": 0 + }, + "DIV_SDIVIDEND": { + "description": "Divider signed dividend\\n\n The same as UDIVIDEND, but starts a signed calculation, rather than unsigned.", + "offset": 104, + "size": 32, + "reset_value": 0 + }, + "DIV_SDIVISOR": { + "description": "Divider signed divisor\\n\n The same as UDIVISOR, but starts a signed calculation, rather than unsigned.", + "offset": 108, + "size": 32, + "reset_value": 0 + }, + "DIV_QUOTIENT": { + "description": "Divider result quotient\\n\n The result of `DIVIDEND / DIVISOR` (division). Contents undefined while CSR_READY is low.\\n\n For signed calculations, QUOTIENT is negative when the signs of DIVIDEND and DIVISOR differ.\\n\n This register can be written to directly, for context save/restore purposes. This halts any\\n\n in-progress calculation and sets the CSR_READY and CSR_DIRTY flags.\\n\n Reading from QUOTIENT clears the CSR_DIRTY flag, so should read results in the order\\n\n REMAINDER, QUOTIENT if CSR_DIRTY is used.", + "offset": 112, + "size": 32, + "reset_value": 0 + }, + "DIV_REMAINDER": { + "description": "Divider result remainder\\n\n The result of `DIVIDEND % DIVISOR` (modulo). Contents undefined while CSR_READY is low.\\n\n For signed calculations, REMAINDER is negative only when DIVIDEND is negative.\\n\n This register can be written to directly, for context save/restore purposes. This halts any\\n\n in-progress calculation and sets the CSR_READY and CSR_DIRTY flags.", + "offset": 116, + "size": 32, + "reset_value": 0 + }, + "DIV_CSR": { + "description": "Control and status register for divider.", + "offset": 120, + "size": 32, + "reset_value": 1, + "children": { + "fields": { + "DIRTY": { + "description": "Changes to 1 when any register is written, and back to 0 when QUOTIENT is read.\\n\n Software can use this flag to make save/restore more efficient (skip if not DIRTY).\\n\n If the flag is used in this way, it's recommended to either read QUOTIENT only,\\n\n or REMAINDER and then QUOTIENT, to prevent data loss on context switch.", + "offset": 1, + "size": 1, + "access": "read-only" + }, + "READY": { + "description": "Reads as 0 when a calculation is in progress, 1 otherwise.\\n\n Writing an operand (xDIVIDEND, xDIVISOR) will immediately start a new calculation, no\\n\n matter if one is already in progress.\\n\n Writing to a result register will immediately terminate any in-progress calculation\\n\n and set the READY and DIRTY flags.", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "INTERP0_ACCUM0": { + "description": "Read/write access to accumulator 0", + "offset": 128, + "size": 32, + "reset_value": 0 + }, + "INTERP0_ACCUM1": { + "description": "Read/write access to accumulator 1", + "offset": 132, + "size": 32, + "reset_value": 0 + }, + "INTERP0_BASE0": { + "description": "Read/write access to BASE0 register.", + "offset": 136, + "size": 32, + "reset_value": 0 + }, + "INTERP0_BASE1": { + "description": "Read/write access to BASE1 register.", + "offset": 140, + "size": 32, + "reset_value": 0 + }, + "INTERP0_BASE2": { + "description": "Read/write access to BASE2 register.", + "offset": 144, + "size": 32, + "reset_value": 0 + }, + "INTERP0_POP_LANE0": { + "description": "Read LANE0 result, and simultaneously write lane results to both accumulators (POP).", + "offset": 148, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "INTERP0_POP_LANE1": { + "description": "Read LANE1 result, and simultaneously write lane results to both accumulators (POP).", + "offset": 152, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "INTERP0_POP_FULL": { + "description": "Read FULL result, and simultaneously write lane results to both accumulators (POP).", + "offset": 156, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "INTERP0_PEEK_LANE0": { + "description": "Read LANE0 result, without altering any internal state (PEEK).", + "offset": 160, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "INTERP0_PEEK_LANE1": { + "description": "Read LANE1 result, without altering any internal state (PEEK).", + "offset": 164, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "INTERP0_PEEK_FULL": { + "description": "Read FULL result, without altering any internal state (PEEK).", + "offset": 168, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "INTERP0_CTRL_LANE0": { + "description": "Control register for lane 0", + "offset": 172, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "OVERF": { + "description": "Set if either OVERF0 or OVERF1 is set.", + "offset": 25, + "size": 1, + "access": "read-only" + }, + "OVERF1": { + "description": "Indicates if any masked-off MSBs in ACCUM1 are set.", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "OVERF0": { + "description": "Indicates if any masked-off MSBs in ACCUM0 are set.", + "offset": 23, + "size": 1, + "access": "read-only" + }, + "BLEND": { + "description": "Only present on INTERP0 on each core. If BLEND mode is enabled:\\n\n - LANE1 result is a linear interpolation between BASE0 and BASE1, controlled\\n\n by the 8 LSBs of lane 1 shift and mask value (a fractional number between\\n\n 0 and 255/256ths)\\n\n - LANE0 result does not have BASE0 added (yields only the 8 LSBs of lane 1 shift+mask value)\\n\n - FULL result does not have lane 1 shift+mask value added (BASE2 + lane 0 shift+mask)\\n\n LANE1 SIGNED flag controls whether the interpolation is signed or unsigned.", + "offset": 21, + "size": 1 + }, + "FORCE_MSB": { + "description": "ORed into bits 29:28 of the lane result presented to the processor on the bus.\\n\n No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence\\n\n of pointers into flash or SRAM.", + "offset": 19, + "size": 2 + }, + "ADD_RAW": { + "description": "If 1, mask + shift is bypassed for LANE0 result. This does not affect FULL result.", + "offset": 18, + "size": 1 + }, + "CROSS_RESULT": { + "description": "If 1, feed the opposite lane's result into this lane's accumulator on POP.", + "offset": 17, + "size": 1 + }, + "CROSS_INPUT": { + "description": "If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware.\\n\n Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass)", + "offset": 16, + "size": 1 + }, + "SIGNED": { + "description": "If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits\\n\n before adding to BASE0, and LANE0 PEEK/POP appear extended to 32 bits when read by processor.", + "offset": 15, + "size": 1 + }, + "MASK_MSB": { + "description": "The most-significant bit allowed to pass by the mask (inclusive)\\n\n Setting MSB < LSB may cause chip to turn inside-out", + "offset": 10, + "size": 5 + }, + "MASK_LSB": { + "description": "The least-significant bit allowed to pass by the mask (inclusive)", + "offset": 5, + "size": 5 + }, + "SHIFT": { + "description": "Logical right-shift applied to accumulator before masking", + "offset": 0, + "size": 5 + } + } + } + }, + "INTERP0_CTRL_LANE1": { + "description": "Control register for lane 1", + "offset": 176, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FORCE_MSB": { + "description": "ORed into bits 29:28 of the lane result presented to the processor on the bus.\\n\n No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence\\n\n of pointers into flash or SRAM.", + "offset": 19, + "size": 2 + }, + "ADD_RAW": { + "description": "If 1, mask + shift is bypassed for LANE1 result. This does not affect FULL result.", + "offset": 18, + "size": 1 + }, + "CROSS_RESULT": { + "description": "If 1, feed the opposite lane's result into this lane's accumulator on POP.", + "offset": 17, + "size": 1 + }, + "CROSS_INPUT": { + "description": "If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware.\\n\n Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass)", + "offset": 16, + "size": 1 + }, + "SIGNED": { + "description": "If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits\\n\n before adding to BASE1, and LANE1 PEEK/POP appear extended to 32 bits when read by processor.", + "offset": 15, + "size": 1 + }, + "MASK_MSB": { + "description": "The most-significant bit allowed to pass by the mask (inclusive)\\n\n Setting MSB < LSB may cause chip to turn inside-out", + "offset": 10, + "size": 5 + }, + "MASK_LSB": { + "description": "The least-significant bit allowed to pass by the mask (inclusive)", + "offset": 5, + "size": 5 + }, + "SHIFT": { + "description": "Logical right-shift applied to accumulator before masking", + "offset": 0, + "size": 5 + } + } + } + }, + "INTERP0_ACCUM0_ADD": { + "description": "Values written here are atomically added to ACCUM0\\n\n Reading yields lane 0's raw shift and mask value (BASE0 not added).", + "offset": 180, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INTERP0_ACCUM0_ADD": { + "offset": 0, + "size": 24 + } + } + } + }, + "INTERP0_ACCUM1_ADD": { + "description": "Values written here are atomically added to ACCUM1\\n\n Reading yields lane 1's raw shift and mask value (BASE1 not added).", + "offset": 184, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INTERP0_ACCUM1_ADD": { + "offset": 0, + "size": 24 + } + } + } + }, + "INTERP0_BASE_1AND0": { + "description": "On write, the lower 16 bits go to BASE0, upper bits to BASE1 simultaneously.\\n\n Each half is sign-extended to 32 bits if that lane's SIGNED flag is set.", + "offset": 188, + "size": 32, + "reset_value": 0, + "access": "write-only" + }, + "INTERP1_ACCUM0": { + "description": "Read/write access to accumulator 0", + "offset": 192, + "size": 32, + "reset_value": 0 + }, + "INTERP1_ACCUM1": { + "description": "Read/write access to accumulator 1", + "offset": 196, + "size": 32, + "reset_value": 0 + }, + "INTERP1_BASE0": { + "description": "Read/write access to BASE0 register.", + "offset": 200, + "size": 32, + "reset_value": 0 + }, + "INTERP1_BASE1": { + "description": "Read/write access to BASE1 register.", + "offset": 204, + "size": 32, + "reset_value": 0 + }, + "INTERP1_BASE2": { + "description": "Read/write access to BASE2 register.", + "offset": 208, + "size": 32, + "reset_value": 0 + }, + "INTERP1_POP_LANE0": { + "description": "Read LANE0 result, and simultaneously write lane results to both accumulators (POP).", + "offset": 212, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "INTERP1_POP_LANE1": { + "description": "Read LANE1 result, and simultaneously write lane results to both accumulators (POP).", + "offset": 216, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "INTERP1_POP_FULL": { + "description": "Read FULL result, and simultaneously write lane results to both accumulators (POP).", + "offset": 220, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "INTERP1_PEEK_LANE0": { + "description": "Read LANE0 result, without altering any internal state (PEEK).", + "offset": 224, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "INTERP1_PEEK_LANE1": { + "description": "Read LANE1 result, without altering any internal state (PEEK).", + "offset": 228, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "INTERP1_PEEK_FULL": { + "description": "Read FULL result, without altering any internal state (PEEK).", + "offset": 232, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "INTERP1_CTRL_LANE0": { + "description": "Control register for lane 0", + "offset": 236, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "OVERF": { + "description": "Set if either OVERF0 or OVERF1 is set.", + "offset": 25, + "size": 1, + "access": "read-only" + }, + "OVERF1": { + "description": "Indicates if any masked-off MSBs in ACCUM1 are set.", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "OVERF0": { + "description": "Indicates if any masked-off MSBs in ACCUM0 are set.", + "offset": 23, + "size": 1, + "access": "read-only" + }, + "CLAMP": { + "description": "Only present on INTERP1 on each core. If CLAMP mode is enabled:\\n\n - LANE0 result is shifted and masked ACCUM0, clamped by a lower bound of\\n\n BASE0 and an upper bound of BASE1.\\n\n - Signedness of these comparisons is determined by LANE0_CTRL_SIGNED", + "offset": 22, + "size": 1 + }, + "FORCE_MSB": { + "description": "ORed into bits 29:28 of the lane result presented to the processor on the bus.\\n\n No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence\\n\n of pointers into flash or SRAM.", + "offset": 19, + "size": 2 + }, + "ADD_RAW": { + "description": "If 1, mask + shift is bypassed for LANE0 result. This does not affect FULL result.", + "offset": 18, + "size": 1 + }, + "CROSS_RESULT": { + "description": "If 1, feed the opposite lane's result into this lane's accumulator on POP.", + "offset": 17, + "size": 1 + }, + "CROSS_INPUT": { + "description": "If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware.\\n\n Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass)", + "offset": 16, + "size": 1 + }, + "SIGNED": { + "description": "If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits\\n\n before adding to BASE0, and LANE0 PEEK/POP appear extended to 32 bits when read by processor.", + "offset": 15, + "size": 1 + }, + "MASK_MSB": { + "description": "The most-significant bit allowed to pass by the mask (inclusive)\\n\n Setting MSB < LSB may cause chip to turn inside-out", + "offset": 10, + "size": 5 + }, + "MASK_LSB": { + "description": "The least-significant bit allowed to pass by the mask (inclusive)", + "offset": 5, + "size": 5 + }, + "SHIFT": { + "description": "Logical right-shift applied to accumulator before masking", + "offset": 0, + "size": 5 + } + } + } + }, + "INTERP1_CTRL_LANE1": { + "description": "Control register for lane 1", + "offset": 240, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FORCE_MSB": { + "description": "ORed into bits 29:28 of the lane result presented to the processor on the bus.\\n\n No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence\\n\n of pointers into flash or SRAM.", + "offset": 19, + "size": 2 + }, + "ADD_RAW": { + "description": "If 1, mask + shift is bypassed for LANE1 result. This does not affect FULL result.", + "offset": 18, + "size": 1 + }, + "CROSS_RESULT": { + "description": "If 1, feed the opposite lane's result into this lane's accumulator on POP.", + "offset": 17, + "size": 1 + }, + "CROSS_INPUT": { + "description": "If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware.\\n\n Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass)", + "offset": 16, + "size": 1 + }, + "SIGNED": { + "description": "If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits\\n\n before adding to BASE1, and LANE1 PEEK/POP appear extended to 32 bits when read by processor.", + "offset": 15, + "size": 1 + }, + "MASK_MSB": { + "description": "The most-significant bit allowed to pass by the mask (inclusive)\\n\n Setting MSB < LSB may cause chip to turn inside-out", + "offset": 10, + "size": 5 + }, + "MASK_LSB": { + "description": "The least-significant bit allowed to pass by the mask (inclusive)", + "offset": 5, + "size": 5 + }, + "SHIFT": { + "description": "Logical right-shift applied to accumulator before masking", + "offset": 0, + "size": 5 + } + } + } + }, + "INTERP1_ACCUM0_ADD": { + "description": "Values written here are atomically added to ACCUM0\\n\n Reading yields lane 0's raw shift and mask value (BASE0 not added).", + "offset": 244, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INTERP1_ACCUM0_ADD": { + "offset": 0, + "size": 24 + } + } + } + }, + "INTERP1_ACCUM1_ADD": { + "description": "Values written here are atomically added to ACCUM1\\n\n Reading yields lane 1's raw shift and mask value (BASE1 not added).", + "offset": 248, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INTERP1_ACCUM1_ADD": { + "offset": 0, + "size": 24 + } + } + } + }, + "INTERP1_BASE_1AND0": { + "description": "On write, the lower 16 bits go to BASE0, upper bits to BASE1 simultaneously.\\n\n Each half is sign-extended to 32 bits if that lane's SIGNED flag is set.", + "offset": 252, + "size": 32, + "reset_value": 0, + "access": "write-only" + }, + "SPINLOCK0": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 256, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK1": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 260, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK2": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 264, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK3": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 268, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK4": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 272, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK5": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 276, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK6": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 280, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK7": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 284, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK8": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 288, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK9": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 292, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK10": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 296, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK11": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 300, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK12": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 304, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK13": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 308, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK14": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 312, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK15": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 316, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK16": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 320, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK17": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 324, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK18": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 328, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK19": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 332, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK20": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 336, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK21": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 340, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK22": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 344, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK23": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 348, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK24": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 352, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK25": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 356, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK26": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 360, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK27": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 364, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK28": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 368, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK29": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 372, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK30": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 376, + "size": 32, + "reset_value": 0 + }, + "SPINLOCK31": { + "description": "Reading from a spinlock address will:\\n\n - Return 0 if lock is already locked\\n\n - Otherwise return nonzero, and simultaneously claim the lock\\n\\n\n Writing (any value) releases the lock.\\n\n If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins.\\n\n The value returned on success is 0x1 << lock number.", + "offset": 380, + "size": 32, + "reset_value": 0 + } + } + } + }, + "SPI0": { + "children": { + "registers": { + "SSPCR0": { + "description": "Control register 0, SSPCR0 on page 3-4", + "offset": 0, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SCR": { + "description": "Serial clock rate. The value SCR is used to generate the transmit and receive bit rate of the PrimeCell SSP. The bit rate is: F SSPCLK CPSDVSR x (1+SCR) where CPSDVSR is an even value from 2-254, programmed through the SSPCPSR register and SCR is a value from 0-255.", + "offset": 8, + "size": 8 + }, + "SPH": { + "description": "SSPCLKOUT phase, applicable to Motorola SPI frame format only. See Motorola SPI frame format on page 2-10.", + "offset": 7, + "size": 1 + }, + "SPO": { + "description": "SSPCLKOUT polarity, applicable to Motorola SPI frame format only. See Motorola SPI frame format on page 2-10.", + "offset": 6, + "size": 1 + }, + "FRF": { + "description": "Frame format: 00 Motorola SPI frame format. 01 TI synchronous serial frame format. 10 National Microwire frame format. 11 Reserved, undefined operation.", + "offset": 4, + "size": 2 + }, + "DSS": { + "description": "Data Size Select: 0000 Reserved, undefined operation. 0001 Reserved, undefined operation. 0010 Reserved, undefined operation. 0011 4-bit data. 0100 5-bit data. 0101 6-bit data. 0110 7-bit data. 0111 8-bit data. 1000 9-bit data. 1001 10-bit data. 1010 11-bit data. 1011 12-bit data. 1100 13-bit data. 1101 14-bit data. 1110 15-bit data. 1111 16-bit data.", + "offset": 0, + "size": 4 + } + } + } + }, + "SSPCR1": { + "description": "Control register 1, SSPCR1 on page 3-5", + "offset": 4, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SOD": { + "description": "Slave-mode output disable. This bit is relevant only in the slave mode, MS=1. In multiple-slave systems, it is possible for an PrimeCell SSP master to broadcast a message to all slaves in the system while ensuring that only one slave drives data onto its serial output line. In such systems the RXD lines from multiple slaves could be tied together. To operate in such systems, the SOD bit can be set if the PrimeCell SSP slave is not supposed to drive the SSPTXD line: 0 SSP can drive the SSPTXD output in slave mode. 1 SSP must not drive the SSPTXD output in slave mode.", + "offset": 3, + "size": 1 + }, + "MS": { + "description": "Master or slave mode select. This bit can be modified only when the PrimeCell SSP is disabled, SSE=0: 0 Device configured as master, default. 1 Device configured as slave.", + "offset": 2, + "size": 1 + }, + "SSE": { + "description": "Synchronous serial port enable: 0 SSP operation disabled. 1 SSP operation enabled.", + "offset": 1, + "size": 1 + }, + "LBM": { + "description": "Loop back mode: 0 Normal serial port operation enabled. 1 Output of transmit serial shifter is connected to input of receive serial shifter internally.", + "offset": 0, + "size": 1 + } + } + } + }, + "SSPDR": { + "description": "Data register, SSPDR on page 3-6", + "offset": 8, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "DATA": { + "description": "Transmit/Receive FIFO: Read Receive FIFO. Write Transmit FIFO. You must right-justify data when the PrimeCell SSP is programmed for a data size that is less than 16 bits. Unused bits at the top are ignored by transmit logic. The receive logic automatically right-justifies.", + "offset": 0, + "size": 16 + } + } + } + }, + "SSPSR": { + "description": "Status register, SSPSR on page 3-7", + "offset": 12, + "size": 32, + "reset_value": 3, + "children": { + "fields": { + "BSY": { + "description": "PrimeCell SSP busy flag, RO: 0 SSP is idle. 1 SSP is currently transmitting and/or receiving a frame or the transmit FIFO is not empty.", + "offset": 4, + "size": 1, + "access": "read-only" + }, + "RFF": { + "description": "Receive FIFO full, RO: 0 Receive FIFO is not full. 1 Receive FIFO is full.", + "offset": 3, + "size": 1, + "access": "read-only" + }, + "RNE": { + "description": "Receive FIFO not empty, RO: 0 Receive FIFO is empty. 1 Receive FIFO is not empty.", + "offset": 2, + "size": 1, + "access": "read-only" + }, + "TNF": { + "description": "Transmit FIFO not full, RO: 0 Transmit FIFO is full. 1 Transmit FIFO is not full.", + "offset": 1, + "size": 1, + "access": "read-only" + }, + "TFE": { + "description": "Transmit FIFO empty, RO: 0 Transmit FIFO is not empty. 1 Transmit FIFO is empty.", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "SSPCPSR": { + "description": "Clock prescale register, SSPCPSR on page 3-8", + "offset": 16, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CPSDVSR": { + "description": "Clock prescale divisor. Must be an even number from 2-254, depending on the frequency of SSPCLK. The least significant bit always returns zero on reads.", + "offset": 0, + "size": 8 + } + } + } + }, + "SSPIMSC": { + "description": "Interrupt mask set or clear register, SSPIMSC on page 3-9", + "offset": 20, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "TXIM": { + "description": "Transmit FIFO interrupt mask: 0 Transmit FIFO half empty or less condition interrupt is masked. 1 Transmit FIFO half empty or less condition interrupt is not masked.", + "offset": 3, + "size": 1 + }, + "RXIM": { + "description": "Receive FIFO interrupt mask: 0 Receive FIFO half full or less condition interrupt is masked. 1 Receive FIFO half full or less condition interrupt is not masked.", + "offset": 2, + "size": 1 + }, + "RTIM": { + "description": "Receive timeout interrupt mask: 0 Receive FIFO not empty and no read prior to timeout period interrupt is masked. 1 Receive FIFO not empty and no read prior to timeout period interrupt is not masked.", + "offset": 1, + "size": 1 + }, + "RORIM": { + "description": "Receive overrun interrupt mask: 0 Receive FIFO written to while full condition interrupt is masked. 1 Receive FIFO written to while full condition interrupt is not masked.", + "offset": 0, + "size": 1 + } + } + } + }, + "SSPRIS": { + "description": "Raw interrupt status register, SSPRIS on page 3-10", + "offset": 24, + "size": 32, + "reset_value": 8, + "children": { + "fields": { + "TXRIS": { + "description": "Gives the raw interrupt state, prior to masking, of the SSPTXINTR interrupt", + "offset": 3, + "size": 1, + "access": "read-only" + }, + "RXRIS": { + "description": "Gives the raw interrupt state, prior to masking, of the SSPRXINTR interrupt", + "offset": 2, + "size": 1, + "access": "read-only" + }, + "RTRIS": { + "description": "Gives the raw interrupt state, prior to masking, of the SSPRTINTR interrupt", + "offset": 1, + "size": 1, + "access": "read-only" + }, + "RORRIS": { + "description": "Gives the raw interrupt state, prior to masking, of the SSPRORINTR interrupt", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "SSPMIS": { + "description": "Masked interrupt status register, SSPMIS on page 3-11", + "offset": 28, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "TXMIS": { + "description": "Gives the transmit FIFO masked interrupt state, after masking, of the SSPTXINTR interrupt", + "offset": 3, + "size": 1, + "access": "read-only" + }, + "RXMIS": { + "description": "Gives the receive FIFO masked interrupt state, after masking, of the SSPRXINTR interrupt", + "offset": 2, + "size": 1, + "access": "read-only" + }, + "RTMIS": { + "description": "Gives the receive timeout masked interrupt state, after masking, of the SSPRTINTR interrupt", + "offset": 1, + "size": 1, + "access": "read-only" + }, + "RORMIS": { + "description": "Gives the receive over run masked interrupt status, after masking, of the SSPRORINTR interrupt", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "SSPICR": { + "description": "Interrupt clear register, SSPICR on page 3-11", + "offset": 32, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "RTIC": { + "description": "Clears the SSPRTINTR interrupt", + "offset": 1, + "size": 1 + }, + "RORIC": { + "description": "Clears the SSPRORINTR interrupt", + "offset": 0, + "size": 1 + } + } + } + }, + "SSPDMACR": { + "description": "DMA control register, SSPDMACR on page 3-12", + "offset": 36, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "TXDMAE": { + "description": "Transmit DMA Enable. If this bit is set to 1, DMA for the transmit FIFO is enabled.", + "offset": 1, + "size": 1 + }, + "RXDMAE": { + "description": "Receive DMA Enable. If this bit is set to 1, DMA for the receive FIFO is enabled.", + "offset": 0, + "size": 1 + } + } + } + }, + "SSPPERIPHID0": { + "description": "Peripheral identification registers, SSPPeriphID0-3 on page 3-13", + "offset": 4064, + "size": 32, + "reset_value": 34, + "children": { + "fields": { + "PARTNUMBER0": { + "description": "These bits read back as 0x22", + "offset": 0, + "size": 8, + "access": "read-only" + } + } + } + }, + "SSPPERIPHID1": { + "description": "Peripheral identification registers, SSPPeriphID0-3 on page 3-13", + "offset": 4068, + "size": 32, + "reset_value": 16, + "children": { + "fields": { + "DESIGNER0": { + "description": "These bits read back as 0x1", + "offset": 4, + "size": 4, + "access": "read-only" + }, + "PARTNUMBER1": { + "description": "These bits read back as 0x0", + "offset": 0, + "size": 4, + "access": "read-only" + } + } + } + }, + "SSPPERIPHID2": { + "description": "Peripheral identification registers, SSPPeriphID0-3 on page 3-13", + "offset": 4072, + "size": 32, + "reset_value": 52, + "children": { + "fields": { + "REVISION": { + "description": "These bits return the peripheral revision", + "offset": 4, + "size": 4, + "access": "read-only" + }, + "DESIGNER1": { + "description": "These bits read back as 0x4", + "offset": 0, + "size": 4, + "access": "read-only" + } + } + } + }, + "SSPPERIPHID3": { + "description": "Peripheral identification registers, SSPPeriphID0-3 on page 3-13", + "offset": 4076, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CONFIGURATION": { + "description": "These bits read back as 0x00", + "offset": 0, + "size": 8, + "access": "read-only" + } + } + } + }, + "SSPPCELLID0": { + "description": "PrimeCell identification registers, SSPPCellID0-3 on page 3-16", + "offset": 4080, + "size": 32, + "reset_value": 13, + "children": { + "fields": { + "SSPPCELLID0": { + "description": "These bits read back as 0x0D", + "offset": 0, + "size": 8, + "access": "read-only" + } + } + } + }, + "SSPPCELLID1": { + "description": "PrimeCell identification registers, SSPPCellID0-3 on page 3-16", + "offset": 4084, + "size": 32, + "reset_value": 240, + "children": { + "fields": { + "SSPPCELLID1": { + "description": "These bits read back as 0xF0", + "offset": 0, + "size": 8, + "access": "read-only" + } + } + } + }, + "SSPPCELLID2": { + "description": "PrimeCell identification registers, SSPPCellID0-3 on page 3-16", + "offset": 4088, + "size": 32, + "reset_value": 5, + "children": { + "fields": { + "SSPPCELLID2": { + "description": "These bits read back as 0x05", + "offset": 0, + "size": 8, + "access": "read-only" + } + } + } + }, + "SSPPCELLID3": { + "description": "PrimeCell identification registers, SSPPCellID0-3 on page 3-16", + "offset": 4092, + "size": 32, + "reset_value": 177, + "children": { + "fields": { + "SSPPCELLID3": { + "description": "These bits read back as 0xB1", + "offset": 0, + "size": 8, + "access": "read-only" + } + } + } + } + } + } + }, + "USBCTRL_REGS": { + "description": "USB FS/LS controller device registers", + "children": { + "registers": { + "ADDR_ENDP": { + "description": "Device address and endpoint control", + "offset": 0, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENDPOINT": { + "description": "Device endpoint to send data to. Only valid for HOST mode.", + "offset": 16, + "size": 4 + }, + "ADDRESS": { + "description": "In device mode, the address that the device should respond to. Set in response to a SET_ADDR setup packet from the host. In host mode set to the address of the device to communicate with.", + "offset": 0, + "size": 7 + } + } + } + }, + "ADDR_ENDP1": { + "description": "Interrupt endpoint 1. Only valid for HOST mode.", + "offset": 4, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INTEP_PREAMBLE": { + "description": "Interrupt EP requires preamble (is a low speed device on a full speed hub)", + "offset": 26, + "size": 1 + }, + "INTEP_DIR": { + "description": "Direction of the interrupt endpoint. In=0, Out=1", + "offset": 25, + "size": 1 + }, + "ENDPOINT": { + "description": "Endpoint number of the interrupt endpoint", + "offset": 16, + "size": 4 + }, + "ADDRESS": { + "description": "Device address", + "offset": 0, + "size": 7 + } + } + } + }, + "ADDR_ENDP2": { + "description": "Interrupt endpoint 2. Only valid for HOST mode.", + "offset": 8, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INTEP_PREAMBLE": { + "description": "Interrupt EP requires preamble (is a low speed device on a full speed hub)", + "offset": 26, + "size": 1 + }, + "INTEP_DIR": { + "description": "Direction of the interrupt endpoint. In=0, Out=1", + "offset": 25, + "size": 1 + }, + "ENDPOINT": { + "description": "Endpoint number of the interrupt endpoint", + "offset": 16, + "size": 4 + }, + "ADDRESS": { + "description": "Device address", + "offset": 0, + "size": 7 + } + } + } + }, + "ADDR_ENDP3": { + "description": "Interrupt endpoint 3. Only valid for HOST mode.", + "offset": 12, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INTEP_PREAMBLE": { + "description": "Interrupt EP requires preamble (is a low speed device on a full speed hub)", + "offset": 26, + "size": 1 + }, + "INTEP_DIR": { + "description": "Direction of the interrupt endpoint. In=0, Out=1", + "offset": 25, + "size": 1 + }, + "ENDPOINT": { + "description": "Endpoint number of the interrupt endpoint", + "offset": 16, + "size": 4 + }, + "ADDRESS": { + "description": "Device address", + "offset": 0, + "size": 7 + } + } + } + }, + "ADDR_ENDP4": { + "description": "Interrupt endpoint 4. Only valid for HOST mode.", + "offset": 16, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INTEP_PREAMBLE": { + "description": "Interrupt EP requires preamble (is a low speed device on a full speed hub)", + "offset": 26, + "size": 1 + }, + "INTEP_DIR": { + "description": "Direction of the interrupt endpoint. In=0, Out=1", + "offset": 25, + "size": 1 + }, + "ENDPOINT": { + "description": "Endpoint number of the interrupt endpoint", + "offset": 16, + "size": 4 + }, + "ADDRESS": { + "description": "Device address", + "offset": 0, + "size": 7 + } + } + } + }, + "ADDR_ENDP5": { + "description": "Interrupt endpoint 5. Only valid for HOST mode.", + "offset": 20, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INTEP_PREAMBLE": { + "description": "Interrupt EP requires preamble (is a low speed device on a full speed hub)", + "offset": 26, + "size": 1 + }, + "INTEP_DIR": { + "description": "Direction of the interrupt endpoint. In=0, Out=1", + "offset": 25, + "size": 1 + }, + "ENDPOINT": { + "description": "Endpoint number of the interrupt endpoint", + "offset": 16, + "size": 4 + }, + "ADDRESS": { + "description": "Device address", + "offset": 0, + "size": 7 + } + } + } + }, + "ADDR_ENDP6": { + "description": "Interrupt endpoint 6. Only valid for HOST mode.", + "offset": 24, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INTEP_PREAMBLE": { + "description": "Interrupt EP requires preamble (is a low speed device on a full speed hub)", + "offset": 26, + "size": 1 + }, + "INTEP_DIR": { + "description": "Direction of the interrupt endpoint. In=0, Out=1", + "offset": 25, + "size": 1 + }, + "ENDPOINT": { + "description": "Endpoint number of the interrupt endpoint", + "offset": 16, + "size": 4 + }, + "ADDRESS": { + "description": "Device address", + "offset": 0, + "size": 7 + } + } + } + }, + "ADDR_ENDP7": { + "description": "Interrupt endpoint 7. Only valid for HOST mode.", + "offset": 28, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INTEP_PREAMBLE": { + "description": "Interrupt EP requires preamble (is a low speed device on a full speed hub)", + "offset": 26, + "size": 1 + }, + "INTEP_DIR": { + "description": "Direction of the interrupt endpoint. In=0, Out=1", + "offset": 25, + "size": 1 + }, + "ENDPOINT": { + "description": "Endpoint number of the interrupt endpoint", + "offset": 16, + "size": 4 + }, + "ADDRESS": { + "description": "Device address", + "offset": 0, + "size": 7 + } + } + } + }, + "ADDR_ENDP8": { + "description": "Interrupt endpoint 8. Only valid for HOST mode.", + "offset": 32, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INTEP_PREAMBLE": { + "description": "Interrupt EP requires preamble (is a low speed device on a full speed hub)", + "offset": 26, + "size": 1 + }, + "INTEP_DIR": { + "description": "Direction of the interrupt endpoint. In=0, Out=1", + "offset": 25, + "size": 1 + }, + "ENDPOINT": { + "description": "Endpoint number of the interrupt endpoint", + "offset": 16, + "size": 4 + }, + "ADDRESS": { + "description": "Device address", + "offset": 0, + "size": 7 + } + } + } + }, + "ADDR_ENDP9": { + "description": "Interrupt endpoint 9. Only valid for HOST mode.", + "offset": 36, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INTEP_PREAMBLE": { + "description": "Interrupt EP requires preamble (is a low speed device on a full speed hub)", + "offset": 26, + "size": 1 + }, + "INTEP_DIR": { + "description": "Direction of the interrupt endpoint. In=0, Out=1", + "offset": 25, + "size": 1 + }, + "ENDPOINT": { + "description": "Endpoint number of the interrupt endpoint", + "offset": 16, + "size": 4 + }, + "ADDRESS": { + "description": "Device address", + "offset": 0, + "size": 7 + } + } + } + }, + "ADDR_ENDP10": { + "description": "Interrupt endpoint 10. Only valid for HOST mode.", + "offset": 40, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INTEP_PREAMBLE": { + "description": "Interrupt EP requires preamble (is a low speed device on a full speed hub)", + "offset": 26, + "size": 1 + }, + "INTEP_DIR": { + "description": "Direction of the interrupt endpoint. In=0, Out=1", + "offset": 25, + "size": 1 + }, + "ENDPOINT": { + "description": "Endpoint number of the interrupt endpoint", + "offset": 16, + "size": 4 + }, + "ADDRESS": { + "description": "Device address", + "offset": 0, + "size": 7 + } + } + } + }, + "ADDR_ENDP11": { + "description": "Interrupt endpoint 11. Only valid for HOST mode.", + "offset": 44, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INTEP_PREAMBLE": { + "description": "Interrupt EP requires preamble (is a low speed device on a full speed hub)", + "offset": 26, + "size": 1 + }, + "INTEP_DIR": { + "description": "Direction of the interrupt endpoint. In=0, Out=1", + "offset": 25, + "size": 1 + }, + "ENDPOINT": { + "description": "Endpoint number of the interrupt endpoint", + "offset": 16, + "size": 4 + }, + "ADDRESS": { + "description": "Device address", + "offset": 0, + "size": 7 + } + } + } + }, + "ADDR_ENDP12": { + "description": "Interrupt endpoint 12. Only valid for HOST mode.", + "offset": 48, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INTEP_PREAMBLE": { + "description": "Interrupt EP requires preamble (is a low speed device on a full speed hub)", + "offset": 26, + "size": 1 + }, + "INTEP_DIR": { + "description": "Direction of the interrupt endpoint. In=0, Out=1", + "offset": 25, + "size": 1 + }, + "ENDPOINT": { + "description": "Endpoint number of the interrupt endpoint", + "offset": 16, + "size": 4 + }, + "ADDRESS": { + "description": "Device address", + "offset": 0, + "size": 7 + } + } + } + }, + "ADDR_ENDP13": { + "description": "Interrupt endpoint 13. Only valid for HOST mode.", + "offset": 52, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INTEP_PREAMBLE": { + "description": "Interrupt EP requires preamble (is a low speed device on a full speed hub)", + "offset": 26, + "size": 1 + }, + "INTEP_DIR": { + "description": "Direction of the interrupt endpoint. In=0, Out=1", + "offset": 25, + "size": 1 + }, + "ENDPOINT": { + "description": "Endpoint number of the interrupt endpoint", + "offset": 16, + "size": 4 + }, + "ADDRESS": { + "description": "Device address", + "offset": 0, + "size": 7 + } + } + } + }, + "ADDR_ENDP14": { + "description": "Interrupt endpoint 14. Only valid for HOST mode.", + "offset": 56, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INTEP_PREAMBLE": { + "description": "Interrupt EP requires preamble (is a low speed device on a full speed hub)", + "offset": 26, + "size": 1 + }, + "INTEP_DIR": { + "description": "Direction of the interrupt endpoint. In=0, Out=1", + "offset": 25, + "size": 1 + }, + "ENDPOINT": { + "description": "Endpoint number of the interrupt endpoint", + "offset": 16, + "size": 4 + }, + "ADDRESS": { + "description": "Device address", + "offset": 0, + "size": 7 + } + } + } + }, + "ADDR_ENDP15": { + "description": "Interrupt endpoint 15. Only valid for HOST mode.", + "offset": 60, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INTEP_PREAMBLE": { + "description": "Interrupt EP requires preamble (is a low speed device on a full speed hub)", + "offset": 26, + "size": 1 + }, + "INTEP_DIR": { + "description": "Direction of the interrupt endpoint. In=0, Out=1", + "offset": 25, + "size": 1 + }, + "ENDPOINT": { + "description": "Endpoint number of the interrupt endpoint", + "offset": 16, + "size": 4 + }, + "ADDRESS": { + "description": "Device address", + "offset": 0, + "size": 7 + } + } + } + }, + "MAIN_CTRL": { + "description": "Main control register", + "offset": 64, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SIM_TIMING": { + "description": "Reduced timings for simulation", + "offset": 31, + "size": 1 + }, + "HOST_NDEVICE": { + "description": "Device mode = 0, Host mode = 1", + "offset": 1, + "size": 1 + }, + "CONTROLLER_EN": { + "description": "Enable controller", + "offset": 0, + "size": 1 + } + } + } + }, + "SOF_WR": { + "description": "Set the SOF (Start of Frame) frame number in the host controller. The SOF packet is sent every 1ms and the host will increment the frame number by 1 each time.", + "offset": 68, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "COUNT": { + "offset": 0, + "size": 11, + "access": "write-only" + } + } + } + }, + "SOF_RD": { + "description": "Read the last SOF (Start of Frame) frame number seen. In device mode the last SOF received from the host. In host mode the last SOF sent by the host.", + "offset": 72, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "COUNT": { + "offset": 0, + "size": 11, + "access": "read-only" + } + } + } + }, + "SIE_CTRL": { + "description": "SIE control register", + "offset": 76, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "EP0_INT_STALL": { + "description": "Device: Set bit in EP_STATUS_STALL_NAK when EP0 sends a STALL", + "offset": 31, + "size": 1 + }, + "EP0_DOUBLE_BUF": { + "description": "Device: EP0 single buffered = 0, double buffered = 1", + "offset": 30, + "size": 1 + }, + "EP0_INT_1BUF": { + "description": "Device: Set bit in BUFF_STATUS for every buffer completed on EP0", + "offset": 29, + "size": 1 + }, + "EP0_INT_2BUF": { + "description": "Device: Set bit in BUFF_STATUS for every 2 buffers completed on EP0", + "offset": 28, + "size": 1 + }, + "EP0_INT_NAK": { + "description": "Device: Set bit in EP_STATUS_STALL_NAK when EP0 sends a NAK", + "offset": 27, + "size": 1 + }, + "DIRECT_EN": { + "description": "Direct bus drive enable", + "offset": 26, + "size": 1 + }, + "DIRECT_DP": { + "description": "Direct control of DP", + "offset": 25, + "size": 1 + }, + "DIRECT_DM": { + "description": "Direct control of DM", + "offset": 24, + "size": 1 + }, + "TRANSCEIVER_PD": { + "description": "Power down bus transceiver", + "offset": 18, + "size": 1 + }, + "RPU_OPT": { + "description": "Device: Pull-up strength (0=1K2, 1=2k3)", + "offset": 17, + "size": 1 + }, + "PULLUP_EN": { + "description": "Device: Enable pull up resistor", + "offset": 16, + "size": 1 + }, + "PULLDOWN_EN": { + "description": "Host: Enable pull down resistors", + "offset": 15, + "size": 1 + }, + "RESET_BUS": { + "description": "Host: Reset bus", + "offset": 13, + "size": 1 + }, + "RESUME": { + "description": "Device: Remote wakeup. Device can initiate its own resume after suspend.", + "offset": 12, + "size": 1 + }, + "VBUS_EN": { + "description": "Host: Enable VBUS", + "offset": 11, + "size": 1 + }, + "KEEP_ALIVE_EN": { + "description": "Host: Enable keep alive packet (for low speed bus)", + "offset": 10, + "size": 1 + }, + "SOF_EN": { + "description": "Host: Enable SOF generation (for full speed bus)", + "offset": 9, + "size": 1 + }, + "SOF_SYNC": { + "description": "Host: Delay packet(s) until after SOF", + "offset": 8, + "size": 1 + }, + "PREAMBLE_EN": { + "description": "Host: Preable enable for LS device on FS hub", + "offset": 6, + "size": 1 + }, + "STOP_TRANS": { + "description": "Host: Stop transaction", + "offset": 4, + "size": 1 + }, + "RECEIVE_DATA": { + "description": "Host: Receive transaction (IN to host)", + "offset": 3, + "size": 1 + }, + "SEND_DATA": { + "description": "Host: Send transaction (OUT from host)", + "offset": 2, + "size": 1 + }, + "SEND_SETUP": { + "description": "Host: Send Setup packet", + "offset": 1, + "size": 1 + }, + "START_TRANS": { + "description": "Host: Start transaction", + "offset": 0, + "size": 1 + } + } + } + }, + "SIE_STATUS": { + "description": "SIE status register", + "offset": 80, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "DATA_SEQ_ERROR": { + "description": "Data Sequence Error.\\n\\n\n The device can raise a sequence error in the following conditions:\\n\\n\n * A SETUP packet is received followed by a DATA1 packet (data phase should always be DATA0) * An OUT packet is received from the host but doesn't match the data pid in the buffer control register read from DPSRAM\\n\\n\n The host can raise a data sequence error in the following conditions:\\n\\n\n * An IN packet from the device has the wrong data PID", + "offset": 31, + "size": 1 + }, + "ACK_REC": { + "description": "ACK received. Raised by both host and device.", + "offset": 30, + "size": 1 + }, + "STALL_REC": { + "description": "Host: STALL received", + "offset": 29, + "size": 1 + }, + "NAK_REC": { + "description": "Host: NAK received", + "offset": 28, + "size": 1 + }, + "RX_TIMEOUT": { + "description": "RX timeout is raised by both the host and device if an ACK is not received in the maximum time specified by the USB spec.", + "offset": 27, + "size": 1 + }, + "RX_OVERFLOW": { + "description": "RX overflow is raised by the Serial RX engine if the incoming data is too fast.", + "offset": 26, + "size": 1 + }, + "BIT_STUFF_ERROR": { + "description": "Bit Stuff Error. Raised by the Serial RX engine.", + "offset": 25, + "size": 1 + }, + "CRC_ERROR": { + "description": "CRC Error. Raised by the Serial RX engine.", + "offset": 24, + "size": 1 + }, + "BUS_RESET": { + "description": "Device: bus reset received", + "offset": 19, + "size": 1 + }, + "TRANS_COMPLETE": { + "description": "Transaction complete.\\n\\n\n Raised by device if:\\n\\n\n * An IN or OUT packet is sent with the `LAST_BUFF` bit set in the buffer control register\\n\\n\n Raised by host if:\\n\\n\n * A setup packet is sent when no data in or data out transaction follows * An IN packet is received and the `LAST_BUFF` bit is set in the buffer control register * An IN packet is received with zero length * An OUT packet is sent and the `LAST_BUFF` bit is set", + "offset": 18, + "size": 1 + }, + "SETUP_REC": { + "description": "Device: Setup packet received", + "offset": 17, + "size": 1 + }, + "CONNECTED": { + "description": "Device: connected", + "offset": 16, + "size": 1 + }, + "RESUME": { + "description": "Host: Device has initiated a remote resume. Device: host has initiated a resume.", + "offset": 11, + "size": 1 + }, + "VBUS_OVER_CURR": { + "description": "VBUS over current detected", + "offset": 10, + "size": 1, + "access": "read-only" + }, + "SPEED": { + "description": "Host: device speed. Disconnected = 00, LS = 01, FS = 10", + "offset": 8, + "size": 2 + }, + "SUSPENDED": { + "description": "Bus in suspended state. Valid for device and host. Host and device will go into suspend if neither Keep Alive / SOF frames are enabled.", + "offset": 4, + "size": 1 + }, + "LINE_STATE": { + "description": "USB bus line state", + "offset": 2, + "size": 2, + "access": "read-only" + }, + "VBUS_DETECTED": { + "description": "Device: VBUS Detected", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "INT_EP_CTRL": { + "description": "interrupt endpoint control register", + "offset": 84, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INT_EP_ACTIVE": { + "description": "Host: Enable interrupt endpoint 1 -> 15", + "offset": 1, + "size": 15 + } + } + } + }, + "BUFF_STATUS": { + "description": "Buffer status register. A bit set here indicates that a buffer has completed on the endpoint (if the buffer interrupt is enabled). It is possible for 2 buffers to be completed, so clearing the buffer status bit may instantly re set it on the next clock cycle.", + "offset": 88, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "EP15_OUT": { + "offset": 31, + "size": 1 + }, + "EP15_IN": { + "offset": 30, + "size": 1 + }, + "EP14_OUT": { + "offset": 29, + "size": 1 + }, + "EP14_IN": { + "offset": 28, + "size": 1 + }, + "EP13_OUT": { + "offset": 27, + "size": 1 + }, + "EP13_IN": { + "offset": 26, + "size": 1 + }, + "EP12_OUT": { + "offset": 25, + "size": 1 + }, + "EP12_IN": { + "offset": 24, + "size": 1 + }, + "EP11_OUT": { + "offset": 23, + "size": 1 + }, + "EP11_IN": { + "offset": 22, + "size": 1 + }, + "EP10_OUT": { + "offset": 21, + "size": 1 + }, + "EP10_IN": { + "offset": 20, + "size": 1 + }, + "EP9_OUT": { + "offset": 19, + "size": 1 + }, + "EP9_IN": { + "offset": 18, + "size": 1 + }, + "EP8_OUT": { + "offset": 17, + "size": 1 + }, + "EP8_IN": { + "offset": 16, + "size": 1 + }, + "EP7_OUT": { + "offset": 15, + "size": 1 + }, + "EP7_IN": { + "offset": 14, + "size": 1 + }, + "EP6_OUT": { + "offset": 13, + "size": 1 + }, + "EP6_IN": { + "offset": 12, + "size": 1 + }, + "EP5_OUT": { + "offset": 11, + "size": 1 + }, + "EP5_IN": { + "offset": 10, + "size": 1 + }, + "EP4_OUT": { + "offset": 9, + "size": 1 + }, + "EP4_IN": { + "offset": 8, + "size": 1 + }, + "EP3_OUT": { + "offset": 7, + "size": 1 + }, + "EP3_IN": { + "offset": 6, + "size": 1 + }, + "EP2_OUT": { + "offset": 5, + "size": 1 + }, + "EP2_IN": { + "offset": 4, + "size": 1 + }, + "EP1_OUT": { + "offset": 3, + "size": 1 + }, + "EP1_IN": { + "offset": 2, + "size": 1 + }, + "EP0_OUT": { + "offset": 1, + "size": 1 + }, + "EP0_IN": { + "offset": 0, + "size": 1 + } + } + } + }, + "BUFF_CPU_SHOULD_HANDLE": { + "description": "Which of the double buffers should be handled. Only valid if using an interrupt per buffer (i.e. not per 2 buffers). Not valid for host interrupt endpoint polling because they are only single buffered.", + "offset": 92, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "EP15_OUT": { + "offset": 31, + "size": 1, + "access": "read-only" + }, + "EP15_IN": { + "offset": 30, + "size": 1, + "access": "read-only" + }, + "EP14_OUT": { + "offset": 29, + "size": 1, + "access": "read-only" + }, + "EP14_IN": { + "offset": 28, + "size": 1, + "access": "read-only" + }, + "EP13_OUT": { + "offset": 27, + "size": 1, + "access": "read-only" + }, + "EP13_IN": { + "offset": 26, + "size": 1, + "access": "read-only" + }, + "EP12_OUT": { + "offset": 25, + "size": 1, + "access": "read-only" + }, + "EP12_IN": { + "offset": 24, + "size": 1, + "access": "read-only" + }, + "EP11_OUT": { + "offset": 23, + "size": 1, + "access": "read-only" + }, + "EP11_IN": { + "offset": 22, + "size": 1, + "access": "read-only" + }, + "EP10_OUT": { + "offset": 21, + "size": 1, + "access": "read-only" + }, + "EP10_IN": { + "offset": 20, + "size": 1, + "access": "read-only" + }, + "EP9_OUT": { + "offset": 19, + "size": 1, + "access": "read-only" + }, + "EP9_IN": { + "offset": 18, + "size": 1, + "access": "read-only" + }, + "EP8_OUT": { + "offset": 17, + "size": 1, + "access": "read-only" + }, + "EP8_IN": { + "offset": 16, + "size": 1, + "access": "read-only" + }, + "EP7_OUT": { + "offset": 15, + "size": 1, + "access": "read-only" + }, + "EP7_IN": { + "offset": 14, + "size": 1, + "access": "read-only" + }, + "EP6_OUT": { + "offset": 13, + "size": 1, + "access": "read-only" + }, + "EP6_IN": { + "offset": 12, + "size": 1, + "access": "read-only" + }, + "EP5_OUT": { + "offset": 11, + "size": 1, + "access": "read-only" + }, + "EP5_IN": { + "offset": 10, + "size": 1, + "access": "read-only" + }, + "EP4_OUT": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "EP4_IN": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "EP3_OUT": { + "offset": 7, + "size": 1, + "access": "read-only" + }, + "EP3_IN": { + "offset": 6, + "size": 1, + "access": "read-only" + }, + "EP2_OUT": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "EP2_IN": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "EP1_OUT": { + "offset": 3, + "size": 1, + "access": "read-only" + }, + "EP1_IN": { + "offset": 2, + "size": 1, + "access": "read-only" + }, + "EP0_OUT": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "EP0_IN": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "EP_ABORT": { + "description": "Device only: Can be set to ignore the buffer control register for this endpoint in case you would like to revoke a buffer. A NAK will be sent for every access to the endpoint until this bit is cleared. A corresponding bit in `EP_ABORT_DONE` is set when it is safe to modify the buffer control register.", + "offset": 96, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "EP15_OUT": { + "offset": 31, + "size": 1 + }, + "EP15_IN": { + "offset": 30, + "size": 1 + }, + "EP14_OUT": { + "offset": 29, + "size": 1 + }, + "EP14_IN": { + "offset": 28, + "size": 1 + }, + "EP13_OUT": { + "offset": 27, + "size": 1 + }, + "EP13_IN": { + "offset": 26, + "size": 1 + }, + "EP12_OUT": { + "offset": 25, + "size": 1 + }, + "EP12_IN": { + "offset": 24, + "size": 1 + }, + "EP11_OUT": { + "offset": 23, + "size": 1 + }, + "EP11_IN": { + "offset": 22, + "size": 1 + }, + "EP10_OUT": { + "offset": 21, + "size": 1 + }, + "EP10_IN": { + "offset": 20, + "size": 1 + }, + "EP9_OUT": { + "offset": 19, + "size": 1 + }, + "EP9_IN": { + "offset": 18, + "size": 1 + }, + "EP8_OUT": { + "offset": 17, + "size": 1 + }, + "EP8_IN": { + "offset": 16, + "size": 1 + }, + "EP7_OUT": { + "offset": 15, + "size": 1 + }, + "EP7_IN": { + "offset": 14, + "size": 1 + }, + "EP6_OUT": { + "offset": 13, + "size": 1 + }, + "EP6_IN": { + "offset": 12, + "size": 1 + }, + "EP5_OUT": { + "offset": 11, + "size": 1 + }, + "EP5_IN": { + "offset": 10, + "size": 1 + }, + "EP4_OUT": { + "offset": 9, + "size": 1 + }, + "EP4_IN": { + "offset": 8, + "size": 1 + }, + "EP3_OUT": { + "offset": 7, + "size": 1 + }, + "EP3_IN": { + "offset": 6, + "size": 1 + }, + "EP2_OUT": { + "offset": 5, + "size": 1 + }, + "EP2_IN": { + "offset": 4, + "size": 1 + }, + "EP1_OUT": { + "offset": 3, + "size": 1 + }, + "EP1_IN": { + "offset": 2, + "size": 1 + }, + "EP0_OUT": { + "offset": 1, + "size": 1 + }, + "EP0_IN": { + "offset": 0, + "size": 1 + } + } + } + }, + "EP_ABORT_DONE": { + "description": "Device only: Used in conjunction with `EP_ABORT`. Set once an endpoint is idle so the programmer knows it is safe to modify the buffer control register.", + "offset": 100, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "EP15_OUT": { + "offset": 31, + "size": 1 + }, + "EP15_IN": { + "offset": 30, + "size": 1 + }, + "EP14_OUT": { + "offset": 29, + "size": 1 + }, + "EP14_IN": { + "offset": 28, + "size": 1 + }, + "EP13_OUT": { + "offset": 27, + "size": 1 + }, + "EP13_IN": { + "offset": 26, + "size": 1 + }, + "EP12_OUT": { + "offset": 25, + "size": 1 + }, + "EP12_IN": { + "offset": 24, + "size": 1 + }, + "EP11_OUT": { + "offset": 23, + "size": 1 + }, + "EP11_IN": { + "offset": 22, + "size": 1 + }, + "EP10_OUT": { + "offset": 21, + "size": 1 + }, + "EP10_IN": { + "offset": 20, + "size": 1 + }, + "EP9_OUT": { + "offset": 19, + "size": 1 + }, + "EP9_IN": { + "offset": 18, + "size": 1 + }, + "EP8_OUT": { + "offset": 17, + "size": 1 + }, + "EP8_IN": { + "offset": 16, + "size": 1 + }, + "EP7_OUT": { + "offset": 15, + "size": 1 + }, + "EP7_IN": { + "offset": 14, + "size": 1 + }, + "EP6_OUT": { + "offset": 13, + "size": 1 + }, + "EP6_IN": { + "offset": 12, + "size": 1 + }, + "EP5_OUT": { + "offset": 11, + "size": 1 + }, + "EP5_IN": { + "offset": 10, + "size": 1 + }, + "EP4_OUT": { + "offset": 9, + "size": 1 + }, + "EP4_IN": { + "offset": 8, + "size": 1 + }, + "EP3_OUT": { + "offset": 7, + "size": 1 + }, + "EP3_IN": { + "offset": 6, + "size": 1 + }, + "EP2_OUT": { + "offset": 5, + "size": 1 + }, + "EP2_IN": { + "offset": 4, + "size": 1 + }, + "EP1_OUT": { + "offset": 3, + "size": 1 + }, + "EP1_IN": { + "offset": 2, + "size": 1 + }, + "EP0_OUT": { + "offset": 1, + "size": 1 + }, + "EP0_IN": { + "offset": 0, + "size": 1 + } + } + } + }, + "EP_STALL_ARM": { + "description": "Device: this bit must be set in conjunction with the `STALL` bit in the buffer control register to send a STALL on EP0. The device controller clears these bits when a SETUP packet is received because the USB spec requires that a STALL condition is cleared when a SETUP packet is received.", + "offset": 104, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "EP0_OUT": { + "offset": 1, + "size": 1 + }, + "EP0_IN": { + "offset": 0, + "size": 1 + } + } + } + }, + "NAK_POLL": { + "description": "Used by the host controller. Sets the wait time in microseconds before trying again if the device replies with a NAK.", + "offset": 108, + "size": 32, + "reset_value": 1048592, + "children": { + "fields": { + "DELAY_FS": { + "description": "NAK polling interval for a full speed device", + "offset": 16, + "size": 10 + }, + "DELAY_LS": { + "description": "NAK polling interval for a low speed device", + "offset": 0, + "size": 10 + } + } + } + }, + "EP_STATUS_STALL_NAK": { + "description": "Device: bits are set when the `IRQ_ON_NAK` or `IRQ_ON_STALL` bits are set. For EP0 this comes from `SIE_CTRL`. For all other endpoints it comes from the endpoint control register.", + "offset": 112, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "EP15_OUT": { + "offset": 31, + "size": 1 + }, + "EP15_IN": { + "offset": 30, + "size": 1 + }, + "EP14_OUT": { + "offset": 29, + "size": 1 + }, + "EP14_IN": { + "offset": 28, + "size": 1 + }, + "EP13_OUT": { + "offset": 27, + "size": 1 + }, + "EP13_IN": { + "offset": 26, + "size": 1 + }, + "EP12_OUT": { + "offset": 25, + "size": 1 + }, + "EP12_IN": { + "offset": 24, + "size": 1 + }, + "EP11_OUT": { + "offset": 23, + "size": 1 + }, + "EP11_IN": { + "offset": 22, + "size": 1 + }, + "EP10_OUT": { + "offset": 21, + "size": 1 + }, + "EP10_IN": { + "offset": 20, + "size": 1 + }, + "EP9_OUT": { + "offset": 19, + "size": 1 + }, + "EP9_IN": { + "offset": 18, + "size": 1 + }, + "EP8_OUT": { + "offset": 17, + "size": 1 + }, + "EP8_IN": { + "offset": 16, + "size": 1 + }, + "EP7_OUT": { + "offset": 15, + "size": 1 + }, + "EP7_IN": { + "offset": 14, + "size": 1 + }, + "EP6_OUT": { + "offset": 13, + "size": 1 + }, + "EP6_IN": { + "offset": 12, + "size": 1 + }, + "EP5_OUT": { + "offset": 11, + "size": 1 + }, + "EP5_IN": { + "offset": 10, + "size": 1 + }, + "EP4_OUT": { + "offset": 9, + "size": 1 + }, + "EP4_IN": { + "offset": 8, + "size": 1 + }, + "EP3_OUT": { + "offset": 7, + "size": 1 + }, + "EP3_IN": { + "offset": 6, + "size": 1 + }, + "EP2_OUT": { + "offset": 5, + "size": 1 + }, + "EP2_IN": { + "offset": 4, + "size": 1 + }, + "EP1_OUT": { + "offset": 3, + "size": 1 + }, + "EP1_IN": { + "offset": 2, + "size": 1 + }, + "EP0_OUT": { + "offset": 1, + "size": 1 + }, + "EP0_IN": { + "offset": 0, + "size": 1 + } + } + } + }, + "USB_MUXING": { + "description": "Where to connect the USB controller. Should be to_phy by default.", + "offset": 116, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SOFTCON": { + "offset": 3, + "size": 1 + }, + "TO_DIGITAL_PAD": { + "offset": 2, + "size": 1 + }, + "TO_EXTPHY": { + "offset": 1, + "size": 1 + }, + "TO_PHY": { + "offset": 0, + "size": 1 + } + } + } + }, + "USB_PWR": { + "description": "Overrides for the power signals in the event that the VBUS signals are not hooked up to GPIO. Set the value of the override and then the override enable to switch over to the override value.", + "offset": 120, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "OVERCURR_DETECT_EN": { + "offset": 5, + "size": 1 + }, + "OVERCURR_DETECT": { + "offset": 4, + "size": 1 + }, + "VBUS_DETECT_OVERRIDE_EN": { + "offset": 3, + "size": 1 + }, + "VBUS_DETECT": { + "offset": 2, + "size": 1 + }, + "VBUS_EN_OVERRIDE_EN": { + "offset": 1, + "size": 1 + }, + "VBUS_EN": { + "offset": 0, + "size": 1 + } + } + } + }, + "USBPHY_DIRECT": { + "description": "This register allows for direct control of the USB phy. Use in conjunction with usbphy_direct_override register to enable each override bit.", + "offset": 124, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "DM_OVV": { + "description": "DM over voltage", + "offset": 22, + "size": 1, + "access": "read-only" + }, + "DP_OVV": { + "description": "DP over voltage", + "offset": 21, + "size": 1, + "access": "read-only" + }, + "DM_OVCN": { + "description": "DM overcurrent", + "offset": 20, + "size": 1, + "access": "read-only" + }, + "DP_OVCN": { + "description": "DP overcurrent", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "RX_DM": { + "description": "DPM pin state", + "offset": 18, + "size": 1, + "access": "read-only" + }, + "RX_DP": { + "description": "DPP pin state", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "RX_DD": { + "description": "Differential RX", + "offset": 16, + "size": 1, + "access": "read-only" + }, + "TX_DIFFMODE": { + "description": "TX_DIFFMODE=0: Single ended mode\\n\n TX_DIFFMODE=1: Differential drive mode (TX_DM, TX_DM_OE ignored)", + "offset": 15, + "size": 1 + }, + "TX_FSSLEW": { + "description": "TX_FSSLEW=0: Low speed slew rate\\n\n TX_FSSLEW=1: Full speed slew rate", + "offset": 14, + "size": 1 + }, + "TX_PD": { + "description": "TX power down override (if override enable is set). 1 = powered down.", + "offset": 13, + "size": 1 + }, + "RX_PD": { + "description": "RX power down override (if override enable is set). 1 = powered down.", + "offset": 12, + "size": 1 + }, + "TX_DM": { + "description": "Output data. TX_DIFFMODE=1, Ignored\\n\n TX_DIFFMODE=0, Drives DPM only. TX_DM_OE=1 to enable drive. DPM=TX_DM", + "offset": 11, + "size": 1 + }, + "TX_DP": { + "description": "Output data. If TX_DIFFMODE=1, Drives DPP/DPM diff pair. TX_DP_OE=1 to enable drive. DPP=TX_DP, DPM=~TX_DP\\n\n If TX_DIFFMODE=0, Drives DPP only. TX_DP_OE=1 to enable drive. DPP=TX_DP", + "offset": 10, + "size": 1 + }, + "TX_DM_OE": { + "description": "Output enable. If TX_DIFFMODE=1, Ignored.\\n\n If TX_DIFFMODE=0, OE for DPM only. 0 - DPM in Hi-Z state; 1 - DPM driving", + "offset": 9, + "size": 1 + }, + "TX_DP_OE": { + "description": "Output enable. If TX_DIFFMODE=1, OE for DPP/DPM diff pair. 0 - DPP/DPM in Hi-Z state; 1 - DPP/DPM driving\\n\n If TX_DIFFMODE=0, OE for DPP only. 0 - DPP in Hi-Z state; 1 - DPP driving", + "offset": 8, + "size": 1 + }, + "DM_PULLDN_EN": { + "description": "DM pull down enable", + "offset": 6, + "size": 1 + }, + "DM_PULLUP_EN": { + "description": "DM pull up enable", + "offset": 5, + "size": 1 + }, + "DM_PULLUP_HISEL": { + "description": "Enable the second DM pull up resistor. 0 - Pull = Rpu2; 1 - Pull = Rpu1 + Rpu2", + "offset": 4, + "size": 1 + }, + "DP_PULLDN_EN": { + "description": "DP pull down enable", + "offset": 2, + "size": 1 + }, + "DP_PULLUP_EN": { + "description": "DP pull up enable", + "offset": 1, + "size": 1 + }, + "DP_PULLUP_HISEL": { + "description": "Enable the second DP pull up resistor. 0 - Pull = Rpu2; 1 - Pull = Rpu1 + Rpu2", + "offset": 0, + "size": 1 + } + } + } + }, + "USBPHY_DIRECT_OVERRIDE": { + "description": "Override enable for each control in usbphy_direct", + "offset": 128, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "TX_DIFFMODE_OVERRIDE_EN": { + "offset": 15, + "size": 1 + }, + "DM_PULLUP_OVERRIDE_EN": { + "offset": 12, + "size": 1 + }, + "TX_FSSLEW_OVERRIDE_EN": { + "offset": 11, + "size": 1 + }, + "TX_PD_OVERRIDE_EN": { + "offset": 10, + "size": 1 + }, + "RX_PD_OVERRIDE_EN": { + "offset": 9, + "size": 1 + }, + "TX_DM_OVERRIDE_EN": { + "offset": 8, + "size": 1 + }, + "TX_DP_OVERRIDE_EN": { + "offset": 7, + "size": 1 + }, + "TX_DM_OE_OVERRIDE_EN": { + "offset": 6, + "size": 1 + }, + "TX_DP_OE_OVERRIDE_EN": { + "offset": 5, + "size": 1 + }, + "DM_PULLDN_EN_OVERRIDE_EN": { + "offset": 4, + "size": 1 + }, + "DP_PULLDN_EN_OVERRIDE_EN": { + "offset": 3, + "size": 1 + }, + "DP_PULLUP_EN_OVERRIDE_EN": { + "offset": 2, + "size": 1 + }, + "DM_PULLUP_HISEL_OVERRIDE_EN": { + "offset": 1, + "size": 1 + }, + "DP_PULLUP_HISEL_OVERRIDE_EN": { + "offset": 0, + "size": 1 + } + } + } + }, + "USBPHY_TRIM": { + "description": "Used to adjust trim values of USB phy pull down resistors.", + "offset": 132, + "size": 32, + "reset_value": 7967, + "children": { + "fields": { + "DM_PULLDN_TRIM": { + "description": "Value to drive to USB PHY\\n\n DM pulldown resistor trim control\\n\n Experimental data suggests that the reset value will work, but this register allows adjustment if required", + "offset": 8, + "size": 5 + }, + "DP_PULLDN_TRIM": { + "description": "Value to drive to USB PHY\\n\n DP pulldown resistor trim control\\n\n Experimental data suggests that the reset value will work, but this register allows adjustment if required", + "offset": 0, + "size": 5 + } + } + } + }, + "INTR": { + "description": "Raw Interrupts", + "offset": 140, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "EP_STALL_NAK": { + "description": "Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK.", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "ABORT_DONE": { + "description": "Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE.", + "offset": 18, + "size": 1, + "access": "read-only" + }, + "DEV_SOF": { + "description": "Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "SETUP_REQ": { + "description": "Device. Source: SIE_STATUS.SETUP_REC", + "offset": 16, + "size": 1, + "access": "read-only" + }, + "DEV_RESUME_FROM_HOST": { + "description": "Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME", + "offset": 15, + "size": 1, + "access": "read-only" + }, + "DEV_SUSPEND": { + "description": "Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED", + "offset": 14, + "size": 1, + "access": "read-only" + }, + "DEV_CONN_DIS": { + "description": "Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "BUS_RESET": { + "description": "Source: SIE_STATUS.BUS_RESET", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "VBUS_DETECT": { + "description": "Source: SIE_STATUS.VBUS_DETECTED", + "offset": 11, + "size": 1, + "access": "read-only" + }, + "STALL": { + "description": "Source: SIE_STATUS.STALL_REC", + "offset": 10, + "size": 1, + "access": "read-only" + }, + "ERROR_CRC": { + "description": "Source: SIE_STATUS.CRC_ERROR", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "ERROR_BIT_STUFF": { + "description": "Source: SIE_STATUS.BIT_STUFF_ERROR", + "offset": 8, + "size": 1, + "access": "read-only" + }, + "ERROR_RX_OVERFLOW": { + "description": "Source: SIE_STATUS.RX_OVERFLOW", + "offset": 7, + "size": 1, + "access": "read-only" + }, + "ERROR_RX_TIMEOUT": { + "description": "Source: SIE_STATUS.RX_TIMEOUT", + "offset": 6, + "size": 1, + "access": "read-only" + }, + "ERROR_DATA_SEQ": { + "description": "Source: SIE_STATUS.DATA_SEQ_ERROR", + "offset": 5, + "size": 1, + "access": "read-only" + }, + "BUFF_STATUS": { + "description": "Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS.", + "offset": 4, + "size": 1, + "access": "read-only" + }, + "TRANS_COMPLETE": { + "description": "Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit.", + "offset": 3, + "size": 1, + "access": "read-only" + }, + "HOST_SOF": { + "description": "Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD", + "offset": 2, + "size": 1, + "access": "read-only" + }, + "HOST_RESUME": { + "description": "Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME", + "offset": 1, + "size": 1, + "access": "read-only" + }, + "HOST_CONN_DIS": { + "description": "Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "INTE": { + "description": "Interrupt Enable", + "offset": 144, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "EP_STALL_NAK": { + "description": "Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK.", + "offset": 19, + "size": 1 + }, + "ABORT_DONE": { + "description": "Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE.", + "offset": 18, + "size": 1 + }, + "DEV_SOF": { + "description": "Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD", + "offset": 17, + "size": 1 + }, + "SETUP_REQ": { + "description": "Device. Source: SIE_STATUS.SETUP_REC", + "offset": 16, + "size": 1 + }, + "DEV_RESUME_FROM_HOST": { + "description": "Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME", + "offset": 15, + "size": 1 + }, + "DEV_SUSPEND": { + "description": "Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED", + "offset": 14, + "size": 1 + }, + "DEV_CONN_DIS": { + "description": "Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED", + "offset": 13, + "size": 1 + }, + "BUS_RESET": { + "description": "Source: SIE_STATUS.BUS_RESET", + "offset": 12, + "size": 1 + }, + "VBUS_DETECT": { + "description": "Source: SIE_STATUS.VBUS_DETECTED", + "offset": 11, + "size": 1 + }, + "STALL": { + "description": "Source: SIE_STATUS.STALL_REC", + "offset": 10, + "size": 1 + }, + "ERROR_CRC": { + "description": "Source: SIE_STATUS.CRC_ERROR", + "offset": 9, + "size": 1 + }, + "ERROR_BIT_STUFF": { + "description": "Source: SIE_STATUS.BIT_STUFF_ERROR", + "offset": 8, + "size": 1 + }, + "ERROR_RX_OVERFLOW": { + "description": "Source: SIE_STATUS.RX_OVERFLOW", + "offset": 7, + "size": 1 + }, + "ERROR_RX_TIMEOUT": { + "description": "Source: SIE_STATUS.RX_TIMEOUT", + "offset": 6, + "size": 1 + }, + "ERROR_DATA_SEQ": { + "description": "Source: SIE_STATUS.DATA_SEQ_ERROR", + "offset": 5, + "size": 1 + }, + "BUFF_STATUS": { + "description": "Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS.", + "offset": 4, + "size": 1 + }, + "TRANS_COMPLETE": { + "description": "Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit.", + "offset": 3, + "size": 1 + }, + "HOST_SOF": { + "description": "Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD", + "offset": 2, + "size": 1 + }, + "HOST_RESUME": { + "description": "Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME", + "offset": 1, + "size": 1 + }, + "HOST_CONN_DIS": { + "description": "Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED", + "offset": 0, + "size": 1 + } + } + } + }, + "INTF": { + "description": "Interrupt Force", + "offset": 148, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "EP_STALL_NAK": { + "description": "Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK.", + "offset": 19, + "size": 1 + }, + "ABORT_DONE": { + "description": "Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE.", + "offset": 18, + "size": 1 + }, + "DEV_SOF": { + "description": "Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD", + "offset": 17, + "size": 1 + }, + "SETUP_REQ": { + "description": "Device. Source: SIE_STATUS.SETUP_REC", + "offset": 16, + "size": 1 + }, + "DEV_RESUME_FROM_HOST": { + "description": "Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME", + "offset": 15, + "size": 1 + }, + "DEV_SUSPEND": { + "description": "Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED", + "offset": 14, + "size": 1 + }, + "DEV_CONN_DIS": { + "description": "Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED", + "offset": 13, + "size": 1 + }, + "BUS_RESET": { + "description": "Source: SIE_STATUS.BUS_RESET", + "offset": 12, + "size": 1 + }, + "VBUS_DETECT": { + "description": "Source: SIE_STATUS.VBUS_DETECTED", + "offset": 11, + "size": 1 + }, + "STALL": { + "description": "Source: SIE_STATUS.STALL_REC", + "offset": 10, + "size": 1 + }, + "ERROR_CRC": { + "description": "Source: SIE_STATUS.CRC_ERROR", + "offset": 9, + "size": 1 + }, + "ERROR_BIT_STUFF": { + "description": "Source: SIE_STATUS.BIT_STUFF_ERROR", + "offset": 8, + "size": 1 + }, + "ERROR_RX_OVERFLOW": { + "description": "Source: SIE_STATUS.RX_OVERFLOW", + "offset": 7, + "size": 1 + }, + "ERROR_RX_TIMEOUT": { + "description": "Source: SIE_STATUS.RX_TIMEOUT", + "offset": 6, + "size": 1 + }, + "ERROR_DATA_SEQ": { + "description": "Source: SIE_STATUS.DATA_SEQ_ERROR", + "offset": 5, + "size": 1 + }, + "BUFF_STATUS": { + "description": "Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS.", + "offset": 4, + "size": 1 + }, + "TRANS_COMPLETE": { + "description": "Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit.", + "offset": 3, + "size": 1 + }, + "HOST_SOF": { + "description": "Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD", + "offset": 2, + "size": 1 + }, + "HOST_RESUME": { + "description": "Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME", + "offset": 1, + "size": 1 + }, + "HOST_CONN_DIS": { + "description": "Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED", + "offset": 0, + "size": 1 + } + } + } + }, + "INTS": { + "description": "Interrupt status after masking & forcing", + "offset": 152, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "EP_STALL_NAK": { + "description": "Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK.", + "offset": 19, + "size": 1, + "access": "read-only" + }, + "ABORT_DONE": { + "description": "Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE.", + "offset": 18, + "size": 1, + "access": "read-only" + }, + "DEV_SOF": { + "description": "Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD", + "offset": 17, + "size": 1, + "access": "read-only" + }, + "SETUP_REQ": { + "description": "Device. Source: SIE_STATUS.SETUP_REC", + "offset": 16, + "size": 1, + "access": "read-only" + }, + "DEV_RESUME_FROM_HOST": { + "description": "Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME", + "offset": 15, + "size": 1, + "access": "read-only" + }, + "DEV_SUSPEND": { + "description": "Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED", + "offset": 14, + "size": 1, + "access": "read-only" + }, + "DEV_CONN_DIS": { + "description": "Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED", + "offset": 13, + "size": 1, + "access": "read-only" + }, + "BUS_RESET": { + "description": "Source: SIE_STATUS.BUS_RESET", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "VBUS_DETECT": { + "description": "Source: SIE_STATUS.VBUS_DETECTED", + "offset": 11, + "size": 1, + "access": "read-only" + }, + "STALL": { + "description": "Source: SIE_STATUS.STALL_REC", + "offset": 10, + "size": 1, + "access": "read-only" + }, + "ERROR_CRC": { + "description": "Source: SIE_STATUS.CRC_ERROR", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "ERROR_BIT_STUFF": { + "description": "Source: SIE_STATUS.BIT_STUFF_ERROR", + "offset": 8, + "size": 1, + "access": "read-only" + }, + "ERROR_RX_OVERFLOW": { + "description": "Source: SIE_STATUS.RX_OVERFLOW", + "offset": 7, + "size": 1, + "access": "read-only" + }, + "ERROR_RX_TIMEOUT": { + "description": "Source: SIE_STATUS.RX_TIMEOUT", + "offset": 6, + "size": 1, + "access": "read-only" + }, + "ERROR_DATA_SEQ": { + "description": "Source: SIE_STATUS.DATA_SEQ_ERROR", + "offset": 5, + "size": 1, + "access": "read-only" + }, + "BUFF_STATUS": { + "description": "Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS.", + "offset": 4, + "size": 1, + "access": "read-only" + }, + "TRANS_COMPLETE": { + "description": "Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit.", + "offset": 3, + "size": 1, + "access": "read-only" + }, + "HOST_SOF": { + "description": "Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD", + "offset": 2, + "size": 1, + "access": "read-only" + }, + "HOST_RESUME": { + "description": "Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME", + "offset": 1, + "size": 1, + "access": "read-only" + }, + "HOST_CONN_DIS": { + "description": "Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + } + } + } + }, + "I2C0": { + "description": "DW_apb_i2c address block\\n\\n\n List of configuration constants for the Synopsys I2C hardware (you may see references to these in I2C register header; these are *fixed* values, set at hardware design time):\\n\\n\n IC_ULTRA_FAST_MODE ................ 0x0\\n\n IC_UFM_TBUF_CNT_DEFAULT ........... 0x8\\n\n IC_UFM_SCL_LOW_COUNT .............. 0x0008\\n\n IC_UFM_SCL_HIGH_COUNT ............. 0x0006\\n\n IC_TX_TL .......................... 0x0\\n\n IC_TX_CMD_BLOCK ................... 0x1\\n\n IC_HAS_DMA ........................ 0x1\\n\n IC_HAS_ASYNC_FIFO ................. 0x0\\n\n IC_SMBUS_ARP ...................... 0x0\\n\n IC_FIRST_DATA_BYTE_STATUS ......... 0x1\\n\n IC_INTR_IO ........................ 0x1\\n\n IC_MASTER_MODE .................... 0x1\\n\n IC_DEFAULT_ACK_GENERAL_CALL ....... 0x1\\n\n IC_INTR_POL ....................... 0x1\\n\n IC_OPTIONAL_SAR ................... 0x0\\n\n IC_DEFAULT_TAR_SLAVE_ADDR ......... 0x055\\n\n IC_DEFAULT_SLAVE_ADDR ............. 0x055\\n\n IC_DEFAULT_HS_SPKLEN .............. 0x1\\n\n IC_FS_SCL_HIGH_COUNT .............. 0x0006\\n\n IC_HS_SCL_LOW_COUNT ............... 0x0008\\n\n IC_DEVICE_ID_VALUE ................ 0x0\\n\n IC_10BITADDR_MASTER ............... 0x0\\n\n IC_CLK_FREQ_OPTIMIZATION .......... 0x0\\n\n IC_DEFAULT_FS_SPKLEN .............. 0x7\\n\n IC_ADD_ENCODED_PARAMS ............. 0x0\\n\n IC_DEFAULT_SDA_HOLD ............... 0x000001\\n\n IC_DEFAULT_SDA_SETUP .............. 0x64\\n\n IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT . 0x0\\n\n IC_CLOCK_PERIOD ................... 100\\n\n IC_EMPTYFIFO_HOLD_MASTER_EN ....... 1\\n\n IC_RESTART_EN ..................... 0x1\\n\n IC_TX_CMD_BLOCK_DEFAULT ........... 0x0\\n\n IC_BUS_CLEAR_FEATURE .............. 0x0\\n\n IC_CAP_LOADING .................... 100\\n\n IC_FS_SCL_LOW_COUNT ............... 0x000d\\n\n APB_DATA_WIDTH .................... 32\\n\n IC_SDA_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff\\n\n IC_SLV_DATA_NACK_ONLY ............. 0x1\\n\n IC_10BITADDR_SLAVE ................ 0x0\\n\n IC_CLK_TYPE ....................... 0x0\\n\n IC_SMBUS_UDID_MSB ................. 0x0\\n\n IC_SMBUS_SUSPEND_ALERT ............ 0x0\\n\n IC_HS_SCL_HIGH_COUNT .............. 0x0006\\n\n IC_SLV_RESTART_DET_EN ............. 0x1\\n\n IC_SMBUS .......................... 0x0\\n\n IC_OPTIONAL_SAR_DEFAULT ........... 0x0\\n\n IC_PERSISTANT_SLV_ADDR_DEFAULT .... 0x0\\n\n IC_USE_COUNTS ..................... 0x0\\n\n IC_RX_BUFFER_DEPTH ................ 16\\n\n IC_SCL_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff\\n\n IC_RX_FULL_HLD_BUS_EN ............. 0x1\\n\n IC_SLAVE_DISABLE .................. 0x1\\n\n IC_RX_TL .......................... 0x0\\n\n IC_DEVICE_ID ...................... 0x0\\n\n IC_HC_COUNT_VALUES ................ 0x0\\n\n I2C_DYNAMIC_TAR_UPDATE ............ 0\\n\n IC_SMBUS_CLK_LOW_MEXT_DEFAULT ..... 0xffffffff\\n\n IC_SMBUS_CLK_LOW_SEXT_DEFAULT ..... 0xffffffff\\n\n IC_HS_MASTER_CODE ................. 0x1\\n\n IC_SMBUS_RST_IDLE_CNT_DEFAULT ..... 0xffff\\n\n IC_SMBUS_UDID_LSB_DEFAULT ......... 0xffffffff\\n\n IC_SS_SCL_HIGH_COUNT .............. 0x0028\\n\n IC_SS_SCL_LOW_COUNT ............... 0x002f\\n\n IC_MAX_SPEED_MODE ................. 0x2\\n\n IC_STAT_FOR_CLK_STRETCH ........... 0x0\\n\n IC_STOP_DET_IF_MASTER_ACTIVE ...... 0x0\\n\n IC_DEFAULT_UFM_SPKLEN ............. 0x1\\n\n IC_TX_BUFFER_DEPTH ................ 16", + "children": { + "registers": { + "IC_CON": { + "description": "I2C Control Register. This register can be written only when the DW_apb_i2c is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect.\\n\\n\n Read/Write Access: - bit 10 is read only. - bit 11 is read only - bit 16 is read only - bit 17 is read only - bits 18 and 19 are read only.", + "offset": 0, + "size": 32, + "reset_value": 101, + "children": { + "fields": { + "STOP_DET_IF_MASTER_ACTIVE": { + "description": "Master issues the STOP_DET interrupt irrespective of whether master is active or not", + "offset": 10, + "size": 1, + "access": "read-only" + }, + "RX_FIFO_FULL_HLD_CTRL": { + "description": "This bit controls whether DW_apb_i2c should hold the bus when the Rx FIFO is physically full to its RX_BUFFER_DEPTH, as described in the IC_RX_FULL_HLD_BUS_EN parameter.\\n\\n\n Reset value: 0x0.", + "offset": 9, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "DISABLED": { + "description": "Overflow when RX_FIFO is full", + "value": 0 + }, + "ENABLED": { + "description": "Hold bus when RX_FIFO is full", + "value": 1 + } + } + } + } + }, + "TX_EMPTY_CTRL": { + "description": "This bit controls the generation of the TX_EMPTY interrupt, as described in the IC_RAW_INTR_STAT register.\\n\\n\n Reset value: 0x0.", + "offset": 8, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "DISABLED": { + "description": "Default behaviour of TX_EMPTY interrupt", + "value": 0 + }, + "ENABLED": { + "description": "Controlled generation of TX_EMPTY interrupt", + "value": 1 + } + } + } + } + }, + "STOP_DET_IFADDRESSED": { + "description": "In slave mode: - 1'b1: issues the STOP_DET interrupt only when it is addressed. - 1'b0: issues the STOP_DET irrespective of whether it's addressed or not. Reset value: 0x0\\n\\n\n NOTE: During a general call address, this slave does not issue the STOP_DET interrupt if STOP_DET_IF_ADDRESSED = 1'b1, even if the slave responds to the general call address by generating ACK. The STOP_DET interrupt is generated only when the transmitted address matches the slave address (SAR).", + "offset": 7, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "DISABLED": { + "description": "slave issues STOP_DET intr always", + "value": 0 + }, + "ENABLED": { + "description": "slave issues STOP_DET intr only if addressed", + "value": 1 + } + } + } + } + }, + "IC_SLAVE_DISABLE": { + "description": "This bit controls whether I2C has its slave disabled, which means once the presetn signal is applied, then this bit is set and the slave is disabled.\\n\\n\n If this bit is set (slave is disabled), DW_apb_i2c functions only as a master and does not perform any action that requires a slave.\\n\\n\n NOTE: Software should ensure that if this bit is written with 0, then bit 0 should also be written with a 0.", + "offset": 6, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "SLAVE_ENABLED": { + "description": "Slave mode is enabled", + "value": 0 + }, + "SLAVE_DISABLED": { + "description": "Slave mode is disabled", + "value": 1 + } + } + } + } + }, + "IC_RESTART_EN": { + "description": "Determines whether RESTART conditions may be sent when acting as a master. Some older slaves do not support handling RESTART conditions; however, RESTART conditions are used in several DW_apb_i2c operations. When RESTART is disabled, the master is prohibited from performing the following functions: - Sending a START BYTE - Performing any high-speed mode operation - High-speed mode operation - Performing direction changes in combined format mode - Performing a read operation with a 10-bit address By replacing RESTART condition followed by a STOP and a subsequent START condition, split operations are broken down into multiple DW_apb_i2c transfers. If the above operations are performed, it will result in setting bit 6 (TX_ABRT) of the IC_RAW_INTR_STAT register.\\n\\n\n Reset value: ENABLED", + "offset": 5, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "DISABLED": { + "description": "Master restart disabled", + "value": 0 + }, + "ENABLED": { + "description": "Master restart enabled", + "value": 1 + } + } + } + } + }, + "IC_10BITADDR_MASTER": { + "description": "Controls whether the DW_apb_i2c starts its transfers in 7- or 10-bit addressing mode when acting as a master. - 0: 7-bit addressing - 1: 10-bit addressing", + "offset": 4, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ADDR_7BITS": { + "description": "Master 7Bit addressing mode", + "value": 0 + }, + "ADDR_10BITS": { + "description": "Master 10Bit addressing mode", + "value": 1 + } + } + } + } + }, + "IC_10BITADDR_SLAVE": { + "description": "When acting as a slave, this bit controls whether the DW_apb_i2c responds to 7- or 10-bit addresses. - 0: 7-bit addressing. The DW_apb_i2c ignores transactions that involve 10-bit addressing; for 7-bit addressing, only the lower 7 bits of the IC_SAR register are compared. - 1: 10-bit addressing. The DW_apb_i2c responds to only 10-bit addressing transfers that match the full 10 bits of the IC_SAR register.", + "offset": 3, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ADDR_7BITS": { + "description": "Slave 7Bit addressing", + "value": 0 + }, + "ADDR_10BITS": { + "description": "Slave 10Bit addressing", + "value": 1 + } + } + } + } + }, + "SPEED": { + "description": "These bits control at which speed the DW_apb_i2c operates; its setting is relevant only if one is operating the DW_apb_i2c in master mode. Hardware protects against illegal values being programmed by software. These bits must be programmed appropriately for slave mode also, as it is used to capture correct value of spike filter as per the speed mode.\\n\\n\n This register should be programmed only with a value in the range of 1 to IC_MAX_SPEED_MODE; otherwise, hardware updates this register with the value of IC_MAX_SPEED_MODE.\\n\\n\n 1: standard mode (100 kbit/s)\\n\\n\n 2: fast mode (<=400 kbit/s) or fast mode plus (<=1000Kbit/s)\\n\\n\n 3: high speed mode (3.4 Mbit/s)\\n\\n\n Note: This field is not applicable when IC_ULTRA_FAST_MODE=1", + "offset": 1, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "STANDARD": { + "description": "Standard Speed mode of operation", + "value": 1 + }, + "FAST": { + "description": "Fast or Fast Plus mode of operation", + "value": 2 + }, + "HIGH": { + "description": "High Speed mode of operation", + "value": 3 + } + } + } + } + }, + "MASTER_MODE": { + "description": "This bit controls whether the DW_apb_i2c master is enabled.\\n\\n\n NOTE: Software should ensure that if this bit is written with '1' then bit 6 should also be written with a '1'.", + "offset": 0, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "DISABLED": { + "description": "Master mode is disabled", + "value": 0 + }, + "ENABLED": { + "description": "Master mode is enabled", + "value": 1 + } + } + } + } + } + } + } + }, + "IC_TAR": { + "description": "I2C Target Address Register\\n\\n\n This register is 12 bits wide, and bits 31:12 are reserved. This register can be written to only when IC_ENABLE[0] is set to 0.\\n\\n\n Note: If the software or application is aware that the DW_apb_i2c is not using the TAR address for the pending commands in the Tx FIFO, then it is possible to update the TAR address even while the Tx FIFO has entries (IC_STATUS[2]= 0). - It is not necessary to perform any write to this register if DW_apb_i2c is enabled as an I2C slave only.", + "offset": 4, + "size": 32, + "reset_value": 85, + "children": { + "fields": { + "SPECIAL": { + "description": "This bit indicates whether software performs a Device-ID or General Call or START BYTE command. - 0: ignore bit 10 GC_OR_START and use IC_TAR normally - 1: perform special I2C command as specified in Device_ID or GC_OR_START bit Reset value: 0x0", + "offset": 11, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "DISABLED": { + "description": "Disables programming of GENERAL_CALL or START_BYTE transmission", + "value": 0 + }, + "ENABLED": { + "description": "Enables programming of GENERAL_CALL or START_BYTE transmission", + "value": 1 + } + } + } + } + }, + "GC_OR_START": { + "description": "If bit 11 (SPECIAL) is set to 1 and bit 13(Device-ID) is set to 0, then this bit indicates whether a General Call or START byte command is to be performed by the DW_apb_i2c. - 0: General Call Address - after issuing a General Call, only writes may be performed. Attempting to issue a read command results in setting bit 6 (TX_ABRT) of the IC_RAW_INTR_STAT register. The DW_apb_i2c remains in General Call mode until the SPECIAL bit value (bit 11) is cleared. - 1: START BYTE Reset value: 0x0", + "offset": 10, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "GENERAL_CALL": { + "description": "GENERAL_CALL byte transmission", + "value": 0 + }, + "START_BYTE": { + "description": "START byte transmission", + "value": 1 + } + } + } + } + }, + "IC_TAR": { + "description": "This is the target address for any master transaction. When transmitting a General Call, these bits are ignored. To generate a START BYTE, the CPU needs to write only once into these bits.\\n\\n\n If the IC_TAR and IC_SAR are the same, loopback exists but the FIFOs are shared between master and slave, so full loopback is not feasible. Only one direction loopback mode is supported (simplex), not duplex. A master cannot transmit to itself; it can transmit to only a slave.", + "offset": 0, + "size": 10 + } + } + } + }, + "IC_SAR": { + "description": "I2C Slave Address Register", + "offset": 8, + "size": 32, + "reset_value": 85, + "children": { + "fields": { + "IC_SAR": { + "description": "The IC_SAR holds the slave address when the I2C is operating as a slave. For 7-bit addressing, only IC_SAR[6:0] is used.\\n\\n\n This register can be written only when the I2C interface is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect.\\n\\n\n Note: The default values cannot be any of the reserved address locations: that is, 0x00 to 0x07, or 0x78 to 0x7f. The correct operation of the device is not guaranteed if you program the IC_SAR or IC_TAR to a reserved value. Refer to <> for a complete list of these reserved values.", + "offset": 0, + "size": 10 + } + } + } + }, + "IC_DATA_CMD": { + "description": "I2C Rx/Tx Data Buffer and Command Register; this is the register the CPU writes to when filling the TX FIFO and the CPU reads from when retrieving bytes from RX FIFO.\\n\\n\n The size of the register changes as follows:\\n\\n\n Write: - 11 bits when IC_EMPTYFIFO_HOLD_MASTER_EN=1 - 9 bits when IC_EMPTYFIFO_HOLD_MASTER_EN=0 Read: - 12 bits when IC_FIRST_DATA_BYTE_STATUS = 1 - 8 bits when IC_FIRST_DATA_BYTE_STATUS = 0 Note: In order for the DW_apb_i2c to continue acknowledging reads, a read command should be written for every byte that is to be received; otherwise the DW_apb_i2c will stop acknowledging.", + "offset": 16, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FIRST_DATA_BYTE": { + "description": "Indicates the first data byte received after the address phase for receive transfer in Master receiver or Slave receiver mode.\\n\\n\n Reset value : 0x0\\n\\n\n NOTE: In case of APB_DATA_WIDTH=8,\\n\\n\n 1. The user has to perform two APB Reads to IC_DATA_CMD in order to get status on 11 bit.\\n\\n\n 2. In order to read the 11 bit, the user has to perform the first data byte read [7:0] (offset 0x10) and then perform the second read [15:8] (offset 0x11) in order to know the status of 11 bit (whether the data received in previous read is a first data byte or not).\\n\\n\n 3. The 11th bit is an optional read field, user can ignore 2nd byte read [15:8] (offset 0x11) if not interested in FIRST_DATA_BYTE status.", + "offset": 11, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "Sequential data byte received", + "value": 0 + }, + "ACTIVE": { + "description": "Non sequential data byte received", + "value": 1 + } + } + } + } + }, + "RESTART": { + "description": "This bit controls whether a RESTART is issued before the byte is sent or received.\\n\\n\n 1 - If IC_RESTART_EN is 1, a RESTART is issued before the data is sent/received (according to the value of CMD), regardless of whether or not the transfer direction is changing from the previous command; if IC_RESTART_EN is 0, a STOP followed by a START is issued instead.\\n\\n\n 0 - If IC_RESTART_EN is 1, a RESTART is issued only if the transfer direction is changing from the previous command; if IC_RESTART_EN is 0, a STOP followed by a START is issued instead.\\n\\n\n Reset value: 0x0", + "offset": 10, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "DISABLE": { + "description": "Don't Issue RESTART before this command", + "value": 0 + }, + "ENABLE": { + "description": "Issue RESTART before this command", + "value": 1 + } + } + } + } + }, + "STOP": { + "description": "This bit controls whether a STOP is issued after the byte is sent or received.\\n\\n\n - 1 - STOP is issued after this byte, regardless of whether or not the Tx FIFO is empty. If the Tx FIFO is not empty, the master immediately tries to start a new transfer by issuing a START and arbitrating for the bus. - 0 - STOP is not issued after this byte, regardless of whether or not the Tx FIFO is empty. If the Tx FIFO is not empty, the master continues the current transfer by sending/receiving data bytes according to the value of the CMD bit. If the Tx FIFO is empty, the master holds the SCL line low and stalls the bus until a new command is available in the Tx FIFO. Reset value: 0x0", + "offset": 9, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "DISABLE": { + "description": "Don't Issue STOP after this command", + "value": 0 + }, + "ENABLE": { + "description": "Issue STOP after this command", + "value": 1 + } + } + } + } + }, + "CMD": { + "description": "This bit controls whether a read or a write is performed. This bit does not control the direction when the DW_apb_i2con acts as a slave. It controls only the direction when it acts as a master.\\n\\n\n When a command is entered in the TX FIFO, this bit distinguishes the write and read commands. In slave-receiver mode, this bit is a 'don't care' because writes to this register are not required. In slave-transmitter mode, a '0' indicates that the data in IC_DATA_CMD is to be transmitted.\\n\\n\n When programming this bit, you should remember the following: attempting to perform a read operation after a General Call command has been sent results in a TX_ABRT interrupt (bit 6 of the IC_RAW_INTR_STAT register), unless bit 11 (SPECIAL) in the IC_TAR register has been cleared. If a '1' is written to this bit after receiving a RD_REQ interrupt, then a TX_ABRT interrupt occurs.\\n\\n\n Reset value: 0x0", + "offset": 8, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "WRITE": { + "description": "Master Write Command", + "value": 0 + }, + "READ": { + "description": "Master Read Command", + "value": 1 + } + } + } + } + }, + "DAT": { + "description": "This register contains the data to be transmitted or received on the I2C bus. If you are writing to this register and want to perform a read, bits 7:0 (DAT) are ignored by the DW_apb_i2c. However, when you read this register, these bits return the value of data received on the DW_apb_i2c interface.\\n\\n\n Reset value: 0x0", + "offset": 0, + "size": 8 + } + } + } + }, + "IC_SS_SCL_HCNT": { + "description": "Standard Speed I2C Clock SCL High Count Register", + "offset": 20, + "size": 32, + "reset_value": 40, + "children": { + "fields": { + "IC_SS_SCL_HCNT": { + "description": "This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock high-period count for standard speed. For more information, refer to 'IC_CLK Frequency Configuration'.\\n\\n\n This register can be written only when the I2C interface is disabled which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect.\\n\\n\n The minimum valid value is 6; hardware prevents values less than this being written, and if attempted results in 6 being set. For designs with APB_DATA_WIDTH = 8, the order of programming is important to ensure the correct operation of the DW_apb_i2c. The lower byte must be programmed first. Then the upper byte is programmed.\\n\\n\n NOTE: This register must not be programmed to a value higher than 65525, because DW_apb_i2c uses a 16-bit counter to flag an I2C bus idle condition when this counter reaches a value of IC_SS_SCL_HCNT + 10.", + "offset": 0, + "size": 16 + } + } + } + }, + "IC_SS_SCL_LCNT": { + "description": "Standard Speed I2C Clock SCL Low Count Register", + "offset": 24, + "size": 32, + "reset_value": 47, + "children": { + "fields": { + "IC_SS_SCL_LCNT": { + "description": "This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock low period count for standard speed. For more information, refer to 'IC_CLK Frequency Configuration'\\n\\n\n This register can be written only when the I2C interface is disabled which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect.\\n\\n\n The minimum valid value is 8; hardware prevents values less than this being written, and if attempted, results in 8 being set. For designs with APB_DATA_WIDTH = 8, the order of programming is important to ensure the correct operation of DW_apb_i2c. The lower byte must be programmed first, and then the upper byte is programmed.", + "offset": 0, + "size": 16 + } + } + } + }, + "IC_FS_SCL_HCNT": { + "description": "Fast Mode or Fast Mode Plus I2C Clock SCL High Count Register", + "offset": 28, + "size": 32, + "reset_value": 6, + "children": { + "fields": { + "IC_FS_SCL_HCNT": { + "description": "This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock high-period count for fast mode or fast mode plus. It is used in high-speed mode to send the Master Code and START BYTE or General CALL. For more information, refer to 'IC_CLK Frequency Configuration'.\\n\\n\n This register goes away and becomes read-only returning 0s if IC_MAX_SPEED_MODE = standard. This register can be written only when the I2C interface is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect.\\n\\n\n The minimum valid value is 6; hardware prevents values less than this being written, and if attempted results in 6 being set. For designs with APB_DATA_WIDTH == 8 the order of programming is important to ensure the correct operation of the DW_apb_i2c. The lower byte must be programmed first. Then the upper byte is programmed.", + "offset": 0, + "size": 16 + } + } + } + }, + "IC_FS_SCL_LCNT": { + "description": "Fast Mode or Fast Mode Plus I2C Clock SCL Low Count Register", + "offset": 32, + "size": 32, + "reset_value": 13, + "children": { + "fields": { + "IC_FS_SCL_LCNT": { + "description": "This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock low period count for fast speed. It is used in high-speed mode to send the Master Code and START BYTE or General CALL. For more information, refer to 'IC_CLK Frequency Configuration'.\\n\\n\n This register goes away and becomes read-only returning 0s if IC_MAX_SPEED_MODE = standard.\\n\\n\n This register can be written only when the I2C interface is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect.\\n\\n\n The minimum valid value is 8; hardware prevents values less than this being written, and if attempted results in 8 being set. For designs with APB_DATA_WIDTH = 8 the order of programming is important to ensure the correct operation of the DW_apb_i2c. The lower byte must be programmed first. Then the upper byte is programmed. If the value is less than 8 then the count value gets changed to 8.", + "offset": 0, + "size": 16 + } + } + } + }, + "IC_INTR_STAT": { + "description": "I2C Interrupt Status Register\\n\\n\n Each bit in this register has a corresponding mask bit in the IC_INTR_MASK register. These bits are cleared by reading the matching interrupt clear register. The unmasked raw versions of these bits are available in the IC_RAW_INTR_STAT register.", + "offset": 44, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "R_RESTART_DET": { + "description": "See IC_RAW_INTR_STAT for a detailed description of R_RESTART_DET bit.\\n\\n\n Reset value: 0x0", + "offset": 12, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "R_RESTART_DET interrupt is inactive", + "value": 0 + }, + "ACTIVE": { + "description": "R_RESTART_DET interrupt is active", + "value": 1 + } + } + } + } + }, + "R_GEN_CALL": { + "description": "See IC_RAW_INTR_STAT for a detailed description of R_GEN_CALL bit.\\n\\n\n Reset value: 0x0", + "offset": 11, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "R_GEN_CALL interrupt is inactive", + "value": 0 + }, + "ACTIVE": { + "description": "R_GEN_CALL interrupt is active", + "value": 1 + } + } + } + } + }, + "R_START_DET": { + "description": "See IC_RAW_INTR_STAT for a detailed description of R_START_DET bit.\\n\\n\n Reset value: 0x0", + "offset": 10, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "R_START_DET interrupt is inactive", + "value": 0 + }, + "ACTIVE": { + "description": "R_START_DET interrupt is active", + "value": 1 + } + } + } + } + }, + "R_STOP_DET": { + "description": "See IC_RAW_INTR_STAT for a detailed description of R_STOP_DET bit.\\n\\n\n Reset value: 0x0", + "offset": 9, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "R_STOP_DET interrupt is inactive", + "value": 0 + }, + "ACTIVE": { + "description": "R_STOP_DET interrupt is active", + "value": 1 + } + } + } + } + }, + "R_ACTIVITY": { + "description": "See IC_RAW_INTR_STAT for a detailed description of R_ACTIVITY bit.\\n\\n\n Reset value: 0x0", + "offset": 8, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "R_ACTIVITY interrupt is inactive", + "value": 0 + }, + "ACTIVE": { + "description": "R_ACTIVITY interrupt is active", + "value": 1 + } + } + } + } + }, + "R_RX_DONE": { + "description": "See IC_RAW_INTR_STAT for a detailed description of R_RX_DONE bit.\\n\\n\n Reset value: 0x0", + "offset": 7, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "R_RX_DONE interrupt is inactive", + "value": 0 + }, + "ACTIVE": { + "description": "R_RX_DONE interrupt is active", + "value": 1 + } + } + } + } + }, + "R_TX_ABRT": { + "description": "See IC_RAW_INTR_STAT for a detailed description of R_TX_ABRT bit.\\n\\n\n Reset value: 0x0", + "offset": 6, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "R_TX_ABRT interrupt is inactive", + "value": 0 + }, + "ACTIVE": { + "description": "R_TX_ABRT interrupt is active", + "value": 1 + } + } + } + } + }, + "R_RD_REQ": { + "description": "See IC_RAW_INTR_STAT for a detailed description of R_RD_REQ bit.\\n\\n\n Reset value: 0x0", + "offset": 5, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "R_RD_REQ interrupt is inactive", + "value": 0 + }, + "ACTIVE": { + "description": "R_RD_REQ interrupt is active", + "value": 1 + } + } + } + } + }, + "R_TX_EMPTY": { + "description": "See IC_RAW_INTR_STAT for a detailed description of R_TX_EMPTY bit.\\n\\n\n Reset value: 0x0", + "offset": 4, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "R_TX_EMPTY interrupt is inactive", + "value": 0 + }, + "ACTIVE": { + "description": "R_TX_EMPTY interrupt is active", + "value": 1 + } + } + } + } + }, + "R_TX_OVER": { + "description": "See IC_RAW_INTR_STAT for a detailed description of R_TX_OVER bit.\\n\\n\n Reset value: 0x0", + "offset": 3, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "R_TX_OVER interrupt is inactive", + "value": 0 + }, + "ACTIVE": { + "description": "R_TX_OVER interrupt is active", + "value": 1 + } + } + } + } + }, + "R_RX_FULL": { + "description": "See IC_RAW_INTR_STAT for a detailed description of R_RX_FULL bit.\\n\\n\n Reset value: 0x0", + "offset": 2, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "R_RX_FULL interrupt is inactive", + "value": 0 + }, + "ACTIVE": { + "description": "R_RX_FULL interrupt is active", + "value": 1 + } + } + } + } + }, + "R_RX_OVER": { + "description": "See IC_RAW_INTR_STAT for a detailed description of R_RX_OVER bit.\\n\\n\n Reset value: 0x0", + "offset": 1, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "R_RX_OVER interrupt is inactive", + "value": 0 + }, + "ACTIVE": { + "description": "R_RX_OVER interrupt is active", + "value": 1 + } + } + } + } + }, + "R_RX_UNDER": { + "description": "See IC_RAW_INTR_STAT for a detailed description of R_RX_UNDER bit.\\n\\n\n Reset value: 0x0", + "offset": 0, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "RX_UNDER interrupt is inactive", + "value": 0 + }, + "ACTIVE": { + "description": "RX_UNDER interrupt is active", + "value": 1 + } + } + } + } + } + } + } + }, + "IC_INTR_MASK": { + "description": "I2C Interrupt Mask Register.\\n\\n\n These bits mask their corresponding interrupt status bits. This register is active low; a value of 0 masks the interrupt, whereas a value of 1 unmasks the interrupt.", + "offset": 48, + "size": 32, + "reset_value": 2303, + "children": { + "fields": { + "M_RESTART_DET": { + "description": "This bit masks the R_RESTART_DET interrupt in IC_INTR_STAT register.\\n\\n\n Reset value: 0x0", + "offset": 12, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ENABLED": { + "description": "RESTART_DET interrupt is masked", + "value": 0 + }, + "DISABLED": { + "description": "RESTART_DET interrupt is unmasked", + "value": 1 + } + } + } + } + }, + "M_GEN_CALL": { + "description": "This bit masks the R_GEN_CALL interrupt in IC_INTR_STAT register.\\n\\n\n Reset value: 0x1", + "offset": 11, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ENABLED": { + "description": "GEN_CALL interrupt is masked", + "value": 0 + }, + "DISABLED": { + "description": "GEN_CALL interrupt is unmasked", + "value": 1 + } + } + } + } + }, + "M_START_DET": { + "description": "This bit masks the R_START_DET interrupt in IC_INTR_STAT register.\\n\\n\n Reset value: 0x0", + "offset": 10, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ENABLED": { + "description": "START_DET interrupt is masked", + "value": 0 + }, + "DISABLED": { + "description": "START_DET interrupt is unmasked", + "value": 1 + } + } + } + } + }, + "M_STOP_DET": { + "description": "This bit masks the R_STOP_DET interrupt in IC_INTR_STAT register.\\n\\n\n Reset value: 0x0", + "offset": 9, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ENABLED": { + "description": "STOP_DET interrupt is masked", + "value": 0 + }, + "DISABLED": { + "description": "STOP_DET interrupt is unmasked", + "value": 1 + } + } + } + } + }, + "M_ACTIVITY": { + "description": "This bit masks the R_ACTIVITY interrupt in IC_INTR_STAT register.\\n\\n\n Reset value: 0x0", + "offset": 8, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ENABLED": { + "description": "ACTIVITY interrupt is masked", + "value": 0 + }, + "DISABLED": { + "description": "ACTIVITY interrupt is unmasked", + "value": 1 + } + } + } + } + }, + "M_RX_DONE": { + "description": "This bit masks the R_RX_DONE interrupt in IC_INTR_STAT register.\\n\\n\n Reset value: 0x1", + "offset": 7, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ENABLED": { + "description": "RX_DONE interrupt is masked", + "value": 0 + }, + "DISABLED": { + "description": "RX_DONE interrupt is unmasked", + "value": 1 + } + } + } + } + }, + "M_TX_ABRT": { + "description": "This bit masks the R_TX_ABRT interrupt in IC_INTR_STAT register.\\n\\n\n Reset value: 0x1", + "offset": 6, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ENABLED": { + "description": "TX_ABORT interrupt is masked", + "value": 0 + }, + "DISABLED": { + "description": "TX_ABORT interrupt is unmasked", + "value": 1 + } + } + } + } + }, + "M_RD_REQ": { + "description": "This bit masks the R_RD_REQ interrupt in IC_INTR_STAT register.\\n\\n\n Reset value: 0x1", + "offset": 5, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ENABLED": { + "description": "RD_REQ interrupt is masked", + "value": 0 + }, + "DISABLED": { + "description": "RD_REQ interrupt is unmasked", + "value": 1 + } + } + } + } + }, + "M_TX_EMPTY": { + "description": "This bit masks the R_TX_EMPTY interrupt in IC_INTR_STAT register.\\n\\n\n Reset value: 0x1", + "offset": 4, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ENABLED": { + "description": "TX_EMPTY interrupt is masked", + "value": 0 + }, + "DISABLED": { + "description": "TX_EMPTY interrupt is unmasked", + "value": 1 + } + } + } + } + }, + "M_TX_OVER": { + "description": "This bit masks the R_TX_OVER interrupt in IC_INTR_STAT register.\\n\\n\n Reset value: 0x1", + "offset": 3, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ENABLED": { + "description": "TX_OVER interrupt is masked", + "value": 0 + }, + "DISABLED": { + "description": "TX_OVER interrupt is unmasked", + "value": 1 + } + } + } + } + }, + "M_RX_FULL": { + "description": "This bit masks the R_RX_FULL interrupt in IC_INTR_STAT register.\\n\\n\n Reset value: 0x1", + "offset": 2, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ENABLED": { + "description": "RX_FULL interrupt is masked", + "value": 0 + }, + "DISABLED": { + "description": "RX_FULL interrupt is unmasked", + "value": 1 + } + } + } + } + }, + "M_RX_OVER": { + "description": "This bit masks the R_RX_OVER interrupt in IC_INTR_STAT register.\\n\\n\n Reset value: 0x1", + "offset": 1, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ENABLED": { + "description": "RX_OVER interrupt is masked", + "value": 0 + }, + "DISABLED": { + "description": "RX_OVER interrupt is unmasked", + "value": 1 + } + } + } + } + }, + "M_RX_UNDER": { + "description": "This bit masks the R_RX_UNDER interrupt in IC_INTR_STAT register.\\n\\n\n Reset value: 0x1", + "offset": 0, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ENABLED": { + "description": "RX_UNDER interrupt is masked", + "value": 0 + }, + "DISABLED": { + "description": "RX_UNDER interrupt is unmasked", + "value": 1 + } + } + } + } + } + } + } + }, + "IC_RAW_INTR_STAT": { + "description": "I2C Raw Interrupt Status Register\\n\\n\n Unlike the IC_INTR_STAT register, these bits are not masked so they always show the true status of the DW_apb_i2c.", + "offset": 52, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "RESTART_DET": { + "description": "Indicates whether a RESTART condition has occurred on the I2C interface when DW_apb_i2c is operating in Slave mode and the slave is being addressed. Enabled only when IC_SLV_RESTART_DET_EN=1.\\n\\n\n Note: However, in high-speed mode or during a START BYTE transfer, the RESTART comes before the address field as per the I2C protocol. In this case, the slave is not the addressed slave when the RESTART is issued, therefore DW_apb_i2c does not generate the RESTART_DET interrupt.\\n\\n\n Reset value: 0x0", + "offset": 12, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "RESTART_DET interrupt is inactive", + "value": 0 + }, + "ACTIVE": { + "description": "RESTART_DET interrupt is active", + "value": 1 + } + } + } + } + }, + "GEN_CALL": { + "description": "Set only when a General Call address is received and it is acknowledged. It stays set until it is cleared either by disabling DW_apb_i2c or when the CPU reads bit 0 of the IC_CLR_GEN_CALL register. DW_apb_i2c stores the received data in the Rx buffer.\\n\\n\n Reset value: 0x0", + "offset": 11, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "GEN_CALL interrupt is inactive", + "value": 0 + }, + "ACTIVE": { + "description": "GEN_CALL interrupt is active", + "value": 1 + } + } + } + } + }, + "START_DET": { + "description": "Indicates whether a START or RESTART condition has occurred on the I2C interface regardless of whether DW_apb_i2c is operating in slave or master mode.\\n\\n\n Reset value: 0x0", + "offset": 10, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "START_DET interrupt is inactive", + "value": 0 + }, + "ACTIVE": { + "description": "START_DET interrupt is active", + "value": 1 + } + } + } + } + }, + "STOP_DET": { + "description": "Indicates whether a STOP condition has occurred on the I2C interface regardless of whether DW_apb_i2c is operating in slave or master mode.\\n\\n\n In Slave Mode: - If IC_CON[7]=1'b1 (STOP_DET_IFADDRESSED), the STOP_DET interrupt will be issued only if slave is addressed. Note: During a general call address, this slave does not issue a STOP_DET interrupt if STOP_DET_IF_ADDRESSED=1'b1, even if the slave responds to the general call address by generating ACK. The STOP_DET interrupt is generated only when the transmitted address matches the slave address (SAR). - If IC_CON[7]=1'b0 (STOP_DET_IFADDRESSED), the STOP_DET interrupt is issued irrespective of whether it is being addressed. In Master Mode: - If IC_CON[10]=1'b1 (STOP_DET_IF_MASTER_ACTIVE),the STOP_DET interrupt will be issued only if Master is active. - If IC_CON[10]=1'b0 (STOP_DET_IFADDRESSED),the STOP_DET interrupt will be issued irrespective of whether master is active or not. Reset value: 0x0", + "offset": 9, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "STOP_DET interrupt is inactive", + "value": 0 + }, + "ACTIVE": { + "description": "STOP_DET interrupt is active", + "value": 1 + } + } + } + } + }, + "ACTIVITY": { + "description": "This bit captures DW_apb_i2c activity and stays set until it is cleared. There are four ways to clear it: - Disabling the DW_apb_i2c - Reading the IC_CLR_ACTIVITY register - Reading the IC_CLR_INTR register - System reset Once this bit is set, it stays set unless one of the four methods is used to clear it. Even if the DW_apb_i2c module is idle, this bit remains set until cleared, indicating that there was activity on the bus.\\n\\n\n Reset value: 0x0", + "offset": 8, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "RAW_INTR_ACTIVITY interrupt is inactive", + "value": 0 + }, + "ACTIVE": { + "description": "RAW_INTR_ACTIVITY interrupt is active", + "value": 1 + } + } + } + } + }, + "RX_DONE": { + "description": "When the DW_apb_i2c is acting as a slave-transmitter, this bit is set to 1 if the master does not acknowledge a transmitted byte. This occurs on the last byte of the transmission, indicating that the transmission is done.\\n\\n\n Reset value: 0x0", + "offset": 7, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "RX_DONE interrupt is inactive", + "value": 0 + }, + "ACTIVE": { + "description": "RX_DONE interrupt is active", + "value": 1 + } + } + } + } + }, + "TX_ABRT": { + "description": "This bit indicates if DW_apb_i2c, as an I2C transmitter, is unable to complete the intended actions on the contents of the transmit FIFO. This situation can occur both as an I2C master or an I2C slave, and is referred to as a 'transmit abort'. When this bit is set to 1, the IC_TX_ABRT_SOURCE register indicates the reason why the transmit abort takes places.\\n\\n\n Note: The DW_apb_i2c flushes/resets/empties the TX_FIFO and RX_FIFO whenever there is a transmit abort caused by any of the events tracked by the IC_TX_ABRT_SOURCE register. The FIFOs remains in this flushed state until the register IC_CLR_TX_ABRT is read. Once this read is performed, the Tx FIFO is then ready to accept more data bytes from the APB interface.\\n\\n\n Reset value: 0x0", + "offset": 6, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "TX_ABRT interrupt is inactive", + "value": 0 + }, + "ACTIVE": { + "description": "TX_ABRT interrupt is active", + "value": 1 + } + } + } + } + }, + "RD_REQ": { + "description": "This bit is set to 1 when DW_apb_i2c is acting as a slave and another I2C master is attempting to read data from DW_apb_i2c. The DW_apb_i2c holds the I2C bus in a wait state (SCL=0) until this interrupt is serviced, which means that the slave has been addressed by a remote master that is asking for data to be transferred. The processor must respond to this interrupt and then write the requested data to the IC_DATA_CMD register. This bit is set to 0 just after the processor reads the IC_CLR_RD_REQ register.\\n\\n\n Reset value: 0x0", + "offset": 5, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "RD_REQ interrupt is inactive", + "value": 0 + }, + "ACTIVE": { + "description": "RD_REQ interrupt is active", + "value": 1 + } + } + } + } + }, + "TX_EMPTY": { + "description": "The behavior of the TX_EMPTY interrupt status differs based on the TX_EMPTY_CTRL selection in the IC_CON register. - When TX_EMPTY_CTRL = 0: This bit is set to 1 when the transmit buffer is at or below the threshold value set in the IC_TX_TL register. - When TX_EMPTY_CTRL = 1: This bit is set to 1 when the transmit buffer is at or below the threshold value set in the IC_TX_TL register and the transmission of the address/data from the internal shift register for the most recently popped command is completed. It is automatically cleared by hardware when the buffer level goes above the threshold. When IC_ENABLE[0] is set to 0, the TX FIFO is flushed and held in reset. There the TX FIFO looks like it has no data within it, so this bit is set to 1, provided there is activity in the master or slave state machines. When there is no longer any activity, then with ic_en=0, this bit is set to 0.\\n\\n\n Reset value: 0x0.", + "offset": 4, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "TX_EMPTY interrupt is inactive", + "value": 0 + }, + "ACTIVE": { + "description": "TX_EMPTY interrupt is active", + "value": 1 + } + } + } + } + }, + "TX_OVER": { + "description": "Set during transmit if the transmit buffer is filled to IC_TX_BUFFER_DEPTH and the processor attempts to issue another I2C command by writing to the IC_DATA_CMD register. When the module is disabled, this bit keeps its level until the master or slave state machines go into idle, and when ic_en goes to 0, this interrupt is cleared.\\n\\n\n Reset value: 0x0", + "offset": 3, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "TX_OVER interrupt is inactive", + "value": 0 + }, + "ACTIVE": { + "description": "TX_OVER interrupt is active", + "value": 1 + } + } + } + } + }, + "RX_FULL": { + "description": "Set when the receive buffer reaches or goes above the RX_TL threshold in the IC_RX_TL register. It is automatically cleared by hardware when buffer level goes below the threshold. If the module is disabled (IC_ENABLE[0]=0), the RX FIFO is flushed and held in reset; therefore the RX FIFO is not full. So this bit is cleared once the IC_ENABLE bit 0 is programmed with a 0, regardless of the activity that continues.\\n\\n\n Reset value: 0x0", + "offset": 2, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "RX_FULL interrupt is inactive", + "value": 0 + }, + "ACTIVE": { + "description": "RX_FULL interrupt is active", + "value": 1 + } + } + } + } + }, + "RX_OVER": { + "description": "Set if the receive buffer is completely filled to IC_RX_BUFFER_DEPTH and an additional byte is received from an external I2C device. The DW_apb_i2c acknowledges this, but any data bytes received after the FIFO is full are lost. If the module is disabled (IC_ENABLE[0]=0), this bit keeps its level until the master or slave state machines go into idle, and when ic_en goes to 0, this interrupt is cleared.\\n\\n\n Note: If bit 9 of the IC_CON register (RX_FIFO_FULL_HLD_CTRL) is programmed to HIGH, then the RX_OVER interrupt never occurs, because the Rx FIFO never overflows.\\n\\n\n Reset value: 0x0", + "offset": 1, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "RX_OVER interrupt is inactive", + "value": 0 + }, + "ACTIVE": { + "description": "RX_OVER interrupt is active", + "value": 1 + } + } + } + } + }, + "RX_UNDER": { + "description": "Set if the processor attempts to read the receive buffer when it is empty by reading from the IC_DATA_CMD register. If the module is disabled (IC_ENABLE[0]=0), this bit keeps its level until the master or slave state machines go into idle, and when ic_en goes to 0, this interrupt is cleared.\\n\\n\n Reset value: 0x0", + "offset": 0, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "RX_UNDER interrupt is inactive", + "value": 0 + }, + "ACTIVE": { + "description": "RX_UNDER interrupt is active", + "value": 1 + } + } + } + } + } + } + } + }, + "IC_RX_TL": { + "description": "I2C Receive FIFO Threshold Register", + "offset": 56, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "RX_TL": { + "description": "Receive FIFO Threshold Level.\\n\\n\n Controls the level of entries (or above) that triggers the RX_FULL interrupt (bit 2 in IC_RAW_INTR_STAT register). The valid range is 0-255, with the additional restriction that hardware does not allow this value to be set to a value larger than the depth of the buffer. If an attempt is made to do that, the actual value set will be the maximum depth of the buffer. A value of 0 sets the threshold for 1 entry, and a value of 255 sets the threshold for 256 entries.", + "offset": 0, + "size": 8 + } + } + } + }, + "IC_TX_TL": { + "description": "I2C Transmit FIFO Threshold Register", + "offset": 60, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "TX_TL": { + "description": "Transmit FIFO Threshold Level.\\n\\n\n Controls the level of entries (or below) that trigger the TX_EMPTY interrupt (bit 4 in IC_RAW_INTR_STAT register). The valid range is 0-255, with the additional restriction that it may not be set to value larger than the depth of the buffer. If an attempt is made to do that, the actual value set will be the maximum depth of the buffer. A value of 0 sets the threshold for 0 entries, and a value of 255 sets the threshold for 255 entries.", + "offset": 0, + "size": 8 + } + } + } + }, + "IC_CLR_INTR": { + "description": "Clear Combined and Individual Interrupt Register", + "offset": 64, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CLR_INTR": { + "description": "Read this register to clear the combined interrupt, all individual interrupts, and the IC_TX_ABRT_SOURCE register. This bit does not clear hardware clearable interrupts but software clearable interrupts. Refer to Bit 9 of the IC_TX_ABRT_SOURCE register for an exception to clearing IC_TX_ABRT_SOURCE.\\n\\n\n Reset value: 0x0", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "IC_CLR_RX_UNDER": { + "description": "Clear RX_UNDER Interrupt Register", + "offset": 68, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CLR_RX_UNDER": { + "description": "Read this register to clear the RX_UNDER interrupt (bit 0) of the IC_RAW_INTR_STAT register.\\n\\n\n Reset value: 0x0", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "IC_CLR_RX_OVER": { + "description": "Clear RX_OVER Interrupt Register", + "offset": 72, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CLR_RX_OVER": { + "description": "Read this register to clear the RX_OVER interrupt (bit 1) of the IC_RAW_INTR_STAT register.\\n\\n\n Reset value: 0x0", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "IC_CLR_TX_OVER": { + "description": "Clear TX_OVER Interrupt Register", + "offset": 76, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CLR_TX_OVER": { + "description": "Read this register to clear the TX_OVER interrupt (bit 3) of the IC_RAW_INTR_STAT register.\\n\\n\n Reset value: 0x0", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "IC_CLR_RD_REQ": { + "description": "Clear RD_REQ Interrupt Register", + "offset": 80, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CLR_RD_REQ": { + "description": "Read this register to clear the RD_REQ interrupt (bit 5) of the IC_RAW_INTR_STAT register.\\n\\n\n Reset value: 0x0", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "IC_CLR_TX_ABRT": { + "description": "Clear TX_ABRT Interrupt Register", + "offset": 84, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CLR_TX_ABRT": { + "description": "Read this register to clear the TX_ABRT interrupt (bit 6) of the IC_RAW_INTR_STAT register, and the IC_TX_ABRT_SOURCE register. This also releases the TX FIFO from the flushed/reset state, allowing more writes to the TX FIFO. Refer to Bit 9 of the IC_TX_ABRT_SOURCE register for an exception to clearing IC_TX_ABRT_SOURCE.\\n\\n\n Reset value: 0x0", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "IC_CLR_RX_DONE": { + "description": "Clear RX_DONE Interrupt Register", + "offset": 88, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CLR_RX_DONE": { + "description": "Read this register to clear the RX_DONE interrupt (bit 7) of the IC_RAW_INTR_STAT register.\\n\\n\n Reset value: 0x0", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "IC_CLR_ACTIVITY": { + "description": "Clear ACTIVITY Interrupt Register", + "offset": 92, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CLR_ACTIVITY": { + "description": "Reading this register clears the ACTIVITY interrupt if the I2C is not active anymore. If the I2C module is still active on the bus, the ACTIVITY interrupt bit continues to be set. It is automatically cleared by hardware if the module is disabled and if there is no further activity on the bus. The value read from this register to get status of the ACTIVITY interrupt (bit 8) of the IC_RAW_INTR_STAT register.\\n\\n\n Reset value: 0x0", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "IC_CLR_STOP_DET": { + "description": "Clear STOP_DET Interrupt Register", + "offset": 96, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CLR_STOP_DET": { + "description": "Read this register to clear the STOP_DET interrupt (bit 9) of the IC_RAW_INTR_STAT register.\\n\\n\n Reset value: 0x0", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "IC_CLR_START_DET": { + "description": "Clear START_DET Interrupt Register", + "offset": 100, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CLR_START_DET": { + "description": "Read this register to clear the START_DET interrupt (bit 10) of the IC_RAW_INTR_STAT register.\\n\\n\n Reset value: 0x0", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "IC_CLR_GEN_CALL": { + "description": "Clear GEN_CALL Interrupt Register", + "offset": 104, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CLR_GEN_CALL": { + "description": "Read this register to clear the GEN_CALL interrupt (bit 11) of IC_RAW_INTR_STAT register.\\n\\n\n Reset value: 0x0", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "IC_ENABLE": { + "description": "I2C Enable Register", + "offset": 108, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "TX_CMD_BLOCK": { + "description": "In Master mode: - 1'b1: Blocks the transmission of data on I2C bus even if Tx FIFO has data to transmit. - 1'b0: The transmission of data starts on I2C bus automatically, as soon as the first data is available in the Tx FIFO. Note: To block the execution of Master commands, set the TX_CMD_BLOCK bit only when Tx FIFO is empty (IC_STATUS[2]==1) and Master is in Idle state (IC_STATUS[5] == 0). Any further commands put in the Tx FIFO are not executed until TX_CMD_BLOCK bit is unset. Reset value: IC_TX_CMD_BLOCK_DEFAULT", + "offset": 2, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "NOT_BLOCKED": { + "description": "Tx Command execution not blocked", + "value": 0 + }, + "BLOCKED": { + "description": "Tx Command execution blocked", + "value": 1 + } + } + } + } + }, + "ABORT": { + "description": "When set, the controller initiates the transfer abort. - 0: ABORT not initiated or ABORT done - 1: ABORT operation in progress The software can abort the I2C transfer in master mode by setting this bit. The software can set this bit only when ENABLE is already set; otherwise, the controller ignores any write to ABORT bit. The software cannot clear the ABORT bit once set. In response to an ABORT, the controller issues a STOP and flushes the Tx FIFO after completing the current transfer, then sets the TX_ABORT interrupt after the abort operation. The ABORT bit is cleared automatically after the abort operation.\\n\\n\n For a detailed description on how to abort I2C transfers, refer to 'Aborting I2C Transfers'.\\n\\n\n Reset value: 0x0", + "offset": 1, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "DISABLE": { + "description": "ABORT operation not in progress", + "value": 0 + }, + "ENABLED": { + "description": "ABORT operation in progress", + "value": 1 + } + } + } + } + }, + "ENABLE": { + "description": "Controls whether the DW_apb_i2c is enabled. - 0: Disables DW_apb_i2c (TX and RX FIFOs are held in an erased state) - 1: Enables DW_apb_i2c Software can disable DW_apb_i2c while it is active. However, it is important that care be taken to ensure that DW_apb_i2c is disabled properly. A recommended procedure is described in 'Disabling DW_apb_i2c'.\\n\\n\n When DW_apb_i2c is disabled, the following occurs: - The TX FIFO and RX FIFO get flushed. - Status bits in the IC_INTR_STAT register are still active until DW_apb_i2c goes into IDLE state. If the module is transmitting, it stops as well as deletes the contents of the transmit buffer after the current transfer is complete. If the module is receiving, the DW_apb_i2c stops the current transfer at the end of the current byte and does not acknowledge the transfer.\\n\\n\n In systems with asynchronous pclk and ic_clk when IC_CLK_TYPE parameter set to asynchronous (1), there is a two ic_clk delay when enabling or disabling the DW_apb_i2c. For a detailed description on how to disable DW_apb_i2c, refer to 'Disabling DW_apb_i2c'\\n\\n\n Reset value: 0x0", + "offset": 0, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "DISABLED": { + "description": "I2C is disabled", + "value": 0 + }, + "ENABLED": { + "description": "I2C is enabled", + "value": 1 + } + } + } + } + } + } + } + }, + "IC_STATUS": { + "description": "I2C Status Register\\n\\n\n This is a read-only register used to indicate the current transfer status and FIFO status. The status register may be read at any time. None of the bits in this register request an interrupt.\\n\\n\n When the I2C is disabled by writing 0 in bit 0 of the IC_ENABLE register: - Bits 1 and 2 are set to 1 - Bits 3 and 10 are set to 0 When the master or slave state machines goes to idle and ic_en=0: - Bits 5 and 6 are set to 0", + "offset": 112, + "size": 32, + "reset_value": 6, + "children": { + "fields": { + "SLV_ACTIVITY": { + "description": "Slave FSM Activity Status. When the Slave Finite State Machine (FSM) is not in the IDLE state, this bit is set. - 0: Slave FSM is in IDLE state so the Slave part of DW_apb_i2c is not Active - 1: Slave FSM is not in IDLE state so the Slave part of DW_apb_i2c is Active Reset value: 0x0", + "offset": 6, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "IDLE": { + "description": "Slave is idle", + "value": 0 + }, + "ACTIVE": { + "description": "Slave not idle", + "value": 1 + } + } + } + } + }, + "MST_ACTIVITY": { + "description": "Master FSM Activity Status. When the Master Finite State Machine (FSM) is not in the IDLE state, this bit is set. - 0: Master FSM is in IDLE state so the Master part of DW_apb_i2c is not Active - 1: Master FSM is not in IDLE state so the Master part of DW_apb_i2c is Active Note: IC_STATUS[0]-that is, ACTIVITY bit-is the OR of SLV_ACTIVITY and MST_ACTIVITY bits.\\n\\n\n Reset value: 0x0", + "offset": 5, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "IDLE": { + "description": "Master is idle", + "value": 0 + }, + "ACTIVE": { + "description": "Master not idle", + "value": 1 + } + } + } + } + }, + "RFF": { + "description": "Receive FIFO Completely Full. When the receive FIFO is completely full, this bit is set. When the receive FIFO contains one or more empty location, this bit is cleared. - 0: Receive FIFO is not full - 1: Receive FIFO is full Reset value: 0x0", + "offset": 4, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "NOT_FULL": { + "description": "Rx FIFO not full", + "value": 0 + }, + "FULL": { + "description": "Rx FIFO is full", + "value": 1 + } + } + } + } + }, + "RFNE": { + "description": "Receive FIFO Not Empty. This bit is set when the receive FIFO contains one or more entries; it is cleared when the receive FIFO is empty. - 0: Receive FIFO is empty - 1: Receive FIFO is not empty Reset value: 0x0", + "offset": 3, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "EMPTY": { + "description": "Rx FIFO is empty", + "value": 0 + }, + "NOT_EMPTY": { + "description": "Rx FIFO not empty", + "value": 1 + } + } + } + } + }, + "TFE": { + "description": "Transmit FIFO Completely Empty. When the transmit FIFO is completely empty, this bit is set. When it contains one or more valid entries, this bit is cleared. This bit field does not request an interrupt. - 0: Transmit FIFO is not empty - 1: Transmit FIFO is empty Reset value: 0x1", + "offset": 2, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "NON_EMPTY": { + "description": "Tx FIFO not empty", + "value": 0 + }, + "EMPTY": { + "description": "Tx FIFO is empty", + "value": 1 + } + } + } + } + }, + "TFNF": { + "description": "Transmit FIFO Not Full. Set when the transmit FIFO contains one or more empty locations, and is cleared when the FIFO is full. - 0: Transmit FIFO is full - 1: Transmit FIFO is not full Reset value: 0x1", + "offset": 1, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "FULL": { + "description": "Tx FIFO is full", + "value": 0 + }, + "NOT_FULL": { + "description": "Tx FIFO not full", + "value": 1 + } + } + } + } + }, + "ACTIVITY": { + "description": "I2C Activity Status. Reset value: 0x0", + "offset": 0, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "I2C is idle", + "value": 0 + }, + "ACTIVE": { + "description": "I2C is active", + "value": 1 + } + } + } + } + } + } + } + }, + "IC_TXFLR": { + "description": "I2C Transmit FIFO Level Register This register contains the number of valid data entries in the transmit FIFO buffer. It is cleared whenever: - The I2C is disabled - There is a transmit abort - that is, TX_ABRT bit is set in the IC_RAW_INTR_STAT register - The slave bulk transmit mode is aborted The register increments whenever data is placed into the transmit FIFO and decrements when data is taken from the transmit FIFO.", + "offset": 116, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "TXFLR": { + "description": "Transmit FIFO Level. Contains the number of valid data entries in the transmit FIFO.\\n\\n\n Reset value: 0x0", + "offset": 0, + "size": 5, + "access": "read-only" + } + } + } + }, + "IC_RXFLR": { + "description": "I2C Receive FIFO Level Register This register contains the number of valid data entries in the receive FIFO buffer. It is cleared whenever: - The I2C is disabled - Whenever there is a transmit abort caused by any of the events tracked in IC_TX_ABRT_SOURCE The register increments whenever data is placed into the receive FIFO and decrements when data is taken from the receive FIFO.", + "offset": 120, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "RXFLR": { + "description": "Receive FIFO Level. Contains the number of valid data entries in the receive FIFO.\\n\\n\n Reset value: 0x0", + "offset": 0, + "size": 5, + "access": "read-only" + } + } + } + }, + "IC_SDA_HOLD": { + "description": "I2C SDA Hold Time Length Register\\n\\n\n The bits [15:0] of this register are used to control the hold time of SDA during transmit in both slave and master mode (after SCL goes from HIGH to LOW).\\n\\n\n The bits [23:16] of this register are used to extend the SDA transition (if any) whenever SCL is HIGH in the receiver in either master or slave mode.\\n\\n\n Writes to this register succeed only when IC_ENABLE[0]=0.\\n\\n\n The values in this register are in units of ic_clk period. The value programmed in IC_SDA_TX_HOLD must be greater than the minimum hold time in each mode (one cycle in master mode, seven cycles in slave mode) for the value to be implemented.\\n\\n\n The programmed SDA hold time during transmit (IC_SDA_TX_HOLD) cannot exceed at any time the duration of the low part of scl. Therefore the programmed value cannot be larger than N_SCL_LOW-2, where N_SCL_LOW is the duration of the low part of the scl period measured in ic_clk cycles.", + "offset": 124, + "size": 32, + "reset_value": 1, + "children": { + "fields": { + "IC_SDA_RX_HOLD": { + "description": "Sets the required SDA hold time in units of ic_clk period, when DW_apb_i2c acts as a receiver.\\n\\n\n Reset value: IC_DEFAULT_SDA_HOLD[23:16].", + "offset": 16, + "size": 8 + }, + "IC_SDA_TX_HOLD": { + "description": "Sets the required SDA hold time in units of ic_clk period, when DW_apb_i2c acts as a transmitter.\\n\\n\n Reset value: IC_DEFAULT_SDA_HOLD[15:0].", + "offset": 0, + "size": 16 + } + } + } + }, + "IC_TX_ABRT_SOURCE": { + "description": "I2C Transmit Abort Source Register\\n\\n\n This register has 32 bits that indicate the source of the TX_ABRT bit. Except for Bit 9, this register is cleared whenever the IC_CLR_TX_ABRT register or the IC_CLR_INTR register is read. To clear Bit 9, the source of the ABRT_SBYTE_NORSTRT must be fixed first; RESTART must be enabled (IC_CON[5]=1), the SPECIAL bit must be cleared (IC_TAR[11]), or the GC_OR_START bit must be cleared (IC_TAR[10]).\\n\\n\n Once the source of the ABRT_SBYTE_NORSTRT is fixed, then this bit can be cleared in the same manner as other bits in this register. If the source of the ABRT_SBYTE_NORSTRT is not fixed before attempting to clear this bit, Bit 9 clears for one cycle and is then re-asserted.", + "offset": 128, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "TX_FLUSH_CNT": { + "description": "This field indicates the number of Tx FIFO Data Commands which are flushed due to TX_ABRT interrupt. It is cleared whenever I2C is disabled.\\n\\n\n Reset value: 0x0\\n\\n\n Role of DW_apb_i2c: Master-Transmitter or Slave-Transmitter", + "offset": 23, + "size": 9, + "access": "read-only" + }, + "ABRT_USER_ABRT": { + "description": "This is a master-mode-only bit. Master has detected the transfer abort (IC_ENABLE[1])\\n\\n\n Reset value: 0x0\\n\\n\n Role of DW_apb_i2c: Master-Transmitter", + "offset": 16, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ABRT_USER_ABRT_VOID": { + "description": "Transfer abort detected by master- scenario not present", + "value": 0 + }, + "ABRT_USER_ABRT_GENERATED": { + "description": "Transfer abort detected by master", + "value": 1 + } + } + } + } + }, + "ABRT_SLVRD_INTX": { + "description": "1: When the processor side responds to a slave mode request for data to be transmitted to a remote master and user writes a 1 in CMD (bit 8) of IC_DATA_CMD register.\\n\\n\n Reset value: 0x0\\n\\n\n Role of DW_apb_i2c: Slave-Transmitter", + "offset": 15, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ABRT_SLVRD_INTX_VOID": { + "description": "Slave trying to transmit to remote master in read mode- scenario not present", + "value": 0 + }, + "ABRT_SLVRD_INTX_GENERATED": { + "description": "Slave trying to transmit to remote master in read mode", + "value": 1 + } + } + } + } + }, + "ABRT_SLV_ARBLOST": { + "description": "This field indicates that a Slave has lost the bus while transmitting data to a remote master. IC_TX_ABRT_SOURCE[12] is set at the same time. Note: Even though the slave never 'owns' the bus, something could go wrong on the bus. This is a fail safe check. For instance, during a data transmission at the low-to-high transition of SCL, if what is on the data bus is not what is supposed to be transmitted, then DW_apb_i2c no longer own the bus.\\n\\n\n Reset value: 0x0\\n\\n\n Role of DW_apb_i2c: Slave-Transmitter", + "offset": 14, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ABRT_SLV_ARBLOST_VOID": { + "description": "Slave lost arbitration to remote master- scenario not present", + "value": 0 + }, + "ABRT_SLV_ARBLOST_GENERATED": { + "description": "Slave lost arbitration to remote master", + "value": 1 + } + } + } + } + }, + "ABRT_SLVFLUSH_TXFIFO": { + "description": "This field specifies that the Slave has received a read command and some data exists in the TX FIFO, so the slave issues a TX_ABRT interrupt to flush old data in TX FIFO.\\n\\n\n Reset value: 0x0\\n\\n\n Role of DW_apb_i2c: Slave-Transmitter", + "offset": 13, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ABRT_SLVFLUSH_TXFIFO_VOID": { + "description": "Slave flushes existing data in TX-FIFO upon getting read command- scenario not present", + "value": 0 + }, + "ABRT_SLVFLUSH_TXFIFO_GENERATED": { + "description": "Slave flushes existing data in TX-FIFO upon getting read command", + "value": 1 + } + } + } + } + }, + "ARB_LOST": { + "description": "This field specifies that the Master has lost arbitration, or if IC_TX_ABRT_SOURCE[14] is also set, then the slave transmitter has lost arbitration.\\n\\n\n Reset value: 0x0\\n\\n\n Role of DW_apb_i2c: Master-Transmitter or Slave-Transmitter", + "offset": 12, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ABRT_LOST_VOID": { + "description": "Master or Slave-Transmitter lost arbitration- scenario not present", + "value": 0 + }, + "ABRT_LOST_GENERATED": { + "description": "Master or Slave-Transmitter lost arbitration", + "value": 1 + } + } + } + } + }, + "ABRT_MASTER_DIS": { + "description": "This field indicates that the User tries to initiate a Master operation with the Master mode disabled.\\n\\n\n Reset value: 0x0\\n\\n\n Role of DW_apb_i2c: Master-Transmitter or Master-Receiver", + "offset": 11, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ABRT_MASTER_DIS_VOID": { + "description": "User initiating master operation when MASTER disabled- scenario not present", + "value": 0 + }, + "ABRT_MASTER_DIS_GENERATED": { + "description": "User initiating master operation when MASTER disabled", + "value": 1 + } + } + } + } + }, + "ABRT_10B_RD_NORSTRT": { + "description": "This field indicates that the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) =0) and the master sends a read command in 10-bit addressing mode.\\n\\n\n Reset value: 0x0\\n\\n\n Role of DW_apb_i2c: Master-Receiver", + "offset": 10, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ABRT_10B_RD_VOID": { + "description": "Master not trying to read in 10Bit addressing mode when RESTART disabled", + "value": 0 + }, + "ABRT_10B_RD_GENERATED": { + "description": "Master trying to read in 10Bit addressing mode when RESTART disabled", + "value": 1 + } + } + } + } + }, + "ABRT_SBYTE_NORSTRT": { + "description": "To clear Bit 9, the source of the ABRT_SBYTE_NORSTRT must be fixed first; restart must be enabled (IC_CON[5]=1), the SPECIAL bit must be cleared (IC_TAR[11]), or the GC_OR_START bit must be cleared (IC_TAR[10]). Once the source of the ABRT_SBYTE_NORSTRT is fixed, then this bit can be cleared in the same manner as other bits in this register. If the source of the ABRT_SBYTE_NORSTRT is not fixed before attempting to clear this bit, bit 9 clears for one cycle and then gets reasserted. When this field is set to 1, the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) =0) and the user is trying to send a START Byte.\\n\\n\n Reset value: 0x0\\n\\n\n Role of DW_apb_i2c: Master", + "offset": 9, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ABRT_SBYTE_NORSTRT_VOID": { + "description": "User trying to send START byte when RESTART disabled- scenario not present", + "value": 0 + }, + "ABRT_SBYTE_NORSTRT_GENERATED": { + "description": "User trying to send START byte when RESTART disabled", + "value": 1 + } + } + } + } + }, + "ABRT_HS_NORSTRT": { + "description": "This field indicates that the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) =0) and the user is trying to use the master to transfer data in High Speed mode.\\n\\n\n Reset value: 0x0\\n\\n\n Role of DW_apb_i2c: Master-Transmitter or Master-Receiver", + "offset": 8, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ABRT_HS_NORSTRT_VOID": { + "description": "User trying to switch Master to HS mode when RESTART disabled- scenario not present", + "value": 0 + }, + "ABRT_HS_NORSTRT_GENERATED": { + "description": "User trying to switch Master to HS mode when RESTART disabled", + "value": 1 + } + } + } + } + }, + "ABRT_SBYTE_ACKDET": { + "description": "This field indicates that the Master has sent a START Byte and the START Byte was acknowledged (wrong behavior).\\n\\n\n Reset value: 0x0\\n\\n\n Role of DW_apb_i2c: Master", + "offset": 7, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ABRT_SBYTE_ACKDET_VOID": { + "description": "ACK detected for START byte- scenario not present", + "value": 0 + }, + "ABRT_SBYTE_ACKDET_GENERATED": { + "description": "ACK detected for START byte", + "value": 1 + } + } + } + } + }, + "ABRT_HS_ACKDET": { + "description": "This field indicates that the Master is in High Speed mode and the High Speed Master code was acknowledged (wrong behavior).\\n\\n\n Reset value: 0x0\\n\\n\n Role of DW_apb_i2c: Master", + "offset": 6, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ABRT_HS_ACK_VOID": { + "description": "HS Master code ACKed in HS Mode- scenario not present", + "value": 0 + }, + "ABRT_HS_ACK_GENERATED": { + "description": "HS Master code ACKed in HS Mode", + "value": 1 + } + } + } + } + }, + "ABRT_GCALL_READ": { + "description": "This field indicates that DW_apb_i2c in the master mode has sent a General Call but the user programmed the byte following the General Call to be a read from the bus (IC_DATA_CMD[9] is set to 1).\\n\\n\n Reset value: 0x0\\n\\n\n Role of DW_apb_i2c: Master-Transmitter", + "offset": 5, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ABRT_GCALL_READ_VOID": { + "description": "GCALL is followed by read from bus-scenario not present", + "value": 0 + }, + "ABRT_GCALL_READ_GENERATED": { + "description": "GCALL is followed by read from bus", + "value": 1 + } + } + } + } + }, + "ABRT_GCALL_NOACK": { + "description": "This field indicates that DW_apb_i2c in master mode has sent a General Call and no slave on the bus acknowledged the General Call.\\n\\n\n Reset value: 0x0\\n\\n\n Role of DW_apb_i2c: Master-Transmitter", + "offset": 4, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ABRT_GCALL_NOACK_VOID": { + "description": "GCALL not ACKed by any slave-scenario not present", + "value": 0 + }, + "ABRT_GCALL_NOACK_GENERATED": { + "description": "GCALL not ACKed by any slave", + "value": 1 + } + } + } + } + }, + "ABRT_TXDATA_NOACK": { + "description": "This field indicates the master-mode only bit. When the master receives an acknowledgement for the address, but when it sends data byte(s) following the address, it did not receive an acknowledge from the remote slave(s).\\n\\n\n Reset value: 0x0\\n\\n\n Role of DW_apb_i2c: Master-Transmitter", + "offset": 3, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "ABRT_TXDATA_NOACK_VOID": { + "description": "Transmitted data non-ACKed by addressed slave-scenario not present", + "value": 0 + }, + "ABRT_TXDATA_NOACK_GENERATED": { + "description": "Transmitted data not ACKed by addressed slave", + "value": 1 + } + } + } + } + }, + "ABRT_10ADDR2_NOACK": { + "description": "This field indicates that the Master is in 10-bit address mode and that the second address byte of the 10-bit address was not acknowledged by any slave.\\n\\n\n Reset value: 0x0\\n\\n\n Role of DW_apb_i2c: Master-Transmitter or Master-Receiver", + "offset": 2, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "This abort is not generated", + "value": 0 + }, + "ACTIVE": { + "description": "Byte 2 of 10Bit Address not ACKed by any slave", + "value": 1 + } + } + } + } + }, + "ABRT_10ADDR1_NOACK": { + "description": "This field indicates that the Master is in 10-bit address mode and the first 10-bit address byte was not acknowledged by any slave.\\n\\n\n Reset value: 0x0\\n\\n\n Role of DW_apb_i2c: Master-Transmitter or Master-Receiver", + "offset": 1, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "This abort is not generated", + "value": 0 + }, + "ACTIVE": { + "description": "Byte 1 of 10Bit Address not ACKed by any slave", + "value": 1 + } + } + } + } + }, + "ABRT_7B_ADDR_NOACK": { + "description": "This field indicates that the Master is in 7-bit addressing mode and the address sent was not acknowledged by any slave.\\n\\n\n Reset value: 0x0\\n\\n\n Role of DW_apb_i2c: Master-Transmitter or Master-Receiver", + "offset": 0, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "This abort is not generated", + "value": 0 + }, + "ACTIVE": { + "description": "This abort is generated because of NOACK for 7-bit address", + "value": 1 + } + } + } + } + } + } + } + }, + "IC_SLV_DATA_NACK_ONLY": { + "description": "Generate Slave Data NACK Register\\n\\n\n The register is used to generate a NACK for the data part of a transfer when DW_apb_i2c is acting as a slave-receiver. This register only exists when the IC_SLV_DATA_NACK_ONLY parameter is set to 1. When this parameter disabled, this register does not exist and writing to the register's address has no effect.\\n\\n\n A write can occur on this register if both of the following conditions are met: - DW_apb_i2c is disabled (IC_ENABLE[0] = 0) - Slave part is inactive (IC_STATUS[6] = 0) Note: The IC_STATUS[6] is a register read-back location for the internal slv_activity signal; the user should poll this before writing the ic_slv_data_nack_only bit.", + "offset": 132, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "NACK": { + "description": "Generate NACK. This NACK generation only occurs when DW_apb_i2c is a slave-receiver. If this register is set to a value of 1, it can only generate a NACK after a data byte is received; hence, the data transfer is aborted and the data received is not pushed to the receive buffer.\\n\\n\n When the register is set to a value of 0, it generates NACK/ACK, depending on normal criteria. - 1: generate NACK after data byte received - 0: generate NACK/ACK normally Reset value: 0x0", + "offset": 0, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "DISABLED": { + "description": "Slave receiver generates NACK normally", + "value": 0 + }, + "ENABLED": { + "description": "Slave receiver generates NACK upon data reception only", + "value": 1 + } + } + } + } + } + } + } + }, + "IC_DMA_CR": { + "description": "DMA Control Register\\n\\n\n The register is used to enable the DMA Controller interface operation. There is a separate bit for transmit and receive. This can be programmed regardless of the state of IC_ENABLE.", + "offset": 136, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "TDMAE": { + "description": "Transmit DMA Enable. This bit enables/disables the transmit FIFO DMA channel. Reset value: 0x0", + "offset": 1, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "DISABLED": { + "description": "transmit FIFO DMA channel disabled", + "value": 0 + }, + "ENABLED": { + "description": "Transmit FIFO DMA channel enabled", + "value": 1 + } + } + } + } + }, + "RDMAE": { + "description": "Receive DMA Enable. This bit enables/disables the receive FIFO DMA channel. Reset value: 0x0", + "offset": 0, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "DISABLED": { + "description": "Receive FIFO DMA channel disabled", + "value": 0 + }, + "ENABLED": { + "description": "Receive FIFO DMA channel enabled", + "value": 1 + } + } + } + } + } + } + } + }, + "IC_DMA_TDLR": { + "description": "DMA Transmit Data Level Register", + "offset": 140, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "DMATDL": { + "description": "Transmit Data Level. This bit field controls the level at which a DMA request is made by the transmit logic. It is equal to the watermark level; that is, the dma_tx_req signal is generated when the number of valid data entries in the transmit FIFO is equal to or below this field value, and TDMAE = 1.\\n\\n\n Reset value: 0x0", + "offset": 0, + "size": 4 + } + } + } + }, + "IC_DMA_RDLR": { + "description": "I2C Receive Data Level Register", + "offset": 144, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "DMARDL": { + "description": "Receive Data Level. This bit field controls the level at which a DMA request is made by the receive logic. The watermark level = DMARDL+1; that is, dma_rx_req is generated when the number of valid data entries in the receive FIFO is equal to or more than this field value + 1, and RDMAE =1. For instance, when DMARDL is 0, then dma_rx_req is asserted when 1 or more data entries are present in the receive FIFO.\\n\\n\n Reset value: 0x0", + "offset": 0, + "size": 4 + } + } + } + }, + "IC_SDA_SETUP": { + "description": "I2C SDA Setup Register\\n\\n\n This register controls the amount of time delay (in terms of number of ic_clk clock periods) introduced in the rising edge of SCL - relative to SDA changing - when DW_apb_i2c services a read request in a slave-transmitter operation. The relevant I2C requirement is tSU:DAT (note 4) as detailed in the I2C Bus Specification. This register must be programmed with a value equal to or greater than 2.\\n\\n\n Writes to this register succeed only when IC_ENABLE[0] = 0.\\n\\n\n Note: The length of setup time is calculated using [(IC_SDA_SETUP - 1) * (ic_clk_period)], so if the user requires 10 ic_clk periods of setup time, they should program a value of 11. The IC_SDA_SETUP register is only used by the DW_apb_i2c when operating as a slave transmitter.", + "offset": 148, + "size": 32, + "reset_value": 100, + "children": { + "fields": { + "SDA_SETUP": { + "description": "SDA Setup. It is recommended that if the required delay is 1000ns, then for an ic_clk frequency of 10 MHz, IC_SDA_SETUP should be programmed to a value of 11. IC_SDA_SETUP must be programmed with a minimum value of 2.", + "offset": 0, + "size": 8 + } + } + } + }, + "IC_ACK_GENERAL_CALL": { + "description": "I2C ACK General Call Register\\n\\n\n The register controls whether DW_apb_i2c responds with a ACK or NACK when it receives an I2C General Call address.\\n\\n\n This register is applicable only when the DW_apb_i2c is in slave mode.", + "offset": 152, + "size": 32, + "reset_value": 1, + "children": { + "fields": { + "ACK_GEN_CALL": { + "description": "ACK General Call. When set to 1, DW_apb_i2c responds with a ACK (by asserting ic_data_oe) when it receives a General Call. Otherwise, DW_apb_i2c responds with a NACK (by negating ic_data_oe).", + "offset": 0, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "DISABLED": { + "description": "Generate NACK for a General Call", + "value": 0 + }, + "ENABLED": { + "description": "Generate ACK for a General Call", + "value": 1 + } + } + } + } + } + } + } + }, + "IC_ENABLE_STATUS": { + "description": "I2C Enable Status Register\\n\\n\n The register is used to report the DW_apb_i2c hardware status when the IC_ENABLE[0] register is set from 1 to 0; that is, when DW_apb_i2c is disabled.\\n\\n\n If IC_ENABLE[0] has been set to 1, bits 2:1 are forced to 0, and bit 0 is forced to 1.\\n\\n\n If IC_ENABLE[0] has been set to 0, bits 2:1 is only be valid as soon as bit 0 is read as '0'.\\n\\n\n Note: When IC_ENABLE[0] has been set to 0, a delay occurs for bit 0 to be read as 0 because disabling the DW_apb_i2c depends on I2C bus activities.", + "offset": 156, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SLV_RX_DATA_LOST": { + "description": "Slave Received Data Lost. This bit indicates if a Slave-Receiver operation has been aborted with at least one data byte received from an I2C transfer due to the setting bit 0 of IC_ENABLE from 1 to 0. When read as 1, DW_apb_i2c is deemed to have been actively engaged in an aborted I2C transfer (with matching address) and the data phase of the I2C transfer has been entered, even though a data byte has been responded with a NACK.\\n\\n\n Note: If the remote I2C master terminates the transfer with a STOP condition before the DW_apb_i2c has a chance to NACK a transfer, and IC_ENABLE[0] has been set to 0, then this bit is also set to 1.\\n\\n\n When read as 0, DW_apb_i2c is deemed to have been disabled without being actively involved in the data phase of a Slave-Receiver transfer.\\n\\n\n Note: The CPU can safely read this bit when IC_EN (bit 0) is read as 0.\\n\\n\n Reset value: 0x0", + "offset": 2, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "Slave RX Data is not lost", + "value": 0 + }, + "ACTIVE": { + "description": "Slave RX Data is lost", + "value": 1 + } + } + } + } + }, + "SLV_DISABLED_WHILE_BUSY": { + "description": "Slave Disabled While Busy (Transmit, Receive). This bit indicates if a potential or active Slave operation has been aborted due to the setting bit 0 of the IC_ENABLE register from 1 to 0. This bit is set when the CPU writes a 0 to the IC_ENABLE register while:\\n\\n\n (a) DW_apb_i2c is receiving the address byte of the Slave-Transmitter operation from a remote master;\\n\\n\n OR,\\n\\n\n (b) address and data bytes of the Slave-Receiver operation from a remote master.\\n\\n\n When read as 1, DW_apb_i2c is deemed to have forced a NACK during any part of an I2C transfer, irrespective of whether the I2C address matches the slave address set in DW_apb_i2c (IC_SAR register) OR if the transfer is completed before IC_ENABLE is set to 0 but has not taken effect.\\n\\n\n Note: If the remote I2C master terminates the transfer with a STOP condition before the DW_apb_i2c has a chance to NACK a transfer, and IC_ENABLE[0] has been set to 0, then this bit will also be set to 1.\\n\\n\n When read as 0, DW_apb_i2c is deemed to have been disabled when there is master activity, or when the I2C bus is idle.\\n\\n\n Note: The CPU can safely read this bit when IC_EN (bit 0) is read as 0.\\n\\n\n Reset value: 0x0", + "offset": 1, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "INACTIVE": { + "description": "Slave is disabled when it is idle", + "value": 0 + }, + "ACTIVE": { + "description": "Slave is disabled when it is active", + "value": 1 + } + } + } + } + }, + "IC_EN": { + "description": "ic_en Status. This bit always reflects the value driven on the output port ic_en. - When read as 1, DW_apb_i2c is deemed to be in an enabled state. - When read as 0, DW_apb_i2c is deemed completely inactive. Note: The CPU can safely read this bit anytime. When this bit is read as 0, the CPU can safely read SLV_RX_DATA_LOST (bit 2) and SLV_DISABLED_WHILE_BUSY (bit 1).\\n\\n\n Reset value: 0x0", + "offset": 0, + "size": 1, + "access": "read-only", + "enum": { + "size": 1, + "children": { + "enum_fields": { + "DISABLED": { + "description": "I2C disabled", + "value": 0 + }, + "ENABLED": { + "description": "I2C enabled", + "value": 1 + } + } + } + } + } + } + } + }, + "IC_FS_SPKLEN": { + "description": "I2C SS, FS or FM+ spike suppression limit\\n\\n\n This register is used to store the duration, measured in ic_clk cycles, of the longest spike that is filtered out by the spike suppression logic when the component is operating in SS, FS or FM+ modes. The relevant I2C requirement is tSP (table 4) as detailed in the I2C Bus Specification. This register must be programmed with a minimum value of 1.", + "offset": 160, + "size": 32, + "reset_value": 7, + "children": { + "fields": { + "IC_FS_SPKLEN": { + "description": "This register must be set before any I2C bus transaction can take place to ensure stable operation. This register sets the duration, measured in ic_clk cycles, of the longest spike in the SCL or SDA lines that will be filtered out by the spike suppression logic. This register can be written only when the I2C interface is disabled which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. The minimum valid value is 1; hardware prevents values less than this being written, and if attempted results in 1 being set. or more information, refer to 'Spike Suppression'.", + "offset": 0, + "size": 8 + } + } + } + }, + "IC_CLR_RESTART_DET": { + "description": "Clear RESTART_DET Interrupt Register", + "offset": 168, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CLR_RESTART_DET": { + "description": "Read this register to clear the RESTART_DET interrupt (bit 12) of IC_RAW_INTR_STAT register.\\n\\n\n Reset value: 0x0", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "IC_COMP_PARAM_1": { + "description": "Component Parameter Register 1\\n\\n\n Note This register is not implemented and therefore reads as 0. If it was implemented it would be a constant read-only register that contains encoded information about the component's parameter settings. Fields shown below are the settings for those parameters", + "offset": 244, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "TX_BUFFER_DEPTH": { + "description": "TX Buffer Depth = 16", + "offset": 16, + "size": 8, + "access": "read-only" + }, + "RX_BUFFER_DEPTH": { + "description": "RX Buffer Depth = 16", + "offset": 8, + "size": 8, + "access": "read-only" + }, + "ADD_ENCODED_PARAMS": { + "description": "Encoded parameters not visible", + "offset": 7, + "size": 1, + "access": "read-only" + }, + "HAS_DMA": { + "description": "DMA handshaking signals are enabled", + "offset": 6, + "size": 1, + "access": "read-only" + }, + "INTR_IO": { + "description": "COMBINED Interrupt outputs", + "offset": 5, + "size": 1, + "access": "read-only" + }, + "HC_COUNT_VALUES": { + "description": "Programmable count values for each mode.", + "offset": 4, + "size": 1, + "access": "read-only" + }, + "MAX_SPEED_MODE": { + "description": "MAX SPEED MODE = FAST MODE", + "offset": 2, + "size": 2, + "access": "read-only" + }, + "APB_DATA_WIDTH": { + "description": "APB data bus width is 32 bits", + "offset": 0, + "size": 2, + "access": "read-only" + } + } + } + }, + "IC_COMP_VERSION": { + "description": "I2C Component Version Register", + "offset": 248, + "size": 32, + "reset_value": 842019114, + "children": { + "fields": { + "IC_COMP_VERSION": { + "offset": 0, + "size": 32, + "access": "read-only" + } + } + } + }, + "IC_COMP_TYPE": { + "description": "I2C Component Type Register", + "offset": 252, + "size": 32, + "reset_value": 1146552640, + "children": { + "fields": { + "IC_COMP_TYPE": { + "description": "Designware Component Type number = 0x44_57_01_40. This assigned unique hex value is constant and is derived from the two ASCII letters 'DW' followed by a 16-bit unsigned number.", + "offset": 0, + "size": 32, + "access": "read-only" + } + } + } + } + } + } + }, + "PIO0": { + "description": "Programmable IO block", + "children": { + "registers": { + "CTRL": { + "description": "PIO control register", + "offset": 0, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CLKDIV_RESTART": { + "description": "Restart a state machine's clock divider from an initial phase of 0. Clock dividers are free-running, so once started, their output (including fractional jitter) is completely determined by the integer/fractional divisor configured in SMx_CLKDIV. This means that, if multiple clock dividers with the same divisor are restarted simultaneously, by writing multiple 1 bits to this field, the execution clocks of those state machines will run in precise lockstep.\\n\\n\n Note that setting/clearing SM_ENABLE does not stop the clock divider from running, so once multiple state machines' clocks are synchronised, it is safe to disable/reenable a state machine, whilst keeping the clock dividers in sync.\\n\\n\n Note also that CLKDIV_RESTART can be written to whilst the state machine is running, and this is useful to resynchronise clock dividers after the divisors (SMx_CLKDIV) have been changed on-the-fly.", + "offset": 8, + "size": 4 + }, + "SM_RESTART": { + "description": "Write 1 to instantly clear internal SM state which may be otherwise difficult to access and will affect future execution.\\n\\n\n Specifically, the following are cleared: input and output shift counters; the contents of the input shift register; the delay counter; the waiting-on-IRQ state; any stalled instruction written to SMx_INSTR or run by OUT/MOV EXEC; any pin write left asserted due to OUT_STICKY.", + "offset": 4, + "size": 4 + }, + "SM_ENABLE": { + "description": "Enable/disable each of the four state machines by writing 1/0 to each of these four bits. When disabled, a state machine will cease executing instructions, except those written directly to SMx_INSTR by the system. Multiple bits can be set/cleared at once to run/halt multiple state machines simultaneously.", + "offset": 0, + "size": 4 + } + } + } + }, + "FSTAT": { + "description": "FIFO status register", + "offset": 4, + "size": 32, + "reset_value": 251662080, + "children": { + "fields": { + "TXEMPTY": { + "description": "State machine TX FIFO is empty", + "offset": 24, + "size": 4, + "access": "read-only" + }, + "TXFULL": { + "description": "State machine TX FIFO is full", + "offset": 16, + "size": 4, + "access": "read-only" + }, + "RXEMPTY": { + "description": "State machine RX FIFO is empty", + "offset": 8, + "size": 4, + "access": "read-only" + }, + "RXFULL": { + "description": "State machine RX FIFO is full", + "offset": 0, + "size": 4, + "access": "read-only" + } + } + } + }, + "FDEBUG": { + "description": "FIFO debug register", + "offset": 8, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "TXSTALL": { + "description": "State machine has stalled on empty TX FIFO during a blocking PULL, or an OUT with autopull enabled. Write 1 to clear.", + "offset": 24, + "size": 4 + }, + "TXOVER": { + "description": "TX FIFO overflow (i.e. write-on-full by the system) has occurred. Write 1 to clear. Note that write-on-full does not alter the state or contents of the FIFO in any way, but the data that the system attempted to write is dropped, so if this flag is set, your software has quite likely dropped some data on the floor.", + "offset": 16, + "size": 4 + }, + "RXUNDER": { + "description": "RX FIFO underflow (i.e. read-on-empty by the system) has occurred. Write 1 to clear. Note that read-on-empty does not perturb the state of the FIFO in any way, but the data returned by reading from an empty FIFO is undefined, so this flag generally only becomes set due to some kind of software error.", + "offset": 8, + "size": 4 + }, + "RXSTALL": { + "description": "State machine has stalled on full RX FIFO during a blocking PUSH, or an IN with autopush enabled. This flag is also set when a nonblocking PUSH to a full FIFO took place, in which case the state machine has dropped data. Write 1 to clear.", + "offset": 0, + "size": 4 + } + } + } + }, + "FLEVEL": { + "description": "FIFO levels", + "offset": 12, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "RX3": { + "offset": 28, + "size": 4, + "access": "read-only" + }, + "TX3": { + "offset": 24, + "size": 4, + "access": "read-only" + }, + "RX2": { + "offset": 20, + "size": 4, + "access": "read-only" + }, + "TX2": { + "offset": 16, + "size": 4, + "access": "read-only" + }, + "RX1": { + "offset": 12, + "size": 4, + "access": "read-only" + }, + "TX1": { + "offset": 8, + "size": 4, + "access": "read-only" + }, + "RX0": { + "offset": 4, + "size": 4, + "access": "read-only" + }, + "TX0": { + "offset": 0, + "size": 4, + "access": "read-only" + } + } + } + }, + "TXF0": { + "description": "Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO.", + "offset": 16, + "size": 32, + "reset_value": 0, + "access": "write-only" + }, + "TXF1": { + "description": "Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO.", + "offset": 20, + "size": 32, + "reset_value": 0, + "access": "write-only" + }, + "TXF2": { + "description": "Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO.", + "offset": 24, + "size": 32, + "reset_value": 0, + "access": "write-only" + }, + "TXF3": { + "description": "Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO.", + "offset": 28, + "size": 32, + "reset_value": 0, + "access": "write-only" + }, + "RXF0": { + "description": "Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined.", + "offset": 32, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "RXF1": { + "description": "Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined.", + "offset": 36, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "RXF2": { + "description": "Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined.", + "offset": 40, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "RXF3": { + "description": "Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined.", + "offset": 44, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "IRQ": { + "description": "State machine IRQ flags register. Write 1 to clear. There are 8 state machine IRQ flags, which can be set, cleared, and waited on by the state machines. There's no fixed association between flags and state machines -- any state machine can use any flag.\\n\\n\n Any of the 8 flags can be used for timing synchronisation between state machines, using IRQ and WAIT instructions. The lower four of these flags are also routed out to system-level interrupt requests, alongside FIFO status interrupts -- see e.g. IRQ0_INTE.", + "offset": 48, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQ": { + "offset": 0, + "size": 8 + } + } + } + }, + "IRQ_FORCE": { + "description": "Writing a 1 to each of these bits will forcibly assert the corresponding IRQ. Note this is different to the INTF register: writing here affects PIO internal state. INTF just asserts the processor-facing IRQ signal for testing ISRs, and is not visible to the state machines.", + "offset": 52, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IRQ_FORCE": { + "offset": 0, + "size": 8, + "access": "write-only" + } + } + } + }, + "INPUT_SYNC_BYPASS": { + "description": "There is a 2-flipflop synchronizer on each GPIO input, which protects PIO logic from metastabilities. This increases input delay, and for fast synchronous IO (e.g. SPI) these synchronizers may need to be bypassed. Each bit in this register corresponds to one GPIO.\\n\n 0 -> input is synchronized (default)\\n\n 1 -> synchronizer is bypassed\\n\n If in doubt, leave this register as all zeroes.", + "offset": 56, + "size": 32, + "reset_value": 0 + }, + "DBG_PADOUT": { + "description": "Read to sample the pad output values PIO is currently driving to the GPIOs. On RP2040 there are 30 GPIOs, so the two most significant bits are hardwired to 0.", + "offset": 60, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "DBG_PADOE": { + "description": "Read to sample the pad output enables (direction) PIO is currently driving to the GPIOs. On RP2040 there are 30 GPIOs, so the two most significant bits are hardwired to 0.", + "offset": 64, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "DBG_CFGINFO": { + "description": "The PIO hardware has some free parameters that may vary between chip products.\\n\n These should be provided in the chip datasheet, but are also exposed here.", + "offset": 68, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "IMEM_SIZE": { + "description": "The size of the instruction memory, measured in units of one instruction", + "offset": 16, + "size": 6, + "access": "read-only" + }, + "SM_COUNT": { + "description": "The number of state machines this PIO instance is equipped with.", + "offset": 8, + "size": 4, + "access": "read-only" + }, + "FIFO_DEPTH": { + "description": "The depth of the state machine TX/RX FIFOs, measured in words.\\n\n Joining fifos via SHIFTCTRL_FJOIN gives one FIFO with double\\n\n this depth.", + "offset": 0, + "size": 6, + "access": "read-only" + } + } + } + }, + "INSTR_MEM0": { + "description": "Write-only access to instruction memory location 0", + "offset": 72, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM0": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM1": { + "description": "Write-only access to instruction memory location 1", + "offset": 76, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM1": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM2": { + "description": "Write-only access to instruction memory location 2", + "offset": 80, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM2": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM3": { + "description": "Write-only access to instruction memory location 3", + "offset": 84, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM3": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM4": { + "description": "Write-only access to instruction memory location 4", + "offset": 88, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM4": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM5": { + "description": "Write-only access to instruction memory location 5", + "offset": 92, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM5": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM6": { + "description": "Write-only access to instruction memory location 6", + "offset": 96, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM6": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM7": { + "description": "Write-only access to instruction memory location 7", + "offset": 100, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM7": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM8": { + "description": "Write-only access to instruction memory location 8", + "offset": 104, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM8": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM9": { + "description": "Write-only access to instruction memory location 9", + "offset": 108, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM9": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM10": { + "description": "Write-only access to instruction memory location 10", + "offset": 112, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM10": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM11": { + "description": "Write-only access to instruction memory location 11", + "offset": 116, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM11": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM12": { + "description": "Write-only access to instruction memory location 12", + "offset": 120, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM12": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM13": { + "description": "Write-only access to instruction memory location 13", + "offset": 124, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM13": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM14": { + "description": "Write-only access to instruction memory location 14", + "offset": 128, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM14": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM15": { + "description": "Write-only access to instruction memory location 15", + "offset": 132, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM15": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM16": { + "description": "Write-only access to instruction memory location 16", + "offset": 136, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM16": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM17": { + "description": "Write-only access to instruction memory location 17", + "offset": 140, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM17": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM18": { + "description": "Write-only access to instruction memory location 18", + "offset": 144, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM18": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM19": { + "description": "Write-only access to instruction memory location 19", + "offset": 148, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM19": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM20": { + "description": "Write-only access to instruction memory location 20", + "offset": 152, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM20": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM21": { + "description": "Write-only access to instruction memory location 21", + "offset": 156, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM21": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM22": { + "description": "Write-only access to instruction memory location 22", + "offset": 160, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM22": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM23": { + "description": "Write-only access to instruction memory location 23", + "offset": 164, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM23": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM24": { + "description": "Write-only access to instruction memory location 24", + "offset": 168, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM24": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM25": { + "description": "Write-only access to instruction memory location 25", + "offset": 172, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM25": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM26": { + "description": "Write-only access to instruction memory location 26", + "offset": 176, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM26": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM27": { + "description": "Write-only access to instruction memory location 27", + "offset": 180, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM27": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM28": { + "description": "Write-only access to instruction memory location 28", + "offset": 184, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM28": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM29": { + "description": "Write-only access to instruction memory location 29", + "offset": 188, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM29": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM30": { + "description": "Write-only access to instruction memory location 30", + "offset": 192, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM30": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "INSTR_MEM31": { + "description": "Write-only access to instruction memory location 31", + "offset": 196, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INSTR_MEM31": { + "offset": 0, + "size": 16, + "access": "write-only" + } + } + } + }, + "SM0_CLKDIV": { + "description": "Clock divisor register for state machine 0\\n\n Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256)", + "offset": 200, + "size": 32, + "reset_value": 65536, + "children": { + "fields": { + "INT": { + "description": "Effective frequency is sysclk/(int + frac/256).\\n\n Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0.", + "offset": 16, + "size": 16 + }, + "FRAC": { + "description": "Fractional part of clock divisor", + "offset": 8, + "size": 8 + } + } + } + }, + "SM0_EXECCTRL": { + "description": "Execution/behavioural settings for state machine 0", + "offset": 204, + "size": 32, + "reset_value": 126976, + "children": { + "fields": { + "EXEC_STALLED": { + "description": "If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes.", + "offset": 31, + "size": 1, + "access": "read-only" + }, + "SIDE_EN": { + "description": "If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit.", + "offset": 30, + "size": 1 + }, + "SIDE_PINDIR": { + "description": "If 1, side-set data is asserted to pin directions, instead of pin values", + "offset": 29, + "size": 1 + }, + "JMP_PIN": { + "description": "The GPIO number to use as condition for JMP PIN. Unaffected by input mapping.", + "offset": 24, + "size": 5 + }, + "OUT_EN_SEL": { + "description": "Which data bit to use for inline OUT enable", + "offset": 19, + "size": 5 + }, + "INLINE_OUT_EN": { + "description": "If 1, use a bit of OUT data as an auxiliary write enable\\n\n When used in conjunction with OUT_STICKY, writes with an enable of 0 will\\n\n deassert the latest pin write. This can create useful masking/override behaviour\\n\n due to the priority ordering of state machine pin writes (SM0 < SM1 < ...)", + "offset": 18, + "size": 1 + }, + "OUT_STICKY": { + "description": "Continuously assert the most recent OUT/SET to the pins", + "offset": 17, + "size": 1 + }, + "WRAP_TOP": { + "description": "After reaching this address, execution is wrapped to wrap_bottom.\\n\n If the instruction is a jump, and the jump condition is true, the jump takes priority.", + "offset": 12, + "size": 5 + }, + "WRAP_BOTTOM": { + "description": "After reaching wrap_top, execution is wrapped to this address.", + "offset": 7, + "size": 5 + }, + "STATUS_SEL": { + "description": "Comparison used for the MOV x, STATUS instruction.", + "offset": 4, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "TXLEVEL": { + "description": "All-ones if TX FIFO level < N, otherwise all-zeroes", + "value": 0 + }, + "RXLEVEL": { + "description": "All-ones if RX FIFO level < N, otherwise all-zeroes", + "value": 1 + } + } + } + } + }, + "STATUS_N": { + "description": "Comparison level for the MOV x, STATUS instruction", + "offset": 0, + "size": 4 + } + } + } + }, + "SM0_SHIFTCTRL": { + "description": "Control behaviour of the input/output shift registers for state machine 0", + "offset": 208, + "size": 32, + "reset_value": 786432, + "children": { + "fields": { + "FJOIN_RX": { + "description": "When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep.\\n\n TX FIFO is disabled as a result (always reads as both full and empty).\\n\n FIFOs are flushed when this bit is changed.", + "offset": 31, + "size": 1 + }, + "FJOIN_TX": { + "description": "When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep.\\n\n RX FIFO is disabled as a result (always reads as both full and empty).\\n\n FIFOs are flushed when this bit is changed.", + "offset": 30, + "size": 1 + }, + "PULL_THRESH": { + "description": "Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place.\\n\n Write 0 for value of 32.", + "offset": 25, + "size": 5 + }, + "PUSH_THRESH": { + "description": "Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place.\\n\n Write 0 for value of 32.", + "offset": 20, + "size": 5 + }, + "OUT_SHIFTDIR": { + "description": "1 = shift out of output shift register to right. 0 = to left.", + "offset": 19, + "size": 1 + }, + "IN_SHIFTDIR": { + "description": "1 = shift input shift register to right (data enters from left). 0 = to left.", + "offset": 18, + "size": 1 + }, + "AUTOPULL": { + "description": "Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH.", + "offset": 17, + "size": 1 + }, + "AUTOPUSH": { + "description": "Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH.", + "offset": 16, + "size": 1 + } + } + } + }, + "SM0_ADDR": { + "description": "Current instruction address of state machine 0", + "offset": 212, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SM0_ADDR": { + "offset": 0, + "size": 5, + "access": "read-only" + } + } + } + }, + "SM0_INSTR": { + "description": "Read to see the instruction currently addressed by state machine 0's program counter\\n\n Write to execute an instruction immediately (including jumps) and then resume execution.", + "offset": 216, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SM0_INSTR": { + "offset": 0, + "size": 16 + } + } + } + }, + "SM0_PINCTRL": { + "description": "State machine pin control", + "offset": 220, + "size": 32, + "reset_value": 335544320, + "children": { + "fields": { + "SIDESET_COUNT": { + "description": "The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay).", + "offset": 29, + "size": 3 + }, + "SET_COUNT": { + "description": "The number of pins asserted by a SET. In the range 0 to 5 inclusive.", + "offset": 26, + "size": 3 + }, + "OUT_COUNT": { + "description": "The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive.", + "offset": 20, + "size": 6 + }, + "IN_BASE": { + "description": "The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number.", + "offset": 15, + "size": 5 + }, + "SIDESET_BASE": { + "description": "The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins.", + "offset": 10, + "size": 5 + }, + "SET_BASE": { + "description": "The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data.", + "offset": 5, + "size": 5 + }, + "OUT_BASE": { + "description": "The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data.", + "offset": 0, + "size": 5 + } + } + } + }, + "SM1_CLKDIV": { + "description": "Clock divisor register for state machine 1\\n\n Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256)", + "offset": 224, + "size": 32, + "reset_value": 65536, + "children": { + "fields": { + "INT": { + "description": "Effective frequency is sysclk/(int + frac/256).\\n\n Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0.", + "offset": 16, + "size": 16 + }, + "FRAC": { + "description": "Fractional part of clock divisor", + "offset": 8, + "size": 8 + } + } + } + }, + "SM1_EXECCTRL": { + "description": "Execution/behavioural settings for state machine 1", + "offset": 228, + "size": 32, + "reset_value": 126976, + "children": { + "fields": { + "EXEC_STALLED": { + "description": "If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes.", + "offset": 31, + "size": 1, + "access": "read-only" + }, + "SIDE_EN": { + "description": "If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit.", + "offset": 30, + "size": 1 + }, + "SIDE_PINDIR": { + "description": "If 1, side-set data is asserted to pin directions, instead of pin values", + "offset": 29, + "size": 1 + }, + "JMP_PIN": { + "description": "The GPIO number to use as condition for JMP PIN. Unaffected by input mapping.", + "offset": 24, + "size": 5 + }, + "OUT_EN_SEL": { + "description": "Which data bit to use for inline OUT enable", + "offset": 19, + "size": 5 + }, + "INLINE_OUT_EN": { + "description": "If 1, use a bit of OUT data as an auxiliary write enable\\n\n When used in conjunction with OUT_STICKY, writes with an enable of 0 will\\n\n deassert the latest pin write. This can create useful masking/override behaviour\\n\n due to the priority ordering of state machine pin writes (SM0 < SM1 < ...)", + "offset": 18, + "size": 1 + }, + "OUT_STICKY": { + "description": "Continuously assert the most recent OUT/SET to the pins", + "offset": 17, + "size": 1 + }, + "WRAP_TOP": { + "description": "After reaching this address, execution is wrapped to wrap_bottom.\\n\n If the instruction is a jump, and the jump condition is true, the jump takes priority.", + "offset": 12, + "size": 5 + }, + "WRAP_BOTTOM": { + "description": "After reaching wrap_top, execution is wrapped to this address.", + "offset": 7, + "size": 5 + }, + "STATUS_SEL": { + "description": "Comparison used for the MOV x, STATUS instruction.", + "offset": 4, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "TXLEVEL": { + "description": "All-ones if TX FIFO level < N, otherwise all-zeroes", + "value": 0 + }, + "RXLEVEL": { + "description": "All-ones if RX FIFO level < N, otherwise all-zeroes", + "value": 1 + } + } + } + } + }, + "STATUS_N": { + "description": "Comparison level for the MOV x, STATUS instruction", + "offset": 0, + "size": 4 + } + } + } + }, + "SM1_SHIFTCTRL": { + "description": "Control behaviour of the input/output shift registers for state machine 1", + "offset": 232, + "size": 32, + "reset_value": 786432, + "children": { + "fields": { + "FJOIN_RX": { + "description": "When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep.\\n\n TX FIFO is disabled as a result (always reads as both full and empty).\\n\n FIFOs are flushed when this bit is changed.", + "offset": 31, + "size": 1 + }, + "FJOIN_TX": { + "description": "When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep.\\n\n RX FIFO is disabled as a result (always reads as both full and empty).\\n\n FIFOs are flushed when this bit is changed.", + "offset": 30, + "size": 1 + }, + "PULL_THRESH": { + "description": "Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place.\\n\n Write 0 for value of 32.", + "offset": 25, + "size": 5 + }, + "PUSH_THRESH": { + "description": "Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place.\\n\n Write 0 for value of 32.", + "offset": 20, + "size": 5 + }, + "OUT_SHIFTDIR": { + "description": "1 = shift out of output shift register to right. 0 = to left.", + "offset": 19, + "size": 1 + }, + "IN_SHIFTDIR": { + "description": "1 = shift input shift register to right (data enters from left). 0 = to left.", + "offset": 18, + "size": 1 + }, + "AUTOPULL": { + "description": "Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH.", + "offset": 17, + "size": 1 + }, + "AUTOPUSH": { + "description": "Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH.", + "offset": 16, + "size": 1 + } + } + } + }, + "SM1_ADDR": { + "description": "Current instruction address of state machine 1", + "offset": 236, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SM1_ADDR": { + "offset": 0, + "size": 5, + "access": "read-only" + } + } + } + }, + "SM1_INSTR": { + "description": "Read to see the instruction currently addressed by state machine 1's program counter\\n\n Write to execute an instruction immediately (including jumps) and then resume execution.", + "offset": 240, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SM1_INSTR": { + "offset": 0, + "size": 16 + } + } + } + }, + "SM1_PINCTRL": { + "description": "State machine pin control", + "offset": 244, + "size": 32, + "reset_value": 335544320, + "children": { + "fields": { + "SIDESET_COUNT": { + "description": "The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay).", + "offset": 29, + "size": 3 + }, + "SET_COUNT": { + "description": "The number of pins asserted by a SET. In the range 0 to 5 inclusive.", + "offset": 26, + "size": 3 + }, + "OUT_COUNT": { + "description": "The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive.", + "offset": 20, + "size": 6 + }, + "IN_BASE": { + "description": "The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number.", + "offset": 15, + "size": 5 + }, + "SIDESET_BASE": { + "description": "The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins.", + "offset": 10, + "size": 5 + }, + "SET_BASE": { + "description": "The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data.", + "offset": 5, + "size": 5 + }, + "OUT_BASE": { + "description": "The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data.", + "offset": 0, + "size": 5 + } + } + } + }, + "SM2_CLKDIV": { + "description": "Clock divisor register for state machine 2\\n\n Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256)", + "offset": 248, + "size": 32, + "reset_value": 65536, + "children": { + "fields": { + "INT": { + "description": "Effective frequency is sysclk/(int + frac/256).\\n\n Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0.", + "offset": 16, + "size": 16 + }, + "FRAC": { + "description": "Fractional part of clock divisor", + "offset": 8, + "size": 8 + } + } + } + }, + "SM2_EXECCTRL": { + "description": "Execution/behavioural settings for state machine 2", + "offset": 252, + "size": 32, + "reset_value": 126976, + "children": { + "fields": { + "EXEC_STALLED": { + "description": "If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes.", + "offset": 31, + "size": 1, + "access": "read-only" + }, + "SIDE_EN": { + "description": "If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit.", + "offset": 30, + "size": 1 + }, + "SIDE_PINDIR": { + "description": "If 1, side-set data is asserted to pin directions, instead of pin values", + "offset": 29, + "size": 1 + }, + "JMP_PIN": { + "description": "The GPIO number to use as condition for JMP PIN. Unaffected by input mapping.", + "offset": 24, + "size": 5 + }, + "OUT_EN_SEL": { + "description": "Which data bit to use for inline OUT enable", + "offset": 19, + "size": 5 + }, + "INLINE_OUT_EN": { + "description": "If 1, use a bit of OUT data as an auxiliary write enable\\n\n When used in conjunction with OUT_STICKY, writes with an enable of 0 will\\n\n deassert the latest pin write. This can create useful masking/override behaviour\\n\n due to the priority ordering of state machine pin writes (SM0 < SM1 < ...)", + "offset": 18, + "size": 1 + }, + "OUT_STICKY": { + "description": "Continuously assert the most recent OUT/SET to the pins", + "offset": 17, + "size": 1 + }, + "WRAP_TOP": { + "description": "After reaching this address, execution is wrapped to wrap_bottom.\\n\n If the instruction is a jump, and the jump condition is true, the jump takes priority.", + "offset": 12, + "size": 5 + }, + "WRAP_BOTTOM": { + "description": "After reaching wrap_top, execution is wrapped to this address.", + "offset": 7, + "size": 5 + }, + "STATUS_SEL": { + "description": "Comparison used for the MOV x, STATUS instruction.", + "offset": 4, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "TXLEVEL": { + "description": "All-ones if TX FIFO level < N, otherwise all-zeroes", + "value": 0 + }, + "RXLEVEL": { + "description": "All-ones if RX FIFO level < N, otherwise all-zeroes", + "value": 1 + } + } + } + } + }, + "STATUS_N": { + "description": "Comparison level for the MOV x, STATUS instruction", + "offset": 0, + "size": 4 + } + } + } + }, + "SM2_SHIFTCTRL": { + "description": "Control behaviour of the input/output shift registers for state machine 2", + "offset": 256, + "size": 32, + "reset_value": 786432, + "children": { + "fields": { + "FJOIN_RX": { + "description": "When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep.\\n\n TX FIFO is disabled as a result (always reads as both full and empty).\\n\n FIFOs are flushed when this bit is changed.", + "offset": 31, + "size": 1 + }, + "FJOIN_TX": { + "description": "When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep.\\n\n RX FIFO is disabled as a result (always reads as both full and empty).\\n\n FIFOs are flushed when this bit is changed.", + "offset": 30, + "size": 1 + }, + "PULL_THRESH": { + "description": "Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place.\\n\n Write 0 for value of 32.", + "offset": 25, + "size": 5 + }, + "PUSH_THRESH": { + "description": "Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place.\\n\n Write 0 for value of 32.", + "offset": 20, + "size": 5 + }, + "OUT_SHIFTDIR": { + "description": "1 = shift out of output shift register to right. 0 = to left.", + "offset": 19, + "size": 1 + }, + "IN_SHIFTDIR": { + "description": "1 = shift input shift register to right (data enters from left). 0 = to left.", + "offset": 18, + "size": 1 + }, + "AUTOPULL": { + "description": "Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH.", + "offset": 17, + "size": 1 + }, + "AUTOPUSH": { + "description": "Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH.", + "offset": 16, + "size": 1 + } + } + } + }, + "SM2_ADDR": { + "description": "Current instruction address of state machine 2", + "offset": 260, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SM2_ADDR": { + "offset": 0, + "size": 5, + "access": "read-only" + } + } + } + }, + "SM2_INSTR": { + "description": "Read to see the instruction currently addressed by state machine 2's program counter\\n\n Write to execute an instruction immediately (including jumps) and then resume execution.", + "offset": 264, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SM2_INSTR": { + "offset": 0, + "size": 16 + } + } + } + }, + "SM2_PINCTRL": { + "description": "State machine pin control", + "offset": 268, + "size": 32, + "reset_value": 335544320, + "children": { + "fields": { + "SIDESET_COUNT": { + "description": "The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay).", + "offset": 29, + "size": 3 + }, + "SET_COUNT": { + "description": "The number of pins asserted by a SET. In the range 0 to 5 inclusive.", + "offset": 26, + "size": 3 + }, + "OUT_COUNT": { + "description": "The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive.", + "offset": 20, + "size": 6 + }, + "IN_BASE": { + "description": "The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number.", + "offset": 15, + "size": 5 + }, + "SIDESET_BASE": { + "description": "The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins.", + "offset": 10, + "size": 5 + }, + "SET_BASE": { + "description": "The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data.", + "offset": 5, + "size": 5 + }, + "OUT_BASE": { + "description": "The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data.", + "offset": 0, + "size": 5 + } + } + } + }, + "SM3_CLKDIV": { + "description": "Clock divisor register for state machine 3\\n\n Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256)", + "offset": 272, + "size": 32, + "reset_value": 65536, + "children": { + "fields": { + "INT": { + "description": "Effective frequency is sysclk/(int + frac/256).\\n\n Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0.", + "offset": 16, + "size": 16 + }, + "FRAC": { + "description": "Fractional part of clock divisor", + "offset": 8, + "size": 8 + } + } + } + }, + "SM3_EXECCTRL": { + "description": "Execution/behavioural settings for state machine 3", + "offset": 276, + "size": 32, + "reset_value": 126976, + "children": { + "fields": { + "EXEC_STALLED": { + "description": "If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes.", + "offset": 31, + "size": 1, + "access": "read-only" + }, + "SIDE_EN": { + "description": "If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit.", + "offset": 30, + "size": 1 + }, + "SIDE_PINDIR": { + "description": "If 1, side-set data is asserted to pin directions, instead of pin values", + "offset": 29, + "size": 1 + }, + "JMP_PIN": { + "description": "The GPIO number to use as condition for JMP PIN. Unaffected by input mapping.", + "offset": 24, + "size": 5 + }, + "OUT_EN_SEL": { + "description": "Which data bit to use for inline OUT enable", + "offset": 19, + "size": 5 + }, + "INLINE_OUT_EN": { + "description": "If 1, use a bit of OUT data as an auxiliary write enable\\n\n When used in conjunction with OUT_STICKY, writes with an enable of 0 will\\n\n deassert the latest pin write. This can create useful masking/override behaviour\\n\n due to the priority ordering of state machine pin writes (SM0 < SM1 < ...)", + "offset": 18, + "size": 1 + }, + "OUT_STICKY": { + "description": "Continuously assert the most recent OUT/SET to the pins", + "offset": 17, + "size": 1 + }, + "WRAP_TOP": { + "description": "After reaching this address, execution is wrapped to wrap_bottom.\\n\n If the instruction is a jump, and the jump condition is true, the jump takes priority.", + "offset": 12, + "size": 5 + }, + "WRAP_BOTTOM": { + "description": "After reaching wrap_top, execution is wrapped to this address.", + "offset": 7, + "size": 5 + }, + "STATUS_SEL": { + "description": "Comparison used for the MOV x, STATUS instruction.", + "offset": 4, + "size": 1, + "enum": { + "size": 1, + "children": { + "enum_fields": { + "TXLEVEL": { + "description": "All-ones if TX FIFO level < N, otherwise all-zeroes", + "value": 0 + }, + "RXLEVEL": { + "description": "All-ones if RX FIFO level < N, otherwise all-zeroes", + "value": 1 + } + } + } + } + }, + "STATUS_N": { + "description": "Comparison level for the MOV x, STATUS instruction", + "offset": 0, + "size": 4 + } + } + } + }, + "SM3_SHIFTCTRL": { + "description": "Control behaviour of the input/output shift registers for state machine 3", + "offset": 280, + "size": 32, + "reset_value": 786432, + "children": { + "fields": { + "FJOIN_RX": { + "description": "When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep.\\n\n TX FIFO is disabled as a result (always reads as both full and empty).\\n\n FIFOs are flushed when this bit is changed.", + "offset": 31, + "size": 1 + }, + "FJOIN_TX": { + "description": "When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep.\\n\n RX FIFO is disabled as a result (always reads as both full and empty).\\n\n FIFOs are flushed when this bit is changed.", + "offset": 30, + "size": 1 + }, + "PULL_THRESH": { + "description": "Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place.\\n\n Write 0 for value of 32.", + "offset": 25, + "size": 5 + }, + "PUSH_THRESH": { + "description": "Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place.\\n\n Write 0 for value of 32.", + "offset": 20, + "size": 5 + }, + "OUT_SHIFTDIR": { + "description": "1 = shift out of output shift register to right. 0 = to left.", + "offset": 19, + "size": 1 + }, + "IN_SHIFTDIR": { + "description": "1 = shift input shift register to right (data enters from left). 0 = to left.", + "offset": 18, + "size": 1 + }, + "AUTOPULL": { + "description": "Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH.", + "offset": 17, + "size": 1 + }, + "AUTOPUSH": { + "description": "Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH.", + "offset": 16, + "size": 1 + } + } + } + }, + "SM3_ADDR": { + "description": "Current instruction address of state machine 3", + "offset": 284, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SM3_ADDR": { + "offset": 0, + "size": 5, + "access": "read-only" + } + } + } + }, + "SM3_INSTR": { + "description": "Read to see the instruction currently addressed by state machine 3's program counter\\n\n Write to execute an instruction immediately (including jumps) and then resume execution.", + "offset": 288, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SM3_INSTR": { + "offset": 0, + "size": 16 + } + } + } + }, + "SM3_PINCTRL": { + "description": "State machine pin control", + "offset": 292, + "size": 32, + "reset_value": 335544320, + "children": { + "fields": { + "SIDESET_COUNT": { + "description": "The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay).", + "offset": 29, + "size": 3 + }, + "SET_COUNT": { + "description": "The number of pins asserted by a SET. In the range 0 to 5 inclusive.", + "offset": 26, + "size": 3 + }, + "OUT_COUNT": { + "description": "The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive.", + "offset": 20, + "size": 6 + }, + "IN_BASE": { + "description": "The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number.", + "offset": 15, + "size": 5 + }, + "SIDESET_BASE": { + "description": "The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins.", + "offset": 10, + "size": 5 + }, + "SET_BASE": { + "description": "The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data.", + "offset": 5, + "size": 5 + }, + "OUT_BASE": { + "description": "The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data.", + "offset": 0, + "size": 5 + } + } + } + }, + "INTR": { + "description": "Raw Interrupts", + "offset": 296, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SM3": { + "offset": 11, + "size": 1, + "access": "read-only" + }, + "SM2": { + "offset": 10, + "size": 1, + "access": "read-only" + }, + "SM1": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "SM0": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "SM3_TXNFULL": { + "offset": 7, + "size": 1, + "access": "read-only" + }, + "SM2_TXNFULL": { + "offset": 6, + "size": 1, + "access": "read-only" + }, + "SM1_TXNFULL": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "SM0_TXNFULL": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "SM3_RXNEMPTY": { + "offset": 3, + "size": 1, + "access": "read-only" + }, + "SM2_RXNEMPTY": { + "offset": 2, + "size": 1, + "access": "read-only" + }, + "SM1_RXNEMPTY": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "SM0_RXNEMPTY": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "IRQ0_INTE": { + "description": "Interrupt Enable for irq0", + "offset": 300, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SM3": { + "offset": 11, + "size": 1 + }, + "SM2": { + "offset": 10, + "size": 1 + }, + "SM1": { + "offset": 9, + "size": 1 + }, + "SM0": { + "offset": 8, + "size": 1 + }, + "SM3_TXNFULL": { + "offset": 7, + "size": 1 + }, + "SM2_TXNFULL": { + "offset": 6, + "size": 1 + }, + "SM1_TXNFULL": { + "offset": 5, + "size": 1 + }, + "SM0_TXNFULL": { + "offset": 4, + "size": 1 + }, + "SM3_RXNEMPTY": { + "offset": 3, + "size": 1 + }, + "SM2_RXNEMPTY": { + "offset": 2, + "size": 1 + }, + "SM1_RXNEMPTY": { + "offset": 1, + "size": 1 + }, + "SM0_RXNEMPTY": { + "offset": 0, + "size": 1 + } + } + } + }, + "IRQ0_INTF": { + "description": "Interrupt Force for irq0", + "offset": 304, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SM3": { + "offset": 11, + "size": 1 + }, + "SM2": { + "offset": 10, + "size": 1 + }, + "SM1": { + "offset": 9, + "size": 1 + }, + "SM0": { + "offset": 8, + "size": 1 + }, + "SM3_TXNFULL": { + "offset": 7, + "size": 1 + }, + "SM2_TXNFULL": { + "offset": 6, + "size": 1 + }, + "SM1_TXNFULL": { + "offset": 5, + "size": 1 + }, + "SM0_TXNFULL": { + "offset": 4, + "size": 1 + }, + "SM3_RXNEMPTY": { + "offset": 3, + "size": 1 + }, + "SM2_RXNEMPTY": { + "offset": 2, + "size": 1 + }, + "SM1_RXNEMPTY": { + "offset": 1, + "size": 1 + }, + "SM0_RXNEMPTY": { + "offset": 0, + "size": 1 + } + } + } + }, + "IRQ0_INTS": { + "description": "Interrupt status after masking & forcing for irq0", + "offset": 308, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SM3": { + "offset": 11, + "size": 1, + "access": "read-only" + }, + "SM2": { + "offset": 10, + "size": 1, + "access": "read-only" + }, + "SM1": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "SM0": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "SM3_TXNFULL": { + "offset": 7, + "size": 1, + "access": "read-only" + }, + "SM2_TXNFULL": { + "offset": 6, + "size": 1, + "access": "read-only" + }, + "SM1_TXNFULL": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "SM0_TXNFULL": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "SM3_RXNEMPTY": { + "offset": 3, + "size": 1, + "access": "read-only" + }, + "SM2_RXNEMPTY": { + "offset": 2, + "size": 1, + "access": "read-only" + }, + "SM1_RXNEMPTY": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "SM0_RXNEMPTY": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "IRQ1_INTE": { + "description": "Interrupt Enable for irq1", + "offset": 312, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SM3": { + "offset": 11, + "size": 1 + }, + "SM2": { + "offset": 10, + "size": 1 + }, + "SM1": { + "offset": 9, + "size": 1 + }, + "SM0": { + "offset": 8, + "size": 1 + }, + "SM3_TXNFULL": { + "offset": 7, + "size": 1 + }, + "SM2_TXNFULL": { + "offset": 6, + "size": 1 + }, + "SM1_TXNFULL": { + "offset": 5, + "size": 1 + }, + "SM0_TXNFULL": { + "offset": 4, + "size": 1 + }, + "SM3_RXNEMPTY": { + "offset": 3, + "size": 1 + }, + "SM2_RXNEMPTY": { + "offset": 2, + "size": 1 + }, + "SM1_RXNEMPTY": { + "offset": 1, + "size": 1 + }, + "SM0_RXNEMPTY": { + "offset": 0, + "size": 1 + } + } + } + }, + "IRQ1_INTF": { + "description": "Interrupt Force for irq1", + "offset": 316, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SM3": { + "offset": 11, + "size": 1 + }, + "SM2": { + "offset": 10, + "size": 1 + }, + "SM1": { + "offset": 9, + "size": 1 + }, + "SM0": { + "offset": 8, + "size": 1 + }, + "SM3_TXNFULL": { + "offset": 7, + "size": 1 + }, + "SM2_TXNFULL": { + "offset": 6, + "size": 1 + }, + "SM1_TXNFULL": { + "offset": 5, + "size": 1 + }, + "SM0_TXNFULL": { + "offset": 4, + "size": 1 + }, + "SM3_RXNEMPTY": { + "offset": 3, + "size": 1 + }, + "SM2_RXNEMPTY": { + "offset": 2, + "size": 1 + }, + "SM1_RXNEMPTY": { + "offset": 1, + "size": 1 + }, + "SM0_RXNEMPTY": { + "offset": 0, + "size": 1 + } + } + } + }, + "IRQ1_INTS": { + "description": "Interrupt status after masking & forcing for irq1", + "offset": 320, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "SM3": { + "offset": 11, + "size": 1, + "access": "read-only" + }, + "SM2": { + "offset": 10, + "size": 1, + "access": "read-only" + }, + "SM1": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "SM0": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "SM3_TXNFULL": { + "offset": 7, + "size": 1, + "access": "read-only" + }, + "SM2_TXNFULL": { + "offset": 6, + "size": 1, + "access": "read-only" + }, + "SM1_TXNFULL": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "SM0_TXNFULL": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "SM3_RXNEMPTY": { + "offset": 3, + "size": 1, + "access": "read-only" + }, + "SM2_RXNEMPTY": { + "offset": 2, + "size": 1, + "access": "read-only" + }, + "SM1_RXNEMPTY": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "SM0_RXNEMPTY": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + } + } + } + }, + "ADC": { + "description": "Control and data interface to SAR ADC", + "children": { + "registers": { + "CS": { + "description": "ADC Control and Status", + "offset": 0, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "RROBIN": { + "description": "Round-robin sampling. 1 bit per channel. Set all bits to 0 to disable.\\n\n Otherwise, the ADC will cycle through each enabled channel in a round-robin fashion.\\n\n The first channel to be sampled will be the one currently indicated by AINSEL.\\n\n AINSEL will be updated after each conversion with the newly-selected channel.", + "offset": 16, + "size": 5 + }, + "AINSEL": { + "description": "Select analog mux input. Updated automatically in round-robin mode.", + "offset": 12, + "size": 3 + }, + "ERR_STICKY": { + "description": "Some past ADC conversion encountered an error. Write 1 to clear.", + "offset": 10, + "size": 1 + }, + "ERR": { + "description": "The most recent ADC conversion encountered an error; result is undefined or noisy.", + "offset": 9, + "size": 1, + "access": "read-only" + }, + "READY": { + "description": "1 if the ADC is ready to start a new conversion. Implies any previous conversion has completed.\\n\n 0 whilst conversion in progress.", + "offset": 8, + "size": 1, + "access": "read-only" + }, + "START_MANY": { + "description": "Continuously perform conversions whilst this bit is 1. A new conversion will start immediately after the previous finishes.", + "offset": 3, + "size": 1 + }, + "START_ONCE": { + "description": "Start a single conversion. Self-clearing. Ignored if start_many is asserted.", + "offset": 2, + "size": 1 + }, + "TS_EN": { + "description": "Power on temperature sensor. 1 - enabled. 0 - disabled.", + "offset": 1, + "size": 1 + }, + "EN": { + "description": "Power on ADC and enable its clock.\\n\n 1 - enabled. 0 - disabled.", + "offset": 0, + "size": 1 + } + } + } + }, + "RESULT": { + "description": "Result of most recent ADC conversion", + "offset": 4, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "RESULT": { + "offset": 0, + "size": 12, + "access": "read-only" + } + } + } + }, + "FCS": { + "description": "FIFO control and status", + "offset": 8, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "THRESH": { + "description": "DREQ/IRQ asserted when level >= threshold", + "offset": 24, + "size": 4 + }, + "LEVEL": { + "description": "The number of conversion results currently waiting in the FIFO", + "offset": 16, + "size": 4, + "access": "read-only" + }, + "OVER": { + "description": "1 if the FIFO has been overflowed. Write 1 to clear.", + "offset": 11, + "size": 1 + }, + "UNDER": { + "description": "1 if the FIFO has been underflowed. Write 1 to clear.", + "offset": 10, + "size": 1 + }, + "FULL": { + "offset": 9, + "size": 1, + "access": "read-only" + }, + "EMPTY": { + "offset": 8, + "size": 1, + "access": "read-only" + }, + "DREQ_EN": { + "description": "If 1: assert DMA requests when FIFO contains data", + "offset": 3, + "size": 1 + }, + "ERR": { + "description": "If 1: conversion error bit appears in the FIFO alongside the result", + "offset": 2, + "size": 1 + }, + "SHIFT": { + "description": "If 1: FIFO results are right-shifted to be one byte in size. Enables DMA to byte buffers.", + "offset": 1, + "size": 1 + }, + "EN": { + "description": "If 1: write result to the FIFO after each conversion.", + "offset": 0, + "size": 1 + } + } + } + }, + "FIFO": { + "description": "Conversion result FIFO", + "offset": 12, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ERR": { + "description": "1 if this particular sample experienced a conversion error. Remains in the same location if the sample is shifted.", + "offset": 15, + "size": 1, + "access": "read-only" + }, + "VAL": { + "offset": 0, + "size": 12, + "access": "read-only" + } + } + } + }, + "DIV": { + "description": "Clock divider. If non-zero, CS_START_MANY will start conversions\\n\n at regular intervals rather than back-to-back.\\n\n The divider is reset when either of these fields are written.\\n\n Total period is 1 + INT + FRAC / 256", + "offset": 16, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INT": { + "description": "Integer part of clock divisor.", + "offset": 8, + "size": 16 + }, + "FRAC": { + "description": "Fractional part of clock divisor. First-order delta-sigma.", + "offset": 0, + "size": 8 + } + } + } + }, + "INTR": { + "description": "Raw Interrupts", + "offset": 20, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FIFO": { + "description": "Triggered when the sample FIFO reaches a certain level.\\n\n This level can be programmed via the FCS_THRESH field.", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "INTE": { + "description": "Interrupt Enable", + "offset": 24, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FIFO": { + "description": "Triggered when the sample FIFO reaches a certain level.\\n\n This level can be programmed via the FCS_THRESH field.", + "offset": 0, + "size": 1 + } + } + } + }, + "INTF": { + "description": "Interrupt Force", + "offset": 28, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FIFO": { + "description": "Triggered when the sample FIFO reaches a certain level.\\n\n This level can be programmed via the FCS_THRESH field.", + "offset": 0, + "size": 1 + } + } + } + }, + "INTS": { + "description": "Interrupt status after masking & forcing", + "offset": 32, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FIFO": { + "description": "Triggered when the sample FIFO reaches a certain level.\\n\n This level can be programmed via the FCS_THRESH field.", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + } + } + } + }, + "PWM": { + "description": "Simple PWM", + "children": { + "registers": { + "CH0_CSR": { + "description": "Control and status register", + "offset": 0, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "PH_ADV": { + "description": "Advance the phase of the counter by 1 count, while it is running.\\n\n Self-clearing. Write a 1, and poll until low. Counter must be running\\n\n at less than full speed (div_int + div_frac / 16 > 1)", + "offset": 7, + "size": 1 + }, + "PH_RET": { + "description": "Retard the phase of the counter by 1 count, while it is running.\\n\n Self-clearing. Write a 1, and poll until low. Counter must be running.", + "offset": 6, + "size": 1 + }, + "DIVMODE": { + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "div": { + "description": "Free-running counting at rate dictated by fractional divider", + "value": 0 + }, + "level": { + "description": "Fractional divider operation is gated by the PWM B pin.", + "value": 1 + }, + "rise": { + "description": "Counter advances with each rising edge of the PWM B pin.", + "value": 2 + }, + "fall": { + "description": "Counter advances with each falling edge of the PWM B pin.", + "value": 3 + } + } + } + } + }, + "B_INV": { + "description": "Invert output B", + "offset": 3, + "size": 1 + }, + "A_INV": { + "description": "Invert output A", + "offset": 2, + "size": 1 + }, + "PH_CORRECT": { + "description": "1: Enable phase-correct modulation. 0: Trailing-edge", + "offset": 1, + "size": 1 + }, + "EN": { + "description": "Enable the PWM channel.", + "offset": 0, + "size": 1 + } + } + } + }, + "CH0_DIV": { + "description": "INT and FRAC form a fixed-point fractional number.\\n\n Counting rate is system clock frequency divided by this number.\\n\n Fractional division uses simple 1st-order sigma-delta.", + "offset": 4, + "size": 32, + "reset_value": 16, + "children": { + "fields": { + "INT": { + "offset": 4, + "size": 8 + }, + "FRAC": { + "offset": 0, + "size": 4 + } + } + } + }, + "CH0_CTR": { + "description": "Direct access to the PWM counter", + "offset": 8, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CH0_CTR": { + "offset": 0, + "size": 16 + } + } + } + }, + "CH0_CC": { + "description": "Counter compare values", + "offset": 12, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "B": { + "offset": 16, + "size": 16 + }, + "A": { + "offset": 0, + "size": 16 + } + } + } + }, + "CH0_TOP": { + "description": "Counter wrap value", + "offset": 16, + "size": 32, + "reset_value": 65535, + "children": { + "fields": { + "CH0_TOP": { + "offset": 0, + "size": 16 + } + } + } + }, + "CH1_CSR": { + "description": "Control and status register", + "offset": 20, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "PH_ADV": { + "description": "Advance the phase of the counter by 1 count, while it is running.\\n\n Self-clearing. Write a 1, and poll until low. Counter must be running\\n\n at less than full speed (div_int + div_frac / 16 > 1)", + "offset": 7, + "size": 1 + }, + "PH_RET": { + "description": "Retard the phase of the counter by 1 count, while it is running.\\n\n Self-clearing. Write a 1, and poll until low. Counter must be running.", + "offset": 6, + "size": 1 + }, + "DIVMODE": { + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "div": { + "description": "Free-running counting at rate dictated by fractional divider", + "value": 0 + }, + "level": { + "description": "Fractional divider operation is gated by the PWM B pin.", + "value": 1 + }, + "rise": { + "description": "Counter advances with each rising edge of the PWM B pin.", + "value": 2 + }, + "fall": { + "description": "Counter advances with each falling edge of the PWM B pin.", + "value": 3 + } + } + } + } + }, + "B_INV": { + "description": "Invert output B", + "offset": 3, + "size": 1 + }, + "A_INV": { + "description": "Invert output A", + "offset": 2, + "size": 1 + }, + "PH_CORRECT": { + "description": "1: Enable phase-correct modulation. 0: Trailing-edge", + "offset": 1, + "size": 1 + }, + "EN": { + "description": "Enable the PWM channel.", + "offset": 0, + "size": 1 + } + } + } + }, + "CH1_DIV": { + "description": "INT and FRAC form a fixed-point fractional number.\\n\n Counting rate is system clock frequency divided by this number.\\n\n Fractional division uses simple 1st-order sigma-delta.", + "offset": 24, + "size": 32, + "reset_value": 16, + "children": { + "fields": { + "INT": { + "offset": 4, + "size": 8 + }, + "FRAC": { + "offset": 0, + "size": 4 + } + } + } + }, + "CH1_CTR": { + "description": "Direct access to the PWM counter", + "offset": 28, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CH1_CTR": { + "offset": 0, + "size": 16 + } + } + } + }, + "CH1_CC": { + "description": "Counter compare values", + "offset": 32, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "B": { + "offset": 16, + "size": 16 + }, + "A": { + "offset": 0, + "size": 16 + } + } + } + }, + "CH1_TOP": { + "description": "Counter wrap value", + "offset": 36, + "size": 32, + "reset_value": 65535, + "children": { + "fields": { + "CH1_TOP": { + "offset": 0, + "size": 16 + } + } + } + }, + "CH2_CSR": { + "description": "Control and status register", + "offset": 40, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "PH_ADV": { + "description": "Advance the phase of the counter by 1 count, while it is running.\\n\n Self-clearing. Write a 1, and poll until low. Counter must be running\\n\n at less than full speed (div_int + div_frac / 16 > 1)", + "offset": 7, + "size": 1 + }, + "PH_RET": { + "description": "Retard the phase of the counter by 1 count, while it is running.\\n\n Self-clearing. Write a 1, and poll until low. Counter must be running.", + "offset": 6, + "size": 1 + }, + "DIVMODE": { + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "div": { + "description": "Free-running counting at rate dictated by fractional divider", + "value": 0 + }, + "level": { + "description": "Fractional divider operation is gated by the PWM B pin.", + "value": 1 + }, + "rise": { + "description": "Counter advances with each rising edge of the PWM B pin.", + "value": 2 + }, + "fall": { + "description": "Counter advances with each falling edge of the PWM B pin.", + "value": 3 + } + } + } + } + }, + "B_INV": { + "description": "Invert output B", + "offset": 3, + "size": 1 + }, + "A_INV": { + "description": "Invert output A", + "offset": 2, + "size": 1 + }, + "PH_CORRECT": { + "description": "1: Enable phase-correct modulation. 0: Trailing-edge", + "offset": 1, + "size": 1 + }, + "EN": { + "description": "Enable the PWM channel.", + "offset": 0, + "size": 1 + } + } + } + }, + "CH2_DIV": { + "description": "INT and FRAC form a fixed-point fractional number.\\n\n Counting rate is system clock frequency divided by this number.\\n\n Fractional division uses simple 1st-order sigma-delta.", + "offset": 44, + "size": 32, + "reset_value": 16, + "children": { + "fields": { + "INT": { + "offset": 4, + "size": 8 + }, + "FRAC": { + "offset": 0, + "size": 4 + } + } + } + }, + "CH2_CTR": { + "description": "Direct access to the PWM counter", + "offset": 48, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CH2_CTR": { + "offset": 0, + "size": 16 + } + } + } + }, + "CH2_CC": { + "description": "Counter compare values", + "offset": 52, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "B": { + "offset": 16, + "size": 16 + }, + "A": { + "offset": 0, + "size": 16 + } + } + } + }, + "CH2_TOP": { + "description": "Counter wrap value", + "offset": 56, + "size": 32, + "reset_value": 65535, + "children": { + "fields": { + "CH2_TOP": { + "offset": 0, + "size": 16 + } + } + } + }, + "CH3_CSR": { + "description": "Control and status register", + "offset": 60, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "PH_ADV": { + "description": "Advance the phase of the counter by 1 count, while it is running.\\n\n Self-clearing. Write a 1, and poll until low. Counter must be running\\n\n at less than full speed (div_int + div_frac / 16 > 1)", + "offset": 7, + "size": 1 + }, + "PH_RET": { + "description": "Retard the phase of the counter by 1 count, while it is running.\\n\n Self-clearing. Write a 1, and poll until low. Counter must be running.", + "offset": 6, + "size": 1 + }, + "DIVMODE": { + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "div": { + "description": "Free-running counting at rate dictated by fractional divider", + "value": 0 + }, + "level": { + "description": "Fractional divider operation is gated by the PWM B pin.", + "value": 1 + }, + "rise": { + "description": "Counter advances with each rising edge of the PWM B pin.", + "value": 2 + }, + "fall": { + "description": "Counter advances with each falling edge of the PWM B pin.", + "value": 3 + } + } + } + } + }, + "B_INV": { + "description": "Invert output B", + "offset": 3, + "size": 1 + }, + "A_INV": { + "description": "Invert output A", + "offset": 2, + "size": 1 + }, + "PH_CORRECT": { + "description": "1: Enable phase-correct modulation. 0: Trailing-edge", + "offset": 1, + "size": 1 + }, + "EN": { + "description": "Enable the PWM channel.", + "offset": 0, + "size": 1 + } + } + } + }, + "CH3_DIV": { + "description": "INT and FRAC form a fixed-point fractional number.\\n\n Counting rate is system clock frequency divided by this number.\\n\n Fractional division uses simple 1st-order sigma-delta.", + "offset": 64, + "size": 32, + "reset_value": 16, + "children": { + "fields": { + "INT": { + "offset": 4, + "size": 8 + }, + "FRAC": { + "offset": 0, + "size": 4 + } + } + } + }, + "CH3_CTR": { + "description": "Direct access to the PWM counter", + "offset": 68, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CH3_CTR": { + "offset": 0, + "size": 16 + } + } + } + }, + "CH3_CC": { + "description": "Counter compare values", + "offset": 72, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "B": { + "offset": 16, + "size": 16 + }, + "A": { + "offset": 0, + "size": 16 + } + } + } + }, + "CH3_TOP": { + "description": "Counter wrap value", + "offset": 76, + "size": 32, + "reset_value": 65535, + "children": { + "fields": { + "CH3_TOP": { + "offset": 0, + "size": 16 + } + } + } + }, + "CH4_CSR": { + "description": "Control and status register", + "offset": 80, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "PH_ADV": { + "description": "Advance the phase of the counter by 1 count, while it is running.\\n\n Self-clearing. Write a 1, and poll until low. Counter must be running\\n\n at less than full speed (div_int + div_frac / 16 > 1)", + "offset": 7, + "size": 1 + }, + "PH_RET": { + "description": "Retard the phase of the counter by 1 count, while it is running.\\n\n Self-clearing. Write a 1, and poll until low. Counter must be running.", + "offset": 6, + "size": 1 + }, + "DIVMODE": { + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "div": { + "description": "Free-running counting at rate dictated by fractional divider", + "value": 0 + }, + "level": { + "description": "Fractional divider operation is gated by the PWM B pin.", + "value": 1 + }, + "rise": { + "description": "Counter advances with each rising edge of the PWM B pin.", + "value": 2 + }, + "fall": { + "description": "Counter advances with each falling edge of the PWM B pin.", + "value": 3 + } + } + } + } + }, + "B_INV": { + "description": "Invert output B", + "offset": 3, + "size": 1 + }, + "A_INV": { + "description": "Invert output A", + "offset": 2, + "size": 1 + }, + "PH_CORRECT": { + "description": "1: Enable phase-correct modulation. 0: Trailing-edge", + "offset": 1, + "size": 1 + }, + "EN": { + "description": "Enable the PWM channel.", + "offset": 0, + "size": 1 + } + } + } + }, + "CH4_DIV": { + "description": "INT and FRAC form a fixed-point fractional number.\\n\n Counting rate is system clock frequency divided by this number.\\n\n Fractional division uses simple 1st-order sigma-delta.", + "offset": 84, + "size": 32, + "reset_value": 16, + "children": { + "fields": { + "INT": { + "offset": 4, + "size": 8 + }, + "FRAC": { + "offset": 0, + "size": 4 + } + } + } + }, + "CH4_CTR": { + "description": "Direct access to the PWM counter", + "offset": 88, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CH4_CTR": { + "offset": 0, + "size": 16 + } + } + } + }, + "CH4_CC": { + "description": "Counter compare values", + "offset": 92, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "B": { + "offset": 16, + "size": 16 + }, + "A": { + "offset": 0, + "size": 16 + } + } + } + }, + "CH4_TOP": { + "description": "Counter wrap value", + "offset": 96, + "size": 32, + "reset_value": 65535, + "children": { + "fields": { + "CH4_TOP": { + "offset": 0, + "size": 16 + } + } + } + }, + "CH5_CSR": { + "description": "Control and status register", + "offset": 100, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "PH_ADV": { + "description": "Advance the phase of the counter by 1 count, while it is running.\\n\n Self-clearing. Write a 1, and poll until low. Counter must be running\\n\n at less than full speed (div_int + div_frac / 16 > 1)", + "offset": 7, + "size": 1 + }, + "PH_RET": { + "description": "Retard the phase of the counter by 1 count, while it is running.\\n\n Self-clearing. Write a 1, and poll until low. Counter must be running.", + "offset": 6, + "size": 1 + }, + "DIVMODE": { + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "div": { + "description": "Free-running counting at rate dictated by fractional divider", + "value": 0 + }, + "level": { + "description": "Fractional divider operation is gated by the PWM B pin.", + "value": 1 + }, + "rise": { + "description": "Counter advances with each rising edge of the PWM B pin.", + "value": 2 + }, + "fall": { + "description": "Counter advances with each falling edge of the PWM B pin.", + "value": 3 + } + } + } + } + }, + "B_INV": { + "description": "Invert output B", + "offset": 3, + "size": 1 + }, + "A_INV": { + "description": "Invert output A", + "offset": 2, + "size": 1 + }, + "PH_CORRECT": { + "description": "1: Enable phase-correct modulation. 0: Trailing-edge", + "offset": 1, + "size": 1 + }, + "EN": { + "description": "Enable the PWM channel.", + "offset": 0, + "size": 1 + } + } + } + }, + "CH5_DIV": { + "description": "INT and FRAC form a fixed-point fractional number.\\n\n Counting rate is system clock frequency divided by this number.\\n\n Fractional division uses simple 1st-order sigma-delta.", + "offset": 104, + "size": 32, + "reset_value": 16, + "children": { + "fields": { + "INT": { + "offset": 4, + "size": 8 + }, + "FRAC": { + "offset": 0, + "size": 4 + } + } + } + }, + "CH5_CTR": { + "description": "Direct access to the PWM counter", + "offset": 108, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CH5_CTR": { + "offset": 0, + "size": 16 + } + } + } + }, + "CH5_CC": { + "description": "Counter compare values", + "offset": 112, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "B": { + "offset": 16, + "size": 16 + }, + "A": { + "offset": 0, + "size": 16 + } + } + } + }, + "CH5_TOP": { + "description": "Counter wrap value", + "offset": 116, + "size": 32, + "reset_value": 65535, + "children": { + "fields": { + "CH5_TOP": { + "offset": 0, + "size": 16 + } + } + } + }, + "CH6_CSR": { + "description": "Control and status register", + "offset": 120, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "PH_ADV": { + "description": "Advance the phase of the counter by 1 count, while it is running.\\n\n Self-clearing. Write a 1, and poll until low. Counter must be running\\n\n at less than full speed (div_int + div_frac / 16 > 1)", + "offset": 7, + "size": 1 + }, + "PH_RET": { + "description": "Retard the phase of the counter by 1 count, while it is running.\\n\n Self-clearing. Write a 1, and poll until low. Counter must be running.", + "offset": 6, + "size": 1 + }, + "DIVMODE": { + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "div": { + "description": "Free-running counting at rate dictated by fractional divider", + "value": 0 + }, + "level": { + "description": "Fractional divider operation is gated by the PWM B pin.", + "value": 1 + }, + "rise": { + "description": "Counter advances with each rising edge of the PWM B pin.", + "value": 2 + }, + "fall": { + "description": "Counter advances with each falling edge of the PWM B pin.", + "value": 3 + } + } + } + } + }, + "B_INV": { + "description": "Invert output B", + "offset": 3, + "size": 1 + }, + "A_INV": { + "description": "Invert output A", + "offset": 2, + "size": 1 + }, + "PH_CORRECT": { + "description": "1: Enable phase-correct modulation. 0: Trailing-edge", + "offset": 1, + "size": 1 + }, + "EN": { + "description": "Enable the PWM channel.", + "offset": 0, + "size": 1 + } + } + } + }, + "CH6_DIV": { + "description": "INT and FRAC form a fixed-point fractional number.\\n\n Counting rate is system clock frequency divided by this number.\\n\n Fractional division uses simple 1st-order sigma-delta.", + "offset": 124, + "size": 32, + "reset_value": 16, + "children": { + "fields": { + "INT": { + "offset": 4, + "size": 8 + }, + "FRAC": { + "offset": 0, + "size": 4 + } + } + } + }, + "CH6_CTR": { + "description": "Direct access to the PWM counter", + "offset": 128, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CH6_CTR": { + "offset": 0, + "size": 16 + } + } + } + }, + "CH6_CC": { + "description": "Counter compare values", + "offset": 132, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "B": { + "offset": 16, + "size": 16 + }, + "A": { + "offset": 0, + "size": 16 + } + } + } + }, + "CH6_TOP": { + "description": "Counter wrap value", + "offset": 136, + "size": 32, + "reset_value": 65535, + "children": { + "fields": { + "CH6_TOP": { + "offset": 0, + "size": 16 + } + } + } + }, + "CH7_CSR": { + "description": "Control and status register", + "offset": 140, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "PH_ADV": { + "description": "Advance the phase of the counter by 1 count, while it is running.\\n\n Self-clearing. Write a 1, and poll until low. Counter must be running\\n\n at less than full speed (div_int + div_frac / 16 > 1)", + "offset": 7, + "size": 1 + }, + "PH_RET": { + "description": "Retard the phase of the counter by 1 count, while it is running.\\n\n Self-clearing. Write a 1, and poll until low. Counter must be running.", + "offset": 6, + "size": 1 + }, + "DIVMODE": { + "offset": 4, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "div": { + "description": "Free-running counting at rate dictated by fractional divider", + "value": 0 + }, + "level": { + "description": "Fractional divider operation is gated by the PWM B pin.", + "value": 1 + }, + "rise": { + "description": "Counter advances with each rising edge of the PWM B pin.", + "value": 2 + }, + "fall": { + "description": "Counter advances with each falling edge of the PWM B pin.", + "value": 3 + } + } + } + } + }, + "B_INV": { + "description": "Invert output B", + "offset": 3, + "size": 1 + }, + "A_INV": { + "description": "Invert output A", + "offset": 2, + "size": 1 + }, + "PH_CORRECT": { + "description": "1: Enable phase-correct modulation. 0: Trailing-edge", + "offset": 1, + "size": 1 + }, + "EN": { + "description": "Enable the PWM channel.", + "offset": 0, + "size": 1 + } + } + } + }, + "CH7_DIV": { + "description": "INT and FRAC form a fixed-point fractional number.\\n\n Counting rate is system clock frequency divided by this number.\\n\n Fractional division uses simple 1st-order sigma-delta.", + "offset": 144, + "size": 32, + "reset_value": 16, + "children": { + "fields": { + "INT": { + "offset": 4, + "size": 8 + }, + "FRAC": { + "offset": 0, + "size": 4 + } + } + } + }, + "CH7_CTR": { + "description": "Direct access to the PWM counter", + "offset": 148, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CH7_CTR": { + "offset": 0, + "size": 16 + } + } + } + }, + "CH7_CC": { + "description": "Counter compare values", + "offset": 152, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "B": { + "offset": 16, + "size": 16 + }, + "A": { + "offset": 0, + "size": 16 + } + } + } + }, + "CH7_TOP": { + "description": "Counter wrap value", + "offset": 156, + "size": 32, + "reset_value": 65535, + "children": { + "fields": { + "CH7_TOP": { + "offset": 0, + "size": 16 + } + } + } + }, + "EN": { + "description": "This register aliases the CSR_EN bits for all channels.\\n\n Writing to this register allows multiple channels to be enabled\\n\n or disabled simultaneously, so they can run in perfect sync.\\n\n For each channel, there is only one physical EN register bit,\\n\n which can be accessed through here or CHx_CSR.", + "offset": 160, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CH7": { + "offset": 7, + "size": 1 + }, + "CH6": { + "offset": 6, + "size": 1 + }, + "CH5": { + "offset": 5, + "size": 1 + }, + "CH4": { + "offset": 4, + "size": 1 + }, + "CH3": { + "offset": 3, + "size": 1 + }, + "CH2": { + "offset": 2, + "size": 1 + }, + "CH1": { + "offset": 1, + "size": 1 + }, + "CH0": { + "offset": 0, + "size": 1 + } + } + } + }, + "INTR": { + "description": "Raw Interrupts", + "offset": 164, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CH7": { + "offset": 7, + "size": 1 + }, + "CH6": { + "offset": 6, + "size": 1 + }, + "CH5": { + "offset": 5, + "size": 1 + }, + "CH4": { + "offset": 4, + "size": 1 + }, + "CH3": { + "offset": 3, + "size": 1 + }, + "CH2": { + "offset": 2, + "size": 1 + }, + "CH1": { + "offset": 1, + "size": 1 + }, + "CH0": { + "offset": 0, + "size": 1 + } + } + } + }, + "INTE": { + "description": "Interrupt Enable", + "offset": 168, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CH7": { + "offset": 7, + "size": 1 + }, + "CH6": { + "offset": 6, + "size": 1 + }, + "CH5": { + "offset": 5, + "size": 1 + }, + "CH4": { + "offset": 4, + "size": 1 + }, + "CH3": { + "offset": 3, + "size": 1 + }, + "CH2": { + "offset": 2, + "size": 1 + }, + "CH1": { + "offset": 1, + "size": 1 + }, + "CH0": { + "offset": 0, + "size": 1 + } + } + } + }, + "INTF": { + "description": "Interrupt Force", + "offset": 172, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CH7": { + "offset": 7, + "size": 1 + }, + "CH6": { + "offset": 6, + "size": 1 + }, + "CH5": { + "offset": 5, + "size": 1 + }, + "CH4": { + "offset": 4, + "size": 1 + }, + "CH3": { + "offset": 3, + "size": 1 + }, + "CH2": { + "offset": 2, + "size": 1 + }, + "CH1": { + "offset": 1, + "size": 1 + }, + "CH0": { + "offset": 0, + "size": 1 + } + } + } + }, + "INTS": { + "description": "Interrupt status after masking & forcing", + "offset": 176, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CH7": { + "offset": 7, + "size": 1, + "access": "read-only" + }, + "CH6": { + "offset": 6, + "size": 1, + "access": "read-only" + }, + "CH5": { + "offset": 5, + "size": 1, + "access": "read-only" + }, + "CH4": { + "offset": 4, + "size": 1, + "access": "read-only" + }, + "CH3": { + "offset": 3, + "size": 1, + "access": "read-only" + }, + "CH2": { + "offset": 2, + "size": 1, + "access": "read-only" + }, + "CH1": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "CH0": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + } + } + } + }, + "TIMER": { + "description": "Controls time and alarms\\n\n time is a 64 bit value indicating the time in usec since power-on\\n\n timeh is the top 32 bits of time & timel is the bottom 32 bits\\n\n to change time write to timelw before timehw\\n\n to read time read from timelr before timehr\\n\n An alarm is set by setting alarm_enable and writing to the corresponding alarm register\\n\n When an alarm is pending, the corresponding alarm_running signal will be high\\n\n An alarm can be cancelled before it has finished by clearing the alarm_enable\\n\n When an alarm fires, the corresponding alarm_irq is set and alarm_running is cleared\\n\n To clear the interrupt write a 1 to the corresponding alarm_irq", + "children": { + "registers": { + "TIMEHW": { + "description": "Write to bits 63:32 of time\\n\n always write timelw before timehw", + "offset": 0, + "size": 32, + "reset_value": 0, + "access": "write-only" + }, + "TIMELW": { + "description": "Write to bits 31:0 of time\\n\n writes do not get copied to time until timehw is written", + "offset": 4, + "size": 32, + "reset_value": 0, + "access": "write-only" + }, + "TIMEHR": { + "description": "Read from bits 63:32 of time\\n\n always read timelr before timehr", + "offset": 8, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "TIMELR": { + "description": "Read from bits 31:0 of time", + "offset": 12, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "ALARM0": { + "description": "Arm alarm 0, and configure the time it will fire.\\n\n Once armed, the alarm fires when TIMER_ALARM0 == TIMELR.\\n\n The alarm will disarm itself once it fires, and can\\n\n be disarmed early using the ARMED status register.", + "offset": 16, + "size": 32, + "reset_value": 0 + }, + "ALARM1": { + "description": "Arm alarm 1, and configure the time it will fire.\\n\n Once armed, the alarm fires when TIMER_ALARM1 == TIMELR.\\n\n The alarm will disarm itself once it fires, and can\\n\n be disarmed early using the ARMED status register.", + "offset": 20, + "size": 32, + "reset_value": 0 + }, + "ALARM2": { + "description": "Arm alarm 2, and configure the time it will fire.\\n\n Once armed, the alarm fires when TIMER_ALARM2 == TIMELR.\\n\n The alarm will disarm itself once it fires, and can\\n\n be disarmed early using the ARMED status register.", + "offset": 24, + "size": 32, + "reset_value": 0 + }, + "ALARM3": { + "description": "Arm alarm 3, and configure the time it will fire.\\n\n Once armed, the alarm fires when TIMER_ALARM3 == TIMELR.\\n\n The alarm will disarm itself once it fires, and can\\n\n be disarmed early using the ARMED status register.", + "offset": 28, + "size": 32, + "reset_value": 0 + }, + "ARMED": { + "description": "Indicates the armed/disarmed status of each alarm.\\n\n A write to the corresponding ALARMx register arms the alarm.\\n\n Alarms automatically disarm upon firing, but writing ones here\\n\n will disarm immediately without waiting to fire.", + "offset": 32, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ARMED": { + "offset": 0, + "size": 4 + } + } + } + }, + "TIMERAWH": { + "description": "Raw read from bits 63:32 of time (no side effects)", + "offset": 36, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "TIMERAWL": { + "description": "Raw read from bits 31:0 of time (no side effects)", + "offset": 40, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "DBGPAUSE": { + "description": "Set bits high to enable pause when the corresponding debug ports are active", + "offset": 44, + "size": 32, + "reset_value": 7, + "children": { + "fields": { + "DBG1": { + "description": "Pause when processor 1 is in debug mode", + "offset": 2, + "size": 1 + }, + "DBG0": { + "description": "Pause when processor 0 is in debug mode", + "offset": 1, + "size": 1 + } + } + } + }, + "PAUSE": { + "description": "Set high to pause the timer", + "offset": 48, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "PAUSE": { + "offset": 0, + "size": 1 + } + } + } + }, + "INTR": { + "description": "Raw Interrupts", + "offset": 52, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ALARM_3": { + "offset": 3, + "size": 1 + }, + "ALARM_2": { + "offset": 2, + "size": 1 + }, + "ALARM_1": { + "offset": 1, + "size": 1 + }, + "ALARM_0": { + "offset": 0, + "size": 1 + } + } + } + }, + "INTE": { + "description": "Interrupt Enable", + "offset": 56, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ALARM_3": { + "offset": 3, + "size": 1 + }, + "ALARM_2": { + "offset": 2, + "size": 1 + }, + "ALARM_1": { + "offset": 1, + "size": 1 + }, + "ALARM_0": { + "offset": 0, + "size": 1 + } + } + } + }, + "INTF": { + "description": "Interrupt Force", + "offset": 60, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ALARM_3": { + "offset": 3, + "size": 1 + }, + "ALARM_2": { + "offset": 2, + "size": 1 + }, + "ALARM_1": { + "offset": 1, + "size": 1 + }, + "ALARM_0": { + "offset": 0, + "size": 1 + } + } + } + }, + "INTS": { + "description": "Interrupt status after masking & forcing", + "offset": 64, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ALARM_3": { + "offset": 3, + "size": 1, + "access": "read-only" + }, + "ALARM_2": { + "offset": 2, + "size": 1, + "access": "read-only" + }, + "ALARM_1": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "ALARM_0": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + } + } + } + }, + "WATCHDOG": { + "children": { + "registers": { + "CTRL": { + "description": "Watchdog control\\n\n The rst_wdsel register determines which subsystems are reset when the watchdog is triggered.\\n\n The watchdog can be triggered in software.", + "offset": 0, + "size": 32, + "reset_value": 117440512, + "children": { + "fields": { + "TRIGGER": { + "description": "Trigger a watchdog reset", + "offset": 31, + "size": 1 + }, + "ENABLE": { + "description": "When not enabled the watchdog timer is paused", + "offset": 30, + "size": 1 + }, + "PAUSE_DBG1": { + "description": "Pause the watchdog timer when processor 1 is in debug mode", + "offset": 26, + "size": 1 + }, + "PAUSE_DBG0": { + "description": "Pause the watchdog timer when processor 0 is in debug mode", + "offset": 25, + "size": 1 + }, + "PAUSE_JTAG": { + "description": "Pause the watchdog timer when JTAG is accessing the bus fabric", + "offset": 24, + "size": 1 + }, + "TIME": { + "description": "Indicates the number of ticks / 2 (see errata RP2040-E1) before a watchdog reset will be triggered", + "offset": 0, + "size": 24, + "access": "read-only" + } + } + } + }, + "LOAD": { + "description": "Load the watchdog timer. The maximum setting is 0xffffff which corresponds to 0xffffff / 2 ticks before triggering a watchdog reset (see errata RP2040-E1).", + "offset": 4, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "LOAD": { + "offset": 0, + "size": 24, + "access": "write-only" + } + } + } + }, + "REASON": { + "description": "Logs the reason for the last reset. Both bits are zero for the case of a hardware reset.", + "offset": 8, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FORCE": { + "offset": 1, + "size": 1, + "access": "read-only" + }, + "TIMER": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "SCRATCH0": { + "description": "Scratch register. Information persists through soft reset of the chip.", + "offset": 12, + "size": 32, + "reset_value": 0 + }, + "SCRATCH1": { + "description": "Scratch register. Information persists through soft reset of the chip.", + "offset": 16, + "size": 32, + "reset_value": 0 + }, + "SCRATCH2": { + "description": "Scratch register. Information persists through soft reset of the chip.", + "offset": 20, + "size": 32, + "reset_value": 0 + }, + "SCRATCH3": { + "description": "Scratch register. Information persists through soft reset of the chip.", + "offset": 24, + "size": 32, + "reset_value": 0 + }, + "SCRATCH4": { + "description": "Scratch register. Information persists through soft reset of the chip.", + "offset": 28, + "size": 32, + "reset_value": 0 + }, + "SCRATCH5": { + "description": "Scratch register. Information persists through soft reset of the chip.", + "offset": 32, + "size": 32, + "reset_value": 0 + }, + "SCRATCH6": { + "description": "Scratch register. Information persists through soft reset of the chip.", + "offset": 36, + "size": 32, + "reset_value": 0 + }, + "SCRATCH7": { + "description": "Scratch register. Information persists through soft reset of the chip.", + "offset": 40, + "size": 32, + "reset_value": 0 + }, + "TICK": { + "description": "Controls the tick generator", + "offset": 44, + "size": 32, + "reset_value": 512, + "children": { + "fields": { + "COUNT": { + "description": "Count down timer: the remaining number clk_tick cycles before the next tick is generated.", + "offset": 11, + "size": 9, + "access": "read-only" + }, + "RUNNING": { + "description": "Is the tick generator running?", + "offset": 10, + "size": 1, + "access": "read-only" + }, + "ENABLE": { + "description": "start / stop tick generation", + "offset": 9, + "size": 1 + }, + "CYCLES": { + "description": "Total number of clk_tick cycles before the next tick.", + "offset": 0, + "size": 9 + } + } + } + } + } + } + }, + "RTC": { + "description": "Register block to control RTC", + "children": { + "registers": { + "CLKDIV_M1": { + "description": "Divider minus 1 for the 1 second counter. Safe to change the value when RTC is not enabled.", + "offset": 0, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CLKDIV_M1": { + "offset": 0, + "size": 16 + } + } + } + }, + "SETUP_0": { + "description": "RTC setup register 0", + "offset": 4, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "YEAR": { + "description": "Year", + "offset": 12, + "size": 12 + }, + "MONTH": { + "description": "Month (1..12)", + "offset": 8, + "size": 4 + }, + "DAY": { + "description": "Day of the month (1..31)", + "offset": 0, + "size": 5 + } + } + } + }, + "SETUP_1": { + "description": "RTC setup register 1", + "offset": 8, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "DOTW": { + "description": "Day of the week: 1-Monday...0-Sunday ISO 8601 mod 7", + "offset": 24, + "size": 3 + }, + "HOUR": { + "description": "Hours", + "offset": 16, + "size": 5 + }, + "MIN": { + "description": "Minutes", + "offset": 8, + "size": 6 + }, + "SEC": { + "description": "Seconds", + "offset": 0, + "size": 6 + } + } + } + }, + "CTRL": { + "description": "RTC Control and status", + "offset": 12, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FORCE_NOTLEAPYEAR": { + "description": "If set, leapyear is forced off.\\n\n Useful for years divisible by 100 but not by 400", + "offset": 8, + "size": 1 + }, + "LOAD": { + "description": "Load RTC", + "offset": 4, + "size": 1 + }, + "RTC_ACTIVE": { + "description": "RTC enabled (running)", + "offset": 1, + "size": 1, + "access": "read-only" + }, + "RTC_ENABLE": { + "description": "Enable RTC", + "offset": 0, + "size": 1 + } + } + } + }, + "IRQ_SETUP_0": { + "description": "Interrupt setup register 0", + "offset": 16, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "MATCH_ACTIVE": { + "offset": 29, + "size": 1, + "access": "read-only" + }, + "MATCH_ENA": { + "description": "Global match enable. Don't change any other value while this one is enabled", + "offset": 28, + "size": 1 + }, + "YEAR_ENA": { + "description": "Enable year matching", + "offset": 26, + "size": 1 + }, + "MONTH_ENA": { + "description": "Enable month matching", + "offset": 25, + "size": 1 + }, + "DAY_ENA": { + "description": "Enable day matching", + "offset": 24, + "size": 1 + }, + "YEAR": { + "description": "Year", + "offset": 12, + "size": 12 + }, + "MONTH": { + "description": "Month (1..12)", + "offset": 8, + "size": 4 + }, + "DAY": { + "description": "Day of the month (1..31)", + "offset": 0, + "size": 5 + } + } + } + }, + "IRQ_SETUP_1": { + "description": "Interrupt setup register 1", + "offset": 20, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "DOTW_ENA": { + "description": "Enable day of the week matching", + "offset": 31, + "size": 1 + }, + "HOUR_ENA": { + "description": "Enable hour matching", + "offset": 30, + "size": 1 + }, + "MIN_ENA": { + "description": "Enable minute matching", + "offset": 29, + "size": 1 + }, + "SEC_ENA": { + "description": "Enable second matching", + "offset": 28, + "size": 1 + }, + "DOTW": { + "description": "Day of the week", + "offset": 24, + "size": 3 + }, + "HOUR": { + "description": "Hours", + "offset": 16, + "size": 5 + }, + "MIN": { + "description": "Minutes", + "offset": 8, + "size": 6 + }, + "SEC": { + "description": "Seconds", + "offset": 0, + "size": 6 + } + } + } + }, + "RTC_1": { + "description": "RTC register 1.", + "offset": 24, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "YEAR": { + "description": "Year", + "offset": 12, + "size": 12, + "access": "read-only" + }, + "MONTH": { + "description": "Month (1..12)", + "offset": 8, + "size": 4, + "access": "read-only" + }, + "DAY": { + "description": "Day of the month (1..31)", + "offset": 0, + "size": 5, + "access": "read-only" + } + } + } + }, + "RTC_0": { + "description": "RTC register 0\\n\n Read this before RTC 1!", + "offset": 28, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "DOTW": { + "description": "Day of the week", + "offset": 24, + "size": 3, + "access": "read-only" + }, + "HOUR": { + "description": "Hours", + "offset": 16, + "size": 5, + "access": "read-only" + }, + "MIN": { + "description": "Minutes", + "offset": 8, + "size": 6, + "access": "read-only" + }, + "SEC": { + "description": "Seconds", + "offset": 0, + "size": 6, + "access": "read-only" + } + } + } + }, + "INTR": { + "description": "Raw Interrupts", + "offset": 32, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "RTC": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "INTE": { + "description": "Interrupt Enable", + "offset": 36, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "RTC": { + "offset": 0, + "size": 1 + } + } + } + }, + "INTF": { + "description": "Interrupt Force", + "offset": 40, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "RTC": { + "offset": 0, + "size": 1 + } + } + } + }, + "INTS": { + "description": "Interrupt status after masking & forcing", + "offset": 44, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "RTC": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + } + } + } + }, + "ROSC": { + "children": { + "registers": { + "CTRL": { + "description": "Ring Oscillator control", + "offset": 0, + "size": 32, + "reset_value": 2720, + "children": { + "fields": { + "ENABLE": { + "description": "On power-up this field is initialised to ENABLE\\n\n The system clock must be switched to another source before setting this field to DISABLE otherwise the chip will lock up\\n\n The 12-bit code is intended to give some protection against accidental writes. An invalid setting will enable the oscillator.", + "offset": 12, + "size": 12, + "enum": { + "size": 12, + "children": { + "enum_fields": { + "DISABLE": { + "value": 3358 + }, + "ENABLE": { + "value": 4011 + } + } + } + } + }, + "FREQ_RANGE": { + "description": "Controls the number of delay stages in the ROSC ring\\n\n LOW uses stages 0 to 7\\n\n MEDIUM uses stages 0 to 5\\n\n HIGH uses stages 0 to 3\\n\n TOOHIGH uses stages 0 to 1 and should not be used because its frequency exceeds design specifications\\n\n The clock output will not glitch when changing the range up one step at a time\\n\n The clock output will glitch when changing the range down\\n\n Note: the values here are gray coded which is why HIGH comes before TOOHIGH", + "offset": 0, + "size": 12, + "enum": { + "size": 12, + "children": { + "enum_fields": { + "LOW": { + "value": 4004 + }, + "MEDIUM": { + "value": 4005 + }, + "HIGH": { + "value": 4007 + }, + "TOOHIGH": { + "value": 4006 + } + } + } + } + } + } + } + }, + "FREQA": { + "description": "The FREQA & FREQB registers control the frequency by controlling the drive strength of each stage\\n\n The drive strength has 4 levels determined by the number of bits set\\n\n Increasing the number of bits set increases the drive strength and increases the oscillation frequency\\n\n 0 bits set is the default drive strength\\n\n 1 bit set doubles the drive strength\\n\n 2 bits set triples drive strength\\n\n 3 bits set quadruples drive strength", + "offset": 4, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "PASSWD": { + "description": "Set to 0x9696 to apply the settings\\n\n Any other value in this field will set all drive strengths to 0", + "offset": 16, + "size": 16, + "enum": { + "size": 16, + "children": { + "enum_fields": { + "PASS": { + "value": 38550 + } + } + } + } + }, + "DS3": { + "description": "Stage 3 drive strength", + "offset": 12, + "size": 3 + }, + "DS2": { + "description": "Stage 2 drive strength", + "offset": 8, + "size": 3 + }, + "DS1": { + "description": "Stage 1 drive strength", + "offset": 4, + "size": 3 + }, + "DS0": { + "description": "Stage 0 drive strength", + "offset": 0, + "size": 3 + } + } + } + }, + "FREQB": { + "description": "For a detailed description see freqa register", + "offset": 8, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "PASSWD": { + "description": "Set to 0x9696 to apply the settings\\n\n Any other value in this field will set all drive strengths to 0", + "offset": 16, + "size": 16, + "enum": { + "size": 16, + "children": { + "enum_fields": { + "PASS": { + "value": 38550 + } + } + } + } + }, + "DS7": { + "description": "Stage 7 drive strength", + "offset": 12, + "size": 3 + }, + "DS6": { + "description": "Stage 6 drive strength", + "offset": 8, + "size": 3 + }, + "DS5": { + "description": "Stage 5 drive strength", + "offset": 4, + "size": 3 + }, + "DS4": { + "description": "Stage 4 drive strength", + "offset": 0, + "size": 3 + } + } + } + }, + "DORMANT": { + "description": "Ring Oscillator pause control\\n\n This is used to save power by pausing the ROSC\\n\n On power-up this field is initialised to WAKE\\n\n An invalid write will also select WAKE\\n\n Warning: setup the irq before selecting dormant mode", + "offset": 12, + "size": 32, + "reset_value": 0 + }, + "DIV": { + "description": "Controls the output divider", + "offset": 16, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "DIV": { + "description": "set to 0xaa0 + div where\\n\n div = 0 divides by 32\\n\n div = 1-31 divides by div\\n\n any other value sets div=31\\n\n this register resets to div=16", + "offset": 0, + "size": 12, + "enum": { + "size": 12, + "children": { + "enum_fields": { + "PASS": { + "value": 2720 + } + } + } + } + } + } + } + }, + "PHASE": { + "description": "Controls the phase shifted output", + "offset": 20, + "size": 32, + "reset_value": 8, + "children": { + "fields": { + "PASSWD": { + "description": "set to 0xaa\\n\n any other value enables the output with shift=0", + "offset": 4, + "size": 8 + }, + "ENABLE": { + "description": "enable the phase-shifted output\\n\n this can be changed on-the-fly", + "offset": 3, + "size": 1 + }, + "FLIP": { + "description": "invert the phase-shifted output\\n\n this is ignored when div=1", + "offset": 2, + "size": 1 + }, + "SHIFT": { + "description": "phase shift the phase-shifted output by SHIFT input clocks\\n\n this can be changed on-the-fly\\n\n must be set to 0 before setting div=1", + "offset": 0, + "size": 2 + } + } + } + }, + "STATUS": { + "description": "Ring Oscillator Status", + "offset": 24, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "STABLE": { + "description": "Oscillator is running and stable", + "offset": 31, + "size": 1, + "access": "read-only" + }, + "BADWRITE": { + "description": "An invalid value has been written to CTRL_ENABLE or CTRL_FREQ_RANGE or FREQA or FREQB or DIV or PHASE or DORMANT", + "offset": 24, + "size": 1 + }, + "DIV_RUNNING": { + "description": "post-divider is running\\n\n this resets to 0 but transitions to 1 during chip startup", + "offset": 16, + "size": 1, + "access": "read-only" + }, + "ENABLED": { + "description": "Oscillator is enabled but not necessarily running and stable\\n\n this resets to 0 but transitions to 1 during chip startup", + "offset": 12, + "size": 1, + "access": "read-only" + } + } + } + }, + "RANDOMBIT": { + "description": "This just reads the state of the oscillator output so randomness is compromised if the ring oscillator is stopped or run at a harmonic of the bus frequency", + "offset": 28, + "size": 32, + "reset_value": 1, + "children": { + "fields": { + "RANDOMBIT": { + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + }, + "COUNT": { + "description": "A down counter running at the ROSC frequency which counts to zero and stops.\\n\n To start the counter write a non-zero value.\\n\n Can be used for short software pauses when setting up time sensitive hardware.", + "offset": 32, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "COUNT": { + "offset": 0, + "size": 8 + } + } + } + } + } + } + }, + "VREG_AND_CHIP_RESET": { + "description": "control and status for on-chip voltage regulator and chip level reset subsystem", + "children": { + "registers": { + "VREG": { + "description": "Voltage regulator control and status", + "offset": 0, + "size": 32, + "reset_value": 177, + "children": { + "fields": { + "ROK": { + "description": "regulation status\\n\n 0=not in regulation, 1=in regulation", + "offset": 12, + "size": 1, + "access": "read-only" + }, + "VSEL": { + "description": "output voltage select\\n\n 0000 to 0101 - 0.80V\\n\n 0110 - 0.85V\\n\n 0111 - 0.90V\\n\n 1000 - 0.95V\\n\n 1001 - 1.00V\\n\n 1010 - 1.05V\\n\n 1011 - 1.10V (default)\\n\n 1100 - 1.15V\\n\n 1101 - 1.20V\\n\n 1110 - 1.25V\\n\n 1111 - 1.30V", + "offset": 4, + "size": 4 + }, + "HIZ": { + "description": "high impedance mode select\\n\n 0=not in high impedance mode, 1=in high impedance mode", + "offset": 1, + "size": 1 + }, + "EN": { + "description": "enable\\n\n 0=not enabled, 1=enabled", + "offset": 0, + "size": 1 + } + } + } + }, + "BOD": { + "description": "brown-out detection control", + "offset": 4, + "size": 32, + "reset_value": 145, + "children": { + "fields": { + "VSEL": { + "description": "threshold select\\n\n 0000 - 0.473V\\n\n 0001 - 0.516V\\n\n 0010 - 0.559V\\n\n 0011 - 0.602V\\n\n 0100 - 0.645V\\n\n 0101 - 0.688V\\n\n 0110 - 0.731V\\n\n 0111 - 0.774V\\n\n 1000 - 0.817V\\n\n 1001 - 0.860V (default)\\n\n 1010 - 0.903V\\n\n 1011 - 0.946V\\n\n 1100 - 0.989V\\n\n 1101 - 1.032V\\n\n 1110 - 1.075V\\n\n 1111 - 1.118V", + "offset": 4, + "size": 4 + }, + "EN": { + "description": "enable\\n\n 0=not enabled, 1=enabled", + "offset": 0, + "size": 1 + } + } + } + }, + "CHIP_RESET": { + "description": "Chip reset control and status", + "offset": 8, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "PSM_RESTART_FLAG": { + "description": "This is set by psm_restart from the debugger.\\n\n Its purpose is to branch bootcode to a safe mode when the debugger has issued a psm_restart in order to recover from a boot lock-up.\\n\n In the safe mode the debugger can repair the boot code, clear this flag then reboot the processor.", + "offset": 24, + "size": 1 + }, + "HAD_PSM_RESTART": { + "description": "Last reset was from the debug port", + "offset": 20, + "size": 1, + "access": "read-only" + }, + "HAD_RUN": { + "description": "Last reset was from the RUN pin", + "offset": 16, + "size": 1, + "access": "read-only" + }, + "HAD_POR": { + "description": "Last reset was from the power-on reset or brown-out detection blocks", + "offset": 8, + "size": 1, + "access": "read-only" + } + } + } + } + } + } + }, + "TBMAN": { + "description": "Testbench manager. Allows the programmer to know what platform their software is running on.", + "children": { + "registers": { + "PLATFORM": { + "description": "Indicates the type of platform in use", + "offset": 0, + "size": 32, + "reset_value": 5, + "children": { + "fields": { + "FPGA": { + "description": "Indicates the platform is an FPGA", + "offset": 1, + "size": 1, + "access": "read-only" + }, + "ASIC": { + "description": "Indicates the platform is an ASIC", + "offset": 0, + "size": 1, + "access": "read-only" + } + } + } + } + } + } + }, + "DMA": { + "description": "DMA with separate read and write masters", + "children": { + "registers": { + "CH0_READ_ADDR": { + "description": "DMA Channel 0 Read Address pointer\\n\n This register updates automatically each time a read completes. The current value is the next address to be read by this channel.", + "offset": 0, + "size": 32, + "reset_value": 0 + }, + "CH0_WRITE_ADDR": { + "description": "DMA Channel 0 Write Address pointer\\n\n This register updates automatically each time a write completes. The current value is the next address to be written by this channel.", + "offset": 4, + "size": 32, + "reset_value": 0 + }, + "CH0_TRANS_COUNT": { + "description": "DMA Channel 0 Transfer Count\\n\n Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE).\\n\\n\n When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes.\\n\\n\n Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write.\\n\\n\n The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD.", + "offset": 8, + "size": 32, + "reset_value": 0 + }, + "CH0_CTRL_TRIG": { + "description": "DMA Channel 0 Control and Status", + "offset": 12, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "AHB_ERROR": { + "description": "Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag.", + "offset": 31, + "size": 1, + "access": "read-only" + }, + "READ_ERROR": { + "description": "If 1, the channel received a read bus error. Write one to clear.\\n\n READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later)", + "offset": 30, + "size": 1 + }, + "WRITE_ERROR": { + "description": "If 1, the channel received a write bus error. Write one to clear.\\n\n WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later)", + "offset": 29, + "size": 1 + }, + "BUSY": { + "description": "This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused.\\n\\n\n To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT.", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "SNIFF_EN": { + "description": "If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected.\\n\\n\n This allows checksum to be enabled or disabled on a per-control- block basis.", + "offset": 23, + "size": 1 + }, + "BSWAP": { + "description": "Apply byte-swap transformation to DMA data.\\n\n For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order.", + "offset": 22, + "size": 1 + }, + "IRQ_QUIET": { + "description": "In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain.\\n\\n\n This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks.", + "offset": 21, + "size": 1 + }, + "TREQ_SEL": { + "description": "Select a Transfer Request signal.\\n\n The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system).\\n\n 0x0 to 0x3a -> select DREQ n as TREQ", + "offset": 15, + "size": 6, + "enum": { + "size": 6, + "children": { + "enum_fields": { + "TIMER0": { + "description": "Select Timer 0 as TREQ", + "value": 59 + }, + "TIMER1": { + "description": "Select Timer 1 as TREQ", + "value": 60 + }, + "TIMER2": { + "description": "Select Timer 2 as TREQ (Optional)", + "value": 61 + }, + "TIMER3": { + "description": "Select Timer 3 as TREQ (Optional)", + "value": 62 + }, + "PERMANENT": { + "description": "Permanent request, for unpaced transfers.", + "value": 63 + } + } + } + } + }, + "CHAIN_TO": { + "description": "When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.", + "offset": 11, + "size": 4 + }, + "RING_SEL": { + "description": "Select whether RING_SIZE applies to read or write addresses.\\n\n If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped.", + "offset": 10, + "size": 1 + }, + "RING_SIZE": { + "description": "Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers.\\n\\n\n Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL.", + "offset": 6, + "size": 4, + "enum": { + "size": 4, + "children": { + "enum_fields": { + "RING_NONE": { + "value": 0 + } + } + } + } + }, + "INCR_WRITE": { + "description": "If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address.\\n\\n\n Generally this should be disabled for memory-to-peripheral transfers.", + "offset": 5, + "size": 1 + }, + "INCR_READ": { + "description": "If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address.\\n\\n\n Generally this should be disabled for peripheral-to-memory transfers.", + "offset": 4, + "size": 1 + }, + "DATA_SIZE": { + "description": "Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer.", + "offset": 2, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "SIZE_BYTE": { + "value": 0 + }, + "SIZE_HALFWORD": { + "value": 1 + }, + "SIZE_WORD": { + "value": 2 + } + } + } + } + }, + "HIGH_PRIORITY": { + "description": "HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels.\\n\\n\n This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput.", + "offset": 1, + "size": 1 + }, + "EN": { + "description": "DMA Channel Enable.\\n\n When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high)", + "offset": 0, + "size": 1 + } + } + } + }, + "CH0_AL1_CTRL": { + "description": "Alias for channel 0 CTRL register", + "offset": 16, + "size": 32, + "reset_value": 0 + }, + "CH0_AL1_READ_ADDR": { + "description": "Alias for channel 0 READ_ADDR register", + "offset": 20, + "size": 32, + "reset_value": 0 + }, + "CH0_AL1_WRITE_ADDR": { + "description": "Alias for channel 0 WRITE_ADDR register", + "offset": 24, + "size": 32, + "reset_value": 0 + }, + "CH0_AL1_TRANS_COUNT_TRIG": { + "description": "Alias for channel 0 TRANS_COUNT register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 28, + "size": 32, + "reset_value": 0 + }, + "CH0_AL2_CTRL": { + "description": "Alias for channel 0 CTRL register", + "offset": 32, + "size": 32, + "reset_value": 0 + }, + "CH0_AL2_TRANS_COUNT": { + "description": "Alias for channel 0 TRANS_COUNT register", + "offset": 36, + "size": 32, + "reset_value": 0 + }, + "CH0_AL2_READ_ADDR": { + "description": "Alias for channel 0 READ_ADDR register", + "offset": 40, + "size": 32, + "reset_value": 0 + }, + "CH0_AL2_WRITE_ADDR_TRIG": { + "description": "Alias for channel 0 WRITE_ADDR register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 44, + "size": 32, + "reset_value": 0 + }, + "CH0_AL3_CTRL": { + "description": "Alias for channel 0 CTRL register", + "offset": 48, + "size": 32, + "reset_value": 0 + }, + "CH0_AL3_WRITE_ADDR": { + "description": "Alias for channel 0 WRITE_ADDR register", + "offset": 52, + "size": 32, + "reset_value": 0 + }, + "CH0_AL3_TRANS_COUNT": { + "description": "Alias for channel 0 TRANS_COUNT register", + "offset": 56, + "size": 32, + "reset_value": 0 + }, + "CH0_AL3_READ_ADDR_TRIG": { + "description": "Alias for channel 0 READ_ADDR register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 60, + "size": 32, + "reset_value": 0 + }, + "CH1_READ_ADDR": { + "description": "DMA Channel 1 Read Address pointer\\n\n This register updates automatically each time a read completes. The current value is the next address to be read by this channel.", + "offset": 64, + "size": 32, + "reset_value": 0 + }, + "CH1_WRITE_ADDR": { + "description": "DMA Channel 1 Write Address pointer\\n\n This register updates automatically each time a write completes. The current value is the next address to be written by this channel.", + "offset": 68, + "size": 32, + "reset_value": 0 + }, + "CH1_TRANS_COUNT": { + "description": "DMA Channel 1 Transfer Count\\n\n Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE).\\n\\n\n When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes.\\n\\n\n Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write.\\n\\n\n The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD.", + "offset": 72, + "size": 32, + "reset_value": 0 + }, + "CH1_CTRL_TRIG": { + "description": "DMA Channel 1 Control and Status", + "offset": 76, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "AHB_ERROR": { + "description": "Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag.", + "offset": 31, + "size": 1, + "access": "read-only" + }, + "READ_ERROR": { + "description": "If 1, the channel received a read bus error. Write one to clear.\\n\n READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later)", + "offset": 30, + "size": 1 + }, + "WRITE_ERROR": { + "description": "If 1, the channel received a write bus error. Write one to clear.\\n\n WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later)", + "offset": 29, + "size": 1 + }, + "BUSY": { + "description": "This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused.\\n\\n\n To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT.", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "SNIFF_EN": { + "description": "If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected.\\n\\n\n This allows checksum to be enabled or disabled on a per-control- block basis.", + "offset": 23, + "size": 1 + }, + "BSWAP": { + "description": "Apply byte-swap transformation to DMA data.\\n\n For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order.", + "offset": 22, + "size": 1 + }, + "IRQ_QUIET": { + "description": "In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain.\\n\\n\n This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks.", + "offset": 21, + "size": 1 + }, + "TREQ_SEL": { + "description": "Select a Transfer Request signal.\\n\n The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system).\\n\n 0x0 to 0x3a -> select DREQ n as TREQ", + "offset": 15, + "size": 6, + "enum": { + "size": 6, + "children": { + "enum_fields": { + "TIMER0": { + "description": "Select Timer 0 as TREQ", + "value": 59 + }, + "TIMER1": { + "description": "Select Timer 1 as TREQ", + "value": 60 + }, + "TIMER2": { + "description": "Select Timer 2 as TREQ (Optional)", + "value": 61 + }, + "TIMER3": { + "description": "Select Timer 3 as TREQ (Optional)", + "value": 62 + }, + "PERMANENT": { + "description": "Permanent request, for unpaced transfers.", + "value": 63 + } + } + } + } + }, + "CHAIN_TO": { + "description": "When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.", + "offset": 11, + "size": 4 + }, + "RING_SEL": { + "description": "Select whether RING_SIZE applies to read or write addresses.\\n\n If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped.", + "offset": 10, + "size": 1 + }, + "RING_SIZE": { + "description": "Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers.\\n\\n\n Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL.", + "offset": 6, + "size": 4, + "enum": { + "size": 4, + "children": { + "enum_fields": { + "RING_NONE": { + "value": 0 + } + } + } + } + }, + "INCR_WRITE": { + "description": "If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address.\\n\\n\n Generally this should be disabled for memory-to-peripheral transfers.", + "offset": 5, + "size": 1 + }, + "INCR_READ": { + "description": "If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address.\\n\\n\n Generally this should be disabled for peripheral-to-memory transfers.", + "offset": 4, + "size": 1 + }, + "DATA_SIZE": { + "description": "Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer.", + "offset": 2, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "SIZE_BYTE": { + "value": 0 + }, + "SIZE_HALFWORD": { + "value": 1 + }, + "SIZE_WORD": { + "value": 2 + } + } + } + } + }, + "HIGH_PRIORITY": { + "description": "HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels.\\n\\n\n This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput.", + "offset": 1, + "size": 1 + }, + "EN": { + "description": "DMA Channel Enable.\\n\n When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high)", + "offset": 0, + "size": 1 + } + } + } + }, + "CH1_AL1_CTRL": { + "description": "Alias for channel 1 CTRL register", + "offset": 80, + "size": 32, + "reset_value": 0 + }, + "CH1_AL1_READ_ADDR": { + "description": "Alias for channel 1 READ_ADDR register", + "offset": 84, + "size": 32, + "reset_value": 0 + }, + "CH1_AL1_WRITE_ADDR": { + "description": "Alias for channel 1 WRITE_ADDR register", + "offset": 88, + "size": 32, + "reset_value": 0 + }, + "CH1_AL1_TRANS_COUNT_TRIG": { + "description": "Alias for channel 1 TRANS_COUNT register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 92, + "size": 32, + "reset_value": 0 + }, + "CH1_AL2_CTRL": { + "description": "Alias for channel 1 CTRL register", + "offset": 96, + "size": 32, + "reset_value": 0 + }, + "CH1_AL2_TRANS_COUNT": { + "description": "Alias for channel 1 TRANS_COUNT register", + "offset": 100, + "size": 32, + "reset_value": 0 + }, + "CH1_AL2_READ_ADDR": { + "description": "Alias for channel 1 READ_ADDR register", + "offset": 104, + "size": 32, + "reset_value": 0 + }, + "CH1_AL2_WRITE_ADDR_TRIG": { + "description": "Alias for channel 1 WRITE_ADDR register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 108, + "size": 32, + "reset_value": 0 + }, + "CH1_AL3_CTRL": { + "description": "Alias for channel 1 CTRL register", + "offset": 112, + "size": 32, + "reset_value": 0 + }, + "CH1_AL3_WRITE_ADDR": { + "description": "Alias for channel 1 WRITE_ADDR register", + "offset": 116, + "size": 32, + "reset_value": 0 + }, + "CH1_AL3_TRANS_COUNT": { + "description": "Alias for channel 1 TRANS_COUNT register", + "offset": 120, + "size": 32, + "reset_value": 0 + }, + "CH1_AL3_READ_ADDR_TRIG": { + "description": "Alias for channel 1 READ_ADDR register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 124, + "size": 32, + "reset_value": 0 + }, + "CH2_READ_ADDR": { + "description": "DMA Channel 2 Read Address pointer\\n\n This register updates automatically each time a read completes. The current value is the next address to be read by this channel.", + "offset": 128, + "size": 32, + "reset_value": 0 + }, + "CH2_WRITE_ADDR": { + "description": "DMA Channel 2 Write Address pointer\\n\n This register updates automatically each time a write completes. The current value is the next address to be written by this channel.", + "offset": 132, + "size": 32, + "reset_value": 0 + }, + "CH2_TRANS_COUNT": { + "description": "DMA Channel 2 Transfer Count\\n\n Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE).\\n\\n\n When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes.\\n\\n\n Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write.\\n\\n\n The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD.", + "offset": 136, + "size": 32, + "reset_value": 0 + }, + "CH2_CTRL_TRIG": { + "description": "DMA Channel 2 Control and Status", + "offset": 140, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "AHB_ERROR": { + "description": "Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag.", + "offset": 31, + "size": 1, + "access": "read-only" + }, + "READ_ERROR": { + "description": "If 1, the channel received a read bus error. Write one to clear.\\n\n READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later)", + "offset": 30, + "size": 1 + }, + "WRITE_ERROR": { + "description": "If 1, the channel received a write bus error. Write one to clear.\\n\n WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later)", + "offset": 29, + "size": 1 + }, + "BUSY": { + "description": "This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused.\\n\\n\n To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT.", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "SNIFF_EN": { + "description": "If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected.\\n\\n\n This allows checksum to be enabled or disabled on a per-control- block basis.", + "offset": 23, + "size": 1 + }, + "BSWAP": { + "description": "Apply byte-swap transformation to DMA data.\\n\n For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order.", + "offset": 22, + "size": 1 + }, + "IRQ_QUIET": { + "description": "In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain.\\n\\n\n This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks.", + "offset": 21, + "size": 1 + }, + "TREQ_SEL": { + "description": "Select a Transfer Request signal.\\n\n The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system).\\n\n 0x0 to 0x3a -> select DREQ n as TREQ", + "offset": 15, + "size": 6, + "enum": { + "size": 6, + "children": { + "enum_fields": { + "TIMER0": { + "description": "Select Timer 0 as TREQ", + "value": 59 + }, + "TIMER1": { + "description": "Select Timer 1 as TREQ", + "value": 60 + }, + "TIMER2": { + "description": "Select Timer 2 as TREQ (Optional)", + "value": 61 + }, + "TIMER3": { + "description": "Select Timer 3 as TREQ (Optional)", + "value": 62 + }, + "PERMANENT": { + "description": "Permanent request, for unpaced transfers.", + "value": 63 + } + } + } + } + }, + "CHAIN_TO": { + "description": "When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.", + "offset": 11, + "size": 4 + }, + "RING_SEL": { + "description": "Select whether RING_SIZE applies to read or write addresses.\\n\n If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped.", + "offset": 10, + "size": 1 + }, + "RING_SIZE": { + "description": "Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers.\\n\\n\n Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL.", + "offset": 6, + "size": 4, + "enum": { + "size": 4, + "children": { + "enum_fields": { + "RING_NONE": { + "value": 0 + } + } + } + } + }, + "INCR_WRITE": { + "description": "If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address.\\n\\n\n Generally this should be disabled for memory-to-peripheral transfers.", + "offset": 5, + "size": 1 + }, + "INCR_READ": { + "description": "If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address.\\n\\n\n Generally this should be disabled for peripheral-to-memory transfers.", + "offset": 4, + "size": 1 + }, + "DATA_SIZE": { + "description": "Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer.", + "offset": 2, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "SIZE_BYTE": { + "value": 0 + }, + "SIZE_HALFWORD": { + "value": 1 + }, + "SIZE_WORD": { + "value": 2 + } + } + } + } + }, + "HIGH_PRIORITY": { + "description": "HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels.\\n\\n\n This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput.", + "offset": 1, + "size": 1 + }, + "EN": { + "description": "DMA Channel Enable.\\n\n When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high)", + "offset": 0, + "size": 1 + } + } + } + }, + "CH2_AL1_CTRL": { + "description": "Alias for channel 2 CTRL register", + "offset": 144, + "size": 32, + "reset_value": 0 + }, + "CH2_AL1_READ_ADDR": { + "description": "Alias for channel 2 READ_ADDR register", + "offset": 148, + "size": 32, + "reset_value": 0 + }, + "CH2_AL1_WRITE_ADDR": { + "description": "Alias for channel 2 WRITE_ADDR register", + "offset": 152, + "size": 32, + "reset_value": 0 + }, + "CH2_AL1_TRANS_COUNT_TRIG": { + "description": "Alias for channel 2 TRANS_COUNT register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 156, + "size": 32, + "reset_value": 0 + }, + "CH2_AL2_CTRL": { + "description": "Alias for channel 2 CTRL register", + "offset": 160, + "size": 32, + "reset_value": 0 + }, + "CH2_AL2_TRANS_COUNT": { + "description": "Alias for channel 2 TRANS_COUNT register", + "offset": 164, + "size": 32, + "reset_value": 0 + }, + "CH2_AL2_READ_ADDR": { + "description": "Alias for channel 2 READ_ADDR register", + "offset": 168, + "size": 32, + "reset_value": 0 + }, + "CH2_AL2_WRITE_ADDR_TRIG": { + "description": "Alias for channel 2 WRITE_ADDR register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 172, + "size": 32, + "reset_value": 0 + }, + "CH2_AL3_CTRL": { + "description": "Alias for channel 2 CTRL register", + "offset": 176, + "size": 32, + "reset_value": 0 + }, + "CH2_AL3_WRITE_ADDR": { + "description": "Alias for channel 2 WRITE_ADDR register", + "offset": 180, + "size": 32, + "reset_value": 0 + }, + "CH2_AL3_TRANS_COUNT": { + "description": "Alias for channel 2 TRANS_COUNT register", + "offset": 184, + "size": 32, + "reset_value": 0 + }, + "CH2_AL3_READ_ADDR_TRIG": { + "description": "Alias for channel 2 READ_ADDR register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 188, + "size": 32, + "reset_value": 0 + }, + "CH3_READ_ADDR": { + "description": "DMA Channel 3 Read Address pointer\\n\n This register updates automatically each time a read completes. The current value is the next address to be read by this channel.", + "offset": 192, + "size": 32, + "reset_value": 0 + }, + "CH3_WRITE_ADDR": { + "description": "DMA Channel 3 Write Address pointer\\n\n This register updates automatically each time a write completes. The current value is the next address to be written by this channel.", + "offset": 196, + "size": 32, + "reset_value": 0 + }, + "CH3_TRANS_COUNT": { + "description": "DMA Channel 3 Transfer Count\\n\n Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE).\\n\\n\n When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes.\\n\\n\n Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write.\\n\\n\n The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD.", + "offset": 200, + "size": 32, + "reset_value": 0 + }, + "CH3_CTRL_TRIG": { + "description": "DMA Channel 3 Control and Status", + "offset": 204, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "AHB_ERROR": { + "description": "Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag.", + "offset": 31, + "size": 1, + "access": "read-only" + }, + "READ_ERROR": { + "description": "If 1, the channel received a read bus error. Write one to clear.\\n\n READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later)", + "offset": 30, + "size": 1 + }, + "WRITE_ERROR": { + "description": "If 1, the channel received a write bus error. Write one to clear.\\n\n WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later)", + "offset": 29, + "size": 1 + }, + "BUSY": { + "description": "This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused.\\n\\n\n To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT.", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "SNIFF_EN": { + "description": "If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected.\\n\\n\n This allows checksum to be enabled or disabled on a per-control- block basis.", + "offset": 23, + "size": 1 + }, + "BSWAP": { + "description": "Apply byte-swap transformation to DMA data.\\n\n For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order.", + "offset": 22, + "size": 1 + }, + "IRQ_QUIET": { + "description": "In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain.\\n\\n\n This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks.", + "offset": 21, + "size": 1 + }, + "TREQ_SEL": { + "description": "Select a Transfer Request signal.\\n\n The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system).\\n\n 0x0 to 0x3a -> select DREQ n as TREQ", + "offset": 15, + "size": 6, + "enum": { + "size": 6, + "children": { + "enum_fields": { + "TIMER0": { + "description": "Select Timer 0 as TREQ", + "value": 59 + }, + "TIMER1": { + "description": "Select Timer 1 as TREQ", + "value": 60 + }, + "TIMER2": { + "description": "Select Timer 2 as TREQ (Optional)", + "value": 61 + }, + "TIMER3": { + "description": "Select Timer 3 as TREQ (Optional)", + "value": 62 + }, + "PERMANENT": { + "description": "Permanent request, for unpaced transfers.", + "value": 63 + } + } + } + } + }, + "CHAIN_TO": { + "description": "When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.", + "offset": 11, + "size": 4 + }, + "RING_SEL": { + "description": "Select whether RING_SIZE applies to read or write addresses.\\n\n If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped.", + "offset": 10, + "size": 1 + }, + "RING_SIZE": { + "description": "Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers.\\n\\n\n Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL.", + "offset": 6, + "size": 4, + "enum": { + "size": 4, + "children": { + "enum_fields": { + "RING_NONE": { + "value": 0 + } + } + } + } + }, + "INCR_WRITE": { + "description": "If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address.\\n\\n\n Generally this should be disabled for memory-to-peripheral transfers.", + "offset": 5, + "size": 1 + }, + "INCR_READ": { + "description": "If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address.\\n\\n\n Generally this should be disabled for peripheral-to-memory transfers.", + "offset": 4, + "size": 1 + }, + "DATA_SIZE": { + "description": "Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer.", + "offset": 2, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "SIZE_BYTE": { + "value": 0 + }, + "SIZE_HALFWORD": { + "value": 1 + }, + "SIZE_WORD": { + "value": 2 + } + } + } + } + }, + "HIGH_PRIORITY": { + "description": "HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels.\\n\\n\n This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput.", + "offset": 1, + "size": 1 + }, + "EN": { + "description": "DMA Channel Enable.\\n\n When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high)", + "offset": 0, + "size": 1 + } + } + } + }, + "CH3_AL1_CTRL": { + "description": "Alias for channel 3 CTRL register", + "offset": 208, + "size": 32, + "reset_value": 0 + }, + "CH3_AL1_READ_ADDR": { + "description": "Alias for channel 3 READ_ADDR register", + "offset": 212, + "size": 32, + "reset_value": 0 + }, + "CH3_AL1_WRITE_ADDR": { + "description": "Alias for channel 3 WRITE_ADDR register", + "offset": 216, + "size": 32, + "reset_value": 0 + }, + "CH3_AL1_TRANS_COUNT_TRIG": { + "description": "Alias for channel 3 TRANS_COUNT register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 220, + "size": 32, + "reset_value": 0 + }, + "CH3_AL2_CTRL": { + "description": "Alias for channel 3 CTRL register", + "offset": 224, + "size": 32, + "reset_value": 0 + }, + "CH3_AL2_TRANS_COUNT": { + "description": "Alias for channel 3 TRANS_COUNT register", + "offset": 228, + "size": 32, + "reset_value": 0 + }, + "CH3_AL2_READ_ADDR": { + "description": "Alias for channel 3 READ_ADDR register", + "offset": 232, + "size": 32, + "reset_value": 0 + }, + "CH3_AL2_WRITE_ADDR_TRIG": { + "description": "Alias for channel 3 WRITE_ADDR register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 236, + "size": 32, + "reset_value": 0 + }, + "CH3_AL3_CTRL": { + "description": "Alias for channel 3 CTRL register", + "offset": 240, + "size": 32, + "reset_value": 0 + }, + "CH3_AL3_WRITE_ADDR": { + "description": "Alias for channel 3 WRITE_ADDR register", + "offset": 244, + "size": 32, + "reset_value": 0 + }, + "CH3_AL3_TRANS_COUNT": { + "description": "Alias for channel 3 TRANS_COUNT register", + "offset": 248, + "size": 32, + "reset_value": 0 + }, + "CH3_AL3_READ_ADDR_TRIG": { + "description": "Alias for channel 3 READ_ADDR register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 252, + "size": 32, + "reset_value": 0 + }, + "CH4_READ_ADDR": { + "description": "DMA Channel 4 Read Address pointer\\n\n This register updates automatically each time a read completes. The current value is the next address to be read by this channel.", + "offset": 256, + "size": 32, + "reset_value": 0 + }, + "CH4_WRITE_ADDR": { + "description": "DMA Channel 4 Write Address pointer\\n\n This register updates automatically each time a write completes. The current value is the next address to be written by this channel.", + "offset": 260, + "size": 32, + "reset_value": 0 + }, + "CH4_TRANS_COUNT": { + "description": "DMA Channel 4 Transfer Count\\n\n Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE).\\n\\n\n When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes.\\n\\n\n Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write.\\n\\n\n The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD.", + "offset": 264, + "size": 32, + "reset_value": 0 + }, + "CH4_CTRL_TRIG": { + "description": "DMA Channel 4 Control and Status", + "offset": 268, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "AHB_ERROR": { + "description": "Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag.", + "offset": 31, + "size": 1, + "access": "read-only" + }, + "READ_ERROR": { + "description": "If 1, the channel received a read bus error. Write one to clear.\\n\n READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later)", + "offset": 30, + "size": 1 + }, + "WRITE_ERROR": { + "description": "If 1, the channel received a write bus error. Write one to clear.\\n\n WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later)", + "offset": 29, + "size": 1 + }, + "BUSY": { + "description": "This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused.\\n\\n\n To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT.", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "SNIFF_EN": { + "description": "If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected.\\n\\n\n This allows checksum to be enabled or disabled on a per-control- block basis.", + "offset": 23, + "size": 1 + }, + "BSWAP": { + "description": "Apply byte-swap transformation to DMA data.\\n\n For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order.", + "offset": 22, + "size": 1 + }, + "IRQ_QUIET": { + "description": "In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain.\\n\\n\n This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks.", + "offset": 21, + "size": 1 + }, + "TREQ_SEL": { + "description": "Select a Transfer Request signal.\\n\n The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system).\\n\n 0x0 to 0x3a -> select DREQ n as TREQ", + "offset": 15, + "size": 6, + "enum": { + "size": 6, + "children": { + "enum_fields": { + "TIMER0": { + "description": "Select Timer 0 as TREQ", + "value": 59 + }, + "TIMER1": { + "description": "Select Timer 1 as TREQ", + "value": 60 + }, + "TIMER2": { + "description": "Select Timer 2 as TREQ (Optional)", + "value": 61 + }, + "TIMER3": { + "description": "Select Timer 3 as TREQ (Optional)", + "value": 62 + }, + "PERMANENT": { + "description": "Permanent request, for unpaced transfers.", + "value": 63 + } + } + } + } + }, + "CHAIN_TO": { + "description": "When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.", + "offset": 11, + "size": 4 + }, + "RING_SEL": { + "description": "Select whether RING_SIZE applies to read or write addresses.\\n\n If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped.", + "offset": 10, + "size": 1 + }, + "RING_SIZE": { + "description": "Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers.\\n\\n\n Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL.", + "offset": 6, + "size": 4, + "enum": { + "size": 4, + "children": { + "enum_fields": { + "RING_NONE": { + "value": 0 + } + } + } + } + }, + "INCR_WRITE": { + "description": "If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address.\\n\\n\n Generally this should be disabled for memory-to-peripheral transfers.", + "offset": 5, + "size": 1 + }, + "INCR_READ": { + "description": "If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address.\\n\\n\n Generally this should be disabled for peripheral-to-memory transfers.", + "offset": 4, + "size": 1 + }, + "DATA_SIZE": { + "description": "Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer.", + "offset": 2, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "SIZE_BYTE": { + "value": 0 + }, + "SIZE_HALFWORD": { + "value": 1 + }, + "SIZE_WORD": { + "value": 2 + } + } + } + } + }, + "HIGH_PRIORITY": { + "description": "HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels.\\n\\n\n This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput.", + "offset": 1, + "size": 1 + }, + "EN": { + "description": "DMA Channel Enable.\\n\n When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high)", + "offset": 0, + "size": 1 + } + } + } + }, + "CH4_AL1_CTRL": { + "description": "Alias for channel 4 CTRL register", + "offset": 272, + "size": 32, + "reset_value": 0 + }, + "CH4_AL1_READ_ADDR": { + "description": "Alias for channel 4 READ_ADDR register", + "offset": 276, + "size": 32, + "reset_value": 0 + }, + "CH4_AL1_WRITE_ADDR": { + "description": "Alias for channel 4 WRITE_ADDR register", + "offset": 280, + "size": 32, + "reset_value": 0 + }, + "CH4_AL1_TRANS_COUNT_TRIG": { + "description": "Alias for channel 4 TRANS_COUNT register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 284, + "size": 32, + "reset_value": 0 + }, + "CH4_AL2_CTRL": { + "description": "Alias for channel 4 CTRL register", + "offset": 288, + "size": 32, + "reset_value": 0 + }, + "CH4_AL2_TRANS_COUNT": { + "description": "Alias for channel 4 TRANS_COUNT register", + "offset": 292, + "size": 32, + "reset_value": 0 + }, + "CH4_AL2_READ_ADDR": { + "description": "Alias for channel 4 READ_ADDR register", + "offset": 296, + "size": 32, + "reset_value": 0 + }, + "CH4_AL2_WRITE_ADDR_TRIG": { + "description": "Alias for channel 4 WRITE_ADDR register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 300, + "size": 32, + "reset_value": 0 + }, + "CH4_AL3_CTRL": { + "description": "Alias for channel 4 CTRL register", + "offset": 304, + "size": 32, + "reset_value": 0 + }, + "CH4_AL3_WRITE_ADDR": { + "description": "Alias for channel 4 WRITE_ADDR register", + "offset": 308, + "size": 32, + "reset_value": 0 + }, + "CH4_AL3_TRANS_COUNT": { + "description": "Alias for channel 4 TRANS_COUNT register", + "offset": 312, + "size": 32, + "reset_value": 0 + }, + "CH4_AL3_READ_ADDR_TRIG": { + "description": "Alias for channel 4 READ_ADDR register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 316, + "size": 32, + "reset_value": 0 + }, + "CH5_READ_ADDR": { + "description": "DMA Channel 5 Read Address pointer\\n\n This register updates automatically each time a read completes. The current value is the next address to be read by this channel.", + "offset": 320, + "size": 32, + "reset_value": 0 + }, + "CH5_WRITE_ADDR": { + "description": "DMA Channel 5 Write Address pointer\\n\n This register updates automatically each time a write completes. The current value is the next address to be written by this channel.", + "offset": 324, + "size": 32, + "reset_value": 0 + }, + "CH5_TRANS_COUNT": { + "description": "DMA Channel 5 Transfer Count\\n\n Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE).\\n\\n\n When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes.\\n\\n\n Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write.\\n\\n\n The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD.", + "offset": 328, + "size": 32, + "reset_value": 0 + }, + "CH5_CTRL_TRIG": { + "description": "DMA Channel 5 Control and Status", + "offset": 332, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "AHB_ERROR": { + "description": "Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag.", + "offset": 31, + "size": 1, + "access": "read-only" + }, + "READ_ERROR": { + "description": "If 1, the channel received a read bus error. Write one to clear.\\n\n READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later)", + "offset": 30, + "size": 1 + }, + "WRITE_ERROR": { + "description": "If 1, the channel received a write bus error. Write one to clear.\\n\n WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later)", + "offset": 29, + "size": 1 + }, + "BUSY": { + "description": "This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused.\\n\\n\n To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT.", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "SNIFF_EN": { + "description": "If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected.\\n\\n\n This allows checksum to be enabled or disabled on a per-control- block basis.", + "offset": 23, + "size": 1 + }, + "BSWAP": { + "description": "Apply byte-swap transformation to DMA data.\\n\n For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order.", + "offset": 22, + "size": 1 + }, + "IRQ_QUIET": { + "description": "In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain.\\n\\n\n This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks.", + "offset": 21, + "size": 1 + }, + "TREQ_SEL": { + "description": "Select a Transfer Request signal.\\n\n The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system).\\n\n 0x0 to 0x3a -> select DREQ n as TREQ", + "offset": 15, + "size": 6, + "enum": { + "size": 6, + "children": { + "enum_fields": { + "TIMER0": { + "description": "Select Timer 0 as TREQ", + "value": 59 + }, + "TIMER1": { + "description": "Select Timer 1 as TREQ", + "value": 60 + }, + "TIMER2": { + "description": "Select Timer 2 as TREQ (Optional)", + "value": 61 + }, + "TIMER3": { + "description": "Select Timer 3 as TREQ (Optional)", + "value": 62 + }, + "PERMANENT": { + "description": "Permanent request, for unpaced transfers.", + "value": 63 + } + } + } + } + }, + "CHAIN_TO": { + "description": "When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.", + "offset": 11, + "size": 4 + }, + "RING_SEL": { + "description": "Select whether RING_SIZE applies to read or write addresses.\\n\n If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped.", + "offset": 10, + "size": 1 + }, + "RING_SIZE": { + "description": "Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers.\\n\\n\n Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL.", + "offset": 6, + "size": 4, + "enum": { + "size": 4, + "children": { + "enum_fields": { + "RING_NONE": { + "value": 0 + } + } + } + } + }, + "INCR_WRITE": { + "description": "If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address.\\n\\n\n Generally this should be disabled for memory-to-peripheral transfers.", + "offset": 5, + "size": 1 + }, + "INCR_READ": { + "description": "If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address.\\n\\n\n Generally this should be disabled for peripheral-to-memory transfers.", + "offset": 4, + "size": 1 + }, + "DATA_SIZE": { + "description": "Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer.", + "offset": 2, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "SIZE_BYTE": { + "value": 0 + }, + "SIZE_HALFWORD": { + "value": 1 + }, + "SIZE_WORD": { + "value": 2 + } + } + } + } + }, + "HIGH_PRIORITY": { + "description": "HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels.\\n\\n\n This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput.", + "offset": 1, + "size": 1 + }, + "EN": { + "description": "DMA Channel Enable.\\n\n When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high)", + "offset": 0, + "size": 1 + } + } + } + }, + "CH5_AL1_CTRL": { + "description": "Alias for channel 5 CTRL register", + "offset": 336, + "size": 32, + "reset_value": 0 + }, + "CH5_AL1_READ_ADDR": { + "description": "Alias for channel 5 READ_ADDR register", + "offset": 340, + "size": 32, + "reset_value": 0 + }, + "CH5_AL1_WRITE_ADDR": { + "description": "Alias for channel 5 WRITE_ADDR register", + "offset": 344, + "size": 32, + "reset_value": 0 + }, + "CH5_AL1_TRANS_COUNT_TRIG": { + "description": "Alias for channel 5 TRANS_COUNT register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 348, + "size": 32, + "reset_value": 0 + }, + "CH5_AL2_CTRL": { + "description": "Alias for channel 5 CTRL register", + "offset": 352, + "size": 32, + "reset_value": 0 + }, + "CH5_AL2_TRANS_COUNT": { + "description": "Alias for channel 5 TRANS_COUNT register", + "offset": 356, + "size": 32, + "reset_value": 0 + }, + "CH5_AL2_READ_ADDR": { + "description": "Alias for channel 5 READ_ADDR register", + "offset": 360, + "size": 32, + "reset_value": 0 + }, + "CH5_AL2_WRITE_ADDR_TRIG": { + "description": "Alias for channel 5 WRITE_ADDR register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 364, + "size": 32, + "reset_value": 0 + }, + "CH5_AL3_CTRL": { + "description": "Alias for channel 5 CTRL register", + "offset": 368, + "size": 32, + "reset_value": 0 + }, + "CH5_AL3_WRITE_ADDR": { + "description": "Alias for channel 5 WRITE_ADDR register", + "offset": 372, + "size": 32, + "reset_value": 0 + }, + "CH5_AL3_TRANS_COUNT": { + "description": "Alias for channel 5 TRANS_COUNT register", + "offset": 376, + "size": 32, + "reset_value": 0 + }, + "CH5_AL3_READ_ADDR_TRIG": { + "description": "Alias for channel 5 READ_ADDR register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 380, + "size": 32, + "reset_value": 0 + }, + "CH6_READ_ADDR": { + "description": "DMA Channel 6 Read Address pointer\\n\n This register updates automatically each time a read completes. The current value is the next address to be read by this channel.", + "offset": 384, + "size": 32, + "reset_value": 0 + }, + "CH6_WRITE_ADDR": { + "description": "DMA Channel 6 Write Address pointer\\n\n This register updates automatically each time a write completes. The current value is the next address to be written by this channel.", + "offset": 388, + "size": 32, + "reset_value": 0 + }, + "CH6_TRANS_COUNT": { + "description": "DMA Channel 6 Transfer Count\\n\n Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE).\\n\\n\n When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes.\\n\\n\n Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write.\\n\\n\n The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD.", + "offset": 392, + "size": 32, + "reset_value": 0 + }, + "CH6_CTRL_TRIG": { + "description": "DMA Channel 6 Control and Status", + "offset": 396, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "AHB_ERROR": { + "description": "Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag.", + "offset": 31, + "size": 1, + "access": "read-only" + }, + "READ_ERROR": { + "description": "If 1, the channel received a read bus error. Write one to clear.\\n\n READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later)", + "offset": 30, + "size": 1 + }, + "WRITE_ERROR": { + "description": "If 1, the channel received a write bus error. Write one to clear.\\n\n WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later)", + "offset": 29, + "size": 1 + }, + "BUSY": { + "description": "This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused.\\n\\n\n To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT.", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "SNIFF_EN": { + "description": "If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected.\\n\\n\n This allows checksum to be enabled or disabled on a per-control- block basis.", + "offset": 23, + "size": 1 + }, + "BSWAP": { + "description": "Apply byte-swap transformation to DMA data.\\n\n For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order.", + "offset": 22, + "size": 1 + }, + "IRQ_QUIET": { + "description": "In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain.\\n\\n\n This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks.", + "offset": 21, + "size": 1 + }, + "TREQ_SEL": { + "description": "Select a Transfer Request signal.\\n\n The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system).\\n\n 0x0 to 0x3a -> select DREQ n as TREQ", + "offset": 15, + "size": 6, + "enum": { + "size": 6, + "children": { + "enum_fields": { + "TIMER0": { + "description": "Select Timer 0 as TREQ", + "value": 59 + }, + "TIMER1": { + "description": "Select Timer 1 as TREQ", + "value": 60 + }, + "TIMER2": { + "description": "Select Timer 2 as TREQ (Optional)", + "value": 61 + }, + "TIMER3": { + "description": "Select Timer 3 as TREQ (Optional)", + "value": 62 + }, + "PERMANENT": { + "description": "Permanent request, for unpaced transfers.", + "value": 63 + } + } + } + } + }, + "CHAIN_TO": { + "description": "When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.", + "offset": 11, + "size": 4 + }, + "RING_SEL": { + "description": "Select whether RING_SIZE applies to read or write addresses.\\n\n If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped.", + "offset": 10, + "size": 1 + }, + "RING_SIZE": { + "description": "Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers.\\n\\n\n Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL.", + "offset": 6, + "size": 4, + "enum": { + "size": 4, + "children": { + "enum_fields": { + "RING_NONE": { + "value": 0 + } + } + } + } + }, + "INCR_WRITE": { + "description": "If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address.\\n\\n\n Generally this should be disabled for memory-to-peripheral transfers.", + "offset": 5, + "size": 1 + }, + "INCR_READ": { + "description": "If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address.\\n\\n\n Generally this should be disabled for peripheral-to-memory transfers.", + "offset": 4, + "size": 1 + }, + "DATA_SIZE": { + "description": "Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer.", + "offset": 2, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "SIZE_BYTE": { + "value": 0 + }, + "SIZE_HALFWORD": { + "value": 1 + }, + "SIZE_WORD": { + "value": 2 + } + } + } + } + }, + "HIGH_PRIORITY": { + "description": "HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels.\\n\\n\n This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput.", + "offset": 1, + "size": 1 + }, + "EN": { + "description": "DMA Channel Enable.\\n\n When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high)", + "offset": 0, + "size": 1 + } + } + } + }, + "CH6_AL1_CTRL": { + "description": "Alias for channel 6 CTRL register", + "offset": 400, + "size": 32, + "reset_value": 0 + }, + "CH6_AL1_READ_ADDR": { + "description": "Alias for channel 6 READ_ADDR register", + "offset": 404, + "size": 32, + "reset_value": 0 + }, + "CH6_AL1_WRITE_ADDR": { + "description": "Alias for channel 6 WRITE_ADDR register", + "offset": 408, + "size": 32, + "reset_value": 0 + }, + "CH6_AL1_TRANS_COUNT_TRIG": { + "description": "Alias for channel 6 TRANS_COUNT register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 412, + "size": 32, + "reset_value": 0 + }, + "CH6_AL2_CTRL": { + "description": "Alias for channel 6 CTRL register", + "offset": 416, + "size": 32, + "reset_value": 0 + }, + "CH6_AL2_TRANS_COUNT": { + "description": "Alias for channel 6 TRANS_COUNT register", + "offset": 420, + "size": 32, + "reset_value": 0 + }, + "CH6_AL2_READ_ADDR": { + "description": "Alias for channel 6 READ_ADDR register", + "offset": 424, + "size": 32, + "reset_value": 0 + }, + "CH6_AL2_WRITE_ADDR_TRIG": { + "description": "Alias for channel 6 WRITE_ADDR register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 428, + "size": 32, + "reset_value": 0 + }, + "CH6_AL3_CTRL": { + "description": "Alias for channel 6 CTRL register", + "offset": 432, + "size": 32, + "reset_value": 0 + }, + "CH6_AL3_WRITE_ADDR": { + "description": "Alias for channel 6 WRITE_ADDR register", + "offset": 436, + "size": 32, + "reset_value": 0 + }, + "CH6_AL3_TRANS_COUNT": { + "description": "Alias for channel 6 TRANS_COUNT register", + "offset": 440, + "size": 32, + "reset_value": 0 + }, + "CH6_AL3_READ_ADDR_TRIG": { + "description": "Alias for channel 6 READ_ADDR register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 444, + "size": 32, + "reset_value": 0 + }, + "CH7_READ_ADDR": { + "description": "DMA Channel 7 Read Address pointer\\n\n This register updates automatically each time a read completes. The current value is the next address to be read by this channel.", + "offset": 448, + "size": 32, + "reset_value": 0 + }, + "CH7_WRITE_ADDR": { + "description": "DMA Channel 7 Write Address pointer\\n\n This register updates automatically each time a write completes. The current value is the next address to be written by this channel.", + "offset": 452, + "size": 32, + "reset_value": 0 + }, + "CH7_TRANS_COUNT": { + "description": "DMA Channel 7 Transfer Count\\n\n Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE).\\n\\n\n When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes.\\n\\n\n Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write.\\n\\n\n The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD.", + "offset": 456, + "size": 32, + "reset_value": 0 + }, + "CH7_CTRL_TRIG": { + "description": "DMA Channel 7 Control and Status", + "offset": 460, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "AHB_ERROR": { + "description": "Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag.", + "offset": 31, + "size": 1, + "access": "read-only" + }, + "READ_ERROR": { + "description": "If 1, the channel received a read bus error. Write one to clear.\\n\n READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later)", + "offset": 30, + "size": 1 + }, + "WRITE_ERROR": { + "description": "If 1, the channel received a write bus error. Write one to clear.\\n\n WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later)", + "offset": 29, + "size": 1 + }, + "BUSY": { + "description": "This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused.\\n\\n\n To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT.", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "SNIFF_EN": { + "description": "If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected.\\n\\n\n This allows checksum to be enabled or disabled on a per-control- block basis.", + "offset": 23, + "size": 1 + }, + "BSWAP": { + "description": "Apply byte-swap transformation to DMA data.\\n\n For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order.", + "offset": 22, + "size": 1 + }, + "IRQ_QUIET": { + "description": "In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain.\\n\\n\n This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks.", + "offset": 21, + "size": 1 + }, + "TREQ_SEL": { + "description": "Select a Transfer Request signal.\\n\n The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system).\\n\n 0x0 to 0x3a -> select DREQ n as TREQ", + "offset": 15, + "size": 6, + "enum": { + "size": 6, + "children": { + "enum_fields": { + "TIMER0": { + "description": "Select Timer 0 as TREQ", + "value": 59 + }, + "TIMER1": { + "description": "Select Timer 1 as TREQ", + "value": 60 + }, + "TIMER2": { + "description": "Select Timer 2 as TREQ (Optional)", + "value": 61 + }, + "TIMER3": { + "description": "Select Timer 3 as TREQ (Optional)", + "value": 62 + }, + "PERMANENT": { + "description": "Permanent request, for unpaced transfers.", + "value": 63 + } + } + } + } + }, + "CHAIN_TO": { + "description": "When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.", + "offset": 11, + "size": 4 + }, + "RING_SEL": { + "description": "Select whether RING_SIZE applies to read or write addresses.\\n\n If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped.", + "offset": 10, + "size": 1 + }, + "RING_SIZE": { + "description": "Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers.\\n\\n\n Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL.", + "offset": 6, + "size": 4, + "enum": { + "size": 4, + "children": { + "enum_fields": { + "RING_NONE": { + "value": 0 + } + } + } + } + }, + "INCR_WRITE": { + "description": "If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address.\\n\\n\n Generally this should be disabled for memory-to-peripheral transfers.", + "offset": 5, + "size": 1 + }, + "INCR_READ": { + "description": "If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address.\\n\\n\n Generally this should be disabled for peripheral-to-memory transfers.", + "offset": 4, + "size": 1 + }, + "DATA_SIZE": { + "description": "Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer.", + "offset": 2, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "SIZE_BYTE": { + "value": 0 + }, + "SIZE_HALFWORD": { + "value": 1 + }, + "SIZE_WORD": { + "value": 2 + } + } + } + } + }, + "HIGH_PRIORITY": { + "description": "HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels.\\n\\n\n This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput.", + "offset": 1, + "size": 1 + }, + "EN": { + "description": "DMA Channel Enable.\\n\n When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high)", + "offset": 0, + "size": 1 + } + } + } + }, + "CH7_AL1_CTRL": { + "description": "Alias for channel 7 CTRL register", + "offset": 464, + "size": 32, + "reset_value": 0 + }, + "CH7_AL1_READ_ADDR": { + "description": "Alias for channel 7 READ_ADDR register", + "offset": 468, + "size": 32, + "reset_value": 0 + }, + "CH7_AL1_WRITE_ADDR": { + "description": "Alias for channel 7 WRITE_ADDR register", + "offset": 472, + "size": 32, + "reset_value": 0 + }, + "CH7_AL1_TRANS_COUNT_TRIG": { + "description": "Alias for channel 7 TRANS_COUNT register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 476, + "size": 32, + "reset_value": 0 + }, + "CH7_AL2_CTRL": { + "description": "Alias for channel 7 CTRL register", + "offset": 480, + "size": 32, + "reset_value": 0 + }, + "CH7_AL2_TRANS_COUNT": { + "description": "Alias for channel 7 TRANS_COUNT register", + "offset": 484, + "size": 32, + "reset_value": 0 + }, + "CH7_AL2_READ_ADDR": { + "description": "Alias for channel 7 READ_ADDR register", + "offset": 488, + "size": 32, + "reset_value": 0 + }, + "CH7_AL2_WRITE_ADDR_TRIG": { + "description": "Alias for channel 7 WRITE_ADDR register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 492, + "size": 32, + "reset_value": 0 + }, + "CH7_AL3_CTRL": { + "description": "Alias for channel 7 CTRL register", + "offset": 496, + "size": 32, + "reset_value": 0 + }, + "CH7_AL3_WRITE_ADDR": { + "description": "Alias for channel 7 WRITE_ADDR register", + "offset": 500, + "size": 32, + "reset_value": 0 + }, + "CH7_AL3_TRANS_COUNT": { + "description": "Alias for channel 7 TRANS_COUNT register", + "offset": 504, + "size": 32, + "reset_value": 0 + }, + "CH7_AL3_READ_ADDR_TRIG": { + "description": "Alias for channel 7 READ_ADDR register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 508, + "size": 32, + "reset_value": 0 + }, + "CH8_READ_ADDR": { + "description": "DMA Channel 8 Read Address pointer\\n\n This register updates automatically each time a read completes. The current value is the next address to be read by this channel.", + "offset": 512, + "size": 32, + "reset_value": 0 + }, + "CH8_WRITE_ADDR": { + "description": "DMA Channel 8 Write Address pointer\\n\n This register updates automatically each time a write completes. The current value is the next address to be written by this channel.", + "offset": 516, + "size": 32, + "reset_value": 0 + }, + "CH8_TRANS_COUNT": { + "description": "DMA Channel 8 Transfer Count\\n\n Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE).\\n\\n\n When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes.\\n\\n\n Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write.\\n\\n\n The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD.", + "offset": 520, + "size": 32, + "reset_value": 0 + }, + "CH8_CTRL_TRIG": { + "description": "DMA Channel 8 Control and Status", + "offset": 524, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "AHB_ERROR": { + "description": "Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag.", + "offset": 31, + "size": 1, + "access": "read-only" + }, + "READ_ERROR": { + "description": "If 1, the channel received a read bus error. Write one to clear.\\n\n READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later)", + "offset": 30, + "size": 1 + }, + "WRITE_ERROR": { + "description": "If 1, the channel received a write bus error. Write one to clear.\\n\n WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later)", + "offset": 29, + "size": 1 + }, + "BUSY": { + "description": "This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused.\\n\\n\n To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT.", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "SNIFF_EN": { + "description": "If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected.\\n\\n\n This allows checksum to be enabled or disabled on a per-control- block basis.", + "offset": 23, + "size": 1 + }, + "BSWAP": { + "description": "Apply byte-swap transformation to DMA data.\\n\n For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order.", + "offset": 22, + "size": 1 + }, + "IRQ_QUIET": { + "description": "In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain.\\n\\n\n This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks.", + "offset": 21, + "size": 1 + }, + "TREQ_SEL": { + "description": "Select a Transfer Request signal.\\n\n The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system).\\n\n 0x0 to 0x3a -> select DREQ n as TREQ", + "offset": 15, + "size": 6, + "enum": { + "size": 6, + "children": { + "enum_fields": { + "TIMER0": { + "description": "Select Timer 0 as TREQ", + "value": 59 + }, + "TIMER1": { + "description": "Select Timer 1 as TREQ", + "value": 60 + }, + "TIMER2": { + "description": "Select Timer 2 as TREQ (Optional)", + "value": 61 + }, + "TIMER3": { + "description": "Select Timer 3 as TREQ (Optional)", + "value": 62 + }, + "PERMANENT": { + "description": "Permanent request, for unpaced transfers.", + "value": 63 + } + } + } + } + }, + "CHAIN_TO": { + "description": "When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.", + "offset": 11, + "size": 4 + }, + "RING_SEL": { + "description": "Select whether RING_SIZE applies to read or write addresses.\\n\n If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped.", + "offset": 10, + "size": 1 + }, + "RING_SIZE": { + "description": "Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers.\\n\\n\n Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL.", + "offset": 6, + "size": 4, + "enum": { + "size": 4, + "children": { + "enum_fields": { + "RING_NONE": { + "value": 0 + } + } + } + } + }, + "INCR_WRITE": { + "description": "If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address.\\n\\n\n Generally this should be disabled for memory-to-peripheral transfers.", + "offset": 5, + "size": 1 + }, + "INCR_READ": { + "description": "If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address.\\n\\n\n Generally this should be disabled for peripheral-to-memory transfers.", + "offset": 4, + "size": 1 + }, + "DATA_SIZE": { + "description": "Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer.", + "offset": 2, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "SIZE_BYTE": { + "value": 0 + }, + "SIZE_HALFWORD": { + "value": 1 + }, + "SIZE_WORD": { + "value": 2 + } + } + } + } + }, + "HIGH_PRIORITY": { + "description": "HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels.\\n\\n\n This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput.", + "offset": 1, + "size": 1 + }, + "EN": { + "description": "DMA Channel Enable.\\n\n When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high)", + "offset": 0, + "size": 1 + } + } + } + }, + "CH8_AL1_CTRL": { + "description": "Alias for channel 8 CTRL register", + "offset": 528, + "size": 32, + "reset_value": 0 + }, + "CH8_AL1_READ_ADDR": { + "description": "Alias for channel 8 READ_ADDR register", + "offset": 532, + "size": 32, + "reset_value": 0 + }, + "CH8_AL1_WRITE_ADDR": { + "description": "Alias for channel 8 WRITE_ADDR register", + "offset": 536, + "size": 32, + "reset_value": 0 + }, + "CH8_AL1_TRANS_COUNT_TRIG": { + "description": "Alias for channel 8 TRANS_COUNT register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 540, + "size": 32, + "reset_value": 0 + }, + "CH8_AL2_CTRL": { + "description": "Alias for channel 8 CTRL register", + "offset": 544, + "size": 32, + "reset_value": 0 + }, + "CH8_AL2_TRANS_COUNT": { + "description": "Alias for channel 8 TRANS_COUNT register", + "offset": 548, + "size": 32, + "reset_value": 0 + }, + "CH8_AL2_READ_ADDR": { + "description": "Alias for channel 8 READ_ADDR register", + "offset": 552, + "size": 32, + "reset_value": 0 + }, + "CH8_AL2_WRITE_ADDR_TRIG": { + "description": "Alias for channel 8 WRITE_ADDR register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 556, + "size": 32, + "reset_value": 0 + }, + "CH8_AL3_CTRL": { + "description": "Alias for channel 8 CTRL register", + "offset": 560, + "size": 32, + "reset_value": 0 + }, + "CH8_AL3_WRITE_ADDR": { + "description": "Alias for channel 8 WRITE_ADDR register", + "offset": 564, + "size": 32, + "reset_value": 0 + }, + "CH8_AL3_TRANS_COUNT": { + "description": "Alias for channel 8 TRANS_COUNT register", + "offset": 568, + "size": 32, + "reset_value": 0 + }, + "CH8_AL3_READ_ADDR_TRIG": { + "description": "Alias for channel 8 READ_ADDR register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 572, + "size": 32, + "reset_value": 0 + }, + "CH9_READ_ADDR": { + "description": "DMA Channel 9 Read Address pointer\\n\n This register updates automatically each time a read completes. The current value is the next address to be read by this channel.", + "offset": 576, + "size": 32, + "reset_value": 0 + }, + "CH9_WRITE_ADDR": { + "description": "DMA Channel 9 Write Address pointer\\n\n This register updates automatically each time a write completes. The current value is the next address to be written by this channel.", + "offset": 580, + "size": 32, + "reset_value": 0 + }, + "CH9_TRANS_COUNT": { + "description": "DMA Channel 9 Transfer Count\\n\n Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE).\\n\\n\n When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes.\\n\\n\n Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write.\\n\\n\n The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD.", + "offset": 584, + "size": 32, + "reset_value": 0 + }, + "CH9_CTRL_TRIG": { + "description": "DMA Channel 9 Control and Status", + "offset": 588, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "AHB_ERROR": { + "description": "Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag.", + "offset": 31, + "size": 1, + "access": "read-only" + }, + "READ_ERROR": { + "description": "If 1, the channel received a read bus error. Write one to clear.\\n\n READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later)", + "offset": 30, + "size": 1 + }, + "WRITE_ERROR": { + "description": "If 1, the channel received a write bus error. Write one to clear.\\n\n WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later)", + "offset": 29, + "size": 1 + }, + "BUSY": { + "description": "This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused.\\n\\n\n To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT.", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "SNIFF_EN": { + "description": "If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected.\\n\\n\n This allows checksum to be enabled or disabled on a per-control- block basis.", + "offset": 23, + "size": 1 + }, + "BSWAP": { + "description": "Apply byte-swap transformation to DMA data.\\n\n For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order.", + "offset": 22, + "size": 1 + }, + "IRQ_QUIET": { + "description": "In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain.\\n\\n\n This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks.", + "offset": 21, + "size": 1 + }, + "TREQ_SEL": { + "description": "Select a Transfer Request signal.\\n\n The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system).\\n\n 0x0 to 0x3a -> select DREQ n as TREQ", + "offset": 15, + "size": 6, + "enum": { + "size": 6, + "children": { + "enum_fields": { + "TIMER0": { + "description": "Select Timer 0 as TREQ", + "value": 59 + }, + "TIMER1": { + "description": "Select Timer 1 as TREQ", + "value": 60 + }, + "TIMER2": { + "description": "Select Timer 2 as TREQ (Optional)", + "value": 61 + }, + "TIMER3": { + "description": "Select Timer 3 as TREQ (Optional)", + "value": 62 + }, + "PERMANENT": { + "description": "Permanent request, for unpaced transfers.", + "value": 63 + } + } + } + } + }, + "CHAIN_TO": { + "description": "When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.", + "offset": 11, + "size": 4 + }, + "RING_SEL": { + "description": "Select whether RING_SIZE applies to read or write addresses.\\n\n If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped.", + "offset": 10, + "size": 1 + }, + "RING_SIZE": { + "description": "Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers.\\n\\n\n Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL.", + "offset": 6, + "size": 4, + "enum": { + "size": 4, + "children": { + "enum_fields": { + "RING_NONE": { + "value": 0 + } + } + } + } + }, + "INCR_WRITE": { + "description": "If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address.\\n\\n\n Generally this should be disabled for memory-to-peripheral transfers.", + "offset": 5, + "size": 1 + }, + "INCR_READ": { + "description": "If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address.\\n\\n\n Generally this should be disabled for peripheral-to-memory transfers.", + "offset": 4, + "size": 1 + }, + "DATA_SIZE": { + "description": "Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer.", + "offset": 2, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "SIZE_BYTE": { + "value": 0 + }, + "SIZE_HALFWORD": { + "value": 1 + }, + "SIZE_WORD": { + "value": 2 + } + } + } + } + }, + "HIGH_PRIORITY": { + "description": "HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels.\\n\\n\n This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput.", + "offset": 1, + "size": 1 + }, + "EN": { + "description": "DMA Channel Enable.\\n\n When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high)", + "offset": 0, + "size": 1 + } + } + } + }, + "CH9_AL1_CTRL": { + "description": "Alias for channel 9 CTRL register", + "offset": 592, + "size": 32, + "reset_value": 0 + }, + "CH9_AL1_READ_ADDR": { + "description": "Alias for channel 9 READ_ADDR register", + "offset": 596, + "size": 32, + "reset_value": 0 + }, + "CH9_AL1_WRITE_ADDR": { + "description": "Alias for channel 9 WRITE_ADDR register", + "offset": 600, + "size": 32, + "reset_value": 0 + }, + "CH9_AL1_TRANS_COUNT_TRIG": { + "description": "Alias for channel 9 TRANS_COUNT register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 604, + "size": 32, + "reset_value": 0 + }, + "CH9_AL2_CTRL": { + "description": "Alias for channel 9 CTRL register", + "offset": 608, + "size": 32, + "reset_value": 0 + }, + "CH9_AL2_TRANS_COUNT": { + "description": "Alias for channel 9 TRANS_COUNT register", + "offset": 612, + "size": 32, + "reset_value": 0 + }, + "CH9_AL2_READ_ADDR": { + "description": "Alias for channel 9 READ_ADDR register", + "offset": 616, + "size": 32, + "reset_value": 0 + }, + "CH9_AL2_WRITE_ADDR_TRIG": { + "description": "Alias for channel 9 WRITE_ADDR register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 620, + "size": 32, + "reset_value": 0 + }, + "CH9_AL3_CTRL": { + "description": "Alias for channel 9 CTRL register", + "offset": 624, + "size": 32, + "reset_value": 0 + }, + "CH9_AL3_WRITE_ADDR": { + "description": "Alias for channel 9 WRITE_ADDR register", + "offset": 628, + "size": 32, + "reset_value": 0 + }, + "CH9_AL3_TRANS_COUNT": { + "description": "Alias for channel 9 TRANS_COUNT register", + "offset": 632, + "size": 32, + "reset_value": 0 + }, + "CH9_AL3_READ_ADDR_TRIG": { + "description": "Alias for channel 9 READ_ADDR register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 636, + "size": 32, + "reset_value": 0 + }, + "CH10_READ_ADDR": { + "description": "DMA Channel 10 Read Address pointer\\n\n This register updates automatically each time a read completes. The current value is the next address to be read by this channel.", + "offset": 640, + "size": 32, + "reset_value": 0 + }, + "CH10_WRITE_ADDR": { + "description": "DMA Channel 10 Write Address pointer\\n\n This register updates automatically each time a write completes. The current value is the next address to be written by this channel.", + "offset": 644, + "size": 32, + "reset_value": 0 + }, + "CH10_TRANS_COUNT": { + "description": "DMA Channel 10 Transfer Count\\n\n Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE).\\n\\n\n When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes.\\n\\n\n Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write.\\n\\n\n The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD.", + "offset": 648, + "size": 32, + "reset_value": 0 + }, + "CH10_CTRL_TRIG": { + "description": "DMA Channel 10 Control and Status", + "offset": 652, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "AHB_ERROR": { + "description": "Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag.", + "offset": 31, + "size": 1, + "access": "read-only" + }, + "READ_ERROR": { + "description": "If 1, the channel received a read bus error. Write one to clear.\\n\n READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later)", + "offset": 30, + "size": 1 + }, + "WRITE_ERROR": { + "description": "If 1, the channel received a write bus error. Write one to clear.\\n\n WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later)", + "offset": 29, + "size": 1 + }, + "BUSY": { + "description": "This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused.\\n\\n\n To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT.", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "SNIFF_EN": { + "description": "If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected.\\n\\n\n This allows checksum to be enabled or disabled on a per-control- block basis.", + "offset": 23, + "size": 1 + }, + "BSWAP": { + "description": "Apply byte-swap transformation to DMA data.\\n\n For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order.", + "offset": 22, + "size": 1 + }, + "IRQ_QUIET": { + "description": "In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain.\\n\\n\n This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks.", + "offset": 21, + "size": 1 + }, + "TREQ_SEL": { + "description": "Select a Transfer Request signal.\\n\n The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system).\\n\n 0x0 to 0x3a -> select DREQ n as TREQ", + "offset": 15, + "size": 6, + "enum": { + "size": 6, + "children": { + "enum_fields": { + "TIMER0": { + "description": "Select Timer 0 as TREQ", + "value": 59 + }, + "TIMER1": { + "description": "Select Timer 1 as TREQ", + "value": 60 + }, + "TIMER2": { + "description": "Select Timer 2 as TREQ (Optional)", + "value": 61 + }, + "TIMER3": { + "description": "Select Timer 3 as TREQ (Optional)", + "value": 62 + }, + "PERMANENT": { + "description": "Permanent request, for unpaced transfers.", + "value": 63 + } + } + } + } + }, + "CHAIN_TO": { + "description": "When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.", + "offset": 11, + "size": 4 + }, + "RING_SEL": { + "description": "Select whether RING_SIZE applies to read or write addresses.\\n\n If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped.", + "offset": 10, + "size": 1 + }, + "RING_SIZE": { + "description": "Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers.\\n\\n\n Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL.", + "offset": 6, + "size": 4, + "enum": { + "size": 4, + "children": { + "enum_fields": { + "RING_NONE": { + "value": 0 + } + } + } + } + }, + "INCR_WRITE": { + "description": "If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address.\\n\\n\n Generally this should be disabled for memory-to-peripheral transfers.", + "offset": 5, + "size": 1 + }, + "INCR_READ": { + "description": "If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address.\\n\\n\n Generally this should be disabled for peripheral-to-memory transfers.", + "offset": 4, + "size": 1 + }, + "DATA_SIZE": { + "description": "Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer.", + "offset": 2, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "SIZE_BYTE": { + "value": 0 + }, + "SIZE_HALFWORD": { + "value": 1 + }, + "SIZE_WORD": { + "value": 2 + } + } + } + } + }, + "HIGH_PRIORITY": { + "description": "HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels.\\n\\n\n This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput.", + "offset": 1, + "size": 1 + }, + "EN": { + "description": "DMA Channel Enable.\\n\n When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high)", + "offset": 0, + "size": 1 + } + } + } + }, + "CH10_AL1_CTRL": { + "description": "Alias for channel 10 CTRL register", + "offset": 656, + "size": 32, + "reset_value": 0 + }, + "CH10_AL1_READ_ADDR": { + "description": "Alias for channel 10 READ_ADDR register", + "offset": 660, + "size": 32, + "reset_value": 0 + }, + "CH10_AL1_WRITE_ADDR": { + "description": "Alias for channel 10 WRITE_ADDR register", + "offset": 664, + "size": 32, + "reset_value": 0 + }, + "CH10_AL1_TRANS_COUNT_TRIG": { + "description": "Alias for channel 10 TRANS_COUNT register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 668, + "size": 32, + "reset_value": 0 + }, + "CH10_AL2_CTRL": { + "description": "Alias for channel 10 CTRL register", + "offset": 672, + "size": 32, + "reset_value": 0 + }, + "CH10_AL2_TRANS_COUNT": { + "description": "Alias for channel 10 TRANS_COUNT register", + "offset": 676, + "size": 32, + "reset_value": 0 + }, + "CH10_AL2_READ_ADDR": { + "description": "Alias for channel 10 READ_ADDR register", + "offset": 680, + "size": 32, + "reset_value": 0 + }, + "CH10_AL2_WRITE_ADDR_TRIG": { + "description": "Alias for channel 10 WRITE_ADDR register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 684, + "size": 32, + "reset_value": 0 + }, + "CH10_AL3_CTRL": { + "description": "Alias for channel 10 CTRL register", + "offset": 688, + "size": 32, + "reset_value": 0 + }, + "CH10_AL3_WRITE_ADDR": { + "description": "Alias for channel 10 WRITE_ADDR register", + "offset": 692, + "size": 32, + "reset_value": 0 + }, + "CH10_AL3_TRANS_COUNT": { + "description": "Alias for channel 10 TRANS_COUNT register", + "offset": 696, + "size": 32, + "reset_value": 0 + }, + "CH10_AL3_READ_ADDR_TRIG": { + "description": "Alias for channel 10 READ_ADDR register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 700, + "size": 32, + "reset_value": 0 + }, + "CH11_READ_ADDR": { + "description": "DMA Channel 11 Read Address pointer\\n\n This register updates automatically each time a read completes. The current value is the next address to be read by this channel.", + "offset": 704, + "size": 32, + "reset_value": 0 + }, + "CH11_WRITE_ADDR": { + "description": "DMA Channel 11 Write Address pointer\\n\n This register updates automatically each time a write completes. The current value is the next address to be written by this channel.", + "offset": 708, + "size": 32, + "reset_value": 0 + }, + "CH11_TRANS_COUNT": { + "description": "DMA Channel 11 Transfer Count\\n\n Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE).\\n\\n\n When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes.\\n\\n\n Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write.\\n\\n\n The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD.", + "offset": 712, + "size": 32, + "reset_value": 0 + }, + "CH11_CTRL_TRIG": { + "description": "DMA Channel 11 Control and Status", + "offset": 716, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "AHB_ERROR": { + "description": "Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag.", + "offset": 31, + "size": 1, + "access": "read-only" + }, + "READ_ERROR": { + "description": "If 1, the channel received a read bus error. Write one to clear.\\n\n READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later)", + "offset": 30, + "size": 1 + }, + "WRITE_ERROR": { + "description": "If 1, the channel received a write bus error. Write one to clear.\\n\n WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later)", + "offset": 29, + "size": 1 + }, + "BUSY": { + "description": "This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused.\\n\\n\n To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT.", + "offset": 24, + "size": 1, + "access": "read-only" + }, + "SNIFF_EN": { + "description": "If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected.\\n\\n\n This allows checksum to be enabled or disabled on a per-control- block basis.", + "offset": 23, + "size": 1 + }, + "BSWAP": { + "description": "Apply byte-swap transformation to DMA data.\\n\n For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order.", + "offset": 22, + "size": 1 + }, + "IRQ_QUIET": { + "description": "In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain.\\n\\n\n This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks.", + "offset": 21, + "size": 1 + }, + "TREQ_SEL": { + "description": "Select a Transfer Request signal.\\n\n The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system).\\n\n 0x0 to 0x3a -> select DREQ n as TREQ", + "offset": 15, + "size": 6, + "enum": { + "size": 6, + "children": { + "enum_fields": { + "TIMER0": { + "description": "Select Timer 0 as TREQ", + "value": 59 + }, + "TIMER1": { + "description": "Select Timer 1 as TREQ", + "value": 60 + }, + "TIMER2": { + "description": "Select Timer 2 as TREQ (Optional)", + "value": 61 + }, + "TIMER3": { + "description": "Select Timer 3 as TREQ (Optional)", + "value": 62 + }, + "PERMANENT": { + "description": "Permanent request, for unpaced transfers.", + "value": 63 + } + } + } + } + }, + "CHAIN_TO": { + "description": "When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.", + "offset": 11, + "size": 4 + }, + "RING_SEL": { + "description": "Select whether RING_SIZE applies to read or write addresses.\\n\n If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped.", + "offset": 10, + "size": 1 + }, + "RING_SIZE": { + "description": "Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers.\\n\\n\n Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL.", + "offset": 6, + "size": 4, + "enum": { + "size": 4, + "children": { + "enum_fields": { + "RING_NONE": { + "value": 0 + } + } + } + } + }, + "INCR_WRITE": { + "description": "If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address.\\n\\n\n Generally this should be disabled for memory-to-peripheral transfers.", + "offset": 5, + "size": 1 + }, + "INCR_READ": { + "description": "If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address.\\n\\n\n Generally this should be disabled for peripheral-to-memory transfers.", + "offset": 4, + "size": 1 + }, + "DATA_SIZE": { + "description": "Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer.", + "offset": 2, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "SIZE_BYTE": { + "value": 0 + }, + "SIZE_HALFWORD": { + "value": 1 + }, + "SIZE_WORD": { + "value": 2 + } + } + } + } + }, + "HIGH_PRIORITY": { + "description": "HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels.\\n\\n\n This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput.", + "offset": 1, + "size": 1 + }, + "EN": { + "description": "DMA Channel Enable.\\n\n When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high)", + "offset": 0, + "size": 1 + } + } + } + }, + "CH11_AL1_CTRL": { + "description": "Alias for channel 11 CTRL register", + "offset": 720, + "size": 32, + "reset_value": 0 + }, + "CH11_AL1_READ_ADDR": { + "description": "Alias for channel 11 READ_ADDR register", + "offset": 724, + "size": 32, + "reset_value": 0 + }, + "CH11_AL1_WRITE_ADDR": { + "description": "Alias for channel 11 WRITE_ADDR register", + "offset": 728, + "size": 32, + "reset_value": 0 + }, + "CH11_AL1_TRANS_COUNT_TRIG": { + "description": "Alias for channel 11 TRANS_COUNT register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 732, + "size": 32, + "reset_value": 0 + }, + "CH11_AL2_CTRL": { + "description": "Alias for channel 11 CTRL register", + "offset": 736, + "size": 32, + "reset_value": 0 + }, + "CH11_AL2_TRANS_COUNT": { + "description": "Alias for channel 11 TRANS_COUNT register", + "offset": 740, + "size": 32, + "reset_value": 0 + }, + "CH11_AL2_READ_ADDR": { + "description": "Alias for channel 11 READ_ADDR register", + "offset": 744, + "size": 32, + "reset_value": 0 + }, + "CH11_AL2_WRITE_ADDR_TRIG": { + "description": "Alias for channel 11 WRITE_ADDR register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 748, + "size": 32, + "reset_value": 0 + }, + "CH11_AL3_CTRL": { + "description": "Alias for channel 11 CTRL register", + "offset": 752, + "size": 32, + "reset_value": 0 + }, + "CH11_AL3_WRITE_ADDR": { + "description": "Alias for channel 11 WRITE_ADDR register", + "offset": 756, + "size": 32, + "reset_value": 0 + }, + "CH11_AL3_TRANS_COUNT": { + "description": "Alias for channel 11 TRANS_COUNT register", + "offset": 760, + "size": 32, + "reset_value": 0 + }, + "CH11_AL3_READ_ADDR_TRIG": { + "description": "Alias for channel 11 READ_ADDR register\\n\n This is a trigger register (0xc). Writing a nonzero value will\\n\n reload the channel counter and start the channel.", + "offset": 764, + "size": 32, + "reset_value": 0 + }, + "INTR": { + "description": "Interrupt Status (raw)", + "offset": 1024, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INTR": { + "description": "Raw interrupt status for DMA Channels 0..15. Bit n corresponds to channel n. Ignores any masking or forcing. Channel interrupts can be cleared by writing a bit mask to INTR, INTS0 or INTS1.\\n\\n\n Channel interrupts can be routed to either of two system-level IRQs based on INTE0 and INTE1.\\n\\n\n This can be used vector different channel interrupts to different ISRs: this might be done to allow NVIC IRQ preemption for more time-critical channels, or to spread IRQ load across different cores.\\n\\n\n It is also valid to ignore this behaviour and just use INTE0/INTS0/IRQ 0.", + "offset": 0, + "size": 16, + "access": "read-only" + } + } + } + }, + "INTE0": { + "description": "Interrupt Enables for IRQ 0", + "offset": 1028, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INTE0": { + "description": "Set bit n to pass interrupts from channel n to DMA IRQ 0.", + "offset": 0, + "size": 16 + } + } + } + }, + "INTF0": { + "description": "Force Interrupts", + "offset": 1032, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INTF0": { + "description": "Write 1s to force the corresponding bits in INTE0. The interrupt remains asserted until INTF0 is cleared.", + "offset": 0, + "size": 16 + } + } + } + }, + "INTS0": { + "description": "Interrupt Status for IRQ 0", + "offset": 1036, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INTS0": { + "description": "Indicates active channel interrupt requests which are currently causing IRQ 0 to be asserted.\\n\n Channel interrupts can be cleared by writing a bit mask here.", + "offset": 0, + "size": 16 + } + } + } + }, + "INTE1": { + "description": "Interrupt Enables for IRQ 1", + "offset": 1044, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INTE1": { + "description": "Set bit n to pass interrupts from channel n to DMA IRQ 1.", + "offset": 0, + "size": 16 + } + } + } + }, + "INTF1": { + "description": "Force Interrupts for IRQ 1", + "offset": 1048, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INTF1": { + "description": "Write 1s to force the corresponding bits in INTE0. The interrupt remains asserted until INTF0 is cleared.", + "offset": 0, + "size": 16 + } + } + } + }, + "INTS1": { + "description": "Interrupt Status (masked) for IRQ 1", + "offset": 1052, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "INTS1": { + "description": "Indicates active channel interrupt requests which are currently causing IRQ 1 to be asserted.\\n\n Channel interrupts can be cleared by writing a bit mask here.", + "offset": 0, + "size": 16 + } + } + } + }, + "TIMER0": { + "description": "Pacing (X/Y) Fractional Timer\\n\n The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less.", + "offset": 1056, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "X": { + "description": "Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer.", + "offset": 16, + "size": 16 + }, + "Y": { + "description": "Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer.", + "offset": 0, + "size": 16 + } + } + } + }, + "TIMER1": { + "description": "Pacing (X/Y) Fractional Timer\\n\n The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less.", + "offset": 1060, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "X": { + "description": "Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer.", + "offset": 16, + "size": 16 + }, + "Y": { + "description": "Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer.", + "offset": 0, + "size": 16 + } + } + } + }, + "TIMER2": { + "description": "Pacing (X/Y) Fractional Timer\\n\n The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less.", + "offset": 1064, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "X": { + "description": "Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer.", + "offset": 16, + "size": 16 + }, + "Y": { + "description": "Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer.", + "offset": 0, + "size": 16 + } + } + } + }, + "TIMER3": { + "description": "Pacing (X/Y) Fractional Timer\\n\n The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less.", + "offset": 1068, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "X": { + "description": "Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer.", + "offset": 16, + "size": 16 + }, + "Y": { + "description": "Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer.", + "offset": 0, + "size": 16 + } + } + } + }, + "MULTI_CHAN_TRIGGER": { + "description": "Trigger one or more channels simultaneously", + "offset": 1072, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "MULTI_CHAN_TRIGGER": { + "description": "Each bit in this register corresponds to a DMA channel. Writing a 1 to the relevant bit is the same as writing to that channel's trigger register; the channel will start if it is currently enabled and not already busy.", + "offset": 0, + "size": 16 + } + } + } + }, + "SNIFF_CTRL": { + "description": "Sniffer Control", + "offset": 1076, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "OUT_INV": { + "description": "If set, the result appears inverted (bitwise complement) when read. This does not affect the way the checksum is calculated; the result is transformed on-the-fly between the result register and the bus.", + "offset": 11, + "size": 1 + }, + "OUT_REV": { + "description": "If set, the result appears bit-reversed when read. This does not affect the way the checksum is calculated; the result is transformed on-the-fly between the result register and the bus.", + "offset": 10, + "size": 1 + }, + "BSWAP": { + "description": "Locally perform a byte reverse on the sniffed data, before feeding into checksum.\\n\\n\n Note that the sniff hardware is downstream of the DMA channel byteswap performed in the read master: if channel CTRL_BSWAP and SNIFF_CTRL_BSWAP are both enabled, their effects cancel from the sniffer's point of view.", + "offset": 9, + "size": 1 + }, + "CALC": { + "offset": 5, + "size": 4, + "enum": { + "size": 4, + "children": { + "enum_fields": { + "CRC32": { + "description": "Calculate a CRC-32 (IEEE802.3 polynomial)", + "value": 0 + }, + "CRC32R": { + "description": "Calculate a CRC-32 (IEEE802.3 polynomial) with bit reversed data", + "value": 1 + }, + "CRC16": { + "description": "Calculate a CRC-16-CCITT", + "value": 2 + }, + "CRC16R": { + "description": "Calculate a CRC-16-CCITT with bit reversed data", + "value": 3 + }, + "EVEN": { + "description": "XOR reduction over all data. == 1 if the total 1 population count is odd.", + "value": 14 + }, + "SUM": { + "description": "Calculate a simple 32-bit checksum (addition with a 32 bit accumulator)", + "value": 15 + } + } + } + } + }, + "DMACH": { + "description": "DMA channel for Sniffer to observe", + "offset": 1, + "size": 4 + }, + "EN": { + "description": "Enable sniffer", + "offset": 0, + "size": 1 + } + } + } + }, + "SNIFF_DATA": { + "description": "Data accumulator for sniff hardware\\n\n Write an initial seed value here before starting a DMA transfer on the channel indicated by SNIFF_CTRL_DMACH. The hardware will update this register each time it observes a read from the indicated channel. Once the channel completes, the final result can be read from this register.", + "offset": 1080, + "size": 32, + "reset_value": 0 + }, + "FIFO_LEVELS": { + "description": "Debug RAF, WAF, TDF levels", + "offset": 1088, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "RAF_LVL": { + "description": "Current Read-Address-FIFO fill level", + "offset": 16, + "size": 8, + "access": "read-only" + }, + "WAF_LVL": { + "description": "Current Write-Address-FIFO fill level", + "offset": 8, + "size": 8, + "access": "read-only" + }, + "TDF_LVL": { + "description": "Current Transfer-Data-FIFO fill level", + "offset": 0, + "size": 8, + "access": "read-only" + } + } + } + }, + "CHAN_ABORT": { + "description": "Abort an in-progress transfer sequence on one or more channels", + "offset": 1092, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CHAN_ABORT": { + "description": "Each bit corresponds to a channel. Writing a 1 aborts whatever transfer sequence is in progress on that channel. The bit will remain high until any in-flight transfers have been flushed through the address and data FIFOs.\\n\\n\n After writing, this register must be polled until it returns all-zero. Until this point, it is unsafe to restart the channel.", + "offset": 0, + "size": 16 + } + } + } + }, + "N_CHANNELS": { + "description": "The number of channels this DMA instance is equipped with. This DMA supports up to 16 hardware channels, but can be configured with as few as one, to minimise silicon area.", + "offset": 1096, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "N_CHANNELS": { + "offset": 0, + "size": 5, + "access": "read-only" + } + } + } + }, + "CH0_DBG_CTDREQ": { + "description": "Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake.", + "offset": 2048, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CH0_DBG_CTDREQ": { + "offset": 0, + "size": 6 + } + } + } + }, + "CH0_DBG_TCR": { + "description": "Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer", + "offset": 2052, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "CH1_DBG_CTDREQ": { + "description": "Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake.", + "offset": 2112, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CH1_DBG_CTDREQ": { + "offset": 0, + "size": 6 + } + } + } + }, + "CH1_DBG_TCR": { + "description": "Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer", + "offset": 2116, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "CH2_DBG_CTDREQ": { + "description": "Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake.", + "offset": 2176, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CH2_DBG_CTDREQ": { + "offset": 0, + "size": 6 + } + } + } + }, + "CH2_DBG_TCR": { + "description": "Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer", + "offset": 2180, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "CH3_DBG_CTDREQ": { + "description": "Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake.", + "offset": 2240, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CH3_DBG_CTDREQ": { + "offset": 0, + "size": 6 + } + } + } + }, + "CH3_DBG_TCR": { + "description": "Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer", + "offset": 2244, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "CH4_DBG_CTDREQ": { + "description": "Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake.", + "offset": 2304, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CH4_DBG_CTDREQ": { + "offset": 0, + "size": 6 + } + } + } + }, + "CH4_DBG_TCR": { + "description": "Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer", + "offset": 2308, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "CH5_DBG_CTDREQ": { + "description": "Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake.", + "offset": 2368, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CH5_DBG_CTDREQ": { + "offset": 0, + "size": 6 + } + } + } + }, + "CH5_DBG_TCR": { + "description": "Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer", + "offset": 2372, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "CH6_DBG_CTDREQ": { + "description": "Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake.", + "offset": 2432, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CH6_DBG_CTDREQ": { + "offset": 0, + "size": 6 + } + } + } + }, + "CH6_DBG_TCR": { + "description": "Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer", + "offset": 2436, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "CH7_DBG_CTDREQ": { + "description": "Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake.", + "offset": 2496, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CH7_DBG_CTDREQ": { + "offset": 0, + "size": 6 + } + } + } + }, + "CH7_DBG_TCR": { + "description": "Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer", + "offset": 2500, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "CH8_DBG_CTDREQ": { + "description": "Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake.", + "offset": 2560, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CH8_DBG_CTDREQ": { + "offset": 0, + "size": 6 + } + } + } + }, + "CH8_DBG_TCR": { + "description": "Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer", + "offset": 2564, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "CH9_DBG_CTDREQ": { + "description": "Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake.", + "offset": 2624, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CH9_DBG_CTDREQ": { + "offset": 0, + "size": 6 + } + } + } + }, + "CH9_DBG_TCR": { + "description": "Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer", + "offset": 2628, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "CH10_DBG_CTDREQ": { + "description": "Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake.", + "offset": 2688, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CH10_DBG_CTDREQ": { + "offset": 0, + "size": 6 + } + } + } + }, + "CH10_DBG_TCR": { + "description": "Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer", + "offset": 2692, + "size": 32, + "reset_value": 0, + "access": "read-only" + }, + "CH11_DBG_CTDREQ": { + "description": "Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake.", + "offset": 2752, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "CH11_DBG_CTDREQ": { + "offset": 0, + "size": 6 + } + } + } + }, + "CH11_DBG_TCR": { + "description": "Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer", + "offset": 2756, + "size": 32, + "reset_value": 0, + "access": "read-only" + } + } + } + }, + "USBCTRL_DPRAM": { + "description": "DPRAM layout for USB device.", + "children": { + "registers": { + "SETUP_PACKET_LOW": { + "description": "Bytes 0-3 of the SETUP packet from the host.", + "offset": 0, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "WVALUE": { + "offset": 16, + "size": 16 + }, + "BREQUEST": { + "offset": 8, + "size": 8 + }, + "BMREQUESTTYPE": { + "offset": 0, + "size": 8 + } + } + } + }, + "SETUP_PACKET_HIGH": { + "description": "Bytes 4-7 of the setup packet from the host.", + "offset": 4, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "WLENGTH": { + "offset": 16, + "size": 16 + }, + "WINDEX": { + "offset": 0, + "size": 16 + } + } + } + }, + "EP1_IN_CONTROL": { + "offset": 8, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP1_OUT_CONTROL": { + "offset": 12, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP2_IN_CONTROL": { + "offset": 16, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP2_OUT_CONTROL": { + "offset": 20, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP3_IN_CONTROL": { + "offset": 24, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP3_OUT_CONTROL": { + "offset": 28, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP4_IN_CONTROL": { + "offset": 32, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP4_OUT_CONTROL": { + "offset": 36, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP5_IN_CONTROL": { + "offset": 40, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP5_OUT_CONTROL": { + "offset": 44, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP6_IN_CONTROL": { + "offset": 48, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP6_OUT_CONTROL": { + "offset": 52, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP7_IN_CONTROL": { + "offset": 56, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP7_OUT_CONTROL": { + "offset": 60, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP8_IN_CONTROL": { + "offset": 64, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP8_OUT_CONTROL": { + "offset": 68, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP9_IN_CONTROL": { + "offset": 72, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP9_OUT_CONTROL": { + "offset": 76, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP10_IN_CONTROL": { + "offset": 80, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP10_OUT_CONTROL": { + "offset": 84, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP11_IN_CONTROL": { + "offset": 88, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP11_OUT_CONTROL": { + "offset": 92, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP12_IN_CONTROL": { + "offset": 96, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP12_OUT_CONTROL": { + "offset": 100, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP13_IN_CONTROL": { + "offset": 104, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP13_OUT_CONTROL": { + "offset": 108, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP14_IN_CONTROL": { + "offset": 112, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP14_OUT_CONTROL": { + "offset": 116, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP15_IN_CONTROL": { + "offset": 120, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP15_OUT_CONTROL": { + "offset": 124, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "ENABLE": { + "description": "Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set.", + "offset": 31, + "size": 1 + }, + "DOUBLE_BUFFERED": { + "description": "This endpoint is double buffered.", + "offset": 30, + "size": 1 + }, + "INTERRUPT_PER_BUFF": { + "description": "Trigger an interrupt each time a buffer is done.", + "offset": 29, + "size": 1 + }, + "INTERRUPT_PER_DOUBLE_BUFF": { + "description": "Trigger an interrupt each time both buffers are done. Only valid in double buffered mode.", + "offset": 28, + "size": 1 + }, + "ENDPOINT_TYPE": { + "offset": 26, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "Control": { + "value": 0 + }, + "Isochronous": { + "value": 1 + }, + "Bulk": { + "value": 2 + }, + "Interrupt": { + "value": 3 + } + } + } + } + }, + "INTERRUPT_ON_STALL": { + "description": "Trigger an interrupt if a STALL is sent. Intended for debug only.", + "offset": 17, + "size": 1 + }, + "INTERRUPT_ON_NAK": { + "description": "Trigger an interrupt if a NAK is sent. Intended for debug only.", + "offset": 16, + "size": 1 + }, + "BUFFER_ADDRESS": { + "description": "64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM.", + "offset": 0, + "size": 16 + } + } + } + }, + "EP0_IN_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 128, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP0_OUT_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 132, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP1_IN_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 136, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP1_OUT_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 140, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP2_IN_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 144, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP2_OUT_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 148, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP3_IN_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 152, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP3_OUT_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 156, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP4_IN_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 160, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP4_OUT_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 164, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP5_IN_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 168, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP5_OUT_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 172, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP6_IN_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 176, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP6_OUT_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 180, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP7_IN_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 184, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP7_OUT_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 188, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP8_IN_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 192, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP8_OUT_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 196, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP9_IN_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 200, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP9_OUT_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 204, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP10_IN_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 208, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP10_OUT_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 212, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP11_IN_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 216, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP11_OUT_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 220, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP12_IN_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 224, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP12_OUT_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 228, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP13_IN_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 232, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP13_OUT_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 236, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP14_IN_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 240, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP14_OUT_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 244, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP15_IN_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 248, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + }, + "EP15_OUT_BUFFER_CONTROL": { + "description": "Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1.\\n\n Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode.", + "offset": 252, + "size": 32, + "reset_value": 0, + "children": { + "fields": { + "FULL_1": { + "description": "Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 31, + "size": 1 + }, + "LAST_1": { + "description": "Buffer 1 is the last buffer of the transfer.", + "offset": 30, + "size": 1 + }, + "PID_1": { + "description": "The data pid of buffer 1.", + "offset": 29, + "size": 1 + }, + "DOUBLE_BUFFER_ISO_OFFSET": { + "description": "The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint.\\n\n For a non Isochronous endpoint the offset is always 64 bytes.", + "offset": 27, + "size": 2, + "enum": { + "size": 2, + "children": { + "enum_fields": { + "128": { + "value": 0 + }, + "256": { + "value": 1 + }, + "512": { + "value": 2 + }, + "1024": { + "value": 3 + } + } + } + } + }, + "AVAILABLE_1": { + "description": "Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 26, + "size": 1 + }, + "LENGTH_1": { + "description": "The length of the data in buffer 1.", + "offset": 16, + "size": 10 + }, + "FULL_0": { + "description": "Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data.", + "offset": 15, + "size": 1 + }, + "LAST_0": { + "description": "Buffer 0 is the last buffer of the transfer.", + "offset": 14, + "size": 1 + }, + "PID_0": { + "description": "The data pid of buffer 0.", + "offset": 13, + "size": 1 + }, + "RESET": { + "description": "Reset the buffer selector to buffer 0.", + "offset": 12, + "size": 1 + }, + "STALL": { + "description": "Reply with a stall (valid for both buffers).", + "offset": 11, + "size": 1 + }, + "AVAILABLE_0": { + "description": "Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back.", + "offset": 10, + "size": 1 + }, + "LENGTH_0": { + "description": "The length of the data in buffer 0.", + "offset": 0, + "size": 10 + } + } + } + } + } + } + } + } + }, + "devices": { + "RP2040": { + "arch": "cortex_m0plus", + "properties": { + "cpu.nvic_prio_bits": "2", + "cpu.mpu": "true", + "cpu.fpu": "false", + "cpu.num_interrupts": "26", + "cpu.vtor": "1", + "cpu.revision": "r0p1", + "cpu.vendor_systick_config": "false", + "license": "\n Copyright (c) 2020 Raspberry Pi (Trading) Ltd. \\n\n \\n\n SPDX-License-Identifier: BSD-3-Clause\n ", + "cpu.name": "CM0PLUS", + "cpu.endian": "little" + }, + "children": { + "interrupts": { + "NMI": { + "index": -14 + }, + "HardFault": { + "index": -13 + }, + "SVCall": { + "index": -5 + }, + "PendSV": { + "index": -2 + }, + "SysTick": { + "index": -1 + }, + "XIP_IRQ": { + "index": 6 + }, + "CLOCKS_IRQ": { + "index": 17 + }, + "IO_IRQ_BANK0": { + "index": 13 + }, + "IO_IRQ_QSPI": { + "index": 14 + }, + "UART0_IRQ": { + "index": 20 + }, + "UART1_IRQ": { + "index": 21 + }, + "SPI0_IRQ": { + "index": 18 + }, + "SPI1_IRQ": { + "index": 19 + }, + "I2C0_IRQ": { + "index": 23 + }, + "I2C1_IRQ": { + "index": 24 + }, + "ADC_IRQ_FIFO": { + "index": 22 + }, + "PWM_IRQ_WRAP": { + "index": 4 + }, + "TIMER_IRQ_0": { + "index": 0 + }, + "TIMER_IRQ_1": { + "index": 1 + }, + "TIMER_IRQ_2": { + "index": 2 + }, + "TIMER_IRQ_3": { + "index": 3 + }, + "RTC_IRQ": { + "index": 25 + }, + "DMA_IRQ_0": { + "index": 11 + }, + "DMA_IRQ_1": { + "index": 12 + }, + "USBCTRL_IRQ": { + "index": 5 + }, + "PIO0_IRQ_0": { + "index": 7 + }, + "PIO0_IRQ_1": { + "index": 8 + }, + "PIO1_IRQ_0": { + "index": 9 + }, + "PIO1_IRQ_1": { + "index": 10 + }, + "SIO_IRQ_PROC0": { + "index": 15 + }, + "SIO_IRQ_PROC1": { + "index": 16 + } + }, + "peripheral_instances": { + "SysTick": { + "offset": 3758153744, + "type": "types.peripherals.SCS.children.register_groups.SysTick" + }, + "SCB": { + "offset": 3758157056, + "type": "types.peripherals.SCS" + }, + "NVIC": { + "offset": 3758153984, + "type": "types.peripherals.SCS" + }, + "MPU": { + "offset": 3472, + "type": "types.peripherals.SCS" + }, + "XIP_CTRL": { + "description": "QSPI flash execute-in-place block", + "offset": 335544320, + "version": "1", + "type": "types.peripherals.XIP_CTRL" + }, + "XIP_SSI": { + "description": "DW_apb_ssi has the following features:\\n\n * APB interface – Allows for easy integration into a DesignWare Synthesizable Components for AMBA 2 implementation.\\n\n * APB3 and APB4 protocol support.\\n\n * Scalable APB data bus width – Supports APB data bus widths of 8, 16, and 32 bits.\\n\n * Serial-master or serial-slave operation – Enables serial communication with serial-master or serial-slave peripheral devices.\\n\n * Programmable Dual/Quad/Octal SPI support in Master Mode.\\n\n * Dual Data Rate (DDR) and Read Data Strobe (RDS) Support - Enables the DW_apb_ssi master to perform operations with the device in DDR and RDS modes when working in Dual/Quad/Octal mode of operation.\\n\n * Data Mask Support - Enables the DW_apb_ssi to selectively update the bytes in the device. This feature is applicable only in enhanced SPI modes.\\n\n * eXecute-In-Place (XIP) support - Enables the DW_apb_ssi master to behave as a memory mapped I/O and fetches the data from the device based on the APB read request. This feature is applicable only in enhanced SPI modes.\\n\n * DMA Controller Interface – Enables the DW_apb_ssi to interface to a DMA controller over the bus using a handshaking interface for transfer requests.\\n\n * Independent masking of interrupts – Master collision, transmit FIFO overflow, transmit FIFO empty, receive FIFO full, receive FIFO underflow, and receive FIFO overflow interrupts can all be masked independently.\\n\n * Multi-master contention detection – Informs the processor of multiple serial-master accesses on the serial bus.\\n\n * Bypass of meta-stability flip-flops for synchronous clocks – When the APB clock (pclk) and the DW_apb_ssi serial clock (ssi_clk) are synchronous, meta-stable flip-flops are not used when transferring control signals across these clock domains.\\n\n * Programmable delay on the sample time of the received serial data bit (rxd); enables programmable control of routing delays resulting in higher serial data-bit rates.\\n\n * Programmable features:\\n\n - Serial interface operation – Choice of Motorola SPI, Texas Instruments Synchronous Serial Protocol or National Semiconductor Microwire.\\n\n - Clock bit-rate – Dynamic control of the serial bit rate of the data transfer; used in only serial-master mode of operation.\\n\n - Data Item size (4 to 32 bits) – Item size of each data transfer under the control of the programmer.\\n\n * Configured features:\\n\n - FIFO depth – 16 words deep. The FIFO width is fixed at 32 bits.\\n\n - 1 slave select output.\\n\n - Hardware slave-select – Dedicated hardware slave-select line.\\n\n - Combined interrupt line - one combined interrupt line from the DW_apb_ssi to the interrupt controller.\\n\n - Interrupt polarity – active high interrupt lines.\\n\n - Serial clock polarity – low serial-clock polarity directly after reset.\\n\n - Serial clock phase – capture on first edge of serial-clock directly after reset.", + "offset": 402653184, + "version": "1", + "type": "types.peripherals.XIP_SSI" + }, + "SYSINFO": { + "offset": 1073741824, + "version": "1", + "type": "types.peripherals.SYSINFO" + }, + "SYSCFG": { + "description": "Register block for various chip control signals", + "offset": 1073758208, + "version": "1", + "type": "types.peripherals.SYSCFG" + }, + "CLOCKS": { + "offset": 1073774592, + "version": "1", + "type": "types.peripherals.CLOCKS" + }, + "RESETS": { + "offset": 1073790976, + "version": "1", + "type": "types.peripherals.RESETS" + }, + "PSM": { + "offset": 1073807360, + "version": "1", + "type": "types.peripherals.PSM" + }, + "IO_BANK0": { + "offset": 1073823744, + "version": "1", + "type": "types.peripherals.IO_BANK0" + }, + "IO_QSPI": { + "offset": 1073840128, + "version": "1", + "type": "types.peripherals.IO_QSPI" + }, + "PADS_BANK0": { + "offset": 1073856512, + "version": "1", + "type": "types.peripherals.PADS_BANK0" + }, + "PADS_QSPI": { + "offset": 1073872896, + "version": "1", + "type": "types.peripherals.PADS_QSPI" + }, + "XOSC": { + "description": "Controls the crystal oscillator", + "offset": 1073889280, + "version": "1", + "type": "types.peripherals.XOSC" + }, + "PLL_SYS": { + "offset": 1073905664, + "version": "1", + "type": "types.peripherals.PLL_SYS" + }, + "PLL_USB": { + "offset": 1073922048, + "type": "types.peripherals.PLL_SYS" + }, + "BUSCTRL": { + "description": "Register block for busfabric control signals and performance counters", + "offset": 1073938432, + "version": "1", + "type": "types.peripherals.BUSCTRL" + }, + "UART0": { + "offset": 1073954816, + "version": "1", + "type": "types.peripherals.UART0" + }, + "UART1": { + "offset": 1073971200, + "type": "types.peripherals.UART0" + }, + "SPI0": { + "offset": 1073987584, + "version": "1", + "type": "types.peripherals.SPI0" + }, + "SPI1": { + "offset": 1074003968, + "type": "types.peripherals.SPI0" + }, + "I2C0": { + "description": "DW_apb_i2c address block\\n\\n\n List of configuration constants for the Synopsys I2C hardware (you may see references to these in I2C register header; these are *fixed* values, set at hardware design time):\\n\\n\n IC_ULTRA_FAST_MODE ................ 0x0\\n\n IC_UFM_TBUF_CNT_DEFAULT ........... 0x8\\n\n IC_UFM_SCL_LOW_COUNT .............. 0x0008\\n\n IC_UFM_SCL_HIGH_COUNT ............. 0x0006\\n\n IC_TX_TL .......................... 0x0\\n\n IC_TX_CMD_BLOCK ................... 0x1\\n\n IC_HAS_DMA ........................ 0x1\\n\n IC_HAS_ASYNC_FIFO ................. 0x0\\n\n IC_SMBUS_ARP ...................... 0x0\\n\n IC_FIRST_DATA_BYTE_STATUS ......... 0x1\\n\n IC_INTR_IO ........................ 0x1\\n\n IC_MASTER_MODE .................... 0x1\\n\n IC_DEFAULT_ACK_GENERAL_CALL ....... 0x1\\n\n IC_INTR_POL ....................... 0x1\\n\n IC_OPTIONAL_SAR ................... 0x0\\n\n IC_DEFAULT_TAR_SLAVE_ADDR ......... 0x055\\n\n IC_DEFAULT_SLAVE_ADDR ............. 0x055\\n\n IC_DEFAULT_HS_SPKLEN .............. 0x1\\n\n IC_FS_SCL_HIGH_COUNT .............. 0x0006\\n\n IC_HS_SCL_LOW_COUNT ............... 0x0008\\n\n IC_DEVICE_ID_VALUE ................ 0x0\\n\n IC_10BITADDR_MASTER ............... 0x0\\n\n IC_CLK_FREQ_OPTIMIZATION .......... 0x0\\n\n IC_DEFAULT_FS_SPKLEN .............. 0x7\\n\n IC_ADD_ENCODED_PARAMS ............. 0x0\\n\n IC_DEFAULT_SDA_HOLD ............... 0x000001\\n\n IC_DEFAULT_SDA_SETUP .............. 0x64\\n\n IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT . 0x0\\n\n IC_CLOCK_PERIOD ................... 100\\n\n IC_EMPTYFIFO_HOLD_MASTER_EN ....... 1\\n\n IC_RESTART_EN ..................... 0x1\\n\n IC_TX_CMD_BLOCK_DEFAULT ........... 0x0\\n\n IC_BUS_CLEAR_FEATURE .............. 0x0\\n\n IC_CAP_LOADING .................... 100\\n\n IC_FS_SCL_LOW_COUNT ............... 0x000d\\n\n APB_DATA_WIDTH .................... 32\\n\n IC_SDA_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff\\n\n IC_SLV_DATA_NACK_ONLY ............. 0x1\\n\n IC_10BITADDR_SLAVE ................ 0x0\\n\n IC_CLK_TYPE ....................... 0x0\\n\n IC_SMBUS_UDID_MSB ................. 0x0\\n\n IC_SMBUS_SUSPEND_ALERT ............ 0x0\\n\n IC_HS_SCL_HIGH_COUNT .............. 0x0006\\n\n IC_SLV_RESTART_DET_EN ............. 0x1\\n\n IC_SMBUS .......................... 0x0\\n\n IC_OPTIONAL_SAR_DEFAULT ........... 0x0\\n\n IC_PERSISTANT_SLV_ADDR_DEFAULT .... 0x0\\n\n IC_USE_COUNTS ..................... 0x0\\n\n IC_RX_BUFFER_DEPTH ................ 16\\n\n IC_SCL_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff\\n\n IC_RX_FULL_HLD_BUS_EN ............. 0x1\\n\n IC_SLAVE_DISABLE .................. 0x1\\n\n IC_RX_TL .......................... 0x0\\n\n IC_DEVICE_ID ...................... 0x0\\n\n IC_HC_COUNT_VALUES ................ 0x0\\n\n I2C_DYNAMIC_TAR_UPDATE ............ 0\\n\n IC_SMBUS_CLK_LOW_MEXT_DEFAULT ..... 0xffffffff\\n\n IC_SMBUS_CLK_LOW_SEXT_DEFAULT ..... 0xffffffff\\n\n IC_HS_MASTER_CODE ................. 0x1\\n\n IC_SMBUS_RST_IDLE_CNT_DEFAULT ..... 0xffff\\n\n IC_SMBUS_UDID_LSB_DEFAULT ......... 0xffffffff\\n\n IC_SS_SCL_HIGH_COUNT .............. 0x0028\\n\n IC_SS_SCL_LOW_COUNT ............... 0x002f\\n\n IC_MAX_SPEED_MODE ................. 0x2\\n\n IC_STAT_FOR_CLK_STRETCH ........... 0x0\\n\n IC_STOP_DET_IF_MASTER_ACTIVE ...... 0x0\\n\n IC_DEFAULT_UFM_SPKLEN ............. 0x1\\n\n IC_TX_BUFFER_DEPTH ................ 16", + "offset": 1074020352, + "version": "1", + "type": "types.peripherals.I2C0" + }, + "I2C1": { + "offset": 1074036736, + "type": "types.peripherals.I2C0" + }, + "ADC": { + "description": "Control and data interface to SAR ADC", + "offset": 1074053120, + "version": "2", + "type": "types.peripherals.ADC" + }, + "PWM": { + "description": "Simple PWM", + "offset": 1074069504, + "version": "1", + "type": "types.peripherals.PWM" + }, + "TIMER": { + "description": "Controls time and alarms\\n\n time is a 64 bit value indicating the time in usec since power-on\\n\n timeh is the top 32 bits of time & timel is the bottom 32 bits\\n\n to change time write to timelw before timehw\\n\n to read time read from timelr before timehr\\n\n An alarm is set by setting alarm_enable and writing to the corresponding alarm register\\n\n When an alarm is pending, the corresponding alarm_running signal will be high\\n\n An alarm can be cancelled before it has finished by clearing the alarm_enable\\n\n When an alarm fires, the corresponding alarm_irq is set and alarm_running is cleared\\n\n To clear the interrupt write a 1 to the corresponding alarm_irq", + "offset": 1074085888, + "version": "1", + "type": "types.peripherals.TIMER" + }, + "WATCHDOG": { + "offset": 1074102272, + "version": "1", + "type": "types.peripherals.WATCHDOG" + }, + "RTC": { + "description": "Register block to control RTC", + "offset": 1074118656, + "version": "1", + "type": "types.peripherals.RTC" + }, + "ROSC": { + "offset": 1074135040, + "version": "1", + "type": "types.peripherals.ROSC" + }, + "VREG_AND_CHIP_RESET": { + "description": "control and status for on-chip voltage regulator and chip level reset subsystem", + "offset": 1074151424, + "version": "1", + "type": "types.peripherals.VREG_AND_CHIP_RESET" + }, + "TBMAN": { + "description": "Testbench manager. Allows the programmer to know what platform their software is running on.", + "offset": 1074184192, + "version": "1", + "type": "types.peripherals.TBMAN" + }, + "DMA": { + "description": "DMA with separate read and write masters", + "offset": 1342177280, + "version": "1", + "type": "types.peripherals.DMA" + }, + "USBCTRL_DPRAM": { + "description": "DPRAM layout for USB device.", + "offset": 1343225856, + "version": "1", + "type": "types.peripherals.USBCTRL_DPRAM" + }, + "USBCTRL_REGS": { + "description": "USB FS/LS controller device registers", + "offset": 1343291392, + "version": "1", + "type": "types.peripherals.USBCTRL_REGS" + }, + "PIO0": { + "description": "Programmable IO block", + "offset": 1344274432, + "version": "1", + "type": "types.peripherals.PIO0" + }, + "PIO1": { + "offset": 1345323008, + "type": "types.peripherals.PIO0" + }, + "SIO": { + "description": "Single-cycle IO block\\n\n Provides core-local and inter-core hardware for the two processors, with single-cycle access.", + "offset": 3489660928, + "version": "1", + "type": "types.peripherals.SIO" + }, + "PPB": { + "offset": 3758096384, + "version": "1", + "type": "types.peripherals.PPB" + } + } + } + } + } +} diff --git a/src/chips/RP2040.zig b/src/chips/RP2040.zig new file mode 100644 index 0000000..62af336 --- /dev/null +++ b/src/chips/RP2040.zig @@ -0,0 +1,18145 @@ +const micro = @import("microzig"); +const mmio = micro.mmio; + +pub const devices = struct { + pub const RP2040 = struct { + pub const properties = struct { + pub const @"cpu.nvic_prio_bits" = "2"; + pub const @"cpu.mpu" = "true"; + pub const @"cpu.fpu" = "false"; + pub const @"cpu.num_interrupts" = "26"; + pub const @"cpu.vtor" = "1"; + pub const @"cpu.revision" = "r0p1"; + pub const @"cpu.vendor_systick_config" = "false"; + pub const license = + \\ + \\ Copyright (c) 2020 Raspberry Pi (Trading) Ltd. \n + \\ \n + \\ SPDX-License-Identifier: BSD-3-Clause + \\ + ; + pub const @"cpu.name" = "CM0PLUS"; + pub const @"cpu.endian" = "little"; + }; + + pub const VectorTable = extern struct { + const Handler = micro.interrupt.Handler; + const unhandled = micro.interrupt.unhandled; + + initial_stack_pointer: u32, + Reset: Handler = unhandled, + NMI: Handler = unhandled, + HardFault: Handler = unhandled, + reserved2: [7]u32 = undefined, + SVCall: Handler = unhandled, + reserved10: [2]u32 = undefined, + PendSV: Handler = unhandled, + SysTick: Handler = unhandled, + TIMER_IRQ_0: Handler = unhandled, + TIMER_IRQ_1: Handler = unhandled, + TIMER_IRQ_2: Handler = unhandled, + TIMER_IRQ_3: Handler = unhandled, + PWM_IRQ_WRAP: Handler = unhandled, + USBCTRL_IRQ: Handler = unhandled, + XIP_IRQ: Handler = unhandled, + PIO0_IRQ_0: Handler = unhandled, + PIO0_IRQ_1: Handler = unhandled, + PIO1_IRQ_0: Handler = unhandled, + PIO1_IRQ_1: Handler = unhandled, + DMA_IRQ_0: Handler = unhandled, + DMA_IRQ_1: Handler = unhandled, + IO_IRQ_BANK0: Handler = unhandled, + IO_IRQ_QSPI: Handler = unhandled, + SIO_IRQ_PROC0: Handler = unhandled, + SIO_IRQ_PROC1: Handler = unhandled, + CLOCKS_IRQ: Handler = unhandled, + SPI0_IRQ: Handler = unhandled, + SPI1_IRQ: Handler = unhandled, + UART0_IRQ: Handler = unhandled, + UART1_IRQ: Handler = unhandled, + ADC_IRQ_FIFO: Handler = unhandled, + I2C0_IRQ: Handler = unhandled, + I2C1_IRQ: Handler = unhandled, + RTC_IRQ: Handler = unhandled, + }; + + pub const peripherals = struct { + /// System Control Space + pub const MPU = @intToPtr(*volatile types.peripherals.SCS, 0xd90); + /// QSPI flash execute-in-place block + pub const XIP_CTRL = @intToPtr(*volatile types.peripherals.XIP_CTRL, 0x14000000); + /// DW_apb_ssi has the following features: + /// * APB interface – Allows for easy integration into a DesignWare Synthesizable Components for AMBA 2 implementation. + /// * APB3 and APB4 protocol support. + /// * Scalable APB data bus width – Supports APB data bus widths of 8, 16, and 32 bits. + /// * Serial-master or serial-slave operation – Enables serial communication with serial-master or serial-slave peripheral devices. + /// * Programmable Dual/Quad/Octal SPI support in Master Mode. + /// * Dual Data Rate (DDR) and Read Data Strobe (RDS) Support - Enables the DW_apb_ssi master to perform operations with the device in DDR and RDS modes when working in Dual/Quad/Octal mode of operation. + /// * Data Mask Support - Enables the DW_apb_ssi to selectively update the bytes in the device. This feature is applicable only in enhanced SPI modes. + /// * eXecute-In-Place (XIP) support - Enables the DW_apb_ssi master to behave as a memory mapped I/O and fetches the data from the device based on the APB read request. This feature is applicable only in enhanced SPI modes. + /// * DMA Controller Interface – Enables the DW_apb_ssi to interface to a DMA controller over the bus using a handshaking interface for transfer requests. + /// * Independent masking of interrupts – Master collision, transmit FIFO overflow, transmit FIFO empty, receive FIFO full, receive FIFO underflow, and receive FIFO overflow interrupts can all be masked independently. + /// * Multi-master contention detection – Informs the processor of multiple serial-master accesses on the serial bus. + /// * Bypass of meta-stability flip-flops for synchronous clocks – When the APB clock (pclk) and the DW_apb_ssi serial clock (ssi_clk) are synchronous, meta-stable flip-flops are not used when transferring control signals across these clock domains. + /// * Programmable delay on the sample time of the received serial data bit (rxd); enables programmable control of routing delays resulting in higher serial data-bit rates. + /// * Programmable features: + /// - Serial interface operation – Choice of Motorola SPI, Texas Instruments Synchronous Serial Protocol or National Semiconductor Microwire. + /// - Clock bit-rate – Dynamic control of the serial bit rate of the data transfer; used in only serial-master mode of operation. + /// - Data Item size (4 to 32 bits) – Item size of each data transfer under the control of the programmer. + /// * Configured features: + /// - FIFO depth – 16 words deep. The FIFO width is fixed at 32 bits. + /// - 1 slave select output. + /// - Hardware slave-select – Dedicated hardware slave-select line. + /// - Combined interrupt line - one combined interrupt line from the DW_apb_ssi to the interrupt controller. + /// - Interrupt polarity – active high interrupt lines. + /// - Serial clock polarity – low serial-clock polarity directly after reset. + /// - Serial clock phase – capture on first edge of serial-clock directly after reset. + pub const XIP_SSI = @intToPtr(*volatile types.peripherals.XIP_SSI, 0x18000000); + pub const SYSINFO = @intToPtr(*volatile types.peripherals.SYSINFO, 0x40000000); + /// Register block for various chip control signals + pub const SYSCFG = @intToPtr(*volatile types.peripherals.SYSCFG, 0x40004000); + pub const CLOCKS = @intToPtr(*volatile types.peripherals.CLOCKS, 0x40008000); + pub const RESETS = @intToPtr(*volatile types.peripherals.RESETS, 0x4000c000); + pub const PSM = @intToPtr(*volatile types.peripherals.PSM, 0x40010000); + pub const IO_BANK0 = @intToPtr(*volatile types.peripherals.IO_BANK0, 0x40014000); + pub const IO_QSPI = @intToPtr(*volatile types.peripherals.IO_QSPI, 0x40018000); + pub const PADS_BANK0 = @intToPtr(*volatile types.peripherals.PADS_BANK0, 0x4001c000); + pub const PADS_QSPI = @intToPtr(*volatile types.peripherals.PADS_QSPI, 0x40020000); + /// Controls the crystal oscillator + pub const XOSC = @intToPtr(*volatile types.peripherals.XOSC, 0x40024000); + pub const PLL_SYS = @intToPtr(*volatile types.peripherals.PLL_SYS, 0x40028000); + pub const PLL_USB = @intToPtr(*volatile types.peripherals.PLL_SYS, 0x4002c000); + /// Register block for busfabric control signals and performance counters + pub const BUSCTRL = @intToPtr(*volatile types.peripherals.BUSCTRL, 0x40030000); + pub const UART0 = @intToPtr(*volatile types.peripherals.UART0, 0x40034000); + pub const UART1 = @intToPtr(*volatile types.peripherals.UART0, 0x40038000); + pub const SPI0 = @intToPtr(*volatile types.peripherals.SPI0, 0x4003c000); + pub const SPI1 = @intToPtr(*volatile types.peripherals.SPI0, 0x40040000); + /// DW_apb_i2c address block + /// List of configuration constants for the Synopsys I2C hardware (you may see references to these in I2C register header; these are *fixed* values, set at hardware design time): + /// IC_ULTRA_FAST_MODE ................ 0x0 + /// IC_UFM_TBUF_CNT_DEFAULT ........... 0x8 + /// IC_UFM_SCL_LOW_COUNT .............. 0x0008 + /// IC_UFM_SCL_HIGH_COUNT ............. 0x0006 + /// IC_TX_TL .......................... 0x0 + /// IC_TX_CMD_BLOCK ................... 0x1 + /// IC_HAS_DMA ........................ 0x1 + /// IC_HAS_ASYNC_FIFO ................. 0x0 + /// IC_SMBUS_ARP ...................... 0x0 + /// IC_FIRST_DATA_BYTE_STATUS ......... 0x1 + /// IC_INTR_IO ........................ 0x1 + /// IC_MASTER_MODE .................... 0x1 + /// IC_DEFAULT_ACK_GENERAL_CALL ....... 0x1 + /// IC_INTR_POL ....................... 0x1 + /// IC_OPTIONAL_SAR ................... 0x0 + /// IC_DEFAULT_TAR_SLAVE_ADDR ......... 0x055 + /// IC_DEFAULT_SLAVE_ADDR ............. 0x055 + /// IC_DEFAULT_HS_SPKLEN .............. 0x1 + /// IC_FS_SCL_HIGH_COUNT .............. 0x0006 + /// IC_HS_SCL_LOW_COUNT ............... 0x0008 + /// IC_DEVICE_ID_VALUE ................ 0x0 + /// IC_10BITADDR_MASTER ............... 0x0 + /// IC_CLK_FREQ_OPTIMIZATION .......... 0x0 + /// IC_DEFAULT_FS_SPKLEN .............. 0x7 + /// IC_ADD_ENCODED_PARAMS ............. 0x0 + /// IC_DEFAULT_SDA_HOLD ............... 0x000001 + /// IC_DEFAULT_SDA_SETUP .............. 0x64 + /// IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT . 0x0 + /// IC_CLOCK_PERIOD ................... 100 + /// IC_EMPTYFIFO_HOLD_MASTER_EN ....... 1 + /// IC_RESTART_EN ..................... 0x1 + /// IC_TX_CMD_BLOCK_DEFAULT ........... 0x0 + /// IC_BUS_CLEAR_FEATURE .............. 0x0 + /// IC_CAP_LOADING .................... 100 + /// IC_FS_SCL_LOW_COUNT ............... 0x000d + /// APB_DATA_WIDTH .................... 32 + /// IC_SDA_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff + /// IC_SLV_DATA_NACK_ONLY ............. 0x1 + /// IC_10BITADDR_SLAVE ................ 0x0 + /// IC_CLK_TYPE ....................... 0x0 + /// IC_SMBUS_UDID_MSB ................. 0x0 + /// IC_SMBUS_SUSPEND_ALERT ............ 0x0 + /// IC_HS_SCL_HIGH_COUNT .............. 0x0006 + /// IC_SLV_RESTART_DET_EN ............. 0x1 + /// IC_SMBUS .......................... 0x0 + /// IC_OPTIONAL_SAR_DEFAULT ........... 0x0 + /// IC_PERSISTANT_SLV_ADDR_DEFAULT .... 0x0 + /// IC_USE_COUNTS ..................... 0x0 + /// IC_RX_BUFFER_DEPTH ................ 16 + /// IC_SCL_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff + /// IC_RX_FULL_HLD_BUS_EN ............. 0x1 + /// IC_SLAVE_DISABLE .................. 0x1 + /// IC_RX_TL .......................... 0x0 + /// IC_DEVICE_ID ...................... 0x0 + /// IC_HC_COUNT_VALUES ................ 0x0 + /// I2C_DYNAMIC_TAR_UPDATE ............ 0 + /// IC_SMBUS_CLK_LOW_MEXT_DEFAULT ..... 0xffffffff + /// IC_SMBUS_CLK_LOW_SEXT_DEFAULT ..... 0xffffffff + /// IC_HS_MASTER_CODE ................. 0x1 + /// IC_SMBUS_RST_IDLE_CNT_DEFAULT ..... 0xffff + /// IC_SMBUS_UDID_LSB_DEFAULT ......... 0xffffffff + /// IC_SS_SCL_HIGH_COUNT .............. 0x0028 + /// IC_SS_SCL_LOW_COUNT ............... 0x002f + /// IC_MAX_SPEED_MODE ................. 0x2 + /// IC_STAT_FOR_CLK_STRETCH ........... 0x0 + /// IC_STOP_DET_IF_MASTER_ACTIVE ...... 0x0 + /// IC_DEFAULT_UFM_SPKLEN ............. 0x1 + /// IC_TX_BUFFER_DEPTH ................ 16 + pub const I2C0 = @intToPtr(*volatile types.peripherals.I2C0, 0x40044000); + /// DW_apb_i2c address block + /// List of configuration constants for the Synopsys I2C hardware (you may see references to these in I2C register header; these are *fixed* values, set at hardware design time): + /// IC_ULTRA_FAST_MODE ................ 0x0 + /// IC_UFM_TBUF_CNT_DEFAULT ........... 0x8 + /// IC_UFM_SCL_LOW_COUNT .............. 0x0008 + /// IC_UFM_SCL_HIGH_COUNT ............. 0x0006 + /// IC_TX_TL .......................... 0x0 + /// IC_TX_CMD_BLOCK ................... 0x1 + /// IC_HAS_DMA ........................ 0x1 + /// IC_HAS_ASYNC_FIFO ................. 0x0 + /// IC_SMBUS_ARP ...................... 0x0 + /// IC_FIRST_DATA_BYTE_STATUS ......... 0x1 + /// IC_INTR_IO ........................ 0x1 + /// IC_MASTER_MODE .................... 0x1 + /// IC_DEFAULT_ACK_GENERAL_CALL ....... 0x1 + /// IC_INTR_POL ....................... 0x1 + /// IC_OPTIONAL_SAR ................... 0x0 + /// IC_DEFAULT_TAR_SLAVE_ADDR ......... 0x055 + /// IC_DEFAULT_SLAVE_ADDR ............. 0x055 + /// IC_DEFAULT_HS_SPKLEN .............. 0x1 + /// IC_FS_SCL_HIGH_COUNT .............. 0x0006 + /// IC_HS_SCL_LOW_COUNT ............... 0x0008 + /// IC_DEVICE_ID_VALUE ................ 0x0 + /// IC_10BITADDR_MASTER ............... 0x0 + /// IC_CLK_FREQ_OPTIMIZATION .......... 0x0 + /// IC_DEFAULT_FS_SPKLEN .............. 0x7 + /// IC_ADD_ENCODED_PARAMS ............. 0x0 + /// IC_DEFAULT_SDA_HOLD ............... 0x000001 + /// IC_DEFAULT_SDA_SETUP .............. 0x64 + /// IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT . 0x0 + /// IC_CLOCK_PERIOD ................... 100 + /// IC_EMPTYFIFO_HOLD_MASTER_EN ....... 1 + /// IC_RESTART_EN ..................... 0x1 + /// IC_TX_CMD_BLOCK_DEFAULT ........... 0x0 + /// IC_BUS_CLEAR_FEATURE .............. 0x0 + /// IC_CAP_LOADING .................... 100 + /// IC_FS_SCL_LOW_COUNT ............... 0x000d + /// APB_DATA_WIDTH .................... 32 + /// IC_SDA_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff + /// IC_SLV_DATA_NACK_ONLY ............. 0x1 + /// IC_10BITADDR_SLAVE ................ 0x0 + /// IC_CLK_TYPE ....................... 0x0 + /// IC_SMBUS_UDID_MSB ................. 0x0 + /// IC_SMBUS_SUSPEND_ALERT ............ 0x0 + /// IC_HS_SCL_HIGH_COUNT .............. 0x0006 + /// IC_SLV_RESTART_DET_EN ............. 0x1 + /// IC_SMBUS .......................... 0x0 + /// IC_OPTIONAL_SAR_DEFAULT ........... 0x0 + /// IC_PERSISTANT_SLV_ADDR_DEFAULT .... 0x0 + /// IC_USE_COUNTS ..................... 0x0 + /// IC_RX_BUFFER_DEPTH ................ 16 + /// IC_SCL_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff + /// IC_RX_FULL_HLD_BUS_EN ............. 0x1 + /// IC_SLAVE_DISABLE .................. 0x1 + /// IC_RX_TL .......................... 0x0 + /// IC_DEVICE_ID ...................... 0x0 + /// IC_HC_COUNT_VALUES ................ 0x0 + /// I2C_DYNAMIC_TAR_UPDATE ............ 0 + /// IC_SMBUS_CLK_LOW_MEXT_DEFAULT ..... 0xffffffff + /// IC_SMBUS_CLK_LOW_SEXT_DEFAULT ..... 0xffffffff + /// IC_HS_MASTER_CODE ................. 0x1 + /// IC_SMBUS_RST_IDLE_CNT_DEFAULT ..... 0xffff + /// IC_SMBUS_UDID_LSB_DEFAULT ......... 0xffffffff + /// IC_SS_SCL_HIGH_COUNT .............. 0x0028 + /// IC_SS_SCL_LOW_COUNT ............... 0x002f + /// IC_MAX_SPEED_MODE ................. 0x2 + /// IC_STAT_FOR_CLK_STRETCH ........... 0x0 + /// IC_STOP_DET_IF_MASTER_ACTIVE ...... 0x0 + /// IC_DEFAULT_UFM_SPKLEN ............. 0x1 + /// IC_TX_BUFFER_DEPTH ................ 16 + pub const I2C1 = @intToPtr(*volatile types.peripherals.I2C0, 0x40048000); + /// Control and data interface to SAR ADC + pub const ADC = @intToPtr(*volatile types.peripherals.ADC, 0x4004c000); + /// Simple PWM + pub const PWM = @intToPtr(*volatile types.peripherals.PWM, 0x40050000); + /// Controls time and alarms + /// time is a 64 bit value indicating the time in usec since power-on + /// timeh is the top 32 bits of time & timel is the bottom 32 bits + /// to change time write to timelw before timehw + /// to read time read from timelr before timehr + /// An alarm is set by setting alarm_enable and writing to the corresponding alarm register + /// When an alarm is pending, the corresponding alarm_running signal will be high + /// An alarm can be cancelled before it has finished by clearing the alarm_enable + /// When an alarm fires, the corresponding alarm_irq is set and alarm_running is cleared + /// To clear the interrupt write a 1 to the corresponding alarm_irq + pub const TIMER = @intToPtr(*volatile types.peripherals.TIMER, 0x40054000); + pub const WATCHDOG = @intToPtr(*volatile types.peripherals.WATCHDOG, 0x40058000); + /// Register block to control RTC + pub const RTC = @intToPtr(*volatile types.peripherals.RTC, 0x4005c000); + pub const ROSC = @intToPtr(*volatile types.peripherals.ROSC, 0x40060000); + /// control and status for on-chip voltage regulator and chip level reset subsystem + pub const VREG_AND_CHIP_RESET = @intToPtr(*volatile types.peripherals.VREG_AND_CHIP_RESET, 0x40064000); + /// Testbench manager. Allows the programmer to know what platform their software is running on. + pub const TBMAN = @intToPtr(*volatile types.peripherals.TBMAN, 0x4006c000); + /// DMA with separate read and write masters + pub const DMA = @intToPtr(*volatile types.peripherals.DMA, 0x50000000); + /// DPRAM layout for USB device. + pub const USBCTRL_DPRAM = @intToPtr(*volatile types.peripherals.USBCTRL_DPRAM, 0x50100000); + /// USB FS/LS controller device registers + pub const USBCTRL_REGS = @intToPtr(*volatile types.peripherals.USBCTRL_REGS, 0x50110000); + /// Programmable IO block + pub const PIO0 = @intToPtr(*volatile types.peripherals.PIO0, 0x50200000); + /// Programmable IO block + pub const PIO1 = @intToPtr(*volatile types.peripherals.PIO0, 0x50300000); + /// Single-cycle IO block + /// Provides core-local and inter-core hardware for the two processors, with single-cycle access. + pub const SIO = @intToPtr(*volatile types.peripherals.SIO, 0xd0000000); + pub const PPB = @intToPtr(*volatile types.peripherals.PPB, 0xe0000000); + /// System Tick Timer + pub const SysTick = @intToPtr(*volatile types.peripherals.SysTick, 0xe000e010); + /// System Control Space + pub const NVIC = @intToPtr(*volatile types.peripherals.NVIC, 0xe000e100); + /// System Control Space + pub const SCB = @intToPtr(*volatile types.peripherals.SCB, 0xe000ed00); + }; + }; +}; + +pub const types = struct { + pub const peripherals = struct { + /// System Tick Timer + pub const SysTick = extern struct { + /// SysTick Control and Status Register + CTRL: mmio.Mmio(packed struct(u32) { + ENABLE: u1, + TICKINT: u1, + CLKSOURCE: u1, + reserved16: u13, + COUNTFLAG: u1, + padding: u15, + }), + /// SysTick Reload Value Register + LOAD: mmio.Mmio(packed struct(u32) { + RELOAD: u24, + padding: u8, + }), + /// SysTick Current Value Register + VAL: mmio.Mmio(packed struct(u32) { + CURRENT: u24, + padding: u8, + }), + /// SysTick Calibration Register + CALIB: mmio.Mmio(packed struct(u32) { + TENMS: u24, + reserved30: u6, + SKEW: u1, + NOREF: u1, + }), + }; + + /// System Control Block + pub const SCB = extern struct { + CPUID: mmio.Mmio(packed struct(u32) { + REVISION: u4, + PARTNO: u12, + ARCHITECTURE: u4, + VARIANT: u4, + IMPLEMENTER: u8, + }), + /// Interrupt Control and State Register + ICSR: mmio.Mmio(packed struct(u32) { + VECTACTIVE: u9, + reserved12: u3, + VECTPENDING: u9, + reserved22: u1, + ISRPENDING: u1, + ISRPREEMPT: u1, + reserved25: u1, + PENDSTCLR: u1, + PENDSTSET: u1, + PENDSVCLR: u1, + PENDSVSET: u1, + reserved31: u2, + NMIPENDSET: u1, + }), + /// Vector Table Offset Register + VTOR: mmio.Mmio(packed struct(u32) { + reserved8: u8, + TBLOFF: u24, + }), + /// Application Interrupt and Reset Control Register + AIRCR: mmio.Mmio(packed struct(u32) { + reserved1: u1, + VECTCLRACTIVE: u1, + SYSRESETREQ: u1, + reserved15: u12, + ENDIANESS: u1, + VECTKEY: u16, + }), + /// System Control Register + SCR: mmio.Mmio(packed struct(u32) { + reserved1: u1, + SLEEPONEXIT: u1, + SLEEPDEEP: u1, + reserved4: u1, + SEVONPEND: u1, + padding: u27, + }), + /// Configuration Control Register + CCR: mmio.Mmio(packed struct(u32) { + reserved3: u3, + UNALIGN_TRP: u1, + reserved9: u5, + STKALIGN: u1, + padding: u22, + }), + reserved28: [4]u8, + /// System Handlers Priority Registers. [0] is RESERVED + SHP: u32, + reserved36: [4]u8, + /// System Handler Control and State Register + SHCSR: mmio.Mmio(packed struct(u32) { + reserved15: u15, + SVCALLPENDED: u1, + padding: u16, + }), + }; + + /// Nested Vectored Interrupt Controller + pub const NVIC = extern struct { + /// Interrupt Set Enable Register + ISER: mmio.Mmio(packed struct(u32) { + TIMER_IRQ_0: u1, + TIMER_IRQ_1: u1, + TIMER_IRQ_2: u1, + TIMER_IRQ_3: u1, + PWM_IRQ_WRAP: u1, + USBCTRL_IRQ: u1, + XIP_IRQ: u1, + PIO0_IRQ_0: u1, + PIO0_IRQ_1: u1, + PIO1_IRQ_0: u1, + PIO1_IRQ_1: u1, + DMA_IRQ_0: u1, + DMA_IRQ_1: u1, + IO_IRQ_BANK0: u1, + IO_IRQ_QSPI: u1, + SIO_IRQ_PROC0: u1, + SIO_IRQ_PROC1: u1, + CLOCKS_IRQ: u1, + SPI0_IRQ: u1, + SPI1_IRQ: u1, + UART0_IRQ: u1, + UART1_IRQ: u1, + ADC_IRQ_FIFO: u1, + I2C0_IRQ: u1, + I2C1_IRQ: u1, + RTC_IRQ: u1, + padding: u6, + }), + reserved128: [124]u8, + /// Interrupt Clear Enable Register + ICER: mmio.Mmio(packed struct(u32) { + TIMER_IRQ_0: u1, + TIMER_IRQ_1: u1, + TIMER_IRQ_2: u1, + TIMER_IRQ_3: u1, + PWM_IRQ_WRAP: u1, + USBCTRL_IRQ: u1, + XIP_IRQ: u1, + PIO0_IRQ_0: u1, + PIO0_IRQ_1: u1, + PIO1_IRQ_0: u1, + PIO1_IRQ_1: u1, + DMA_IRQ_0: u1, + DMA_IRQ_1: u1, + IO_IRQ_BANK0: u1, + IO_IRQ_QSPI: u1, + SIO_IRQ_PROC0: u1, + SIO_IRQ_PROC1: u1, + CLOCKS_IRQ: u1, + SPI0_IRQ: u1, + SPI1_IRQ: u1, + UART0_IRQ: u1, + UART1_IRQ: u1, + ADC_IRQ_FIFO: u1, + I2C0_IRQ: u1, + I2C1_IRQ: u1, + RTC_IRQ: u1, + padding: u6, + }), + reserved256: [124]u8, + /// Interrupt Set Pending Register + ISPR: mmio.Mmio(packed struct(u32) { + TIMER_IRQ_0: u1, + TIMER_IRQ_1: u1, + TIMER_IRQ_2: u1, + TIMER_IRQ_3: u1, + PWM_IRQ_WRAP: u1, + USBCTRL_IRQ: u1, + XIP_IRQ: u1, + PIO0_IRQ_0: u1, + PIO0_IRQ_1: u1, + PIO1_IRQ_0: u1, + PIO1_IRQ_1: u1, + DMA_IRQ_0: u1, + DMA_IRQ_1: u1, + IO_IRQ_BANK0: u1, + IO_IRQ_QSPI: u1, + SIO_IRQ_PROC0: u1, + SIO_IRQ_PROC1: u1, + CLOCKS_IRQ: u1, + SPI0_IRQ: u1, + SPI1_IRQ: u1, + UART0_IRQ: u1, + UART1_IRQ: u1, + ADC_IRQ_FIFO: u1, + I2C0_IRQ: u1, + I2C1_IRQ: u1, + RTC_IRQ: u1, + padding: u6, + }), + reserved384: [124]u8, + /// Interrupt Clear Pending Register + ICPR: mmio.Mmio(packed struct(u32) { + TIMER_IRQ_0: u1, + TIMER_IRQ_1: u1, + TIMER_IRQ_2: u1, + TIMER_IRQ_3: u1, + PWM_IRQ_WRAP: u1, + USBCTRL_IRQ: u1, + XIP_IRQ: u1, + PIO0_IRQ_0: u1, + PIO0_IRQ_1: u1, + PIO1_IRQ_0: u1, + PIO1_IRQ_1: u1, + DMA_IRQ_0: u1, + DMA_IRQ_1: u1, + IO_IRQ_BANK0: u1, + IO_IRQ_QSPI: u1, + SIO_IRQ_PROC0: u1, + SIO_IRQ_PROC1: u1, + CLOCKS_IRQ: u1, + SPI0_IRQ: u1, + SPI1_IRQ: u1, + UART0_IRQ: u1, + UART1_IRQ: u1, + ADC_IRQ_FIFO: u1, + I2C0_IRQ: u1, + I2C1_IRQ: u1, + RTC_IRQ: u1, + padding: u6, + }), + reserved768: [380]u8, + /// Interrupt Priority Register + IPR0: mmio.Mmio(packed struct(u32) { + reserved6: u6, + TIMER_IRQ_0: u2, + reserved14: u6, + TIMER_IRQ_1: u2, + reserved22: u6, + TIMER_IRQ_2: u2, + reserved30: u6, + TIMER_IRQ_3: u2, + }), + /// Interrupt Priority Register + IPR1: mmio.Mmio(packed struct(u32) { + reserved6: u6, + PWM_IRQ_WRAP: u2, + reserved14: u6, + USBCTRL_IRQ: u2, + reserved22: u6, + XIP_IRQ: u2, + reserved30: u6, + PIO0_IRQ_0: u2, + }), + /// Interrupt Priority Register + IPR2: mmio.Mmio(packed struct(u32) { + reserved6: u6, + PIO0_IRQ_1: u2, + reserved14: u6, + PIO1_IRQ_0: u2, + reserved22: u6, + PIO1_IRQ_1: u2, + reserved30: u6, + DMA_IRQ_0: u2, + }), + /// Interrupt Priority Register + IPR3: mmio.Mmio(packed struct(u32) { + reserved6: u6, + DMA_IRQ_1: u2, + reserved14: u6, + IO_IRQ_BANK0: u2, + reserved22: u6, + IO_IRQ_QSPI: u2, + reserved30: u6, + SIO_IRQ_PROC0: u2, + }), + /// Interrupt Priority Register + IPR4: mmio.Mmio(packed struct(u32) { + reserved6: u6, + SIO_IRQ_PROC1: u2, + reserved14: u6, + CLOCKS_IRQ: u2, + reserved22: u6, + SPI0_IRQ: u2, + reserved30: u6, + SPI1_IRQ: u2, + }), + /// Interrupt Priority Register + IPR5: mmio.Mmio(packed struct(u32) { + reserved6: u6, + UART0_IRQ: u2, + reserved14: u6, + UART1_IRQ: u2, + reserved22: u6, + ADC_IRQ_FIFO: u2, + reserved30: u6, + I2C0_IRQ: u2, + }), + /// Interrupt Priority Register + IPR6: mmio.Mmio(packed struct(u32) { + reserved6: u6, + I2C1_IRQ: u2, + reserved14: u6, + RTC_IRQ: u2, + padding: u16, + }), + /// Interrupt Priority Register + IPR7: u32, + }; + + /// Memory Protection Unit + pub const MPU = extern struct { + /// MPU Type Register + TYPE: mmio.Mmio(packed struct(u32) { + SEPARATE: u1, + reserved8: u7, + DREGION: u8, + IREGION: u8, + padding: u8, + }), + /// MPU Control Register + CTRL: mmio.Mmio(packed struct(u32) { + ENABLE: u1, + HFNMIENA: u1, + PRIVDEFENA: u1, + padding: u29, + }), + /// MPU Region RNRber Register + RNR: mmio.Mmio(packed struct(u32) { + REGION: u8, + padding: u24, + }), + /// MPU Region Base Address Register + RBAR: mmio.Mmio(packed struct(u32) { + REGION: u4, + VALID: u1, + reserved8: u3, + ADDR: u24, + }), + /// MPU Region Attribute and Size Register + RASR: mmio.Mmio(packed struct(u32) { + ENABLE: u1, + SIZE: u5, + reserved8: u2, + SRD: u8, + B: u1, + C: u1, + S: u1, + TEX: u3, + reserved24: u2, + AP: u3, + reserved28: u1, + XN: u1, + padding: u3, + }), + }; + + /// QSPI flash execute-in-place block + pub const XIP_CTRL = extern struct { + /// Cache control + CTRL: mmio.Mmio(packed struct(u32) { + /// When 1, enable the cache. When the cache is disabled, all XIP accesses + /// will go straight to the flash, without querying the cache. When enabled, + /// cacheable XIP accesses will query the cache, and the flash will + /// not be accessed if the tag matches and the valid bit is set. + /// If the cache is enabled, cache-as-SRAM accesses have no effect on the + /// cache data RAM, and will produce a bus error response. + EN: u1, + /// When 1, writes to any alias other than 0x0 (caching, allocating) + /// will produce a bus fault. When 0, these writes are silently ignored. + /// In either case, writes to the 0x0 alias will deallocate on tag match, + /// as usual. + ERR_BADWRITE: u1, + reserved3: u1, + /// When 1, the cache memories are powered down. They retain state, + /// but can not be accessed. This reduces static power dissipation. + /// Writing 1 to this bit forces CTRL_EN to 0, i.e. the cache cannot + /// be enabled when powered down. + /// Cache-as-SRAM accesses will produce a bus error response when + /// the cache is powered down. + POWER_DOWN: u1, + padding: u28, + }), + /// Cache Flush control + FLUSH: mmio.Mmio(packed struct(u32) { + /// Write 1 to flush the cache. This clears the tag memory, but + /// the data memory retains its contents. (This means cache-as-SRAM + /// contents is not affected by flush or reset.) + /// Reading will hold the bus (stall the processor) until the flush + /// completes. Alternatively STAT can be polled until completion. + FLUSH: u1, + padding: u31, + }), + /// Cache Status + STAT: mmio.Mmio(packed struct(u32) { + /// Reads as 0 while a cache flush is in progress, and 1 otherwise. + /// The cache is flushed whenever the XIP block is reset, and also + /// when requested via the FLUSH register. + FLUSH_READY: u1, + /// When 1, indicates the XIP streaming FIFO is completely empty. + FIFO_EMPTY: u1, + /// When 1, indicates the XIP streaming FIFO is completely full. + /// The streaming FIFO is 2 entries deep, so the full and empty + /// flag allow its level to be ascertained. + FIFO_FULL: u1, + padding: u29, + }), + /// Cache Hit counter + /// A 32 bit saturating counter that increments upon each cache hit, + /// i.e. when an XIP access is serviced directly from cached data. + /// Write any value to clear. + CTR_HIT: u32, + /// Cache Access counter + /// A 32 bit saturating counter that increments upon each XIP access, + /// whether the cache is hit or not. This includes noncacheable accesses. + /// Write any value to clear. + CTR_ACC: u32, + /// FIFO stream address + STREAM_ADDR: mmio.Mmio(packed struct(u32) { + reserved2: u2, + /// The address of the next word to be streamed from flash to the streaming FIFO. + /// Increments automatically after each flash access. + /// Write the initial access address here before starting a streaming read. + STREAM_ADDR: u30, + }), + /// FIFO stream control + STREAM_CTR: mmio.Mmio(packed struct(u32) { + /// Write a nonzero value to start a streaming read. This will then + /// progress in the background, using flash idle cycles to transfer + /// a linear data block from flash to the streaming FIFO. + /// Decrements automatically (1 at a time) as the stream + /// progresses, and halts on reaching 0. + /// Write 0 to halt an in-progress stream, and discard any in-flight + /// read, so that a new stream can immediately be started (after + /// draining the FIFO and reinitialising STREAM_ADDR) + STREAM_CTR: u22, + padding: u10, + }), + /// FIFO stream data + /// Streamed data is buffered here, for retrieval by the system DMA. + /// This FIFO can also be accessed via the XIP_AUX slave, to avoid exposing + /// the DMA to bus stalls caused by other XIP traffic. + STREAM_FIFO: u32, + }; + + /// DW_apb_ssi has the following features: + /// * APB interface – Allows for easy integration into a DesignWare Synthesizable Components for AMBA 2 implementation. + /// * APB3 and APB4 protocol support. + /// * Scalable APB data bus width – Supports APB data bus widths of 8, 16, and 32 bits. + /// * Serial-master or serial-slave operation – Enables serial communication with serial-master or serial-slave peripheral devices. + /// * Programmable Dual/Quad/Octal SPI support in Master Mode. + /// * Dual Data Rate (DDR) and Read Data Strobe (RDS) Support - Enables the DW_apb_ssi master to perform operations with the device in DDR and RDS modes when working in Dual/Quad/Octal mode of operation. + /// * Data Mask Support - Enables the DW_apb_ssi to selectively update the bytes in the device. This feature is applicable only in enhanced SPI modes. + /// * eXecute-In-Place (XIP) support - Enables the DW_apb_ssi master to behave as a memory mapped I/O and fetches the data from the device based on the APB read request. This feature is applicable only in enhanced SPI modes. + /// * DMA Controller Interface – Enables the DW_apb_ssi to interface to a DMA controller over the bus using a handshaking interface for transfer requests. + /// * Independent masking of interrupts – Master collision, transmit FIFO overflow, transmit FIFO empty, receive FIFO full, receive FIFO underflow, and receive FIFO overflow interrupts can all be masked independently. + /// * Multi-master contention detection – Informs the processor of multiple serial-master accesses on the serial bus. + /// * Bypass of meta-stability flip-flops for synchronous clocks – When the APB clock (pclk) and the DW_apb_ssi serial clock (ssi_clk) are synchronous, meta-stable flip-flops are not used when transferring control signals across these clock domains. + /// * Programmable delay on the sample time of the received serial data bit (rxd); enables programmable control of routing delays resulting in higher serial data-bit rates. + /// * Programmable features: + /// - Serial interface operation – Choice of Motorola SPI, Texas Instruments Synchronous Serial Protocol or National Semiconductor Microwire. + /// - Clock bit-rate – Dynamic control of the serial bit rate of the data transfer; used in only serial-master mode of operation. + /// - Data Item size (4 to 32 bits) – Item size of each data transfer under the control of the programmer. + /// * Configured features: + /// - FIFO depth – 16 words deep. The FIFO width is fixed at 32 bits. + /// - 1 slave select output. + /// - Hardware slave-select – Dedicated hardware slave-select line. + /// - Combined interrupt line - one combined interrupt line from the DW_apb_ssi to the interrupt controller. + /// - Interrupt polarity – active high interrupt lines. + /// - Serial clock polarity – low serial-clock polarity directly after reset. + /// - Serial clock phase – capture on first edge of serial-clock directly after reset. + pub const XIP_SSI = extern struct { + /// Control register 0 + CTRLR0: mmio.Mmio(packed struct(u32) { + /// Data frame size + DFS: u4, + /// Frame format + FRF: u2, + /// Serial clock phase + SCPH: u1, + /// Serial clock polarity + SCPOL: u1, + /// Transfer mode + TMOD: packed union { + raw: u2, + value: enum(u2) { + /// Both transmit and receive + TX_AND_RX = 0x0, + /// Transmit only (not for FRF == 0, standard SPI mode) + TX_ONLY = 0x1, + /// Receive only (not for FRF == 0, standard SPI mode) + RX_ONLY = 0x2, + /// EEPROM read mode (TX then RX; RX starts after control data TX'd) + EEPROM_READ = 0x3, + }, + }, + /// Slave output enable + SLV_OE: u1, + /// Shift register loop (test mode) + SRL: u1, + /// Control frame size + /// Value of n -> n+1 clocks per frame. + CFS: u4, + /// Data frame size in 32b transfer mode + /// Value of n -> n+1 clocks per frame. + DFS_32: u5, + /// SPI frame format + SPI_FRF: packed union { + raw: u2, + value: enum(u2) { + /// Standard 1-bit SPI frame format; 1 bit per SCK, full-duplex + STD = 0x0, + /// Dual-SPI frame format; two bits per SCK, half-duplex + DUAL = 0x1, + /// Quad-SPI frame format; four bits per SCK, half-duplex + QUAD = 0x2, + _, + }, + }, + reserved24: u1, + /// Slave select toggle enable + SSTE: u1, + padding: u7, + }), + /// Master Control register 1 + CTRLR1: mmio.Mmio(packed struct(u32) { + /// Number of data frames + NDF: u16, + padding: u16, + }), + /// SSI Enable + SSIENR: mmio.Mmio(packed struct(u32) { + /// SSI enable + SSI_EN: u1, + padding: u31, + }), + /// Microwire Control + MWCR: mmio.Mmio(packed struct(u32) { + /// Microwire transfer mode + MWMOD: u1, + /// Microwire control + MDD: u1, + /// Microwire handshaking + MHS: u1, + padding: u29, + }), + /// Slave enable + SER: mmio.Mmio(packed struct(u32) { + /// For each bit: + /// 0 -> slave not selected + /// 1 -> slave selected + SER: u1, + padding: u31, + }), + /// Baud rate + BAUDR: mmio.Mmio(packed struct(u32) { + /// SSI clock divider + SCKDV: u16, + padding: u16, + }), + /// TX FIFO threshold level + TXFTLR: mmio.Mmio(packed struct(u32) { + /// Transmit FIFO threshold + TFT: u8, + padding: u24, + }), + /// RX FIFO threshold level + RXFTLR: mmio.Mmio(packed struct(u32) { + /// Receive FIFO threshold + RFT: u8, + padding: u24, + }), + /// TX FIFO level + TXFLR: mmio.Mmio(packed struct(u32) { + /// Transmit FIFO level + TFTFL: u8, + padding: u24, + }), + /// RX FIFO level + RXFLR: mmio.Mmio(packed struct(u32) { + /// Receive FIFO level + RXTFL: u8, + padding: u24, + }), + /// Status register + SR: mmio.Mmio(packed struct(u32) { + /// SSI busy flag + BUSY: u1, + /// Transmit FIFO not full + TFNF: u1, + /// Transmit FIFO empty + TFE: u1, + /// Receive FIFO not empty + RFNE: u1, + /// Receive FIFO full + RFF: u1, + /// Transmission error + TXE: u1, + /// Data collision error + DCOL: u1, + padding: u25, + }), + /// Interrupt mask + IMR: mmio.Mmio(packed struct(u32) { + /// Transmit FIFO empty interrupt mask + TXEIM: u1, + /// Transmit FIFO overflow interrupt mask + TXOIM: u1, + /// Receive FIFO underflow interrupt mask + RXUIM: u1, + /// Receive FIFO overflow interrupt mask + RXOIM: u1, + /// Receive FIFO full interrupt mask + RXFIM: u1, + /// Multi-master contention interrupt mask + MSTIM: u1, + padding: u26, + }), + /// Interrupt status + ISR: mmio.Mmio(packed struct(u32) { + /// Transmit FIFO empty interrupt status + TXEIS: u1, + /// Transmit FIFO overflow interrupt status + TXOIS: u1, + /// Receive FIFO underflow interrupt status + RXUIS: u1, + /// Receive FIFO overflow interrupt status + RXOIS: u1, + /// Receive FIFO full interrupt status + RXFIS: u1, + /// Multi-master contention interrupt status + MSTIS: u1, + padding: u26, + }), + /// Raw interrupt status + RISR: mmio.Mmio(packed struct(u32) { + /// Transmit FIFO empty raw interrupt status + TXEIR: u1, + /// Transmit FIFO overflow raw interrupt status + TXOIR: u1, + /// Receive FIFO underflow raw interrupt status + RXUIR: u1, + /// Receive FIFO overflow raw interrupt status + RXOIR: u1, + /// Receive FIFO full raw interrupt status + RXFIR: u1, + /// Multi-master contention raw interrupt status + MSTIR: u1, + padding: u26, + }), + /// TX FIFO overflow interrupt clear + TXOICR: mmio.Mmio(packed struct(u32) { + /// Clear-on-read transmit FIFO overflow interrupt + TXOICR: u1, + padding: u31, + }), + /// RX FIFO overflow interrupt clear + RXOICR: mmio.Mmio(packed struct(u32) { + /// Clear-on-read receive FIFO overflow interrupt + RXOICR: u1, + padding: u31, + }), + /// RX FIFO underflow interrupt clear + RXUICR: mmio.Mmio(packed struct(u32) { + /// Clear-on-read receive FIFO underflow interrupt + RXUICR: u1, + padding: u31, + }), + /// Multi-master interrupt clear + MSTICR: mmio.Mmio(packed struct(u32) { + /// Clear-on-read multi-master contention interrupt + MSTICR: u1, + padding: u31, + }), + /// Interrupt clear + ICR: mmio.Mmio(packed struct(u32) { + /// Clear-on-read all active interrupts + ICR: u1, + padding: u31, + }), + /// DMA control + DMACR: mmio.Mmio(packed struct(u32) { + /// Receive DMA enable + RDMAE: u1, + /// Transmit DMA enable + TDMAE: u1, + padding: u30, + }), + /// DMA TX data level + DMATDLR: mmio.Mmio(packed struct(u32) { + /// Transmit data watermark level + DMATDL: u8, + padding: u24, + }), + /// DMA RX data level + DMARDLR: mmio.Mmio(packed struct(u32) { + /// Receive data watermark level (DMARDLR+1) + DMARDL: u8, + padding: u24, + }), + /// Identification register + IDR: mmio.Mmio(packed struct(u32) { + /// Peripheral dentification code + IDCODE: u32, + }), + /// Version ID + SSI_VERSION_ID: mmio.Mmio(packed struct(u32) { + /// SNPS component version (format X.YY) + SSI_COMP_VERSION: u32, + }), + /// Data Register 0 (of 36) + DR0: mmio.Mmio(packed struct(u32) { + /// First data register of 36 + DR: u32, + }), + reserved240: [140]u8, + /// RX sample delay + RX_SAMPLE_DLY: mmio.Mmio(packed struct(u32) { + /// RXD sample delay (in SCLK cycles) + RSD: u8, + padding: u24, + }), + /// SPI control + SPI_CTRLR0: mmio.Mmio(packed struct(u32) { + /// Address and instruction transfer format + TRANS_TYPE: packed union { + raw: u2, + value: enum(u2) { + /// Command and address both in standard SPI frame format + @"1C1A" = 0x0, + /// Command in standard SPI format, address in format specified by FRF + @"1C2A" = 0x1, + /// Command and address both in format specified by FRF (e.g. Dual-SPI) + @"2C2A" = 0x2, + _, + }, + }, + /// Address length (0b-60b in 4b increments) + ADDR_L: u4, + reserved8: u2, + /// Instruction length (0/4/8/16b) + INST_L: packed union { + raw: u2, + value: enum(u2) { + /// No instruction + NONE = 0x0, + /// 4-bit instruction + @"4B" = 0x1, + /// 8-bit instruction + @"8B" = 0x2, + /// 16-bit instruction + @"16B" = 0x3, + }, + }, + reserved11: u1, + /// Wait cycles between control frame transmit and data reception (in SCLK cycles) + WAIT_CYCLES: u5, + /// SPI DDR transfer enable + SPI_DDR_EN: u1, + /// Instruction DDR transfer enable + INST_DDR_EN: u1, + /// Read data strobe enable + SPI_RXDS_EN: u1, + reserved24: u5, + /// SPI Command to send in XIP mode (INST_L = 8-bit) or to append to Address (INST_L = 0-bit) + XIP_CMD: u8, + }), + /// TX drive edge + TXD_DRIVE_EDGE: mmio.Mmio(packed struct(u32) { + /// TXD drive edge + TDE: u8, + padding: u24, + }), + }; + + pub const SYSINFO = extern struct { + /// JEDEC JEP-106 compliant chip identifier. + CHIP_ID: mmio.Mmio(packed struct(u32) { + MANUFACTURER: u12, + PART: u16, + REVISION: u4, + }), + /// Platform register. Allows software to know what environment it is running in. + PLATFORM: mmio.Mmio(packed struct(u32) { + FPGA: u1, + ASIC: u1, + padding: u30, + }), + reserved64: [56]u8, + /// Git hash of the chip source. Used to identify chip version. + GITREF_RP2040: u32, + }; + + /// Register block for various chip control signals + pub const SYSCFG = extern struct { + /// Processor core 0 NMI source mask + /// Set a bit high to enable NMI from that IRQ + PROC0_NMI_MASK: u32, + /// Processor core 1 NMI source mask + /// Set a bit high to enable NMI from that IRQ + PROC1_NMI_MASK: u32, + /// Configuration for processors + PROC_CONFIG: mmio.Mmio(packed struct(u32) { + /// Indication that proc0 has halted + PROC0_HALTED: u1, + /// Indication that proc1 has halted + PROC1_HALTED: u1, + reserved24: u22, + /// Configure proc0 DAP instance ID. + /// Recommend that this is NOT changed until you require debug access in multi-chip environment + /// WARNING: do not set to 15 as this is reserved for RescueDP + PROC0_DAP_INSTID: u4, + /// Configure proc1 DAP instance ID. + /// Recommend that this is NOT changed until you require debug access in multi-chip environment + /// WARNING: do not set to 15 as this is reserved for RescueDP + PROC1_DAP_INSTID: u4, + }), + /// For each bit, if 1, bypass the input synchronizer between that GPIO + /// and the GPIO input register in the SIO. The input synchronizers should + /// generally be unbypassed, to avoid injecting metastabilities into processors. + /// If you're feeling brave, you can bypass to save two cycles of input + /// latency. This register applies to GPIO 0...29. + PROC_IN_SYNC_BYPASS: mmio.Mmio(packed struct(u32) { + PROC_IN_SYNC_BYPASS: u30, + padding: u2, + }), + /// For each bit, if 1, bypass the input synchronizer between that GPIO + /// and the GPIO input register in the SIO. The input synchronizers should + /// generally be unbypassed, to avoid injecting metastabilities into processors. + /// If you're feeling brave, you can bypass to save two cycles of input + /// latency. This register applies to GPIO 30...35 (the QSPI IOs). + PROC_IN_SYNC_BYPASS_HI: mmio.Mmio(packed struct(u32) { + PROC_IN_SYNC_BYPASS_HI: u6, + padding: u26, + }), + /// Directly control the SWD debug port of either processor + DBGFORCE: mmio.Mmio(packed struct(u32) { + /// Observe the value of processor 0 SWDIO output. + PROC0_SWDO: u1, + /// Directly drive processor 0 SWDIO input, if PROC0_ATTACH is set + PROC0_SWDI: u1, + /// Directly drive processor 0 SWCLK, if PROC0_ATTACH is set + PROC0_SWCLK: u1, + /// Attach processor 0 debug port to syscfg controls, and disconnect it from external SWD pads. + PROC0_ATTACH: u1, + /// Observe the value of processor 1 SWDIO output. + PROC1_SWDO: u1, + /// Directly drive processor 1 SWDIO input, if PROC1_ATTACH is set + PROC1_SWDI: u1, + /// Directly drive processor 1 SWCLK, if PROC1_ATTACH is set + PROC1_SWCLK: u1, + /// Attach processor 1 debug port to syscfg controls, and disconnect it from external SWD pads. + PROC1_ATTACH: u1, + padding: u24, + }), + /// Control power downs to memories. Set high to power down memories. + /// Use with extreme caution + MEMPOWERDOWN: mmio.Mmio(packed struct(u32) { + SRAM0: u1, + SRAM1: u1, + SRAM2: u1, + SRAM3: u1, + SRAM4: u1, + SRAM5: u1, + USB: u1, + ROM: u1, + padding: u24, + }), + }; + + pub const CLOCKS = extern struct { + /// Clock control, can be changed on-the-fly (except for auxsrc) + CLK_GPOUT0_CTRL: mmio.Mmio(packed struct(u32) { + reserved5: u5, + /// Selects the auxiliary clock source, will glitch when switching + AUXSRC: packed union { + raw: u4, + value: enum(u4) { + clksrc_pll_sys = 0x0, + clksrc_gpin0 = 0x1, + clksrc_gpin1 = 0x2, + clksrc_pll_usb = 0x3, + rosc_clksrc = 0x4, + xosc_clksrc = 0x5, + clk_sys = 0x6, + clk_usb = 0x7, + clk_adc = 0x8, + clk_rtc = 0x9, + clk_ref = 0xa, + _, + }, + }, + reserved10: u1, + /// Asynchronously kills the clock generator + KILL: u1, + /// Starts and stops the clock generator cleanly + ENABLE: u1, + /// Enables duty cycle correction for odd divisors + DC50: u1, + reserved16: u3, + /// This delays the enable signal by up to 3 cycles of the input clock + /// This must be set before the clock is enabled to have any effect + PHASE: u2, + reserved20: u2, + /// An edge on this signal shifts the phase of the output by 1 cycle of the input clock + /// This can be done at any time + NUDGE: u1, + padding: u11, + }), + /// Clock divisor, can be changed on-the-fly + CLK_GPOUT0_DIV: mmio.Mmio(packed struct(u32) { + /// Fractional component of the divisor + FRAC: u8, + /// Integer component of the divisor, 0 -> divide by 2^16 + INT: u24, + }), + /// Indicates which SRC is currently selected by the glitchless mux (one-hot). + /// This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + CLK_GPOUT0_SELECTED: u32, + /// Clock control, can be changed on-the-fly (except for auxsrc) + CLK_GPOUT1_CTRL: mmio.Mmio(packed struct(u32) { + reserved5: u5, + /// Selects the auxiliary clock source, will glitch when switching + AUXSRC: packed union { + raw: u4, + value: enum(u4) { + clksrc_pll_sys = 0x0, + clksrc_gpin0 = 0x1, + clksrc_gpin1 = 0x2, + clksrc_pll_usb = 0x3, + rosc_clksrc = 0x4, + xosc_clksrc = 0x5, + clk_sys = 0x6, + clk_usb = 0x7, + clk_adc = 0x8, + clk_rtc = 0x9, + clk_ref = 0xa, + _, + }, + }, + reserved10: u1, + /// Asynchronously kills the clock generator + KILL: u1, + /// Starts and stops the clock generator cleanly + ENABLE: u1, + /// Enables duty cycle correction for odd divisors + DC50: u1, + reserved16: u3, + /// This delays the enable signal by up to 3 cycles of the input clock + /// This must be set before the clock is enabled to have any effect + PHASE: u2, + reserved20: u2, + /// An edge on this signal shifts the phase of the output by 1 cycle of the input clock + /// This can be done at any time + NUDGE: u1, + padding: u11, + }), + /// Clock divisor, can be changed on-the-fly + CLK_GPOUT1_DIV: mmio.Mmio(packed struct(u32) { + /// Fractional component of the divisor + FRAC: u8, + /// Integer component of the divisor, 0 -> divide by 2^16 + INT: u24, + }), + /// Indicates which SRC is currently selected by the glitchless mux (one-hot). + /// This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + CLK_GPOUT1_SELECTED: u32, + /// Clock control, can be changed on-the-fly (except for auxsrc) + CLK_GPOUT2_CTRL: mmio.Mmio(packed struct(u32) { + reserved5: u5, + /// Selects the auxiliary clock source, will glitch when switching + AUXSRC: packed union { + raw: u4, + value: enum(u4) { + clksrc_pll_sys = 0x0, + clksrc_gpin0 = 0x1, + clksrc_gpin1 = 0x2, + clksrc_pll_usb = 0x3, + rosc_clksrc_ph = 0x4, + xosc_clksrc = 0x5, + clk_sys = 0x6, + clk_usb = 0x7, + clk_adc = 0x8, + clk_rtc = 0x9, + clk_ref = 0xa, + _, + }, + }, + reserved10: u1, + /// Asynchronously kills the clock generator + KILL: u1, + /// Starts and stops the clock generator cleanly + ENABLE: u1, + /// Enables duty cycle correction for odd divisors + DC50: u1, + reserved16: u3, + /// This delays the enable signal by up to 3 cycles of the input clock + /// This must be set before the clock is enabled to have any effect + PHASE: u2, + reserved20: u2, + /// An edge on this signal shifts the phase of the output by 1 cycle of the input clock + /// This can be done at any time + NUDGE: u1, + padding: u11, + }), + /// Clock divisor, can be changed on-the-fly + CLK_GPOUT2_DIV: mmio.Mmio(packed struct(u32) { + /// Fractional component of the divisor + FRAC: u8, + /// Integer component of the divisor, 0 -> divide by 2^16 + INT: u24, + }), + /// Indicates which SRC is currently selected by the glitchless mux (one-hot). + /// This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + CLK_GPOUT2_SELECTED: u32, + /// Clock control, can be changed on-the-fly (except for auxsrc) + CLK_GPOUT3_CTRL: mmio.Mmio(packed struct(u32) { + reserved5: u5, + /// Selects the auxiliary clock source, will glitch when switching + AUXSRC: packed union { + raw: u4, + value: enum(u4) { + clksrc_pll_sys = 0x0, + clksrc_gpin0 = 0x1, + clksrc_gpin1 = 0x2, + clksrc_pll_usb = 0x3, + rosc_clksrc_ph = 0x4, + xosc_clksrc = 0x5, + clk_sys = 0x6, + clk_usb = 0x7, + clk_adc = 0x8, + clk_rtc = 0x9, + clk_ref = 0xa, + _, + }, + }, + reserved10: u1, + /// Asynchronously kills the clock generator + KILL: u1, + /// Starts and stops the clock generator cleanly + ENABLE: u1, + /// Enables duty cycle correction for odd divisors + DC50: u1, + reserved16: u3, + /// This delays the enable signal by up to 3 cycles of the input clock + /// This must be set before the clock is enabled to have any effect + PHASE: u2, + reserved20: u2, + /// An edge on this signal shifts the phase of the output by 1 cycle of the input clock + /// This can be done at any time + NUDGE: u1, + padding: u11, + }), + /// Clock divisor, can be changed on-the-fly + CLK_GPOUT3_DIV: mmio.Mmio(packed struct(u32) { + /// Fractional component of the divisor + FRAC: u8, + /// Integer component of the divisor, 0 -> divide by 2^16 + INT: u24, + }), + /// Indicates which SRC is currently selected by the glitchless mux (one-hot). + /// This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + CLK_GPOUT3_SELECTED: u32, + /// Clock control, can be changed on-the-fly (except for auxsrc) + CLK_REF_CTRL: mmio.Mmio(packed struct(u32) { + /// Selects the clock source glitchlessly, can be changed on-the-fly + SRC: packed union { + raw: u2, + value: enum(u2) { + rosc_clksrc_ph = 0x0, + clksrc_clk_ref_aux = 0x1, + xosc_clksrc = 0x2, + _, + }, + }, + reserved5: u3, + /// Selects the auxiliary clock source, will glitch when switching + AUXSRC: packed union { + raw: u2, + value: enum(u2) { + clksrc_pll_usb = 0x0, + clksrc_gpin0 = 0x1, + clksrc_gpin1 = 0x2, + _, + }, + }, + padding: u25, + }), + /// Clock divisor, can be changed on-the-fly + CLK_REF_DIV: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// Integer component of the divisor, 0 -> divide by 2^16 + INT: u2, + padding: u22, + }), + /// Indicates which SRC is currently selected by the glitchless mux (one-hot). + /// The glitchless multiplexer does not switch instantaneously (to avoid glitches), so software should poll this register to wait for the switch to complete. This register contains one decoded bit for each of the clock sources enumerated in the CTRL SRC field. At most one of these bits will be set at any time, indicating that clock is currently present at the output of the glitchless mux. Whilst switching is in progress, this register may briefly show all-0s. + CLK_REF_SELECTED: u32, + /// Clock control, can be changed on-the-fly (except for auxsrc) + CLK_SYS_CTRL: mmio.Mmio(packed struct(u32) { + /// Selects the clock source glitchlessly, can be changed on-the-fly + SRC: packed union { + raw: u1, + value: enum(u1) { + clk_ref = 0x0, + clksrc_clk_sys_aux = 0x1, + }, + }, + reserved5: u4, + /// Selects the auxiliary clock source, will glitch when switching + AUXSRC: packed union { + raw: u3, + value: enum(u3) { + clksrc_pll_sys = 0x0, + clksrc_pll_usb = 0x1, + rosc_clksrc = 0x2, + xosc_clksrc = 0x3, + clksrc_gpin0 = 0x4, + clksrc_gpin1 = 0x5, + _, + }, + }, + padding: u24, + }), + /// Clock divisor, can be changed on-the-fly + CLK_SYS_DIV: mmio.Mmio(packed struct(u32) { + /// Fractional component of the divisor + FRAC: u8, + /// Integer component of the divisor, 0 -> divide by 2^16 + INT: u24, + }), + /// Indicates which SRC is currently selected by the glitchless mux (one-hot). + /// The glitchless multiplexer does not switch instantaneously (to avoid glitches), so software should poll this register to wait for the switch to complete. This register contains one decoded bit for each of the clock sources enumerated in the CTRL SRC field. At most one of these bits will be set at any time, indicating that clock is currently present at the output of the glitchless mux. Whilst switching is in progress, this register may briefly show all-0s. + CLK_SYS_SELECTED: u32, + /// Clock control, can be changed on-the-fly (except for auxsrc) + CLK_PERI_CTRL: mmio.Mmio(packed struct(u32) { + reserved5: u5, + /// Selects the auxiliary clock source, will glitch when switching + AUXSRC: packed union { + raw: u3, + value: enum(u3) { + clk_sys = 0x0, + clksrc_pll_sys = 0x1, + clksrc_pll_usb = 0x2, + rosc_clksrc_ph = 0x3, + xosc_clksrc = 0x4, + clksrc_gpin0 = 0x5, + clksrc_gpin1 = 0x6, + _, + }, + }, + reserved10: u2, + /// Asynchronously kills the clock generator + KILL: u1, + /// Starts and stops the clock generator cleanly + ENABLE: u1, + padding: u20, + }), + reserved80: [4]u8, + /// Indicates which SRC is currently selected by the glitchless mux (one-hot). + /// This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + CLK_PERI_SELECTED: u32, + /// Clock control, can be changed on-the-fly (except for auxsrc) + CLK_USB_CTRL: mmio.Mmio(packed struct(u32) { + reserved5: u5, + /// Selects the auxiliary clock source, will glitch when switching + AUXSRC: packed union { + raw: u3, + value: enum(u3) { + clksrc_pll_usb = 0x0, + clksrc_pll_sys = 0x1, + rosc_clksrc_ph = 0x2, + xosc_clksrc = 0x3, + clksrc_gpin0 = 0x4, + clksrc_gpin1 = 0x5, + _, + }, + }, + reserved10: u2, + /// Asynchronously kills the clock generator + KILL: u1, + /// Starts and stops the clock generator cleanly + ENABLE: u1, + reserved16: u4, + /// This delays the enable signal by up to 3 cycles of the input clock + /// This must be set before the clock is enabled to have any effect + PHASE: u2, + reserved20: u2, + /// An edge on this signal shifts the phase of the output by 1 cycle of the input clock + /// This can be done at any time + NUDGE: u1, + padding: u11, + }), + /// Clock divisor, can be changed on-the-fly + CLK_USB_DIV: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// Integer component of the divisor, 0 -> divide by 2^16 + INT: u2, + padding: u22, + }), + /// Indicates which SRC is currently selected by the glitchless mux (one-hot). + /// This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + CLK_USB_SELECTED: u32, + /// Clock control, can be changed on-the-fly (except for auxsrc) + CLK_ADC_CTRL: mmio.Mmio(packed struct(u32) { + reserved5: u5, + /// Selects the auxiliary clock source, will glitch when switching + AUXSRC: packed union { + raw: u3, + value: enum(u3) { + clksrc_pll_usb = 0x0, + clksrc_pll_sys = 0x1, + rosc_clksrc_ph = 0x2, + xosc_clksrc = 0x3, + clksrc_gpin0 = 0x4, + clksrc_gpin1 = 0x5, + _, + }, + }, + reserved10: u2, + /// Asynchronously kills the clock generator + KILL: u1, + /// Starts and stops the clock generator cleanly + ENABLE: u1, + reserved16: u4, + /// This delays the enable signal by up to 3 cycles of the input clock + /// This must be set before the clock is enabled to have any effect + PHASE: u2, + reserved20: u2, + /// An edge on this signal shifts the phase of the output by 1 cycle of the input clock + /// This can be done at any time + NUDGE: u1, + padding: u11, + }), + /// Clock divisor, can be changed on-the-fly + CLK_ADC_DIV: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// Integer component of the divisor, 0 -> divide by 2^16 + INT: u2, + padding: u22, + }), + /// Indicates which SRC is currently selected by the glitchless mux (one-hot). + /// This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + CLK_ADC_SELECTED: u32, + /// Clock control, can be changed on-the-fly (except for auxsrc) + CLK_RTC_CTRL: mmio.Mmio(packed struct(u32) { + reserved5: u5, + /// Selects the auxiliary clock source, will glitch when switching + AUXSRC: packed union { + raw: u3, + value: enum(u3) { + clksrc_pll_usb = 0x0, + clksrc_pll_sys = 0x1, + rosc_clksrc_ph = 0x2, + xosc_clksrc = 0x3, + clksrc_gpin0 = 0x4, + clksrc_gpin1 = 0x5, + _, + }, + }, + reserved10: u2, + /// Asynchronously kills the clock generator + KILL: u1, + /// Starts and stops the clock generator cleanly + ENABLE: u1, + reserved16: u4, + /// This delays the enable signal by up to 3 cycles of the input clock + /// This must be set before the clock is enabled to have any effect + PHASE: u2, + reserved20: u2, + /// An edge on this signal shifts the phase of the output by 1 cycle of the input clock + /// This can be done at any time + NUDGE: u1, + padding: u11, + }), + /// Clock divisor, can be changed on-the-fly + CLK_RTC_DIV: mmio.Mmio(packed struct(u32) { + /// Fractional component of the divisor + FRAC: u8, + /// Integer component of the divisor, 0 -> divide by 2^16 + INT: u24, + }), + /// Indicates which SRC is currently selected by the glitchless mux (one-hot). + /// This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + CLK_RTC_SELECTED: u32, + CLK_SYS_RESUS_CTRL: mmio.Mmio(packed struct(u32) { + /// This is expressed as a number of clk_ref cycles + /// and must be >= 2x clk_ref_freq/min_clk_tst_freq + TIMEOUT: u8, + /// Enable resus + ENABLE: u1, + reserved12: u3, + /// Force a resus, for test purposes only + FRCE: u1, + reserved16: u3, + /// For clearing the resus after the fault that triggered it has been corrected + CLEAR: u1, + padding: u15, + }), + CLK_SYS_RESUS_STATUS: mmio.Mmio(packed struct(u32) { + /// Clock has been resuscitated, correct the error then send ctrl_clear=1 + RESUSSED: u1, + padding: u31, + }), + /// Reference clock frequency in kHz + FC0_REF_KHZ: mmio.Mmio(packed struct(u32) { + FC0_REF_KHZ: u20, + padding: u12, + }), + /// Minimum pass frequency in kHz. This is optional. Set to 0 if you are not using the pass/fail flags + FC0_MIN_KHZ: mmio.Mmio(packed struct(u32) { + FC0_MIN_KHZ: u25, + padding: u7, + }), + /// Maximum pass frequency in kHz. This is optional. Set to 0x1ffffff if you are not using the pass/fail flags + FC0_MAX_KHZ: mmio.Mmio(packed struct(u32) { + FC0_MAX_KHZ: u25, + padding: u7, + }), + /// Delays the start of frequency counting to allow the mux to settle + /// Delay is measured in multiples of the reference clock period + FC0_DELAY: mmio.Mmio(packed struct(u32) { + FC0_DELAY: u3, + padding: u29, + }), + /// The test interval is 0.98us * 2**interval, but let's call it 1us * 2**interval + /// The default gives a test interval of 250us + FC0_INTERVAL: mmio.Mmio(packed struct(u32) { + FC0_INTERVAL: u4, + padding: u28, + }), + /// Clock sent to frequency counter, set to 0 when not required + /// Writing to this register initiates the frequency count + FC0_SRC: mmio.Mmio(packed struct(u32) { + FC0_SRC: packed union { + raw: u8, + value: enum(u8) { + NULL = 0x0, + pll_sys_clksrc_primary = 0x1, + pll_usb_clksrc_primary = 0x2, + rosc_clksrc = 0x3, + rosc_clksrc_ph = 0x4, + xosc_clksrc = 0x5, + clksrc_gpin0 = 0x6, + clksrc_gpin1 = 0x7, + clk_ref = 0x8, + clk_sys = 0x9, + clk_peri = 0xa, + clk_usb = 0xb, + clk_adc = 0xc, + clk_rtc = 0xd, + _, + }, + }, + padding: u24, + }), + /// Frequency counter status + FC0_STATUS: mmio.Mmio(packed struct(u32) { + /// Test passed + PASS: u1, + reserved4: u3, + /// Test complete + DONE: u1, + reserved8: u3, + /// Test running + RUNNING: u1, + reserved12: u3, + /// Waiting for test clock to start + WAITING: u1, + reserved16: u3, + /// Test failed + FAIL: u1, + reserved20: u3, + /// Test clock slower than expected, only valid when status_done=1 + SLOW: u1, + reserved24: u3, + /// Test clock faster than expected, only valid when status_done=1 + FAST: u1, + reserved28: u3, + /// Test clock stopped during test + DIED: u1, + padding: u3, + }), + /// Result of frequency measurement, only valid when status_done=1 + FC0_RESULT: mmio.Mmio(packed struct(u32) { + FRAC: u5, + KHZ: u25, + padding: u2, + }), + /// enable clock in wake mode + WAKE_EN0: mmio.Mmio(packed struct(u32) { + clk_sys_clocks: u1, + clk_adc_adc: u1, + clk_sys_adc: u1, + clk_sys_busctrl: u1, + clk_sys_busfabric: u1, + clk_sys_dma: u1, + clk_sys_i2c0: u1, + clk_sys_i2c1: u1, + clk_sys_io: u1, + clk_sys_jtag: u1, + clk_sys_vreg_and_chip_reset: u1, + clk_sys_pads: u1, + clk_sys_pio0: u1, + clk_sys_pio1: u1, + clk_sys_pll_sys: u1, + clk_sys_pll_usb: u1, + clk_sys_psm: u1, + clk_sys_pwm: u1, + clk_sys_resets: u1, + clk_sys_rom: u1, + clk_sys_rosc: u1, + clk_rtc_rtc: u1, + clk_sys_rtc: u1, + clk_sys_sio: u1, + clk_peri_spi0: u1, + clk_sys_spi0: u1, + clk_peri_spi1: u1, + clk_sys_spi1: u1, + clk_sys_sram0: u1, + clk_sys_sram1: u1, + clk_sys_sram2: u1, + clk_sys_sram3: u1, + }), + /// enable clock in wake mode + WAKE_EN1: mmio.Mmio(packed struct(u32) { + clk_sys_sram4: u1, + clk_sys_sram5: u1, + clk_sys_syscfg: u1, + clk_sys_sysinfo: u1, + clk_sys_tbman: u1, + clk_sys_timer: u1, + clk_peri_uart0: u1, + clk_sys_uart0: u1, + clk_peri_uart1: u1, + clk_sys_uart1: u1, + clk_sys_usbctrl: u1, + clk_usb_usbctrl: u1, + clk_sys_watchdog: u1, + clk_sys_xip: u1, + clk_sys_xosc: u1, + padding: u17, + }), + /// enable clock in sleep mode + SLEEP_EN0: mmio.Mmio(packed struct(u32) { + clk_sys_clocks: u1, + clk_adc_adc: u1, + clk_sys_adc: u1, + clk_sys_busctrl: u1, + clk_sys_busfabric: u1, + clk_sys_dma: u1, + clk_sys_i2c0: u1, + clk_sys_i2c1: u1, + clk_sys_io: u1, + clk_sys_jtag: u1, + clk_sys_vreg_and_chip_reset: u1, + clk_sys_pads: u1, + clk_sys_pio0: u1, + clk_sys_pio1: u1, + clk_sys_pll_sys: u1, + clk_sys_pll_usb: u1, + clk_sys_psm: u1, + clk_sys_pwm: u1, + clk_sys_resets: u1, + clk_sys_rom: u1, + clk_sys_rosc: u1, + clk_rtc_rtc: u1, + clk_sys_rtc: u1, + clk_sys_sio: u1, + clk_peri_spi0: u1, + clk_sys_spi0: u1, + clk_peri_spi1: u1, + clk_sys_spi1: u1, + clk_sys_sram0: u1, + clk_sys_sram1: u1, + clk_sys_sram2: u1, + clk_sys_sram3: u1, + }), + /// enable clock in sleep mode + SLEEP_EN1: mmio.Mmio(packed struct(u32) { + clk_sys_sram4: u1, + clk_sys_sram5: u1, + clk_sys_syscfg: u1, + clk_sys_sysinfo: u1, + clk_sys_tbman: u1, + clk_sys_timer: u1, + clk_peri_uart0: u1, + clk_sys_uart0: u1, + clk_peri_uart1: u1, + clk_sys_uart1: u1, + clk_sys_usbctrl: u1, + clk_usb_usbctrl: u1, + clk_sys_watchdog: u1, + clk_sys_xip: u1, + clk_sys_xosc: u1, + padding: u17, + }), + /// indicates the state of the clock enable + ENABLED0: mmio.Mmio(packed struct(u32) { + clk_sys_clocks: u1, + clk_adc_adc: u1, + clk_sys_adc: u1, + clk_sys_busctrl: u1, + clk_sys_busfabric: u1, + clk_sys_dma: u1, + clk_sys_i2c0: u1, + clk_sys_i2c1: u1, + clk_sys_io: u1, + clk_sys_jtag: u1, + clk_sys_vreg_and_chip_reset: u1, + clk_sys_pads: u1, + clk_sys_pio0: u1, + clk_sys_pio1: u1, + clk_sys_pll_sys: u1, + clk_sys_pll_usb: u1, + clk_sys_psm: u1, + clk_sys_pwm: u1, + clk_sys_resets: u1, + clk_sys_rom: u1, + clk_sys_rosc: u1, + clk_rtc_rtc: u1, + clk_sys_rtc: u1, + clk_sys_sio: u1, + clk_peri_spi0: u1, + clk_sys_spi0: u1, + clk_peri_spi1: u1, + clk_sys_spi1: u1, + clk_sys_sram0: u1, + clk_sys_sram1: u1, + clk_sys_sram2: u1, + clk_sys_sram3: u1, + }), + /// indicates the state of the clock enable + ENABLED1: mmio.Mmio(packed struct(u32) { + clk_sys_sram4: u1, + clk_sys_sram5: u1, + clk_sys_syscfg: u1, + clk_sys_sysinfo: u1, + clk_sys_tbman: u1, + clk_sys_timer: u1, + clk_peri_uart0: u1, + clk_sys_uart0: u1, + clk_peri_uart1: u1, + clk_sys_uart1: u1, + clk_sys_usbctrl: u1, + clk_usb_usbctrl: u1, + clk_sys_watchdog: u1, + clk_sys_xip: u1, + clk_sys_xosc: u1, + padding: u17, + }), + /// Raw Interrupts + INTR: mmio.Mmio(packed struct(u32) { + CLK_SYS_RESUS: u1, + padding: u31, + }), + /// Interrupt Enable + INTE: mmio.Mmio(packed struct(u32) { + CLK_SYS_RESUS: u1, + padding: u31, + }), + /// Interrupt Force + INTF: mmio.Mmio(packed struct(u32) { + CLK_SYS_RESUS: u1, + padding: u31, + }), + /// Interrupt status after masking & forcing + INTS: mmio.Mmio(packed struct(u32) { + CLK_SYS_RESUS: u1, + padding: u31, + }), + }; + + pub const RESETS = extern struct { + /// Reset control. If a bit is set it means the peripheral is in reset. 0 means the peripheral's reset is deasserted. + RESET: mmio.Mmio(packed struct(u32) { + adc: u1, + busctrl: u1, + dma: u1, + i2c0: u1, + i2c1: u1, + io_bank0: u1, + io_qspi: u1, + jtag: u1, + pads_bank0: u1, + pads_qspi: u1, + pio0: u1, + pio1: u1, + pll_sys: u1, + pll_usb: u1, + pwm: u1, + rtc: u1, + spi0: u1, + spi1: u1, + syscfg: u1, + sysinfo: u1, + tbman: u1, + timer: u1, + uart0: u1, + uart1: u1, + usbctrl: u1, + padding: u7, + }), + /// Watchdog select. If a bit is set then the watchdog will reset this peripheral when the watchdog fires. + WDSEL: mmio.Mmio(packed struct(u32) { + adc: u1, + busctrl: u1, + dma: u1, + i2c0: u1, + i2c1: u1, + io_bank0: u1, + io_qspi: u1, + jtag: u1, + pads_bank0: u1, + pads_qspi: u1, + pio0: u1, + pio1: u1, + pll_sys: u1, + pll_usb: u1, + pwm: u1, + rtc: u1, + spi0: u1, + spi1: u1, + syscfg: u1, + sysinfo: u1, + tbman: u1, + timer: u1, + uart0: u1, + uart1: u1, + usbctrl: u1, + padding: u7, + }), + /// Reset done. If a bit is set then a reset done signal has been returned by the peripheral. This indicates that the peripheral's registers are ready to be accessed. + RESET_DONE: mmio.Mmio(packed struct(u32) { + adc: u1, + busctrl: u1, + dma: u1, + i2c0: u1, + i2c1: u1, + io_bank0: u1, + io_qspi: u1, + jtag: u1, + pads_bank0: u1, + pads_qspi: u1, + pio0: u1, + pio1: u1, + pll_sys: u1, + pll_usb: u1, + pwm: u1, + rtc: u1, + spi0: u1, + spi1: u1, + syscfg: u1, + sysinfo: u1, + tbman: u1, + timer: u1, + uart0: u1, + uart1: u1, + usbctrl: u1, + padding: u7, + }), + }; + + pub const PSM = extern struct { + /// Force block out of reset (i.e. power it on) + FRCE_ON: mmio.Mmio(packed struct(u32) { + rosc: u1, + xosc: u1, + clocks: u1, + resets: u1, + busfabric: u1, + rom: u1, + sram0: u1, + sram1: u1, + sram2: u1, + sram3: u1, + sram4: u1, + sram5: u1, + xip: u1, + vreg_and_chip_reset: u1, + sio: u1, + proc0: u1, + proc1: u1, + padding: u15, + }), + /// Force into reset (i.e. power it off) + FRCE_OFF: mmio.Mmio(packed struct(u32) { + rosc: u1, + xosc: u1, + clocks: u1, + resets: u1, + busfabric: u1, + rom: u1, + sram0: u1, + sram1: u1, + sram2: u1, + sram3: u1, + sram4: u1, + sram5: u1, + xip: u1, + vreg_and_chip_reset: u1, + sio: u1, + proc0: u1, + proc1: u1, + padding: u15, + }), + /// Set to 1 if this peripheral should be reset when the watchdog fires. + WDSEL: mmio.Mmio(packed struct(u32) { + rosc: u1, + xosc: u1, + clocks: u1, + resets: u1, + busfabric: u1, + rom: u1, + sram0: u1, + sram1: u1, + sram2: u1, + sram3: u1, + sram4: u1, + sram5: u1, + xip: u1, + vreg_and_chip_reset: u1, + sio: u1, + proc0: u1, + proc1: u1, + padding: u15, + }), + /// Indicates the peripheral's registers are ready to access. + DONE: mmio.Mmio(packed struct(u32) { + rosc: u1, + xosc: u1, + clocks: u1, + resets: u1, + busfabric: u1, + rom: u1, + sram0: u1, + sram1: u1, + sram2: u1, + sram3: u1, + sram4: u1, + sram5: u1, + xip: u1, + vreg_and_chip_reset: u1, + sio: u1, + proc0: u1, + proc1: u1, + padding: u15, + }), + }; + + pub const IO_BANK0 = extern struct { + /// GPIO status + GPIO0_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO0_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + jtag_tck = 0x0, + spi0_rx = 0x1, + uart0_tx = 0x2, + i2c0_sda = 0x3, + pwm_a_0 = 0x4, + sio_0 = 0x5, + pio0_0 = 0x6, + pio1_0 = 0x7, + usb_muxing_overcurr_detect = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO1_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO1_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + jtag_tms = 0x0, + spi0_ss_n = 0x1, + uart0_rx = 0x2, + i2c0_scl = 0x3, + pwm_b_0 = 0x4, + sio_1 = 0x5, + pio0_1 = 0x6, + pio1_1 = 0x7, + usb_muxing_vbus_detect = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO2_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO2_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + jtag_tdi = 0x0, + spi0_sclk = 0x1, + uart0_cts = 0x2, + i2c1_sda = 0x3, + pwm_a_1 = 0x4, + sio_2 = 0x5, + pio0_2 = 0x6, + pio1_2 = 0x7, + usb_muxing_vbus_en = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO3_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO3_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + jtag_tdo = 0x0, + spi0_tx = 0x1, + uart0_rts = 0x2, + i2c1_scl = 0x3, + pwm_b_1 = 0x4, + sio_3 = 0x5, + pio0_3 = 0x6, + pio1_3 = 0x7, + usb_muxing_overcurr_detect = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO4_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO4_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + spi0_rx = 0x1, + uart1_tx = 0x2, + i2c0_sda = 0x3, + pwm_a_2 = 0x4, + sio_4 = 0x5, + pio0_4 = 0x6, + pio1_4 = 0x7, + usb_muxing_vbus_detect = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO5_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO5_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + spi0_ss_n = 0x1, + uart1_rx = 0x2, + i2c0_scl = 0x3, + pwm_b_2 = 0x4, + sio_5 = 0x5, + pio0_5 = 0x6, + pio1_5 = 0x7, + usb_muxing_vbus_en = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO6_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO6_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + spi0_sclk = 0x1, + uart1_cts = 0x2, + i2c1_sda = 0x3, + pwm_a_3 = 0x4, + sio_6 = 0x5, + pio0_6 = 0x6, + pio1_6 = 0x7, + usb_muxing_extphy_softcon = 0x8, + usb_muxing_overcurr_detect = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO7_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO7_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + spi0_tx = 0x1, + uart1_rts = 0x2, + i2c1_scl = 0x3, + pwm_b_3 = 0x4, + sio_7 = 0x5, + pio0_7 = 0x6, + pio1_7 = 0x7, + usb_muxing_extphy_oe_n = 0x8, + usb_muxing_vbus_detect = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO8_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO8_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + spi1_rx = 0x1, + uart1_tx = 0x2, + i2c0_sda = 0x3, + pwm_a_4 = 0x4, + sio_8 = 0x5, + pio0_8 = 0x6, + pio1_8 = 0x7, + usb_muxing_extphy_rcv = 0x8, + usb_muxing_vbus_en = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO9_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO9_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + spi1_ss_n = 0x1, + uart1_rx = 0x2, + i2c0_scl = 0x3, + pwm_b_4 = 0x4, + sio_9 = 0x5, + pio0_9 = 0x6, + pio1_9 = 0x7, + usb_muxing_extphy_vp = 0x8, + usb_muxing_overcurr_detect = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO10_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO10_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + spi1_sclk = 0x1, + uart1_cts = 0x2, + i2c1_sda = 0x3, + pwm_a_5 = 0x4, + sio_10 = 0x5, + pio0_10 = 0x6, + pio1_10 = 0x7, + usb_muxing_extphy_vm = 0x8, + usb_muxing_vbus_detect = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO11_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO11_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + spi1_tx = 0x1, + uart1_rts = 0x2, + i2c1_scl = 0x3, + pwm_b_5 = 0x4, + sio_11 = 0x5, + pio0_11 = 0x6, + pio1_11 = 0x7, + usb_muxing_extphy_suspnd = 0x8, + usb_muxing_vbus_en = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO12_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO12_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + spi1_rx = 0x1, + uart0_tx = 0x2, + i2c0_sda = 0x3, + pwm_a_6 = 0x4, + sio_12 = 0x5, + pio0_12 = 0x6, + pio1_12 = 0x7, + usb_muxing_extphy_speed = 0x8, + usb_muxing_overcurr_detect = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO13_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO13_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + spi1_ss_n = 0x1, + uart0_rx = 0x2, + i2c0_scl = 0x3, + pwm_b_6 = 0x4, + sio_13 = 0x5, + pio0_13 = 0x6, + pio1_13 = 0x7, + usb_muxing_extphy_vpo = 0x8, + usb_muxing_vbus_detect = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO14_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO14_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + spi1_sclk = 0x1, + uart0_cts = 0x2, + i2c1_sda = 0x3, + pwm_a_7 = 0x4, + sio_14 = 0x5, + pio0_14 = 0x6, + pio1_14 = 0x7, + usb_muxing_extphy_vmo = 0x8, + usb_muxing_vbus_en = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO15_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO15_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + spi1_tx = 0x1, + uart0_rts = 0x2, + i2c1_scl = 0x3, + pwm_b_7 = 0x4, + sio_15 = 0x5, + pio0_15 = 0x6, + pio1_15 = 0x7, + usb_muxing_digital_dp = 0x8, + usb_muxing_overcurr_detect = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO16_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO16_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + spi0_rx = 0x1, + uart0_tx = 0x2, + i2c0_sda = 0x3, + pwm_a_0 = 0x4, + sio_16 = 0x5, + pio0_16 = 0x6, + pio1_16 = 0x7, + usb_muxing_digital_dm = 0x8, + usb_muxing_vbus_detect = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO17_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO17_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + spi0_ss_n = 0x1, + uart0_rx = 0x2, + i2c0_scl = 0x3, + pwm_b_0 = 0x4, + sio_17 = 0x5, + pio0_17 = 0x6, + pio1_17 = 0x7, + usb_muxing_vbus_en = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO18_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO18_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + spi0_sclk = 0x1, + uart0_cts = 0x2, + i2c1_sda = 0x3, + pwm_a_1 = 0x4, + sio_18 = 0x5, + pio0_18 = 0x6, + pio1_18 = 0x7, + usb_muxing_overcurr_detect = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO19_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO19_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + spi0_tx = 0x1, + uart0_rts = 0x2, + i2c1_scl = 0x3, + pwm_b_1 = 0x4, + sio_19 = 0x5, + pio0_19 = 0x6, + pio1_19 = 0x7, + usb_muxing_vbus_detect = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO20_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO20_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + spi0_rx = 0x1, + uart1_tx = 0x2, + i2c0_sda = 0x3, + pwm_a_2 = 0x4, + sio_20 = 0x5, + pio0_20 = 0x6, + pio1_20 = 0x7, + clocks_gpin_0 = 0x8, + usb_muxing_vbus_en = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO21_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO21_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + spi0_ss_n = 0x1, + uart1_rx = 0x2, + i2c0_scl = 0x3, + pwm_b_2 = 0x4, + sio_21 = 0x5, + pio0_21 = 0x6, + pio1_21 = 0x7, + clocks_gpout_0 = 0x8, + usb_muxing_overcurr_detect = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO22_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO22_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + spi0_sclk = 0x1, + uart1_cts = 0x2, + i2c1_sda = 0x3, + pwm_a_3 = 0x4, + sio_22 = 0x5, + pio0_22 = 0x6, + pio1_22 = 0x7, + clocks_gpin_1 = 0x8, + usb_muxing_vbus_detect = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO23_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO23_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + spi0_tx = 0x1, + uart1_rts = 0x2, + i2c1_scl = 0x3, + pwm_b_3 = 0x4, + sio_23 = 0x5, + pio0_23 = 0x6, + pio1_23 = 0x7, + clocks_gpout_1 = 0x8, + usb_muxing_vbus_en = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO24_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO24_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + spi1_rx = 0x1, + uart1_tx = 0x2, + i2c0_sda = 0x3, + pwm_a_4 = 0x4, + sio_24 = 0x5, + pio0_24 = 0x6, + pio1_24 = 0x7, + clocks_gpout_2 = 0x8, + usb_muxing_overcurr_detect = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO25_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO25_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + spi1_ss_n = 0x1, + uart1_rx = 0x2, + i2c0_scl = 0x3, + pwm_b_4 = 0x4, + sio_25 = 0x5, + pio0_25 = 0x6, + pio1_25 = 0x7, + clocks_gpout_3 = 0x8, + usb_muxing_vbus_detect = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO26_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO26_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + spi1_sclk = 0x1, + uart1_cts = 0x2, + i2c1_sda = 0x3, + pwm_a_5 = 0x4, + sio_26 = 0x5, + pio0_26 = 0x6, + pio1_26 = 0x7, + usb_muxing_vbus_en = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO27_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO27_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + spi1_tx = 0x1, + uart1_rts = 0x2, + i2c1_scl = 0x3, + pwm_b_5 = 0x4, + sio_27 = 0x5, + pio0_27 = 0x6, + pio1_27 = 0x7, + usb_muxing_overcurr_detect = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO28_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO28_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + spi1_rx = 0x1, + uart0_tx = 0x2, + i2c0_sda = 0x3, + pwm_a_6 = 0x4, + sio_28 = 0x5, + pio0_28 = 0x6, + pio1_28 = 0x7, + usb_muxing_vbus_detect = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO29_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO29_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + spi1_ss_n = 0x1, + uart0_rx = 0x2, + i2c0_scl = 0x3, + pwm_b_6 = 0x4, + sio_29 = 0x5, + pio0_29 = 0x6, + pio1_29 = 0x7, + usb_muxing_vbus_en = 0x9, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// Raw Interrupts + INTR0: mmio.Mmio(packed struct(u32) { + GPIO0_LEVEL_LOW: u1, + GPIO0_LEVEL_HIGH: u1, + GPIO0_EDGE_LOW: u1, + GPIO0_EDGE_HIGH: u1, + GPIO1_LEVEL_LOW: u1, + GPIO1_LEVEL_HIGH: u1, + GPIO1_EDGE_LOW: u1, + GPIO1_EDGE_HIGH: u1, + GPIO2_LEVEL_LOW: u1, + GPIO2_LEVEL_HIGH: u1, + GPIO2_EDGE_LOW: u1, + GPIO2_EDGE_HIGH: u1, + GPIO3_LEVEL_LOW: u1, + GPIO3_LEVEL_HIGH: u1, + GPIO3_EDGE_LOW: u1, + GPIO3_EDGE_HIGH: u1, + GPIO4_LEVEL_LOW: u1, + GPIO4_LEVEL_HIGH: u1, + GPIO4_EDGE_LOW: u1, + GPIO4_EDGE_HIGH: u1, + GPIO5_LEVEL_LOW: u1, + GPIO5_LEVEL_HIGH: u1, + GPIO5_EDGE_LOW: u1, + GPIO5_EDGE_HIGH: u1, + GPIO6_LEVEL_LOW: u1, + GPIO6_LEVEL_HIGH: u1, + GPIO6_EDGE_LOW: u1, + GPIO6_EDGE_HIGH: u1, + GPIO7_LEVEL_LOW: u1, + GPIO7_LEVEL_HIGH: u1, + GPIO7_EDGE_LOW: u1, + GPIO7_EDGE_HIGH: u1, + }), + /// Raw Interrupts + INTR1: mmio.Mmio(packed struct(u32) { + GPIO8_LEVEL_LOW: u1, + GPIO8_LEVEL_HIGH: u1, + GPIO8_EDGE_LOW: u1, + GPIO8_EDGE_HIGH: u1, + GPIO9_LEVEL_LOW: u1, + GPIO9_LEVEL_HIGH: u1, + GPIO9_EDGE_LOW: u1, + GPIO9_EDGE_HIGH: u1, + GPIO10_LEVEL_LOW: u1, + GPIO10_LEVEL_HIGH: u1, + GPIO10_EDGE_LOW: u1, + GPIO10_EDGE_HIGH: u1, + GPIO11_LEVEL_LOW: u1, + GPIO11_LEVEL_HIGH: u1, + GPIO11_EDGE_LOW: u1, + GPIO11_EDGE_HIGH: u1, + GPIO12_LEVEL_LOW: u1, + GPIO12_LEVEL_HIGH: u1, + GPIO12_EDGE_LOW: u1, + GPIO12_EDGE_HIGH: u1, + GPIO13_LEVEL_LOW: u1, + GPIO13_LEVEL_HIGH: u1, + GPIO13_EDGE_LOW: u1, + GPIO13_EDGE_HIGH: u1, + GPIO14_LEVEL_LOW: u1, + GPIO14_LEVEL_HIGH: u1, + GPIO14_EDGE_LOW: u1, + GPIO14_EDGE_HIGH: u1, + GPIO15_LEVEL_LOW: u1, + GPIO15_LEVEL_HIGH: u1, + GPIO15_EDGE_LOW: u1, + GPIO15_EDGE_HIGH: u1, + }), + /// Raw Interrupts + INTR2: mmio.Mmio(packed struct(u32) { + GPIO16_LEVEL_LOW: u1, + GPIO16_LEVEL_HIGH: u1, + GPIO16_EDGE_LOW: u1, + GPIO16_EDGE_HIGH: u1, + GPIO17_LEVEL_LOW: u1, + GPIO17_LEVEL_HIGH: u1, + GPIO17_EDGE_LOW: u1, + GPIO17_EDGE_HIGH: u1, + GPIO18_LEVEL_LOW: u1, + GPIO18_LEVEL_HIGH: u1, + GPIO18_EDGE_LOW: u1, + GPIO18_EDGE_HIGH: u1, + GPIO19_LEVEL_LOW: u1, + GPIO19_LEVEL_HIGH: u1, + GPIO19_EDGE_LOW: u1, + GPIO19_EDGE_HIGH: u1, + GPIO20_LEVEL_LOW: u1, + GPIO20_LEVEL_HIGH: u1, + GPIO20_EDGE_LOW: u1, + GPIO20_EDGE_HIGH: u1, + GPIO21_LEVEL_LOW: u1, + GPIO21_LEVEL_HIGH: u1, + GPIO21_EDGE_LOW: u1, + GPIO21_EDGE_HIGH: u1, + GPIO22_LEVEL_LOW: u1, + GPIO22_LEVEL_HIGH: u1, + GPIO22_EDGE_LOW: u1, + GPIO22_EDGE_HIGH: u1, + GPIO23_LEVEL_LOW: u1, + GPIO23_LEVEL_HIGH: u1, + GPIO23_EDGE_LOW: u1, + GPIO23_EDGE_HIGH: u1, + }), + /// Raw Interrupts + INTR3: mmio.Mmio(packed struct(u32) { + GPIO24_LEVEL_LOW: u1, + GPIO24_LEVEL_HIGH: u1, + GPIO24_EDGE_LOW: u1, + GPIO24_EDGE_HIGH: u1, + GPIO25_LEVEL_LOW: u1, + GPIO25_LEVEL_HIGH: u1, + GPIO25_EDGE_LOW: u1, + GPIO25_EDGE_HIGH: u1, + GPIO26_LEVEL_LOW: u1, + GPIO26_LEVEL_HIGH: u1, + GPIO26_EDGE_LOW: u1, + GPIO26_EDGE_HIGH: u1, + GPIO27_LEVEL_LOW: u1, + GPIO27_LEVEL_HIGH: u1, + GPIO27_EDGE_LOW: u1, + GPIO27_EDGE_HIGH: u1, + GPIO28_LEVEL_LOW: u1, + GPIO28_LEVEL_HIGH: u1, + GPIO28_EDGE_LOW: u1, + GPIO28_EDGE_HIGH: u1, + GPIO29_LEVEL_LOW: u1, + GPIO29_LEVEL_HIGH: u1, + GPIO29_EDGE_LOW: u1, + GPIO29_EDGE_HIGH: u1, + padding: u8, + }), + /// Interrupt Enable for proc0 + PROC0_INTE0: mmio.Mmio(packed struct(u32) { + GPIO0_LEVEL_LOW: u1, + GPIO0_LEVEL_HIGH: u1, + GPIO0_EDGE_LOW: u1, + GPIO0_EDGE_HIGH: u1, + GPIO1_LEVEL_LOW: u1, + GPIO1_LEVEL_HIGH: u1, + GPIO1_EDGE_LOW: u1, + GPIO1_EDGE_HIGH: u1, + GPIO2_LEVEL_LOW: u1, + GPIO2_LEVEL_HIGH: u1, + GPIO2_EDGE_LOW: u1, + GPIO2_EDGE_HIGH: u1, + GPIO3_LEVEL_LOW: u1, + GPIO3_LEVEL_HIGH: u1, + GPIO3_EDGE_LOW: u1, + GPIO3_EDGE_HIGH: u1, + GPIO4_LEVEL_LOW: u1, + GPIO4_LEVEL_HIGH: u1, + GPIO4_EDGE_LOW: u1, + GPIO4_EDGE_HIGH: u1, + GPIO5_LEVEL_LOW: u1, + GPIO5_LEVEL_HIGH: u1, + GPIO5_EDGE_LOW: u1, + GPIO5_EDGE_HIGH: u1, + GPIO6_LEVEL_LOW: u1, + GPIO6_LEVEL_HIGH: u1, + GPIO6_EDGE_LOW: u1, + GPIO6_EDGE_HIGH: u1, + GPIO7_LEVEL_LOW: u1, + GPIO7_LEVEL_HIGH: u1, + GPIO7_EDGE_LOW: u1, + GPIO7_EDGE_HIGH: u1, + }), + /// Interrupt Enable for proc0 + PROC0_INTE1: mmio.Mmio(packed struct(u32) { + GPIO8_LEVEL_LOW: u1, + GPIO8_LEVEL_HIGH: u1, + GPIO8_EDGE_LOW: u1, + GPIO8_EDGE_HIGH: u1, + GPIO9_LEVEL_LOW: u1, + GPIO9_LEVEL_HIGH: u1, + GPIO9_EDGE_LOW: u1, + GPIO9_EDGE_HIGH: u1, + GPIO10_LEVEL_LOW: u1, + GPIO10_LEVEL_HIGH: u1, + GPIO10_EDGE_LOW: u1, + GPIO10_EDGE_HIGH: u1, + GPIO11_LEVEL_LOW: u1, + GPIO11_LEVEL_HIGH: u1, + GPIO11_EDGE_LOW: u1, + GPIO11_EDGE_HIGH: u1, + GPIO12_LEVEL_LOW: u1, + GPIO12_LEVEL_HIGH: u1, + GPIO12_EDGE_LOW: u1, + GPIO12_EDGE_HIGH: u1, + GPIO13_LEVEL_LOW: u1, + GPIO13_LEVEL_HIGH: u1, + GPIO13_EDGE_LOW: u1, + GPIO13_EDGE_HIGH: u1, + GPIO14_LEVEL_LOW: u1, + GPIO14_LEVEL_HIGH: u1, + GPIO14_EDGE_LOW: u1, + GPIO14_EDGE_HIGH: u1, + GPIO15_LEVEL_LOW: u1, + GPIO15_LEVEL_HIGH: u1, + GPIO15_EDGE_LOW: u1, + GPIO15_EDGE_HIGH: u1, + }), + /// Interrupt Enable for proc0 + PROC0_INTE2: mmio.Mmio(packed struct(u32) { + GPIO16_LEVEL_LOW: u1, + GPIO16_LEVEL_HIGH: u1, + GPIO16_EDGE_LOW: u1, + GPIO16_EDGE_HIGH: u1, + GPIO17_LEVEL_LOW: u1, + GPIO17_LEVEL_HIGH: u1, + GPIO17_EDGE_LOW: u1, + GPIO17_EDGE_HIGH: u1, + GPIO18_LEVEL_LOW: u1, + GPIO18_LEVEL_HIGH: u1, + GPIO18_EDGE_LOW: u1, + GPIO18_EDGE_HIGH: u1, + GPIO19_LEVEL_LOW: u1, + GPIO19_LEVEL_HIGH: u1, + GPIO19_EDGE_LOW: u1, + GPIO19_EDGE_HIGH: u1, + GPIO20_LEVEL_LOW: u1, + GPIO20_LEVEL_HIGH: u1, + GPIO20_EDGE_LOW: u1, + GPIO20_EDGE_HIGH: u1, + GPIO21_LEVEL_LOW: u1, + GPIO21_LEVEL_HIGH: u1, + GPIO21_EDGE_LOW: u1, + GPIO21_EDGE_HIGH: u1, + GPIO22_LEVEL_LOW: u1, + GPIO22_LEVEL_HIGH: u1, + GPIO22_EDGE_LOW: u1, + GPIO22_EDGE_HIGH: u1, + GPIO23_LEVEL_LOW: u1, + GPIO23_LEVEL_HIGH: u1, + GPIO23_EDGE_LOW: u1, + GPIO23_EDGE_HIGH: u1, + }), + /// Interrupt Enable for proc0 + PROC0_INTE3: mmio.Mmio(packed struct(u32) { + GPIO24_LEVEL_LOW: u1, + GPIO24_LEVEL_HIGH: u1, + GPIO24_EDGE_LOW: u1, + GPIO24_EDGE_HIGH: u1, + GPIO25_LEVEL_LOW: u1, + GPIO25_LEVEL_HIGH: u1, + GPIO25_EDGE_LOW: u1, + GPIO25_EDGE_HIGH: u1, + GPIO26_LEVEL_LOW: u1, + GPIO26_LEVEL_HIGH: u1, + GPIO26_EDGE_LOW: u1, + GPIO26_EDGE_HIGH: u1, + GPIO27_LEVEL_LOW: u1, + GPIO27_LEVEL_HIGH: u1, + GPIO27_EDGE_LOW: u1, + GPIO27_EDGE_HIGH: u1, + GPIO28_LEVEL_LOW: u1, + GPIO28_LEVEL_HIGH: u1, + GPIO28_EDGE_LOW: u1, + GPIO28_EDGE_HIGH: u1, + GPIO29_LEVEL_LOW: u1, + GPIO29_LEVEL_HIGH: u1, + GPIO29_EDGE_LOW: u1, + GPIO29_EDGE_HIGH: u1, + padding: u8, + }), + /// Interrupt Force for proc0 + PROC0_INTF0: mmio.Mmio(packed struct(u32) { + GPIO0_LEVEL_LOW: u1, + GPIO0_LEVEL_HIGH: u1, + GPIO0_EDGE_LOW: u1, + GPIO0_EDGE_HIGH: u1, + GPIO1_LEVEL_LOW: u1, + GPIO1_LEVEL_HIGH: u1, + GPIO1_EDGE_LOW: u1, + GPIO1_EDGE_HIGH: u1, + GPIO2_LEVEL_LOW: u1, + GPIO2_LEVEL_HIGH: u1, + GPIO2_EDGE_LOW: u1, + GPIO2_EDGE_HIGH: u1, + GPIO3_LEVEL_LOW: u1, + GPIO3_LEVEL_HIGH: u1, + GPIO3_EDGE_LOW: u1, + GPIO3_EDGE_HIGH: u1, + GPIO4_LEVEL_LOW: u1, + GPIO4_LEVEL_HIGH: u1, + GPIO4_EDGE_LOW: u1, + GPIO4_EDGE_HIGH: u1, + GPIO5_LEVEL_LOW: u1, + GPIO5_LEVEL_HIGH: u1, + GPIO5_EDGE_LOW: u1, + GPIO5_EDGE_HIGH: u1, + GPIO6_LEVEL_LOW: u1, + GPIO6_LEVEL_HIGH: u1, + GPIO6_EDGE_LOW: u1, + GPIO6_EDGE_HIGH: u1, + GPIO7_LEVEL_LOW: u1, + GPIO7_LEVEL_HIGH: u1, + GPIO7_EDGE_LOW: u1, + GPIO7_EDGE_HIGH: u1, + }), + /// Interrupt Force for proc0 + PROC0_INTF1: mmio.Mmio(packed struct(u32) { + GPIO8_LEVEL_LOW: u1, + GPIO8_LEVEL_HIGH: u1, + GPIO8_EDGE_LOW: u1, + GPIO8_EDGE_HIGH: u1, + GPIO9_LEVEL_LOW: u1, + GPIO9_LEVEL_HIGH: u1, + GPIO9_EDGE_LOW: u1, + GPIO9_EDGE_HIGH: u1, + GPIO10_LEVEL_LOW: u1, + GPIO10_LEVEL_HIGH: u1, + GPIO10_EDGE_LOW: u1, + GPIO10_EDGE_HIGH: u1, + GPIO11_LEVEL_LOW: u1, + GPIO11_LEVEL_HIGH: u1, + GPIO11_EDGE_LOW: u1, + GPIO11_EDGE_HIGH: u1, + GPIO12_LEVEL_LOW: u1, + GPIO12_LEVEL_HIGH: u1, + GPIO12_EDGE_LOW: u1, + GPIO12_EDGE_HIGH: u1, + GPIO13_LEVEL_LOW: u1, + GPIO13_LEVEL_HIGH: u1, + GPIO13_EDGE_LOW: u1, + GPIO13_EDGE_HIGH: u1, + GPIO14_LEVEL_LOW: u1, + GPIO14_LEVEL_HIGH: u1, + GPIO14_EDGE_LOW: u1, + GPIO14_EDGE_HIGH: u1, + GPIO15_LEVEL_LOW: u1, + GPIO15_LEVEL_HIGH: u1, + GPIO15_EDGE_LOW: u1, + GPIO15_EDGE_HIGH: u1, + }), + /// Interrupt Force for proc0 + PROC0_INTF2: mmio.Mmio(packed struct(u32) { + GPIO16_LEVEL_LOW: u1, + GPIO16_LEVEL_HIGH: u1, + GPIO16_EDGE_LOW: u1, + GPIO16_EDGE_HIGH: u1, + GPIO17_LEVEL_LOW: u1, + GPIO17_LEVEL_HIGH: u1, + GPIO17_EDGE_LOW: u1, + GPIO17_EDGE_HIGH: u1, + GPIO18_LEVEL_LOW: u1, + GPIO18_LEVEL_HIGH: u1, + GPIO18_EDGE_LOW: u1, + GPIO18_EDGE_HIGH: u1, + GPIO19_LEVEL_LOW: u1, + GPIO19_LEVEL_HIGH: u1, + GPIO19_EDGE_LOW: u1, + GPIO19_EDGE_HIGH: u1, + GPIO20_LEVEL_LOW: u1, + GPIO20_LEVEL_HIGH: u1, + GPIO20_EDGE_LOW: u1, + GPIO20_EDGE_HIGH: u1, + GPIO21_LEVEL_LOW: u1, + GPIO21_LEVEL_HIGH: u1, + GPIO21_EDGE_LOW: u1, + GPIO21_EDGE_HIGH: u1, + GPIO22_LEVEL_LOW: u1, + GPIO22_LEVEL_HIGH: u1, + GPIO22_EDGE_LOW: u1, + GPIO22_EDGE_HIGH: u1, + GPIO23_LEVEL_LOW: u1, + GPIO23_LEVEL_HIGH: u1, + GPIO23_EDGE_LOW: u1, + GPIO23_EDGE_HIGH: u1, + }), + /// Interrupt Force for proc0 + PROC0_INTF3: mmio.Mmio(packed struct(u32) { + GPIO24_LEVEL_LOW: u1, + GPIO24_LEVEL_HIGH: u1, + GPIO24_EDGE_LOW: u1, + GPIO24_EDGE_HIGH: u1, + GPIO25_LEVEL_LOW: u1, + GPIO25_LEVEL_HIGH: u1, + GPIO25_EDGE_LOW: u1, + GPIO25_EDGE_HIGH: u1, + GPIO26_LEVEL_LOW: u1, + GPIO26_LEVEL_HIGH: u1, + GPIO26_EDGE_LOW: u1, + GPIO26_EDGE_HIGH: u1, + GPIO27_LEVEL_LOW: u1, + GPIO27_LEVEL_HIGH: u1, + GPIO27_EDGE_LOW: u1, + GPIO27_EDGE_HIGH: u1, + GPIO28_LEVEL_LOW: u1, + GPIO28_LEVEL_HIGH: u1, + GPIO28_EDGE_LOW: u1, + GPIO28_EDGE_HIGH: u1, + GPIO29_LEVEL_LOW: u1, + GPIO29_LEVEL_HIGH: u1, + GPIO29_EDGE_LOW: u1, + GPIO29_EDGE_HIGH: u1, + padding: u8, + }), + /// Interrupt status after masking & forcing for proc0 + PROC0_INTS0: mmio.Mmio(packed struct(u32) { + GPIO0_LEVEL_LOW: u1, + GPIO0_LEVEL_HIGH: u1, + GPIO0_EDGE_LOW: u1, + GPIO0_EDGE_HIGH: u1, + GPIO1_LEVEL_LOW: u1, + GPIO1_LEVEL_HIGH: u1, + GPIO1_EDGE_LOW: u1, + GPIO1_EDGE_HIGH: u1, + GPIO2_LEVEL_LOW: u1, + GPIO2_LEVEL_HIGH: u1, + GPIO2_EDGE_LOW: u1, + GPIO2_EDGE_HIGH: u1, + GPIO3_LEVEL_LOW: u1, + GPIO3_LEVEL_HIGH: u1, + GPIO3_EDGE_LOW: u1, + GPIO3_EDGE_HIGH: u1, + GPIO4_LEVEL_LOW: u1, + GPIO4_LEVEL_HIGH: u1, + GPIO4_EDGE_LOW: u1, + GPIO4_EDGE_HIGH: u1, + GPIO5_LEVEL_LOW: u1, + GPIO5_LEVEL_HIGH: u1, + GPIO5_EDGE_LOW: u1, + GPIO5_EDGE_HIGH: u1, + GPIO6_LEVEL_LOW: u1, + GPIO6_LEVEL_HIGH: u1, + GPIO6_EDGE_LOW: u1, + GPIO6_EDGE_HIGH: u1, + GPIO7_LEVEL_LOW: u1, + GPIO7_LEVEL_HIGH: u1, + GPIO7_EDGE_LOW: u1, + GPIO7_EDGE_HIGH: u1, + }), + /// Interrupt status after masking & forcing for proc0 + PROC0_INTS1: mmio.Mmio(packed struct(u32) { + GPIO8_LEVEL_LOW: u1, + GPIO8_LEVEL_HIGH: u1, + GPIO8_EDGE_LOW: u1, + GPIO8_EDGE_HIGH: u1, + GPIO9_LEVEL_LOW: u1, + GPIO9_LEVEL_HIGH: u1, + GPIO9_EDGE_LOW: u1, + GPIO9_EDGE_HIGH: u1, + GPIO10_LEVEL_LOW: u1, + GPIO10_LEVEL_HIGH: u1, + GPIO10_EDGE_LOW: u1, + GPIO10_EDGE_HIGH: u1, + GPIO11_LEVEL_LOW: u1, + GPIO11_LEVEL_HIGH: u1, + GPIO11_EDGE_LOW: u1, + GPIO11_EDGE_HIGH: u1, + GPIO12_LEVEL_LOW: u1, + GPIO12_LEVEL_HIGH: u1, + GPIO12_EDGE_LOW: u1, + GPIO12_EDGE_HIGH: u1, + GPIO13_LEVEL_LOW: u1, + GPIO13_LEVEL_HIGH: u1, + GPIO13_EDGE_LOW: u1, + GPIO13_EDGE_HIGH: u1, + GPIO14_LEVEL_LOW: u1, + GPIO14_LEVEL_HIGH: u1, + GPIO14_EDGE_LOW: u1, + GPIO14_EDGE_HIGH: u1, + GPIO15_LEVEL_LOW: u1, + GPIO15_LEVEL_HIGH: u1, + GPIO15_EDGE_LOW: u1, + GPIO15_EDGE_HIGH: u1, + }), + /// Interrupt status after masking & forcing for proc0 + PROC0_INTS2: mmio.Mmio(packed struct(u32) { + GPIO16_LEVEL_LOW: u1, + GPIO16_LEVEL_HIGH: u1, + GPIO16_EDGE_LOW: u1, + GPIO16_EDGE_HIGH: u1, + GPIO17_LEVEL_LOW: u1, + GPIO17_LEVEL_HIGH: u1, + GPIO17_EDGE_LOW: u1, + GPIO17_EDGE_HIGH: u1, + GPIO18_LEVEL_LOW: u1, + GPIO18_LEVEL_HIGH: u1, + GPIO18_EDGE_LOW: u1, + GPIO18_EDGE_HIGH: u1, + GPIO19_LEVEL_LOW: u1, + GPIO19_LEVEL_HIGH: u1, + GPIO19_EDGE_LOW: u1, + GPIO19_EDGE_HIGH: u1, + GPIO20_LEVEL_LOW: u1, + GPIO20_LEVEL_HIGH: u1, + GPIO20_EDGE_LOW: u1, + GPIO20_EDGE_HIGH: u1, + GPIO21_LEVEL_LOW: u1, + GPIO21_LEVEL_HIGH: u1, + GPIO21_EDGE_LOW: u1, + GPIO21_EDGE_HIGH: u1, + GPIO22_LEVEL_LOW: u1, + GPIO22_LEVEL_HIGH: u1, + GPIO22_EDGE_LOW: u1, + GPIO22_EDGE_HIGH: u1, + GPIO23_LEVEL_LOW: u1, + GPIO23_LEVEL_HIGH: u1, + GPIO23_EDGE_LOW: u1, + GPIO23_EDGE_HIGH: u1, + }), + /// Interrupt status after masking & forcing for proc0 + PROC0_INTS3: mmio.Mmio(packed struct(u32) { + GPIO24_LEVEL_LOW: u1, + GPIO24_LEVEL_HIGH: u1, + GPIO24_EDGE_LOW: u1, + GPIO24_EDGE_HIGH: u1, + GPIO25_LEVEL_LOW: u1, + GPIO25_LEVEL_HIGH: u1, + GPIO25_EDGE_LOW: u1, + GPIO25_EDGE_HIGH: u1, + GPIO26_LEVEL_LOW: u1, + GPIO26_LEVEL_HIGH: u1, + GPIO26_EDGE_LOW: u1, + GPIO26_EDGE_HIGH: u1, + GPIO27_LEVEL_LOW: u1, + GPIO27_LEVEL_HIGH: u1, + GPIO27_EDGE_LOW: u1, + GPIO27_EDGE_HIGH: u1, + GPIO28_LEVEL_LOW: u1, + GPIO28_LEVEL_HIGH: u1, + GPIO28_EDGE_LOW: u1, + GPIO28_EDGE_HIGH: u1, + GPIO29_LEVEL_LOW: u1, + GPIO29_LEVEL_HIGH: u1, + GPIO29_EDGE_LOW: u1, + GPIO29_EDGE_HIGH: u1, + padding: u8, + }), + /// Interrupt Enable for proc1 + PROC1_INTE0: mmio.Mmio(packed struct(u32) { + GPIO0_LEVEL_LOW: u1, + GPIO0_LEVEL_HIGH: u1, + GPIO0_EDGE_LOW: u1, + GPIO0_EDGE_HIGH: u1, + GPIO1_LEVEL_LOW: u1, + GPIO1_LEVEL_HIGH: u1, + GPIO1_EDGE_LOW: u1, + GPIO1_EDGE_HIGH: u1, + GPIO2_LEVEL_LOW: u1, + GPIO2_LEVEL_HIGH: u1, + GPIO2_EDGE_LOW: u1, + GPIO2_EDGE_HIGH: u1, + GPIO3_LEVEL_LOW: u1, + GPIO3_LEVEL_HIGH: u1, + GPIO3_EDGE_LOW: u1, + GPIO3_EDGE_HIGH: u1, + GPIO4_LEVEL_LOW: u1, + GPIO4_LEVEL_HIGH: u1, + GPIO4_EDGE_LOW: u1, + GPIO4_EDGE_HIGH: u1, + GPIO5_LEVEL_LOW: u1, + GPIO5_LEVEL_HIGH: u1, + GPIO5_EDGE_LOW: u1, + GPIO5_EDGE_HIGH: u1, + GPIO6_LEVEL_LOW: u1, + GPIO6_LEVEL_HIGH: u1, + GPIO6_EDGE_LOW: u1, + GPIO6_EDGE_HIGH: u1, + GPIO7_LEVEL_LOW: u1, + GPIO7_LEVEL_HIGH: u1, + GPIO7_EDGE_LOW: u1, + GPIO7_EDGE_HIGH: u1, + }), + /// Interrupt Enable for proc1 + PROC1_INTE1: mmio.Mmio(packed struct(u32) { + GPIO8_LEVEL_LOW: u1, + GPIO8_LEVEL_HIGH: u1, + GPIO8_EDGE_LOW: u1, + GPIO8_EDGE_HIGH: u1, + GPIO9_LEVEL_LOW: u1, + GPIO9_LEVEL_HIGH: u1, + GPIO9_EDGE_LOW: u1, + GPIO9_EDGE_HIGH: u1, + GPIO10_LEVEL_LOW: u1, + GPIO10_LEVEL_HIGH: u1, + GPIO10_EDGE_LOW: u1, + GPIO10_EDGE_HIGH: u1, + GPIO11_LEVEL_LOW: u1, + GPIO11_LEVEL_HIGH: u1, + GPIO11_EDGE_LOW: u1, + GPIO11_EDGE_HIGH: u1, + GPIO12_LEVEL_LOW: u1, + GPIO12_LEVEL_HIGH: u1, + GPIO12_EDGE_LOW: u1, + GPIO12_EDGE_HIGH: u1, + GPIO13_LEVEL_LOW: u1, + GPIO13_LEVEL_HIGH: u1, + GPIO13_EDGE_LOW: u1, + GPIO13_EDGE_HIGH: u1, + GPIO14_LEVEL_LOW: u1, + GPIO14_LEVEL_HIGH: u1, + GPIO14_EDGE_LOW: u1, + GPIO14_EDGE_HIGH: u1, + GPIO15_LEVEL_LOW: u1, + GPIO15_LEVEL_HIGH: u1, + GPIO15_EDGE_LOW: u1, + GPIO15_EDGE_HIGH: u1, + }), + /// Interrupt Enable for proc1 + PROC1_INTE2: mmio.Mmio(packed struct(u32) { + GPIO16_LEVEL_LOW: u1, + GPIO16_LEVEL_HIGH: u1, + GPIO16_EDGE_LOW: u1, + GPIO16_EDGE_HIGH: u1, + GPIO17_LEVEL_LOW: u1, + GPIO17_LEVEL_HIGH: u1, + GPIO17_EDGE_LOW: u1, + GPIO17_EDGE_HIGH: u1, + GPIO18_LEVEL_LOW: u1, + GPIO18_LEVEL_HIGH: u1, + GPIO18_EDGE_LOW: u1, + GPIO18_EDGE_HIGH: u1, + GPIO19_LEVEL_LOW: u1, + GPIO19_LEVEL_HIGH: u1, + GPIO19_EDGE_LOW: u1, + GPIO19_EDGE_HIGH: u1, + GPIO20_LEVEL_LOW: u1, + GPIO20_LEVEL_HIGH: u1, + GPIO20_EDGE_LOW: u1, + GPIO20_EDGE_HIGH: u1, + GPIO21_LEVEL_LOW: u1, + GPIO21_LEVEL_HIGH: u1, + GPIO21_EDGE_LOW: u1, + GPIO21_EDGE_HIGH: u1, + GPIO22_LEVEL_LOW: u1, + GPIO22_LEVEL_HIGH: u1, + GPIO22_EDGE_LOW: u1, + GPIO22_EDGE_HIGH: u1, + GPIO23_LEVEL_LOW: u1, + GPIO23_LEVEL_HIGH: u1, + GPIO23_EDGE_LOW: u1, + GPIO23_EDGE_HIGH: u1, + }), + /// Interrupt Enable for proc1 + PROC1_INTE3: mmio.Mmio(packed struct(u32) { + GPIO24_LEVEL_LOW: u1, + GPIO24_LEVEL_HIGH: u1, + GPIO24_EDGE_LOW: u1, + GPIO24_EDGE_HIGH: u1, + GPIO25_LEVEL_LOW: u1, + GPIO25_LEVEL_HIGH: u1, + GPIO25_EDGE_LOW: u1, + GPIO25_EDGE_HIGH: u1, + GPIO26_LEVEL_LOW: u1, + GPIO26_LEVEL_HIGH: u1, + GPIO26_EDGE_LOW: u1, + GPIO26_EDGE_HIGH: u1, + GPIO27_LEVEL_LOW: u1, + GPIO27_LEVEL_HIGH: u1, + GPIO27_EDGE_LOW: u1, + GPIO27_EDGE_HIGH: u1, + GPIO28_LEVEL_LOW: u1, + GPIO28_LEVEL_HIGH: u1, + GPIO28_EDGE_LOW: u1, + GPIO28_EDGE_HIGH: u1, + GPIO29_LEVEL_LOW: u1, + GPIO29_LEVEL_HIGH: u1, + GPIO29_EDGE_LOW: u1, + GPIO29_EDGE_HIGH: u1, + padding: u8, + }), + /// Interrupt Force for proc1 + PROC1_INTF0: mmio.Mmio(packed struct(u32) { + GPIO0_LEVEL_LOW: u1, + GPIO0_LEVEL_HIGH: u1, + GPIO0_EDGE_LOW: u1, + GPIO0_EDGE_HIGH: u1, + GPIO1_LEVEL_LOW: u1, + GPIO1_LEVEL_HIGH: u1, + GPIO1_EDGE_LOW: u1, + GPIO1_EDGE_HIGH: u1, + GPIO2_LEVEL_LOW: u1, + GPIO2_LEVEL_HIGH: u1, + GPIO2_EDGE_LOW: u1, + GPIO2_EDGE_HIGH: u1, + GPIO3_LEVEL_LOW: u1, + GPIO3_LEVEL_HIGH: u1, + GPIO3_EDGE_LOW: u1, + GPIO3_EDGE_HIGH: u1, + GPIO4_LEVEL_LOW: u1, + GPIO4_LEVEL_HIGH: u1, + GPIO4_EDGE_LOW: u1, + GPIO4_EDGE_HIGH: u1, + GPIO5_LEVEL_LOW: u1, + GPIO5_LEVEL_HIGH: u1, + GPIO5_EDGE_LOW: u1, + GPIO5_EDGE_HIGH: u1, + GPIO6_LEVEL_LOW: u1, + GPIO6_LEVEL_HIGH: u1, + GPIO6_EDGE_LOW: u1, + GPIO6_EDGE_HIGH: u1, + GPIO7_LEVEL_LOW: u1, + GPIO7_LEVEL_HIGH: u1, + GPIO7_EDGE_LOW: u1, + GPIO7_EDGE_HIGH: u1, + }), + /// Interrupt Force for proc1 + PROC1_INTF1: mmio.Mmio(packed struct(u32) { + GPIO8_LEVEL_LOW: u1, + GPIO8_LEVEL_HIGH: u1, + GPIO8_EDGE_LOW: u1, + GPIO8_EDGE_HIGH: u1, + GPIO9_LEVEL_LOW: u1, + GPIO9_LEVEL_HIGH: u1, + GPIO9_EDGE_LOW: u1, + GPIO9_EDGE_HIGH: u1, + GPIO10_LEVEL_LOW: u1, + GPIO10_LEVEL_HIGH: u1, + GPIO10_EDGE_LOW: u1, + GPIO10_EDGE_HIGH: u1, + GPIO11_LEVEL_LOW: u1, + GPIO11_LEVEL_HIGH: u1, + GPIO11_EDGE_LOW: u1, + GPIO11_EDGE_HIGH: u1, + GPIO12_LEVEL_LOW: u1, + GPIO12_LEVEL_HIGH: u1, + GPIO12_EDGE_LOW: u1, + GPIO12_EDGE_HIGH: u1, + GPIO13_LEVEL_LOW: u1, + GPIO13_LEVEL_HIGH: u1, + GPIO13_EDGE_LOW: u1, + GPIO13_EDGE_HIGH: u1, + GPIO14_LEVEL_LOW: u1, + GPIO14_LEVEL_HIGH: u1, + GPIO14_EDGE_LOW: u1, + GPIO14_EDGE_HIGH: u1, + GPIO15_LEVEL_LOW: u1, + GPIO15_LEVEL_HIGH: u1, + GPIO15_EDGE_LOW: u1, + GPIO15_EDGE_HIGH: u1, + }), + /// Interrupt Force for proc1 + PROC1_INTF2: mmio.Mmio(packed struct(u32) { + GPIO16_LEVEL_LOW: u1, + GPIO16_LEVEL_HIGH: u1, + GPIO16_EDGE_LOW: u1, + GPIO16_EDGE_HIGH: u1, + GPIO17_LEVEL_LOW: u1, + GPIO17_LEVEL_HIGH: u1, + GPIO17_EDGE_LOW: u1, + GPIO17_EDGE_HIGH: u1, + GPIO18_LEVEL_LOW: u1, + GPIO18_LEVEL_HIGH: u1, + GPIO18_EDGE_LOW: u1, + GPIO18_EDGE_HIGH: u1, + GPIO19_LEVEL_LOW: u1, + GPIO19_LEVEL_HIGH: u1, + GPIO19_EDGE_LOW: u1, + GPIO19_EDGE_HIGH: u1, + GPIO20_LEVEL_LOW: u1, + GPIO20_LEVEL_HIGH: u1, + GPIO20_EDGE_LOW: u1, + GPIO20_EDGE_HIGH: u1, + GPIO21_LEVEL_LOW: u1, + GPIO21_LEVEL_HIGH: u1, + GPIO21_EDGE_LOW: u1, + GPIO21_EDGE_HIGH: u1, + GPIO22_LEVEL_LOW: u1, + GPIO22_LEVEL_HIGH: u1, + GPIO22_EDGE_LOW: u1, + GPIO22_EDGE_HIGH: u1, + GPIO23_LEVEL_LOW: u1, + GPIO23_LEVEL_HIGH: u1, + GPIO23_EDGE_LOW: u1, + GPIO23_EDGE_HIGH: u1, + }), + /// Interrupt Force for proc1 + PROC1_INTF3: mmio.Mmio(packed struct(u32) { + GPIO24_LEVEL_LOW: u1, + GPIO24_LEVEL_HIGH: u1, + GPIO24_EDGE_LOW: u1, + GPIO24_EDGE_HIGH: u1, + GPIO25_LEVEL_LOW: u1, + GPIO25_LEVEL_HIGH: u1, + GPIO25_EDGE_LOW: u1, + GPIO25_EDGE_HIGH: u1, + GPIO26_LEVEL_LOW: u1, + GPIO26_LEVEL_HIGH: u1, + GPIO26_EDGE_LOW: u1, + GPIO26_EDGE_HIGH: u1, + GPIO27_LEVEL_LOW: u1, + GPIO27_LEVEL_HIGH: u1, + GPIO27_EDGE_LOW: u1, + GPIO27_EDGE_HIGH: u1, + GPIO28_LEVEL_LOW: u1, + GPIO28_LEVEL_HIGH: u1, + GPIO28_EDGE_LOW: u1, + GPIO28_EDGE_HIGH: u1, + GPIO29_LEVEL_LOW: u1, + GPIO29_LEVEL_HIGH: u1, + GPIO29_EDGE_LOW: u1, + GPIO29_EDGE_HIGH: u1, + padding: u8, + }), + /// Interrupt status after masking & forcing for proc1 + PROC1_INTS0: mmio.Mmio(packed struct(u32) { + GPIO0_LEVEL_LOW: u1, + GPIO0_LEVEL_HIGH: u1, + GPIO0_EDGE_LOW: u1, + GPIO0_EDGE_HIGH: u1, + GPIO1_LEVEL_LOW: u1, + GPIO1_LEVEL_HIGH: u1, + GPIO1_EDGE_LOW: u1, + GPIO1_EDGE_HIGH: u1, + GPIO2_LEVEL_LOW: u1, + GPIO2_LEVEL_HIGH: u1, + GPIO2_EDGE_LOW: u1, + GPIO2_EDGE_HIGH: u1, + GPIO3_LEVEL_LOW: u1, + GPIO3_LEVEL_HIGH: u1, + GPIO3_EDGE_LOW: u1, + GPIO3_EDGE_HIGH: u1, + GPIO4_LEVEL_LOW: u1, + GPIO4_LEVEL_HIGH: u1, + GPIO4_EDGE_LOW: u1, + GPIO4_EDGE_HIGH: u1, + GPIO5_LEVEL_LOW: u1, + GPIO5_LEVEL_HIGH: u1, + GPIO5_EDGE_LOW: u1, + GPIO5_EDGE_HIGH: u1, + GPIO6_LEVEL_LOW: u1, + GPIO6_LEVEL_HIGH: u1, + GPIO6_EDGE_LOW: u1, + GPIO6_EDGE_HIGH: u1, + GPIO7_LEVEL_LOW: u1, + GPIO7_LEVEL_HIGH: u1, + GPIO7_EDGE_LOW: u1, + GPIO7_EDGE_HIGH: u1, + }), + /// Interrupt status after masking & forcing for proc1 + PROC1_INTS1: mmio.Mmio(packed struct(u32) { + GPIO8_LEVEL_LOW: u1, + GPIO8_LEVEL_HIGH: u1, + GPIO8_EDGE_LOW: u1, + GPIO8_EDGE_HIGH: u1, + GPIO9_LEVEL_LOW: u1, + GPIO9_LEVEL_HIGH: u1, + GPIO9_EDGE_LOW: u1, + GPIO9_EDGE_HIGH: u1, + GPIO10_LEVEL_LOW: u1, + GPIO10_LEVEL_HIGH: u1, + GPIO10_EDGE_LOW: u1, + GPIO10_EDGE_HIGH: u1, + GPIO11_LEVEL_LOW: u1, + GPIO11_LEVEL_HIGH: u1, + GPIO11_EDGE_LOW: u1, + GPIO11_EDGE_HIGH: u1, + GPIO12_LEVEL_LOW: u1, + GPIO12_LEVEL_HIGH: u1, + GPIO12_EDGE_LOW: u1, + GPIO12_EDGE_HIGH: u1, + GPIO13_LEVEL_LOW: u1, + GPIO13_LEVEL_HIGH: u1, + GPIO13_EDGE_LOW: u1, + GPIO13_EDGE_HIGH: u1, + GPIO14_LEVEL_LOW: u1, + GPIO14_LEVEL_HIGH: u1, + GPIO14_EDGE_LOW: u1, + GPIO14_EDGE_HIGH: u1, + GPIO15_LEVEL_LOW: u1, + GPIO15_LEVEL_HIGH: u1, + GPIO15_EDGE_LOW: u1, + GPIO15_EDGE_HIGH: u1, + }), + /// Interrupt status after masking & forcing for proc1 + PROC1_INTS2: mmio.Mmio(packed struct(u32) { + GPIO16_LEVEL_LOW: u1, + GPIO16_LEVEL_HIGH: u1, + GPIO16_EDGE_LOW: u1, + GPIO16_EDGE_HIGH: u1, + GPIO17_LEVEL_LOW: u1, + GPIO17_LEVEL_HIGH: u1, + GPIO17_EDGE_LOW: u1, + GPIO17_EDGE_HIGH: u1, + GPIO18_LEVEL_LOW: u1, + GPIO18_LEVEL_HIGH: u1, + GPIO18_EDGE_LOW: u1, + GPIO18_EDGE_HIGH: u1, + GPIO19_LEVEL_LOW: u1, + GPIO19_LEVEL_HIGH: u1, + GPIO19_EDGE_LOW: u1, + GPIO19_EDGE_HIGH: u1, + GPIO20_LEVEL_LOW: u1, + GPIO20_LEVEL_HIGH: u1, + GPIO20_EDGE_LOW: u1, + GPIO20_EDGE_HIGH: u1, + GPIO21_LEVEL_LOW: u1, + GPIO21_LEVEL_HIGH: u1, + GPIO21_EDGE_LOW: u1, + GPIO21_EDGE_HIGH: u1, + GPIO22_LEVEL_LOW: u1, + GPIO22_LEVEL_HIGH: u1, + GPIO22_EDGE_LOW: u1, + GPIO22_EDGE_HIGH: u1, + GPIO23_LEVEL_LOW: u1, + GPIO23_LEVEL_HIGH: u1, + GPIO23_EDGE_LOW: u1, + GPIO23_EDGE_HIGH: u1, + }), + /// Interrupt status after masking & forcing for proc1 + PROC1_INTS3: mmio.Mmio(packed struct(u32) { + GPIO24_LEVEL_LOW: u1, + GPIO24_LEVEL_HIGH: u1, + GPIO24_EDGE_LOW: u1, + GPIO24_EDGE_HIGH: u1, + GPIO25_LEVEL_LOW: u1, + GPIO25_LEVEL_HIGH: u1, + GPIO25_EDGE_LOW: u1, + GPIO25_EDGE_HIGH: u1, + GPIO26_LEVEL_LOW: u1, + GPIO26_LEVEL_HIGH: u1, + GPIO26_EDGE_LOW: u1, + GPIO26_EDGE_HIGH: u1, + GPIO27_LEVEL_LOW: u1, + GPIO27_LEVEL_HIGH: u1, + GPIO27_EDGE_LOW: u1, + GPIO27_EDGE_HIGH: u1, + GPIO28_LEVEL_LOW: u1, + GPIO28_LEVEL_HIGH: u1, + GPIO28_EDGE_LOW: u1, + GPIO28_EDGE_HIGH: u1, + GPIO29_LEVEL_LOW: u1, + GPIO29_LEVEL_HIGH: u1, + GPIO29_EDGE_LOW: u1, + GPIO29_EDGE_HIGH: u1, + padding: u8, + }), + /// Interrupt Enable for dormant_wake + DORMANT_WAKE_INTE0: mmio.Mmio(packed struct(u32) { + GPIO0_LEVEL_LOW: u1, + GPIO0_LEVEL_HIGH: u1, + GPIO0_EDGE_LOW: u1, + GPIO0_EDGE_HIGH: u1, + GPIO1_LEVEL_LOW: u1, + GPIO1_LEVEL_HIGH: u1, + GPIO1_EDGE_LOW: u1, + GPIO1_EDGE_HIGH: u1, + GPIO2_LEVEL_LOW: u1, + GPIO2_LEVEL_HIGH: u1, + GPIO2_EDGE_LOW: u1, + GPIO2_EDGE_HIGH: u1, + GPIO3_LEVEL_LOW: u1, + GPIO3_LEVEL_HIGH: u1, + GPIO3_EDGE_LOW: u1, + GPIO3_EDGE_HIGH: u1, + GPIO4_LEVEL_LOW: u1, + GPIO4_LEVEL_HIGH: u1, + GPIO4_EDGE_LOW: u1, + GPIO4_EDGE_HIGH: u1, + GPIO5_LEVEL_LOW: u1, + GPIO5_LEVEL_HIGH: u1, + GPIO5_EDGE_LOW: u1, + GPIO5_EDGE_HIGH: u1, + GPIO6_LEVEL_LOW: u1, + GPIO6_LEVEL_HIGH: u1, + GPIO6_EDGE_LOW: u1, + GPIO6_EDGE_HIGH: u1, + GPIO7_LEVEL_LOW: u1, + GPIO7_LEVEL_HIGH: u1, + GPIO7_EDGE_LOW: u1, + GPIO7_EDGE_HIGH: u1, + }), + /// Interrupt Enable for dormant_wake + DORMANT_WAKE_INTE1: mmio.Mmio(packed struct(u32) { + GPIO8_LEVEL_LOW: u1, + GPIO8_LEVEL_HIGH: u1, + GPIO8_EDGE_LOW: u1, + GPIO8_EDGE_HIGH: u1, + GPIO9_LEVEL_LOW: u1, + GPIO9_LEVEL_HIGH: u1, + GPIO9_EDGE_LOW: u1, + GPIO9_EDGE_HIGH: u1, + GPIO10_LEVEL_LOW: u1, + GPIO10_LEVEL_HIGH: u1, + GPIO10_EDGE_LOW: u1, + GPIO10_EDGE_HIGH: u1, + GPIO11_LEVEL_LOW: u1, + GPIO11_LEVEL_HIGH: u1, + GPIO11_EDGE_LOW: u1, + GPIO11_EDGE_HIGH: u1, + GPIO12_LEVEL_LOW: u1, + GPIO12_LEVEL_HIGH: u1, + GPIO12_EDGE_LOW: u1, + GPIO12_EDGE_HIGH: u1, + GPIO13_LEVEL_LOW: u1, + GPIO13_LEVEL_HIGH: u1, + GPIO13_EDGE_LOW: u1, + GPIO13_EDGE_HIGH: u1, + GPIO14_LEVEL_LOW: u1, + GPIO14_LEVEL_HIGH: u1, + GPIO14_EDGE_LOW: u1, + GPIO14_EDGE_HIGH: u1, + GPIO15_LEVEL_LOW: u1, + GPIO15_LEVEL_HIGH: u1, + GPIO15_EDGE_LOW: u1, + GPIO15_EDGE_HIGH: u1, + }), + /// Interrupt Enable for dormant_wake + DORMANT_WAKE_INTE2: mmio.Mmio(packed struct(u32) { + GPIO16_LEVEL_LOW: u1, + GPIO16_LEVEL_HIGH: u1, + GPIO16_EDGE_LOW: u1, + GPIO16_EDGE_HIGH: u1, + GPIO17_LEVEL_LOW: u1, + GPIO17_LEVEL_HIGH: u1, + GPIO17_EDGE_LOW: u1, + GPIO17_EDGE_HIGH: u1, + GPIO18_LEVEL_LOW: u1, + GPIO18_LEVEL_HIGH: u1, + GPIO18_EDGE_LOW: u1, + GPIO18_EDGE_HIGH: u1, + GPIO19_LEVEL_LOW: u1, + GPIO19_LEVEL_HIGH: u1, + GPIO19_EDGE_LOW: u1, + GPIO19_EDGE_HIGH: u1, + GPIO20_LEVEL_LOW: u1, + GPIO20_LEVEL_HIGH: u1, + GPIO20_EDGE_LOW: u1, + GPIO20_EDGE_HIGH: u1, + GPIO21_LEVEL_LOW: u1, + GPIO21_LEVEL_HIGH: u1, + GPIO21_EDGE_LOW: u1, + GPIO21_EDGE_HIGH: u1, + GPIO22_LEVEL_LOW: u1, + GPIO22_LEVEL_HIGH: u1, + GPIO22_EDGE_LOW: u1, + GPIO22_EDGE_HIGH: u1, + GPIO23_LEVEL_LOW: u1, + GPIO23_LEVEL_HIGH: u1, + GPIO23_EDGE_LOW: u1, + GPIO23_EDGE_HIGH: u1, + }), + /// Interrupt Enable for dormant_wake + DORMANT_WAKE_INTE3: mmio.Mmio(packed struct(u32) { + GPIO24_LEVEL_LOW: u1, + GPIO24_LEVEL_HIGH: u1, + GPIO24_EDGE_LOW: u1, + GPIO24_EDGE_HIGH: u1, + GPIO25_LEVEL_LOW: u1, + GPIO25_LEVEL_HIGH: u1, + GPIO25_EDGE_LOW: u1, + GPIO25_EDGE_HIGH: u1, + GPIO26_LEVEL_LOW: u1, + GPIO26_LEVEL_HIGH: u1, + GPIO26_EDGE_LOW: u1, + GPIO26_EDGE_HIGH: u1, + GPIO27_LEVEL_LOW: u1, + GPIO27_LEVEL_HIGH: u1, + GPIO27_EDGE_LOW: u1, + GPIO27_EDGE_HIGH: u1, + GPIO28_LEVEL_LOW: u1, + GPIO28_LEVEL_HIGH: u1, + GPIO28_EDGE_LOW: u1, + GPIO28_EDGE_HIGH: u1, + GPIO29_LEVEL_LOW: u1, + GPIO29_LEVEL_HIGH: u1, + GPIO29_EDGE_LOW: u1, + GPIO29_EDGE_HIGH: u1, + padding: u8, + }), + /// Interrupt Force for dormant_wake + DORMANT_WAKE_INTF0: mmio.Mmio(packed struct(u32) { + GPIO0_LEVEL_LOW: u1, + GPIO0_LEVEL_HIGH: u1, + GPIO0_EDGE_LOW: u1, + GPIO0_EDGE_HIGH: u1, + GPIO1_LEVEL_LOW: u1, + GPIO1_LEVEL_HIGH: u1, + GPIO1_EDGE_LOW: u1, + GPIO1_EDGE_HIGH: u1, + GPIO2_LEVEL_LOW: u1, + GPIO2_LEVEL_HIGH: u1, + GPIO2_EDGE_LOW: u1, + GPIO2_EDGE_HIGH: u1, + GPIO3_LEVEL_LOW: u1, + GPIO3_LEVEL_HIGH: u1, + GPIO3_EDGE_LOW: u1, + GPIO3_EDGE_HIGH: u1, + GPIO4_LEVEL_LOW: u1, + GPIO4_LEVEL_HIGH: u1, + GPIO4_EDGE_LOW: u1, + GPIO4_EDGE_HIGH: u1, + GPIO5_LEVEL_LOW: u1, + GPIO5_LEVEL_HIGH: u1, + GPIO5_EDGE_LOW: u1, + GPIO5_EDGE_HIGH: u1, + GPIO6_LEVEL_LOW: u1, + GPIO6_LEVEL_HIGH: u1, + GPIO6_EDGE_LOW: u1, + GPIO6_EDGE_HIGH: u1, + GPIO7_LEVEL_LOW: u1, + GPIO7_LEVEL_HIGH: u1, + GPIO7_EDGE_LOW: u1, + GPIO7_EDGE_HIGH: u1, + }), + /// Interrupt Force for dormant_wake + DORMANT_WAKE_INTF1: mmio.Mmio(packed struct(u32) { + GPIO8_LEVEL_LOW: u1, + GPIO8_LEVEL_HIGH: u1, + GPIO8_EDGE_LOW: u1, + GPIO8_EDGE_HIGH: u1, + GPIO9_LEVEL_LOW: u1, + GPIO9_LEVEL_HIGH: u1, + GPIO9_EDGE_LOW: u1, + GPIO9_EDGE_HIGH: u1, + GPIO10_LEVEL_LOW: u1, + GPIO10_LEVEL_HIGH: u1, + GPIO10_EDGE_LOW: u1, + GPIO10_EDGE_HIGH: u1, + GPIO11_LEVEL_LOW: u1, + GPIO11_LEVEL_HIGH: u1, + GPIO11_EDGE_LOW: u1, + GPIO11_EDGE_HIGH: u1, + GPIO12_LEVEL_LOW: u1, + GPIO12_LEVEL_HIGH: u1, + GPIO12_EDGE_LOW: u1, + GPIO12_EDGE_HIGH: u1, + GPIO13_LEVEL_LOW: u1, + GPIO13_LEVEL_HIGH: u1, + GPIO13_EDGE_LOW: u1, + GPIO13_EDGE_HIGH: u1, + GPIO14_LEVEL_LOW: u1, + GPIO14_LEVEL_HIGH: u1, + GPIO14_EDGE_LOW: u1, + GPIO14_EDGE_HIGH: u1, + GPIO15_LEVEL_LOW: u1, + GPIO15_LEVEL_HIGH: u1, + GPIO15_EDGE_LOW: u1, + GPIO15_EDGE_HIGH: u1, + }), + /// Interrupt Force for dormant_wake + DORMANT_WAKE_INTF2: mmio.Mmio(packed struct(u32) { + GPIO16_LEVEL_LOW: u1, + GPIO16_LEVEL_HIGH: u1, + GPIO16_EDGE_LOW: u1, + GPIO16_EDGE_HIGH: u1, + GPIO17_LEVEL_LOW: u1, + GPIO17_LEVEL_HIGH: u1, + GPIO17_EDGE_LOW: u1, + GPIO17_EDGE_HIGH: u1, + GPIO18_LEVEL_LOW: u1, + GPIO18_LEVEL_HIGH: u1, + GPIO18_EDGE_LOW: u1, + GPIO18_EDGE_HIGH: u1, + GPIO19_LEVEL_LOW: u1, + GPIO19_LEVEL_HIGH: u1, + GPIO19_EDGE_LOW: u1, + GPIO19_EDGE_HIGH: u1, + GPIO20_LEVEL_LOW: u1, + GPIO20_LEVEL_HIGH: u1, + GPIO20_EDGE_LOW: u1, + GPIO20_EDGE_HIGH: u1, + GPIO21_LEVEL_LOW: u1, + GPIO21_LEVEL_HIGH: u1, + GPIO21_EDGE_LOW: u1, + GPIO21_EDGE_HIGH: u1, + GPIO22_LEVEL_LOW: u1, + GPIO22_LEVEL_HIGH: u1, + GPIO22_EDGE_LOW: u1, + GPIO22_EDGE_HIGH: u1, + GPIO23_LEVEL_LOW: u1, + GPIO23_LEVEL_HIGH: u1, + GPIO23_EDGE_LOW: u1, + GPIO23_EDGE_HIGH: u1, + }), + /// Interrupt Force for dormant_wake + DORMANT_WAKE_INTF3: mmio.Mmio(packed struct(u32) { + GPIO24_LEVEL_LOW: u1, + GPIO24_LEVEL_HIGH: u1, + GPIO24_EDGE_LOW: u1, + GPIO24_EDGE_HIGH: u1, + GPIO25_LEVEL_LOW: u1, + GPIO25_LEVEL_HIGH: u1, + GPIO25_EDGE_LOW: u1, + GPIO25_EDGE_HIGH: u1, + GPIO26_LEVEL_LOW: u1, + GPIO26_LEVEL_HIGH: u1, + GPIO26_EDGE_LOW: u1, + GPIO26_EDGE_HIGH: u1, + GPIO27_LEVEL_LOW: u1, + GPIO27_LEVEL_HIGH: u1, + GPIO27_EDGE_LOW: u1, + GPIO27_EDGE_HIGH: u1, + GPIO28_LEVEL_LOW: u1, + GPIO28_LEVEL_HIGH: u1, + GPIO28_EDGE_LOW: u1, + GPIO28_EDGE_HIGH: u1, + GPIO29_LEVEL_LOW: u1, + GPIO29_LEVEL_HIGH: u1, + GPIO29_EDGE_LOW: u1, + GPIO29_EDGE_HIGH: u1, + padding: u8, + }), + /// Interrupt status after masking & forcing for dormant_wake + DORMANT_WAKE_INTS0: mmio.Mmio(packed struct(u32) { + GPIO0_LEVEL_LOW: u1, + GPIO0_LEVEL_HIGH: u1, + GPIO0_EDGE_LOW: u1, + GPIO0_EDGE_HIGH: u1, + GPIO1_LEVEL_LOW: u1, + GPIO1_LEVEL_HIGH: u1, + GPIO1_EDGE_LOW: u1, + GPIO1_EDGE_HIGH: u1, + GPIO2_LEVEL_LOW: u1, + GPIO2_LEVEL_HIGH: u1, + GPIO2_EDGE_LOW: u1, + GPIO2_EDGE_HIGH: u1, + GPIO3_LEVEL_LOW: u1, + GPIO3_LEVEL_HIGH: u1, + GPIO3_EDGE_LOW: u1, + GPIO3_EDGE_HIGH: u1, + GPIO4_LEVEL_LOW: u1, + GPIO4_LEVEL_HIGH: u1, + GPIO4_EDGE_LOW: u1, + GPIO4_EDGE_HIGH: u1, + GPIO5_LEVEL_LOW: u1, + GPIO5_LEVEL_HIGH: u1, + GPIO5_EDGE_LOW: u1, + GPIO5_EDGE_HIGH: u1, + GPIO6_LEVEL_LOW: u1, + GPIO6_LEVEL_HIGH: u1, + GPIO6_EDGE_LOW: u1, + GPIO6_EDGE_HIGH: u1, + GPIO7_LEVEL_LOW: u1, + GPIO7_LEVEL_HIGH: u1, + GPIO7_EDGE_LOW: u1, + GPIO7_EDGE_HIGH: u1, + }), + /// Interrupt status after masking & forcing for dormant_wake + DORMANT_WAKE_INTS1: mmio.Mmio(packed struct(u32) { + GPIO8_LEVEL_LOW: u1, + GPIO8_LEVEL_HIGH: u1, + GPIO8_EDGE_LOW: u1, + GPIO8_EDGE_HIGH: u1, + GPIO9_LEVEL_LOW: u1, + GPIO9_LEVEL_HIGH: u1, + GPIO9_EDGE_LOW: u1, + GPIO9_EDGE_HIGH: u1, + GPIO10_LEVEL_LOW: u1, + GPIO10_LEVEL_HIGH: u1, + GPIO10_EDGE_LOW: u1, + GPIO10_EDGE_HIGH: u1, + GPIO11_LEVEL_LOW: u1, + GPIO11_LEVEL_HIGH: u1, + GPIO11_EDGE_LOW: u1, + GPIO11_EDGE_HIGH: u1, + GPIO12_LEVEL_LOW: u1, + GPIO12_LEVEL_HIGH: u1, + GPIO12_EDGE_LOW: u1, + GPIO12_EDGE_HIGH: u1, + GPIO13_LEVEL_LOW: u1, + GPIO13_LEVEL_HIGH: u1, + GPIO13_EDGE_LOW: u1, + GPIO13_EDGE_HIGH: u1, + GPIO14_LEVEL_LOW: u1, + GPIO14_LEVEL_HIGH: u1, + GPIO14_EDGE_LOW: u1, + GPIO14_EDGE_HIGH: u1, + GPIO15_LEVEL_LOW: u1, + GPIO15_LEVEL_HIGH: u1, + GPIO15_EDGE_LOW: u1, + GPIO15_EDGE_HIGH: u1, + }), + /// Interrupt status after masking & forcing for dormant_wake + DORMANT_WAKE_INTS2: mmio.Mmio(packed struct(u32) { + GPIO16_LEVEL_LOW: u1, + GPIO16_LEVEL_HIGH: u1, + GPIO16_EDGE_LOW: u1, + GPIO16_EDGE_HIGH: u1, + GPIO17_LEVEL_LOW: u1, + GPIO17_LEVEL_HIGH: u1, + GPIO17_EDGE_LOW: u1, + GPIO17_EDGE_HIGH: u1, + GPIO18_LEVEL_LOW: u1, + GPIO18_LEVEL_HIGH: u1, + GPIO18_EDGE_LOW: u1, + GPIO18_EDGE_HIGH: u1, + GPIO19_LEVEL_LOW: u1, + GPIO19_LEVEL_HIGH: u1, + GPIO19_EDGE_LOW: u1, + GPIO19_EDGE_HIGH: u1, + GPIO20_LEVEL_LOW: u1, + GPIO20_LEVEL_HIGH: u1, + GPIO20_EDGE_LOW: u1, + GPIO20_EDGE_HIGH: u1, + GPIO21_LEVEL_LOW: u1, + GPIO21_LEVEL_HIGH: u1, + GPIO21_EDGE_LOW: u1, + GPIO21_EDGE_HIGH: u1, + GPIO22_LEVEL_LOW: u1, + GPIO22_LEVEL_HIGH: u1, + GPIO22_EDGE_LOW: u1, + GPIO22_EDGE_HIGH: u1, + GPIO23_LEVEL_LOW: u1, + GPIO23_LEVEL_HIGH: u1, + GPIO23_EDGE_LOW: u1, + GPIO23_EDGE_HIGH: u1, + }), + /// Interrupt status after masking & forcing for dormant_wake + DORMANT_WAKE_INTS3: mmio.Mmio(packed struct(u32) { + GPIO24_LEVEL_LOW: u1, + GPIO24_LEVEL_HIGH: u1, + GPIO24_EDGE_LOW: u1, + GPIO24_EDGE_HIGH: u1, + GPIO25_LEVEL_LOW: u1, + GPIO25_LEVEL_HIGH: u1, + GPIO25_EDGE_LOW: u1, + GPIO25_EDGE_HIGH: u1, + GPIO26_LEVEL_LOW: u1, + GPIO26_LEVEL_HIGH: u1, + GPIO26_EDGE_LOW: u1, + GPIO26_EDGE_HIGH: u1, + GPIO27_LEVEL_LOW: u1, + GPIO27_LEVEL_HIGH: u1, + GPIO27_EDGE_LOW: u1, + GPIO27_EDGE_HIGH: u1, + GPIO28_LEVEL_LOW: u1, + GPIO28_LEVEL_HIGH: u1, + GPIO28_EDGE_LOW: u1, + GPIO28_EDGE_HIGH: u1, + GPIO29_LEVEL_LOW: u1, + GPIO29_LEVEL_HIGH: u1, + GPIO29_EDGE_LOW: u1, + GPIO29_EDGE_HIGH: u1, + padding: u8, + }), + }; + + pub const IO_QSPI = extern struct { + /// GPIO status + GPIO_QSPI_SCLK_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO_QSPI_SCLK_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + xip_sclk = 0x0, + sio_30 = 0x5, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO_QSPI_SS_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO_QSPI_SS_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + xip_ss_n = 0x0, + sio_31 = 0x5, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO_QSPI_SD0_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO_QSPI_SD0_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + xip_sd0 = 0x0, + sio_32 = 0x5, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO_QSPI_SD1_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO_QSPI_SD1_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + xip_sd1 = 0x0, + sio_33 = 0x5, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO_QSPI_SD2_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO_QSPI_SD2_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + xip_sd2 = 0x0, + sio_34 = 0x5, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// GPIO status + GPIO_QSPI_SD3_STATUS: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// output signal from selected peripheral, before register override is applied + OUTFROMPERI: u1, + /// output signal to pad after register override is applied + OUTTOPAD: u1, + reserved12: u2, + /// output enable from selected peripheral, before register override is applied + OEFROMPERI: u1, + /// output enable to pad after register override is applied + OETOPAD: u1, + reserved17: u3, + /// input signal from pad, before override is applied + INFROMPAD: u1, + reserved19: u1, + /// input signal to peripheral, after override is applied + INTOPERI: u1, + reserved24: u4, + /// interrupt from pad before override is applied + IRQFROMPAD: u1, + reserved26: u1, + /// interrupt to processors, after override is applied + IRQTOPROC: u1, + padding: u5, + }), + /// GPIO control including function select and overrides. + GPIO_QSPI_SD3_CTRL: mmio.Mmio(packed struct(u32) { + /// 0-31 -> selects pin function according to the gpio table + /// 31 == NULL + FUNCSEL: packed union { + raw: u5, + value: enum(u5) { + xip_sd3 = 0x0, + sio_35 = 0x5, + null = 0x1f, + _, + }, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// drive output low + LOW = 0x2, + /// drive output high + HIGH = 0x3, + }, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: enum(u2) { + /// drive output enable from peripheral signal selected by funcsel + NORMAL = 0x0, + /// drive output enable from inverse of peripheral signal selected by funcsel + INVERT = 0x1, + /// disable output + DISABLE = 0x2, + /// enable output + ENABLE = 0x3, + }, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the peri input + NORMAL = 0x0, + /// invert the peri input + INVERT = 0x1, + /// drive peri input low + LOW = 0x2, + /// drive peri input high + HIGH = 0x3, + }, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: enum(u2) { + /// don't invert the interrupt + NORMAL = 0x0, + /// invert the interrupt + INVERT = 0x1, + /// drive interrupt low + LOW = 0x2, + /// drive interrupt high + HIGH = 0x3, + }, + }, + padding: u2, + }), + /// Raw Interrupts + INTR: mmio.Mmio(packed struct(u32) { + GPIO_QSPI_SCLK_LEVEL_LOW: u1, + GPIO_QSPI_SCLK_LEVEL_HIGH: u1, + GPIO_QSPI_SCLK_EDGE_LOW: u1, + GPIO_QSPI_SCLK_EDGE_HIGH: u1, + GPIO_QSPI_SS_LEVEL_LOW: u1, + GPIO_QSPI_SS_LEVEL_HIGH: u1, + GPIO_QSPI_SS_EDGE_LOW: u1, + GPIO_QSPI_SS_EDGE_HIGH: u1, + GPIO_QSPI_SD0_LEVEL_LOW: u1, + GPIO_QSPI_SD0_LEVEL_HIGH: u1, + GPIO_QSPI_SD0_EDGE_LOW: u1, + GPIO_QSPI_SD0_EDGE_HIGH: u1, + GPIO_QSPI_SD1_LEVEL_LOW: u1, + GPIO_QSPI_SD1_LEVEL_HIGH: u1, + GPIO_QSPI_SD1_EDGE_LOW: u1, + GPIO_QSPI_SD1_EDGE_HIGH: u1, + GPIO_QSPI_SD2_LEVEL_LOW: u1, + GPIO_QSPI_SD2_LEVEL_HIGH: u1, + GPIO_QSPI_SD2_EDGE_LOW: u1, + GPIO_QSPI_SD2_EDGE_HIGH: u1, + GPIO_QSPI_SD3_LEVEL_LOW: u1, + GPIO_QSPI_SD3_LEVEL_HIGH: u1, + GPIO_QSPI_SD3_EDGE_LOW: u1, + GPIO_QSPI_SD3_EDGE_HIGH: u1, + padding: u8, + }), + /// Interrupt Enable for proc0 + PROC0_INTE: mmio.Mmio(packed struct(u32) { + GPIO_QSPI_SCLK_LEVEL_LOW: u1, + GPIO_QSPI_SCLK_LEVEL_HIGH: u1, + GPIO_QSPI_SCLK_EDGE_LOW: u1, + GPIO_QSPI_SCLK_EDGE_HIGH: u1, + GPIO_QSPI_SS_LEVEL_LOW: u1, + GPIO_QSPI_SS_LEVEL_HIGH: u1, + GPIO_QSPI_SS_EDGE_LOW: u1, + GPIO_QSPI_SS_EDGE_HIGH: u1, + GPIO_QSPI_SD0_LEVEL_LOW: u1, + GPIO_QSPI_SD0_LEVEL_HIGH: u1, + GPIO_QSPI_SD0_EDGE_LOW: u1, + GPIO_QSPI_SD0_EDGE_HIGH: u1, + GPIO_QSPI_SD1_LEVEL_LOW: u1, + GPIO_QSPI_SD1_LEVEL_HIGH: u1, + GPIO_QSPI_SD1_EDGE_LOW: u1, + GPIO_QSPI_SD1_EDGE_HIGH: u1, + GPIO_QSPI_SD2_LEVEL_LOW: u1, + GPIO_QSPI_SD2_LEVEL_HIGH: u1, + GPIO_QSPI_SD2_EDGE_LOW: u1, + GPIO_QSPI_SD2_EDGE_HIGH: u1, + GPIO_QSPI_SD3_LEVEL_LOW: u1, + GPIO_QSPI_SD3_LEVEL_HIGH: u1, + GPIO_QSPI_SD3_EDGE_LOW: u1, + GPIO_QSPI_SD3_EDGE_HIGH: u1, + padding: u8, + }), + /// Interrupt Force for proc0 + PROC0_INTF: mmio.Mmio(packed struct(u32) { + GPIO_QSPI_SCLK_LEVEL_LOW: u1, + GPIO_QSPI_SCLK_LEVEL_HIGH: u1, + GPIO_QSPI_SCLK_EDGE_LOW: u1, + GPIO_QSPI_SCLK_EDGE_HIGH: u1, + GPIO_QSPI_SS_LEVEL_LOW: u1, + GPIO_QSPI_SS_LEVEL_HIGH: u1, + GPIO_QSPI_SS_EDGE_LOW: u1, + GPIO_QSPI_SS_EDGE_HIGH: u1, + GPIO_QSPI_SD0_LEVEL_LOW: u1, + GPIO_QSPI_SD0_LEVEL_HIGH: u1, + GPIO_QSPI_SD0_EDGE_LOW: u1, + GPIO_QSPI_SD0_EDGE_HIGH: u1, + GPIO_QSPI_SD1_LEVEL_LOW: u1, + GPIO_QSPI_SD1_LEVEL_HIGH: u1, + GPIO_QSPI_SD1_EDGE_LOW: u1, + GPIO_QSPI_SD1_EDGE_HIGH: u1, + GPIO_QSPI_SD2_LEVEL_LOW: u1, + GPIO_QSPI_SD2_LEVEL_HIGH: u1, + GPIO_QSPI_SD2_EDGE_LOW: u1, + GPIO_QSPI_SD2_EDGE_HIGH: u1, + GPIO_QSPI_SD3_LEVEL_LOW: u1, + GPIO_QSPI_SD3_LEVEL_HIGH: u1, + GPIO_QSPI_SD3_EDGE_LOW: u1, + GPIO_QSPI_SD3_EDGE_HIGH: u1, + padding: u8, + }), + /// Interrupt status after masking & forcing for proc0 + PROC0_INTS: mmio.Mmio(packed struct(u32) { + GPIO_QSPI_SCLK_LEVEL_LOW: u1, + GPIO_QSPI_SCLK_LEVEL_HIGH: u1, + GPIO_QSPI_SCLK_EDGE_LOW: u1, + GPIO_QSPI_SCLK_EDGE_HIGH: u1, + GPIO_QSPI_SS_LEVEL_LOW: u1, + GPIO_QSPI_SS_LEVEL_HIGH: u1, + GPIO_QSPI_SS_EDGE_LOW: u1, + GPIO_QSPI_SS_EDGE_HIGH: u1, + GPIO_QSPI_SD0_LEVEL_LOW: u1, + GPIO_QSPI_SD0_LEVEL_HIGH: u1, + GPIO_QSPI_SD0_EDGE_LOW: u1, + GPIO_QSPI_SD0_EDGE_HIGH: u1, + GPIO_QSPI_SD1_LEVEL_LOW: u1, + GPIO_QSPI_SD1_LEVEL_HIGH: u1, + GPIO_QSPI_SD1_EDGE_LOW: u1, + GPIO_QSPI_SD1_EDGE_HIGH: u1, + GPIO_QSPI_SD2_LEVEL_LOW: u1, + GPIO_QSPI_SD2_LEVEL_HIGH: u1, + GPIO_QSPI_SD2_EDGE_LOW: u1, + GPIO_QSPI_SD2_EDGE_HIGH: u1, + GPIO_QSPI_SD3_LEVEL_LOW: u1, + GPIO_QSPI_SD3_LEVEL_HIGH: u1, + GPIO_QSPI_SD3_EDGE_LOW: u1, + GPIO_QSPI_SD3_EDGE_HIGH: u1, + padding: u8, + }), + /// Interrupt Enable for proc1 + PROC1_INTE: mmio.Mmio(packed struct(u32) { + GPIO_QSPI_SCLK_LEVEL_LOW: u1, + GPIO_QSPI_SCLK_LEVEL_HIGH: u1, + GPIO_QSPI_SCLK_EDGE_LOW: u1, + GPIO_QSPI_SCLK_EDGE_HIGH: u1, + GPIO_QSPI_SS_LEVEL_LOW: u1, + GPIO_QSPI_SS_LEVEL_HIGH: u1, + GPIO_QSPI_SS_EDGE_LOW: u1, + GPIO_QSPI_SS_EDGE_HIGH: u1, + GPIO_QSPI_SD0_LEVEL_LOW: u1, + GPIO_QSPI_SD0_LEVEL_HIGH: u1, + GPIO_QSPI_SD0_EDGE_LOW: u1, + GPIO_QSPI_SD0_EDGE_HIGH: u1, + GPIO_QSPI_SD1_LEVEL_LOW: u1, + GPIO_QSPI_SD1_LEVEL_HIGH: u1, + GPIO_QSPI_SD1_EDGE_LOW: u1, + GPIO_QSPI_SD1_EDGE_HIGH: u1, + GPIO_QSPI_SD2_LEVEL_LOW: u1, + GPIO_QSPI_SD2_LEVEL_HIGH: u1, + GPIO_QSPI_SD2_EDGE_LOW: u1, + GPIO_QSPI_SD2_EDGE_HIGH: u1, + GPIO_QSPI_SD3_LEVEL_LOW: u1, + GPIO_QSPI_SD3_LEVEL_HIGH: u1, + GPIO_QSPI_SD3_EDGE_LOW: u1, + GPIO_QSPI_SD3_EDGE_HIGH: u1, + padding: u8, + }), + /// Interrupt Force for proc1 + PROC1_INTF: mmio.Mmio(packed struct(u32) { + GPIO_QSPI_SCLK_LEVEL_LOW: u1, + GPIO_QSPI_SCLK_LEVEL_HIGH: u1, + GPIO_QSPI_SCLK_EDGE_LOW: u1, + GPIO_QSPI_SCLK_EDGE_HIGH: u1, + GPIO_QSPI_SS_LEVEL_LOW: u1, + GPIO_QSPI_SS_LEVEL_HIGH: u1, + GPIO_QSPI_SS_EDGE_LOW: u1, + GPIO_QSPI_SS_EDGE_HIGH: u1, + GPIO_QSPI_SD0_LEVEL_LOW: u1, + GPIO_QSPI_SD0_LEVEL_HIGH: u1, + GPIO_QSPI_SD0_EDGE_LOW: u1, + GPIO_QSPI_SD0_EDGE_HIGH: u1, + GPIO_QSPI_SD1_LEVEL_LOW: u1, + GPIO_QSPI_SD1_LEVEL_HIGH: u1, + GPIO_QSPI_SD1_EDGE_LOW: u1, + GPIO_QSPI_SD1_EDGE_HIGH: u1, + GPIO_QSPI_SD2_LEVEL_LOW: u1, + GPIO_QSPI_SD2_LEVEL_HIGH: u1, + GPIO_QSPI_SD2_EDGE_LOW: u1, + GPIO_QSPI_SD2_EDGE_HIGH: u1, + GPIO_QSPI_SD3_LEVEL_LOW: u1, + GPIO_QSPI_SD3_LEVEL_HIGH: u1, + GPIO_QSPI_SD3_EDGE_LOW: u1, + GPIO_QSPI_SD3_EDGE_HIGH: u1, + padding: u8, + }), + /// Interrupt status after masking & forcing for proc1 + PROC1_INTS: mmio.Mmio(packed struct(u32) { + GPIO_QSPI_SCLK_LEVEL_LOW: u1, + GPIO_QSPI_SCLK_LEVEL_HIGH: u1, + GPIO_QSPI_SCLK_EDGE_LOW: u1, + GPIO_QSPI_SCLK_EDGE_HIGH: u1, + GPIO_QSPI_SS_LEVEL_LOW: u1, + GPIO_QSPI_SS_LEVEL_HIGH: u1, + GPIO_QSPI_SS_EDGE_LOW: u1, + GPIO_QSPI_SS_EDGE_HIGH: u1, + GPIO_QSPI_SD0_LEVEL_LOW: u1, + GPIO_QSPI_SD0_LEVEL_HIGH: u1, + GPIO_QSPI_SD0_EDGE_LOW: u1, + GPIO_QSPI_SD0_EDGE_HIGH: u1, + GPIO_QSPI_SD1_LEVEL_LOW: u1, + GPIO_QSPI_SD1_LEVEL_HIGH: u1, + GPIO_QSPI_SD1_EDGE_LOW: u1, + GPIO_QSPI_SD1_EDGE_HIGH: u1, + GPIO_QSPI_SD2_LEVEL_LOW: u1, + GPIO_QSPI_SD2_LEVEL_HIGH: u1, + GPIO_QSPI_SD2_EDGE_LOW: u1, + GPIO_QSPI_SD2_EDGE_HIGH: u1, + GPIO_QSPI_SD3_LEVEL_LOW: u1, + GPIO_QSPI_SD3_LEVEL_HIGH: u1, + GPIO_QSPI_SD3_EDGE_LOW: u1, + GPIO_QSPI_SD3_EDGE_HIGH: u1, + padding: u8, + }), + /// Interrupt Enable for dormant_wake + DORMANT_WAKE_INTE: mmio.Mmio(packed struct(u32) { + GPIO_QSPI_SCLK_LEVEL_LOW: u1, + GPIO_QSPI_SCLK_LEVEL_HIGH: u1, + GPIO_QSPI_SCLK_EDGE_LOW: u1, + GPIO_QSPI_SCLK_EDGE_HIGH: u1, + GPIO_QSPI_SS_LEVEL_LOW: u1, + GPIO_QSPI_SS_LEVEL_HIGH: u1, + GPIO_QSPI_SS_EDGE_LOW: u1, + GPIO_QSPI_SS_EDGE_HIGH: u1, + GPIO_QSPI_SD0_LEVEL_LOW: u1, + GPIO_QSPI_SD0_LEVEL_HIGH: u1, + GPIO_QSPI_SD0_EDGE_LOW: u1, + GPIO_QSPI_SD0_EDGE_HIGH: u1, + GPIO_QSPI_SD1_LEVEL_LOW: u1, + GPIO_QSPI_SD1_LEVEL_HIGH: u1, + GPIO_QSPI_SD1_EDGE_LOW: u1, + GPIO_QSPI_SD1_EDGE_HIGH: u1, + GPIO_QSPI_SD2_LEVEL_LOW: u1, + GPIO_QSPI_SD2_LEVEL_HIGH: u1, + GPIO_QSPI_SD2_EDGE_LOW: u1, + GPIO_QSPI_SD2_EDGE_HIGH: u1, + GPIO_QSPI_SD3_LEVEL_LOW: u1, + GPIO_QSPI_SD3_LEVEL_HIGH: u1, + GPIO_QSPI_SD3_EDGE_LOW: u1, + GPIO_QSPI_SD3_EDGE_HIGH: u1, + padding: u8, + }), + /// Interrupt Force for dormant_wake + DORMANT_WAKE_INTF: mmio.Mmio(packed struct(u32) { + GPIO_QSPI_SCLK_LEVEL_LOW: u1, + GPIO_QSPI_SCLK_LEVEL_HIGH: u1, + GPIO_QSPI_SCLK_EDGE_LOW: u1, + GPIO_QSPI_SCLK_EDGE_HIGH: u1, + GPIO_QSPI_SS_LEVEL_LOW: u1, + GPIO_QSPI_SS_LEVEL_HIGH: u1, + GPIO_QSPI_SS_EDGE_LOW: u1, + GPIO_QSPI_SS_EDGE_HIGH: u1, + GPIO_QSPI_SD0_LEVEL_LOW: u1, + GPIO_QSPI_SD0_LEVEL_HIGH: u1, + GPIO_QSPI_SD0_EDGE_LOW: u1, + GPIO_QSPI_SD0_EDGE_HIGH: u1, + GPIO_QSPI_SD1_LEVEL_LOW: u1, + GPIO_QSPI_SD1_LEVEL_HIGH: u1, + GPIO_QSPI_SD1_EDGE_LOW: u1, + GPIO_QSPI_SD1_EDGE_HIGH: u1, + GPIO_QSPI_SD2_LEVEL_LOW: u1, + GPIO_QSPI_SD2_LEVEL_HIGH: u1, + GPIO_QSPI_SD2_EDGE_LOW: u1, + GPIO_QSPI_SD2_EDGE_HIGH: u1, + GPIO_QSPI_SD3_LEVEL_LOW: u1, + GPIO_QSPI_SD3_LEVEL_HIGH: u1, + GPIO_QSPI_SD3_EDGE_LOW: u1, + GPIO_QSPI_SD3_EDGE_HIGH: u1, + padding: u8, + }), + /// Interrupt status after masking & forcing for dormant_wake + DORMANT_WAKE_INTS: mmio.Mmio(packed struct(u32) { + GPIO_QSPI_SCLK_LEVEL_LOW: u1, + GPIO_QSPI_SCLK_LEVEL_HIGH: u1, + GPIO_QSPI_SCLK_EDGE_LOW: u1, + GPIO_QSPI_SCLK_EDGE_HIGH: u1, + GPIO_QSPI_SS_LEVEL_LOW: u1, + GPIO_QSPI_SS_LEVEL_HIGH: u1, + GPIO_QSPI_SS_EDGE_LOW: u1, + GPIO_QSPI_SS_EDGE_HIGH: u1, + GPIO_QSPI_SD0_LEVEL_LOW: u1, + GPIO_QSPI_SD0_LEVEL_HIGH: u1, + GPIO_QSPI_SD0_EDGE_LOW: u1, + GPIO_QSPI_SD0_EDGE_HIGH: u1, + GPIO_QSPI_SD1_LEVEL_LOW: u1, + GPIO_QSPI_SD1_LEVEL_HIGH: u1, + GPIO_QSPI_SD1_EDGE_LOW: u1, + GPIO_QSPI_SD1_EDGE_HIGH: u1, + GPIO_QSPI_SD2_LEVEL_LOW: u1, + GPIO_QSPI_SD2_LEVEL_HIGH: u1, + GPIO_QSPI_SD2_EDGE_LOW: u1, + GPIO_QSPI_SD2_EDGE_HIGH: u1, + GPIO_QSPI_SD3_LEVEL_LOW: u1, + GPIO_QSPI_SD3_LEVEL_HIGH: u1, + GPIO_QSPI_SD3_EDGE_LOW: u1, + GPIO_QSPI_SD3_EDGE_HIGH: u1, + padding: u8, + }), + }; + + pub const PADS_BANK0 = extern struct { + /// Voltage select. Per bank control + VOLTAGE_SELECT: mmio.Mmio(packed struct(u32) { + VOLTAGE_SELECT: packed union { + raw: u1, + value: enum(u1) { + /// Set voltage to 3.3V (DVDD >= 2V5) + @"3v3" = 0x0, + /// Set voltage to 1.8V (DVDD <= 1V8) + @"1v8" = 0x1, + }, + }, + padding: u31, + }), + /// Pad control register + GPIO0: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO1: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO2: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO3: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO4: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO5: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO6: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO7: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO8: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO9: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO10: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO11: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO12: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO13: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO14: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO15: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO16: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO17: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO18: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO19: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO20: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO21: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO22: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO23: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO24: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO25: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO26: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO27: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO28: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO29: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + SWCLK: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + SWD: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + }; + + pub const PADS_QSPI = extern struct { + /// Voltage select. Per bank control + VOLTAGE_SELECT: mmio.Mmio(packed struct(u32) { + VOLTAGE_SELECT: packed union { + raw: u1, + value: enum(u1) { + /// Set voltage to 3.3V (DVDD >= 2V5) + @"3v3" = 0x0, + /// Set voltage to 1.8V (DVDD <= 1V8) + @"1v8" = 0x1, + }, + }, + padding: u31, + }), + /// Pad control register + GPIO_QSPI_SCLK: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO_QSPI_SD0: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO_QSPI_SD1: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO_QSPI_SD2: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO_QSPI_SD3: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + /// Pad control register + GPIO_QSPI_SS: mmio.Mmio(packed struct(u32) { + /// Slew rate control. 1 = Fast, 0 = Slow + SLEWFAST: u1, + /// Enable schmitt trigger + SCHMITT: u1, + /// Pull down enable + PDE: u1, + /// Pull up enable + PUE: u1, + /// Drive strength. + DRIVE: packed union { + raw: u2, + value: enum(u2) { + @"2mA" = 0x0, + @"4mA" = 0x1, + @"8mA" = 0x2, + @"12mA" = 0x3, + }, + }, + /// Input enable + IE: u1, + /// Output disable. Has priority over output enable from peripherals + OD: u1, + padding: u24, + }), + }; + + /// Controls the crystal oscillator + pub const XOSC = extern struct { + /// Crystal Oscillator Control + CTRL: mmio.Mmio(packed struct(u32) { + /// Frequency range. This resets to 0xAA0 and cannot be changed. + FREQ_RANGE: packed union { + raw: u12, + value: enum(u12) { + @"1_15MHZ" = 0xaa0, + RESERVED_1 = 0xaa1, + RESERVED_2 = 0xaa2, + RESERVED_3 = 0xaa3, + _, + }, + }, + /// On power-up this field is initialised to DISABLE and the chip runs from the ROSC. + /// If the chip has subsequently been programmed to run from the XOSC then setting this field to DISABLE may lock-up the chip. If this is a concern then run the clk_ref from the ROSC and enable the clk_sys RESUS feature. + /// The 12-bit code is intended to give some protection against accidental writes. An invalid setting will enable the oscillator. + ENABLE: packed union { + raw: u12, + value: enum(u12) { + DISABLE = 0xd1e, + ENABLE = 0xfab, + _, + }, + }, + padding: u8, + }), + /// Crystal Oscillator Status + STATUS: mmio.Mmio(packed struct(u32) { + /// The current frequency range setting, always reads 0 + FREQ_RANGE: packed union { + raw: u2, + value: enum(u2) { + @"1_15MHZ" = 0x0, + RESERVED_1 = 0x1, + RESERVED_2 = 0x2, + RESERVED_3 = 0x3, + }, + }, + reserved12: u10, + /// Oscillator is enabled but not necessarily running and stable, resets to 0 + ENABLED: u1, + reserved24: u11, + /// An invalid value has been written to CTRL_ENABLE or CTRL_FREQ_RANGE or DORMANT + BADWRITE: u1, + reserved31: u6, + /// Oscillator is running and stable + STABLE: u1, + }), + /// Crystal Oscillator pause control + /// This is used to save power by pausing the XOSC + /// On power-up this field is initialised to WAKE + /// An invalid write will also select WAKE + /// WARNING: stop the PLLs before selecting dormant mode + /// WARNING: setup the irq before selecting dormant mode + DORMANT: u32, + /// Controls the startup delay + STARTUP: mmio.Mmio(packed struct(u32) { + /// in multiples of 256*xtal_period. The reset value of 0xc4 corresponds to approx 50 000 cycles. + DELAY: u14, + reserved20: u6, + /// Multiplies the startup_delay by 4. This is of little value to the user given that the delay can be programmed directly. + X4: u1, + padding: u11, + }), + reserved28: [12]u8, + /// A down counter running at the xosc frequency which counts to zero and stops. + /// To start the counter write a non-zero value. + /// Can be used for short software pauses when setting up time sensitive hardware. + COUNT: mmio.Mmio(packed struct(u32) { + COUNT: u8, + padding: u24, + }), + }; + + pub const PLL_SYS = extern struct { + /// Control and Status + /// GENERAL CONSTRAINTS: + /// Reference clock frequency min=5MHz, max=800MHz + /// Feedback divider min=16, max=320 + /// VCO frequency min=400MHz, max=1600MHz + CS: mmio.Mmio(packed struct(u32) { + /// Divides the PLL input reference clock. + /// Behaviour is undefined for div=0. + /// PLL output will be unpredictable during refdiv changes, wait for lock=1 before using it. + REFDIV: u6, + reserved8: u2, + /// Passes the reference clock to the output instead of the divided VCO. The VCO continues to run so the user can switch between the reference clock and the divided VCO but the output will glitch when doing so. + BYPASS: u1, + reserved31: u22, + /// PLL is locked + LOCK: u1, + }), + /// Controls the PLL power modes. + PWR: mmio.Mmio(packed struct(u32) { + /// PLL powerdown + /// To save power set high when PLL output not required. + PD: u1, + reserved2: u1, + /// PLL DSM powerdown + /// Nothing is achieved by setting this low. + DSMPD: u1, + /// PLL post divider powerdown + /// To save power set high when PLL output not required or bypass=1. + POSTDIVPD: u1, + reserved5: u1, + /// PLL VCO powerdown + /// To save power set high when PLL output not required or bypass=1. + VCOPD: u1, + padding: u26, + }), + /// Feedback divisor + /// (note: this PLL does not support fractional division) + FBDIV_INT: mmio.Mmio(packed struct(u32) { + /// see ctrl reg description for constraints + FBDIV_INT: u12, + padding: u20, + }), + /// Controls the PLL post dividers for the primary output + /// (note: this PLL does not have a secondary output) + /// the primary output is driven from VCO divided by postdiv1*postdiv2 + PRIM: mmio.Mmio(packed struct(u32) { + reserved12: u12, + /// divide by 1-7 + POSTDIV2: u3, + reserved16: u1, + /// divide by 1-7 + POSTDIV1: u3, + padding: u13, + }), + }; + + pub const PPB = extern struct { + reserved57360: [57360]u8, + /// Use the SysTick Control and Status Register to enable the SysTick features. + SYST_CSR: mmio.Mmio(packed struct(u32) { + /// Enable SysTick counter: + /// 0 = Counter disabled. + /// 1 = Counter enabled. + ENABLE: u1, + /// Enables SysTick exception request: + /// 0 = Counting down to zero does not assert the SysTick exception request. + /// 1 = Counting down to zero to asserts the SysTick exception request. + TICKINT: u1, + /// SysTick clock source. Always reads as one if SYST_CALIB reports NOREF. + /// Selects the SysTick timer clock source: + /// 0 = External reference clock. + /// 1 = Processor clock. + CLKSOURCE: u1, + reserved16: u13, + /// Returns 1 if timer counted to 0 since last time this was read. Clears on read by application or debugger. + COUNTFLAG: u1, + padding: u15, + }), + /// Use the SysTick Reload Value Register to specify the start value to load into the current value register when the counter reaches 0. It can be any value between 0 and 0x00FFFFFF. A start value of 0 is possible, but has no effect because the SysTick interrupt and COUNTFLAG are activated when counting from 1 to 0. The reset value of this register is UNKNOWN. + /// To generate a multi-shot timer with a period of N processor clock cycles, use a RELOAD value of N-1. For example, if the SysTick interrupt is required every 100 clock pulses, set RELOAD to 99. + SYST_RVR: mmio.Mmio(packed struct(u32) { + /// Value to load into the SysTick Current Value Register when the counter reaches 0. + RELOAD: u24, + padding: u8, + }), + /// Use the SysTick Current Value Register to find the current value in the register. The reset value of this register is UNKNOWN. + SYST_CVR: mmio.Mmio(packed struct(u32) { + /// Reads return the current value of the SysTick counter. This register is write-clear. Writing to it with any value clears the register to 0. Clearing this register also clears the COUNTFLAG bit of the SysTick Control and Status Register. + CURRENT: u24, + padding: u8, + }), + /// Use the SysTick Calibration Value Register to enable software to scale to any required speed using divide and multiply. + SYST_CALIB: mmio.Mmio(packed struct(u32) { + /// An optional Reload value to be used for 10ms (100Hz) timing, subject to system clock skew errors. If the value reads as 0, the calibration value is not known. + TENMS: u24, + reserved30: u6, + /// If reads as 1, the calibration value for 10ms is inexact (due to clock frequency). + SKEW: u1, + /// If reads as 1, the Reference clock is not provided - the CLKSOURCE bit of the SysTick Control and Status register will be forced to 1 and cannot be cleared to 0. + NOREF: u1, + }), + reserved57600: [224]u8, + /// Use the Interrupt Set-Enable Register to enable interrupts and determine which interrupts are currently enabled. + /// If a pending interrupt is enabled, the NVIC activates the interrupt based on its priority. If an interrupt is not enabled, asserting its interrupt signal changes the interrupt state to pending, but the NVIC never activates the interrupt, regardless of its priority. + NVIC_ISER: mmio.Mmio(packed struct(u32) { + /// Interrupt set-enable bits. + /// Write: + /// 0 = No effect. + /// 1 = Enable interrupt. + /// Read: + /// 0 = Interrupt disabled. + /// 1 = Interrupt enabled. + SETENA: u32, + }), + reserved57728: [124]u8, + /// Use the Interrupt Clear-Enable Registers to disable interrupts and determine which interrupts are currently enabled. + NVIC_ICER: mmio.Mmio(packed struct(u32) { + /// Interrupt clear-enable bits. + /// Write: + /// 0 = No effect. + /// 1 = Disable interrupt. + /// Read: + /// 0 = Interrupt disabled. + /// 1 = Interrupt enabled. + CLRENA: u32, + }), + reserved57856: [124]u8, + /// The NVIC_ISPR forces interrupts into the pending state, and shows which interrupts are pending. + NVIC_ISPR: mmio.Mmio(packed struct(u32) { + /// Interrupt set-pending bits. + /// Write: + /// 0 = No effect. + /// 1 = Changes interrupt state to pending. + /// Read: + /// 0 = Interrupt is not pending. + /// 1 = Interrupt is pending. + /// Note: Writing 1 to the NVIC_ISPR bit corresponding to: + /// An interrupt that is pending has no effect. + /// A disabled interrupt sets the state of that interrupt to pending. + SETPEND: u32, + }), + reserved57984: [124]u8, + /// Use the Interrupt Clear-Pending Register to clear pending interrupts and determine which interrupts are currently pending. + NVIC_ICPR: mmio.Mmio(packed struct(u32) { + /// Interrupt clear-pending bits. + /// Write: + /// 0 = No effect. + /// 1 = Removes pending state and interrupt. + /// Read: + /// 0 = Interrupt is not pending. + /// 1 = Interrupt is pending. + CLRPEND: u32, + }), + reserved58368: [380]u8, + /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + /// Note: Writing 1 to an NVIC_ICPR bit does not affect the active state of the corresponding interrupt. + /// These registers are only word-accessible + NVIC_IPR0: mmio.Mmio(packed struct(u32) { + reserved6: u6, + /// Priority of interrupt 0 + IP_0: u2, + reserved14: u6, + /// Priority of interrupt 1 + IP_1: u2, + reserved22: u6, + /// Priority of interrupt 2 + IP_2: u2, + reserved30: u6, + /// Priority of interrupt 3 + IP_3: u2, + }), + /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + NVIC_IPR1: mmio.Mmio(packed struct(u32) { + reserved6: u6, + /// Priority of interrupt 4 + IP_4: u2, + reserved14: u6, + /// Priority of interrupt 5 + IP_5: u2, + reserved22: u6, + /// Priority of interrupt 6 + IP_6: u2, + reserved30: u6, + /// Priority of interrupt 7 + IP_7: u2, + }), + /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + NVIC_IPR2: mmio.Mmio(packed struct(u32) { + reserved6: u6, + /// Priority of interrupt 8 + IP_8: u2, + reserved14: u6, + /// Priority of interrupt 9 + IP_9: u2, + reserved22: u6, + /// Priority of interrupt 10 + IP_10: u2, + reserved30: u6, + /// Priority of interrupt 11 + IP_11: u2, + }), + /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + NVIC_IPR3: mmio.Mmio(packed struct(u32) { + reserved6: u6, + /// Priority of interrupt 12 + IP_12: u2, + reserved14: u6, + /// Priority of interrupt 13 + IP_13: u2, + reserved22: u6, + /// Priority of interrupt 14 + IP_14: u2, + reserved30: u6, + /// Priority of interrupt 15 + IP_15: u2, + }), + /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + NVIC_IPR4: mmio.Mmio(packed struct(u32) { + reserved6: u6, + /// Priority of interrupt 16 + IP_16: u2, + reserved14: u6, + /// Priority of interrupt 17 + IP_17: u2, + reserved22: u6, + /// Priority of interrupt 18 + IP_18: u2, + reserved30: u6, + /// Priority of interrupt 19 + IP_19: u2, + }), + /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + NVIC_IPR5: mmio.Mmio(packed struct(u32) { + reserved6: u6, + /// Priority of interrupt 20 + IP_20: u2, + reserved14: u6, + /// Priority of interrupt 21 + IP_21: u2, + reserved22: u6, + /// Priority of interrupt 22 + IP_22: u2, + reserved30: u6, + /// Priority of interrupt 23 + IP_23: u2, + }), + /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + NVIC_IPR6: mmio.Mmio(packed struct(u32) { + reserved6: u6, + /// Priority of interrupt 24 + IP_24: u2, + reserved14: u6, + /// Priority of interrupt 25 + IP_25: u2, + reserved22: u6, + /// Priority of interrupt 26 + IP_26: u2, + reserved30: u6, + /// Priority of interrupt 27 + IP_27: u2, + }), + /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + NVIC_IPR7: mmio.Mmio(packed struct(u32) { + reserved6: u6, + /// Priority of interrupt 28 + IP_28: u2, + reserved14: u6, + /// Priority of interrupt 29 + IP_29: u2, + reserved22: u6, + /// Priority of interrupt 30 + IP_30: u2, + reserved30: u6, + /// Priority of interrupt 31 + IP_31: u2, + }), + reserved60672: [2272]u8, + /// Read the CPU ID Base Register to determine: the ID number of the processor core, the version number of the processor core, the implementation details of the processor core. + CPUID: mmio.Mmio(packed struct(u32) { + /// Minor revision number m in the rnpm revision status: + /// 0x1 = Patch 1. + REVISION: u4, + /// Number of processor within family: 0xC60 = Cortex-M0+ + PARTNO: u12, + /// Constant that defines the architecture of the processor: + /// 0xC = ARMv6-M architecture. + ARCHITECTURE: u4, + /// Major revision number n in the rnpm revision status: + /// 0x0 = Revision 0. + VARIANT: u4, + /// Implementor code: 0x41 = ARM + IMPLEMENTER: u8, + }), + /// Use the Interrupt Control State Register to set a pending Non-Maskable Interrupt (NMI), set or clear a pending PendSV, set or clear a pending SysTick, check for pending exceptions, check the vector number of the highest priority pended exception, check the vector number of the active exception. + ICSR: mmio.Mmio(packed struct(u32) { + /// Active exception number field. Reset clears the VECTACTIVE field. + VECTACTIVE: u9, + reserved12: u3, + /// Indicates the exception number for the highest priority pending exception: 0 = no pending exceptions. Non zero = The pending state includes the effect of memory-mapped enable and mask registers. It does not include the PRIMASK special-purpose register qualifier. + VECTPENDING: u9, + reserved22: u1, + /// External interrupt pending flag + ISRPENDING: u1, + /// The system can only access this bit when the core is halted. It indicates that a pending interrupt is to be taken in the next running cycle. If C_MASKINTS is clear in the Debug Halting Control and Status Register, the interrupt is serviced. + ISRPREEMPT: u1, + reserved25: u1, + /// SysTick exception clear-pending bit. + /// Write: + /// 0 = No effect. + /// 1 = Removes the pending state from the SysTick exception. + /// This bit is WO. On a register read its value is Unknown. + PENDSTCLR: u1, + /// SysTick exception set-pending bit. + /// Write: + /// 0 = No effect. + /// 1 = Changes SysTick exception state to pending. + /// Read: + /// 0 = SysTick exception is not pending. + /// 1 = SysTick exception is pending. + PENDSTSET: u1, + /// PendSV clear-pending bit. + /// Write: + /// 0 = No effect. + /// 1 = Removes the pending state from the PendSV exception. + PENDSVCLR: u1, + /// PendSV set-pending bit. + /// Write: + /// 0 = No effect. + /// 1 = Changes PendSV exception state to pending. + /// Read: + /// 0 = PendSV exception is not pending. + /// 1 = PendSV exception is pending. + /// Writing 1 to this bit is the only way to set the PendSV exception state to pending. + PENDSVSET: u1, + reserved31: u2, + /// Setting this bit will activate an NMI. Since NMI is the highest priority exception, it will activate as soon as it is registered. + /// NMI set-pending bit. + /// Write: + /// 0 = No effect. + /// 1 = Changes NMI exception state to pending. + /// Read: + /// 0 = NMI exception is not pending. + /// 1 = NMI exception is pending. + /// Because NMI is the highest-priority exception, normally the processor enters the NMI + /// exception handler as soon as it detects a write of 1 to this bit. Entering the handler then clears + /// this bit to 0. This means a read of this bit by the NMI exception handler returns 1 only if the + /// NMI signal is reasserted while the processor is executing that handler. + NMIPENDSET: u1, + }), + /// The VTOR holds the vector table offset address. + VTOR: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// Bits [31:8] of the indicate the vector table offset address. + TBLOFF: u24, + }), + /// Use the Application Interrupt and Reset Control Register to: determine data endianness, clear all active state information from debug halt mode, request a system reset. + AIRCR: mmio.Mmio(packed struct(u32) { + reserved1: u1, + /// Clears all active state information for fixed and configurable exceptions. This bit: is self-clearing, can only be set by the DAP when the core is halted. When set: clears all active exception status of the processor, forces a return to Thread mode, forces an IPSR of 0. A debugger must re-initialize the stack. + VECTCLRACTIVE: u1, + /// Writing 1 to this bit causes the SYSRESETREQ signal to the outer system to be asserted to request a reset. The intention is to force a large system reset of all major components except for debug. The C_HALT bit in the DHCSR is cleared as a result of the system reset requested. The debugger does not lose contact with the device. + SYSRESETREQ: u1, + reserved15: u12, + /// Data endianness implemented: + /// 0 = Little-endian. + ENDIANESS: u1, + /// Register key: + /// Reads as Unknown + /// On writes, write 0x05FA to VECTKEY, otherwise the write is ignored. + VECTKEY: u16, + }), + /// System Control Register. Use the System Control Register for power-management functions: signal to the system when the processor can enter a low power state, control how the processor enters and exits low power states. + SCR: mmio.Mmio(packed struct(u32) { + reserved1: u1, + /// Indicates sleep-on-exit when returning from Handler mode to Thread mode: + /// 0 = Do not sleep when returning to Thread mode. + /// 1 = Enter sleep, or deep sleep, on return from an ISR to Thread mode. + /// Setting this bit to 1 enables an interrupt driven application to avoid returning to an empty main application. + SLEEPONEXIT: u1, + /// Controls whether the processor uses sleep or deep sleep as its low power mode: + /// 0 = Sleep. + /// 1 = Deep sleep. + SLEEPDEEP: u1, + reserved4: u1, + /// Send Event on Pending bit: + /// 0 = Only enabled interrupts or events can wakeup the processor, disabled interrupts are excluded. + /// 1 = Enabled events and all interrupts, including disabled interrupts, can wakeup the processor. + /// When an event or interrupt becomes pending, the event signal wakes up the processor from WFE. If the + /// processor is not waiting for an event, the event is registered and affects the next WFE. + /// The processor also wakes up on execution of an SEV instruction or an external event. + SEVONPEND: u1, + padding: u27, + }), + /// The Configuration and Control Register permanently enables stack alignment and causes unaligned accesses to result in a Hard Fault. + CCR: mmio.Mmio(packed struct(u32) { + reserved3: u3, + /// Always reads as one, indicates that all unaligned accesses generate a HardFault. + UNALIGN_TRP: u1, + reserved9: u5, + /// Always reads as one, indicates 8-byte stack alignment on exception entry. On exception entry, the processor uses bit[9] of the stacked PSR to indicate the stack alignment. On return from the exception it uses this stacked bit to restore the correct stack alignment. + STKALIGN: u1, + padding: u22, + }), + reserved60700: [4]u8, + /// System handlers are a special class of exception handler that can have their priority set to any of the priority levels. Use the System Handler Priority Register 2 to set the priority of SVCall. + SHPR2: mmio.Mmio(packed struct(u32) { + reserved30: u30, + /// Priority of system handler 11, SVCall + PRI_11: u2, + }), + /// System handlers are a special class of exception handler that can have their priority set to any of the priority levels. Use the System Handler Priority Register 3 to set the priority of PendSV and SysTick. + SHPR3: mmio.Mmio(packed struct(u32) { + reserved22: u22, + /// Priority of system handler 14, PendSV + PRI_14: u2, + reserved30: u6, + /// Priority of system handler 15, SysTick + PRI_15: u2, + }), + /// Use the System Handler Control and State Register to determine or clear the pending status of SVCall. + SHCSR: mmio.Mmio(packed struct(u32) { + reserved15: u15, + /// Reads as 1 if SVCall is Pending. Write 1 to set pending SVCall, write 0 to clear pending SVCall. + SVCALLPENDED: u1, + padding: u16, + }), + reserved60816: [104]u8, + /// Read the MPU Type Register to determine if the processor implements an MPU, and how many regions the MPU supports. + MPU_TYPE: mmio.Mmio(packed struct(u32) { + /// Indicates support for separate instruction and data address maps. Reads as 0 as ARMv6-M only supports a unified MPU. + SEPARATE: u1, + reserved8: u7, + /// Number of regions supported by the MPU. + DREGION: u8, + /// Instruction region. Reads as zero as ARMv6-M only supports a unified MPU. + IREGION: u8, + padding: u8, + }), + /// Use the MPU Control Register to enable and disable the MPU, and to control whether the default memory map is enabled as a background region for privileged accesses, and whether the MPU is enabled for HardFaults and NMIs. + MPU_CTRL: mmio.Mmio(packed struct(u32) { + /// Enables the MPU. If the MPU is disabled, privileged and unprivileged accesses use the default memory map. + /// 0 = MPU disabled. + /// 1 = MPU enabled. + ENABLE: u1, + /// Controls the use of the MPU for HardFaults and NMIs. Setting this bit when ENABLE is clear results in UNPREDICTABLE behaviour. + /// When the MPU is enabled: + /// 0 = MPU is disabled during HardFault and NMI handlers, regardless of the value of the ENABLE bit. + /// 1 = the MPU is enabled during HardFault and NMI handlers. + HFNMIENA: u1, + /// Controls whether the default memory map is enabled as a background region for privileged accesses. This bit is ignored when ENABLE is clear. + /// 0 = If the MPU is enabled, disables use of the default memory map. Any memory access to a location not + /// covered by any enabled region causes a fault. + /// 1 = If the MPU is enabled, enables use of the default memory map as a background region for privileged software accesses. + /// When enabled, the background region acts as if it is region number -1. Any region that is defined and enabled has priority over this default map. + PRIVDEFENA: u1, + padding: u29, + }), + /// Use the MPU Region Number Register to select the region currently accessed by MPU_RBAR and MPU_RASR. + MPU_RNR: mmio.Mmio(packed struct(u32) { + /// Indicates the MPU region referenced by the MPU_RBAR and MPU_RASR registers. + /// The MPU supports 8 memory regions, so the permitted values of this field are 0-7. + REGION: u4, + padding: u28, + }), + /// Read the MPU Region Base Address Register to determine the base address of the region identified by MPU_RNR. Write to update the base address of said region or that of a specified region, with whose number MPU_RNR will also be updated. + MPU_RBAR: mmio.Mmio(packed struct(u32) { + /// On writes, specifies the number of the region whose base address to update provided VALID is set written as 1. On reads, returns bits [3:0] of MPU_RNR. + REGION: u4, + /// On writes, indicates whether the write must update the base address of the region identified by the REGION field, updating the MPU_RNR to indicate this new region. + /// Write: + /// 0 = MPU_RNR not changed, and the processor: + /// Updates the base address for the region specified in the MPU_RNR. + /// Ignores the value of the REGION field. + /// 1 = The processor: + /// Updates the value of the MPU_RNR to the value of the REGION field. + /// Updates the base address for the region specified in the REGION field. + /// Always reads as zero. + VALID: u1, + reserved8: u3, + /// Base address of the region. + ADDR: u24, + }), + /// Use the MPU Region Attribute and Size Register to define the size, access behaviour and memory type of the region identified by MPU_RNR, and enable that region. + MPU_RASR: mmio.Mmio(packed struct(u32) { + /// Enables the region. + ENABLE: u1, + /// Indicates the region size. Region size in bytes = 2^(SIZE+1). The minimum permitted value is 7 (b00111) = 256Bytes + SIZE: u5, + reserved8: u2, + /// Subregion Disable. For regions of 256 bytes or larger, each bit of this field controls whether one of the eight equal subregions is enabled. + SRD: u8, + /// The MPU Region Attribute field. Use to define the region attribute control. + /// 28 = XN: Instruction access disable bit: + /// 0 = Instruction fetches enabled. + /// 1 = Instruction fetches disabled. + /// 26:24 = AP: Access permission field + /// 18 = S: Shareable bit + /// 17 = C: Cacheable bit + /// 16 = B: Bufferable bit + ATTRS: u16, + }), + }; + + /// Register block for busfabric control signals and performance counters + pub const BUSCTRL = extern struct { + /// Set the priority of each master for bus arbitration. + BUS_PRIORITY: mmio.Mmio(packed struct(u32) { + /// 0 - low priority, 1 - high priority + PROC0: u1, + reserved4: u3, + /// 0 - low priority, 1 - high priority + PROC1: u1, + reserved8: u3, + /// 0 - low priority, 1 - high priority + DMA_R: u1, + reserved12: u3, + /// 0 - low priority, 1 - high priority + DMA_W: u1, + padding: u19, + }), + /// Bus priority acknowledge + BUS_PRIORITY_ACK: mmio.Mmio(packed struct(u32) { + /// Goes to 1 once all arbiters have registered the new global priority levels. + /// Arbiters update their local priority when servicing a new nonsequential access. + /// In normal circumstances this will happen almost immediately. + BUS_PRIORITY_ACK: u1, + padding: u31, + }), + /// Bus fabric performance counter 0 + PERFCTR0: mmio.Mmio(packed struct(u32) { + /// Busfabric saturating performance counter 0 + /// Count some event signal from the busfabric arbiters. + /// Write any value to clear. Select an event to count using PERFSEL0 + PERFCTR0: u24, + padding: u8, + }), + /// Bus fabric performance event select for PERFCTR0 + PERFSEL0: mmio.Mmio(packed struct(u32) { + /// Select an event for PERFCTR0. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. + PERFSEL0: packed union { + raw: u5, + value: enum(u5) { + apb_contested = 0x0, + apb = 0x1, + fastperi_contested = 0x2, + fastperi = 0x3, + sram5_contested = 0x4, + sram5 = 0x5, + sram4_contested = 0x6, + sram4 = 0x7, + sram3_contested = 0x8, + sram3 = 0x9, + sram2_contested = 0xa, + sram2 = 0xb, + sram1_contested = 0xc, + sram1 = 0xd, + sram0_contested = 0xe, + sram0 = 0xf, + xip_main_contested = 0x10, + xip_main = 0x11, + rom_contested = 0x12, + rom = 0x13, + _, + }, + }, + padding: u27, + }), + /// Bus fabric performance counter 1 + PERFCTR1: mmio.Mmio(packed struct(u32) { + /// Busfabric saturating performance counter 1 + /// Count some event signal from the busfabric arbiters. + /// Write any value to clear. Select an event to count using PERFSEL1 + PERFCTR1: u24, + padding: u8, + }), + /// Bus fabric performance event select for PERFCTR1 + PERFSEL1: mmio.Mmio(packed struct(u32) { + /// Select an event for PERFCTR1. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. + PERFSEL1: packed union { + raw: u5, + value: enum(u5) { + apb_contested = 0x0, + apb = 0x1, + fastperi_contested = 0x2, + fastperi = 0x3, + sram5_contested = 0x4, + sram5 = 0x5, + sram4_contested = 0x6, + sram4 = 0x7, + sram3_contested = 0x8, + sram3 = 0x9, + sram2_contested = 0xa, + sram2 = 0xb, + sram1_contested = 0xc, + sram1 = 0xd, + sram0_contested = 0xe, + sram0 = 0xf, + xip_main_contested = 0x10, + xip_main = 0x11, + rom_contested = 0x12, + rom = 0x13, + _, + }, + }, + padding: u27, + }), + /// Bus fabric performance counter 2 + PERFCTR2: mmio.Mmio(packed struct(u32) { + /// Busfabric saturating performance counter 2 + /// Count some event signal from the busfabric arbiters. + /// Write any value to clear. Select an event to count using PERFSEL2 + PERFCTR2: u24, + padding: u8, + }), + /// Bus fabric performance event select for PERFCTR2 + PERFSEL2: mmio.Mmio(packed struct(u32) { + /// Select an event for PERFCTR2. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. + PERFSEL2: packed union { + raw: u5, + value: enum(u5) { + apb_contested = 0x0, + apb = 0x1, + fastperi_contested = 0x2, + fastperi = 0x3, + sram5_contested = 0x4, + sram5 = 0x5, + sram4_contested = 0x6, + sram4 = 0x7, + sram3_contested = 0x8, + sram3 = 0x9, + sram2_contested = 0xa, + sram2 = 0xb, + sram1_contested = 0xc, + sram1 = 0xd, + sram0_contested = 0xe, + sram0 = 0xf, + xip_main_contested = 0x10, + xip_main = 0x11, + rom_contested = 0x12, + rom = 0x13, + _, + }, + }, + padding: u27, + }), + /// Bus fabric performance counter 3 + PERFCTR3: mmio.Mmio(packed struct(u32) { + /// Busfabric saturating performance counter 3 + /// Count some event signal from the busfabric arbiters. + /// Write any value to clear. Select an event to count using PERFSEL3 + PERFCTR3: u24, + padding: u8, + }), + /// Bus fabric performance event select for PERFCTR3 + PERFSEL3: mmio.Mmio(packed struct(u32) { + /// Select an event for PERFCTR3. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. + PERFSEL3: packed union { + raw: u5, + value: enum(u5) { + apb_contested = 0x0, + apb = 0x1, + fastperi_contested = 0x2, + fastperi = 0x3, + sram5_contested = 0x4, + sram5 = 0x5, + sram4_contested = 0x6, + sram4 = 0x7, + sram3_contested = 0x8, + sram3 = 0x9, + sram2_contested = 0xa, + sram2 = 0xb, + sram1_contested = 0xc, + sram1 = 0xd, + sram0_contested = 0xe, + sram0 = 0xf, + xip_main_contested = 0x10, + xip_main = 0x11, + rom_contested = 0x12, + rom = 0x13, + _, + }, + }, + padding: u27, + }), + }; + + pub const UART0 = extern struct { + /// Data Register, UARTDR + UARTDR: mmio.Mmio(packed struct(u32) { + /// Receive (read) data character. Transmit (write) data character. + DATA: u8, + /// Framing error. When set to 1, it indicates that the received character did not have a valid stop bit (a valid stop bit is 1). In FIFO mode, this error is associated with the character at the top of the FIFO. + FE: u1, + /// Parity error. When set to 1, it indicates that the parity of the received data character does not match the parity that the EPS and SPS bits in the Line Control Register, UARTLCR_H. In FIFO mode, this error is associated with the character at the top of the FIFO. + PE: u1, + /// Break error. This bit is set to 1 if a break condition was detected, indicating that the received data input was held LOW for longer than a full-word transmission time (defined as start, data, parity and stop bits). In FIFO mode, this error is associated with the character at the top of the FIFO. When a break occurs, only one 0 character is loaded into the FIFO. The next character is only enabled after the receive data input goes to a 1 (marking state), and the next valid start bit is received. + BE: u1, + /// Overrun error. This bit is set to 1 if data is received and the receive FIFO is already full. This is cleared to 0 once there is an empty space in the FIFO and a new character can be written to it. + OE: u1, + padding: u20, + }), + /// Receive Status Register/Error Clear Register, UARTRSR/UARTECR + UARTRSR: mmio.Mmio(packed struct(u32) { + /// Framing error. When set to 1, it indicates that the received character did not have a valid stop bit (a valid stop bit is 1). This bit is cleared to 0 by a write to UARTECR. In FIFO mode, this error is associated with the character at the top of the FIFO. + FE: u1, + /// Parity error. When set to 1, it indicates that the parity of the received data character does not match the parity that the EPS and SPS bits in the Line Control Register, UARTLCR_H. This bit is cleared to 0 by a write to UARTECR. In FIFO mode, this error is associated with the character at the top of the FIFO. + PE: u1, + /// Break error. This bit is set to 1 if a break condition was detected, indicating that the received data input was held LOW for longer than a full-word transmission time (defined as start, data, parity, and stop bits). This bit is cleared to 0 after a write to UARTECR. In FIFO mode, this error is associated with the character at the top of the FIFO. When a break occurs, only one 0 character is loaded into the FIFO. The next character is only enabled after the receive data input goes to a 1 (marking state) and the next valid start bit is received. + BE: u1, + /// Overrun error. This bit is set to 1 if data is received and the FIFO is already full. This bit is cleared to 0 by a write to UARTECR. The FIFO contents remain valid because no more data is written when the FIFO is full, only the contents of the shift register are overwritten. The CPU must now read the data, to empty the FIFO. + OE: u1, + padding: u28, + }), + reserved24: [16]u8, + /// Flag Register, UARTFR + UARTFR: mmio.Mmio(packed struct(u32) { + /// Clear to send. This bit is the complement of the UART clear to send, nUARTCTS, modem status input. That is, the bit is 1 when nUARTCTS is LOW. + CTS: u1, + /// Data set ready. This bit is the complement of the UART data set ready, nUARTDSR, modem status input. That is, the bit is 1 when nUARTDSR is LOW. + DSR: u1, + /// Data carrier detect. This bit is the complement of the UART data carrier detect, nUARTDCD, modem status input. That is, the bit is 1 when nUARTDCD is LOW. + DCD: u1, + /// UART busy. If this bit is set to 1, the UART is busy transmitting data. This bit remains set until the complete byte, including all the stop bits, has been sent from the shift register. This bit is set as soon as the transmit FIFO becomes non-empty, regardless of whether the UART is enabled or not. + BUSY: u1, + /// Receive FIFO empty. The meaning of this bit depends on the state of the FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the receive holding register is empty. If the FIFO is enabled, the RXFE bit is set when the receive FIFO is empty. + RXFE: u1, + /// Transmit FIFO full. The meaning of this bit depends on the state of the FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the transmit holding register is full. If the FIFO is enabled, the TXFF bit is set when the transmit FIFO is full. + TXFF: u1, + /// Receive FIFO full. The meaning of this bit depends on the state of the FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the receive holding register is full. If the FIFO is enabled, the RXFF bit is set when the receive FIFO is full. + RXFF: u1, + /// Transmit FIFO empty. The meaning of this bit depends on the state of the FEN bit in the Line Control Register, UARTLCR_H. If the FIFO is disabled, this bit is set when the transmit holding register is empty. If the FIFO is enabled, the TXFE bit is set when the transmit FIFO is empty. This bit does not indicate if there is data in the transmit shift register. + TXFE: u1, + /// Ring indicator. This bit is the complement of the UART ring indicator, nUARTRI, modem status input. That is, the bit is 1 when nUARTRI is LOW. + RI: u1, + padding: u23, + }), + reserved32: [4]u8, + /// IrDA Low-Power Counter Register, UARTILPR + UARTILPR: mmio.Mmio(packed struct(u32) { + /// 8-bit low-power divisor value. These bits are cleared to 0 at reset. + ILPDVSR: u8, + padding: u24, + }), + /// Integer Baud Rate Register, UARTIBRD + UARTIBRD: mmio.Mmio(packed struct(u32) { + /// The integer baud rate divisor. These bits are cleared to 0 on reset. + BAUD_DIVINT: u16, + padding: u16, + }), + /// Fractional Baud Rate Register, UARTFBRD + UARTFBRD: mmio.Mmio(packed struct(u32) { + /// The fractional baud rate divisor. These bits are cleared to 0 on reset. + BAUD_DIVFRAC: u6, + padding: u26, + }), + /// Line Control Register, UARTLCR_H + UARTLCR_H: mmio.Mmio(packed struct(u32) { + /// Send break. If this bit is set to 1, a low-level is continually output on the UARTTXD output, after completing transmission of the current character. For the proper execution of the break command, the software must set this bit for at least two complete frames. For normal use, this bit must be cleared to 0. + BRK: u1, + /// Parity enable: 0 = parity is disabled and no parity bit added to the data frame 1 = parity checking and generation is enabled. + PEN: u1, + /// Even parity select. Controls the type of parity the UART uses during transmission and reception: 0 = odd parity. The UART generates or checks for an odd number of 1s in the data and parity bits. 1 = even parity. The UART generates or checks for an even number of 1s in the data and parity bits. This bit has no effect when the PEN bit disables parity checking and generation. + EPS: u1, + /// Two stop bits select. If this bit is set to 1, two stop bits are transmitted at the end of the frame. The receive logic does not check for two stop bits being received. + STP2: u1, + /// Enable FIFOs: 0 = FIFOs are disabled (character mode) that is, the FIFOs become 1-byte-deep holding registers 1 = transmit and receive FIFO buffers are enabled (FIFO mode). + FEN: u1, + /// Word length. These bits indicate the number of data bits transmitted or received in a frame as follows: b11 = 8 bits b10 = 7 bits b01 = 6 bits b00 = 5 bits. + WLEN: u2, + /// Stick parity select. 0 = stick parity is disabled 1 = either: * if the EPS bit is 0 then the parity bit is transmitted and checked as a 1 * if the EPS bit is 1 then the parity bit is transmitted and checked as a 0. This bit has no effect when the PEN bit disables parity checking and generation. + SPS: u1, + padding: u24, + }), + /// Control Register, UARTCR + UARTCR: mmio.Mmio(packed struct(u32) { + /// UART enable: 0 = UART is disabled. If the UART is disabled in the middle of transmission or reception, it completes the current character before stopping. 1 = the UART is enabled. Data transmission and reception occurs for either UART signals or SIR signals depending on the setting of the SIREN bit. + UARTEN: u1, + /// SIR enable: 0 = IrDA SIR ENDEC is disabled. nSIROUT remains LOW (no light pulse generated), and signal transitions on SIRIN have no effect. 1 = IrDA SIR ENDEC is enabled. Data is transmitted and received on nSIROUT and SIRIN. UARTTXD remains HIGH, in the marking state. Signal transitions on UARTRXD or modem status inputs have no effect. This bit has no effect if the UARTEN bit disables the UART. + SIREN: u1, + /// SIR low-power IrDA mode. This bit selects the IrDA encoding mode. If this bit is cleared to 0, low-level bits are transmitted as an active high pulse with a width of 3 / 16th of the bit period. If this bit is set to 1, low-level bits are transmitted with a pulse width that is 3 times the period of the IrLPBaud16 input signal, regardless of the selected bit rate. Setting this bit uses less power, but might reduce transmission distances. + SIRLP: u1, + reserved7: u4, + /// Loopback enable. If this bit is set to 1 and the SIREN bit is set to 1 and the SIRTEST bit in the Test Control Register, UARTTCR is set to 1, then the nSIROUT path is inverted, and fed through to the SIRIN path. The SIRTEST bit in the test register must be set to 1 to override the normal half-duplex SIR operation. This must be the requirement for accessing the test registers during normal operation, and SIRTEST must be cleared to 0 when loopback testing is finished. This feature reduces the amount of external coupling required during system test. If this bit is set to 1, and the SIRTEST bit is set to 0, the UARTTXD path is fed through to the UARTRXD path. In either SIR mode or UART mode, when this bit is set, the modem outputs are also fed through to the modem inputs. This bit is cleared to 0 on reset, to disable loopback. + LBE: u1, + /// Transmit enable. If this bit is set to 1, the transmit section of the UART is enabled. Data transmission occurs for either UART signals, or SIR signals depending on the setting of the SIREN bit. When the UART is disabled in the middle of transmission, it completes the current character before stopping. + TXE: u1, + /// Receive enable. If this bit is set to 1, the receive section of the UART is enabled. Data reception occurs for either UART signals or SIR signals depending on the setting of the SIREN bit. When the UART is disabled in the middle of reception, it completes the current character before stopping. + RXE: u1, + /// Data transmit ready. This bit is the complement of the UART data transmit ready, nUARTDTR, modem status output. That is, when the bit is programmed to a 1 then nUARTDTR is LOW. + DTR: u1, + /// Request to send. This bit is the complement of the UART request to send, nUARTRTS, modem status output. That is, when the bit is programmed to a 1 then nUARTRTS is LOW. + RTS: u1, + /// This bit is the complement of the UART Out1 (nUARTOut1) modem status output. That is, when the bit is programmed to a 1 the output is 0. For DTE this can be used as Data Carrier Detect (DCD). + OUT1: u1, + /// This bit is the complement of the UART Out2 (nUARTOut2) modem status output. That is, when the bit is programmed to a 1, the output is 0. For DTE this can be used as Ring Indicator (RI). + OUT2: u1, + /// RTS hardware flow control enable. If this bit is set to 1, RTS hardware flow control is enabled. Data is only requested when there is space in the receive FIFO for it to be received. + RTSEN: u1, + /// CTS hardware flow control enable. If this bit is set to 1, CTS hardware flow control is enabled. Data is only transmitted when the nUARTCTS signal is asserted. + CTSEN: u1, + padding: u16, + }), + /// Interrupt FIFO Level Select Register, UARTIFLS + UARTIFLS: mmio.Mmio(packed struct(u32) { + /// Transmit interrupt FIFO level select. The trigger points for the transmit interrupt are as follows: b000 = Transmit FIFO becomes <= 1 / 8 full b001 = Transmit FIFO becomes <= 1 / 4 full b010 = Transmit FIFO becomes <= 1 / 2 full b011 = Transmit FIFO becomes <= 3 / 4 full b100 = Transmit FIFO becomes <= 7 / 8 full b101-b111 = reserved. + TXIFLSEL: u3, + /// Receive interrupt FIFO level select. The trigger points for the receive interrupt are as follows: b000 = Receive FIFO becomes >= 1 / 8 full b001 = Receive FIFO becomes >= 1 / 4 full b010 = Receive FIFO becomes >= 1 / 2 full b011 = Receive FIFO becomes >= 3 / 4 full b100 = Receive FIFO becomes >= 7 / 8 full b101-b111 = reserved. + RXIFLSEL: u3, + padding: u26, + }), + /// Interrupt Mask Set/Clear Register, UARTIMSC + UARTIMSC: mmio.Mmio(packed struct(u32) { + /// nUARTRI modem interrupt mask. A read returns the current mask for the UARTRIINTR interrupt. On a write of 1, the mask of the UARTRIINTR interrupt is set. A write of 0 clears the mask. + RIMIM: u1, + /// nUARTCTS modem interrupt mask. A read returns the current mask for the UARTCTSINTR interrupt. On a write of 1, the mask of the UARTCTSINTR interrupt is set. A write of 0 clears the mask. + CTSMIM: u1, + /// nUARTDCD modem interrupt mask. A read returns the current mask for the UARTDCDINTR interrupt. On a write of 1, the mask of the UARTDCDINTR interrupt is set. A write of 0 clears the mask. + DCDMIM: u1, + /// nUARTDSR modem interrupt mask. A read returns the current mask for the UARTDSRINTR interrupt. On a write of 1, the mask of the UARTDSRINTR interrupt is set. A write of 0 clears the mask. + DSRMIM: u1, + /// Receive interrupt mask. A read returns the current mask for the UARTRXINTR interrupt. On a write of 1, the mask of the UARTRXINTR interrupt is set. A write of 0 clears the mask. + RXIM: u1, + /// Transmit interrupt mask. A read returns the current mask for the UARTTXINTR interrupt. On a write of 1, the mask of the UARTTXINTR interrupt is set. A write of 0 clears the mask. + TXIM: u1, + /// Receive timeout interrupt mask. A read returns the current mask for the UARTRTINTR interrupt. On a write of 1, the mask of the UARTRTINTR interrupt is set. A write of 0 clears the mask. + RTIM: u1, + /// Framing error interrupt mask. A read returns the current mask for the UARTFEINTR interrupt. On a write of 1, the mask of the UARTFEINTR interrupt is set. A write of 0 clears the mask. + FEIM: u1, + /// Parity error interrupt mask. A read returns the current mask for the UARTPEINTR interrupt. On a write of 1, the mask of the UARTPEINTR interrupt is set. A write of 0 clears the mask. + PEIM: u1, + /// Break error interrupt mask. A read returns the current mask for the UARTBEINTR interrupt. On a write of 1, the mask of the UARTBEINTR interrupt is set. A write of 0 clears the mask. + BEIM: u1, + /// Overrun error interrupt mask. A read returns the current mask for the UARTOEINTR interrupt. On a write of 1, the mask of the UARTOEINTR interrupt is set. A write of 0 clears the mask. + OEIM: u1, + padding: u21, + }), + /// Raw Interrupt Status Register, UARTRIS + UARTRIS: mmio.Mmio(packed struct(u32) { + /// nUARTRI modem interrupt status. Returns the raw interrupt state of the UARTRIINTR interrupt. + RIRMIS: u1, + /// nUARTCTS modem interrupt status. Returns the raw interrupt state of the UARTCTSINTR interrupt. + CTSRMIS: u1, + /// nUARTDCD modem interrupt status. Returns the raw interrupt state of the UARTDCDINTR interrupt. + DCDRMIS: u1, + /// nUARTDSR modem interrupt status. Returns the raw interrupt state of the UARTDSRINTR interrupt. + DSRRMIS: u1, + /// Receive interrupt status. Returns the raw interrupt state of the UARTRXINTR interrupt. + RXRIS: u1, + /// Transmit interrupt status. Returns the raw interrupt state of the UARTTXINTR interrupt. + TXRIS: u1, + /// Receive timeout interrupt status. Returns the raw interrupt state of the UARTRTINTR interrupt. a + RTRIS: u1, + /// Framing error interrupt status. Returns the raw interrupt state of the UARTFEINTR interrupt. + FERIS: u1, + /// Parity error interrupt status. Returns the raw interrupt state of the UARTPEINTR interrupt. + PERIS: u1, + /// Break error interrupt status. Returns the raw interrupt state of the UARTBEINTR interrupt. + BERIS: u1, + /// Overrun error interrupt status. Returns the raw interrupt state of the UARTOEINTR interrupt. + OERIS: u1, + padding: u21, + }), + /// Masked Interrupt Status Register, UARTMIS + UARTMIS: mmio.Mmio(packed struct(u32) { + /// nUARTRI modem masked interrupt status. Returns the masked interrupt state of the UARTRIINTR interrupt. + RIMMIS: u1, + /// nUARTCTS modem masked interrupt status. Returns the masked interrupt state of the UARTCTSINTR interrupt. + CTSMMIS: u1, + /// nUARTDCD modem masked interrupt status. Returns the masked interrupt state of the UARTDCDINTR interrupt. + DCDMMIS: u1, + /// nUARTDSR modem masked interrupt status. Returns the masked interrupt state of the UARTDSRINTR interrupt. + DSRMMIS: u1, + /// Receive masked interrupt status. Returns the masked interrupt state of the UARTRXINTR interrupt. + RXMIS: u1, + /// Transmit masked interrupt status. Returns the masked interrupt state of the UARTTXINTR interrupt. + TXMIS: u1, + /// Receive timeout masked interrupt status. Returns the masked interrupt state of the UARTRTINTR interrupt. + RTMIS: u1, + /// Framing error masked interrupt status. Returns the masked interrupt state of the UARTFEINTR interrupt. + FEMIS: u1, + /// Parity error masked interrupt status. Returns the masked interrupt state of the UARTPEINTR interrupt. + PEMIS: u1, + /// Break error masked interrupt status. Returns the masked interrupt state of the UARTBEINTR interrupt. + BEMIS: u1, + /// Overrun error masked interrupt status. Returns the masked interrupt state of the UARTOEINTR interrupt. + OEMIS: u1, + padding: u21, + }), + /// Interrupt Clear Register, UARTICR + UARTICR: mmio.Mmio(packed struct(u32) { + /// nUARTRI modem interrupt clear. Clears the UARTRIINTR interrupt. + RIMIC: u1, + /// nUARTCTS modem interrupt clear. Clears the UARTCTSINTR interrupt. + CTSMIC: u1, + /// nUARTDCD modem interrupt clear. Clears the UARTDCDINTR interrupt. + DCDMIC: u1, + /// nUARTDSR modem interrupt clear. Clears the UARTDSRINTR interrupt. + DSRMIC: u1, + /// Receive interrupt clear. Clears the UARTRXINTR interrupt. + RXIC: u1, + /// Transmit interrupt clear. Clears the UARTTXINTR interrupt. + TXIC: u1, + /// Receive timeout interrupt clear. Clears the UARTRTINTR interrupt. + RTIC: u1, + /// Framing error interrupt clear. Clears the UARTFEINTR interrupt. + FEIC: u1, + /// Parity error interrupt clear. Clears the UARTPEINTR interrupt. + PEIC: u1, + /// Break error interrupt clear. Clears the UARTBEINTR interrupt. + BEIC: u1, + /// Overrun error interrupt clear. Clears the UARTOEINTR interrupt. + OEIC: u1, + padding: u21, + }), + /// DMA Control Register, UARTDMACR + UARTDMACR: mmio.Mmio(packed struct(u32) { + /// Receive DMA enable. If this bit is set to 1, DMA for the receive FIFO is enabled. + RXDMAE: u1, + /// Transmit DMA enable. If this bit is set to 1, DMA for the transmit FIFO is enabled. + TXDMAE: u1, + /// DMA on error. If this bit is set to 1, the DMA receive request outputs, UARTRXDMASREQ or UARTRXDMABREQ, are disabled when the UART error interrupt is asserted. + DMAONERR: u1, + padding: u29, + }), + reserved4064: [3988]u8, + /// UARTPeriphID0 Register + UARTPERIPHID0: mmio.Mmio(packed struct(u32) { + /// These bits read back as 0x11 + PARTNUMBER0: u8, + padding: u24, + }), + /// UARTPeriphID1 Register + UARTPERIPHID1: mmio.Mmio(packed struct(u32) { + /// These bits read back as 0x0 + PARTNUMBER1: u4, + /// These bits read back as 0x1 + DESIGNER0: u4, + padding: u24, + }), + /// UARTPeriphID2 Register + UARTPERIPHID2: mmio.Mmio(packed struct(u32) { + /// These bits read back as 0x4 + DESIGNER1: u4, + /// This field depends on the revision of the UART: r1p0 0x0 r1p1 0x1 r1p3 0x2 r1p4 0x2 r1p5 0x3 + REVISION: u4, + padding: u24, + }), + /// UARTPeriphID3 Register + UARTPERIPHID3: mmio.Mmio(packed struct(u32) { + /// These bits read back as 0x00 + CONFIGURATION: u8, + padding: u24, + }), + /// UARTPCellID0 Register + UARTPCELLID0: mmio.Mmio(packed struct(u32) { + /// These bits read back as 0x0D + UARTPCELLID0: u8, + padding: u24, + }), + /// UARTPCellID1 Register + UARTPCELLID1: mmio.Mmio(packed struct(u32) { + /// These bits read back as 0xF0 + UARTPCELLID1: u8, + padding: u24, + }), + /// UARTPCellID2 Register + UARTPCELLID2: mmio.Mmio(packed struct(u32) { + /// These bits read back as 0x05 + UARTPCELLID2: u8, + padding: u24, + }), + /// UARTPCellID3 Register + UARTPCELLID3: mmio.Mmio(packed struct(u32) { + /// These bits read back as 0xB1 + UARTPCELLID3: u8, + padding: u24, + }), + }; + + /// Single-cycle IO block + /// Provides core-local and inter-core hardware for the two processors, with single-cycle access. + pub const SIO = extern struct { + /// Processor core identifier + /// Value is 0 when read from processor core 0, and 1 when read from processor core 1. + CPUID: u32, + /// Input value for GPIO pins + GPIO_IN: mmio.Mmio(packed struct(u32) { + /// Input value for GPIO0...29 + GPIO_IN: u30, + padding: u2, + }), + /// Input value for QSPI pins + GPIO_HI_IN: mmio.Mmio(packed struct(u32) { + /// Input value on QSPI IO in order 0..5: SCLK, SSn, SD0, SD1, SD2, SD3 + GPIO_HI_IN: u6, + padding: u26, + }), + reserved16: [4]u8, + /// GPIO output value + GPIO_OUT: mmio.Mmio(packed struct(u32) { + /// Set output level (1/0 -> high/low) for GPIO0...29. + /// Reading back gives the last value written, NOT the input value from the pins. + /// If core 0 and core 1 both write to GPIO_OUT simultaneously (or to a SET/CLR/XOR alias), + /// the result is as though the write from core 0 took place first, + /// and the write from core 1 was then applied to that intermediate result. + GPIO_OUT: u30, + padding: u2, + }), + /// GPIO output value set + GPIO_OUT_SET: mmio.Mmio(packed struct(u32) { + /// Perform an atomic bit-set on GPIO_OUT, i.e. `GPIO_OUT |= wdata` + GPIO_OUT_SET: u30, + padding: u2, + }), + /// GPIO output value clear + GPIO_OUT_CLR: mmio.Mmio(packed struct(u32) { + /// Perform an atomic bit-clear on GPIO_OUT, i.e. `GPIO_OUT &= ~wdata` + GPIO_OUT_CLR: u30, + padding: u2, + }), + /// GPIO output value XOR + GPIO_OUT_XOR: mmio.Mmio(packed struct(u32) { + /// Perform an atomic bitwise XOR on GPIO_OUT, i.e. `GPIO_OUT ^= wdata` + GPIO_OUT_XOR: u30, + padding: u2, + }), + /// GPIO output enable + GPIO_OE: mmio.Mmio(packed struct(u32) { + /// Set output enable (1/0 -> output/input) for GPIO0...29. + /// Reading back gives the last value written. + /// If core 0 and core 1 both write to GPIO_OE simultaneously (or to a SET/CLR/XOR alias), + /// the result is as though the write from core 0 took place first, + /// and the write from core 1 was then applied to that intermediate result. + GPIO_OE: u30, + padding: u2, + }), + /// GPIO output enable set + GPIO_OE_SET: mmio.Mmio(packed struct(u32) { + /// Perform an atomic bit-set on GPIO_OE, i.e. `GPIO_OE |= wdata` + GPIO_OE_SET: u30, + padding: u2, + }), + /// GPIO output enable clear + GPIO_OE_CLR: mmio.Mmio(packed struct(u32) { + /// Perform an atomic bit-clear on GPIO_OE, i.e. `GPIO_OE &= ~wdata` + GPIO_OE_CLR: u30, + padding: u2, + }), + /// GPIO output enable XOR + GPIO_OE_XOR: mmio.Mmio(packed struct(u32) { + /// Perform an atomic bitwise XOR on GPIO_OE, i.e. `GPIO_OE ^= wdata` + GPIO_OE_XOR: u30, + padding: u2, + }), + /// QSPI output value + GPIO_HI_OUT: mmio.Mmio(packed struct(u32) { + /// Set output level (1/0 -> high/low) for QSPI IO0...5. + /// Reading back gives the last value written, NOT the input value from the pins. + /// If core 0 and core 1 both write to GPIO_HI_OUT simultaneously (or to a SET/CLR/XOR alias), + /// the result is as though the write from core 0 took place first, + /// and the write from core 1 was then applied to that intermediate result. + GPIO_HI_OUT: u6, + padding: u26, + }), + /// QSPI output value set + GPIO_HI_OUT_SET: mmio.Mmio(packed struct(u32) { + /// Perform an atomic bit-set on GPIO_HI_OUT, i.e. `GPIO_HI_OUT |= wdata` + GPIO_HI_OUT_SET: u6, + padding: u26, + }), + /// QSPI output value clear + GPIO_HI_OUT_CLR: mmio.Mmio(packed struct(u32) { + /// Perform an atomic bit-clear on GPIO_HI_OUT, i.e. `GPIO_HI_OUT &= ~wdata` + GPIO_HI_OUT_CLR: u6, + padding: u26, + }), + /// QSPI output value XOR + GPIO_HI_OUT_XOR: mmio.Mmio(packed struct(u32) { + /// Perform an atomic bitwise XOR on GPIO_HI_OUT, i.e. `GPIO_HI_OUT ^= wdata` + GPIO_HI_OUT_XOR: u6, + padding: u26, + }), + /// QSPI output enable + GPIO_HI_OE: mmio.Mmio(packed struct(u32) { + /// Set output enable (1/0 -> output/input) for QSPI IO0...5. + /// Reading back gives the last value written. + /// If core 0 and core 1 both write to GPIO_HI_OE simultaneously (or to a SET/CLR/XOR alias), + /// the result is as though the write from core 0 took place first, + /// and the write from core 1 was then applied to that intermediate result. + GPIO_HI_OE: u6, + padding: u26, + }), + /// QSPI output enable set + GPIO_HI_OE_SET: mmio.Mmio(packed struct(u32) { + /// Perform an atomic bit-set on GPIO_HI_OE, i.e. `GPIO_HI_OE |= wdata` + GPIO_HI_OE_SET: u6, + padding: u26, + }), + /// QSPI output enable clear + GPIO_HI_OE_CLR: mmio.Mmio(packed struct(u32) { + /// Perform an atomic bit-clear on GPIO_HI_OE, i.e. `GPIO_HI_OE &= ~wdata` + GPIO_HI_OE_CLR: u6, + padding: u26, + }), + /// QSPI output enable XOR + GPIO_HI_OE_XOR: mmio.Mmio(packed struct(u32) { + /// Perform an atomic bitwise XOR on GPIO_HI_OE, i.e. `GPIO_HI_OE ^= wdata` + GPIO_HI_OE_XOR: u6, + padding: u26, + }), + /// Status register for inter-core FIFOs (mailboxes). + /// There is one FIFO in the core 0 -> core 1 direction, and one core 1 -> core 0. Both are 32 bits wide and 8 words deep. + /// Core 0 can see the read side of the 1->0 FIFO (RX), and the write side of 0->1 FIFO (TX). + /// Core 1 can see the read side of the 0->1 FIFO (RX), and the write side of 1->0 FIFO (TX). + /// The SIO IRQ for each core is the logical OR of the VLD, WOF and ROE fields of its FIFO_ST register. + FIFO_ST: mmio.Mmio(packed struct(u32) { + /// Value is 1 if this core's RX FIFO is not empty (i.e. if FIFO_RD is valid) + VLD: u1, + /// Value is 1 if this core's TX FIFO is not full (i.e. if FIFO_WR is ready for more data) + RDY: u1, + /// Sticky flag indicating the TX FIFO was written when full. This write was ignored by the FIFO. + WOF: u1, + /// Sticky flag indicating the RX FIFO was read when empty. This read was ignored by the FIFO. + ROE: u1, + padding: u28, + }), + /// Write access to this core's TX FIFO + FIFO_WR: u32, + /// Read access to this core's RX FIFO + FIFO_RD: u32, + /// Spinlock state + /// A bitmap containing the state of all 32 spinlocks (1=locked). + /// Mainly intended for debugging. + SPINLOCK_ST: u32, + /// Divider unsigned dividend + /// Write to the DIVIDEND operand of the divider, i.e. the p in `p / q`. + /// Any operand write starts a new calculation. The results appear in QUOTIENT, REMAINDER. + /// UDIVIDEND/SDIVIDEND are aliases of the same internal register. The U alias starts an + /// unsigned calculation, and the S alias starts a signed calculation. + DIV_UDIVIDEND: u32, + /// Divider unsigned divisor + /// Write to the DIVISOR operand of the divider, i.e. the q in `p / q`. + /// Any operand write starts a new calculation. The results appear in QUOTIENT, REMAINDER. + /// UDIVISOR/SDIVISOR are aliases of the same internal register. The U alias starts an + /// unsigned calculation, and the S alias starts a signed calculation. + DIV_UDIVISOR: u32, + /// Divider signed dividend + /// The same as UDIVIDEND, but starts a signed calculation, rather than unsigned. + DIV_SDIVIDEND: u32, + /// Divider signed divisor + /// The same as UDIVISOR, but starts a signed calculation, rather than unsigned. + DIV_SDIVISOR: u32, + /// Divider result quotient + /// The result of `DIVIDEND / DIVISOR` (division). Contents undefined while CSR_READY is low. + /// For signed calculations, QUOTIENT is negative when the signs of DIVIDEND and DIVISOR differ. + /// This register can be written to directly, for context save/restore purposes. This halts any + /// in-progress calculation and sets the CSR_READY and CSR_DIRTY flags. + /// Reading from QUOTIENT clears the CSR_DIRTY flag, so should read results in the order + /// REMAINDER, QUOTIENT if CSR_DIRTY is used. + DIV_QUOTIENT: u32, + /// Divider result remainder + /// The result of `DIVIDEND % DIVISOR` (modulo). Contents undefined while CSR_READY is low. + /// For signed calculations, REMAINDER is negative only when DIVIDEND is negative. + /// This register can be written to directly, for context save/restore purposes. This halts any + /// in-progress calculation and sets the CSR_READY and CSR_DIRTY flags. + DIV_REMAINDER: u32, + /// Control and status register for divider. + DIV_CSR: mmio.Mmio(packed struct(u32) { + /// Reads as 0 when a calculation is in progress, 1 otherwise. + /// Writing an operand (xDIVIDEND, xDIVISOR) will immediately start a new calculation, no + /// matter if one is already in progress. + /// Writing to a result register will immediately terminate any in-progress calculation + /// and set the READY and DIRTY flags. + READY: u1, + /// Changes to 1 when any register is written, and back to 0 when QUOTIENT is read. + /// Software can use this flag to make save/restore more efficient (skip if not DIRTY). + /// If the flag is used in this way, it's recommended to either read QUOTIENT only, + /// or REMAINDER and then QUOTIENT, to prevent data loss on context switch. + DIRTY: u1, + padding: u30, + }), + reserved128: [4]u8, + /// Read/write access to accumulator 0 + INTERP0_ACCUM0: u32, + /// Read/write access to accumulator 1 + INTERP0_ACCUM1: u32, + /// Read/write access to BASE0 register. + INTERP0_BASE0: u32, + /// Read/write access to BASE1 register. + INTERP0_BASE1: u32, + /// Read/write access to BASE2 register. + INTERP0_BASE2: u32, + /// Read LANE0 result, and simultaneously write lane results to both accumulators (POP). + INTERP0_POP_LANE0: u32, + /// Read LANE1 result, and simultaneously write lane results to both accumulators (POP). + INTERP0_POP_LANE1: u32, + /// Read FULL result, and simultaneously write lane results to both accumulators (POP). + INTERP0_POP_FULL: u32, + /// Read LANE0 result, without altering any internal state (PEEK). + INTERP0_PEEK_LANE0: u32, + /// Read LANE1 result, without altering any internal state (PEEK). + INTERP0_PEEK_LANE1: u32, + /// Read FULL result, without altering any internal state (PEEK). + INTERP0_PEEK_FULL: u32, + /// Control register for lane 0 + INTERP0_CTRL_LANE0: mmio.Mmio(packed struct(u32) { + /// Logical right-shift applied to accumulator before masking + SHIFT: u5, + /// The least-significant bit allowed to pass by the mask (inclusive) + MASK_LSB: u5, + /// The most-significant bit allowed to pass by the mask (inclusive) + /// Setting MSB < LSB may cause chip to turn inside-out + MASK_MSB: u5, + /// If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits + /// before adding to BASE0, and LANE0 PEEK/POP appear extended to 32 bits when read by processor. + SIGNED: u1, + /// If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware. + /// Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass) + CROSS_INPUT: u1, + /// If 1, feed the opposite lane's result into this lane's accumulator on POP. + CROSS_RESULT: u1, + /// If 1, mask + shift is bypassed for LANE0 result. This does not affect FULL result. + ADD_RAW: u1, + /// ORed into bits 29:28 of the lane result presented to the processor on the bus. + /// No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence + /// of pointers into flash or SRAM. + FORCE_MSB: u2, + /// Only present on INTERP0 on each core. If BLEND mode is enabled: + /// - LANE1 result is a linear interpolation between BASE0 and BASE1, controlled + /// by the 8 LSBs of lane 1 shift and mask value (a fractional number between + /// 0 and 255/256ths) + /// - LANE0 result does not have BASE0 added (yields only the 8 LSBs of lane 1 shift+mask value) + /// - FULL result does not have lane 1 shift+mask value added (BASE2 + lane 0 shift+mask) + /// LANE1 SIGNED flag controls whether the interpolation is signed or unsigned. + BLEND: u1, + reserved23: u1, + /// Indicates if any masked-off MSBs in ACCUM0 are set. + OVERF0: u1, + /// Indicates if any masked-off MSBs in ACCUM1 are set. + OVERF1: u1, + /// Set if either OVERF0 or OVERF1 is set. + OVERF: u1, + padding: u6, + }), + /// Control register for lane 1 + INTERP0_CTRL_LANE1: mmio.Mmio(packed struct(u32) { + /// Logical right-shift applied to accumulator before masking + SHIFT: u5, + /// The least-significant bit allowed to pass by the mask (inclusive) + MASK_LSB: u5, + /// The most-significant bit allowed to pass by the mask (inclusive) + /// Setting MSB < LSB may cause chip to turn inside-out + MASK_MSB: u5, + /// If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits + /// before adding to BASE1, and LANE1 PEEK/POP appear extended to 32 bits when read by processor. + SIGNED: u1, + /// If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware. + /// Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass) + CROSS_INPUT: u1, + /// If 1, feed the opposite lane's result into this lane's accumulator on POP. + CROSS_RESULT: u1, + /// If 1, mask + shift is bypassed for LANE1 result. This does not affect FULL result. + ADD_RAW: u1, + /// ORed into bits 29:28 of the lane result presented to the processor on the bus. + /// No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence + /// of pointers into flash or SRAM. + FORCE_MSB: u2, + padding: u11, + }), + /// Values written here are atomically added to ACCUM0 + /// Reading yields lane 0's raw shift and mask value (BASE0 not added). + INTERP0_ACCUM0_ADD: mmio.Mmio(packed struct(u32) { + INTERP0_ACCUM0_ADD: u24, + padding: u8, + }), + /// Values written here are atomically added to ACCUM1 + /// Reading yields lane 1's raw shift and mask value (BASE1 not added). + INTERP0_ACCUM1_ADD: mmio.Mmio(packed struct(u32) { + INTERP0_ACCUM1_ADD: u24, + padding: u8, + }), + /// On write, the lower 16 bits go to BASE0, upper bits to BASE1 simultaneously. + /// Each half is sign-extended to 32 bits if that lane's SIGNED flag is set. + INTERP0_BASE_1AND0: u32, + /// Read/write access to accumulator 0 + INTERP1_ACCUM0: u32, + /// Read/write access to accumulator 1 + INTERP1_ACCUM1: u32, + /// Read/write access to BASE0 register. + INTERP1_BASE0: u32, + /// Read/write access to BASE1 register. + INTERP1_BASE1: u32, + /// Read/write access to BASE2 register. + INTERP1_BASE2: u32, + /// Read LANE0 result, and simultaneously write lane results to both accumulators (POP). + INTERP1_POP_LANE0: u32, + /// Read LANE1 result, and simultaneously write lane results to both accumulators (POP). + INTERP1_POP_LANE1: u32, + /// Read FULL result, and simultaneously write lane results to both accumulators (POP). + INTERP1_POP_FULL: u32, + /// Read LANE0 result, without altering any internal state (PEEK). + INTERP1_PEEK_LANE0: u32, + /// Read LANE1 result, without altering any internal state (PEEK). + INTERP1_PEEK_LANE1: u32, + /// Read FULL result, without altering any internal state (PEEK). + INTERP1_PEEK_FULL: u32, + /// Control register for lane 0 + INTERP1_CTRL_LANE0: mmio.Mmio(packed struct(u32) { + /// Logical right-shift applied to accumulator before masking + SHIFT: u5, + /// The least-significant bit allowed to pass by the mask (inclusive) + MASK_LSB: u5, + /// The most-significant bit allowed to pass by the mask (inclusive) + /// Setting MSB < LSB may cause chip to turn inside-out + MASK_MSB: u5, + /// If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits + /// before adding to BASE0, and LANE0 PEEK/POP appear extended to 32 bits when read by processor. + SIGNED: u1, + /// If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware. + /// Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass) + CROSS_INPUT: u1, + /// If 1, feed the opposite lane's result into this lane's accumulator on POP. + CROSS_RESULT: u1, + /// If 1, mask + shift is bypassed for LANE0 result. This does not affect FULL result. + ADD_RAW: u1, + /// ORed into bits 29:28 of the lane result presented to the processor on the bus. + /// No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence + /// of pointers into flash or SRAM. + FORCE_MSB: u2, + reserved22: u1, + /// Only present on INTERP1 on each core. If CLAMP mode is enabled: + /// - LANE0 result is shifted and masked ACCUM0, clamped by a lower bound of + /// BASE0 and an upper bound of BASE1. + /// - Signedness of these comparisons is determined by LANE0_CTRL_SIGNED + CLAMP: u1, + /// Indicates if any masked-off MSBs in ACCUM0 are set. + OVERF0: u1, + /// Indicates if any masked-off MSBs in ACCUM1 are set. + OVERF1: u1, + /// Set if either OVERF0 or OVERF1 is set. + OVERF: u1, + padding: u6, + }), + /// Control register for lane 1 + INTERP1_CTRL_LANE1: mmio.Mmio(packed struct(u32) { + /// Logical right-shift applied to accumulator before masking + SHIFT: u5, + /// The least-significant bit allowed to pass by the mask (inclusive) + MASK_LSB: u5, + /// The most-significant bit allowed to pass by the mask (inclusive) + /// Setting MSB < LSB may cause chip to turn inside-out + MASK_MSB: u5, + /// If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits + /// before adding to BASE1, and LANE1 PEEK/POP appear extended to 32 bits when read by processor. + SIGNED: u1, + /// If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware. + /// Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass) + CROSS_INPUT: u1, + /// If 1, feed the opposite lane's result into this lane's accumulator on POP. + CROSS_RESULT: u1, + /// If 1, mask + shift is bypassed for LANE1 result. This does not affect FULL result. + ADD_RAW: u1, + /// ORed into bits 29:28 of the lane result presented to the processor on the bus. + /// No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence + /// of pointers into flash or SRAM. + FORCE_MSB: u2, + padding: u11, + }), + /// Values written here are atomically added to ACCUM0 + /// Reading yields lane 0's raw shift and mask value (BASE0 not added). + INTERP1_ACCUM0_ADD: mmio.Mmio(packed struct(u32) { + INTERP1_ACCUM0_ADD: u24, + padding: u8, + }), + /// Values written here are atomically added to ACCUM1 + /// Reading yields lane 1's raw shift and mask value (BASE1 not added). + INTERP1_ACCUM1_ADD: mmio.Mmio(packed struct(u32) { + INTERP1_ACCUM1_ADD: u24, + padding: u8, + }), + /// On write, the lower 16 bits go to BASE0, upper bits to BASE1 simultaneously. + /// Each half is sign-extended to 32 bits if that lane's SIGNED flag is set. + INTERP1_BASE_1AND0: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK0: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK1: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK2: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK3: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK4: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK5: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK6: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK7: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK8: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK9: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK10: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK11: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK12: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK13: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK14: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK15: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK16: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK17: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK18: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK19: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK20: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK21: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK22: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK23: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK24: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK25: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK26: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK27: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK28: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK29: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK30: u32, + /// Reading from a spinlock address will: + /// - Return 0 if lock is already locked + /// - Otherwise return nonzero, and simultaneously claim the lock + /// Writing (any value) releases the lock. + /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + /// The value returned on success is 0x1 << lock number. + SPINLOCK31: u32, + }; + + pub const SPI0 = extern struct { + /// Control register 0, SSPCR0 on page 3-4 + SSPCR0: mmio.Mmio(packed struct(u32) { + /// Data Size Select: 0000 Reserved, undefined operation. 0001 Reserved, undefined operation. 0010 Reserved, undefined operation. 0011 4-bit data. 0100 5-bit data. 0101 6-bit data. 0110 7-bit data. 0111 8-bit data. 1000 9-bit data. 1001 10-bit data. 1010 11-bit data. 1011 12-bit data. 1100 13-bit data. 1101 14-bit data. 1110 15-bit data. 1111 16-bit data. + DSS: u4, + /// Frame format: 00 Motorola SPI frame format. 01 TI synchronous serial frame format. 10 National Microwire frame format. 11 Reserved, undefined operation. + FRF: u2, + /// SSPCLKOUT polarity, applicable to Motorola SPI frame format only. See Motorola SPI frame format on page 2-10. + SPO: u1, + /// SSPCLKOUT phase, applicable to Motorola SPI frame format only. See Motorola SPI frame format on page 2-10. + SPH: u1, + /// Serial clock rate. The value SCR is used to generate the transmit and receive bit rate of the PrimeCell SSP. The bit rate is: F SSPCLK CPSDVSR x (1+SCR) where CPSDVSR is an even value from 2-254, programmed through the SSPCPSR register and SCR is a value from 0-255. + SCR: u8, + padding: u16, + }), + /// Control register 1, SSPCR1 on page 3-5 + SSPCR1: mmio.Mmio(packed struct(u32) { + /// Loop back mode: 0 Normal serial port operation enabled. 1 Output of transmit serial shifter is connected to input of receive serial shifter internally. + LBM: u1, + /// Synchronous serial port enable: 0 SSP operation disabled. 1 SSP operation enabled. + SSE: u1, + /// Master or slave mode select. This bit can be modified only when the PrimeCell SSP is disabled, SSE=0: 0 Device configured as master, default. 1 Device configured as slave. + MS: u1, + /// Slave-mode output disable. This bit is relevant only in the slave mode, MS=1. In multiple-slave systems, it is possible for an PrimeCell SSP master to broadcast a message to all slaves in the system while ensuring that only one slave drives data onto its serial output line. In such systems the RXD lines from multiple slaves could be tied together. To operate in such systems, the SOD bit can be set if the PrimeCell SSP slave is not supposed to drive the SSPTXD line: 0 SSP can drive the SSPTXD output in slave mode. 1 SSP must not drive the SSPTXD output in slave mode. + SOD: u1, + padding: u28, + }), + /// Data register, SSPDR on page 3-6 + SSPDR: mmio.Mmio(packed struct(u32) { + /// Transmit/Receive FIFO: Read Receive FIFO. Write Transmit FIFO. You must right-justify data when the PrimeCell SSP is programmed for a data size that is less than 16 bits. Unused bits at the top are ignored by transmit logic. The receive logic automatically right-justifies. + DATA: u16, + padding: u16, + }), + /// Status register, SSPSR on page 3-7 + SSPSR: mmio.Mmio(packed struct(u32) { + /// Transmit FIFO empty, RO: 0 Transmit FIFO is not empty. 1 Transmit FIFO is empty. + TFE: u1, + /// Transmit FIFO not full, RO: 0 Transmit FIFO is full. 1 Transmit FIFO is not full. + TNF: u1, + /// Receive FIFO not empty, RO: 0 Receive FIFO is empty. 1 Receive FIFO is not empty. + RNE: u1, + /// Receive FIFO full, RO: 0 Receive FIFO is not full. 1 Receive FIFO is full. + RFF: u1, + /// PrimeCell SSP busy flag, RO: 0 SSP is idle. 1 SSP is currently transmitting and/or receiving a frame or the transmit FIFO is not empty. + BSY: u1, + padding: u27, + }), + /// Clock prescale register, SSPCPSR on page 3-8 + SSPCPSR: mmio.Mmio(packed struct(u32) { + /// Clock prescale divisor. Must be an even number from 2-254, depending on the frequency of SSPCLK. The least significant bit always returns zero on reads. + CPSDVSR: u8, + padding: u24, + }), + /// Interrupt mask set or clear register, SSPIMSC on page 3-9 + SSPIMSC: mmio.Mmio(packed struct(u32) { + /// Receive overrun interrupt mask: 0 Receive FIFO written to while full condition interrupt is masked. 1 Receive FIFO written to while full condition interrupt is not masked. + RORIM: u1, + /// Receive timeout interrupt mask: 0 Receive FIFO not empty and no read prior to timeout period interrupt is masked. 1 Receive FIFO not empty and no read prior to timeout period interrupt is not masked. + RTIM: u1, + /// Receive FIFO interrupt mask: 0 Receive FIFO half full or less condition interrupt is masked. 1 Receive FIFO half full or less condition interrupt is not masked. + RXIM: u1, + /// Transmit FIFO interrupt mask: 0 Transmit FIFO half empty or less condition interrupt is masked. 1 Transmit FIFO half empty or less condition interrupt is not masked. + TXIM: u1, + padding: u28, + }), + /// Raw interrupt status register, SSPRIS on page 3-10 + SSPRIS: mmio.Mmio(packed struct(u32) { + /// Gives the raw interrupt state, prior to masking, of the SSPRORINTR interrupt + RORRIS: u1, + /// Gives the raw interrupt state, prior to masking, of the SSPRTINTR interrupt + RTRIS: u1, + /// Gives the raw interrupt state, prior to masking, of the SSPRXINTR interrupt + RXRIS: u1, + /// Gives the raw interrupt state, prior to masking, of the SSPTXINTR interrupt + TXRIS: u1, + padding: u28, + }), + /// Masked interrupt status register, SSPMIS on page 3-11 + SSPMIS: mmio.Mmio(packed struct(u32) { + /// Gives the receive over run masked interrupt status, after masking, of the SSPRORINTR interrupt + RORMIS: u1, + /// Gives the receive timeout masked interrupt state, after masking, of the SSPRTINTR interrupt + RTMIS: u1, + /// Gives the receive FIFO masked interrupt state, after masking, of the SSPRXINTR interrupt + RXMIS: u1, + /// Gives the transmit FIFO masked interrupt state, after masking, of the SSPTXINTR interrupt + TXMIS: u1, + padding: u28, + }), + /// Interrupt clear register, SSPICR on page 3-11 + SSPICR: mmio.Mmio(packed struct(u32) { + /// Clears the SSPRORINTR interrupt + RORIC: u1, + /// Clears the SSPRTINTR interrupt + RTIC: u1, + padding: u30, + }), + /// DMA control register, SSPDMACR on page 3-12 + SSPDMACR: mmio.Mmio(packed struct(u32) { + /// Receive DMA Enable. If this bit is set to 1, DMA for the receive FIFO is enabled. + RXDMAE: u1, + /// Transmit DMA Enable. If this bit is set to 1, DMA for the transmit FIFO is enabled. + TXDMAE: u1, + padding: u30, + }), + reserved4064: [4024]u8, + /// Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + SSPPERIPHID0: mmio.Mmio(packed struct(u32) { + /// These bits read back as 0x22 + PARTNUMBER0: u8, + padding: u24, + }), + /// Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + SSPPERIPHID1: mmio.Mmio(packed struct(u32) { + /// These bits read back as 0x0 + PARTNUMBER1: u4, + /// These bits read back as 0x1 + DESIGNER0: u4, + padding: u24, + }), + /// Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + SSPPERIPHID2: mmio.Mmio(packed struct(u32) { + /// These bits read back as 0x4 + DESIGNER1: u4, + /// These bits return the peripheral revision + REVISION: u4, + padding: u24, + }), + /// Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + SSPPERIPHID3: mmio.Mmio(packed struct(u32) { + /// These bits read back as 0x00 + CONFIGURATION: u8, + padding: u24, + }), + /// PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + SSPPCELLID0: mmio.Mmio(packed struct(u32) { + /// These bits read back as 0x0D + SSPPCELLID0: u8, + padding: u24, + }), + /// PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + SSPPCELLID1: mmio.Mmio(packed struct(u32) { + /// These bits read back as 0xF0 + SSPPCELLID1: u8, + padding: u24, + }), + /// PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + SSPPCELLID2: mmio.Mmio(packed struct(u32) { + /// These bits read back as 0x05 + SSPPCELLID2: u8, + padding: u24, + }), + /// PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + SSPPCELLID3: mmio.Mmio(packed struct(u32) { + /// These bits read back as 0xB1 + SSPPCELLID3: u8, + padding: u24, + }), + }; + + /// USB FS/LS controller device registers + pub const USBCTRL_REGS = extern struct { + /// Device address and endpoint control + ADDR_ENDP: mmio.Mmio(packed struct(u32) { + /// In device mode, the address that the device should respond to. Set in response to a SET_ADDR setup packet from the host. In host mode set to the address of the device to communicate with. + ADDRESS: u7, + reserved16: u9, + /// Device endpoint to send data to. Only valid for HOST mode. + ENDPOINT: u4, + padding: u12, + }), + /// Interrupt endpoint 1. Only valid for HOST mode. + ADDR_ENDP1: mmio.Mmio(packed struct(u32) { + /// Device address + ADDRESS: u7, + reserved16: u9, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved25: u5, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding: u5, + }), + /// Interrupt endpoint 2. Only valid for HOST mode. + ADDR_ENDP2: mmio.Mmio(packed struct(u32) { + /// Device address + ADDRESS: u7, + reserved16: u9, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved25: u5, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding: u5, + }), + /// Interrupt endpoint 3. Only valid for HOST mode. + ADDR_ENDP3: mmio.Mmio(packed struct(u32) { + /// Device address + ADDRESS: u7, + reserved16: u9, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved25: u5, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding: u5, + }), + /// Interrupt endpoint 4. Only valid for HOST mode. + ADDR_ENDP4: mmio.Mmio(packed struct(u32) { + /// Device address + ADDRESS: u7, + reserved16: u9, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved25: u5, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding: u5, + }), + /// Interrupt endpoint 5. Only valid for HOST mode. + ADDR_ENDP5: mmio.Mmio(packed struct(u32) { + /// Device address + ADDRESS: u7, + reserved16: u9, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved25: u5, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding: u5, + }), + /// Interrupt endpoint 6. Only valid for HOST mode. + ADDR_ENDP6: mmio.Mmio(packed struct(u32) { + /// Device address + ADDRESS: u7, + reserved16: u9, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved25: u5, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding: u5, + }), + /// Interrupt endpoint 7. Only valid for HOST mode. + ADDR_ENDP7: mmio.Mmio(packed struct(u32) { + /// Device address + ADDRESS: u7, + reserved16: u9, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved25: u5, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding: u5, + }), + /// Interrupt endpoint 8. Only valid for HOST mode. + ADDR_ENDP8: mmio.Mmio(packed struct(u32) { + /// Device address + ADDRESS: u7, + reserved16: u9, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved25: u5, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding: u5, + }), + /// Interrupt endpoint 9. Only valid for HOST mode. + ADDR_ENDP9: mmio.Mmio(packed struct(u32) { + /// Device address + ADDRESS: u7, + reserved16: u9, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved25: u5, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding: u5, + }), + /// Interrupt endpoint 10. Only valid for HOST mode. + ADDR_ENDP10: mmio.Mmio(packed struct(u32) { + /// Device address + ADDRESS: u7, + reserved16: u9, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved25: u5, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding: u5, + }), + /// Interrupt endpoint 11. Only valid for HOST mode. + ADDR_ENDP11: mmio.Mmio(packed struct(u32) { + /// Device address + ADDRESS: u7, + reserved16: u9, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved25: u5, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding: u5, + }), + /// Interrupt endpoint 12. Only valid for HOST mode. + ADDR_ENDP12: mmio.Mmio(packed struct(u32) { + /// Device address + ADDRESS: u7, + reserved16: u9, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved25: u5, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding: u5, + }), + /// Interrupt endpoint 13. Only valid for HOST mode. + ADDR_ENDP13: mmio.Mmio(packed struct(u32) { + /// Device address + ADDRESS: u7, + reserved16: u9, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved25: u5, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding: u5, + }), + /// Interrupt endpoint 14. Only valid for HOST mode. + ADDR_ENDP14: mmio.Mmio(packed struct(u32) { + /// Device address + ADDRESS: u7, + reserved16: u9, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved25: u5, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding: u5, + }), + /// Interrupt endpoint 15. Only valid for HOST mode. + ADDR_ENDP15: mmio.Mmio(packed struct(u32) { + /// Device address + ADDRESS: u7, + reserved16: u9, + /// Endpoint number of the interrupt endpoint + ENDPOINT: u4, + reserved25: u5, + /// Direction of the interrupt endpoint. In=0, Out=1 + INTEP_DIR: u1, + /// Interrupt EP requires preamble (is a low speed device on a full speed hub) + INTEP_PREAMBLE: u1, + padding: u5, + }), + /// Main control register + MAIN_CTRL: mmio.Mmio(packed struct(u32) { + /// Enable controller + CONTROLLER_EN: u1, + /// Device mode = 0, Host mode = 1 + HOST_NDEVICE: u1, + reserved31: u29, + /// Reduced timings for simulation + SIM_TIMING: u1, + }), + /// Set the SOF (Start of Frame) frame number in the host controller. The SOF packet is sent every 1ms and the host will increment the frame number by 1 each time. + SOF_WR: mmio.Mmio(packed struct(u32) { + COUNT: u11, + padding: u21, + }), + /// Read the last SOF (Start of Frame) frame number seen. In device mode the last SOF received from the host. In host mode the last SOF sent by the host. + SOF_RD: mmio.Mmio(packed struct(u32) { + COUNT: u11, + padding: u21, + }), + /// SIE control register + SIE_CTRL: mmio.Mmio(packed struct(u32) { + /// Host: Start transaction + START_TRANS: u1, + /// Host: Send Setup packet + SEND_SETUP: u1, + /// Host: Send transaction (OUT from host) + SEND_DATA: u1, + /// Host: Receive transaction (IN to host) + RECEIVE_DATA: u1, + /// Host: Stop transaction + STOP_TRANS: u1, + reserved6: u1, + /// Host: Preable enable for LS device on FS hub + PREAMBLE_EN: u1, + reserved8: u1, + /// Host: Delay packet(s) until after SOF + SOF_SYNC: u1, + /// Host: Enable SOF generation (for full speed bus) + SOF_EN: u1, + /// Host: Enable keep alive packet (for low speed bus) + KEEP_ALIVE_EN: u1, + /// Host: Enable VBUS + VBUS_EN: u1, + /// Device: Remote wakeup. Device can initiate its own resume after suspend. + RESUME: u1, + /// Host: Reset bus + RESET_BUS: u1, + reserved15: u1, + /// Host: Enable pull down resistors + PULLDOWN_EN: u1, + /// Device: Enable pull up resistor + PULLUP_EN: u1, + /// Device: Pull-up strength (0=1K2, 1=2k3) + RPU_OPT: u1, + /// Power down bus transceiver + TRANSCEIVER_PD: u1, + reserved24: u5, + /// Direct control of DM + DIRECT_DM: u1, + /// Direct control of DP + DIRECT_DP: u1, + /// Direct bus drive enable + DIRECT_EN: u1, + /// Device: Set bit in EP_STATUS_STALL_NAK when EP0 sends a NAK + EP0_INT_NAK: u1, + /// Device: Set bit in BUFF_STATUS for every 2 buffers completed on EP0 + EP0_INT_2BUF: u1, + /// Device: Set bit in BUFF_STATUS for every buffer completed on EP0 + EP0_INT_1BUF: u1, + /// Device: EP0 single buffered = 0, double buffered = 1 + EP0_DOUBLE_BUF: u1, + /// Device: Set bit in EP_STATUS_STALL_NAK when EP0 sends a STALL + EP0_INT_STALL: u1, + }), + /// SIE status register + SIE_STATUS: mmio.Mmio(packed struct(u32) { + /// Device: VBUS Detected + VBUS_DETECTED: u1, + reserved2: u1, + /// USB bus line state + LINE_STATE: u2, + /// Bus in suspended state. Valid for device and host. Host and device will go into suspend if neither Keep Alive / SOF frames are enabled. + SUSPENDED: u1, + reserved8: u3, + /// Host: device speed. Disconnected = 00, LS = 01, FS = 10 + SPEED: u2, + /// VBUS over current detected + VBUS_OVER_CURR: u1, + /// Host: Device has initiated a remote resume. Device: host has initiated a resume. + RESUME: u1, + reserved16: u4, + /// Device: connected + CONNECTED: u1, + /// Device: Setup packet received + SETUP_REC: u1, + /// Transaction complete. + /// Raised by device if: + /// * An IN or OUT packet is sent with the `LAST_BUFF` bit set in the buffer control register + /// Raised by host if: + /// * A setup packet is sent when no data in or data out transaction follows * An IN packet is received and the `LAST_BUFF` bit is set in the buffer control register * An IN packet is received with zero length * An OUT packet is sent and the `LAST_BUFF` bit is set + TRANS_COMPLETE: u1, + /// Device: bus reset received + BUS_RESET: u1, + reserved24: u4, + /// CRC Error. Raised by the Serial RX engine. + CRC_ERROR: u1, + /// Bit Stuff Error. Raised by the Serial RX engine. + BIT_STUFF_ERROR: u1, + /// RX overflow is raised by the Serial RX engine if the incoming data is too fast. + RX_OVERFLOW: u1, + /// RX timeout is raised by both the host and device if an ACK is not received in the maximum time specified by the USB spec. + RX_TIMEOUT: u1, + /// Host: NAK received + NAK_REC: u1, + /// Host: STALL received + STALL_REC: u1, + /// ACK received. Raised by both host and device. + ACK_REC: u1, + /// Data Sequence Error. + /// The device can raise a sequence error in the following conditions: + /// * A SETUP packet is received followed by a DATA1 packet (data phase should always be DATA0) * An OUT packet is received from the host but doesn't match the data pid in the buffer control register read from DPSRAM + /// The host can raise a data sequence error in the following conditions: + /// * An IN packet from the device has the wrong data PID + DATA_SEQ_ERROR: u1, + }), + /// interrupt endpoint control register + INT_EP_CTRL: mmio.Mmio(packed struct(u32) { + reserved1: u1, + /// Host: Enable interrupt endpoint 1 -> 15 + INT_EP_ACTIVE: u15, + padding: u16, + }), + /// Buffer status register. A bit set here indicates that a buffer has completed on the endpoint (if the buffer interrupt is enabled). It is possible for 2 buffers to be completed, so clearing the buffer status bit may instantly re set it on the next clock cycle. + BUFF_STATUS: mmio.Mmio(packed struct(u32) { + EP0_IN: u1, + EP0_OUT: u1, + EP1_IN: u1, + EP1_OUT: u1, + EP2_IN: u1, + EP2_OUT: u1, + EP3_IN: u1, + EP3_OUT: u1, + EP4_IN: u1, + EP4_OUT: u1, + EP5_IN: u1, + EP5_OUT: u1, + EP6_IN: u1, + EP6_OUT: u1, + EP7_IN: u1, + EP7_OUT: u1, + EP8_IN: u1, + EP8_OUT: u1, + EP9_IN: u1, + EP9_OUT: u1, + EP10_IN: u1, + EP10_OUT: u1, + EP11_IN: u1, + EP11_OUT: u1, + EP12_IN: u1, + EP12_OUT: u1, + EP13_IN: u1, + EP13_OUT: u1, + EP14_IN: u1, + EP14_OUT: u1, + EP15_IN: u1, + EP15_OUT: u1, + }), + /// Which of the double buffers should be handled. Only valid if using an interrupt per buffer (i.e. not per 2 buffers). Not valid for host interrupt endpoint polling because they are only single buffered. + BUFF_CPU_SHOULD_HANDLE: mmio.Mmio(packed struct(u32) { + EP0_IN: u1, + EP0_OUT: u1, + EP1_IN: u1, + EP1_OUT: u1, + EP2_IN: u1, + EP2_OUT: u1, + EP3_IN: u1, + EP3_OUT: u1, + EP4_IN: u1, + EP4_OUT: u1, + EP5_IN: u1, + EP5_OUT: u1, + EP6_IN: u1, + EP6_OUT: u1, + EP7_IN: u1, + EP7_OUT: u1, + EP8_IN: u1, + EP8_OUT: u1, + EP9_IN: u1, + EP9_OUT: u1, + EP10_IN: u1, + EP10_OUT: u1, + EP11_IN: u1, + EP11_OUT: u1, + EP12_IN: u1, + EP12_OUT: u1, + EP13_IN: u1, + EP13_OUT: u1, + EP14_IN: u1, + EP14_OUT: u1, + EP15_IN: u1, + EP15_OUT: u1, + }), + /// Device only: Can be set to ignore the buffer control register for this endpoint in case you would like to revoke a buffer. A NAK will be sent for every access to the endpoint until this bit is cleared. A corresponding bit in `EP_ABORT_DONE` is set when it is safe to modify the buffer control register. + EP_ABORT: mmio.Mmio(packed struct(u32) { + EP0_IN: u1, + EP0_OUT: u1, + EP1_IN: u1, + EP1_OUT: u1, + EP2_IN: u1, + EP2_OUT: u1, + EP3_IN: u1, + EP3_OUT: u1, + EP4_IN: u1, + EP4_OUT: u1, + EP5_IN: u1, + EP5_OUT: u1, + EP6_IN: u1, + EP6_OUT: u1, + EP7_IN: u1, + EP7_OUT: u1, + EP8_IN: u1, + EP8_OUT: u1, + EP9_IN: u1, + EP9_OUT: u1, + EP10_IN: u1, + EP10_OUT: u1, + EP11_IN: u1, + EP11_OUT: u1, + EP12_IN: u1, + EP12_OUT: u1, + EP13_IN: u1, + EP13_OUT: u1, + EP14_IN: u1, + EP14_OUT: u1, + EP15_IN: u1, + EP15_OUT: u1, + }), + /// Device only: Used in conjunction with `EP_ABORT`. Set once an endpoint is idle so the programmer knows it is safe to modify the buffer control register. + EP_ABORT_DONE: mmio.Mmio(packed struct(u32) { + EP0_IN: u1, + EP0_OUT: u1, + EP1_IN: u1, + EP1_OUT: u1, + EP2_IN: u1, + EP2_OUT: u1, + EP3_IN: u1, + EP3_OUT: u1, + EP4_IN: u1, + EP4_OUT: u1, + EP5_IN: u1, + EP5_OUT: u1, + EP6_IN: u1, + EP6_OUT: u1, + EP7_IN: u1, + EP7_OUT: u1, + EP8_IN: u1, + EP8_OUT: u1, + EP9_IN: u1, + EP9_OUT: u1, + EP10_IN: u1, + EP10_OUT: u1, + EP11_IN: u1, + EP11_OUT: u1, + EP12_IN: u1, + EP12_OUT: u1, + EP13_IN: u1, + EP13_OUT: u1, + EP14_IN: u1, + EP14_OUT: u1, + EP15_IN: u1, + EP15_OUT: u1, + }), + /// Device: this bit must be set in conjunction with the `STALL` bit in the buffer control register to send a STALL on EP0. The device controller clears these bits when a SETUP packet is received because the USB spec requires that a STALL condition is cleared when a SETUP packet is received. + EP_STALL_ARM: mmio.Mmio(packed struct(u32) { + EP0_IN: u1, + EP0_OUT: u1, + padding: u30, + }), + /// Used by the host controller. Sets the wait time in microseconds before trying again if the device replies with a NAK. + NAK_POLL: mmio.Mmio(packed struct(u32) { + /// NAK polling interval for a low speed device + DELAY_LS: u10, + reserved16: u6, + /// NAK polling interval for a full speed device + DELAY_FS: u10, + padding: u6, + }), + /// Device: bits are set when the `IRQ_ON_NAK` or `IRQ_ON_STALL` bits are set. For EP0 this comes from `SIE_CTRL`. For all other endpoints it comes from the endpoint control register. + EP_STATUS_STALL_NAK: mmio.Mmio(packed struct(u32) { + EP0_IN: u1, + EP0_OUT: u1, + EP1_IN: u1, + EP1_OUT: u1, + EP2_IN: u1, + EP2_OUT: u1, + EP3_IN: u1, + EP3_OUT: u1, + EP4_IN: u1, + EP4_OUT: u1, + EP5_IN: u1, + EP5_OUT: u1, + EP6_IN: u1, + EP6_OUT: u1, + EP7_IN: u1, + EP7_OUT: u1, + EP8_IN: u1, + EP8_OUT: u1, + EP9_IN: u1, + EP9_OUT: u1, + EP10_IN: u1, + EP10_OUT: u1, + EP11_IN: u1, + EP11_OUT: u1, + EP12_IN: u1, + EP12_OUT: u1, + EP13_IN: u1, + EP13_OUT: u1, + EP14_IN: u1, + EP14_OUT: u1, + EP15_IN: u1, + EP15_OUT: u1, + }), + /// Where to connect the USB controller. Should be to_phy by default. + USB_MUXING: mmio.Mmio(packed struct(u32) { + TO_PHY: u1, + TO_EXTPHY: u1, + TO_DIGITAL_PAD: u1, + SOFTCON: u1, + padding: u28, + }), + /// Overrides for the power signals in the event that the VBUS signals are not hooked up to GPIO. Set the value of the override and then the override enable to switch over to the override value. + USB_PWR: mmio.Mmio(packed struct(u32) { + VBUS_EN: u1, + VBUS_EN_OVERRIDE_EN: u1, + VBUS_DETECT: u1, + VBUS_DETECT_OVERRIDE_EN: u1, + OVERCURR_DETECT: u1, + OVERCURR_DETECT_EN: u1, + padding: u26, + }), + /// This register allows for direct control of the USB phy. Use in conjunction with usbphy_direct_override register to enable each override bit. + USBPHY_DIRECT: mmio.Mmio(packed struct(u32) { + /// Enable the second DP pull up resistor. 0 - Pull = Rpu2; 1 - Pull = Rpu1 + Rpu2 + DP_PULLUP_HISEL: u1, + /// DP pull up enable + DP_PULLUP_EN: u1, + /// DP pull down enable + DP_PULLDN_EN: u1, + reserved4: u1, + /// Enable the second DM pull up resistor. 0 - Pull = Rpu2; 1 - Pull = Rpu1 + Rpu2 + DM_PULLUP_HISEL: u1, + /// DM pull up enable + DM_PULLUP_EN: u1, + /// DM pull down enable + DM_PULLDN_EN: u1, + reserved8: u1, + /// Output enable. If TX_DIFFMODE=1, OE for DPP/DPM diff pair. 0 - DPP/DPM in Hi-Z state; 1 - DPP/DPM driving + /// If TX_DIFFMODE=0, OE for DPP only. 0 - DPP in Hi-Z state; 1 - DPP driving + TX_DP_OE: u1, + /// Output enable. If TX_DIFFMODE=1, Ignored. + /// If TX_DIFFMODE=0, OE for DPM only. 0 - DPM in Hi-Z state; 1 - DPM driving + TX_DM_OE: u1, + /// Output data. If TX_DIFFMODE=1, Drives DPP/DPM diff pair. TX_DP_OE=1 to enable drive. DPP=TX_DP, DPM=~TX_DP + /// If TX_DIFFMODE=0, Drives DPP only. TX_DP_OE=1 to enable drive. DPP=TX_DP + TX_DP: u1, + /// Output data. TX_DIFFMODE=1, Ignored + /// TX_DIFFMODE=0, Drives DPM only. TX_DM_OE=1 to enable drive. DPM=TX_DM + TX_DM: u1, + /// RX power down override (if override enable is set). 1 = powered down. + RX_PD: u1, + /// TX power down override (if override enable is set). 1 = powered down. + TX_PD: u1, + /// TX_FSSLEW=0: Low speed slew rate + /// TX_FSSLEW=1: Full speed slew rate + TX_FSSLEW: u1, + /// TX_DIFFMODE=0: Single ended mode + /// TX_DIFFMODE=1: Differential drive mode (TX_DM, TX_DM_OE ignored) + TX_DIFFMODE: u1, + /// Differential RX + RX_DD: u1, + /// DPP pin state + RX_DP: u1, + /// DPM pin state + RX_DM: u1, + /// DP overcurrent + DP_OVCN: u1, + /// DM overcurrent + DM_OVCN: u1, + /// DP over voltage + DP_OVV: u1, + /// DM over voltage + DM_OVV: u1, + padding: u9, + }), + /// Override enable for each control in usbphy_direct + USBPHY_DIRECT_OVERRIDE: mmio.Mmio(packed struct(u32) { + DP_PULLUP_HISEL_OVERRIDE_EN: u1, + DM_PULLUP_HISEL_OVERRIDE_EN: u1, + DP_PULLUP_EN_OVERRIDE_EN: u1, + DP_PULLDN_EN_OVERRIDE_EN: u1, + DM_PULLDN_EN_OVERRIDE_EN: u1, + TX_DP_OE_OVERRIDE_EN: u1, + TX_DM_OE_OVERRIDE_EN: u1, + TX_DP_OVERRIDE_EN: u1, + TX_DM_OVERRIDE_EN: u1, + RX_PD_OVERRIDE_EN: u1, + TX_PD_OVERRIDE_EN: u1, + TX_FSSLEW_OVERRIDE_EN: u1, + DM_PULLUP_OVERRIDE_EN: u1, + reserved15: u2, + TX_DIFFMODE_OVERRIDE_EN: u1, + padding: u16, + }), + /// Used to adjust trim values of USB phy pull down resistors. + USBPHY_TRIM: mmio.Mmio(packed struct(u32) { + /// Value to drive to USB PHY + /// DP pulldown resistor trim control + /// Experimental data suggests that the reset value will work, but this register allows adjustment if required + DP_PULLDN_TRIM: u5, + reserved8: u3, + /// Value to drive to USB PHY + /// DM pulldown resistor trim control + /// Experimental data suggests that the reset value will work, but this register allows adjustment if required + DM_PULLDN_TRIM: u5, + padding: u19, + }), + reserved140: [4]u8, + /// Raw Interrupts + INTR: mmio.Mmio(packed struct(u32) { + /// Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED + HOST_CONN_DIS: u1, + /// Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME + HOST_RESUME: u1, + /// Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD + HOST_SOF: u1, + /// Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit. + TRANS_COMPLETE: u1, + /// Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS. + BUFF_STATUS: u1, + /// Source: SIE_STATUS.DATA_SEQ_ERROR + ERROR_DATA_SEQ: u1, + /// Source: SIE_STATUS.RX_TIMEOUT + ERROR_RX_TIMEOUT: u1, + /// Source: SIE_STATUS.RX_OVERFLOW + ERROR_RX_OVERFLOW: u1, + /// Source: SIE_STATUS.BIT_STUFF_ERROR + ERROR_BIT_STUFF: u1, + /// Source: SIE_STATUS.CRC_ERROR + ERROR_CRC: u1, + /// Source: SIE_STATUS.STALL_REC + STALL: u1, + /// Source: SIE_STATUS.VBUS_DETECTED + VBUS_DETECT: u1, + /// Source: SIE_STATUS.BUS_RESET + BUS_RESET: u1, + /// Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED + DEV_CONN_DIS: u1, + /// Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED + DEV_SUSPEND: u1, + /// Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME + DEV_RESUME_FROM_HOST: u1, + /// Device. Source: SIE_STATUS.SETUP_REC + SETUP_REQ: u1, + /// Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD + DEV_SOF: u1, + /// Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. + ABORT_DONE: u1, + /// Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. + EP_STALL_NAK: u1, + padding: u12, + }), + /// Interrupt Enable + INTE: mmio.Mmio(packed struct(u32) { + /// Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED + HOST_CONN_DIS: u1, + /// Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME + HOST_RESUME: u1, + /// Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD + HOST_SOF: u1, + /// Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit. + TRANS_COMPLETE: u1, + /// Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS. + BUFF_STATUS: u1, + /// Source: SIE_STATUS.DATA_SEQ_ERROR + ERROR_DATA_SEQ: u1, + /// Source: SIE_STATUS.RX_TIMEOUT + ERROR_RX_TIMEOUT: u1, + /// Source: SIE_STATUS.RX_OVERFLOW + ERROR_RX_OVERFLOW: u1, + /// Source: SIE_STATUS.BIT_STUFF_ERROR + ERROR_BIT_STUFF: u1, + /// Source: SIE_STATUS.CRC_ERROR + ERROR_CRC: u1, + /// Source: SIE_STATUS.STALL_REC + STALL: u1, + /// Source: SIE_STATUS.VBUS_DETECTED + VBUS_DETECT: u1, + /// Source: SIE_STATUS.BUS_RESET + BUS_RESET: u1, + /// Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED + DEV_CONN_DIS: u1, + /// Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED + DEV_SUSPEND: u1, + /// Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME + DEV_RESUME_FROM_HOST: u1, + /// Device. Source: SIE_STATUS.SETUP_REC + SETUP_REQ: u1, + /// Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD + DEV_SOF: u1, + /// Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. + ABORT_DONE: u1, + /// Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. + EP_STALL_NAK: u1, + padding: u12, + }), + /// Interrupt Force + INTF: mmio.Mmio(packed struct(u32) { + /// Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED + HOST_CONN_DIS: u1, + /// Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME + HOST_RESUME: u1, + /// Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD + HOST_SOF: u1, + /// Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit. + TRANS_COMPLETE: u1, + /// Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS. + BUFF_STATUS: u1, + /// Source: SIE_STATUS.DATA_SEQ_ERROR + ERROR_DATA_SEQ: u1, + /// Source: SIE_STATUS.RX_TIMEOUT + ERROR_RX_TIMEOUT: u1, + /// Source: SIE_STATUS.RX_OVERFLOW + ERROR_RX_OVERFLOW: u1, + /// Source: SIE_STATUS.BIT_STUFF_ERROR + ERROR_BIT_STUFF: u1, + /// Source: SIE_STATUS.CRC_ERROR + ERROR_CRC: u1, + /// Source: SIE_STATUS.STALL_REC + STALL: u1, + /// Source: SIE_STATUS.VBUS_DETECTED + VBUS_DETECT: u1, + /// Source: SIE_STATUS.BUS_RESET + BUS_RESET: u1, + /// Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED + DEV_CONN_DIS: u1, + /// Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED + DEV_SUSPEND: u1, + /// Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME + DEV_RESUME_FROM_HOST: u1, + /// Device. Source: SIE_STATUS.SETUP_REC + SETUP_REQ: u1, + /// Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD + DEV_SOF: u1, + /// Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. + ABORT_DONE: u1, + /// Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. + EP_STALL_NAK: u1, + padding: u12, + }), + /// Interrupt status after masking & forcing + INTS: mmio.Mmio(packed struct(u32) { + /// Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED + HOST_CONN_DIS: u1, + /// Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME + HOST_RESUME: u1, + /// Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD + HOST_SOF: u1, + /// Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit. + TRANS_COMPLETE: u1, + /// Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS. + BUFF_STATUS: u1, + /// Source: SIE_STATUS.DATA_SEQ_ERROR + ERROR_DATA_SEQ: u1, + /// Source: SIE_STATUS.RX_TIMEOUT + ERROR_RX_TIMEOUT: u1, + /// Source: SIE_STATUS.RX_OVERFLOW + ERROR_RX_OVERFLOW: u1, + /// Source: SIE_STATUS.BIT_STUFF_ERROR + ERROR_BIT_STUFF: u1, + /// Source: SIE_STATUS.CRC_ERROR + ERROR_CRC: u1, + /// Source: SIE_STATUS.STALL_REC + STALL: u1, + /// Source: SIE_STATUS.VBUS_DETECTED + VBUS_DETECT: u1, + /// Source: SIE_STATUS.BUS_RESET + BUS_RESET: u1, + /// Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED + DEV_CONN_DIS: u1, + /// Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED + DEV_SUSPEND: u1, + /// Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME + DEV_RESUME_FROM_HOST: u1, + /// Device. Source: SIE_STATUS.SETUP_REC + SETUP_REQ: u1, + /// Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD + DEV_SOF: u1, + /// Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. + ABORT_DONE: u1, + /// Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. + EP_STALL_NAK: u1, + padding: u12, + }), + }; + + /// DW_apb_i2c address block + /// List of configuration constants for the Synopsys I2C hardware (you may see references to these in I2C register header; these are *fixed* values, set at hardware design time): + /// IC_ULTRA_FAST_MODE ................ 0x0 + /// IC_UFM_TBUF_CNT_DEFAULT ........... 0x8 + /// IC_UFM_SCL_LOW_COUNT .............. 0x0008 + /// IC_UFM_SCL_HIGH_COUNT ............. 0x0006 + /// IC_TX_TL .......................... 0x0 + /// IC_TX_CMD_BLOCK ................... 0x1 + /// IC_HAS_DMA ........................ 0x1 + /// IC_HAS_ASYNC_FIFO ................. 0x0 + /// IC_SMBUS_ARP ...................... 0x0 + /// IC_FIRST_DATA_BYTE_STATUS ......... 0x1 + /// IC_INTR_IO ........................ 0x1 + /// IC_MASTER_MODE .................... 0x1 + /// IC_DEFAULT_ACK_GENERAL_CALL ....... 0x1 + /// IC_INTR_POL ....................... 0x1 + /// IC_OPTIONAL_SAR ................... 0x0 + /// IC_DEFAULT_TAR_SLAVE_ADDR ......... 0x055 + /// IC_DEFAULT_SLAVE_ADDR ............. 0x055 + /// IC_DEFAULT_HS_SPKLEN .............. 0x1 + /// IC_FS_SCL_HIGH_COUNT .............. 0x0006 + /// IC_HS_SCL_LOW_COUNT ............... 0x0008 + /// IC_DEVICE_ID_VALUE ................ 0x0 + /// IC_10BITADDR_MASTER ............... 0x0 + /// IC_CLK_FREQ_OPTIMIZATION .......... 0x0 + /// IC_DEFAULT_FS_SPKLEN .............. 0x7 + /// IC_ADD_ENCODED_PARAMS ............. 0x0 + /// IC_DEFAULT_SDA_HOLD ............... 0x000001 + /// IC_DEFAULT_SDA_SETUP .............. 0x64 + /// IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT . 0x0 + /// IC_CLOCK_PERIOD ................... 100 + /// IC_EMPTYFIFO_HOLD_MASTER_EN ....... 1 + /// IC_RESTART_EN ..................... 0x1 + /// IC_TX_CMD_BLOCK_DEFAULT ........... 0x0 + /// IC_BUS_CLEAR_FEATURE .............. 0x0 + /// IC_CAP_LOADING .................... 100 + /// IC_FS_SCL_LOW_COUNT ............... 0x000d + /// APB_DATA_WIDTH .................... 32 + /// IC_SDA_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff + /// IC_SLV_DATA_NACK_ONLY ............. 0x1 + /// IC_10BITADDR_SLAVE ................ 0x0 + /// IC_CLK_TYPE ....................... 0x0 + /// IC_SMBUS_UDID_MSB ................. 0x0 + /// IC_SMBUS_SUSPEND_ALERT ............ 0x0 + /// IC_HS_SCL_HIGH_COUNT .............. 0x0006 + /// IC_SLV_RESTART_DET_EN ............. 0x1 + /// IC_SMBUS .......................... 0x0 + /// IC_OPTIONAL_SAR_DEFAULT ........... 0x0 + /// IC_PERSISTANT_SLV_ADDR_DEFAULT .... 0x0 + /// IC_USE_COUNTS ..................... 0x0 + /// IC_RX_BUFFER_DEPTH ................ 16 + /// IC_SCL_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff + /// IC_RX_FULL_HLD_BUS_EN ............. 0x1 + /// IC_SLAVE_DISABLE .................. 0x1 + /// IC_RX_TL .......................... 0x0 + /// IC_DEVICE_ID ...................... 0x0 + /// IC_HC_COUNT_VALUES ................ 0x0 + /// I2C_DYNAMIC_TAR_UPDATE ............ 0 + /// IC_SMBUS_CLK_LOW_MEXT_DEFAULT ..... 0xffffffff + /// IC_SMBUS_CLK_LOW_SEXT_DEFAULT ..... 0xffffffff + /// IC_HS_MASTER_CODE ................. 0x1 + /// IC_SMBUS_RST_IDLE_CNT_DEFAULT ..... 0xffff + /// IC_SMBUS_UDID_LSB_DEFAULT ......... 0xffffffff + /// IC_SS_SCL_HIGH_COUNT .............. 0x0028 + /// IC_SS_SCL_LOW_COUNT ............... 0x002f + /// IC_MAX_SPEED_MODE ................. 0x2 + /// IC_STAT_FOR_CLK_STRETCH ........... 0x0 + /// IC_STOP_DET_IF_MASTER_ACTIVE ...... 0x0 + /// IC_DEFAULT_UFM_SPKLEN ............. 0x1 + /// IC_TX_BUFFER_DEPTH ................ 16 + pub const I2C0 = extern struct { + /// I2C Control Register. This register can be written only when the DW_apb_i2c is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. + /// Read/Write Access: - bit 10 is read only. - bit 11 is read only - bit 16 is read only - bit 17 is read only - bits 18 and 19 are read only. + IC_CON: mmio.Mmio(packed struct(u32) { + /// This bit controls whether the DW_apb_i2c master is enabled. + /// NOTE: Software should ensure that if this bit is written with '1' then bit 6 should also be written with a '1'. + MASTER_MODE: packed union { + raw: u1, + value: enum(u1) { + /// Master mode is disabled + DISABLED = 0x0, + /// Master mode is enabled + ENABLED = 0x1, + }, + }, + /// These bits control at which speed the DW_apb_i2c operates; its setting is relevant only if one is operating the DW_apb_i2c in master mode. Hardware protects against illegal values being programmed by software. These bits must be programmed appropriately for slave mode also, as it is used to capture correct value of spike filter as per the speed mode. + /// This register should be programmed only with a value in the range of 1 to IC_MAX_SPEED_MODE; otherwise, hardware updates this register with the value of IC_MAX_SPEED_MODE. + /// 1: standard mode (100 kbit/s) + /// 2: fast mode (<=400 kbit/s) or fast mode plus (<=1000Kbit/s) + /// 3: high speed mode (3.4 Mbit/s) + /// Note: This field is not applicable when IC_ULTRA_FAST_MODE=1 + SPEED: packed union { + raw: u2, + value: enum(u2) { + /// Standard Speed mode of operation + STANDARD = 0x1, + /// Fast or Fast Plus mode of operation + FAST = 0x2, + /// High Speed mode of operation + HIGH = 0x3, + _, + }, + }, + /// When acting as a slave, this bit controls whether the DW_apb_i2c responds to 7- or 10-bit addresses. - 0: 7-bit addressing. The DW_apb_i2c ignores transactions that involve 10-bit addressing; for 7-bit addressing, only the lower 7 bits of the IC_SAR register are compared. - 1: 10-bit addressing. The DW_apb_i2c responds to only 10-bit addressing transfers that match the full 10 bits of the IC_SAR register. + IC_10BITADDR_SLAVE: packed union { + raw: u1, + value: enum(u1) { + /// Slave 7Bit addressing + ADDR_7BITS = 0x0, + /// Slave 10Bit addressing + ADDR_10BITS = 0x1, + }, + }, + /// Controls whether the DW_apb_i2c starts its transfers in 7- or 10-bit addressing mode when acting as a master. - 0: 7-bit addressing - 1: 10-bit addressing + IC_10BITADDR_MASTER: packed union { + raw: u1, + value: enum(u1) { + /// Master 7Bit addressing mode + ADDR_7BITS = 0x0, + /// Master 10Bit addressing mode + ADDR_10BITS = 0x1, + }, + }, + /// Determines whether RESTART conditions may be sent when acting as a master. Some older slaves do not support handling RESTART conditions; however, RESTART conditions are used in several DW_apb_i2c operations. When RESTART is disabled, the master is prohibited from performing the following functions: - Sending a START BYTE - Performing any high-speed mode operation - High-speed mode operation - Performing direction changes in combined format mode - Performing a read operation with a 10-bit address By replacing RESTART condition followed by a STOP and a subsequent START condition, split operations are broken down into multiple DW_apb_i2c transfers. If the above operations are performed, it will result in setting bit 6 (TX_ABRT) of the IC_RAW_INTR_STAT register. + /// Reset value: ENABLED + IC_RESTART_EN: packed union { + raw: u1, + value: enum(u1) { + /// Master restart disabled + DISABLED = 0x0, + /// Master restart enabled + ENABLED = 0x1, + }, + }, + /// This bit controls whether I2C has its slave disabled, which means once the presetn signal is applied, then this bit is set and the slave is disabled. + /// If this bit is set (slave is disabled), DW_apb_i2c functions only as a master and does not perform any action that requires a slave. + /// NOTE: Software should ensure that if this bit is written with 0, then bit 0 should also be written with a 0. + IC_SLAVE_DISABLE: packed union { + raw: u1, + value: enum(u1) { + /// Slave mode is enabled + SLAVE_ENABLED = 0x0, + /// Slave mode is disabled + SLAVE_DISABLED = 0x1, + }, + }, + /// In slave mode: - 1'b1: issues the STOP_DET interrupt only when it is addressed. - 1'b0: issues the STOP_DET irrespective of whether it's addressed or not. Reset value: 0x0 + /// NOTE: During a general call address, this slave does not issue the STOP_DET interrupt if STOP_DET_IF_ADDRESSED = 1'b1, even if the slave responds to the general call address by generating ACK. The STOP_DET interrupt is generated only when the transmitted address matches the slave address (SAR). + STOP_DET_IFADDRESSED: packed union { + raw: u1, + value: enum(u1) { + /// slave issues STOP_DET intr always + DISABLED = 0x0, + /// slave issues STOP_DET intr only if addressed + ENABLED = 0x1, + }, + }, + /// This bit controls the generation of the TX_EMPTY interrupt, as described in the IC_RAW_INTR_STAT register. + /// Reset value: 0x0. + TX_EMPTY_CTRL: packed union { + raw: u1, + value: enum(u1) { + /// Default behaviour of TX_EMPTY interrupt + DISABLED = 0x0, + /// Controlled generation of TX_EMPTY interrupt + ENABLED = 0x1, + }, + }, + /// This bit controls whether DW_apb_i2c should hold the bus when the Rx FIFO is physically full to its RX_BUFFER_DEPTH, as described in the IC_RX_FULL_HLD_BUS_EN parameter. + /// Reset value: 0x0. + RX_FIFO_FULL_HLD_CTRL: packed union { + raw: u1, + value: enum(u1) { + /// Overflow when RX_FIFO is full + DISABLED = 0x0, + /// Hold bus when RX_FIFO is full + ENABLED = 0x1, + }, + }, + /// Master issues the STOP_DET interrupt irrespective of whether master is active or not + STOP_DET_IF_MASTER_ACTIVE: u1, + padding: u21, + }), + /// I2C Target Address Register + /// This register is 12 bits wide, and bits 31:12 are reserved. This register can be written to only when IC_ENABLE[0] is set to 0. + /// Note: If the software or application is aware that the DW_apb_i2c is not using the TAR address for the pending commands in the Tx FIFO, then it is possible to update the TAR address even while the Tx FIFO has entries (IC_STATUS[2]= 0). - It is not necessary to perform any write to this register if DW_apb_i2c is enabled as an I2C slave only. + IC_TAR: mmio.Mmio(packed struct(u32) { + /// This is the target address for any master transaction. When transmitting a General Call, these bits are ignored. To generate a START BYTE, the CPU needs to write only once into these bits. + /// If the IC_TAR and IC_SAR are the same, loopback exists but the FIFOs are shared between master and slave, so full loopback is not feasible. Only one direction loopback mode is supported (simplex), not duplex. A master cannot transmit to itself; it can transmit to only a slave. + IC_TAR: u10, + /// If bit 11 (SPECIAL) is set to 1 and bit 13(Device-ID) is set to 0, then this bit indicates whether a General Call or START byte command is to be performed by the DW_apb_i2c. - 0: General Call Address - after issuing a General Call, only writes may be performed. Attempting to issue a read command results in setting bit 6 (TX_ABRT) of the IC_RAW_INTR_STAT register. The DW_apb_i2c remains in General Call mode until the SPECIAL bit value (bit 11) is cleared. - 1: START BYTE Reset value: 0x0 + GC_OR_START: packed union { + raw: u1, + value: enum(u1) { + /// GENERAL_CALL byte transmission + GENERAL_CALL = 0x0, + /// START byte transmission + START_BYTE = 0x1, + }, + }, + /// This bit indicates whether software performs a Device-ID or General Call or START BYTE command. - 0: ignore bit 10 GC_OR_START and use IC_TAR normally - 1: perform special I2C command as specified in Device_ID or GC_OR_START bit Reset value: 0x0 + SPECIAL: packed union { + raw: u1, + value: enum(u1) { + /// Disables programming of GENERAL_CALL or START_BYTE transmission + DISABLED = 0x0, + /// Enables programming of GENERAL_CALL or START_BYTE transmission + ENABLED = 0x1, + }, + }, + padding: u20, + }), + /// I2C Slave Address Register + IC_SAR: mmio.Mmio(packed struct(u32) { + /// The IC_SAR holds the slave address when the I2C is operating as a slave. For 7-bit addressing, only IC_SAR[6:0] is used. + /// This register can be written only when the I2C interface is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. + /// Note: The default values cannot be any of the reserved address locations: that is, 0x00 to 0x07, or 0x78 to 0x7f. The correct operation of the device is not guaranteed if you program the IC_SAR or IC_TAR to a reserved value. Refer to <> for a complete list of these reserved values. + IC_SAR: u10, + padding: u22, + }), + reserved16: [4]u8, + /// I2C Rx/Tx Data Buffer and Command Register; this is the register the CPU writes to when filling the TX FIFO and the CPU reads from when retrieving bytes from RX FIFO. + /// The size of the register changes as follows: + /// Write: - 11 bits when IC_EMPTYFIFO_HOLD_MASTER_EN=1 - 9 bits when IC_EMPTYFIFO_HOLD_MASTER_EN=0 Read: - 12 bits when IC_FIRST_DATA_BYTE_STATUS = 1 - 8 bits when IC_FIRST_DATA_BYTE_STATUS = 0 Note: In order for the DW_apb_i2c to continue acknowledging reads, a read command should be written for every byte that is to be received; otherwise the DW_apb_i2c will stop acknowledging. + IC_DATA_CMD: mmio.Mmio(packed struct(u32) { + /// This register contains the data to be transmitted or received on the I2C bus. If you are writing to this register and want to perform a read, bits 7:0 (DAT) are ignored by the DW_apb_i2c. However, when you read this register, these bits return the value of data received on the DW_apb_i2c interface. + /// Reset value: 0x0 + DAT: u8, + /// This bit controls whether a read or a write is performed. This bit does not control the direction when the DW_apb_i2con acts as a slave. It controls only the direction when it acts as a master. + /// When a command is entered in the TX FIFO, this bit distinguishes the write and read commands. In slave-receiver mode, this bit is a 'don't care' because writes to this register are not required. In slave-transmitter mode, a '0' indicates that the data in IC_DATA_CMD is to be transmitted. + /// When programming this bit, you should remember the following: attempting to perform a read operation after a General Call command has been sent results in a TX_ABRT interrupt (bit 6 of the IC_RAW_INTR_STAT register), unless bit 11 (SPECIAL) in the IC_TAR register has been cleared. If a '1' is written to this bit after receiving a RD_REQ interrupt, then a TX_ABRT interrupt occurs. + /// Reset value: 0x0 + CMD: packed union { + raw: u1, + value: enum(u1) { + /// Master Write Command + WRITE = 0x0, + /// Master Read Command + READ = 0x1, + }, + }, + /// This bit controls whether a STOP is issued after the byte is sent or received. + /// - 1 - STOP is issued after this byte, regardless of whether or not the Tx FIFO is empty. If the Tx FIFO is not empty, the master immediately tries to start a new transfer by issuing a START and arbitrating for the bus. - 0 - STOP is not issued after this byte, regardless of whether or not the Tx FIFO is empty. If the Tx FIFO is not empty, the master continues the current transfer by sending/receiving data bytes according to the value of the CMD bit. If the Tx FIFO is empty, the master holds the SCL line low and stalls the bus until a new command is available in the Tx FIFO. Reset value: 0x0 + STOP: packed union { + raw: u1, + value: enum(u1) { + /// Don't Issue STOP after this command + DISABLE = 0x0, + /// Issue STOP after this command + ENABLE = 0x1, + }, + }, + /// This bit controls whether a RESTART is issued before the byte is sent or received. + /// 1 - If IC_RESTART_EN is 1, a RESTART is issued before the data is sent/received (according to the value of CMD), regardless of whether or not the transfer direction is changing from the previous command; if IC_RESTART_EN is 0, a STOP followed by a START is issued instead. + /// 0 - If IC_RESTART_EN is 1, a RESTART is issued only if the transfer direction is changing from the previous command; if IC_RESTART_EN is 0, a STOP followed by a START is issued instead. + /// Reset value: 0x0 + RESTART: packed union { + raw: u1, + value: enum(u1) { + /// Don't Issue RESTART before this command + DISABLE = 0x0, + /// Issue RESTART before this command + ENABLE = 0x1, + }, + }, + /// Indicates the first data byte received after the address phase for receive transfer in Master receiver or Slave receiver mode. + /// Reset value : 0x0 + /// NOTE: In case of APB_DATA_WIDTH=8, + /// 1. The user has to perform two APB Reads to IC_DATA_CMD in order to get status on 11 bit. + /// 2. In order to read the 11 bit, the user has to perform the first data byte read [7:0] (offset 0x10) and then perform the second read [15:8] (offset 0x11) in order to know the status of 11 bit (whether the data received in previous read is a first data byte or not). + /// 3. The 11th bit is an optional read field, user can ignore 2nd byte read [15:8] (offset 0x11) if not interested in FIRST_DATA_BYTE status. + FIRST_DATA_BYTE: packed union { + raw: u1, + value: enum(u1) { + /// Sequential data byte received + INACTIVE = 0x0, + /// Non sequential data byte received + ACTIVE = 0x1, + }, + }, + padding: u20, + }), + /// Standard Speed I2C Clock SCL High Count Register + IC_SS_SCL_HCNT: mmio.Mmio(packed struct(u32) { + /// This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock high-period count for standard speed. For more information, refer to 'IC_CLK Frequency Configuration'. + /// This register can be written only when the I2C interface is disabled which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. + /// The minimum valid value is 6; hardware prevents values less than this being written, and if attempted results in 6 being set. For designs with APB_DATA_WIDTH = 8, the order of programming is important to ensure the correct operation of the DW_apb_i2c. The lower byte must be programmed first. Then the upper byte is programmed. + /// NOTE: This register must not be programmed to a value higher than 65525, because DW_apb_i2c uses a 16-bit counter to flag an I2C bus idle condition when this counter reaches a value of IC_SS_SCL_HCNT + 10. + IC_SS_SCL_HCNT: u16, + padding: u16, + }), + /// Standard Speed I2C Clock SCL Low Count Register + IC_SS_SCL_LCNT: mmio.Mmio(packed struct(u32) { + /// This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock low period count for standard speed. For more information, refer to 'IC_CLK Frequency Configuration' + /// This register can be written only when the I2C interface is disabled which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. + /// The minimum valid value is 8; hardware prevents values less than this being written, and if attempted, results in 8 being set. For designs with APB_DATA_WIDTH = 8, the order of programming is important to ensure the correct operation of DW_apb_i2c. The lower byte must be programmed first, and then the upper byte is programmed. + IC_SS_SCL_LCNT: u16, + padding: u16, + }), + /// Fast Mode or Fast Mode Plus I2C Clock SCL High Count Register + IC_FS_SCL_HCNT: mmio.Mmio(packed struct(u32) { + /// This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock high-period count for fast mode or fast mode plus. It is used in high-speed mode to send the Master Code and START BYTE or General CALL. For more information, refer to 'IC_CLK Frequency Configuration'. + /// This register goes away and becomes read-only returning 0s if IC_MAX_SPEED_MODE = standard. This register can be written only when the I2C interface is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. + /// The minimum valid value is 6; hardware prevents values less than this being written, and if attempted results in 6 being set. For designs with APB_DATA_WIDTH == 8 the order of programming is important to ensure the correct operation of the DW_apb_i2c. The lower byte must be programmed first. Then the upper byte is programmed. + IC_FS_SCL_HCNT: u16, + padding: u16, + }), + /// Fast Mode or Fast Mode Plus I2C Clock SCL Low Count Register + IC_FS_SCL_LCNT: mmio.Mmio(packed struct(u32) { + /// This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock low period count for fast speed. It is used in high-speed mode to send the Master Code and START BYTE or General CALL. For more information, refer to 'IC_CLK Frequency Configuration'. + /// This register goes away and becomes read-only returning 0s if IC_MAX_SPEED_MODE = standard. + /// This register can be written only when the I2C interface is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. + /// The minimum valid value is 8; hardware prevents values less than this being written, and if attempted results in 8 being set. For designs with APB_DATA_WIDTH = 8 the order of programming is important to ensure the correct operation of the DW_apb_i2c. The lower byte must be programmed first. Then the upper byte is programmed. If the value is less than 8 then the count value gets changed to 8. + IC_FS_SCL_LCNT: u16, + padding: u16, + }), + reserved44: [8]u8, + /// I2C Interrupt Status Register + /// Each bit in this register has a corresponding mask bit in the IC_INTR_MASK register. These bits are cleared by reading the matching interrupt clear register. The unmasked raw versions of these bits are available in the IC_RAW_INTR_STAT register. + IC_INTR_STAT: mmio.Mmio(packed struct(u32) { + /// See IC_RAW_INTR_STAT for a detailed description of R_RX_UNDER bit. + /// Reset value: 0x0 + R_RX_UNDER: packed union { + raw: u1, + value: enum(u1) { + /// RX_UNDER interrupt is inactive + INACTIVE = 0x0, + /// RX_UNDER interrupt is active + ACTIVE = 0x1, + }, + }, + /// See IC_RAW_INTR_STAT for a detailed description of R_RX_OVER bit. + /// Reset value: 0x0 + R_RX_OVER: packed union { + raw: u1, + value: enum(u1) { + /// R_RX_OVER interrupt is inactive + INACTIVE = 0x0, + /// R_RX_OVER interrupt is active + ACTIVE = 0x1, + }, + }, + /// See IC_RAW_INTR_STAT for a detailed description of R_RX_FULL bit. + /// Reset value: 0x0 + R_RX_FULL: packed union { + raw: u1, + value: enum(u1) { + /// R_RX_FULL interrupt is inactive + INACTIVE = 0x0, + /// R_RX_FULL interrupt is active + ACTIVE = 0x1, + }, + }, + /// See IC_RAW_INTR_STAT for a detailed description of R_TX_OVER bit. + /// Reset value: 0x0 + R_TX_OVER: packed union { + raw: u1, + value: enum(u1) { + /// R_TX_OVER interrupt is inactive + INACTIVE = 0x0, + /// R_TX_OVER interrupt is active + ACTIVE = 0x1, + }, + }, + /// See IC_RAW_INTR_STAT for a detailed description of R_TX_EMPTY bit. + /// Reset value: 0x0 + R_TX_EMPTY: packed union { + raw: u1, + value: enum(u1) { + /// R_TX_EMPTY interrupt is inactive + INACTIVE = 0x0, + /// R_TX_EMPTY interrupt is active + ACTIVE = 0x1, + }, + }, + /// See IC_RAW_INTR_STAT for a detailed description of R_RD_REQ bit. + /// Reset value: 0x0 + R_RD_REQ: packed union { + raw: u1, + value: enum(u1) { + /// R_RD_REQ interrupt is inactive + INACTIVE = 0x0, + /// R_RD_REQ interrupt is active + ACTIVE = 0x1, + }, + }, + /// See IC_RAW_INTR_STAT for a detailed description of R_TX_ABRT bit. + /// Reset value: 0x0 + R_TX_ABRT: packed union { + raw: u1, + value: enum(u1) { + /// R_TX_ABRT interrupt is inactive + INACTIVE = 0x0, + /// R_TX_ABRT interrupt is active + ACTIVE = 0x1, + }, + }, + /// See IC_RAW_INTR_STAT for a detailed description of R_RX_DONE bit. + /// Reset value: 0x0 + R_RX_DONE: packed union { + raw: u1, + value: enum(u1) { + /// R_RX_DONE interrupt is inactive + INACTIVE = 0x0, + /// R_RX_DONE interrupt is active + ACTIVE = 0x1, + }, + }, + /// See IC_RAW_INTR_STAT for a detailed description of R_ACTIVITY bit. + /// Reset value: 0x0 + R_ACTIVITY: packed union { + raw: u1, + value: enum(u1) { + /// R_ACTIVITY interrupt is inactive + INACTIVE = 0x0, + /// R_ACTIVITY interrupt is active + ACTIVE = 0x1, + }, + }, + /// See IC_RAW_INTR_STAT for a detailed description of R_STOP_DET bit. + /// Reset value: 0x0 + R_STOP_DET: packed union { + raw: u1, + value: enum(u1) { + /// R_STOP_DET interrupt is inactive + INACTIVE = 0x0, + /// R_STOP_DET interrupt is active + ACTIVE = 0x1, + }, + }, + /// See IC_RAW_INTR_STAT for a detailed description of R_START_DET bit. + /// Reset value: 0x0 + R_START_DET: packed union { + raw: u1, + value: enum(u1) { + /// R_START_DET interrupt is inactive + INACTIVE = 0x0, + /// R_START_DET interrupt is active + ACTIVE = 0x1, + }, + }, + /// See IC_RAW_INTR_STAT for a detailed description of R_GEN_CALL bit. + /// Reset value: 0x0 + R_GEN_CALL: packed union { + raw: u1, + value: enum(u1) { + /// R_GEN_CALL interrupt is inactive + INACTIVE = 0x0, + /// R_GEN_CALL interrupt is active + ACTIVE = 0x1, + }, + }, + /// See IC_RAW_INTR_STAT for a detailed description of R_RESTART_DET bit. + /// Reset value: 0x0 + R_RESTART_DET: packed union { + raw: u1, + value: enum(u1) { + /// R_RESTART_DET interrupt is inactive + INACTIVE = 0x0, + /// R_RESTART_DET interrupt is active + ACTIVE = 0x1, + }, + }, + padding: u19, + }), + /// I2C Interrupt Mask Register. + /// These bits mask their corresponding interrupt status bits. This register is active low; a value of 0 masks the interrupt, whereas a value of 1 unmasks the interrupt. + IC_INTR_MASK: mmio.Mmio(packed struct(u32) { + /// This bit masks the R_RX_UNDER interrupt in IC_INTR_STAT register. + /// Reset value: 0x1 + M_RX_UNDER: packed union { + raw: u1, + value: enum(u1) { + /// RX_UNDER interrupt is masked + ENABLED = 0x0, + /// RX_UNDER interrupt is unmasked + DISABLED = 0x1, + }, + }, + /// This bit masks the R_RX_OVER interrupt in IC_INTR_STAT register. + /// Reset value: 0x1 + M_RX_OVER: packed union { + raw: u1, + value: enum(u1) { + /// RX_OVER interrupt is masked + ENABLED = 0x0, + /// RX_OVER interrupt is unmasked + DISABLED = 0x1, + }, + }, + /// This bit masks the R_RX_FULL interrupt in IC_INTR_STAT register. + /// Reset value: 0x1 + M_RX_FULL: packed union { + raw: u1, + value: enum(u1) { + /// RX_FULL interrupt is masked + ENABLED = 0x0, + /// RX_FULL interrupt is unmasked + DISABLED = 0x1, + }, + }, + /// This bit masks the R_TX_OVER interrupt in IC_INTR_STAT register. + /// Reset value: 0x1 + M_TX_OVER: packed union { + raw: u1, + value: enum(u1) { + /// TX_OVER interrupt is masked + ENABLED = 0x0, + /// TX_OVER interrupt is unmasked + DISABLED = 0x1, + }, + }, + /// This bit masks the R_TX_EMPTY interrupt in IC_INTR_STAT register. + /// Reset value: 0x1 + M_TX_EMPTY: packed union { + raw: u1, + value: enum(u1) { + /// TX_EMPTY interrupt is masked + ENABLED = 0x0, + /// TX_EMPTY interrupt is unmasked + DISABLED = 0x1, + }, + }, + /// This bit masks the R_RD_REQ interrupt in IC_INTR_STAT register. + /// Reset value: 0x1 + M_RD_REQ: packed union { + raw: u1, + value: enum(u1) { + /// RD_REQ interrupt is masked + ENABLED = 0x0, + /// RD_REQ interrupt is unmasked + DISABLED = 0x1, + }, + }, + /// This bit masks the R_TX_ABRT interrupt in IC_INTR_STAT register. + /// Reset value: 0x1 + M_TX_ABRT: packed union { + raw: u1, + value: enum(u1) { + /// TX_ABORT interrupt is masked + ENABLED = 0x0, + /// TX_ABORT interrupt is unmasked + DISABLED = 0x1, + }, + }, + /// This bit masks the R_RX_DONE interrupt in IC_INTR_STAT register. + /// Reset value: 0x1 + M_RX_DONE: packed union { + raw: u1, + value: enum(u1) { + /// RX_DONE interrupt is masked + ENABLED = 0x0, + /// RX_DONE interrupt is unmasked + DISABLED = 0x1, + }, + }, + /// This bit masks the R_ACTIVITY interrupt in IC_INTR_STAT register. + /// Reset value: 0x0 + M_ACTIVITY: packed union { + raw: u1, + value: enum(u1) { + /// ACTIVITY interrupt is masked + ENABLED = 0x0, + /// ACTIVITY interrupt is unmasked + DISABLED = 0x1, + }, + }, + /// This bit masks the R_STOP_DET interrupt in IC_INTR_STAT register. + /// Reset value: 0x0 + M_STOP_DET: packed union { + raw: u1, + value: enum(u1) { + /// STOP_DET interrupt is masked + ENABLED = 0x0, + /// STOP_DET interrupt is unmasked + DISABLED = 0x1, + }, + }, + /// This bit masks the R_START_DET interrupt in IC_INTR_STAT register. + /// Reset value: 0x0 + M_START_DET: packed union { + raw: u1, + value: enum(u1) { + /// START_DET interrupt is masked + ENABLED = 0x0, + /// START_DET interrupt is unmasked + DISABLED = 0x1, + }, + }, + /// This bit masks the R_GEN_CALL interrupt in IC_INTR_STAT register. + /// Reset value: 0x1 + M_GEN_CALL: packed union { + raw: u1, + value: enum(u1) { + /// GEN_CALL interrupt is masked + ENABLED = 0x0, + /// GEN_CALL interrupt is unmasked + DISABLED = 0x1, + }, + }, + /// This bit masks the R_RESTART_DET interrupt in IC_INTR_STAT register. + /// Reset value: 0x0 + M_RESTART_DET: packed union { + raw: u1, + value: enum(u1) { + /// RESTART_DET interrupt is masked + ENABLED = 0x0, + /// RESTART_DET interrupt is unmasked + DISABLED = 0x1, + }, + }, + padding: u19, + }), + /// I2C Raw Interrupt Status Register + /// Unlike the IC_INTR_STAT register, these bits are not masked so they always show the true status of the DW_apb_i2c. + IC_RAW_INTR_STAT: mmio.Mmio(packed struct(u32) { + /// Set if the processor attempts to read the receive buffer when it is empty by reading from the IC_DATA_CMD register. If the module is disabled (IC_ENABLE[0]=0), this bit keeps its level until the master or slave state machines go into idle, and when ic_en goes to 0, this interrupt is cleared. + /// Reset value: 0x0 + RX_UNDER: packed union { + raw: u1, + value: enum(u1) { + /// RX_UNDER interrupt is inactive + INACTIVE = 0x0, + /// RX_UNDER interrupt is active + ACTIVE = 0x1, + }, + }, + /// Set if the receive buffer is completely filled to IC_RX_BUFFER_DEPTH and an additional byte is received from an external I2C device. The DW_apb_i2c acknowledges this, but any data bytes received after the FIFO is full are lost. If the module is disabled (IC_ENABLE[0]=0), this bit keeps its level until the master or slave state machines go into idle, and when ic_en goes to 0, this interrupt is cleared. + /// Note: If bit 9 of the IC_CON register (RX_FIFO_FULL_HLD_CTRL) is programmed to HIGH, then the RX_OVER interrupt never occurs, because the Rx FIFO never overflows. + /// Reset value: 0x0 + RX_OVER: packed union { + raw: u1, + value: enum(u1) { + /// RX_OVER interrupt is inactive + INACTIVE = 0x0, + /// RX_OVER interrupt is active + ACTIVE = 0x1, + }, + }, + /// Set when the receive buffer reaches or goes above the RX_TL threshold in the IC_RX_TL register. It is automatically cleared by hardware when buffer level goes below the threshold. If the module is disabled (IC_ENABLE[0]=0), the RX FIFO is flushed and held in reset; therefore the RX FIFO is not full. So this bit is cleared once the IC_ENABLE bit 0 is programmed with a 0, regardless of the activity that continues. + /// Reset value: 0x0 + RX_FULL: packed union { + raw: u1, + value: enum(u1) { + /// RX_FULL interrupt is inactive + INACTIVE = 0x0, + /// RX_FULL interrupt is active + ACTIVE = 0x1, + }, + }, + /// Set during transmit if the transmit buffer is filled to IC_TX_BUFFER_DEPTH and the processor attempts to issue another I2C command by writing to the IC_DATA_CMD register. When the module is disabled, this bit keeps its level until the master or slave state machines go into idle, and when ic_en goes to 0, this interrupt is cleared. + /// Reset value: 0x0 + TX_OVER: packed union { + raw: u1, + value: enum(u1) { + /// TX_OVER interrupt is inactive + INACTIVE = 0x0, + /// TX_OVER interrupt is active + ACTIVE = 0x1, + }, + }, + /// The behavior of the TX_EMPTY interrupt status differs based on the TX_EMPTY_CTRL selection in the IC_CON register. - When TX_EMPTY_CTRL = 0: This bit is set to 1 when the transmit buffer is at or below the threshold value set in the IC_TX_TL register. - When TX_EMPTY_CTRL = 1: This bit is set to 1 when the transmit buffer is at or below the threshold value set in the IC_TX_TL register and the transmission of the address/data from the internal shift register for the most recently popped command is completed. It is automatically cleared by hardware when the buffer level goes above the threshold. When IC_ENABLE[0] is set to 0, the TX FIFO is flushed and held in reset. There the TX FIFO looks like it has no data within it, so this bit is set to 1, provided there is activity in the master or slave state machines. When there is no longer any activity, then with ic_en=0, this bit is set to 0. + /// Reset value: 0x0. + TX_EMPTY: packed union { + raw: u1, + value: enum(u1) { + /// TX_EMPTY interrupt is inactive + INACTIVE = 0x0, + /// TX_EMPTY interrupt is active + ACTIVE = 0x1, + }, + }, + /// This bit is set to 1 when DW_apb_i2c is acting as a slave and another I2C master is attempting to read data from DW_apb_i2c. The DW_apb_i2c holds the I2C bus in a wait state (SCL=0) until this interrupt is serviced, which means that the slave has been addressed by a remote master that is asking for data to be transferred. The processor must respond to this interrupt and then write the requested data to the IC_DATA_CMD register. This bit is set to 0 just after the processor reads the IC_CLR_RD_REQ register. + /// Reset value: 0x0 + RD_REQ: packed union { + raw: u1, + value: enum(u1) { + /// RD_REQ interrupt is inactive + INACTIVE = 0x0, + /// RD_REQ interrupt is active + ACTIVE = 0x1, + }, + }, + /// This bit indicates if DW_apb_i2c, as an I2C transmitter, is unable to complete the intended actions on the contents of the transmit FIFO. This situation can occur both as an I2C master or an I2C slave, and is referred to as a 'transmit abort'. When this bit is set to 1, the IC_TX_ABRT_SOURCE register indicates the reason why the transmit abort takes places. + /// Note: The DW_apb_i2c flushes/resets/empties the TX_FIFO and RX_FIFO whenever there is a transmit abort caused by any of the events tracked by the IC_TX_ABRT_SOURCE register. The FIFOs remains in this flushed state until the register IC_CLR_TX_ABRT is read. Once this read is performed, the Tx FIFO is then ready to accept more data bytes from the APB interface. + /// Reset value: 0x0 + TX_ABRT: packed union { + raw: u1, + value: enum(u1) { + /// TX_ABRT interrupt is inactive + INACTIVE = 0x0, + /// TX_ABRT interrupt is active + ACTIVE = 0x1, + }, + }, + /// When the DW_apb_i2c is acting as a slave-transmitter, this bit is set to 1 if the master does not acknowledge a transmitted byte. This occurs on the last byte of the transmission, indicating that the transmission is done. + /// Reset value: 0x0 + RX_DONE: packed union { + raw: u1, + value: enum(u1) { + /// RX_DONE interrupt is inactive + INACTIVE = 0x0, + /// RX_DONE interrupt is active + ACTIVE = 0x1, + }, + }, + /// This bit captures DW_apb_i2c activity and stays set until it is cleared. There are four ways to clear it: - Disabling the DW_apb_i2c - Reading the IC_CLR_ACTIVITY register - Reading the IC_CLR_INTR register - System reset Once this bit is set, it stays set unless one of the four methods is used to clear it. Even if the DW_apb_i2c module is idle, this bit remains set until cleared, indicating that there was activity on the bus. + /// Reset value: 0x0 + ACTIVITY: packed union { + raw: u1, + value: enum(u1) { + /// RAW_INTR_ACTIVITY interrupt is inactive + INACTIVE = 0x0, + /// RAW_INTR_ACTIVITY interrupt is active + ACTIVE = 0x1, + }, + }, + /// Indicates whether a STOP condition has occurred on the I2C interface regardless of whether DW_apb_i2c is operating in slave or master mode. + /// In Slave Mode: - If IC_CON[7]=1'b1 (STOP_DET_IFADDRESSED), the STOP_DET interrupt will be issued only if slave is addressed. Note: During a general call address, this slave does not issue a STOP_DET interrupt if STOP_DET_IF_ADDRESSED=1'b1, even if the slave responds to the general call address by generating ACK. The STOP_DET interrupt is generated only when the transmitted address matches the slave address (SAR). - If IC_CON[7]=1'b0 (STOP_DET_IFADDRESSED), the STOP_DET interrupt is issued irrespective of whether it is being addressed. In Master Mode: - If IC_CON[10]=1'b1 (STOP_DET_IF_MASTER_ACTIVE),the STOP_DET interrupt will be issued only if Master is active. - If IC_CON[10]=1'b0 (STOP_DET_IFADDRESSED),the STOP_DET interrupt will be issued irrespective of whether master is active or not. Reset value: 0x0 + STOP_DET: packed union { + raw: u1, + value: enum(u1) { + /// STOP_DET interrupt is inactive + INACTIVE = 0x0, + /// STOP_DET interrupt is active + ACTIVE = 0x1, + }, + }, + /// Indicates whether a START or RESTART condition has occurred on the I2C interface regardless of whether DW_apb_i2c is operating in slave or master mode. + /// Reset value: 0x0 + START_DET: packed union { + raw: u1, + value: enum(u1) { + /// START_DET interrupt is inactive + INACTIVE = 0x0, + /// START_DET interrupt is active + ACTIVE = 0x1, + }, + }, + /// Set only when a General Call address is received and it is acknowledged. It stays set until it is cleared either by disabling DW_apb_i2c or when the CPU reads bit 0 of the IC_CLR_GEN_CALL register. DW_apb_i2c stores the received data in the Rx buffer. + /// Reset value: 0x0 + GEN_CALL: packed union { + raw: u1, + value: enum(u1) { + /// GEN_CALL interrupt is inactive + INACTIVE = 0x0, + /// GEN_CALL interrupt is active + ACTIVE = 0x1, + }, + }, + /// Indicates whether a RESTART condition has occurred on the I2C interface when DW_apb_i2c is operating in Slave mode and the slave is being addressed. Enabled only when IC_SLV_RESTART_DET_EN=1. + /// Note: However, in high-speed mode or during a START BYTE transfer, the RESTART comes before the address field as per the I2C protocol. In this case, the slave is not the addressed slave when the RESTART is issued, therefore DW_apb_i2c does not generate the RESTART_DET interrupt. + /// Reset value: 0x0 + RESTART_DET: packed union { + raw: u1, + value: enum(u1) { + /// RESTART_DET interrupt is inactive + INACTIVE = 0x0, + /// RESTART_DET interrupt is active + ACTIVE = 0x1, + }, + }, + padding: u19, + }), + /// I2C Receive FIFO Threshold Register + IC_RX_TL: mmio.Mmio(packed struct(u32) { + /// Receive FIFO Threshold Level. + /// Controls the level of entries (or above) that triggers the RX_FULL interrupt (bit 2 in IC_RAW_INTR_STAT register). The valid range is 0-255, with the additional restriction that hardware does not allow this value to be set to a value larger than the depth of the buffer. If an attempt is made to do that, the actual value set will be the maximum depth of the buffer. A value of 0 sets the threshold for 1 entry, and a value of 255 sets the threshold for 256 entries. + RX_TL: u8, + padding: u24, + }), + /// I2C Transmit FIFO Threshold Register + IC_TX_TL: mmio.Mmio(packed struct(u32) { + /// Transmit FIFO Threshold Level. + /// Controls the level of entries (or below) that trigger the TX_EMPTY interrupt (bit 4 in IC_RAW_INTR_STAT register). The valid range is 0-255, with the additional restriction that it may not be set to value larger than the depth of the buffer. If an attempt is made to do that, the actual value set will be the maximum depth of the buffer. A value of 0 sets the threshold for 0 entries, and a value of 255 sets the threshold for 255 entries. + TX_TL: u8, + padding: u24, + }), + /// Clear Combined and Individual Interrupt Register + IC_CLR_INTR: mmio.Mmio(packed struct(u32) { + /// Read this register to clear the combined interrupt, all individual interrupts, and the IC_TX_ABRT_SOURCE register. This bit does not clear hardware clearable interrupts but software clearable interrupts. Refer to Bit 9 of the IC_TX_ABRT_SOURCE register for an exception to clearing IC_TX_ABRT_SOURCE. + /// Reset value: 0x0 + CLR_INTR: u1, + padding: u31, + }), + /// Clear RX_UNDER Interrupt Register + IC_CLR_RX_UNDER: mmio.Mmio(packed struct(u32) { + /// Read this register to clear the RX_UNDER interrupt (bit 0) of the IC_RAW_INTR_STAT register. + /// Reset value: 0x0 + CLR_RX_UNDER: u1, + padding: u31, + }), + /// Clear RX_OVER Interrupt Register + IC_CLR_RX_OVER: mmio.Mmio(packed struct(u32) { + /// Read this register to clear the RX_OVER interrupt (bit 1) of the IC_RAW_INTR_STAT register. + /// Reset value: 0x0 + CLR_RX_OVER: u1, + padding: u31, + }), + /// Clear TX_OVER Interrupt Register + IC_CLR_TX_OVER: mmio.Mmio(packed struct(u32) { + /// Read this register to clear the TX_OVER interrupt (bit 3) of the IC_RAW_INTR_STAT register. + /// Reset value: 0x0 + CLR_TX_OVER: u1, + padding: u31, + }), + /// Clear RD_REQ Interrupt Register + IC_CLR_RD_REQ: mmio.Mmio(packed struct(u32) { + /// Read this register to clear the RD_REQ interrupt (bit 5) of the IC_RAW_INTR_STAT register. + /// Reset value: 0x0 + CLR_RD_REQ: u1, + padding: u31, + }), + /// Clear TX_ABRT Interrupt Register + IC_CLR_TX_ABRT: mmio.Mmio(packed struct(u32) { + /// Read this register to clear the TX_ABRT interrupt (bit 6) of the IC_RAW_INTR_STAT register, and the IC_TX_ABRT_SOURCE register. This also releases the TX FIFO from the flushed/reset state, allowing more writes to the TX FIFO. Refer to Bit 9 of the IC_TX_ABRT_SOURCE register for an exception to clearing IC_TX_ABRT_SOURCE. + /// Reset value: 0x0 + CLR_TX_ABRT: u1, + padding: u31, + }), + /// Clear RX_DONE Interrupt Register + IC_CLR_RX_DONE: mmio.Mmio(packed struct(u32) { + /// Read this register to clear the RX_DONE interrupt (bit 7) of the IC_RAW_INTR_STAT register. + /// Reset value: 0x0 + CLR_RX_DONE: u1, + padding: u31, + }), + /// Clear ACTIVITY Interrupt Register + IC_CLR_ACTIVITY: mmio.Mmio(packed struct(u32) { + /// Reading this register clears the ACTIVITY interrupt if the I2C is not active anymore. If the I2C module is still active on the bus, the ACTIVITY interrupt bit continues to be set. It is automatically cleared by hardware if the module is disabled and if there is no further activity on the bus. The value read from this register to get status of the ACTIVITY interrupt (bit 8) of the IC_RAW_INTR_STAT register. + /// Reset value: 0x0 + CLR_ACTIVITY: u1, + padding: u31, + }), + /// Clear STOP_DET Interrupt Register + IC_CLR_STOP_DET: mmio.Mmio(packed struct(u32) { + /// Read this register to clear the STOP_DET interrupt (bit 9) of the IC_RAW_INTR_STAT register. + /// Reset value: 0x0 + CLR_STOP_DET: u1, + padding: u31, + }), + /// Clear START_DET Interrupt Register + IC_CLR_START_DET: mmio.Mmio(packed struct(u32) { + /// Read this register to clear the START_DET interrupt (bit 10) of the IC_RAW_INTR_STAT register. + /// Reset value: 0x0 + CLR_START_DET: u1, + padding: u31, + }), + /// Clear GEN_CALL Interrupt Register + IC_CLR_GEN_CALL: mmio.Mmio(packed struct(u32) { + /// Read this register to clear the GEN_CALL interrupt (bit 11) of IC_RAW_INTR_STAT register. + /// Reset value: 0x0 + CLR_GEN_CALL: u1, + padding: u31, + }), + /// I2C Enable Register + IC_ENABLE: mmio.Mmio(packed struct(u32) { + /// Controls whether the DW_apb_i2c is enabled. - 0: Disables DW_apb_i2c (TX and RX FIFOs are held in an erased state) - 1: Enables DW_apb_i2c Software can disable DW_apb_i2c while it is active. However, it is important that care be taken to ensure that DW_apb_i2c is disabled properly. A recommended procedure is described in 'Disabling DW_apb_i2c'. + /// When DW_apb_i2c is disabled, the following occurs: - The TX FIFO and RX FIFO get flushed. - Status bits in the IC_INTR_STAT register are still active until DW_apb_i2c goes into IDLE state. If the module is transmitting, it stops as well as deletes the contents of the transmit buffer after the current transfer is complete. If the module is receiving, the DW_apb_i2c stops the current transfer at the end of the current byte and does not acknowledge the transfer. + /// In systems with asynchronous pclk and ic_clk when IC_CLK_TYPE parameter set to asynchronous (1), there is a two ic_clk delay when enabling or disabling the DW_apb_i2c. For a detailed description on how to disable DW_apb_i2c, refer to 'Disabling DW_apb_i2c' + /// Reset value: 0x0 + ENABLE: packed union { + raw: u1, + value: enum(u1) { + /// I2C is disabled + DISABLED = 0x0, + /// I2C is enabled + ENABLED = 0x1, + }, + }, + /// When set, the controller initiates the transfer abort. - 0: ABORT not initiated or ABORT done - 1: ABORT operation in progress The software can abort the I2C transfer in master mode by setting this bit. The software can set this bit only when ENABLE is already set; otherwise, the controller ignores any write to ABORT bit. The software cannot clear the ABORT bit once set. In response to an ABORT, the controller issues a STOP and flushes the Tx FIFO after completing the current transfer, then sets the TX_ABORT interrupt after the abort operation. The ABORT bit is cleared automatically after the abort operation. + /// For a detailed description on how to abort I2C transfers, refer to 'Aborting I2C Transfers'. + /// Reset value: 0x0 + ABORT: packed union { + raw: u1, + value: enum(u1) { + /// ABORT operation not in progress + DISABLE = 0x0, + /// ABORT operation in progress + ENABLED = 0x1, + }, + }, + /// In Master mode: - 1'b1: Blocks the transmission of data on I2C bus even if Tx FIFO has data to transmit. - 1'b0: The transmission of data starts on I2C bus automatically, as soon as the first data is available in the Tx FIFO. Note: To block the execution of Master commands, set the TX_CMD_BLOCK bit only when Tx FIFO is empty (IC_STATUS[2]==1) and Master is in Idle state (IC_STATUS[5] == 0). Any further commands put in the Tx FIFO are not executed until TX_CMD_BLOCK bit is unset. Reset value: IC_TX_CMD_BLOCK_DEFAULT + TX_CMD_BLOCK: packed union { + raw: u1, + value: enum(u1) { + /// Tx Command execution not blocked + NOT_BLOCKED = 0x0, + /// Tx Command execution blocked + BLOCKED = 0x1, + }, + }, + padding: u29, + }), + /// I2C Status Register + /// This is a read-only register used to indicate the current transfer status and FIFO status. The status register may be read at any time. None of the bits in this register request an interrupt. + /// When the I2C is disabled by writing 0 in bit 0 of the IC_ENABLE register: - Bits 1 and 2 are set to 1 - Bits 3 and 10 are set to 0 When the master or slave state machines goes to idle and ic_en=0: - Bits 5 and 6 are set to 0 + IC_STATUS: mmio.Mmio(packed struct(u32) { + /// I2C Activity Status. Reset value: 0x0 + ACTIVITY: packed union { + raw: u1, + value: enum(u1) { + /// I2C is idle + INACTIVE = 0x0, + /// I2C is active + ACTIVE = 0x1, + }, + }, + /// Transmit FIFO Not Full. Set when the transmit FIFO contains one or more empty locations, and is cleared when the FIFO is full. - 0: Transmit FIFO is full - 1: Transmit FIFO is not full Reset value: 0x1 + TFNF: packed union { + raw: u1, + value: enum(u1) { + /// Tx FIFO is full + FULL = 0x0, + /// Tx FIFO not full + NOT_FULL = 0x1, + }, + }, + /// Transmit FIFO Completely Empty. When the transmit FIFO is completely empty, this bit is set. When it contains one or more valid entries, this bit is cleared. This bit field does not request an interrupt. - 0: Transmit FIFO is not empty - 1: Transmit FIFO is empty Reset value: 0x1 + TFE: packed union { + raw: u1, + value: enum(u1) { + /// Tx FIFO not empty + NON_EMPTY = 0x0, + /// Tx FIFO is empty + EMPTY = 0x1, + }, + }, + /// Receive FIFO Not Empty. This bit is set when the receive FIFO contains one or more entries; it is cleared when the receive FIFO is empty. - 0: Receive FIFO is empty - 1: Receive FIFO is not empty Reset value: 0x0 + RFNE: packed union { + raw: u1, + value: enum(u1) { + /// Rx FIFO is empty + EMPTY = 0x0, + /// Rx FIFO not empty + NOT_EMPTY = 0x1, + }, + }, + /// Receive FIFO Completely Full. When the receive FIFO is completely full, this bit is set. When the receive FIFO contains one or more empty location, this bit is cleared. - 0: Receive FIFO is not full - 1: Receive FIFO is full Reset value: 0x0 + RFF: packed union { + raw: u1, + value: enum(u1) { + /// Rx FIFO not full + NOT_FULL = 0x0, + /// Rx FIFO is full + FULL = 0x1, + }, + }, + /// Master FSM Activity Status. When the Master Finite State Machine (FSM) is not in the IDLE state, this bit is set. - 0: Master FSM is in IDLE state so the Master part of DW_apb_i2c is not Active - 1: Master FSM is not in IDLE state so the Master part of DW_apb_i2c is Active Note: IC_STATUS[0]-that is, ACTIVITY bit-is the OR of SLV_ACTIVITY and MST_ACTIVITY bits. + /// Reset value: 0x0 + MST_ACTIVITY: packed union { + raw: u1, + value: enum(u1) { + /// Master is idle + IDLE = 0x0, + /// Master not idle + ACTIVE = 0x1, + }, + }, + /// Slave FSM Activity Status. When the Slave Finite State Machine (FSM) is not in the IDLE state, this bit is set. - 0: Slave FSM is in IDLE state so the Slave part of DW_apb_i2c is not Active - 1: Slave FSM is not in IDLE state so the Slave part of DW_apb_i2c is Active Reset value: 0x0 + SLV_ACTIVITY: packed union { + raw: u1, + value: enum(u1) { + /// Slave is idle + IDLE = 0x0, + /// Slave not idle + ACTIVE = 0x1, + }, + }, + padding: u25, + }), + /// I2C Transmit FIFO Level Register This register contains the number of valid data entries in the transmit FIFO buffer. It is cleared whenever: - The I2C is disabled - There is a transmit abort - that is, TX_ABRT bit is set in the IC_RAW_INTR_STAT register - The slave bulk transmit mode is aborted The register increments whenever data is placed into the transmit FIFO and decrements when data is taken from the transmit FIFO. + IC_TXFLR: mmio.Mmio(packed struct(u32) { + /// Transmit FIFO Level. Contains the number of valid data entries in the transmit FIFO. + /// Reset value: 0x0 + TXFLR: u5, + padding: u27, + }), + /// I2C Receive FIFO Level Register This register contains the number of valid data entries in the receive FIFO buffer. It is cleared whenever: - The I2C is disabled - Whenever there is a transmit abort caused by any of the events tracked in IC_TX_ABRT_SOURCE The register increments whenever data is placed into the receive FIFO and decrements when data is taken from the receive FIFO. + IC_RXFLR: mmio.Mmio(packed struct(u32) { + /// Receive FIFO Level. Contains the number of valid data entries in the receive FIFO. + /// Reset value: 0x0 + RXFLR: u5, + padding: u27, + }), + /// I2C SDA Hold Time Length Register + /// The bits [15:0] of this register are used to control the hold time of SDA during transmit in both slave and master mode (after SCL goes from HIGH to LOW). + /// The bits [23:16] of this register are used to extend the SDA transition (if any) whenever SCL is HIGH in the receiver in either master or slave mode. + /// Writes to this register succeed only when IC_ENABLE[0]=0. + /// The values in this register are in units of ic_clk period. The value programmed in IC_SDA_TX_HOLD must be greater than the minimum hold time in each mode (one cycle in master mode, seven cycles in slave mode) for the value to be implemented. + /// The programmed SDA hold time during transmit (IC_SDA_TX_HOLD) cannot exceed at any time the duration of the low part of scl. Therefore the programmed value cannot be larger than N_SCL_LOW-2, where N_SCL_LOW is the duration of the low part of the scl period measured in ic_clk cycles. + IC_SDA_HOLD: mmio.Mmio(packed struct(u32) { + /// Sets the required SDA hold time in units of ic_clk period, when DW_apb_i2c acts as a transmitter. + /// Reset value: IC_DEFAULT_SDA_HOLD[15:0]. + IC_SDA_TX_HOLD: u16, + /// Sets the required SDA hold time in units of ic_clk period, when DW_apb_i2c acts as a receiver. + /// Reset value: IC_DEFAULT_SDA_HOLD[23:16]. + IC_SDA_RX_HOLD: u8, + padding: u8, + }), + /// I2C Transmit Abort Source Register + /// This register has 32 bits that indicate the source of the TX_ABRT bit. Except for Bit 9, this register is cleared whenever the IC_CLR_TX_ABRT register or the IC_CLR_INTR register is read. To clear Bit 9, the source of the ABRT_SBYTE_NORSTRT must be fixed first; RESTART must be enabled (IC_CON[5]=1), the SPECIAL bit must be cleared (IC_TAR[11]), or the GC_OR_START bit must be cleared (IC_TAR[10]). + /// Once the source of the ABRT_SBYTE_NORSTRT is fixed, then this bit can be cleared in the same manner as other bits in this register. If the source of the ABRT_SBYTE_NORSTRT is not fixed before attempting to clear this bit, Bit 9 clears for one cycle and is then re-asserted. + IC_TX_ABRT_SOURCE: mmio.Mmio(packed struct(u32) { + /// This field indicates that the Master is in 7-bit addressing mode and the address sent was not acknowledged by any slave. + /// Reset value: 0x0 + /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + ABRT_7B_ADDR_NOACK: packed union { + raw: u1, + value: enum(u1) { + /// This abort is not generated + INACTIVE = 0x0, + /// This abort is generated because of NOACK for 7-bit address + ACTIVE = 0x1, + }, + }, + /// This field indicates that the Master is in 10-bit address mode and the first 10-bit address byte was not acknowledged by any slave. + /// Reset value: 0x0 + /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + ABRT_10ADDR1_NOACK: packed union { + raw: u1, + value: enum(u1) { + /// This abort is not generated + INACTIVE = 0x0, + /// Byte 1 of 10Bit Address not ACKed by any slave + ACTIVE = 0x1, + }, + }, + /// This field indicates that the Master is in 10-bit address mode and that the second address byte of the 10-bit address was not acknowledged by any slave. + /// Reset value: 0x0 + /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + ABRT_10ADDR2_NOACK: packed union { + raw: u1, + value: enum(u1) { + /// This abort is not generated + INACTIVE = 0x0, + /// Byte 2 of 10Bit Address not ACKed by any slave + ACTIVE = 0x1, + }, + }, + /// This field indicates the master-mode only bit. When the master receives an acknowledgement for the address, but when it sends data byte(s) following the address, it did not receive an acknowledge from the remote slave(s). + /// Reset value: 0x0 + /// Role of DW_apb_i2c: Master-Transmitter + ABRT_TXDATA_NOACK: packed union { + raw: u1, + value: enum(u1) { + /// Transmitted data non-ACKed by addressed slave-scenario not present + ABRT_TXDATA_NOACK_VOID = 0x0, + /// Transmitted data not ACKed by addressed slave + ABRT_TXDATA_NOACK_GENERATED = 0x1, + }, + }, + /// This field indicates that DW_apb_i2c in master mode has sent a General Call and no slave on the bus acknowledged the General Call. + /// Reset value: 0x0 + /// Role of DW_apb_i2c: Master-Transmitter + ABRT_GCALL_NOACK: packed union { + raw: u1, + value: enum(u1) { + /// GCALL not ACKed by any slave-scenario not present + ABRT_GCALL_NOACK_VOID = 0x0, + /// GCALL not ACKed by any slave + ABRT_GCALL_NOACK_GENERATED = 0x1, + }, + }, + /// This field indicates that DW_apb_i2c in the master mode has sent a General Call but the user programmed the byte following the General Call to be a read from the bus (IC_DATA_CMD[9] is set to 1). + /// Reset value: 0x0 + /// Role of DW_apb_i2c: Master-Transmitter + ABRT_GCALL_READ: packed union { + raw: u1, + value: enum(u1) { + /// GCALL is followed by read from bus-scenario not present + ABRT_GCALL_READ_VOID = 0x0, + /// GCALL is followed by read from bus + ABRT_GCALL_READ_GENERATED = 0x1, + }, + }, + /// This field indicates that the Master is in High Speed mode and the High Speed Master code was acknowledged (wrong behavior). + /// Reset value: 0x0 + /// Role of DW_apb_i2c: Master + ABRT_HS_ACKDET: packed union { + raw: u1, + value: enum(u1) { + /// HS Master code ACKed in HS Mode- scenario not present + ABRT_HS_ACK_VOID = 0x0, + /// HS Master code ACKed in HS Mode + ABRT_HS_ACK_GENERATED = 0x1, + }, + }, + /// This field indicates that the Master has sent a START Byte and the START Byte was acknowledged (wrong behavior). + /// Reset value: 0x0 + /// Role of DW_apb_i2c: Master + ABRT_SBYTE_ACKDET: packed union { + raw: u1, + value: enum(u1) { + /// ACK detected for START byte- scenario not present + ABRT_SBYTE_ACKDET_VOID = 0x0, + /// ACK detected for START byte + ABRT_SBYTE_ACKDET_GENERATED = 0x1, + }, + }, + /// This field indicates that the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) =0) and the user is trying to use the master to transfer data in High Speed mode. + /// Reset value: 0x0 + /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + ABRT_HS_NORSTRT: packed union { + raw: u1, + value: enum(u1) { + /// User trying to switch Master to HS mode when RESTART disabled- scenario not present + ABRT_HS_NORSTRT_VOID = 0x0, + /// User trying to switch Master to HS mode when RESTART disabled + ABRT_HS_NORSTRT_GENERATED = 0x1, + }, + }, + /// To clear Bit 9, the source of the ABRT_SBYTE_NORSTRT must be fixed first; restart must be enabled (IC_CON[5]=1), the SPECIAL bit must be cleared (IC_TAR[11]), or the GC_OR_START bit must be cleared (IC_TAR[10]). Once the source of the ABRT_SBYTE_NORSTRT is fixed, then this bit can be cleared in the same manner as other bits in this register. If the source of the ABRT_SBYTE_NORSTRT is not fixed before attempting to clear this bit, bit 9 clears for one cycle and then gets reasserted. When this field is set to 1, the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) =0) and the user is trying to send a START Byte. + /// Reset value: 0x0 + /// Role of DW_apb_i2c: Master + ABRT_SBYTE_NORSTRT: packed union { + raw: u1, + value: enum(u1) { + /// User trying to send START byte when RESTART disabled- scenario not present + ABRT_SBYTE_NORSTRT_VOID = 0x0, + /// User trying to send START byte when RESTART disabled + ABRT_SBYTE_NORSTRT_GENERATED = 0x1, + }, + }, + /// This field indicates that the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) =0) and the master sends a read command in 10-bit addressing mode. + /// Reset value: 0x0 + /// Role of DW_apb_i2c: Master-Receiver + ABRT_10B_RD_NORSTRT: packed union { + raw: u1, + value: enum(u1) { + /// Master not trying to read in 10Bit addressing mode when RESTART disabled + ABRT_10B_RD_VOID = 0x0, + /// Master trying to read in 10Bit addressing mode when RESTART disabled + ABRT_10B_RD_GENERATED = 0x1, + }, + }, + /// This field indicates that the User tries to initiate a Master operation with the Master mode disabled. + /// Reset value: 0x0 + /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + ABRT_MASTER_DIS: packed union { + raw: u1, + value: enum(u1) { + /// User initiating master operation when MASTER disabled- scenario not present + ABRT_MASTER_DIS_VOID = 0x0, + /// User initiating master operation when MASTER disabled + ABRT_MASTER_DIS_GENERATED = 0x1, + }, + }, + /// This field specifies that the Master has lost arbitration, or if IC_TX_ABRT_SOURCE[14] is also set, then the slave transmitter has lost arbitration. + /// Reset value: 0x0 + /// Role of DW_apb_i2c: Master-Transmitter or Slave-Transmitter + ARB_LOST: packed union { + raw: u1, + value: enum(u1) { + /// Master or Slave-Transmitter lost arbitration- scenario not present + ABRT_LOST_VOID = 0x0, + /// Master or Slave-Transmitter lost arbitration + ABRT_LOST_GENERATED = 0x1, + }, + }, + /// This field specifies that the Slave has received a read command and some data exists in the TX FIFO, so the slave issues a TX_ABRT interrupt to flush old data in TX FIFO. + /// Reset value: 0x0 + /// Role of DW_apb_i2c: Slave-Transmitter + ABRT_SLVFLUSH_TXFIFO: packed union { + raw: u1, + value: enum(u1) { + /// Slave flushes existing data in TX-FIFO upon getting read command- scenario not present + ABRT_SLVFLUSH_TXFIFO_VOID = 0x0, + /// Slave flushes existing data in TX-FIFO upon getting read command + ABRT_SLVFLUSH_TXFIFO_GENERATED = 0x1, + }, + }, + /// This field indicates that a Slave has lost the bus while transmitting data to a remote master. IC_TX_ABRT_SOURCE[12] is set at the same time. Note: Even though the slave never 'owns' the bus, something could go wrong on the bus. This is a fail safe check. For instance, during a data transmission at the low-to-high transition of SCL, if what is on the data bus is not what is supposed to be transmitted, then DW_apb_i2c no longer own the bus. + /// Reset value: 0x0 + /// Role of DW_apb_i2c: Slave-Transmitter + ABRT_SLV_ARBLOST: packed union { + raw: u1, + value: enum(u1) { + /// Slave lost arbitration to remote master- scenario not present + ABRT_SLV_ARBLOST_VOID = 0x0, + /// Slave lost arbitration to remote master + ABRT_SLV_ARBLOST_GENERATED = 0x1, + }, + }, + /// 1: When the processor side responds to a slave mode request for data to be transmitted to a remote master and user writes a 1 in CMD (bit 8) of IC_DATA_CMD register. + /// Reset value: 0x0 + /// Role of DW_apb_i2c: Slave-Transmitter + ABRT_SLVRD_INTX: packed union { + raw: u1, + value: enum(u1) { + /// Slave trying to transmit to remote master in read mode- scenario not present + ABRT_SLVRD_INTX_VOID = 0x0, + /// Slave trying to transmit to remote master in read mode + ABRT_SLVRD_INTX_GENERATED = 0x1, + }, + }, + /// This is a master-mode-only bit. Master has detected the transfer abort (IC_ENABLE[1]) + /// Reset value: 0x0 + /// Role of DW_apb_i2c: Master-Transmitter + ABRT_USER_ABRT: packed union { + raw: u1, + value: enum(u1) { + /// Transfer abort detected by master- scenario not present + ABRT_USER_ABRT_VOID = 0x0, + /// Transfer abort detected by master + ABRT_USER_ABRT_GENERATED = 0x1, + }, + }, + reserved23: u6, + /// This field indicates the number of Tx FIFO Data Commands which are flushed due to TX_ABRT interrupt. It is cleared whenever I2C is disabled. + /// Reset value: 0x0 + /// Role of DW_apb_i2c: Master-Transmitter or Slave-Transmitter + TX_FLUSH_CNT: u9, + }), + /// Generate Slave Data NACK Register + /// The register is used to generate a NACK for the data part of a transfer when DW_apb_i2c is acting as a slave-receiver. This register only exists when the IC_SLV_DATA_NACK_ONLY parameter is set to 1. When this parameter disabled, this register does not exist and writing to the register's address has no effect. + /// A write can occur on this register if both of the following conditions are met: - DW_apb_i2c is disabled (IC_ENABLE[0] = 0) - Slave part is inactive (IC_STATUS[6] = 0) Note: The IC_STATUS[6] is a register read-back location for the internal slv_activity signal; the user should poll this before writing the ic_slv_data_nack_only bit. + IC_SLV_DATA_NACK_ONLY: mmio.Mmio(packed struct(u32) { + /// Generate NACK. This NACK generation only occurs when DW_apb_i2c is a slave-receiver. If this register is set to a value of 1, it can only generate a NACK after a data byte is received; hence, the data transfer is aborted and the data received is not pushed to the receive buffer. + /// When the register is set to a value of 0, it generates NACK/ACK, depending on normal criteria. - 1: generate NACK after data byte received - 0: generate NACK/ACK normally Reset value: 0x0 + NACK: packed union { + raw: u1, + value: enum(u1) { + /// Slave receiver generates NACK normally + DISABLED = 0x0, + /// Slave receiver generates NACK upon data reception only + ENABLED = 0x1, + }, + }, + padding: u31, + }), + /// DMA Control Register + /// The register is used to enable the DMA Controller interface operation. There is a separate bit for transmit and receive. This can be programmed regardless of the state of IC_ENABLE. + IC_DMA_CR: mmio.Mmio(packed struct(u32) { + /// Receive DMA Enable. This bit enables/disables the receive FIFO DMA channel. Reset value: 0x0 + RDMAE: packed union { + raw: u1, + value: enum(u1) { + /// Receive FIFO DMA channel disabled + DISABLED = 0x0, + /// Receive FIFO DMA channel enabled + ENABLED = 0x1, + }, + }, + /// Transmit DMA Enable. This bit enables/disables the transmit FIFO DMA channel. Reset value: 0x0 + TDMAE: packed union { + raw: u1, + value: enum(u1) { + /// transmit FIFO DMA channel disabled + DISABLED = 0x0, + /// Transmit FIFO DMA channel enabled + ENABLED = 0x1, + }, + }, + padding: u30, + }), + /// DMA Transmit Data Level Register + IC_DMA_TDLR: mmio.Mmio(packed struct(u32) { + /// Transmit Data Level. This bit field controls the level at which a DMA request is made by the transmit logic. It is equal to the watermark level; that is, the dma_tx_req signal is generated when the number of valid data entries in the transmit FIFO is equal to or below this field value, and TDMAE = 1. + /// Reset value: 0x0 + DMATDL: u4, + padding: u28, + }), + /// I2C Receive Data Level Register + IC_DMA_RDLR: mmio.Mmio(packed struct(u32) { + /// Receive Data Level. This bit field controls the level at which a DMA request is made by the receive logic. The watermark level = DMARDL+1; that is, dma_rx_req is generated when the number of valid data entries in the receive FIFO is equal to or more than this field value + 1, and RDMAE =1. For instance, when DMARDL is 0, then dma_rx_req is asserted when 1 or more data entries are present in the receive FIFO. + /// Reset value: 0x0 + DMARDL: u4, + padding: u28, + }), + /// I2C SDA Setup Register + /// This register controls the amount of time delay (in terms of number of ic_clk clock periods) introduced in the rising edge of SCL - relative to SDA changing - when DW_apb_i2c services a read request in a slave-transmitter operation. The relevant I2C requirement is tSU:DAT (note 4) as detailed in the I2C Bus Specification. This register must be programmed with a value equal to or greater than 2. + /// Writes to this register succeed only when IC_ENABLE[0] = 0. + /// Note: The length of setup time is calculated using [(IC_SDA_SETUP - 1) * (ic_clk_period)], so if the user requires 10 ic_clk periods of setup time, they should program a value of 11. The IC_SDA_SETUP register is only used by the DW_apb_i2c when operating as a slave transmitter. + IC_SDA_SETUP: mmio.Mmio(packed struct(u32) { + /// SDA Setup. It is recommended that if the required delay is 1000ns, then for an ic_clk frequency of 10 MHz, IC_SDA_SETUP should be programmed to a value of 11. IC_SDA_SETUP must be programmed with a minimum value of 2. + SDA_SETUP: u8, + padding: u24, + }), + /// I2C ACK General Call Register + /// The register controls whether DW_apb_i2c responds with a ACK or NACK when it receives an I2C General Call address. + /// This register is applicable only when the DW_apb_i2c is in slave mode. + IC_ACK_GENERAL_CALL: mmio.Mmio(packed struct(u32) { + /// ACK General Call. When set to 1, DW_apb_i2c responds with a ACK (by asserting ic_data_oe) when it receives a General Call. Otherwise, DW_apb_i2c responds with a NACK (by negating ic_data_oe). + ACK_GEN_CALL: packed union { + raw: u1, + value: enum(u1) { + /// Generate NACK for a General Call + DISABLED = 0x0, + /// Generate ACK for a General Call + ENABLED = 0x1, + }, + }, + padding: u31, + }), + /// I2C Enable Status Register + /// The register is used to report the DW_apb_i2c hardware status when the IC_ENABLE[0] register is set from 1 to 0; that is, when DW_apb_i2c is disabled. + /// If IC_ENABLE[0] has been set to 1, bits 2:1 are forced to 0, and bit 0 is forced to 1. + /// If IC_ENABLE[0] has been set to 0, bits 2:1 is only be valid as soon as bit 0 is read as '0'. + /// Note: When IC_ENABLE[0] has been set to 0, a delay occurs for bit 0 to be read as 0 because disabling the DW_apb_i2c depends on I2C bus activities. + IC_ENABLE_STATUS: mmio.Mmio(packed struct(u32) { + /// ic_en Status. This bit always reflects the value driven on the output port ic_en. - When read as 1, DW_apb_i2c is deemed to be in an enabled state. - When read as 0, DW_apb_i2c is deemed completely inactive. Note: The CPU can safely read this bit anytime. When this bit is read as 0, the CPU can safely read SLV_RX_DATA_LOST (bit 2) and SLV_DISABLED_WHILE_BUSY (bit 1). + /// Reset value: 0x0 + IC_EN: packed union { + raw: u1, + value: enum(u1) { + /// I2C disabled + DISABLED = 0x0, + /// I2C enabled + ENABLED = 0x1, + }, + }, + /// Slave Disabled While Busy (Transmit, Receive). This bit indicates if a potential or active Slave operation has been aborted due to the setting bit 0 of the IC_ENABLE register from 1 to 0. This bit is set when the CPU writes a 0 to the IC_ENABLE register while: + /// (a) DW_apb_i2c is receiving the address byte of the Slave-Transmitter operation from a remote master; + /// OR, + /// (b) address and data bytes of the Slave-Receiver operation from a remote master. + /// When read as 1, DW_apb_i2c is deemed to have forced a NACK during any part of an I2C transfer, irrespective of whether the I2C address matches the slave address set in DW_apb_i2c (IC_SAR register) OR if the transfer is completed before IC_ENABLE is set to 0 but has not taken effect. + /// Note: If the remote I2C master terminates the transfer with a STOP condition before the DW_apb_i2c has a chance to NACK a transfer, and IC_ENABLE[0] has been set to 0, then this bit will also be set to 1. + /// When read as 0, DW_apb_i2c is deemed to have been disabled when there is master activity, or when the I2C bus is idle. + /// Note: The CPU can safely read this bit when IC_EN (bit 0) is read as 0. + /// Reset value: 0x0 + SLV_DISABLED_WHILE_BUSY: packed union { + raw: u1, + value: enum(u1) { + /// Slave is disabled when it is idle + INACTIVE = 0x0, + /// Slave is disabled when it is active + ACTIVE = 0x1, + }, + }, + /// Slave Received Data Lost. This bit indicates if a Slave-Receiver operation has been aborted with at least one data byte received from an I2C transfer due to the setting bit 0 of IC_ENABLE from 1 to 0. When read as 1, DW_apb_i2c is deemed to have been actively engaged in an aborted I2C transfer (with matching address) and the data phase of the I2C transfer has been entered, even though a data byte has been responded with a NACK. + /// Note: If the remote I2C master terminates the transfer with a STOP condition before the DW_apb_i2c has a chance to NACK a transfer, and IC_ENABLE[0] has been set to 0, then this bit is also set to 1. + /// When read as 0, DW_apb_i2c is deemed to have been disabled without being actively involved in the data phase of a Slave-Receiver transfer. + /// Note: The CPU can safely read this bit when IC_EN (bit 0) is read as 0. + /// Reset value: 0x0 + SLV_RX_DATA_LOST: packed union { + raw: u1, + value: enum(u1) { + /// Slave RX Data is not lost + INACTIVE = 0x0, + /// Slave RX Data is lost + ACTIVE = 0x1, + }, + }, + padding: u29, + }), + /// I2C SS, FS or FM+ spike suppression limit + /// This register is used to store the duration, measured in ic_clk cycles, of the longest spike that is filtered out by the spike suppression logic when the component is operating in SS, FS or FM+ modes. The relevant I2C requirement is tSP (table 4) as detailed in the I2C Bus Specification. This register must be programmed with a minimum value of 1. + IC_FS_SPKLEN: mmio.Mmio(packed struct(u32) { + /// This register must be set before any I2C bus transaction can take place to ensure stable operation. This register sets the duration, measured in ic_clk cycles, of the longest spike in the SCL or SDA lines that will be filtered out by the spike suppression logic. This register can be written only when the I2C interface is disabled which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. The minimum valid value is 1; hardware prevents values less than this being written, and if attempted results in 1 being set. or more information, refer to 'Spike Suppression'. + IC_FS_SPKLEN: u8, + padding: u24, + }), + reserved168: [4]u8, + /// Clear RESTART_DET Interrupt Register + IC_CLR_RESTART_DET: mmio.Mmio(packed struct(u32) { + /// Read this register to clear the RESTART_DET interrupt (bit 12) of IC_RAW_INTR_STAT register. + /// Reset value: 0x0 + CLR_RESTART_DET: u1, + padding: u31, + }), + reserved244: [72]u8, + /// Component Parameter Register 1 + /// Note This register is not implemented and therefore reads as 0. If it was implemented it would be a constant read-only register that contains encoded information about the component's parameter settings. Fields shown below are the settings for those parameters + IC_COMP_PARAM_1: mmio.Mmio(packed struct(u32) { + /// APB data bus width is 32 bits + APB_DATA_WIDTH: u2, + /// MAX SPEED MODE = FAST MODE + MAX_SPEED_MODE: u2, + /// Programmable count values for each mode. + HC_COUNT_VALUES: u1, + /// COMBINED Interrupt outputs + INTR_IO: u1, + /// DMA handshaking signals are enabled + HAS_DMA: u1, + /// Encoded parameters not visible + ADD_ENCODED_PARAMS: u1, + /// RX Buffer Depth = 16 + RX_BUFFER_DEPTH: u8, + /// TX Buffer Depth = 16 + TX_BUFFER_DEPTH: u8, + padding: u8, + }), + /// I2C Component Version Register + IC_COMP_VERSION: mmio.Mmio(packed struct(u32) { + IC_COMP_VERSION: u32, + }), + /// I2C Component Type Register + IC_COMP_TYPE: mmio.Mmio(packed struct(u32) { + /// Designware Component Type number = 0x44_57_01_40. This assigned unique hex value is constant and is derived from the two ASCII letters 'DW' followed by a 16-bit unsigned number. + IC_COMP_TYPE: u32, + }), + }; + + /// Programmable IO block + pub const PIO0 = extern struct { + /// PIO control register + CTRL: mmio.Mmio(packed struct(u32) { + /// Enable/disable each of the four state machines by writing 1/0 to each of these four bits. When disabled, a state machine will cease executing instructions, except those written directly to SMx_INSTR by the system. Multiple bits can be set/cleared at once to run/halt multiple state machines simultaneously. + SM_ENABLE: u4, + /// Write 1 to instantly clear internal SM state which may be otherwise difficult to access and will affect future execution. + /// Specifically, the following are cleared: input and output shift counters; the contents of the input shift register; the delay counter; the waiting-on-IRQ state; any stalled instruction written to SMx_INSTR or run by OUT/MOV EXEC; any pin write left asserted due to OUT_STICKY. + SM_RESTART: u4, + /// Restart a state machine's clock divider from an initial phase of 0. Clock dividers are free-running, so once started, their output (including fractional jitter) is completely determined by the integer/fractional divisor configured in SMx_CLKDIV. This means that, if multiple clock dividers with the same divisor are restarted simultaneously, by writing multiple 1 bits to this field, the execution clocks of those state machines will run in precise lockstep. + /// Note that setting/clearing SM_ENABLE does not stop the clock divider from running, so once multiple state machines' clocks are synchronised, it is safe to disable/reenable a state machine, whilst keeping the clock dividers in sync. + /// Note also that CLKDIV_RESTART can be written to whilst the state machine is running, and this is useful to resynchronise clock dividers after the divisors (SMx_CLKDIV) have been changed on-the-fly. + CLKDIV_RESTART: u4, + padding: u20, + }), + /// FIFO status register + FSTAT: mmio.Mmio(packed struct(u32) { + /// State machine RX FIFO is full + RXFULL: u4, + reserved8: u4, + /// State machine RX FIFO is empty + RXEMPTY: u4, + reserved16: u4, + /// State machine TX FIFO is full + TXFULL: u4, + reserved24: u4, + /// State machine TX FIFO is empty + TXEMPTY: u4, + padding: u4, + }), + /// FIFO debug register + FDEBUG: mmio.Mmio(packed struct(u32) { + /// State machine has stalled on full RX FIFO during a blocking PUSH, or an IN with autopush enabled. This flag is also set when a nonblocking PUSH to a full FIFO took place, in which case the state machine has dropped data. Write 1 to clear. + RXSTALL: u4, + reserved8: u4, + /// RX FIFO underflow (i.e. read-on-empty by the system) has occurred. Write 1 to clear. Note that read-on-empty does not perturb the state of the FIFO in any way, but the data returned by reading from an empty FIFO is undefined, so this flag generally only becomes set due to some kind of software error. + RXUNDER: u4, + reserved16: u4, + /// TX FIFO overflow (i.e. write-on-full by the system) has occurred. Write 1 to clear. Note that write-on-full does not alter the state or contents of the FIFO in any way, but the data that the system attempted to write is dropped, so if this flag is set, your software has quite likely dropped some data on the floor. + TXOVER: u4, + reserved24: u4, + /// State machine has stalled on empty TX FIFO during a blocking PULL, or an OUT with autopull enabled. Write 1 to clear. + TXSTALL: u4, + padding: u4, + }), + /// FIFO levels + FLEVEL: mmio.Mmio(packed struct(u32) { + TX0: u4, + RX0: u4, + TX1: u4, + RX1: u4, + TX2: u4, + RX2: u4, + TX3: u4, + RX3: u4, + }), + /// Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + TXF0: u32, + /// Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + TXF1: u32, + /// Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + TXF2: u32, + /// Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + TXF3: u32, + /// Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + RXF0: u32, + /// Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + RXF1: u32, + /// Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + RXF2: u32, + /// Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + RXF3: u32, + /// State machine IRQ flags register. Write 1 to clear. There are 8 state machine IRQ flags, which can be set, cleared, and waited on by the state machines. There's no fixed association between flags and state machines -- any state machine can use any flag. + /// Any of the 8 flags can be used for timing synchronisation between state machines, using IRQ and WAIT instructions. The lower four of these flags are also routed out to system-level interrupt requests, alongside FIFO status interrupts -- see e.g. IRQ0_INTE. + IRQ: mmio.Mmio(packed struct(u32) { + IRQ: u8, + padding: u24, + }), + /// Writing a 1 to each of these bits will forcibly assert the corresponding IRQ. Note this is different to the INTF register: writing here affects PIO internal state. INTF just asserts the processor-facing IRQ signal for testing ISRs, and is not visible to the state machines. + IRQ_FORCE: mmio.Mmio(packed struct(u32) { + IRQ_FORCE: u8, + padding: u24, + }), + /// There is a 2-flipflop synchronizer on each GPIO input, which protects PIO logic from metastabilities. This increases input delay, and for fast synchronous IO (e.g. SPI) these synchronizers may need to be bypassed. Each bit in this register corresponds to one GPIO. + /// 0 -> input is synchronized (default) + /// 1 -> synchronizer is bypassed + /// If in doubt, leave this register as all zeroes. + INPUT_SYNC_BYPASS: u32, + /// Read to sample the pad output values PIO is currently driving to the GPIOs. On RP2040 there are 30 GPIOs, so the two most significant bits are hardwired to 0. + DBG_PADOUT: u32, + /// Read to sample the pad output enables (direction) PIO is currently driving to the GPIOs. On RP2040 there are 30 GPIOs, so the two most significant bits are hardwired to 0. + DBG_PADOE: u32, + /// The PIO hardware has some free parameters that may vary between chip products. + /// These should be provided in the chip datasheet, but are also exposed here. + DBG_CFGINFO: mmio.Mmio(packed struct(u32) { + /// The depth of the state machine TX/RX FIFOs, measured in words. + /// Joining fifos via SHIFTCTRL_FJOIN gives one FIFO with double + /// this depth. + FIFO_DEPTH: u6, + reserved8: u2, + /// The number of state machines this PIO instance is equipped with. + SM_COUNT: u4, + reserved16: u4, + /// The size of the instruction memory, measured in units of one instruction + IMEM_SIZE: u6, + padding: u10, + }), + /// Write-only access to instruction memory location 0 + INSTR_MEM0: mmio.Mmio(packed struct(u32) { + INSTR_MEM0: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 1 + INSTR_MEM1: mmio.Mmio(packed struct(u32) { + INSTR_MEM1: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 2 + INSTR_MEM2: mmio.Mmio(packed struct(u32) { + INSTR_MEM2: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 3 + INSTR_MEM3: mmio.Mmio(packed struct(u32) { + INSTR_MEM3: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 4 + INSTR_MEM4: mmio.Mmio(packed struct(u32) { + INSTR_MEM4: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 5 + INSTR_MEM5: mmio.Mmio(packed struct(u32) { + INSTR_MEM5: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 6 + INSTR_MEM6: mmio.Mmio(packed struct(u32) { + INSTR_MEM6: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 7 + INSTR_MEM7: mmio.Mmio(packed struct(u32) { + INSTR_MEM7: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 8 + INSTR_MEM8: mmio.Mmio(packed struct(u32) { + INSTR_MEM8: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 9 + INSTR_MEM9: mmio.Mmio(packed struct(u32) { + INSTR_MEM9: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 10 + INSTR_MEM10: mmio.Mmio(packed struct(u32) { + INSTR_MEM10: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 11 + INSTR_MEM11: mmio.Mmio(packed struct(u32) { + INSTR_MEM11: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 12 + INSTR_MEM12: mmio.Mmio(packed struct(u32) { + INSTR_MEM12: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 13 + INSTR_MEM13: mmio.Mmio(packed struct(u32) { + INSTR_MEM13: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 14 + INSTR_MEM14: mmio.Mmio(packed struct(u32) { + INSTR_MEM14: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 15 + INSTR_MEM15: mmio.Mmio(packed struct(u32) { + INSTR_MEM15: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 16 + INSTR_MEM16: mmio.Mmio(packed struct(u32) { + INSTR_MEM16: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 17 + INSTR_MEM17: mmio.Mmio(packed struct(u32) { + INSTR_MEM17: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 18 + INSTR_MEM18: mmio.Mmio(packed struct(u32) { + INSTR_MEM18: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 19 + INSTR_MEM19: mmio.Mmio(packed struct(u32) { + INSTR_MEM19: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 20 + INSTR_MEM20: mmio.Mmio(packed struct(u32) { + INSTR_MEM20: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 21 + INSTR_MEM21: mmio.Mmio(packed struct(u32) { + INSTR_MEM21: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 22 + INSTR_MEM22: mmio.Mmio(packed struct(u32) { + INSTR_MEM22: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 23 + INSTR_MEM23: mmio.Mmio(packed struct(u32) { + INSTR_MEM23: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 24 + INSTR_MEM24: mmio.Mmio(packed struct(u32) { + INSTR_MEM24: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 25 + INSTR_MEM25: mmio.Mmio(packed struct(u32) { + INSTR_MEM25: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 26 + INSTR_MEM26: mmio.Mmio(packed struct(u32) { + INSTR_MEM26: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 27 + INSTR_MEM27: mmio.Mmio(packed struct(u32) { + INSTR_MEM27: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 28 + INSTR_MEM28: mmio.Mmio(packed struct(u32) { + INSTR_MEM28: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 29 + INSTR_MEM29: mmio.Mmio(packed struct(u32) { + INSTR_MEM29: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 30 + INSTR_MEM30: mmio.Mmio(packed struct(u32) { + INSTR_MEM30: u16, + padding: u16, + }), + /// Write-only access to instruction memory location 31 + INSTR_MEM31: mmio.Mmio(packed struct(u32) { + INSTR_MEM31: u16, + padding: u16, + }), + /// Clock divisor register for state machine 0 + /// Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + SM0_CLKDIV: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// Fractional part of clock divisor + FRAC: u8, + /// Effective frequency is sysclk/(int + frac/256). + /// Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + INT: u16, + }), + /// Execution/behavioural settings for state machine 0 + SM0_EXECCTRL: mmio.Mmio(packed struct(u32) { + /// Comparison level for the MOV x, STATUS instruction + STATUS_N: u4, + /// Comparison used for the MOV x, STATUS instruction. + STATUS_SEL: packed union { + raw: u1, + value: enum(u1) { + /// All-ones if TX FIFO level < N, otherwise all-zeroes + TXLEVEL = 0x0, + /// All-ones if RX FIFO level < N, otherwise all-zeroes + RXLEVEL = 0x1, + }, + }, + reserved7: u2, + /// After reaching wrap_top, execution is wrapped to this address. + WRAP_BOTTOM: u5, + /// After reaching this address, execution is wrapped to wrap_bottom. + /// If the instruction is a jump, and the jump condition is true, the jump takes priority. + WRAP_TOP: u5, + /// Continuously assert the most recent OUT/SET to the pins + OUT_STICKY: u1, + /// If 1, use a bit of OUT data as an auxiliary write enable + /// When used in conjunction with OUT_STICKY, writes with an enable of 0 will + /// deassert the latest pin write. This can create useful masking/override behaviour + /// due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + INLINE_OUT_EN: u1, + /// Which data bit to use for inline OUT enable + OUT_EN_SEL: u5, + /// The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + JMP_PIN: u5, + /// If 1, side-set data is asserted to pin directions, instead of pin values + SIDE_PINDIR: u1, + /// If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + SIDE_EN: u1, + /// If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes. + EXEC_STALLED: u1, + }), + /// Control behaviour of the input/output shift registers for state machine 0 + SM0_SHIFTCTRL: mmio.Mmio(packed struct(u32) { + reserved16: u16, + /// Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + AUTOPUSH: u1, + /// Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH. + AUTOPULL: u1, + /// 1 = shift input shift register to right (data enters from left). 0 = to left. + IN_SHIFTDIR: u1, + /// 1 = shift out of output shift register to right. 0 = to left. + OUT_SHIFTDIR: u1, + /// Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place. + /// Write 0 for value of 32. + PUSH_THRESH: u5, + /// Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place. + /// Write 0 for value of 32. + PULL_THRESH: u5, + /// When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep. + /// RX FIFO is disabled as a result (always reads as both full and empty). + /// FIFOs are flushed when this bit is changed. + FJOIN_TX: u1, + /// When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep. + /// TX FIFO is disabled as a result (always reads as both full and empty). + /// FIFOs are flushed when this bit is changed. + FJOIN_RX: u1, + }), + /// Current instruction address of state machine 0 + SM0_ADDR: mmio.Mmio(packed struct(u32) { + SM0_ADDR: u5, + padding: u27, + }), + /// Read to see the instruction currently addressed by state machine 0's program counter + /// Write to execute an instruction immediately (including jumps) and then resume execution. + SM0_INSTR: mmio.Mmio(packed struct(u32) { + SM0_INSTR: u16, + padding: u16, + }), + /// State machine pin control + SM0_PINCTRL: mmio.Mmio(packed struct(u32) { + /// The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. + OUT_BASE: u5, + /// The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data. + SET_BASE: u5, + /// The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins. + SIDESET_BASE: u5, + /// The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number. + IN_BASE: u5, + /// The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive. + OUT_COUNT: u6, + /// The number of pins asserted by a SET. In the range 0 to 5 inclusive. + SET_COUNT: u3, + /// The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay). + SIDESET_COUNT: u3, + }), + /// Clock divisor register for state machine 1 + /// Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + SM1_CLKDIV: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// Fractional part of clock divisor + FRAC: u8, + /// Effective frequency is sysclk/(int + frac/256). + /// Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + INT: u16, + }), + /// Execution/behavioural settings for state machine 1 + SM1_EXECCTRL: mmio.Mmio(packed struct(u32) { + /// Comparison level for the MOV x, STATUS instruction + STATUS_N: u4, + /// Comparison used for the MOV x, STATUS instruction. + STATUS_SEL: packed union { + raw: u1, + value: enum(u1) { + /// All-ones if TX FIFO level < N, otherwise all-zeroes + TXLEVEL = 0x0, + /// All-ones if RX FIFO level < N, otherwise all-zeroes + RXLEVEL = 0x1, + }, + }, + reserved7: u2, + /// After reaching wrap_top, execution is wrapped to this address. + WRAP_BOTTOM: u5, + /// After reaching this address, execution is wrapped to wrap_bottom. + /// If the instruction is a jump, and the jump condition is true, the jump takes priority. + WRAP_TOP: u5, + /// Continuously assert the most recent OUT/SET to the pins + OUT_STICKY: u1, + /// If 1, use a bit of OUT data as an auxiliary write enable + /// When used in conjunction with OUT_STICKY, writes with an enable of 0 will + /// deassert the latest pin write. This can create useful masking/override behaviour + /// due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + INLINE_OUT_EN: u1, + /// Which data bit to use for inline OUT enable + OUT_EN_SEL: u5, + /// The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + JMP_PIN: u5, + /// If 1, side-set data is asserted to pin directions, instead of pin values + SIDE_PINDIR: u1, + /// If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + SIDE_EN: u1, + /// If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes. + EXEC_STALLED: u1, + }), + /// Control behaviour of the input/output shift registers for state machine 1 + SM1_SHIFTCTRL: mmio.Mmio(packed struct(u32) { + reserved16: u16, + /// Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + AUTOPUSH: u1, + /// Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH. + AUTOPULL: u1, + /// 1 = shift input shift register to right (data enters from left). 0 = to left. + IN_SHIFTDIR: u1, + /// 1 = shift out of output shift register to right. 0 = to left. + OUT_SHIFTDIR: u1, + /// Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place. + /// Write 0 for value of 32. + PUSH_THRESH: u5, + /// Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place. + /// Write 0 for value of 32. + PULL_THRESH: u5, + /// When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep. + /// RX FIFO is disabled as a result (always reads as both full and empty). + /// FIFOs are flushed when this bit is changed. + FJOIN_TX: u1, + /// When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep. + /// TX FIFO is disabled as a result (always reads as both full and empty). + /// FIFOs are flushed when this bit is changed. + FJOIN_RX: u1, + }), + /// Current instruction address of state machine 1 + SM1_ADDR: mmio.Mmio(packed struct(u32) { + SM1_ADDR: u5, + padding: u27, + }), + /// Read to see the instruction currently addressed by state machine 1's program counter + /// Write to execute an instruction immediately (including jumps) and then resume execution. + SM1_INSTR: mmio.Mmio(packed struct(u32) { + SM1_INSTR: u16, + padding: u16, + }), + /// State machine pin control + SM1_PINCTRL: mmio.Mmio(packed struct(u32) { + /// The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. + OUT_BASE: u5, + /// The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data. + SET_BASE: u5, + /// The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins. + SIDESET_BASE: u5, + /// The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number. + IN_BASE: u5, + /// The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive. + OUT_COUNT: u6, + /// The number of pins asserted by a SET. In the range 0 to 5 inclusive. + SET_COUNT: u3, + /// The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay). + SIDESET_COUNT: u3, + }), + /// Clock divisor register for state machine 2 + /// Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + SM2_CLKDIV: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// Fractional part of clock divisor + FRAC: u8, + /// Effective frequency is sysclk/(int + frac/256). + /// Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + INT: u16, + }), + /// Execution/behavioural settings for state machine 2 + SM2_EXECCTRL: mmio.Mmio(packed struct(u32) { + /// Comparison level for the MOV x, STATUS instruction + STATUS_N: u4, + /// Comparison used for the MOV x, STATUS instruction. + STATUS_SEL: packed union { + raw: u1, + value: enum(u1) { + /// All-ones if TX FIFO level < N, otherwise all-zeroes + TXLEVEL = 0x0, + /// All-ones if RX FIFO level < N, otherwise all-zeroes + RXLEVEL = 0x1, + }, + }, + reserved7: u2, + /// After reaching wrap_top, execution is wrapped to this address. + WRAP_BOTTOM: u5, + /// After reaching this address, execution is wrapped to wrap_bottom. + /// If the instruction is a jump, and the jump condition is true, the jump takes priority. + WRAP_TOP: u5, + /// Continuously assert the most recent OUT/SET to the pins + OUT_STICKY: u1, + /// If 1, use a bit of OUT data as an auxiliary write enable + /// When used in conjunction with OUT_STICKY, writes with an enable of 0 will + /// deassert the latest pin write. This can create useful masking/override behaviour + /// due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + INLINE_OUT_EN: u1, + /// Which data bit to use for inline OUT enable + OUT_EN_SEL: u5, + /// The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + JMP_PIN: u5, + /// If 1, side-set data is asserted to pin directions, instead of pin values + SIDE_PINDIR: u1, + /// If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + SIDE_EN: u1, + /// If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes. + EXEC_STALLED: u1, + }), + /// Control behaviour of the input/output shift registers for state machine 2 + SM2_SHIFTCTRL: mmio.Mmio(packed struct(u32) { + reserved16: u16, + /// Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + AUTOPUSH: u1, + /// Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH. + AUTOPULL: u1, + /// 1 = shift input shift register to right (data enters from left). 0 = to left. + IN_SHIFTDIR: u1, + /// 1 = shift out of output shift register to right. 0 = to left. + OUT_SHIFTDIR: u1, + /// Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place. + /// Write 0 for value of 32. + PUSH_THRESH: u5, + /// Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place. + /// Write 0 for value of 32. + PULL_THRESH: u5, + /// When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep. + /// RX FIFO is disabled as a result (always reads as both full and empty). + /// FIFOs are flushed when this bit is changed. + FJOIN_TX: u1, + /// When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep. + /// TX FIFO is disabled as a result (always reads as both full and empty). + /// FIFOs are flushed when this bit is changed. + FJOIN_RX: u1, + }), + /// Current instruction address of state machine 2 + SM2_ADDR: mmio.Mmio(packed struct(u32) { + SM2_ADDR: u5, + padding: u27, + }), + /// Read to see the instruction currently addressed by state machine 2's program counter + /// Write to execute an instruction immediately (including jumps) and then resume execution. + SM2_INSTR: mmio.Mmio(packed struct(u32) { + SM2_INSTR: u16, + padding: u16, + }), + /// State machine pin control + SM2_PINCTRL: mmio.Mmio(packed struct(u32) { + /// The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. + OUT_BASE: u5, + /// The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data. + SET_BASE: u5, + /// The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins. + SIDESET_BASE: u5, + /// The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number. + IN_BASE: u5, + /// The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive. + OUT_COUNT: u6, + /// The number of pins asserted by a SET. In the range 0 to 5 inclusive. + SET_COUNT: u3, + /// The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay). + SIDESET_COUNT: u3, + }), + /// Clock divisor register for state machine 3 + /// Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + SM3_CLKDIV: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// Fractional part of clock divisor + FRAC: u8, + /// Effective frequency is sysclk/(int + frac/256). + /// Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + INT: u16, + }), + /// Execution/behavioural settings for state machine 3 + SM3_EXECCTRL: mmio.Mmio(packed struct(u32) { + /// Comparison level for the MOV x, STATUS instruction + STATUS_N: u4, + /// Comparison used for the MOV x, STATUS instruction. + STATUS_SEL: packed union { + raw: u1, + value: enum(u1) { + /// All-ones if TX FIFO level < N, otherwise all-zeroes + TXLEVEL = 0x0, + /// All-ones if RX FIFO level < N, otherwise all-zeroes + RXLEVEL = 0x1, + }, + }, + reserved7: u2, + /// After reaching wrap_top, execution is wrapped to this address. + WRAP_BOTTOM: u5, + /// After reaching this address, execution is wrapped to wrap_bottom. + /// If the instruction is a jump, and the jump condition is true, the jump takes priority. + WRAP_TOP: u5, + /// Continuously assert the most recent OUT/SET to the pins + OUT_STICKY: u1, + /// If 1, use a bit of OUT data as an auxiliary write enable + /// When used in conjunction with OUT_STICKY, writes with an enable of 0 will + /// deassert the latest pin write. This can create useful masking/override behaviour + /// due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + INLINE_OUT_EN: u1, + /// Which data bit to use for inline OUT enable + OUT_EN_SEL: u5, + /// The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + JMP_PIN: u5, + /// If 1, side-set data is asserted to pin directions, instead of pin values + SIDE_PINDIR: u1, + /// If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + SIDE_EN: u1, + /// If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes. + EXEC_STALLED: u1, + }), + /// Control behaviour of the input/output shift registers for state machine 3 + SM3_SHIFTCTRL: mmio.Mmio(packed struct(u32) { + reserved16: u16, + /// Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + AUTOPUSH: u1, + /// Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH. + AUTOPULL: u1, + /// 1 = shift input shift register to right (data enters from left). 0 = to left. + IN_SHIFTDIR: u1, + /// 1 = shift out of output shift register to right. 0 = to left. + OUT_SHIFTDIR: u1, + /// Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place. + /// Write 0 for value of 32. + PUSH_THRESH: u5, + /// Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place. + /// Write 0 for value of 32. + PULL_THRESH: u5, + /// When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep. + /// RX FIFO is disabled as a result (always reads as both full and empty). + /// FIFOs are flushed when this bit is changed. + FJOIN_TX: u1, + /// When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep. + /// TX FIFO is disabled as a result (always reads as both full and empty). + /// FIFOs are flushed when this bit is changed. + FJOIN_RX: u1, + }), + /// Current instruction address of state machine 3 + SM3_ADDR: mmio.Mmio(packed struct(u32) { + SM3_ADDR: u5, + padding: u27, + }), + /// Read to see the instruction currently addressed by state machine 3's program counter + /// Write to execute an instruction immediately (including jumps) and then resume execution. + SM3_INSTR: mmio.Mmio(packed struct(u32) { + SM3_INSTR: u16, + padding: u16, + }), + /// State machine pin control + SM3_PINCTRL: mmio.Mmio(packed struct(u32) { + /// The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. + OUT_BASE: u5, + /// The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data. + SET_BASE: u5, + /// The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins. + SIDESET_BASE: u5, + /// The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number. + IN_BASE: u5, + /// The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive. + OUT_COUNT: u6, + /// The number of pins asserted by a SET. In the range 0 to 5 inclusive. + SET_COUNT: u3, + /// The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay). + SIDESET_COUNT: u3, + }), + /// Raw Interrupts + INTR: mmio.Mmio(packed struct(u32) { + SM0_RXNEMPTY: u1, + SM1_RXNEMPTY: u1, + SM2_RXNEMPTY: u1, + SM3_RXNEMPTY: u1, + SM0_TXNFULL: u1, + SM1_TXNFULL: u1, + SM2_TXNFULL: u1, + SM3_TXNFULL: u1, + SM0: u1, + SM1: u1, + SM2: u1, + SM3: u1, + padding: u20, + }), + /// Interrupt Enable for irq0 + IRQ0_INTE: mmio.Mmio(packed struct(u32) { + SM0_RXNEMPTY: u1, + SM1_RXNEMPTY: u1, + SM2_RXNEMPTY: u1, + SM3_RXNEMPTY: u1, + SM0_TXNFULL: u1, + SM1_TXNFULL: u1, + SM2_TXNFULL: u1, + SM3_TXNFULL: u1, + SM0: u1, + SM1: u1, + SM2: u1, + SM3: u1, + padding: u20, + }), + /// Interrupt Force for irq0 + IRQ0_INTF: mmio.Mmio(packed struct(u32) { + SM0_RXNEMPTY: u1, + SM1_RXNEMPTY: u1, + SM2_RXNEMPTY: u1, + SM3_RXNEMPTY: u1, + SM0_TXNFULL: u1, + SM1_TXNFULL: u1, + SM2_TXNFULL: u1, + SM3_TXNFULL: u1, + SM0: u1, + SM1: u1, + SM2: u1, + SM3: u1, + padding: u20, + }), + /// Interrupt status after masking & forcing for irq0 + IRQ0_INTS: mmio.Mmio(packed struct(u32) { + SM0_RXNEMPTY: u1, + SM1_RXNEMPTY: u1, + SM2_RXNEMPTY: u1, + SM3_RXNEMPTY: u1, + SM0_TXNFULL: u1, + SM1_TXNFULL: u1, + SM2_TXNFULL: u1, + SM3_TXNFULL: u1, + SM0: u1, + SM1: u1, + SM2: u1, + SM3: u1, + padding: u20, + }), + /// Interrupt Enable for irq1 + IRQ1_INTE: mmio.Mmio(packed struct(u32) { + SM0_RXNEMPTY: u1, + SM1_RXNEMPTY: u1, + SM2_RXNEMPTY: u1, + SM3_RXNEMPTY: u1, + SM0_TXNFULL: u1, + SM1_TXNFULL: u1, + SM2_TXNFULL: u1, + SM3_TXNFULL: u1, + SM0: u1, + SM1: u1, + SM2: u1, + SM3: u1, + padding: u20, + }), + /// Interrupt Force for irq1 + IRQ1_INTF: mmio.Mmio(packed struct(u32) { + SM0_RXNEMPTY: u1, + SM1_RXNEMPTY: u1, + SM2_RXNEMPTY: u1, + SM3_RXNEMPTY: u1, + SM0_TXNFULL: u1, + SM1_TXNFULL: u1, + SM2_TXNFULL: u1, + SM3_TXNFULL: u1, + SM0: u1, + SM1: u1, + SM2: u1, + SM3: u1, + padding: u20, + }), + /// Interrupt status after masking & forcing for irq1 + IRQ1_INTS: mmio.Mmio(packed struct(u32) { + SM0_RXNEMPTY: u1, + SM1_RXNEMPTY: u1, + SM2_RXNEMPTY: u1, + SM3_RXNEMPTY: u1, + SM0_TXNFULL: u1, + SM1_TXNFULL: u1, + SM2_TXNFULL: u1, + SM3_TXNFULL: u1, + SM0: u1, + SM1: u1, + SM2: u1, + SM3: u1, + padding: u20, + }), + }; + + /// Control and data interface to SAR ADC + pub const ADC = extern struct { + /// ADC Control and Status + CS: mmio.Mmio(packed struct(u32) { + /// Power on ADC and enable its clock. + /// 1 - enabled. 0 - disabled. + EN: u1, + /// Power on temperature sensor. 1 - enabled. 0 - disabled. + TS_EN: u1, + /// Start a single conversion. Self-clearing. Ignored if start_many is asserted. + START_ONCE: u1, + /// Continuously perform conversions whilst this bit is 1. A new conversion will start immediately after the previous finishes. + START_MANY: u1, + reserved8: u4, + /// 1 if the ADC is ready to start a new conversion. Implies any previous conversion has completed. + /// 0 whilst conversion in progress. + READY: u1, + /// The most recent ADC conversion encountered an error; result is undefined or noisy. + ERR: u1, + /// Some past ADC conversion encountered an error. Write 1 to clear. + ERR_STICKY: u1, + reserved12: u1, + /// Select analog mux input. Updated automatically in round-robin mode. + AINSEL: u3, + reserved16: u1, + /// Round-robin sampling. 1 bit per channel. Set all bits to 0 to disable. + /// Otherwise, the ADC will cycle through each enabled channel in a round-robin fashion. + /// The first channel to be sampled will be the one currently indicated by AINSEL. + /// AINSEL will be updated after each conversion with the newly-selected channel. + RROBIN: u5, + padding: u11, + }), + /// Result of most recent ADC conversion + RESULT: mmio.Mmio(packed struct(u32) { + RESULT: u12, + padding: u20, + }), + /// FIFO control and status + FCS: mmio.Mmio(packed struct(u32) { + /// If 1: write result to the FIFO after each conversion. + EN: u1, + /// If 1: FIFO results are right-shifted to be one byte in size. Enables DMA to byte buffers. + SHIFT: u1, + /// If 1: conversion error bit appears in the FIFO alongside the result + ERR: u1, + /// If 1: assert DMA requests when FIFO contains data + DREQ_EN: u1, + reserved8: u4, + EMPTY: u1, + FULL: u1, + /// 1 if the FIFO has been underflowed. Write 1 to clear. + UNDER: u1, + /// 1 if the FIFO has been overflowed. Write 1 to clear. + OVER: u1, + reserved16: u4, + /// The number of conversion results currently waiting in the FIFO + LEVEL: u4, + reserved24: u4, + /// DREQ/IRQ asserted when level >= threshold + THRESH: u4, + padding: u4, + }), + /// Conversion result FIFO + FIFO: mmio.Mmio(packed struct(u32) { + VAL: u12, + reserved15: u3, + /// 1 if this particular sample experienced a conversion error. Remains in the same location if the sample is shifted. + ERR: u1, + padding: u16, + }), + /// Clock divider. If non-zero, CS_START_MANY will start conversions + /// at regular intervals rather than back-to-back. + /// The divider is reset when either of these fields are written. + /// Total period is 1 + INT + FRAC / 256 + DIV: mmio.Mmio(packed struct(u32) { + /// Fractional part of clock divisor. First-order delta-sigma. + FRAC: u8, + /// Integer part of clock divisor. + INT: u16, + padding: u8, + }), + /// Raw Interrupts + INTR: mmio.Mmio(packed struct(u32) { + /// Triggered when the sample FIFO reaches a certain level. + /// This level can be programmed via the FCS_THRESH field. + FIFO: u1, + padding: u31, + }), + /// Interrupt Enable + INTE: mmio.Mmio(packed struct(u32) { + /// Triggered when the sample FIFO reaches a certain level. + /// This level can be programmed via the FCS_THRESH field. + FIFO: u1, + padding: u31, + }), + /// Interrupt Force + INTF: mmio.Mmio(packed struct(u32) { + /// Triggered when the sample FIFO reaches a certain level. + /// This level can be programmed via the FCS_THRESH field. + FIFO: u1, + padding: u31, + }), + /// Interrupt status after masking & forcing + INTS: mmio.Mmio(packed struct(u32) { + /// Triggered when the sample FIFO reaches a certain level. + /// This level can be programmed via the FCS_THRESH field. + FIFO: u1, + padding: u31, + }), + }; + + /// Simple PWM + pub const PWM = extern struct { + /// Control and status register + CH0_CSR: mmio.Mmio(packed struct(u32) { + /// Enable the PWM channel. + EN: u1, + /// 1: Enable phase-correct modulation. 0: Trailing-edge + PH_CORRECT: u1, + /// Invert output A + A_INV: u1, + /// Invert output B + B_INV: u1, + DIVMODE: packed union { + raw: u2, + value: enum(u2) { + /// Free-running counting at rate dictated by fractional divider + div = 0x0, + /// Fractional divider operation is gated by the PWM B pin. + level = 0x1, + /// Counter advances with each rising edge of the PWM B pin. + rise = 0x2, + /// Counter advances with each falling edge of the PWM B pin. + fall = 0x3, + }, + }, + /// Retard the phase of the counter by 1 count, while it is running. + /// Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_RET: u1, + /// Advance the phase of the counter by 1 count, while it is running. + /// Self-clearing. Write a 1, and poll until low. Counter must be running + /// at less than full speed (div_int + div_frac / 16 > 1) + PH_ADV: u1, + padding: u24, + }), + /// INT and FRAC form a fixed-point fractional number. + /// Counting rate is system clock frequency divided by this number. + /// Fractional division uses simple 1st-order sigma-delta. + CH0_DIV: mmio.Mmio(packed struct(u32) { + FRAC: u4, + INT: u8, + padding: u20, + }), + /// Direct access to the PWM counter + CH0_CTR: mmio.Mmio(packed struct(u32) { + CH0_CTR: u16, + padding: u16, + }), + /// Counter compare values + CH0_CC: mmio.Mmio(packed struct(u32) { + A: u16, + B: u16, + }), + /// Counter wrap value + CH0_TOP: mmio.Mmio(packed struct(u32) { + CH0_TOP: u16, + padding: u16, + }), + /// Control and status register + CH1_CSR: mmio.Mmio(packed struct(u32) { + /// Enable the PWM channel. + EN: u1, + /// 1: Enable phase-correct modulation. 0: Trailing-edge + PH_CORRECT: u1, + /// Invert output A + A_INV: u1, + /// Invert output B + B_INV: u1, + DIVMODE: packed union { + raw: u2, + value: enum(u2) { + /// Free-running counting at rate dictated by fractional divider + div = 0x0, + /// Fractional divider operation is gated by the PWM B pin. + level = 0x1, + /// Counter advances with each rising edge of the PWM B pin. + rise = 0x2, + /// Counter advances with each falling edge of the PWM B pin. + fall = 0x3, + }, + }, + /// Retard the phase of the counter by 1 count, while it is running. + /// Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_RET: u1, + /// Advance the phase of the counter by 1 count, while it is running. + /// Self-clearing. Write a 1, and poll until low. Counter must be running + /// at less than full speed (div_int + div_frac / 16 > 1) + PH_ADV: u1, + padding: u24, + }), + /// INT and FRAC form a fixed-point fractional number. + /// Counting rate is system clock frequency divided by this number. + /// Fractional division uses simple 1st-order sigma-delta. + CH1_DIV: mmio.Mmio(packed struct(u32) { + FRAC: u4, + INT: u8, + padding: u20, + }), + /// Direct access to the PWM counter + CH1_CTR: mmio.Mmio(packed struct(u32) { + CH1_CTR: u16, + padding: u16, + }), + /// Counter compare values + CH1_CC: mmio.Mmio(packed struct(u32) { + A: u16, + B: u16, + }), + /// Counter wrap value + CH1_TOP: mmio.Mmio(packed struct(u32) { + CH1_TOP: u16, + padding: u16, + }), + /// Control and status register + CH2_CSR: mmio.Mmio(packed struct(u32) { + /// Enable the PWM channel. + EN: u1, + /// 1: Enable phase-correct modulation. 0: Trailing-edge + PH_CORRECT: u1, + /// Invert output A + A_INV: u1, + /// Invert output B + B_INV: u1, + DIVMODE: packed union { + raw: u2, + value: enum(u2) { + /// Free-running counting at rate dictated by fractional divider + div = 0x0, + /// Fractional divider operation is gated by the PWM B pin. + level = 0x1, + /// Counter advances with each rising edge of the PWM B pin. + rise = 0x2, + /// Counter advances with each falling edge of the PWM B pin. + fall = 0x3, + }, + }, + /// Retard the phase of the counter by 1 count, while it is running. + /// Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_RET: u1, + /// Advance the phase of the counter by 1 count, while it is running. + /// Self-clearing. Write a 1, and poll until low. Counter must be running + /// at less than full speed (div_int + div_frac / 16 > 1) + PH_ADV: u1, + padding: u24, + }), + /// INT and FRAC form a fixed-point fractional number. + /// Counting rate is system clock frequency divided by this number. + /// Fractional division uses simple 1st-order sigma-delta. + CH2_DIV: mmio.Mmio(packed struct(u32) { + FRAC: u4, + INT: u8, + padding: u20, + }), + /// Direct access to the PWM counter + CH2_CTR: mmio.Mmio(packed struct(u32) { + CH2_CTR: u16, + padding: u16, + }), + /// Counter compare values + CH2_CC: mmio.Mmio(packed struct(u32) { + A: u16, + B: u16, + }), + /// Counter wrap value + CH2_TOP: mmio.Mmio(packed struct(u32) { + CH2_TOP: u16, + padding: u16, + }), + /// Control and status register + CH3_CSR: mmio.Mmio(packed struct(u32) { + /// Enable the PWM channel. + EN: u1, + /// 1: Enable phase-correct modulation. 0: Trailing-edge + PH_CORRECT: u1, + /// Invert output A + A_INV: u1, + /// Invert output B + B_INV: u1, + DIVMODE: packed union { + raw: u2, + value: enum(u2) { + /// Free-running counting at rate dictated by fractional divider + div = 0x0, + /// Fractional divider operation is gated by the PWM B pin. + level = 0x1, + /// Counter advances with each rising edge of the PWM B pin. + rise = 0x2, + /// Counter advances with each falling edge of the PWM B pin. + fall = 0x3, + }, + }, + /// Retard the phase of the counter by 1 count, while it is running. + /// Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_RET: u1, + /// Advance the phase of the counter by 1 count, while it is running. + /// Self-clearing. Write a 1, and poll until low. Counter must be running + /// at less than full speed (div_int + div_frac / 16 > 1) + PH_ADV: u1, + padding: u24, + }), + /// INT and FRAC form a fixed-point fractional number. + /// Counting rate is system clock frequency divided by this number. + /// Fractional division uses simple 1st-order sigma-delta. + CH3_DIV: mmio.Mmio(packed struct(u32) { + FRAC: u4, + INT: u8, + padding: u20, + }), + /// Direct access to the PWM counter + CH3_CTR: mmio.Mmio(packed struct(u32) { + CH3_CTR: u16, + padding: u16, + }), + /// Counter compare values + CH3_CC: mmio.Mmio(packed struct(u32) { + A: u16, + B: u16, + }), + /// Counter wrap value + CH3_TOP: mmio.Mmio(packed struct(u32) { + CH3_TOP: u16, + padding: u16, + }), + /// Control and status register + CH4_CSR: mmio.Mmio(packed struct(u32) { + /// Enable the PWM channel. + EN: u1, + /// 1: Enable phase-correct modulation. 0: Trailing-edge + PH_CORRECT: u1, + /// Invert output A + A_INV: u1, + /// Invert output B + B_INV: u1, + DIVMODE: packed union { + raw: u2, + value: enum(u2) { + /// Free-running counting at rate dictated by fractional divider + div = 0x0, + /// Fractional divider operation is gated by the PWM B pin. + level = 0x1, + /// Counter advances with each rising edge of the PWM B pin. + rise = 0x2, + /// Counter advances with each falling edge of the PWM B pin. + fall = 0x3, + }, + }, + /// Retard the phase of the counter by 1 count, while it is running. + /// Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_RET: u1, + /// Advance the phase of the counter by 1 count, while it is running. + /// Self-clearing. Write a 1, and poll until low. Counter must be running + /// at less than full speed (div_int + div_frac / 16 > 1) + PH_ADV: u1, + padding: u24, + }), + /// INT and FRAC form a fixed-point fractional number. + /// Counting rate is system clock frequency divided by this number. + /// Fractional division uses simple 1st-order sigma-delta. + CH4_DIV: mmio.Mmio(packed struct(u32) { + FRAC: u4, + INT: u8, + padding: u20, + }), + /// Direct access to the PWM counter + CH4_CTR: mmio.Mmio(packed struct(u32) { + CH4_CTR: u16, + padding: u16, + }), + /// Counter compare values + CH4_CC: mmio.Mmio(packed struct(u32) { + A: u16, + B: u16, + }), + /// Counter wrap value + CH4_TOP: mmio.Mmio(packed struct(u32) { + CH4_TOP: u16, + padding: u16, + }), + /// Control and status register + CH5_CSR: mmio.Mmio(packed struct(u32) { + /// Enable the PWM channel. + EN: u1, + /// 1: Enable phase-correct modulation. 0: Trailing-edge + PH_CORRECT: u1, + /// Invert output A + A_INV: u1, + /// Invert output B + B_INV: u1, + DIVMODE: packed union { + raw: u2, + value: enum(u2) { + /// Free-running counting at rate dictated by fractional divider + div = 0x0, + /// Fractional divider operation is gated by the PWM B pin. + level = 0x1, + /// Counter advances with each rising edge of the PWM B pin. + rise = 0x2, + /// Counter advances with each falling edge of the PWM B pin. + fall = 0x3, + }, + }, + /// Retard the phase of the counter by 1 count, while it is running. + /// Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_RET: u1, + /// Advance the phase of the counter by 1 count, while it is running. + /// Self-clearing. Write a 1, and poll until low. Counter must be running + /// at less than full speed (div_int + div_frac / 16 > 1) + PH_ADV: u1, + padding: u24, + }), + /// INT and FRAC form a fixed-point fractional number. + /// Counting rate is system clock frequency divided by this number. + /// Fractional division uses simple 1st-order sigma-delta. + CH5_DIV: mmio.Mmio(packed struct(u32) { + FRAC: u4, + INT: u8, + padding: u20, + }), + /// Direct access to the PWM counter + CH5_CTR: mmio.Mmio(packed struct(u32) { + CH5_CTR: u16, + padding: u16, + }), + /// Counter compare values + CH5_CC: mmio.Mmio(packed struct(u32) { + A: u16, + B: u16, + }), + /// Counter wrap value + CH5_TOP: mmio.Mmio(packed struct(u32) { + CH5_TOP: u16, + padding: u16, + }), + /// Control and status register + CH6_CSR: mmio.Mmio(packed struct(u32) { + /// Enable the PWM channel. + EN: u1, + /// 1: Enable phase-correct modulation. 0: Trailing-edge + PH_CORRECT: u1, + /// Invert output A + A_INV: u1, + /// Invert output B + B_INV: u1, + DIVMODE: packed union { + raw: u2, + value: enum(u2) { + /// Free-running counting at rate dictated by fractional divider + div = 0x0, + /// Fractional divider operation is gated by the PWM B pin. + level = 0x1, + /// Counter advances with each rising edge of the PWM B pin. + rise = 0x2, + /// Counter advances with each falling edge of the PWM B pin. + fall = 0x3, + }, + }, + /// Retard the phase of the counter by 1 count, while it is running. + /// Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_RET: u1, + /// Advance the phase of the counter by 1 count, while it is running. + /// Self-clearing. Write a 1, and poll until low. Counter must be running + /// at less than full speed (div_int + div_frac / 16 > 1) + PH_ADV: u1, + padding: u24, + }), + /// INT and FRAC form a fixed-point fractional number. + /// Counting rate is system clock frequency divided by this number. + /// Fractional division uses simple 1st-order sigma-delta. + CH6_DIV: mmio.Mmio(packed struct(u32) { + FRAC: u4, + INT: u8, + padding: u20, + }), + /// Direct access to the PWM counter + CH6_CTR: mmio.Mmio(packed struct(u32) { + CH6_CTR: u16, + padding: u16, + }), + /// Counter compare values + CH6_CC: mmio.Mmio(packed struct(u32) { + A: u16, + B: u16, + }), + /// Counter wrap value + CH6_TOP: mmio.Mmio(packed struct(u32) { + CH6_TOP: u16, + padding: u16, + }), + /// Control and status register + CH7_CSR: mmio.Mmio(packed struct(u32) { + /// Enable the PWM channel. + EN: u1, + /// 1: Enable phase-correct modulation. 0: Trailing-edge + PH_CORRECT: u1, + /// Invert output A + A_INV: u1, + /// Invert output B + B_INV: u1, + DIVMODE: packed union { + raw: u2, + value: enum(u2) { + /// Free-running counting at rate dictated by fractional divider + div = 0x0, + /// Fractional divider operation is gated by the PWM B pin. + level = 0x1, + /// Counter advances with each rising edge of the PWM B pin. + rise = 0x2, + /// Counter advances with each falling edge of the PWM B pin. + fall = 0x3, + }, + }, + /// Retard the phase of the counter by 1 count, while it is running. + /// Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_RET: u1, + /// Advance the phase of the counter by 1 count, while it is running. + /// Self-clearing. Write a 1, and poll until low. Counter must be running + /// at less than full speed (div_int + div_frac / 16 > 1) + PH_ADV: u1, + padding: u24, + }), + /// INT and FRAC form a fixed-point fractional number. + /// Counting rate is system clock frequency divided by this number. + /// Fractional division uses simple 1st-order sigma-delta. + CH7_DIV: mmio.Mmio(packed struct(u32) { + FRAC: u4, + INT: u8, + padding: u20, + }), + /// Direct access to the PWM counter + CH7_CTR: mmio.Mmio(packed struct(u32) { + CH7_CTR: u16, + padding: u16, + }), + /// Counter compare values + CH7_CC: mmio.Mmio(packed struct(u32) { + A: u16, + B: u16, + }), + /// Counter wrap value + CH7_TOP: mmio.Mmio(packed struct(u32) { + CH7_TOP: u16, + padding: u16, + }), + /// This register aliases the CSR_EN bits for all channels. + /// Writing to this register allows multiple channels to be enabled + /// or disabled simultaneously, so they can run in perfect sync. + /// For each channel, there is only one physical EN register bit, + /// which can be accessed through here or CHx_CSR. + EN: mmio.Mmio(packed struct(u32) { + CH0: u1, + CH1: u1, + CH2: u1, + CH3: u1, + CH4: u1, + CH5: u1, + CH6: u1, + CH7: u1, + padding: u24, + }), + /// Raw Interrupts + INTR: mmio.Mmio(packed struct(u32) { + CH0: u1, + CH1: u1, + CH2: u1, + CH3: u1, + CH4: u1, + CH5: u1, + CH6: u1, + CH7: u1, + padding: u24, + }), + /// Interrupt Enable + INTE: mmio.Mmio(packed struct(u32) { + CH0: u1, + CH1: u1, + CH2: u1, + CH3: u1, + CH4: u1, + CH5: u1, + CH6: u1, + CH7: u1, + padding: u24, + }), + /// Interrupt Force + INTF: mmio.Mmio(packed struct(u32) { + CH0: u1, + CH1: u1, + CH2: u1, + CH3: u1, + CH4: u1, + CH5: u1, + CH6: u1, + CH7: u1, + padding: u24, + }), + /// Interrupt status after masking & forcing + INTS: mmio.Mmio(packed struct(u32) { + CH0: u1, + CH1: u1, + CH2: u1, + CH3: u1, + CH4: u1, + CH5: u1, + CH6: u1, + CH7: u1, + padding: u24, + }), + }; + + /// Controls time and alarms + /// time is a 64 bit value indicating the time in usec since power-on + /// timeh is the top 32 bits of time & timel is the bottom 32 bits + /// to change time write to timelw before timehw + /// to read time read from timelr before timehr + /// An alarm is set by setting alarm_enable and writing to the corresponding alarm register + /// When an alarm is pending, the corresponding alarm_running signal will be high + /// An alarm can be cancelled before it has finished by clearing the alarm_enable + /// When an alarm fires, the corresponding alarm_irq is set and alarm_running is cleared + /// To clear the interrupt write a 1 to the corresponding alarm_irq + pub const TIMER = extern struct { + /// Write to bits 63:32 of time + /// always write timelw before timehw + TIMEHW: u32, + /// Write to bits 31:0 of time + /// writes do not get copied to time until timehw is written + TIMELW: u32, + /// Read from bits 63:32 of time + /// always read timelr before timehr + TIMEHR: u32, + /// Read from bits 31:0 of time + TIMELR: u32, + /// Arm alarm 0, and configure the time it will fire. + /// Once armed, the alarm fires when TIMER_ALARM0 == TIMELR. + /// The alarm will disarm itself once it fires, and can + /// be disarmed early using the ARMED status register. + ALARM0: u32, + /// Arm alarm 1, and configure the time it will fire. + /// Once armed, the alarm fires when TIMER_ALARM1 == TIMELR. + /// The alarm will disarm itself once it fires, and can + /// be disarmed early using the ARMED status register. + ALARM1: u32, + /// Arm alarm 2, and configure the time it will fire. + /// Once armed, the alarm fires when TIMER_ALARM2 == TIMELR. + /// The alarm will disarm itself once it fires, and can + /// be disarmed early using the ARMED status register. + ALARM2: u32, + /// Arm alarm 3, and configure the time it will fire. + /// Once armed, the alarm fires when TIMER_ALARM3 == TIMELR. + /// The alarm will disarm itself once it fires, and can + /// be disarmed early using the ARMED status register. + ALARM3: u32, + /// Indicates the armed/disarmed status of each alarm. + /// A write to the corresponding ALARMx register arms the alarm. + /// Alarms automatically disarm upon firing, but writing ones here + /// will disarm immediately without waiting to fire. + ARMED: mmio.Mmio(packed struct(u32) { + ARMED: u4, + padding: u28, + }), + /// Raw read from bits 63:32 of time (no side effects) + TIMERAWH: u32, + /// Raw read from bits 31:0 of time (no side effects) + TIMERAWL: u32, + /// Set bits high to enable pause when the corresponding debug ports are active + DBGPAUSE: mmio.Mmio(packed struct(u32) { + reserved1: u1, + /// Pause when processor 0 is in debug mode + DBG0: u1, + /// Pause when processor 1 is in debug mode + DBG1: u1, + padding: u29, + }), + /// Set high to pause the timer + PAUSE: mmio.Mmio(packed struct(u32) { + PAUSE: u1, + padding: u31, + }), + /// Raw Interrupts + INTR: mmio.Mmio(packed struct(u32) { + ALARM_0: u1, + ALARM_1: u1, + ALARM_2: u1, + ALARM_3: u1, + padding: u28, + }), + /// Interrupt Enable + INTE: mmio.Mmio(packed struct(u32) { + ALARM_0: u1, + ALARM_1: u1, + ALARM_2: u1, + ALARM_3: u1, + padding: u28, + }), + /// Interrupt Force + INTF: mmio.Mmio(packed struct(u32) { + ALARM_0: u1, + ALARM_1: u1, + ALARM_2: u1, + ALARM_3: u1, + padding: u28, + }), + /// Interrupt status after masking & forcing + INTS: mmio.Mmio(packed struct(u32) { + ALARM_0: u1, + ALARM_1: u1, + ALARM_2: u1, + ALARM_3: u1, + padding: u28, + }), + }; + + pub const WATCHDOG = extern struct { + /// Watchdog control + /// The rst_wdsel register determines which subsystems are reset when the watchdog is triggered. + /// The watchdog can be triggered in software. + CTRL: mmio.Mmio(packed struct(u32) { + /// Indicates the number of ticks / 2 (see errata RP2040-E1) before a watchdog reset will be triggered + TIME: u24, + /// Pause the watchdog timer when JTAG is accessing the bus fabric + PAUSE_JTAG: u1, + /// Pause the watchdog timer when processor 0 is in debug mode + PAUSE_DBG0: u1, + /// Pause the watchdog timer when processor 1 is in debug mode + PAUSE_DBG1: u1, + reserved30: u3, + /// When not enabled the watchdog timer is paused + ENABLE: u1, + /// Trigger a watchdog reset + TRIGGER: u1, + }), + /// Load the watchdog timer. The maximum setting is 0xffffff which corresponds to 0xffffff / 2 ticks before triggering a watchdog reset (see errata RP2040-E1). + LOAD: mmio.Mmio(packed struct(u32) { + LOAD: u24, + padding: u8, + }), + /// Logs the reason for the last reset. Both bits are zero for the case of a hardware reset. + REASON: mmio.Mmio(packed struct(u32) { + TIMER: u1, + FORCE: u1, + padding: u30, + }), + /// Scratch register. Information persists through soft reset of the chip. + SCRATCH0: u32, + /// Scratch register. Information persists through soft reset of the chip. + SCRATCH1: u32, + /// Scratch register. Information persists through soft reset of the chip. + SCRATCH2: u32, + /// Scratch register. Information persists through soft reset of the chip. + SCRATCH3: u32, + /// Scratch register. Information persists through soft reset of the chip. + SCRATCH4: u32, + /// Scratch register. Information persists through soft reset of the chip. + SCRATCH5: u32, + /// Scratch register. Information persists through soft reset of the chip. + SCRATCH6: u32, + /// Scratch register. Information persists through soft reset of the chip. + SCRATCH7: u32, + /// Controls the tick generator + TICK: mmio.Mmio(packed struct(u32) { + /// Total number of clk_tick cycles before the next tick. + CYCLES: u9, + /// start / stop tick generation + ENABLE: u1, + /// Is the tick generator running? + RUNNING: u1, + /// Count down timer: the remaining number clk_tick cycles before the next tick is generated. + COUNT: u9, + padding: u12, + }), + }; + + /// Register block to control RTC + pub const RTC = extern struct { + /// Divider minus 1 for the 1 second counter. Safe to change the value when RTC is not enabled. + CLKDIV_M1: mmio.Mmio(packed struct(u32) { + CLKDIV_M1: u16, + padding: u16, + }), + /// RTC setup register 0 + SETUP_0: mmio.Mmio(packed struct(u32) { + /// Day of the month (1..31) + DAY: u5, + reserved8: u3, + /// Month (1..12) + MONTH: u4, + /// Year + YEAR: u12, + padding: u8, + }), + /// RTC setup register 1 + SETUP_1: mmio.Mmio(packed struct(u32) { + /// Seconds + SEC: u6, + reserved8: u2, + /// Minutes + MIN: u6, + reserved16: u2, + /// Hours + HOUR: u5, + reserved24: u3, + /// Day of the week: 1-Monday...0-Sunday ISO 8601 mod 7 + DOTW: u3, + padding: u5, + }), + /// RTC Control and status + CTRL: mmio.Mmio(packed struct(u32) { + /// Enable RTC + RTC_ENABLE: u1, + /// RTC enabled (running) + RTC_ACTIVE: u1, + reserved4: u2, + /// Load RTC + LOAD: u1, + reserved8: u3, + /// If set, leapyear is forced off. + /// Useful for years divisible by 100 but not by 400 + FORCE_NOTLEAPYEAR: u1, + padding: u23, + }), + /// Interrupt setup register 0 + IRQ_SETUP_0: mmio.Mmio(packed struct(u32) { + /// Day of the month (1..31) + DAY: u5, + reserved8: u3, + /// Month (1..12) + MONTH: u4, + /// Year + YEAR: u12, + /// Enable day matching + DAY_ENA: u1, + /// Enable month matching + MONTH_ENA: u1, + /// Enable year matching + YEAR_ENA: u1, + reserved28: u1, + /// Global match enable. Don't change any other value while this one is enabled + MATCH_ENA: u1, + MATCH_ACTIVE: u1, + padding: u2, + }), + /// Interrupt setup register 1 + IRQ_SETUP_1: mmio.Mmio(packed struct(u32) { + /// Seconds + SEC: u6, + reserved8: u2, + /// Minutes + MIN: u6, + reserved16: u2, + /// Hours + HOUR: u5, + reserved24: u3, + /// Day of the week + DOTW: u3, + reserved28: u1, + /// Enable second matching + SEC_ENA: u1, + /// Enable minute matching + MIN_ENA: u1, + /// Enable hour matching + HOUR_ENA: u1, + /// Enable day of the week matching + DOTW_ENA: u1, + }), + /// RTC register 1. + RTC_1: mmio.Mmio(packed struct(u32) { + /// Day of the month (1..31) + DAY: u5, + reserved8: u3, + /// Month (1..12) + MONTH: u4, + /// Year + YEAR: u12, + padding: u8, + }), + /// RTC register 0 + /// Read this before RTC 1! + RTC_0: mmio.Mmio(packed struct(u32) { + /// Seconds + SEC: u6, + reserved8: u2, + /// Minutes + MIN: u6, + reserved16: u2, + /// Hours + HOUR: u5, + reserved24: u3, + /// Day of the week + DOTW: u3, + padding: u5, + }), + /// Raw Interrupts + INTR: mmio.Mmio(packed struct(u32) { + RTC: u1, + padding: u31, + }), + /// Interrupt Enable + INTE: mmio.Mmio(packed struct(u32) { + RTC: u1, + padding: u31, + }), + /// Interrupt Force + INTF: mmio.Mmio(packed struct(u32) { + RTC: u1, + padding: u31, + }), + /// Interrupt status after masking & forcing + INTS: mmio.Mmio(packed struct(u32) { + RTC: u1, + padding: u31, + }), + }; + + pub const ROSC = extern struct { + /// Ring Oscillator control + CTRL: mmio.Mmio(packed struct(u32) { + /// Controls the number of delay stages in the ROSC ring + /// LOW uses stages 0 to 7 + /// MEDIUM uses stages 0 to 5 + /// HIGH uses stages 0 to 3 + /// TOOHIGH uses stages 0 to 1 and should not be used because its frequency exceeds design specifications + /// The clock output will not glitch when changing the range up one step at a time + /// The clock output will glitch when changing the range down + /// Note: the values here are gray coded which is why HIGH comes before TOOHIGH + FREQ_RANGE: packed union { + raw: u12, + value: enum(u12) { + LOW = 0xfa4, + MEDIUM = 0xfa5, + HIGH = 0xfa7, + TOOHIGH = 0xfa6, + _, + }, + }, + /// On power-up this field is initialised to ENABLE + /// The system clock must be switched to another source before setting this field to DISABLE otherwise the chip will lock up + /// The 12-bit code is intended to give some protection against accidental writes. An invalid setting will enable the oscillator. + ENABLE: packed union { + raw: u12, + value: enum(u12) { + DISABLE = 0xd1e, + ENABLE = 0xfab, + _, + }, + }, + padding: u8, + }), + /// The FREQA & FREQB registers control the frequency by controlling the drive strength of each stage + /// The drive strength has 4 levels determined by the number of bits set + /// Increasing the number of bits set increases the drive strength and increases the oscillation frequency + /// 0 bits set is the default drive strength + /// 1 bit set doubles the drive strength + /// 2 bits set triples drive strength + /// 3 bits set quadruples drive strength + FREQA: mmio.Mmio(packed struct(u32) { + /// Stage 0 drive strength + DS0: u3, + reserved4: u1, + /// Stage 1 drive strength + DS1: u3, + reserved8: u1, + /// Stage 2 drive strength + DS2: u3, + reserved12: u1, + /// Stage 3 drive strength + DS3: u3, + reserved16: u1, + /// Set to 0x9696 to apply the settings + /// Any other value in this field will set all drive strengths to 0 + PASSWD: packed union { + raw: u16, + value: enum(u16) { + PASS = 0x9696, + _, + }, + }, + }), + /// For a detailed description see freqa register + FREQB: mmio.Mmio(packed struct(u32) { + /// Stage 4 drive strength + DS4: u3, + reserved4: u1, + /// Stage 5 drive strength + DS5: u3, + reserved8: u1, + /// Stage 6 drive strength + DS6: u3, + reserved12: u1, + /// Stage 7 drive strength + DS7: u3, + reserved16: u1, + /// Set to 0x9696 to apply the settings + /// Any other value in this field will set all drive strengths to 0 + PASSWD: packed union { + raw: u16, + value: enum(u16) { + PASS = 0x9696, + _, + }, + }, + }), + /// Ring Oscillator pause control + /// This is used to save power by pausing the ROSC + /// On power-up this field is initialised to WAKE + /// An invalid write will also select WAKE + /// Warning: setup the irq before selecting dormant mode + DORMANT: u32, + /// Controls the output divider + DIV: mmio.Mmio(packed struct(u32) { + /// set to 0xaa0 + div where + /// div = 0 divides by 32 + /// div = 1-31 divides by div + /// any other value sets div=31 + /// this register resets to div=16 + DIV: packed union { + raw: u12, + value: enum(u12) { + PASS = 0xaa0, + _, + }, + }, + padding: u20, + }), + /// Controls the phase shifted output + PHASE: mmio.Mmio(packed struct(u32) { + /// phase shift the phase-shifted output by SHIFT input clocks + /// this can be changed on-the-fly + /// must be set to 0 before setting div=1 + SHIFT: u2, + /// invert the phase-shifted output + /// this is ignored when div=1 + FLIP: u1, + /// enable the phase-shifted output + /// this can be changed on-the-fly + ENABLE: u1, + /// set to 0xaa + /// any other value enables the output with shift=0 + PASSWD: u8, + padding: u20, + }), + /// Ring Oscillator Status + STATUS: mmio.Mmio(packed struct(u32) { + reserved12: u12, + /// Oscillator is enabled but not necessarily running and stable + /// this resets to 0 but transitions to 1 during chip startup + ENABLED: u1, + reserved16: u3, + /// post-divider is running + /// this resets to 0 but transitions to 1 during chip startup + DIV_RUNNING: u1, + reserved24: u7, + /// An invalid value has been written to CTRL_ENABLE or CTRL_FREQ_RANGE or FREQA or FREQB or DIV or PHASE or DORMANT + BADWRITE: u1, + reserved31: u6, + /// Oscillator is running and stable + STABLE: u1, + }), + /// This just reads the state of the oscillator output so randomness is compromised if the ring oscillator is stopped or run at a harmonic of the bus frequency + RANDOMBIT: mmio.Mmio(packed struct(u32) { + RANDOMBIT: u1, + padding: u31, + }), + /// A down counter running at the ROSC frequency which counts to zero and stops. + /// To start the counter write a non-zero value. + /// Can be used for short software pauses when setting up time sensitive hardware. + COUNT: mmio.Mmio(packed struct(u32) { + COUNT: u8, + padding: u24, + }), + }; + + /// control and status for on-chip voltage regulator and chip level reset subsystem + pub const VREG_AND_CHIP_RESET = extern struct { + /// Voltage regulator control and status + VREG: mmio.Mmio(packed struct(u32) { + /// enable + /// 0=not enabled, 1=enabled + EN: u1, + /// high impedance mode select + /// 0=not in high impedance mode, 1=in high impedance mode + HIZ: u1, + reserved4: u2, + /// output voltage select + /// 0000 to 0101 - 0.80V + /// 0110 - 0.85V + /// 0111 - 0.90V + /// 1000 - 0.95V + /// 1001 - 1.00V + /// 1010 - 1.05V + /// 1011 - 1.10V (default) + /// 1100 - 1.15V + /// 1101 - 1.20V + /// 1110 - 1.25V + /// 1111 - 1.30V + VSEL: u4, + reserved12: u4, + /// regulation status + /// 0=not in regulation, 1=in regulation + ROK: u1, + padding: u19, + }), + /// brown-out detection control + BOD: mmio.Mmio(packed struct(u32) { + /// enable + /// 0=not enabled, 1=enabled + EN: u1, + reserved4: u3, + /// threshold select + /// 0000 - 0.473V + /// 0001 - 0.516V + /// 0010 - 0.559V + /// 0011 - 0.602V + /// 0100 - 0.645V + /// 0101 - 0.688V + /// 0110 - 0.731V + /// 0111 - 0.774V + /// 1000 - 0.817V + /// 1001 - 0.860V (default) + /// 1010 - 0.903V + /// 1011 - 0.946V + /// 1100 - 0.989V + /// 1101 - 1.032V + /// 1110 - 1.075V + /// 1111 - 1.118V + VSEL: u4, + padding: u24, + }), + /// Chip reset control and status + CHIP_RESET: mmio.Mmio(packed struct(u32) { + reserved8: u8, + /// Last reset was from the power-on reset or brown-out detection blocks + HAD_POR: u1, + reserved16: u7, + /// Last reset was from the RUN pin + HAD_RUN: u1, + reserved20: u3, + /// Last reset was from the debug port + HAD_PSM_RESTART: u1, + reserved24: u3, + /// This is set by psm_restart from the debugger. + /// Its purpose is to branch bootcode to a safe mode when the debugger has issued a psm_restart in order to recover from a boot lock-up. + /// In the safe mode the debugger can repair the boot code, clear this flag then reboot the processor. + PSM_RESTART_FLAG: u1, + padding: u7, + }), + }; + + /// Testbench manager. Allows the programmer to know what platform their software is running on. + pub const TBMAN = extern struct { + /// Indicates the type of platform in use + PLATFORM: mmio.Mmio(packed struct(u32) { + /// Indicates the platform is an ASIC + ASIC: u1, + /// Indicates the platform is an FPGA + FPGA: u1, + padding: u30, + }), + }; + + /// DMA with separate read and write masters + pub const DMA = extern struct { + /// DMA Channel 0 Read Address pointer + /// This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + CH0_READ_ADDR: u32, + /// DMA Channel 0 Write Address pointer + /// This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + CH0_WRITE_ADDR: u32, + /// DMA Channel 0 Transfer Count + /// Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + /// When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + /// Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + CH0_TRANS_COUNT: u32, + /// DMA Channel 0 Control and Status + CH0_CTRL_TRIG: mmio.Mmio(packed struct(u32) { + /// DMA Channel Enable. + /// When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + EN: u1, + /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + /// This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + HIGH_PRIORITY: u1, + /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + DATA_SIZE: packed union { + raw: u2, + value: enum(u2) { + SIZE_BYTE = 0x0, + SIZE_HALFWORD = 0x1, + SIZE_WORD = 0x2, + _, + }, + }, + /// If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + /// Generally this should be disabled for peripheral-to-memory transfers. + INCR_READ: u1, + /// If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + /// Generally this should be disabled for memory-to-peripheral transfers. + INCR_WRITE: u1, + /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SIZE: packed union { + raw: u4, + value: enum(u4) { + RING_NONE = 0x0, + _, + }, + }, + /// Select whether RING_SIZE applies to read or write addresses. + /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + RING_SEL: u1, + /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + CHAIN_TO: u4, + /// Select a Transfer Request signal. + /// The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + /// 0x0 to 0x3a -> select DREQ n as TREQ + TREQ_SEL: packed union { + raw: u6, + value: enum(u6) { + /// Select Timer 0 as TREQ + TIMER0 = 0x3b, + /// Select Timer 1 as TREQ + TIMER1 = 0x3c, + /// Select Timer 2 as TREQ (Optional) + TIMER2 = 0x3d, + /// Select Timer 3 as TREQ (Optional) + TIMER3 = 0x3e, + /// Permanent request, for unpaced transfers. + PERMANENT = 0x3f, + _, + }, + }, + /// In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + /// This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + IRQ_QUIET: u1, + /// Apply byte-swap transformation to DMA data. + /// For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + BSWAP: u1, + /// If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + /// This allows checksum to be enabled or disabled on a per-control- block basis. + SNIFF_EN: u1, + /// This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + BUSY: u1, + reserved29: u4, + /// If 1, the channel received a write bus error. Write one to clear. + /// WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later) + WRITE_ERROR: u1, + /// If 1, the channel received a read bus error. Write one to clear. + /// READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later) + READ_ERROR: u1, + /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + AHB_ERROR: u1, + }), + /// Alias for channel 0 CTRL register + CH0_AL1_CTRL: u32, + /// Alias for channel 0 READ_ADDR register + CH0_AL1_READ_ADDR: u32, + /// Alias for channel 0 WRITE_ADDR register + CH0_AL1_WRITE_ADDR: u32, + /// Alias for channel 0 TRANS_COUNT register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH0_AL1_TRANS_COUNT_TRIG: u32, + /// Alias for channel 0 CTRL register + CH0_AL2_CTRL: u32, + /// Alias for channel 0 TRANS_COUNT register + CH0_AL2_TRANS_COUNT: u32, + /// Alias for channel 0 READ_ADDR register + CH0_AL2_READ_ADDR: u32, + /// Alias for channel 0 WRITE_ADDR register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH0_AL2_WRITE_ADDR_TRIG: u32, + /// Alias for channel 0 CTRL register + CH0_AL3_CTRL: u32, + /// Alias for channel 0 WRITE_ADDR register + CH0_AL3_WRITE_ADDR: u32, + /// Alias for channel 0 TRANS_COUNT register + CH0_AL3_TRANS_COUNT: u32, + /// Alias for channel 0 READ_ADDR register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH0_AL3_READ_ADDR_TRIG: u32, + /// DMA Channel 1 Read Address pointer + /// This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + CH1_READ_ADDR: u32, + /// DMA Channel 1 Write Address pointer + /// This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + CH1_WRITE_ADDR: u32, + /// DMA Channel 1 Transfer Count + /// Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + /// When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + /// Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + CH1_TRANS_COUNT: u32, + /// DMA Channel 1 Control and Status + CH1_CTRL_TRIG: mmio.Mmio(packed struct(u32) { + /// DMA Channel Enable. + /// When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + EN: u1, + /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + /// This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + HIGH_PRIORITY: u1, + /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + DATA_SIZE: packed union { + raw: u2, + value: enum(u2) { + SIZE_BYTE = 0x0, + SIZE_HALFWORD = 0x1, + SIZE_WORD = 0x2, + _, + }, + }, + /// If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + /// Generally this should be disabled for peripheral-to-memory transfers. + INCR_READ: u1, + /// If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + /// Generally this should be disabled for memory-to-peripheral transfers. + INCR_WRITE: u1, + /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SIZE: packed union { + raw: u4, + value: enum(u4) { + RING_NONE = 0x0, + _, + }, + }, + /// Select whether RING_SIZE applies to read or write addresses. + /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + RING_SEL: u1, + /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + CHAIN_TO: u4, + /// Select a Transfer Request signal. + /// The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + /// 0x0 to 0x3a -> select DREQ n as TREQ + TREQ_SEL: packed union { + raw: u6, + value: enum(u6) { + /// Select Timer 0 as TREQ + TIMER0 = 0x3b, + /// Select Timer 1 as TREQ + TIMER1 = 0x3c, + /// Select Timer 2 as TREQ (Optional) + TIMER2 = 0x3d, + /// Select Timer 3 as TREQ (Optional) + TIMER3 = 0x3e, + /// Permanent request, for unpaced transfers. + PERMANENT = 0x3f, + _, + }, + }, + /// In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + /// This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + IRQ_QUIET: u1, + /// Apply byte-swap transformation to DMA data. + /// For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + BSWAP: u1, + /// If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + /// This allows checksum to be enabled or disabled on a per-control- block basis. + SNIFF_EN: u1, + /// This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + BUSY: u1, + reserved29: u4, + /// If 1, the channel received a write bus error. Write one to clear. + /// WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later) + WRITE_ERROR: u1, + /// If 1, the channel received a read bus error. Write one to clear. + /// READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later) + READ_ERROR: u1, + /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + AHB_ERROR: u1, + }), + /// Alias for channel 1 CTRL register + CH1_AL1_CTRL: u32, + /// Alias for channel 1 READ_ADDR register + CH1_AL1_READ_ADDR: u32, + /// Alias for channel 1 WRITE_ADDR register + CH1_AL1_WRITE_ADDR: u32, + /// Alias for channel 1 TRANS_COUNT register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH1_AL1_TRANS_COUNT_TRIG: u32, + /// Alias for channel 1 CTRL register + CH1_AL2_CTRL: u32, + /// Alias for channel 1 TRANS_COUNT register + CH1_AL2_TRANS_COUNT: u32, + /// Alias for channel 1 READ_ADDR register + CH1_AL2_READ_ADDR: u32, + /// Alias for channel 1 WRITE_ADDR register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH1_AL2_WRITE_ADDR_TRIG: u32, + /// Alias for channel 1 CTRL register + CH1_AL3_CTRL: u32, + /// Alias for channel 1 WRITE_ADDR register + CH1_AL3_WRITE_ADDR: u32, + /// Alias for channel 1 TRANS_COUNT register + CH1_AL3_TRANS_COUNT: u32, + /// Alias for channel 1 READ_ADDR register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH1_AL3_READ_ADDR_TRIG: u32, + /// DMA Channel 2 Read Address pointer + /// This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + CH2_READ_ADDR: u32, + /// DMA Channel 2 Write Address pointer + /// This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + CH2_WRITE_ADDR: u32, + /// DMA Channel 2 Transfer Count + /// Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + /// When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + /// Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + CH2_TRANS_COUNT: u32, + /// DMA Channel 2 Control and Status + CH2_CTRL_TRIG: mmio.Mmio(packed struct(u32) { + /// DMA Channel Enable. + /// When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + EN: u1, + /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + /// This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + HIGH_PRIORITY: u1, + /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + DATA_SIZE: packed union { + raw: u2, + value: enum(u2) { + SIZE_BYTE = 0x0, + SIZE_HALFWORD = 0x1, + SIZE_WORD = 0x2, + _, + }, + }, + /// If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + /// Generally this should be disabled for peripheral-to-memory transfers. + INCR_READ: u1, + /// If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + /// Generally this should be disabled for memory-to-peripheral transfers. + INCR_WRITE: u1, + /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SIZE: packed union { + raw: u4, + value: enum(u4) { + RING_NONE = 0x0, + _, + }, + }, + /// Select whether RING_SIZE applies to read or write addresses. + /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + RING_SEL: u1, + /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + CHAIN_TO: u4, + /// Select a Transfer Request signal. + /// The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + /// 0x0 to 0x3a -> select DREQ n as TREQ + TREQ_SEL: packed union { + raw: u6, + value: enum(u6) { + /// Select Timer 0 as TREQ + TIMER0 = 0x3b, + /// Select Timer 1 as TREQ + TIMER1 = 0x3c, + /// Select Timer 2 as TREQ (Optional) + TIMER2 = 0x3d, + /// Select Timer 3 as TREQ (Optional) + TIMER3 = 0x3e, + /// Permanent request, for unpaced transfers. + PERMANENT = 0x3f, + _, + }, + }, + /// In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + /// This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + IRQ_QUIET: u1, + /// Apply byte-swap transformation to DMA data. + /// For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + BSWAP: u1, + /// If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + /// This allows checksum to be enabled or disabled on a per-control- block basis. + SNIFF_EN: u1, + /// This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + BUSY: u1, + reserved29: u4, + /// If 1, the channel received a write bus error. Write one to clear. + /// WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later) + WRITE_ERROR: u1, + /// If 1, the channel received a read bus error. Write one to clear. + /// READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later) + READ_ERROR: u1, + /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + AHB_ERROR: u1, + }), + /// Alias for channel 2 CTRL register + CH2_AL1_CTRL: u32, + /// Alias for channel 2 READ_ADDR register + CH2_AL1_READ_ADDR: u32, + /// Alias for channel 2 WRITE_ADDR register + CH2_AL1_WRITE_ADDR: u32, + /// Alias for channel 2 TRANS_COUNT register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH2_AL1_TRANS_COUNT_TRIG: u32, + /// Alias for channel 2 CTRL register + CH2_AL2_CTRL: u32, + /// Alias for channel 2 TRANS_COUNT register + CH2_AL2_TRANS_COUNT: u32, + /// Alias for channel 2 READ_ADDR register + CH2_AL2_READ_ADDR: u32, + /// Alias for channel 2 WRITE_ADDR register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH2_AL2_WRITE_ADDR_TRIG: u32, + /// Alias for channel 2 CTRL register + CH2_AL3_CTRL: u32, + /// Alias for channel 2 WRITE_ADDR register + CH2_AL3_WRITE_ADDR: u32, + /// Alias for channel 2 TRANS_COUNT register + CH2_AL3_TRANS_COUNT: u32, + /// Alias for channel 2 READ_ADDR register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH2_AL3_READ_ADDR_TRIG: u32, + /// DMA Channel 3 Read Address pointer + /// This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + CH3_READ_ADDR: u32, + /// DMA Channel 3 Write Address pointer + /// This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + CH3_WRITE_ADDR: u32, + /// DMA Channel 3 Transfer Count + /// Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + /// When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + /// Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + CH3_TRANS_COUNT: u32, + /// DMA Channel 3 Control and Status + CH3_CTRL_TRIG: mmio.Mmio(packed struct(u32) { + /// DMA Channel Enable. + /// When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + EN: u1, + /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + /// This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + HIGH_PRIORITY: u1, + /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + DATA_SIZE: packed union { + raw: u2, + value: enum(u2) { + SIZE_BYTE = 0x0, + SIZE_HALFWORD = 0x1, + SIZE_WORD = 0x2, + _, + }, + }, + /// If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + /// Generally this should be disabled for peripheral-to-memory transfers. + INCR_READ: u1, + /// If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + /// Generally this should be disabled for memory-to-peripheral transfers. + INCR_WRITE: u1, + /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SIZE: packed union { + raw: u4, + value: enum(u4) { + RING_NONE = 0x0, + _, + }, + }, + /// Select whether RING_SIZE applies to read or write addresses. + /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + RING_SEL: u1, + /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + CHAIN_TO: u4, + /// Select a Transfer Request signal. + /// The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + /// 0x0 to 0x3a -> select DREQ n as TREQ + TREQ_SEL: packed union { + raw: u6, + value: enum(u6) { + /// Select Timer 0 as TREQ + TIMER0 = 0x3b, + /// Select Timer 1 as TREQ + TIMER1 = 0x3c, + /// Select Timer 2 as TREQ (Optional) + TIMER2 = 0x3d, + /// Select Timer 3 as TREQ (Optional) + TIMER3 = 0x3e, + /// Permanent request, for unpaced transfers. + PERMANENT = 0x3f, + _, + }, + }, + /// In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + /// This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + IRQ_QUIET: u1, + /// Apply byte-swap transformation to DMA data. + /// For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + BSWAP: u1, + /// If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + /// This allows checksum to be enabled or disabled on a per-control- block basis. + SNIFF_EN: u1, + /// This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + BUSY: u1, + reserved29: u4, + /// If 1, the channel received a write bus error. Write one to clear. + /// WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later) + WRITE_ERROR: u1, + /// If 1, the channel received a read bus error. Write one to clear. + /// READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later) + READ_ERROR: u1, + /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + AHB_ERROR: u1, + }), + /// Alias for channel 3 CTRL register + CH3_AL1_CTRL: u32, + /// Alias for channel 3 READ_ADDR register + CH3_AL1_READ_ADDR: u32, + /// Alias for channel 3 WRITE_ADDR register + CH3_AL1_WRITE_ADDR: u32, + /// Alias for channel 3 TRANS_COUNT register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH3_AL1_TRANS_COUNT_TRIG: u32, + /// Alias for channel 3 CTRL register + CH3_AL2_CTRL: u32, + /// Alias for channel 3 TRANS_COUNT register + CH3_AL2_TRANS_COUNT: u32, + /// Alias for channel 3 READ_ADDR register + CH3_AL2_READ_ADDR: u32, + /// Alias for channel 3 WRITE_ADDR register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH3_AL2_WRITE_ADDR_TRIG: u32, + /// Alias for channel 3 CTRL register + CH3_AL3_CTRL: u32, + /// Alias for channel 3 WRITE_ADDR register + CH3_AL3_WRITE_ADDR: u32, + /// Alias for channel 3 TRANS_COUNT register + CH3_AL3_TRANS_COUNT: u32, + /// Alias for channel 3 READ_ADDR register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH3_AL3_READ_ADDR_TRIG: u32, + /// DMA Channel 4 Read Address pointer + /// This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + CH4_READ_ADDR: u32, + /// DMA Channel 4 Write Address pointer + /// This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + CH4_WRITE_ADDR: u32, + /// DMA Channel 4 Transfer Count + /// Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + /// When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + /// Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + CH4_TRANS_COUNT: u32, + /// DMA Channel 4 Control and Status + CH4_CTRL_TRIG: mmio.Mmio(packed struct(u32) { + /// DMA Channel Enable. + /// When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + EN: u1, + /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + /// This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + HIGH_PRIORITY: u1, + /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + DATA_SIZE: packed union { + raw: u2, + value: enum(u2) { + SIZE_BYTE = 0x0, + SIZE_HALFWORD = 0x1, + SIZE_WORD = 0x2, + _, + }, + }, + /// If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + /// Generally this should be disabled for peripheral-to-memory transfers. + INCR_READ: u1, + /// If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + /// Generally this should be disabled for memory-to-peripheral transfers. + INCR_WRITE: u1, + /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SIZE: packed union { + raw: u4, + value: enum(u4) { + RING_NONE = 0x0, + _, + }, + }, + /// Select whether RING_SIZE applies to read or write addresses. + /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + RING_SEL: u1, + /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + CHAIN_TO: u4, + /// Select a Transfer Request signal. + /// The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + /// 0x0 to 0x3a -> select DREQ n as TREQ + TREQ_SEL: packed union { + raw: u6, + value: enum(u6) { + /// Select Timer 0 as TREQ + TIMER0 = 0x3b, + /// Select Timer 1 as TREQ + TIMER1 = 0x3c, + /// Select Timer 2 as TREQ (Optional) + TIMER2 = 0x3d, + /// Select Timer 3 as TREQ (Optional) + TIMER3 = 0x3e, + /// Permanent request, for unpaced transfers. + PERMANENT = 0x3f, + _, + }, + }, + /// In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + /// This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + IRQ_QUIET: u1, + /// Apply byte-swap transformation to DMA data. + /// For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + BSWAP: u1, + /// If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + /// This allows checksum to be enabled or disabled on a per-control- block basis. + SNIFF_EN: u1, + /// This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + BUSY: u1, + reserved29: u4, + /// If 1, the channel received a write bus error. Write one to clear. + /// WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later) + WRITE_ERROR: u1, + /// If 1, the channel received a read bus error. Write one to clear. + /// READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later) + READ_ERROR: u1, + /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + AHB_ERROR: u1, + }), + /// Alias for channel 4 CTRL register + CH4_AL1_CTRL: u32, + /// Alias for channel 4 READ_ADDR register + CH4_AL1_READ_ADDR: u32, + /// Alias for channel 4 WRITE_ADDR register + CH4_AL1_WRITE_ADDR: u32, + /// Alias for channel 4 TRANS_COUNT register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH4_AL1_TRANS_COUNT_TRIG: u32, + /// Alias for channel 4 CTRL register + CH4_AL2_CTRL: u32, + /// Alias for channel 4 TRANS_COUNT register + CH4_AL2_TRANS_COUNT: u32, + /// Alias for channel 4 READ_ADDR register + CH4_AL2_READ_ADDR: u32, + /// Alias for channel 4 WRITE_ADDR register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH4_AL2_WRITE_ADDR_TRIG: u32, + /// Alias for channel 4 CTRL register + CH4_AL3_CTRL: u32, + /// Alias for channel 4 WRITE_ADDR register + CH4_AL3_WRITE_ADDR: u32, + /// Alias for channel 4 TRANS_COUNT register + CH4_AL3_TRANS_COUNT: u32, + /// Alias for channel 4 READ_ADDR register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH4_AL3_READ_ADDR_TRIG: u32, + /// DMA Channel 5 Read Address pointer + /// This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + CH5_READ_ADDR: u32, + /// DMA Channel 5 Write Address pointer + /// This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + CH5_WRITE_ADDR: u32, + /// DMA Channel 5 Transfer Count + /// Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + /// When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + /// Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + CH5_TRANS_COUNT: u32, + /// DMA Channel 5 Control and Status + CH5_CTRL_TRIG: mmio.Mmio(packed struct(u32) { + /// DMA Channel Enable. + /// When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + EN: u1, + /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + /// This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + HIGH_PRIORITY: u1, + /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + DATA_SIZE: packed union { + raw: u2, + value: enum(u2) { + SIZE_BYTE = 0x0, + SIZE_HALFWORD = 0x1, + SIZE_WORD = 0x2, + _, + }, + }, + /// If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + /// Generally this should be disabled for peripheral-to-memory transfers. + INCR_READ: u1, + /// If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + /// Generally this should be disabled for memory-to-peripheral transfers. + INCR_WRITE: u1, + /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SIZE: packed union { + raw: u4, + value: enum(u4) { + RING_NONE = 0x0, + _, + }, + }, + /// Select whether RING_SIZE applies to read or write addresses. + /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + RING_SEL: u1, + /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + CHAIN_TO: u4, + /// Select a Transfer Request signal. + /// The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + /// 0x0 to 0x3a -> select DREQ n as TREQ + TREQ_SEL: packed union { + raw: u6, + value: enum(u6) { + /// Select Timer 0 as TREQ + TIMER0 = 0x3b, + /// Select Timer 1 as TREQ + TIMER1 = 0x3c, + /// Select Timer 2 as TREQ (Optional) + TIMER2 = 0x3d, + /// Select Timer 3 as TREQ (Optional) + TIMER3 = 0x3e, + /// Permanent request, for unpaced transfers. + PERMANENT = 0x3f, + _, + }, + }, + /// In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + /// This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + IRQ_QUIET: u1, + /// Apply byte-swap transformation to DMA data. + /// For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + BSWAP: u1, + /// If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + /// This allows checksum to be enabled or disabled on a per-control- block basis. + SNIFF_EN: u1, + /// This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + BUSY: u1, + reserved29: u4, + /// If 1, the channel received a write bus error. Write one to clear. + /// WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later) + WRITE_ERROR: u1, + /// If 1, the channel received a read bus error. Write one to clear. + /// READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later) + READ_ERROR: u1, + /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + AHB_ERROR: u1, + }), + /// Alias for channel 5 CTRL register + CH5_AL1_CTRL: u32, + /// Alias for channel 5 READ_ADDR register + CH5_AL1_READ_ADDR: u32, + /// Alias for channel 5 WRITE_ADDR register + CH5_AL1_WRITE_ADDR: u32, + /// Alias for channel 5 TRANS_COUNT register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH5_AL1_TRANS_COUNT_TRIG: u32, + /// Alias for channel 5 CTRL register + CH5_AL2_CTRL: u32, + /// Alias for channel 5 TRANS_COUNT register + CH5_AL2_TRANS_COUNT: u32, + /// Alias for channel 5 READ_ADDR register + CH5_AL2_READ_ADDR: u32, + /// Alias for channel 5 WRITE_ADDR register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH5_AL2_WRITE_ADDR_TRIG: u32, + /// Alias for channel 5 CTRL register + CH5_AL3_CTRL: u32, + /// Alias for channel 5 WRITE_ADDR register + CH5_AL3_WRITE_ADDR: u32, + /// Alias for channel 5 TRANS_COUNT register + CH5_AL3_TRANS_COUNT: u32, + /// Alias for channel 5 READ_ADDR register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH5_AL3_READ_ADDR_TRIG: u32, + /// DMA Channel 6 Read Address pointer + /// This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + CH6_READ_ADDR: u32, + /// DMA Channel 6 Write Address pointer + /// This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + CH6_WRITE_ADDR: u32, + /// DMA Channel 6 Transfer Count + /// Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + /// When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + /// Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + CH6_TRANS_COUNT: u32, + /// DMA Channel 6 Control and Status + CH6_CTRL_TRIG: mmio.Mmio(packed struct(u32) { + /// DMA Channel Enable. + /// When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + EN: u1, + /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + /// This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + HIGH_PRIORITY: u1, + /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + DATA_SIZE: packed union { + raw: u2, + value: enum(u2) { + SIZE_BYTE = 0x0, + SIZE_HALFWORD = 0x1, + SIZE_WORD = 0x2, + _, + }, + }, + /// If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + /// Generally this should be disabled for peripheral-to-memory transfers. + INCR_READ: u1, + /// If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + /// Generally this should be disabled for memory-to-peripheral transfers. + INCR_WRITE: u1, + /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SIZE: packed union { + raw: u4, + value: enum(u4) { + RING_NONE = 0x0, + _, + }, + }, + /// Select whether RING_SIZE applies to read or write addresses. + /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + RING_SEL: u1, + /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + CHAIN_TO: u4, + /// Select a Transfer Request signal. + /// The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + /// 0x0 to 0x3a -> select DREQ n as TREQ + TREQ_SEL: packed union { + raw: u6, + value: enum(u6) { + /// Select Timer 0 as TREQ + TIMER0 = 0x3b, + /// Select Timer 1 as TREQ + TIMER1 = 0x3c, + /// Select Timer 2 as TREQ (Optional) + TIMER2 = 0x3d, + /// Select Timer 3 as TREQ (Optional) + TIMER3 = 0x3e, + /// Permanent request, for unpaced transfers. + PERMANENT = 0x3f, + _, + }, + }, + /// In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + /// This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + IRQ_QUIET: u1, + /// Apply byte-swap transformation to DMA data. + /// For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + BSWAP: u1, + /// If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + /// This allows checksum to be enabled or disabled on a per-control- block basis. + SNIFF_EN: u1, + /// This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + BUSY: u1, + reserved29: u4, + /// If 1, the channel received a write bus error. Write one to clear. + /// WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later) + WRITE_ERROR: u1, + /// If 1, the channel received a read bus error. Write one to clear. + /// READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later) + READ_ERROR: u1, + /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + AHB_ERROR: u1, + }), + /// Alias for channel 6 CTRL register + CH6_AL1_CTRL: u32, + /// Alias for channel 6 READ_ADDR register + CH6_AL1_READ_ADDR: u32, + /// Alias for channel 6 WRITE_ADDR register + CH6_AL1_WRITE_ADDR: u32, + /// Alias for channel 6 TRANS_COUNT register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH6_AL1_TRANS_COUNT_TRIG: u32, + /// Alias for channel 6 CTRL register + CH6_AL2_CTRL: u32, + /// Alias for channel 6 TRANS_COUNT register + CH6_AL2_TRANS_COUNT: u32, + /// Alias for channel 6 READ_ADDR register + CH6_AL2_READ_ADDR: u32, + /// Alias for channel 6 WRITE_ADDR register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH6_AL2_WRITE_ADDR_TRIG: u32, + /// Alias for channel 6 CTRL register + CH6_AL3_CTRL: u32, + /// Alias for channel 6 WRITE_ADDR register + CH6_AL3_WRITE_ADDR: u32, + /// Alias for channel 6 TRANS_COUNT register + CH6_AL3_TRANS_COUNT: u32, + /// Alias for channel 6 READ_ADDR register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH6_AL3_READ_ADDR_TRIG: u32, + /// DMA Channel 7 Read Address pointer + /// This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + CH7_READ_ADDR: u32, + /// DMA Channel 7 Write Address pointer + /// This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + CH7_WRITE_ADDR: u32, + /// DMA Channel 7 Transfer Count + /// Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + /// When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + /// Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + CH7_TRANS_COUNT: u32, + /// DMA Channel 7 Control and Status + CH7_CTRL_TRIG: mmio.Mmio(packed struct(u32) { + /// DMA Channel Enable. + /// When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + EN: u1, + /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + /// This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + HIGH_PRIORITY: u1, + /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + DATA_SIZE: packed union { + raw: u2, + value: enum(u2) { + SIZE_BYTE = 0x0, + SIZE_HALFWORD = 0x1, + SIZE_WORD = 0x2, + _, + }, + }, + /// If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + /// Generally this should be disabled for peripheral-to-memory transfers. + INCR_READ: u1, + /// If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + /// Generally this should be disabled for memory-to-peripheral transfers. + INCR_WRITE: u1, + /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SIZE: packed union { + raw: u4, + value: enum(u4) { + RING_NONE = 0x0, + _, + }, + }, + /// Select whether RING_SIZE applies to read or write addresses. + /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + RING_SEL: u1, + /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + CHAIN_TO: u4, + /// Select a Transfer Request signal. + /// The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + /// 0x0 to 0x3a -> select DREQ n as TREQ + TREQ_SEL: packed union { + raw: u6, + value: enum(u6) { + /// Select Timer 0 as TREQ + TIMER0 = 0x3b, + /// Select Timer 1 as TREQ + TIMER1 = 0x3c, + /// Select Timer 2 as TREQ (Optional) + TIMER2 = 0x3d, + /// Select Timer 3 as TREQ (Optional) + TIMER3 = 0x3e, + /// Permanent request, for unpaced transfers. + PERMANENT = 0x3f, + _, + }, + }, + /// In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + /// This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + IRQ_QUIET: u1, + /// Apply byte-swap transformation to DMA data. + /// For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + BSWAP: u1, + /// If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + /// This allows checksum to be enabled or disabled on a per-control- block basis. + SNIFF_EN: u1, + /// This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + BUSY: u1, + reserved29: u4, + /// If 1, the channel received a write bus error. Write one to clear. + /// WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later) + WRITE_ERROR: u1, + /// If 1, the channel received a read bus error. Write one to clear. + /// READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later) + READ_ERROR: u1, + /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + AHB_ERROR: u1, + }), + /// Alias for channel 7 CTRL register + CH7_AL1_CTRL: u32, + /// Alias for channel 7 READ_ADDR register + CH7_AL1_READ_ADDR: u32, + /// Alias for channel 7 WRITE_ADDR register + CH7_AL1_WRITE_ADDR: u32, + /// Alias for channel 7 TRANS_COUNT register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH7_AL1_TRANS_COUNT_TRIG: u32, + /// Alias for channel 7 CTRL register + CH7_AL2_CTRL: u32, + /// Alias for channel 7 TRANS_COUNT register + CH7_AL2_TRANS_COUNT: u32, + /// Alias for channel 7 READ_ADDR register + CH7_AL2_READ_ADDR: u32, + /// Alias for channel 7 WRITE_ADDR register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH7_AL2_WRITE_ADDR_TRIG: u32, + /// Alias for channel 7 CTRL register + CH7_AL3_CTRL: u32, + /// Alias for channel 7 WRITE_ADDR register + CH7_AL3_WRITE_ADDR: u32, + /// Alias for channel 7 TRANS_COUNT register + CH7_AL3_TRANS_COUNT: u32, + /// Alias for channel 7 READ_ADDR register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH7_AL3_READ_ADDR_TRIG: u32, + /// DMA Channel 8 Read Address pointer + /// This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + CH8_READ_ADDR: u32, + /// DMA Channel 8 Write Address pointer + /// This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + CH8_WRITE_ADDR: u32, + /// DMA Channel 8 Transfer Count + /// Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + /// When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + /// Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + CH8_TRANS_COUNT: u32, + /// DMA Channel 8 Control and Status + CH8_CTRL_TRIG: mmio.Mmio(packed struct(u32) { + /// DMA Channel Enable. + /// When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + EN: u1, + /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + /// This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + HIGH_PRIORITY: u1, + /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + DATA_SIZE: packed union { + raw: u2, + value: enum(u2) { + SIZE_BYTE = 0x0, + SIZE_HALFWORD = 0x1, + SIZE_WORD = 0x2, + _, + }, + }, + /// If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + /// Generally this should be disabled for peripheral-to-memory transfers. + INCR_READ: u1, + /// If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + /// Generally this should be disabled for memory-to-peripheral transfers. + INCR_WRITE: u1, + /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SIZE: packed union { + raw: u4, + value: enum(u4) { + RING_NONE = 0x0, + _, + }, + }, + /// Select whether RING_SIZE applies to read or write addresses. + /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + RING_SEL: u1, + /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + CHAIN_TO: u4, + /// Select a Transfer Request signal. + /// The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + /// 0x0 to 0x3a -> select DREQ n as TREQ + TREQ_SEL: packed union { + raw: u6, + value: enum(u6) { + /// Select Timer 0 as TREQ + TIMER0 = 0x3b, + /// Select Timer 1 as TREQ + TIMER1 = 0x3c, + /// Select Timer 2 as TREQ (Optional) + TIMER2 = 0x3d, + /// Select Timer 3 as TREQ (Optional) + TIMER3 = 0x3e, + /// Permanent request, for unpaced transfers. + PERMANENT = 0x3f, + _, + }, + }, + /// In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + /// This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + IRQ_QUIET: u1, + /// Apply byte-swap transformation to DMA data. + /// For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + BSWAP: u1, + /// If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + /// This allows checksum to be enabled or disabled on a per-control- block basis. + SNIFF_EN: u1, + /// This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + BUSY: u1, + reserved29: u4, + /// If 1, the channel received a write bus error. Write one to clear. + /// WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later) + WRITE_ERROR: u1, + /// If 1, the channel received a read bus error. Write one to clear. + /// READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later) + READ_ERROR: u1, + /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + AHB_ERROR: u1, + }), + /// Alias for channel 8 CTRL register + CH8_AL1_CTRL: u32, + /// Alias for channel 8 READ_ADDR register + CH8_AL1_READ_ADDR: u32, + /// Alias for channel 8 WRITE_ADDR register + CH8_AL1_WRITE_ADDR: u32, + /// Alias for channel 8 TRANS_COUNT register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH8_AL1_TRANS_COUNT_TRIG: u32, + /// Alias for channel 8 CTRL register + CH8_AL2_CTRL: u32, + /// Alias for channel 8 TRANS_COUNT register + CH8_AL2_TRANS_COUNT: u32, + /// Alias for channel 8 READ_ADDR register + CH8_AL2_READ_ADDR: u32, + /// Alias for channel 8 WRITE_ADDR register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH8_AL2_WRITE_ADDR_TRIG: u32, + /// Alias for channel 8 CTRL register + CH8_AL3_CTRL: u32, + /// Alias for channel 8 WRITE_ADDR register + CH8_AL3_WRITE_ADDR: u32, + /// Alias for channel 8 TRANS_COUNT register + CH8_AL3_TRANS_COUNT: u32, + /// Alias for channel 8 READ_ADDR register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH8_AL3_READ_ADDR_TRIG: u32, + /// DMA Channel 9 Read Address pointer + /// This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + CH9_READ_ADDR: u32, + /// DMA Channel 9 Write Address pointer + /// This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + CH9_WRITE_ADDR: u32, + /// DMA Channel 9 Transfer Count + /// Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + /// When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + /// Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + CH9_TRANS_COUNT: u32, + /// DMA Channel 9 Control and Status + CH9_CTRL_TRIG: mmio.Mmio(packed struct(u32) { + /// DMA Channel Enable. + /// When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + EN: u1, + /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + /// This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + HIGH_PRIORITY: u1, + /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + DATA_SIZE: packed union { + raw: u2, + value: enum(u2) { + SIZE_BYTE = 0x0, + SIZE_HALFWORD = 0x1, + SIZE_WORD = 0x2, + _, + }, + }, + /// If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + /// Generally this should be disabled for peripheral-to-memory transfers. + INCR_READ: u1, + /// If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + /// Generally this should be disabled for memory-to-peripheral transfers. + INCR_WRITE: u1, + /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SIZE: packed union { + raw: u4, + value: enum(u4) { + RING_NONE = 0x0, + _, + }, + }, + /// Select whether RING_SIZE applies to read or write addresses. + /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + RING_SEL: u1, + /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + CHAIN_TO: u4, + /// Select a Transfer Request signal. + /// The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + /// 0x0 to 0x3a -> select DREQ n as TREQ + TREQ_SEL: packed union { + raw: u6, + value: enum(u6) { + /// Select Timer 0 as TREQ + TIMER0 = 0x3b, + /// Select Timer 1 as TREQ + TIMER1 = 0x3c, + /// Select Timer 2 as TREQ (Optional) + TIMER2 = 0x3d, + /// Select Timer 3 as TREQ (Optional) + TIMER3 = 0x3e, + /// Permanent request, for unpaced transfers. + PERMANENT = 0x3f, + _, + }, + }, + /// In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + /// This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + IRQ_QUIET: u1, + /// Apply byte-swap transformation to DMA data. + /// For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + BSWAP: u1, + /// If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + /// This allows checksum to be enabled or disabled on a per-control- block basis. + SNIFF_EN: u1, + /// This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + BUSY: u1, + reserved29: u4, + /// If 1, the channel received a write bus error. Write one to clear. + /// WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later) + WRITE_ERROR: u1, + /// If 1, the channel received a read bus error. Write one to clear. + /// READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later) + READ_ERROR: u1, + /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + AHB_ERROR: u1, + }), + /// Alias for channel 9 CTRL register + CH9_AL1_CTRL: u32, + /// Alias for channel 9 READ_ADDR register + CH9_AL1_READ_ADDR: u32, + /// Alias for channel 9 WRITE_ADDR register + CH9_AL1_WRITE_ADDR: u32, + /// Alias for channel 9 TRANS_COUNT register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH9_AL1_TRANS_COUNT_TRIG: u32, + /// Alias for channel 9 CTRL register + CH9_AL2_CTRL: u32, + /// Alias for channel 9 TRANS_COUNT register + CH9_AL2_TRANS_COUNT: u32, + /// Alias for channel 9 READ_ADDR register + CH9_AL2_READ_ADDR: u32, + /// Alias for channel 9 WRITE_ADDR register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH9_AL2_WRITE_ADDR_TRIG: u32, + /// Alias for channel 9 CTRL register + CH9_AL3_CTRL: u32, + /// Alias for channel 9 WRITE_ADDR register + CH9_AL3_WRITE_ADDR: u32, + /// Alias for channel 9 TRANS_COUNT register + CH9_AL3_TRANS_COUNT: u32, + /// Alias for channel 9 READ_ADDR register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH9_AL3_READ_ADDR_TRIG: u32, + /// DMA Channel 10 Read Address pointer + /// This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + CH10_READ_ADDR: u32, + /// DMA Channel 10 Write Address pointer + /// This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + CH10_WRITE_ADDR: u32, + /// DMA Channel 10 Transfer Count + /// Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + /// When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + /// Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + CH10_TRANS_COUNT: u32, + /// DMA Channel 10 Control and Status + CH10_CTRL_TRIG: mmio.Mmio(packed struct(u32) { + /// DMA Channel Enable. + /// When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + EN: u1, + /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + /// This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + HIGH_PRIORITY: u1, + /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + DATA_SIZE: packed union { + raw: u2, + value: enum(u2) { + SIZE_BYTE = 0x0, + SIZE_HALFWORD = 0x1, + SIZE_WORD = 0x2, + _, + }, + }, + /// If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + /// Generally this should be disabled for peripheral-to-memory transfers. + INCR_READ: u1, + /// If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + /// Generally this should be disabled for memory-to-peripheral transfers. + INCR_WRITE: u1, + /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SIZE: packed union { + raw: u4, + value: enum(u4) { + RING_NONE = 0x0, + _, + }, + }, + /// Select whether RING_SIZE applies to read or write addresses. + /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + RING_SEL: u1, + /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + CHAIN_TO: u4, + /// Select a Transfer Request signal. + /// The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + /// 0x0 to 0x3a -> select DREQ n as TREQ + TREQ_SEL: packed union { + raw: u6, + value: enum(u6) { + /// Select Timer 0 as TREQ + TIMER0 = 0x3b, + /// Select Timer 1 as TREQ + TIMER1 = 0x3c, + /// Select Timer 2 as TREQ (Optional) + TIMER2 = 0x3d, + /// Select Timer 3 as TREQ (Optional) + TIMER3 = 0x3e, + /// Permanent request, for unpaced transfers. + PERMANENT = 0x3f, + _, + }, + }, + /// In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + /// This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + IRQ_QUIET: u1, + /// Apply byte-swap transformation to DMA data. + /// For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + BSWAP: u1, + /// If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + /// This allows checksum to be enabled or disabled on a per-control- block basis. + SNIFF_EN: u1, + /// This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + BUSY: u1, + reserved29: u4, + /// If 1, the channel received a write bus error. Write one to clear. + /// WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later) + WRITE_ERROR: u1, + /// If 1, the channel received a read bus error. Write one to clear. + /// READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later) + READ_ERROR: u1, + /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + AHB_ERROR: u1, + }), + /// Alias for channel 10 CTRL register + CH10_AL1_CTRL: u32, + /// Alias for channel 10 READ_ADDR register + CH10_AL1_READ_ADDR: u32, + /// Alias for channel 10 WRITE_ADDR register + CH10_AL1_WRITE_ADDR: u32, + /// Alias for channel 10 TRANS_COUNT register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH10_AL1_TRANS_COUNT_TRIG: u32, + /// Alias for channel 10 CTRL register + CH10_AL2_CTRL: u32, + /// Alias for channel 10 TRANS_COUNT register + CH10_AL2_TRANS_COUNT: u32, + /// Alias for channel 10 READ_ADDR register + CH10_AL2_READ_ADDR: u32, + /// Alias for channel 10 WRITE_ADDR register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH10_AL2_WRITE_ADDR_TRIG: u32, + /// Alias for channel 10 CTRL register + CH10_AL3_CTRL: u32, + /// Alias for channel 10 WRITE_ADDR register + CH10_AL3_WRITE_ADDR: u32, + /// Alias for channel 10 TRANS_COUNT register + CH10_AL3_TRANS_COUNT: u32, + /// Alias for channel 10 READ_ADDR register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH10_AL3_READ_ADDR_TRIG: u32, + /// DMA Channel 11 Read Address pointer + /// This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + CH11_READ_ADDR: u32, + /// DMA Channel 11 Write Address pointer + /// This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + CH11_WRITE_ADDR: u32, + /// DMA Channel 11 Transfer Count + /// Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + /// When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + /// Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + CH11_TRANS_COUNT: u32, + /// DMA Channel 11 Control and Status + CH11_CTRL_TRIG: mmio.Mmio(packed struct(u32) { + /// DMA Channel Enable. + /// When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + EN: u1, + /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + /// This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + HIGH_PRIORITY: u1, + /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + DATA_SIZE: packed union { + raw: u2, + value: enum(u2) { + SIZE_BYTE = 0x0, + SIZE_HALFWORD = 0x1, + SIZE_WORD = 0x2, + _, + }, + }, + /// If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + /// Generally this should be disabled for peripheral-to-memory transfers. + INCR_READ: u1, + /// If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + /// Generally this should be disabled for memory-to-peripheral transfers. + INCR_WRITE: u1, + /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SIZE: packed union { + raw: u4, + value: enum(u4) { + RING_NONE = 0x0, + _, + }, + }, + /// Select whether RING_SIZE applies to read or write addresses. + /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + RING_SEL: u1, + /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + CHAIN_TO: u4, + /// Select a Transfer Request signal. + /// The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + /// 0x0 to 0x3a -> select DREQ n as TREQ + TREQ_SEL: packed union { + raw: u6, + value: enum(u6) { + /// Select Timer 0 as TREQ + TIMER0 = 0x3b, + /// Select Timer 1 as TREQ + TIMER1 = 0x3c, + /// Select Timer 2 as TREQ (Optional) + TIMER2 = 0x3d, + /// Select Timer 3 as TREQ (Optional) + TIMER3 = 0x3e, + /// Permanent request, for unpaced transfers. + PERMANENT = 0x3f, + _, + }, + }, + /// In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + /// This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + IRQ_QUIET: u1, + /// Apply byte-swap transformation to DMA data. + /// For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + BSWAP: u1, + /// If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + /// This allows checksum to be enabled or disabled on a per-control- block basis. + SNIFF_EN: u1, + /// This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + BUSY: u1, + reserved29: u4, + /// If 1, the channel received a write bus error. Write one to clear. + /// WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later) + WRITE_ERROR: u1, + /// If 1, the channel received a read bus error. Write one to clear. + /// READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later) + READ_ERROR: u1, + /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + AHB_ERROR: u1, + }), + /// Alias for channel 11 CTRL register + CH11_AL1_CTRL: u32, + /// Alias for channel 11 READ_ADDR register + CH11_AL1_READ_ADDR: u32, + /// Alias for channel 11 WRITE_ADDR register + CH11_AL1_WRITE_ADDR: u32, + /// Alias for channel 11 TRANS_COUNT register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH11_AL1_TRANS_COUNT_TRIG: u32, + /// Alias for channel 11 CTRL register + CH11_AL2_CTRL: u32, + /// Alias for channel 11 TRANS_COUNT register + CH11_AL2_TRANS_COUNT: u32, + /// Alias for channel 11 READ_ADDR register + CH11_AL2_READ_ADDR: u32, + /// Alias for channel 11 WRITE_ADDR register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH11_AL2_WRITE_ADDR_TRIG: u32, + /// Alias for channel 11 CTRL register + CH11_AL3_CTRL: u32, + /// Alias for channel 11 WRITE_ADDR register + CH11_AL3_WRITE_ADDR: u32, + /// Alias for channel 11 TRANS_COUNT register + CH11_AL3_TRANS_COUNT: u32, + /// Alias for channel 11 READ_ADDR register + /// This is a trigger register (0xc). Writing a nonzero value will + /// reload the channel counter and start the channel. + CH11_AL3_READ_ADDR_TRIG: u32, + reserved1024: [256]u8, + /// Interrupt Status (raw) + INTR: mmio.Mmio(packed struct(u32) { + /// Raw interrupt status for DMA Channels 0..15. Bit n corresponds to channel n. Ignores any masking or forcing. Channel interrupts can be cleared by writing a bit mask to INTR, INTS0 or INTS1. + /// Channel interrupts can be routed to either of two system-level IRQs based on INTE0 and INTE1. + /// This can be used vector different channel interrupts to different ISRs: this might be done to allow NVIC IRQ preemption for more time-critical channels, or to spread IRQ load across different cores. + /// It is also valid to ignore this behaviour and just use INTE0/INTS0/IRQ 0. + INTR: u16, + padding: u16, + }), + /// Interrupt Enables for IRQ 0 + INTE0: mmio.Mmio(packed struct(u32) { + /// Set bit n to pass interrupts from channel n to DMA IRQ 0. + INTE0: u16, + padding: u16, + }), + /// Force Interrupts + INTF0: mmio.Mmio(packed struct(u32) { + /// Write 1s to force the corresponding bits in INTE0. The interrupt remains asserted until INTF0 is cleared. + INTF0: u16, + padding: u16, + }), + /// Interrupt Status for IRQ 0 + INTS0: mmio.Mmio(packed struct(u32) { + /// Indicates active channel interrupt requests which are currently causing IRQ 0 to be asserted. + /// Channel interrupts can be cleared by writing a bit mask here. + INTS0: u16, + padding: u16, + }), + reserved1044: [4]u8, + /// Interrupt Enables for IRQ 1 + INTE1: mmio.Mmio(packed struct(u32) { + /// Set bit n to pass interrupts from channel n to DMA IRQ 1. + INTE1: u16, + padding: u16, + }), + /// Force Interrupts for IRQ 1 + INTF1: mmio.Mmio(packed struct(u32) { + /// Write 1s to force the corresponding bits in INTE0. The interrupt remains asserted until INTF0 is cleared. + INTF1: u16, + padding: u16, + }), + /// Interrupt Status (masked) for IRQ 1 + INTS1: mmio.Mmio(packed struct(u32) { + /// Indicates active channel interrupt requests which are currently causing IRQ 1 to be asserted. + /// Channel interrupts can be cleared by writing a bit mask here. + INTS1: u16, + padding: u16, + }), + /// Pacing (X/Y) Fractional Timer + /// The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. + TIMER0: mmio.Mmio(packed struct(u32) { + /// Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. + Y: u16, + /// Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. + X: u16, + }), + /// Pacing (X/Y) Fractional Timer + /// The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. + TIMER1: mmio.Mmio(packed struct(u32) { + /// Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. + Y: u16, + /// Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. + X: u16, + }), + /// Pacing (X/Y) Fractional Timer + /// The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. + TIMER2: mmio.Mmio(packed struct(u32) { + /// Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. + Y: u16, + /// Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. + X: u16, + }), + /// Pacing (X/Y) Fractional Timer + /// The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. + TIMER3: mmio.Mmio(packed struct(u32) { + /// Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. + Y: u16, + /// Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. + X: u16, + }), + /// Trigger one or more channels simultaneously + MULTI_CHAN_TRIGGER: mmio.Mmio(packed struct(u32) { + /// Each bit in this register corresponds to a DMA channel. Writing a 1 to the relevant bit is the same as writing to that channel's trigger register; the channel will start if it is currently enabled and not already busy. + MULTI_CHAN_TRIGGER: u16, + padding: u16, + }), + /// Sniffer Control + SNIFF_CTRL: mmio.Mmio(packed struct(u32) { + /// Enable sniffer + EN: u1, + /// DMA channel for Sniffer to observe + DMACH: u4, + CALC: packed union { + raw: u4, + value: enum(u4) { + /// Calculate a CRC-32 (IEEE802.3 polynomial) + CRC32 = 0x0, + /// Calculate a CRC-32 (IEEE802.3 polynomial) with bit reversed data + CRC32R = 0x1, + /// Calculate a CRC-16-CCITT + CRC16 = 0x2, + /// Calculate a CRC-16-CCITT with bit reversed data + CRC16R = 0x3, + /// XOR reduction over all data. == 1 if the total 1 population count is odd. + EVEN = 0xe, + /// Calculate a simple 32-bit checksum (addition with a 32 bit accumulator) + SUM = 0xf, + _, + }, + }, + /// Locally perform a byte reverse on the sniffed data, before feeding into checksum. + /// Note that the sniff hardware is downstream of the DMA channel byteswap performed in the read master: if channel CTRL_BSWAP and SNIFF_CTRL_BSWAP are both enabled, their effects cancel from the sniffer's point of view. + BSWAP: u1, + /// If set, the result appears bit-reversed when read. This does not affect the way the checksum is calculated; the result is transformed on-the-fly between the result register and the bus. + OUT_REV: u1, + /// If set, the result appears inverted (bitwise complement) when read. This does not affect the way the checksum is calculated; the result is transformed on-the-fly between the result register and the bus. + OUT_INV: u1, + padding: u20, + }), + /// Data accumulator for sniff hardware + /// Write an initial seed value here before starting a DMA transfer on the channel indicated by SNIFF_CTRL_DMACH. The hardware will update this register each time it observes a read from the indicated channel. Once the channel completes, the final result can be read from this register. + SNIFF_DATA: u32, + reserved1088: [4]u8, + /// Debug RAF, WAF, TDF levels + FIFO_LEVELS: mmio.Mmio(packed struct(u32) { + /// Current Transfer-Data-FIFO fill level + TDF_LVL: u8, + /// Current Write-Address-FIFO fill level + WAF_LVL: u8, + /// Current Read-Address-FIFO fill level + RAF_LVL: u8, + padding: u8, + }), + /// Abort an in-progress transfer sequence on one or more channels + CHAN_ABORT: mmio.Mmio(packed struct(u32) { + /// Each bit corresponds to a channel. Writing a 1 aborts whatever transfer sequence is in progress on that channel. The bit will remain high until any in-flight transfers have been flushed through the address and data FIFOs. + /// After writing, this register must be polled until it returns all-zero. Until this point, it is unsafe to restart the channel. + CHAN_ABORT: u16, + padding: u16, + }), + /// The number of channels this DMA instance is equipped with. This DMA supports up to 16 hardware channels, but can be configured with as few as one, to minimise silicon area. + N_CHANNELS: mmio.Mmio(packed struct(u32) { + N_CHANNELS: u5, + padding: u27, + }), + reserved2048: [948]u8, + /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + CH0_DBG_CTDREQ: mmio.Mmio(packed struct(u32) { + CH0_DBG_CTDREQ: u6, + padding: u26, + }), + /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + CH0_DBG_TCR: u32, + reserved2112: [56]u8, + /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + CH1_DBG_CTDREQ: mmio.Mmio(packed struct(u32) { + CH1_DBG_CTDREQ: u6, + padding: u26, + }), + /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + CH1_DBG_TCR: u32, + reserved2176: [56]u8, + /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + CH2_DBG_CTDREQ: mmio.Mmio(packed struct(u32) { + CH2_DBG_CTDREQ: u6, + padding: u26, + }), + /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + CH2_DBG_TCR: u32, + reserved2240: [56]u8, + /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + CH3_DBG_CTDREQ: mmio.Mmio(packed struct(u32) { + CH3_DBG_CTDREQ: u6, + padding: u26, + }), + /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + CH3_DBG_TCR: u32, + reserved2304: [56]u8, + /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + CH4_DBG_CTDREQ: mmio.Mmio(packed struct(u32) { + CH4_DBG_CTDREQ: u6, + padding: u26, + }), + /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + CH4_DBG_TCR: u32, + reserved2368: [56]u8, + /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + CH5_DBG_CTDREQ: mmio.Mmio(packed struct(u32) { + CH5_DBG_CTDREQ: u6, + padding: u26, + }), + /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + CH5_DBG_TCR: u32, + reserved2432: [56]u8, + /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + CH6_DBG_CTDREQ: mmio.Mmio(packed struct(u32) { + CH6_DBG_CTDREQ: u6, + padding: u26, + }), + /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + CH6_DBG_TCR: u32, + reserved2496: [56]u8, + /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + CH7_DBG_CTDREQ: mmio.Mmio(packed struct(u32) { + CH7_DBG_CTDREQ: u6, + padding: u26, + }), + /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + CH7_DBG_TCR: u32, + reserved2560: [56]u8, + /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + CH8_DBG_CTDREQ: mmio.Mmio(packed struct(u32) { + CH8_DBG_CTDREQ: u6, + padding: u26, + }), + /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + CH8_DBG_TCR: u32, + reserved2624: [56]u8, + /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + CH9_DBG_CTDREQ: mmio.Mmio(packed struct(u32) { + CH9_DBG_CTDREQ: u6, + padding: u26, + }), + /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + CH9_DBG_TCR: u32, + reserved2688: [56]u8, + /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + CH10_DBG_CTDREQ: mmio.Mmio(packed struct(u32) { + CH10_DBG_CTDREQ: u6, + padding: u26, + }), + /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + CH10_DBG_TCR: u32, + reserved2752: [56]u8, + /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + CH11_DBG_CTDREQ: mmio.Mmio(packed struct(u32) { + CH11_DBG_CTDREQ: u6, + padding: u26, + }), + /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + CH11_DBG_TCR: u32, + }; + + /// DPRAM layout for USB device. + pub const USBCTRL_DPRAM = extern struct { + /// Bytes 0-3 of the SETUP packet from the host. + SETUP_PACKET_LOW: mmio.Mmio(packed struct(u32) { + BMREQUESTTYPE: u8, + BREQUEST: u8, + WVALUE: u16, + }), + /// Bytes 4-7 of the setup packet from the host. + SETUP_PACKET_HIGH: mmio.Mmio(packed struct(u32) { + WINDEX: u16, + WLENGTH: u16, + }), + EP1_IN_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP1_OUT_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP2_IN_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP2_OUT_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP3_IN_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP3_OUT_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP4_IN_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP4_OUT_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP5_IN_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP5_OUT_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP6_IN_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP6_OUT_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP7_IN_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP7_OUT_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP8_IN_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP8_OUT_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP9_IN_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP9_OUT_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP10_IN_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP10_OUT_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP11_IN_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP11_OUT_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP12_IN_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP12_OUT_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP13_IN_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP13_OUT_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP14_IN_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP14_OUT_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP15_IN_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + EP15_OUT_CONTROL: mmio.Mmio(packed struct(u32) { + /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + BUFFER_ADDRESS: u16, + /// Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_NAK: u1, + /// Trigger an interrupt if a STALL is sent. Intended for debug only. + INTERRUPT_ON_STALL: u1, + reserved26: u8, + ENDPOINT_TYPE: packed union { + raw: u2, + value: enum(u2) { + Control = 0x0, + Isochronous = 0x1, + Bulk = 0x2, + Interrupt = 0x3, + }, + }, + /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_DOUBLE_BUFF: u1, + /// Trigger an interrupt each time a buffer is done. + INTERRUPT_PER_BUFF: u1, + /// This endpoint is double buffered. + DOUBLE_BUFFERED: u1, + /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + ENABLE: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP0_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP0_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP1_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP1_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP2_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP2_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP3_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP3_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP4_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP4_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP5_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP5_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP6_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP6_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP7_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP7_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP8_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP8_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP9_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP9_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP10_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP10_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP11_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP11_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP12_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP12_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP13_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP13_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP14_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP14_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP15_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + EP15_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { + /// The length of the data in buffer 0. + LENGTH_0: u10, + /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_0: u1, + /// Reply with a stall (valid for both buffers). + STALL: u1, + /// Reset the buffer selector to buffer 0. + RESET: u1, + /// The data pid of buffer 0. + PID_0: u1, + /// Buffer 0 is the last buffer of the transfer. + LAST_0: u1, + /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_0: u1, + /// The length of the data in buffer 1. + LENGTH_1: u10, + /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + AVAILABLE_1: u1, + /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + /// For a non Isochronous endpoint the offset is always 64 bytes. + DOUBLE_BUFFER_ISO_OFFSET: packed union { + raw: u2, + value: enum(u2) { + @"128" = 0x0, + @"256" = 0x1, + @"512" = 0x2, + @"1024" = 0x3, + }, + }, + /// The data pid of buffer 1. + PID_1: u1, + /// Buffer 1 is the last buffer of the transfer. + LAST_1: u1, + /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + FULL_1: u1, + }), + }; + }; +}; diff --git a/src/hal.zig b/src/hal.zig index 06c0cdd..21323de 100644 --- a/src/hal.zig +++ b/src/hal.zig @@ -28,6 +28,6 @@ pub fn init() void { clock_config.apply(); } -pub fn getCpuId() u32 { +pub fn get_cpu_id() u32 { return regs.SIO.CPUID.*; } diff --git a/src/hal/adc.zig b/src/hal/adc.zig index 3cf29fa..1746ccc 100644 --- a/src/hal/adc.zig +++ b/src/hal/adc.zig @@ -4,28 +4,28 @@ const std = @import("std"); const assert = std.debug.assert; const microzig = @import("microzig"); -const ADC = microzig.chip.registers.ADC; +const ADC = microzig.chip.peripherals.ADC; const rp2040 = microzig.hal; const gpio = rp2040.gpio; const resets = rp2040.resets; pub const temperature_sensor = struct { pub inline fn init() void { - setTempSensorEnabled(true); + set_temp_sensor_enabled(true); } pub inline fn deinit() void { - setTempSensorEnabled(false); + set_temp_sensor_enabled(false); } - pub inline fn readRaw() u16 { + pub inline fn read_raw() u16 { return Input.read(.temperature_sensor); } // One-shot conversion returning the temperature in Celcius pub inline fn read(comptime T: type, comptime Vref: T) T { // TODO: consider fixed-point - const raw = @intToFloat(T, readRaw()); + const raw = @intToFloat(T, read_raw()); const voltage: T = Vref * raw / 0x0fff; return (27.0 - ((voltage - 0.706) / 0.001721)); } @@ -41,11 +41,11 @@ pub const Input = enum(u3) { /// Setup the GPIO pin as an ADC input pub fn init(comptime input: Input) void { switch (input) { - .temperature_sensor => setTempSensorEnabled(true), + .temperature_sensor => set_temp_sensor_enabled(true), else => { const gpio_num = @as(u32, @enumToInt(input)) + 26; - gpio.setFunction(gpio_num, .@"null"); + gpio.set_function(gpio_num, .null); // TODO: implement these, otherwise adc isn't going to work. //gpio.disablePulls(gpio_num); //gpio.setInputEnabled(gpio_num, false); @@ -57,7 +57,7 @@ pub const Input = enum(u3) { /// one of the others. pub inline fn deinit(input: Input) void { switch (input) { - .temperature_sensor => setTempSensorEnabled(true), + .temperature_sensor => set_temp_sensor_enabled(true), else => {}, } } @@ -74,7 +74,7 @@ pub const Input = enum(u3) { // wait for the while (ADC.CS.read().READY == 0) {} - return ADC.RESULT.read(); + return ADC.RESULT.read().RESULT; } }; @@ -116,42 +116,47 @@ pub fn init() void { .ERR_STICKY = 0, .AINSEL = 0, .RROBIN = 0, + + .reserved8 = 0, + .reserved12 = 0, + .reserved16 = 0, + .padding = 0, }); while (ADC.CS.read().READY == 0) {} } /// Enable/disable ADC interrupt -pub inline fn irqSetEnabled(enable: bool) void { +pub inline fn irq_set_enabled(enable: bool) void { // TODO: check if this works ADC.INTE.write(.{ .FIFO = if (enable) @as(u1, 1) else @as(u1, 0) }); } /// Select analog input for next conversion. -pub inline fn selectInput(input: Input) void { +pub inline fn select_input(input: Input) void { ADC.CS.modify(.{ .AINSEL = @enumToInt(input) }); } /// Get the currently selected analog input. 0..3 are GPIO 26..29 respectively, /// 4 is the temperature sensor. -pub inline fn getSelectedInput() Input { +pub inline fn get_selected_input() Input { // TODO: ensure that the field shouldn't have other values return @intToEnum(Input, ADC.CS.read().AINSEL); } /// Set to true to power on the temperature sensor. -pub inline fn setTempSensorEnabled(enable: bool) void { +pub inline fn set_temp_sensor_enabled(enable: bool) void { ADC.CS.modify(.{ .TS_EN = if (enable) @as(u1, 1) else @as(u1, 0) }); } /// Sets which of the inputs are to be run in round-robin mode. Setting all to /// 0 will disable round-robin mode but `disableRoundRobin()` is provided so /// the user may be explicit. -pub inline fn setRoundRobin(comptime enabled_inputs: InputMask) void { +pub inline fn set_round_robin(comptime enabled_inputs: InputMask) void { ADC.CS.modify(.{ .RROBIN = @bitCast(u5, enabled_inputs) }); } /// Disable round-robin sample mode. -pub inline fn disableRoundRobin() void { +pub inline fn disable_round_robin() void { ADC.CS.modify(.{ .RROBIN = 0 }); } @@ -160,7 +165,7 @@ pub inline fn run(enable: bool) void { ADC.CS.modify(.{ .START_MANY = if (enable) @as(u1, 1) else @as(u1, 0) }); } -pub inline fn setClkDiv() void { +pub inline fn set_clk_div() void { @compileError("todo"); } @@ -173,12 +178,12 @@ pub const fifo = struct { } /// Return true if FIFO is empty. - pub inline fn isEmpty() bool { + pub inline fn is_empty() bool { @compileError("todo"); } /// Read how many samples are in the FIFO. - pub inline fn getLevel() u8 { + pub inline fn get_level() u8 { @compileError("todo"); } @@ -188,7 +193,7 @@ pub const fifo = struct { } /// Block until result is available in FIFO, then pop it. - pub inline fn getBlocking() u16 { + pub inline fn get_blocking() u16 { @compileError("todo"); } diff --git a/src/hal/clocks.zig b/src/hal/clocks.zig index e703db4..4a49809 100644 --- a/src/hal/clocks.zig +++ b/src/hal/clocks.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const microzig = @import("microzig"); + const pll = @import("pll.zig"); const util = @import("util.zig"); const assert = std.debug.assert; @@ -7,8 +7,11 @@ const assert = std.debug.assert; // TODO: remove const gpio = @import("gpio.zig"); -const regs = microzig.chip.registers; -const CLOCKS = regs.CLOCKS; +const microzig = @import("microzig"); +const peripherals = microzig.chip.peripherals; +const CLOCKS = peripherals.CLOCKS; +const WATCHDOG = peripherals.WATCHDOG; +const XOSC = peripherals.XOSC; const xosc_freq = microzig.board.xosc_freq; /// this is only nominal, very imprecise and prone to drift over time const rosc_freq = 6_500_000; @@ -22,25 +25,25 @@ pub const xosc = struct { const startup_delay_value = xosc_freq * startup_delay_ms / 1000 / 256; pub fn init() void { - regs.XOSC.STARTUP.modify(.{ .DELAY = startup_delay_value }); - regs.XOSC.CTRL.modify(.{ .ENABLE = 4011 }); + XOSC.STARTUP.modify(.{ .DELAY = startup_delay_value }); + XOSC.CTRL.modify(.{ .ENABLE = .{ .value = .ENABLE } }); // wait for xosc startup to complete: - while (regs.XOSC.STATUS.read().STABLE == 0) {} + while (XOSC.STATUS.read().STABLE == 0) {} } - pub fn waitCycles(value: u8) void { + pub fn wait_cycles(value: u8) void { assert(is_enabled: { - const status = regs.XOSC.STATUS.read(); + const status = XOSC.STATUS.read(); break :is_enabled status.STABLE != 0 and status.ENABLED != 0; }); - regs.XOSC.COUNT.modify(value); - while (regs.XOSC.COUNT.read() != 0) {} + XOSC.COUNT.modify(value); + while (XOSC.COUNT.read() != 0) {} } }; -fn formatUppercase( +fn format_uppercase( bytes: []const u8, comptime fmt: []const u8, options: std.fmt.FormatOptions, @@ -52,7 +55,7 @@ fn formatUppercase( try writer.writeByte(std.ascii.toUpper(c)); } -fn uppercase(bytes: []const u8) std.fmt.Formatter(formatUppercase) { +fn uppercase(bytes: []const u8) std.fmt.Formatter(format_uppercase) { return .{ .data = bytes }; } @@ -81,16 +84,13 @@ pub const Generator = enum(u32) { assert(24 == @sizeOf([2]GeneratorRegs)); } - const generators = @intToPtr( - *volatile [@typeInfo(Generator).Enum.fields.len]GeneratorRegs, - regs.CLOCKS.base_address, - ); + const generators = @ptrCast(*volatile [@typeInfo(Generator).Enum.fields.len]GeneratorRegs, CLOCKS); - fn getRegs(generator: Generator) *volatile GeneratorRegs { + fn get_regs(generator: Generator) *volatile GeneratorRegs { return &generators[@enumToInt(generator)]; } - pub fn hasGlitchlessMux(generator: Generator) bool { + pub fn has_glitchless_mux(generator: Generator) bool { return switch (generator) { .sys, .ref => true, else => false, @@ -100,22 +100,22 @@ pub const Generator = enum(u32) { pub fn enable(generator: Generator) void { switch (generator) { .ref, .sys => {}, - else => generator.getRegs().ctrl |= (1 << 11), + else => generator.get_regs().ctrl |= (1 << 11), } } - pub fn setDiv(generator: Generator, div: u32) void { + pub fn set_div(generator: Generator, div: u32) void { if (generator == .peri) return; - generator.getRegs().div = div; + generator.get_regs().div = div; } - pub fn getDiv(generator: Generator) u32 { + pub fn get_div(generator: Generator) u32 { if (generator == .peri) return 1; - return generator.getRegs().div; + return generator.get_regs().div; } // The bitfields for the *_SELECTED registers are actually a mask of which @@ -125,21 +125,21 @@ pub const Generator = enum(u32) { // // Some mention that this is only for the glitchless mux, so if it is non-glitchless then return true pub fn selected(generator: Generator) bool { - return (0 != generator.getRegs().selected); + return (0 != generator.get_regs().selected); } - pub fn clearSource(generator: Generator) void { - generator.getRegs().ctrl &= ~@as(u32, 0x3); + pub fn clear_source(generator: Generator) void { + generator.get_regs().ctrl &= ~@as(u32, 0x3); } pub fn disable(generator: Generator) void { switch (generator) { .sys, .ref => {}, - else => generator.getRegs().ctrl &= ~@as(u32, 1 << 11), + else => generator.get_regs().ctrl &= ~@as(u32, 1 << 11), } } - pub fn isAuxSource(generator: Generator, source: Source) bool { + pub fn is_aux_source(generator: Generator, source: Source) bool { return switch (generator) { .sys => switch (source) { .clk_ref => false, @@ -153,16 +153,16 @@ pub const Generator = enum(u32) { }; } - pub fn setSource(generator: Generator, src: u32) void { - std.debug.assert(generator.hasGlitchlessMux()); - const gen_regs = generator.getRegs(); + pub fn set_source(generator: Generator, src: u32) void { + std.debug.assert(generator.has_glitchless_mux()); + const gen_regs = generator.get_regs(); const mask = ~@as(u32, 0x3); const ctrl_value = gen_regs.ctrl; gen_regs.ctrl = (ctrl_value & mask) | src; } - pub fn setAuxSource(generator: Generator, auxsrc: u32) void { - const gen_regs = generator.getRegs(); + pub fn set_aux_source(generator: Generator, auxsrc: u32) void { + const gen_regs = generator.get_regs(); const mask = ~@as(u32, 0x1e0); const ctrl_value = gen_regs.ctrl; gen_regs.ctrl = (ctrl_value & mask) | (auxsrc << 5); @@ -183,7 +183,7 @@ pub const Source = enum { clk_rtc, }; -fn srcValue(generator: Generator, source: Source) u32 { +fn src_value(generator: Generator, source: Source) u32 { return switch (generator) { .sys => src: { const ret: u32 = switch (source) { @@ -204,7 +204,7 @@ fn srcValue(generator: Generator, source: Source) u32 { }; } -fn auxSrcValue(generator: Generator, source: Source) u32 { +fn aux_src_value(generator: Generator, source: Source) u32 { return switch (generator) { .sys => auxsrc: { const ret: u32 = switch (source) { @@ -308,7 +308,7 @@ pub const GlobalConfiguration = struct { // TODO: allow user to configure PLLs to optimize for low-jitter, low-power, or manually specify }; - pub fn getFrequency(config: GlobalConfiguration, source: Source) ?u32 { + pub fn get_frequency(config: GlobalConfiguration, source: Source) ?u32 { return switch (source) { .src_xosc => xosc_freq, .src_rosc => rosc_freq, @@ -337,11 +337,11 @@ pub const GlobalConfiguration = struct { .generator = .ref, .input = .{ .source = ref_opts.source, - .freq = config.getFrequency(ref_opts.source).?, - .src_value = srcValue(.ref, ref_opts.source), - .auxsrc_value = auxSrcValue(.ref, ref_opts.source), + .freq = config.get_frequency(ref_opts.source).?, + .src_value = src_value(.ref, ref_opts.source), + .auxsrc_value = aux_src_value(.ref, ref_opts.source), }, - .output_freq = config.getFrequency(ref_opts.source).?, + .output_freq = config.get_frequency(ref_opts.source).?, }; } else if (config.pll_sys != null or config.pll_usb != null) ref_config: { config.xosc_configured = true; @@ -350,8 +350,8 @@ pub const GlobalConfiguration = struct { .input = .{ .source = .src_xosc, .freq = xosc_freq, - .src_value = srcValue(.ref, .src_xosc), - .auxsrc_value = auxSrcValue(.ref, .src_xosc), + .src_value = src_value(.ref, .src_xosc), + .auxsrc_value = aux_src_value(.ref, .src_xosc), }, .output_freq = xosc_freq, }; @@ -369,8 +369,8 @@ pub const GlobalConfiguration = struct { break :input .{ .source = .src_rosc, .freq = rosc_freq, - .src_value = srcValue(.sys, .src_rosc), - .auxsrc_value = auxSrcValue(.sys, .src_rosc), + .src_value = src_value(.sys, .src_rosc), + .auxsrc_value = aux_src_value(.sys, .src_rosc), }; }, .src_xosc => input: { @@ -380,8 +380,8 @@ pub const GlobalConfiguration = struct { break :input .{ .source = .src_xosc, .freq = xosc_freq, - .src_value = srcValue(.sys, .src_xosc), - .auxsrc_value = auxSrcValue(.sys, .src_xosc), + .src_value = src_value(.sys, .src_xosc), + .auxsrc_value = aux_src_value(.sys, .src_xosc), }; }, .pll_sys => input: { @@ -402,8 +402,8 @@ pub const GlobalConfiguration = struct { // TODO: not really sure what frequency to // drive pll at yet, but this is an okay start .freq = 125_000_000, - .src_value = srcValue(.sys, .pll_sys), - .auxsrc_value = auxSrcValue(.sys, .pll_sys), + .src_value = src_value(.sys, .pll_sys), + .auxsrc_value = aux_src_value(.sys, .pll_sys), }; }, @@ -433,8 +433,8 @@ pub const GlobalConfiguration = struct { .input = .{ .source = .pll_usb, .freq = 48_000_000, - .src_value = srcValue(.usb, .pll_usb), - .auxsrc_value = auxSrcValue(.usb, .pll_usb), + .src_value = src_value(.usb, .pll_usb), + .auxsrc_value = aux_src_value(.usb, .pll_usb), }, .output_freq = 48_000_000, }; @@ -470,8 +470,8 @@ pub const GlobalConfiguration = struct { .input = .{ .source = .pll_usb, .freq = 48_000_000, - .src_value = srcValue(.adc, .pll_usb), - .auxsrc_value = auxSrcValue(.adc, .pll_usb), + .src_value = src_value(.adc, .pll_usb), + .auxsrc_value = aux_src_value(.adc, .pll_usb), }, .output_freq = 48_000_000, }; @@ -501,8 +501,8 @@ pub const GlobalConfiguration = struct { .input = .{ .source = .pll_usb, .freq = 48_000_000, - .src_value = srcValue(.rtc, .pll_usb), - .auxsrc_value = auxSrcValue(.rtc, .pll_usb), + .src_value = src_value(.rtc, .pll_usb), + .auxsrc_value = aux_src_value(.rtc, .pll_usb), }, .output_freq = 48_000_000, }; @@ -516,15 +516,15 @@ pub const GlobalConfiguration = struct { .generator = .peri, .input = .{ .source = peri_opts.source, - .freq = config.getFrequency(peri_opts.source) orelse + .freq = config.get_frequency(peri_opts.source) orelse @compileError("you need to configure the source: " ++ @tagName(peri_opts.source)), - .src_value = srcValue(.peri, peri_opts.source), - .auxsrc_value = auxSrcValue(.peri, peri_opts.source), + .src_value = src_value(.peri, peri_opts.source), + .auxsrc_value = aux_src_value(.peri, peri_opts.source), }, .output_freq = if (peri_opts.freq) |output_freq| output_freq else - config.getFrequency(peri_opts.source).?, + config.get_frequency(peri_opts.source).?, }; } else null; @@ -532,15 +532,15 @@ pub const GlobalConfiguration = struct { .generator = .gpout0, .input = .{ .source = gpout0_opts.source, - .freq = config.getFrequency(gpout0_opts.source) orelse + .freq = config.get_frequency(gpout0_opts.source) orelse @compileError("you need to configure the source: " ++ @tagName(gpout0_opts.source)), - .src_value = srcValue(.gpout0, gpout0_opts.source), - .auxsrc_value = auxSrcValue(.gpout0, gpout0_opts.source), + .src_value = src_value(.gpout0, gpout0_opts.source), + .auxsrc_value = aux_src_value(.gpout0, gpout0_opts.source), }, .output_freq = if (gpout0_opts.freq) |output_freq| output_freq else - config.getFrequency(gpout0_opts.source).?, + config.get_frequency(gpout0_opts.source).?, } else null; return config; @@ -551,10 +551,10 @@ pub const GlobalConfiguration = struct { pub fn apply(comptime config: GlobalConfiguration) void { // disable resus if it has been turned on elsewhere - regs.CLOCKS.CLK_SYS_RESUS_CTRL.raw = 0; + CLOCKS.CLK_SYS_RESUS_CTRL.raw = 0; if (config.xosc_configured) { - regs.WATCHDOG.TICK.modify(.{ + WATCHDOG.TICK.modify(.{ .CYCLES = xosc_freq / 1_000_000, .ENABLE = 1, }); @@ -565,7 +565,7 @@ pub const GlobalConfiguration = struct { // configured to use/be used from PLLs if (config.sys) |sys| switch (sys.input.source) { .pll_usb, .pll_sys => { - regs.CLOCKS.CLK_SYS_CTRL.modify(.{ .SRC = 0 }); + CLOCKS.CLK_SYS_CTRL.modify(.{ .SRC = .{ .raw = 0 } }); while (!Generator.sys.selected()) {} }, else => {}, @@ -573,7 +573,7 @@ pub const GlobalConfiguration = struct { if (config.ref) |ref| switch (ref.input.source) { .pll_usb, .pll_sys => { - regs.CLOCKS.CLK_REF_CTRL.modify(.{ .SRC = 0 }); + CLOCKS.CLK_REF_CTRL.modify(.{ .SRC = .{ .raw = 0 } }); while (!Generator.ref.selected()) {} }, else => {}, @@ -621,11 +621,11 @@ pub const Configuration = struct { const div = @intCast(u32, (@intCast(u64, input.freq) << 8) / output_freq); // check divisor - if (div > generator.getDiv()) - generator.setDiv(div); + if (div > generator.get_div()) + generator.set_div(div); - if (generator.hasGlitchlessMux() and input.src_value == 1) { - generator.clearSource(); + if (generator.has_glitchless_mux() and input.src_value == 1) { + generator.clear_source(); while (!generator.selected()) {} } else { @@ -643,21 +643,21 @@ pub const Configuration = struct { ); } - generator.setAuxSource(input.auxsrc_value); + generator.set_aux_source(input.auxsrc_value); // set aux mux first and then glitchless mex if this clock has one - if (generator.hasGlitchlessMux()) { - generator.setSource(input.src_value); + if (generator.has_glitchless_mux()) { + generator.set_source(input.src_value); while (!generator.selected()) {} } generator.enable(); - generator.setDiv(div); + generator.set_div(div); } }; // NOTE: untested -pub fn countFrequencyKhz(source: Source, comptime clock_config: GlobalConfiguration) u32 { +pub fn count_frequency_khz(source: Source, comptime clock_config: GlobalConfiguration) u32 { const ref_freq = clock_config.ref.?.output_freq; // wait for counter to be done diff --git a/src/hal/gpio.zig b/src/hal/gpio.zig index e725d79..1e333b1 100644 --- a/src/hal/gpio.zig +++ b/src/hal/gpio.zig @@ -1,8 +1,13 @@ const std = @import("std"); +const assert = std.debug.assert; + const microzig = @import("microzig"); +const peripherals = microzig.chip.peripherals; +const SIO = peripherals.SIO; +const PADS_BANK0 = peripherals.PADS_BANK0; +const IO_BANK0 = peripherals.IO_BANK0; + const resets = @import("resets.zig"); -const regs = microzig.chip.registers; -const assert = std.debug.assert; const log = std.log.scoped(.gpio); @@ -17,7 +22,7 @@ pub const Function = enum(u5) { pio1, gpck, usb, - @"null" = 0x1f, + null = 0x1f, }; pub const Direction = enum(u1) { @@ -65,14 +70,14 @@ pub inline fn reset() void { /// Initialize a GPIO, set func to SIO pub inline fn init(comptime gpio: u32) void { const mask = 1 << gpio; - regs.SIO.GPIO_OE_CLR.raw = mask; - regs.SIO.GPIO_OUT_CLR.raw = mask; - setFunction(gpio, .sio); + SIO.GPIO_OE_CLR.raw = mask; + SIO.GPIO_OUT_CLR.raw = mask; + set_function(gpio, .sio); } /// Reset GPIO back to null function (disables it) pub inline fn deinit(comptime gpio: u32) void { - setFunction(gpio, .@"null"); + set_function(gpio, .null); } pub const PullUpDown = enum { @@ -80,9 +85,9 @@ pub const PullUpDown = enum { down, }; -pub inline fn setPullUpDown(comptime gpio: u32, mode: ?PullUpDown) void { +pub inline fn set_pull(comptime gpio: u32, mode: ?PullUpDown) void { const gpio_name = comptime std.fmt.comptimePrint("GPIO{d}", .{gpio}); - const gpio_regs = @field(regs.PADS_BANK0, gpio_name); + const gpio_regs = @field(PADS_BANK0, gpio_name); if (mode == null) { gpio_regs.modify(.{ .PUE = 0, .PDE = 0 }); @@ -92,11 +97,11 @@ pub inline fn setPullUpDown(comptime gpio: u32, mode: ?PullUpDown) void { } } -pub inline fn setDir(comptime gpio: u32, direction: Direction) void { +pub inline fn set_direction(comptime gpio: u32, direction: Direction) void { const mask = 1 << gpio; switch (direction) { - .in => regs.SIO.GPIO_OE_CLR.raw = mask, - .out => regs.SIO.GPIO_OE_SET.raw = mask, + .in => SIO.GPIO_OE_CLR.raw = mask, + .out => SIO.GPIO_OE_SET.raw = mask, } } @@ -105,37 +110,43 @@ pub inline fn put(comptime gpio: u32, value: u1) void { std.log.debug("GPIO{} put: {}", .{ gpio, value }); const mask = 1 << gpio; switch (value) { - 0 => regs.SIO.GPIO_OUT_CLR.raw = mask, - 1 => regs.SIO.GPIO_OUT_SET.raw = mask, + 0 => SIO.GPIO_OUT_CLR.raw = mask, + 1 => SIO.GPIO_OUT_SET.raw = mask, } } pub inline fn toggle(comptime gpio: u32) void { - regs.SIO.GPIO_OUT_XOR.raw = (1 << gpio); + SIO.GPIO_OUT_XOR.raw = (1 << gpio); } pub inline fn read(comptime gpio: u32) u1 { const mask = 1 << gpio; - return if ((regs.SIO.GPIO_IN.raw & mask) != 0) + return if ((SIO.GPIO_IN.raw & mask) != 0) 1 else 0; } -pub inline fn setFunction(comptime gpio: u32, function: Function) void { +pub inline fn set_function(comptime gpio: u32, function: Function) void { const pad_bank_reg = comptime std.fmt.comptimePrint("GPIO{}", .{gpio}); - @field(regs.PADS_BANK0, pad_bank_reg).modify(.{ + @field(PADS_BANK0, pad_bank_reg).modify(.{ .IE = 1, .OD = 0, }); const io_bank_reg = comptime std.fmt.comptimePrint("GPIO{}_CTRL", .{gpio}); - @field(regs.IO_BANK0, io_bank_reg).write(.{ - .FUNCSEL = @enumToInt(function), - .OUTOVER = 0, - .INOVER = 0, - .IRQOVER = 0, - .OEOVER = 0, + @field(IO_BANK0, io_bank_reg).write(.{ + .FUNCSEL = .{ .raw = @enumToInt(function) }, + .OUTOVER = .{ .value = .NORMAL }, + .INOVER = .{ .value = .NORMAL }, + .IRQOVER = .{ .value = .NORMAL }, + .OEOVER = .{ .value = .NORMAL }, + + .reserved8 = 0, + .reserved12 = 0, + .reserved16 = 0, + .reserved28 = 0, + .padding = 0, }); } diff --git a/src/hal/irq.zig b/src/hal/irq.zig index 7d57c78..f3502be 100644 --- a/src/hal/irq.zig +++ b/src/hal/irq.zig @@ -3,18 +3,18 @@ const regs = microzig.chip.registers; // TODO: the register definitions are improved now, use them instead of raw // writes/reads -fn getInterruptMask(comptime interrupt_name: []const u8) u32 { +fn get_interrupt_mask(comptime interrupt_name: []const u8) u32 { const offset = @offsetOf(microzig.chip.VectorTable, interrupt_name); return (1 << ((offset / 4) - 16)); } pub fn enable(comptime interrupt_name: []const u8) void { - const mask = comptime getInterruptMask(interrupt_name); + const mask = comptime get_interrupt_mask(interrupt_name); regs.SCS.NVIC.ICPR.raw = mask; regs.SCS.NVIC.ISER.raw = mask; } pub fn disable(comptime interrupt_name: []const u8) void { - const mask = comptime getInterruptMask(interrupt_name); + const mask = comptime get_interrupt_mask(interrupt_name); regs.SCS.NVIC.ICER.raw = mask; } diff --git a/src/hal/multicore.zig b/src/hal/multicore.zig index f1bcfe0..e3199d9 100644 --- a/src/hal/multicore.zig +++ b/src/hal/multicore.zig @@ -1,25 +1,29 @@ const std = @import("std"); -const microzig = @import("microzig"); -const regs = microzig.chip.registers; const assert = std.debug.assert; +const microzig = @import("microzig"); +const peripherals = microzig.chip.peripherals; +const SIO = peripherals.SIO; +const PSM = peripherals.PSM; +const SCB = peripherals.SCB; + pub const fifo = struct { /// Check if the FIFO has valid data for reading. - pub fn isReadReady() bool { - return regs.SIO.FIFO_ST.read().VLD == 1; + pub fn is_read_ready() bool { + return SIO.FIFO_ST.read().VLD == 1; } /// Read from the FIFO /// Will return null if it is empty. pub fn read() ?u32 { - if (!isReadReady()) + if (!is_read_ready()) return null; - return regs.SIO.FIFO_RD.*; + return SIO.FIFO_RD; } /// Read from the FIFO, waiting for data if there is none. - pub fn readBloacking() u32 { + pub fn read_blocking() u32 { while (true) { if (read()) |value| return value; microzig.cpu.wfe(); @@ -32,20 +36,20 @@ pub const fifo = struct { } /// Check if the FIFO is ready to receive data. - pub fn isWriteReady() bool { - return regs.SIO.FIFO_ST.read().RDY == 1; + pub fn is_write_ready() bool { + return SIO.FIFO_ST.read().RDY == 1; } /// Write to the FIFO /// You must check if there is space by calling is_write_ready pub fn write(value: u32) void { - regs.SIO.FIFO_WR.* = value; + SIO.FIFO_WR = value; microzig.cpu.sev(); } /// Write to the FIFO, waiting for room if it is full. - pub fn writeBlocking(value: u32) void { - while (!isWriteReady()) + pub fn write_blocking(value: u32) void { + while (!is_write_ready()) std.mem.doNotOptimizeAway(value); write(value); @@ -55,11 +59,11 @@ pub const fifo = struct { var core1_stack: [128]u32 = undefined; /// Runs `entrypoint` on the second core. -pub fn launchCore1(entrypoint: *const fn () void) void { - launchCore1WithStack(entrypoint, &core1_stack); +pub fn launch_core1(entrypoint: *const fn () void) void { + launch_core1_with_stack(entrypoint, &core1_stack); } -pub fn launchCore1WithStack(entrypoint: *const fn () void, stack: []u32) void { +pub fn launch_core1_with_stack(entrypoint: *const fn () void, stack: []u32) void { // TODO: disable SIO interrupts const wrapper = &struct { @@ -71,9 +75,9 @@ pub fn launchCore1WithStack(entrypoint: *const fn () void, stack: []u32) void { }.wrapper; // reset the second core - regs.PSM.FRCE_OFF.modify(.{ .proc1 = 1 }); - while (regs.PSM.FRCE_OFF.read().proc1 != 1) microzig.cpu.nop(); - regs.PSM.FRCE_OFF.modify(.{ .proc1 = 0 }); + PSM.FRCE_OFF.modify(.{ .proc1 = 1 }); + while (PSM.FRCE_OFF.read().proc1 != 1) microzig.cpu.nop(); + PSM.FRCE_OFF.modify(.{ .proc1 = 0 }); stack[stack.len - 2] = @ptrToInt(entrypoint); stack[stack.len - 1] = @ptrToInt(stack.ptr); @@ -88,7 +92,7 @@ pub fn launchCore1WithStack(entrypoint: *const fn () void, stack: []u32) void { 0, 0, 1, - regs.SCS.SCB.VTOR.raw, + SCB.VTOR.raw, stack_ptr, @ptrToInt(wrapper), }; @@ -102,8 +106,8 @@ pub fn launchCore1WithStack(entrypoint: *const fn () void, stack: []u32) void { microzig.cpu.sev(); } - fifo.writeBlocking(cmd); + fifo.write_blocking(cmd); // the second core should respond with the same value, if it doesnt't lets start over - seq = if (cmd == fifo.readBloacking()) seq + 1 else 0; + seq = if (cmd == fifo.read_blocking()) seq + 1 else 0; } } diff --git a/src/hal/pins.zig b/src/hal/pins.zig index dce1c24..24b9d7a 100644 --- a/src/hal/pins.zig +++ b/src/hal/pins.zig @@ -1,13 +1,15 @@ const std = @import("std"); +const assert = std.debug.assert; +const comptimePrint = std.fmt.comptimePrint; +const StructField = std.builtin.Type.StructField; + +const microzig = @import("microzig"); +const SIO = microzig.chip.peripherals.SIO; + const gpio = @import("gpio.zig"); const pwm = @import("pwm.zig"); const adc = @import("adc.zig"); const resets = @import("resets.zig"); -const regs = @import("microzig").chip.registers; - -const assert = std.debug.assert; -const comptimePrint = std.fmt.comptimePrint; -const StructField = std.builtin.Type.StructField; pub const Pin = enum { GPIO0, @@ -52,16 +54,16 @@ pub const Pin = enum { // schmitt trigger // hysteresis - pub fn getDirection(comptime config: Configuration) gpio.Direction { + pub fn get_direction(comptime config: Configuration) gpio.Direction { return if (config.direction) |direction| direction - else if (comptime config.function.isPwm()) + else if (comptime config.function.is_pwm()) .out - else if (comptime config.function.isUartTx()) + else if (comptime config.function.is_uart_tx()) .out - else if (comptime config.function.isUartRx()) + else if (comptime config.function.is_uart_rx()) .in - else if (comptime config.function.isAdc()) + else if (comptime config.function.is_adc()) .in else @panic("TODO"); @@ -142,7 +144,7 @@ pub const Function = enum { ADC2, ADC3, - pub fn isPwm(function: Function) bool { + pub fn is_pwm(function: Function) bool { return switch (function) { .PWM0_A, .PWM0_B, @@ -165,7 +167,7 @@ pub const Function = enum { }; } - pub fn isUartTx(function: Function) bool { + pub fn is_uart_tx(function: Function) bool { return switch (function) { .UART0_TX, .UART1_TX, @@ -174,7 +176,7 @@ pub const Function = enum { }; } - pub fn isUartRx(function: Function) bool { + pub fn is_uart_rx(function: Function) bool { return switch (function) { .UART0_RX, .UART1_RX, @@ -183,7 +185,7 @@ pub const Function = enum { }; } - pub fn pwmSlice(comptime function: Function) u32 { + pub fn pwm_slice(comptime function: Function) u32 { return switch (function) { .PWM0_A, .PWM0_B => 0, .PWM1_A, .PWM1_B => 1, @@ -197,7 +199,7 @@ pub const Function = enum { }; } - pub fn isAdc(function: Function) bool { + pub fn is_adc(function: Function) bool { return switch (function) { .ADC0, .ADC1, @@ -208,7 +210,7 @@ pub const Function = enum { }; } - pub fn pwmChannel(comptime function: Function) pwm.Channel { + pub fn pwm_channel(comptime function: Function) pwm.Channel { return switch (function) { .PWM0_A, .PWM1_A, @@ -354,10 +356,10 @@ pub fn Pins(comptime config: GlobalConfiguration) type { if (pin_config.function == .SIO) { pin_field.name = pin_config.name orelse field.name; pin_field.type = GPIO(@enumToInt(@field(Pin, field.name)), pin_config.direction orelse .in); - } else if (pin_config.function.isPwm()) { + } else if (pin_config.function.is_pwm()) { pin_field.name = pin_config.name orelse @tagName(pin_config.function); - pin_field.type = pwm.PWM(pin_config.function.pwmSlice(), pin_config.function.pwmChannel()); - } else if (pin_config.function.isAdc()) { + pin_field.type = pwm.Pwm(pin_config.function.pwm_slice(), pin_config.function.pwm_channel()); + } else if (pin_config.function.is_adc()) { pin_field.name = pin_config.name orelse @tagName(pin_config.function); pin_field.type = adc.Input; pin_field.default_value = @ptrCast(?*const anyopaque, switch (pin_config.function) { @@ -453,16 +455,16 @@ pub const GlobalConfiguration = struct { @compileError(comptimePrint("{s} cannot be configured for {}", .{ field.name, pin_config.function })); if (pin_config.function == .SIO) { - switch (pin_config.getDirection()) { + switch (pin_config.get_direction()) { .in => input_gpios |= 1 << gpio_num, .out => output_gpios |= 1 << gpio_num, } } - if (pin_config.function.isAdc()) { + if (pin_config.function.is_adc()) { has_adc = true; } - if (pin_config.function.isPwm()) { + if (pin_config.function.is_pwm()) { has_pwm = true; } }; @@ -474,8 +476,8 @@ pub const GlobalConfiguration = struct { gpio.reset(); if (used_gpios != 0) { - regs.SIO.GPIO_OE_CLR.raw = used_gpios; - regs.SIO.GPIO_OUT_CLR.raw = used_gpios; + SIO.GPIO_OE_CLR.raw = used_gpios; + SIO.GPIO_OUT_CLR.raw = used_gpios; } inline for (@typeInfo(GlobalConfiguration).Struct.fields) |field| { @@ -494,13 +496,13 @@ pub const GlobalConfiguration = struct { // @"null" = 0x1f, if (func == .SIO) { - gpio.setFunction(gpio_num, .sio); - } else if (comptime func.isPwm()) { - gpio.setFunction(gpio_num, .pwm); - } else if (comptime func.isAdc()) { - gpio.setFunction(gpio_num, .null); + gpio.set_function(gpio_num, .sio); + } else if (comptime func.is_pwm()) { + gpio.set_function(gpio_num, .pwm); + } else if (comptime func.is_adc()) { + gpio.set_function(gpio_num, .null); } else if (comptime func.isUartTx() or func.isUartRx()) { - gpio.setFunction(gpio_num, .uart); + gpio.set_function(gpio_num, .uart); } else { @compileError(std.fmt.comptimePrint("Unimplemented pin function. Please implement setting pin function {s} for GPIO {}", .{ @tagName(func), @@ -511,7 +513,7 @@ pub const GlobalConfiguration = struct { } if (output_gpios != 0) - regs.SIO.GPIO_OE_SET.raw = output_gpios; + SIO.GPIO_OE_SET.raw = output_gpios; if (input_gpios != 0) { inline for (@typeInfo(GlobalConfiguration).Struct.fields) |field| @@ -521,7 +523,7 @@ pub const GlobalConfiguration = struct { if (comptime pin_config.getDirection() != .in) @compileError("Only input pins can have pull up/down enabled"); - gpio.setPullUpDown(gpio_num, pull); + gpio.set_pull(gpio_num, pull); }; } diff --git a/src/hal/pll.zig b/src/hal/pll.zig index 117a42c..62fd9ec 100644 --- a/src/hal/pll.zig +++ b/src/hal/pll.zig @@ -1,12 +1,12 @@ const std = @import("std"); -const microzig = @import("microzig"); const assert = std.debug.assert; -// TODO: remove -const gpio = @import("gpio.zig"); - -const regs = microzig.chip.registers; +const microzig = @import("microzig"); const xosc_freq = microzig.board.xosc_freq; +const peripherals = microzig.chip.peripherals; +const RESETS = peripherals.RESETS; + +const PllRegs = microzig.chip.types.peripherals.PLL_SYS; pub const Configuration = struct { refdiv: u6, @@ -23,28 +23,31 @@ pub const PLL = enum { sys, usb, - fn getRegs(pll: PLL) *volatile PllRegs { - return &plls[@enumToInt(pll)]; + fn get_regs(pll: PLL) *volatile PllRegs { + return switch (pll) { + .sys => peripherals.PLL_SYS, + .usb => peripherals.PLL_USB, + }; } pub fn reset(pll: PLL) void { switch (pll) { .sys => { - regs.RESETS.RESET.modify(.{ .pll_sys = 1 }); - regs.RESETS.RESET.modify(.{ .pll_sys = 0 }); - while (regs.RESETS.RESET_DONE.read().pll_sys != 1) {} + RESETS.RESET.modify(.{ .pll_sys = 1 }); + RESETS.RESET.modify(.{ .pll_sys = 0 }); + while (RESETS.RESET_DONE.read().pll_sys != 1) {} }, .usb => { - regs.RESETS.RESET.modify(.{ .pll_usb = 1 }); - regs.RESETS.RESET.modify(.{ .pll_usb = 0 }); - while (regs.RESETS.RESET_DONE.read().pll_usb != 1) {} + RESETS.RESET.modify(.{ .pll_usb = 1 }); + RESETS.RESET.modify(.{ .pll_usb = 0 }); + while (RESETS.RESET_DONE.read().pll_usb != 1) {} }, } } - pub fn isLocked(pll: PLL) bool { - const pll_regs = pll.getRegs(); - return pll_regs.cs.read().LOCK == 1; + pub fn is_locked(pll: PLL) bool { + const pll_regs = pll.get_regs(); + return pll_regs.CS.read().LOCK == 1; } pub fn apply(pll: PLL, comptime config: Configuration) void { @@ -53,7 +56,7 @@ pub const PLL = enum { assert(config.postdiv2 >= 1 and config.postdiv2 <= 7); assert(config.postdiv2 <= config.postdiv1); - const pll_regs = pll.getRegs(); + const pll_regs = pll.get_regs(); const ref_freq = xosc_freq / @as(u32, config.refdiv); const vco_freq = ref_freq * config.fbdiv; assert(ref_freq <= vco_freq / 16); @@ -65,11 +68,11 @@ pub const PLL = enum { // 5. set up post dividers and turn them on // do not bother a PLL which is already configured - if (pll.isLocked() and - config.refdiv == pll_regs.cs.read().REFDIV and - config.fbdiv == pll_regs.fbdiv_int.read() and - config.postdiv1 == pll_regs.prim.read().POSTDIV1 and - config.postdiv2 == pll_regs.prim.read().POSTDIV2) + if (pll.is_locked() and + config.refdiv == pll_regs.CS.read().REFDIV and + config.fbdiv == pll_regs.FBDIV_INT.read().FBDIV_INT and + config.postdiv1 == pll_regs.PRIM.read().POSTDIV1 and + config.postdiv2 == pll_regs.PRIM.read().POSTDIV2) { return; } @@ -77,39 +80,20 @@ pub const PLL = enum { pll.reset(); // load vco related dividers - pll_regs.cs.modify(.{ .REFDIV = config.refdiv }); - pll_regs.fbdiv_int.modify(config.fbdiv); + pll_regs.CS.modify(.{ .REFDIV = config.refdiv }); + pll_regs.FBDIV_INT.modify(.{ .FBDIV_INT = config.fbdiv }); // turn on PLL - pll_regs.pwr.modify(.{ .PD = 0, .VCOPD = 0 }); + pll_regs.PWR.modify(.{ .PD = 0, .VCOPD = 0 }); // wait for PLL to lock - while (!pll.isLocked()) {} + while (!pll.is_locked()) {} - pll_regs.prim.modify(.{ + pll_regs.PRIM.modify(.{ .POSTDIV1 = config.postdiv1, .POSTDIV2 = config.postdiv2, }); - pll_regs.pwr.modify(.{ .POSTDIVPD = 0 }); + pll_regs.PWR.modify(.{ .POSTDIVPD = 0 }); } }; - -const plls = @intToPtr(*volatile [2]PllRegs, regs.PLL_SYS.base_address); -comptime { - assert(@sizeOf(PllRegs) == (regs.PLL_USB.base_address - regs.PLL_SYS.base_address)); -} - -const CsReg = @typeInfo(@TypeOf(regs.PLL_SYS.CS)).Pointer.child; -const PwrReg = @typeInfo(@TypeOf(regs.PLL_SYS.PWR)).Pointer.child; -const FbdivIntReg = @typeInfo(@TypeOf(regs.PLL_SYS.FBDIV_INT)).Pointer.child; -const PrimReg = @typeInfo(@TypeOf(regs.PLL_SYS.PRIM)).Pointer.child; - -pub const PllRegs = extern struct { - cs: CsReg, - pwr: PwrReg, - fbdiv_int: FbdivIntReg, - prim: PrimReg, - - padding: [4092]u32, -}; diff --git a/src/hal/pwm.zig b/src/hal/pwm.zig index 8d28573..7277b11 100644 --- a/src/hal/pwm.zig +++ b/src/hal/pwm.zig @@ -1,24 +1,25 @@ const std = @import("std"); const microzig = @import("microzig"); -const regs = microzig.chip.registers; +const PWM = microzig.chip.peripherals.PWM; const log = std.log.scoped(.pwm); pub const Config = struct {}; -fn getRegs(comptime slice: u32) *volatile Regs { +fn get_regs(comptime slice: u32) *volatile Regs { @import("std").debug.assert(slice < 8); - const reg_diff = comptime (@ptrToInt(regs.PWM.CH1_CSR) - @ptrToInt(regs.PWM.CH0_CSR)); - return @intToPtr(*volatile Regs, regs.PWM.base_address + reg_diff * slice); + const PwmType = microzig.chip.types.peripherals.PWM; + const reg_diff = comptime @offsetOf(PwmType, "CH1_CSR") - @offsetOf(PwmType, "CH0_CSR"); + return @intToPtr(*volatile Regs, @ptrToInt(PWM) + reg_diff * slice); } -pub fn PWM(comptime slice_num: u32, comptime chan: Channel) type { +pub fn Pwm(comptime slice_num: u32, comptime chan: Channel) type { return struct { pub const slice_number = slice_num; pub const channel = chan; - pub inline fn setLevel(_: @This(), level: u16) void { - setChannelLevel(slice_number, channel, level); + pub inline fn set_level(_: @This(), level: u16) void { + set_channel_level(slice_number, channel, level); } pub fn slice(_: @This()) Slice(slice_number) { @@ -31,24 +32,24 @@ pub fn Slice(comptime slice_num: u32) type { return struct { const slice_number = slice_num; - pub inline fn setWrap(_: @This(), wrap: u16) void { - setSliceWrap(slice_number, wrap); + pub inline fn set_wrap(_: @This(), wrap: u16) void { + set_slice_wrap(slice_number, wrap); } pub inline fn enable(_: @This()) void { - getRegs(slice_number).csr.modify(.{ .EN = 1 }); + get_regs(slice_number).csr.modify(.{ .EN = 1 }); } pub inline fn disable(_: @This()) void { - getRegs(slice_number).csr.modify(.{ .EN = 0 }); + get_regs(slice_number).csr.modify(.{ .EN = 0 }); } - pub inline fn setPhaseCorrect(_: @This(), phase_correct: bool) void { - setSlicePhaseCorrect(slice_number, phase_correct); + pub inline fn set_phase_correct(_: @This(), phase_correct: bool) void { + set_slice_phase_correct(slice_number, phase_correct); } - pub inline fn setClkDiv(_: @This(), integer: u8, fraction: u4) void { - setSliceClkDiv(slice_number, integer, fraction); + pub inline fn set_clk_div(_: @This(), integer: u8, fraction: u4) void { + set_slice_clk_div(slice_number, integer, fraction); } }; } @@ -63,63 +64,63 @@ pub const ClkDivMode = enum(u2) { pub const Channel = enum(u1) { a, b }; const Regs = extern struct { - csr: @typeInfo(@TypeOf(regs.PWM.CH0_CSR)).Pointer.child, - div: @typeInfo(@TypeOf(regs.PWM.CH0_DIV)).Pointer.child, - ctr: @typeInfo(@TypeOf(regs.PWM.CH0_CTR)).Pointer.child, - cc: @typeInfo(@TypeOf(regs.PWM.CH0_CC)).Pointer.child, - top: @typeInfo(@TypeOf(regs.PWM.CH0_TOP)).Pointer.child, + csr: @TypeOf(PWM.CH0_CSR), + div: @TypeOf(PWM.CH0_DIV), + ctr: @TypeOf(PWM.CH0_CTR), + cc: @TypeOf(PWM.CH0_CC), + top: @TypeOf(PWM.CH0_TOP), }; -pub inline fn setSlicePhaseCorrect(comptime slice: u32, phase_correct: bool) void { +pub inline fn set_slice_phase_correct(comptime slice: u32, phase_correct: bool) void { log.debug("PWM{} set phase correct: {}", .{ slice, phase_correct }); - getRegs(slice).csr.modify(.{ + get_regs(slice).csr.modify(.{ .PH_CORRECT = @boolToInt(phase_correct), }); } -pub inline fn setSliceClkDiv(comptime slice: u32, integer: u8, fraction: u4) void { +pub inline fn set_slice_clk_div(comptime slice: u32, integer: u8, fraction: u4) void { log.debug("PWM{} set clk div: {}.{}", .{ slice, integer, fraction }); - getRegs(slice).div.modify(.{ + get_regs(slice).div.modify(.{ .INT = integer, .FRAC = fraction, }); } -pub inline fn setSliceClkDivMode(comptime slice: u32, mode: ClkDivMode) void { +pub inline fn set_slice_clk_div_mode(comptime slice: u32, mode: ClkDivMode) void { log.debug("PWM{} set clk div mode: {}", .{ slice, mode }); - getRegs(slice).csr.modify(.{ + get_regs(slice).csr.modify(.{ .DIVMODE = @enumToInt(mode), }); } -pub inline fn setChannelInversion( +pub inline fn set_channel_inversion( comptime slice: u32, comptime channel: Channel, invert: bool, ) void { switch (channel) { - .a => getRegs(slice).csr.modify(.{ + .a => get_regs(slice).csr.modify(.{ .A_INV = @boolToInt(invert), }), - .b => getRegs(slice).csr.modifi(.{ + .b => get_regs(slice).csr.modifi(.{ .B_INV = @boolToInt(invert), }), } } -pub inline fn setSliceWrap(comptime slice: u32, wrap: u16) void { +pub inline fn set_slice_wrap(comptime slice: u32, wrap: u16) void { log.debug("PWM{} set wrap: {}", .{ slice, wrap }); - getRegs(slice).top.raw = wrap; + get_regs(slice).top.raw = wrap; } -pub inline fn setChannelLevel( +pub inline fn set_channel_level( comptime slice: u32, comptime channel: Channel, level: u16, ) void { log.debug("PWM{} {} set level: {}", .{ slice, channel, level }); switch (channel) { - .a => getRegs(slice).cc.modify(.{ .A = level }), - .b => getRegs(slice).cc.modify(.{ .B = level }), + .a => get_regs(slice).cc.modify(.{ .A = level }), + .b => get_regs(slice).cc.modify(.{ .B = level }), } } diff --git a/src/hal/resets.zig b/src/hal/resets.zig index 45b2230..218e6b4 100644 --- a/src/hal/resets.zig +++ b/src/hal/resets.zig @@ -1,9 +1,9 @@ const std = @import("std"); -const microzig = @import("microzig"); - -const regs = microzig.chip.registers; const EnumField = std.builtin.Type.EnumField; -const Mask = @typeInfo(@TypeOf(regs.RESETS.RESET)).Pointer.child.underlying_type; + +const microzig = @import("microzig"); +const RESETS = microzig.chip.peripherals.RESETS; +const Mask = @TypeOf(RESETS.RESET).underlying_type; pub const Module = enum { adc, @@ -41,8 +41,8 @@ pub inline fn reset(comptime modules: []const Module) void { const raw_mask = @bitCast(u32, mask); - regs.RESETS.RESET.raw = raw_mask; - regs.RESETS.RESET.raw = 0; + RESETS.RESET.raw = raw_mask; + RESETS.RESET.raw = 0; - while ((regs.RESETS.RESET_DONE.raw & raw_mask) != raw_mask) {} + while ((RESETS.RESET_DONE.raw & raw_mask) != raw_mask) {} } diff --git a/src/hal/time.zig b/src/hal/time.zig index 2ed49ae..3b568bf 100644 --- a/src/hal/time.zig +++ b/src/hal/time.zig @@ -1,16 +1,16 @@ const microzig = @import("microzig"); -const TIMER = microzig.chip.registers.TIMER; +const TIMER = microzig.chip.peripherals.TIMER; pub const Absolute = struct { us_since_boot: u64, }; -pub fn getTimeSinceBoot() Absolute { - var high_word = TIMER.TIMERAWH.*; +pub fn get_time_since_boot() Absolute { + var high_word = TIMER.TIMERAWH; return while (true) { - var low_word = TIMER.TIMERAWL.*; - const next_high_word = TIMER.TIMERAWH.*; + var low_word = TIMER.TIMERAWL; + const next_high_word = TIMER.TIMERAWH; if (next_high_word == high_word) break Absolute{ .us_since_boot = @intCast(u64, high_word) << 32 | low_word, @@ -20,24 +20,24 @@ pub fn getTimeSinceBoot() Absolute { } else unreachable; } -pub fn makeTimeoutUs(timeout_us: u64) Absolute { +pub fn make_timeout_us(timeout_us: u64) Absolute { return Absolute{ - .us_since_boot = getTimeSinceBoot().us_since_boot + timeout_us, + .us_since_boot = get_time_since_boot().us_since_boot + timeout_us, }; } pub fn reached(time: Absolute) bool { - const now = getTimeSinceBoot(); + const now = get_time_since_boot(); return now.us_since_boot >= time.us_since_boot; } -pub fn sleepMs(time_ms: u32) void { - sleepUs(time_ms * 1000); +pub fn sleep_ms(time_ms: u32) void { + sleep_us(time_ms * 1000); } -pub fn sleepUs(time_us: u64) void { +pub fn sleep_us(time_us: u64) void { const end_time = Absolute{ - .us_since_boot = time_us + getTimeSinceBoot().us_since_boot, + .us_since_boot = time_us + get_time_since_boot().us_since_boot, }; while (!reached(end_time)) {} diff --git a/src/hal/uart.zig b/src/hal/uart.zig index d1ca419..f4c72c5 100644 --- a/src/hal/uart.zig +++ b/src/hal/uart.zig @@ -1,12 +1,17 @@ const std = @import("std"); const microzig = @import("microzig"); +const peripherals = microzig.chip.peripherals; +const UART0 = peripherals.UART0; +const UART1 = peripherals.UART1; + const gpio = @import("gpio.zig"); const clocks = @import("clocks.zig"); const resets = @import("resets.zig"); const time = @import("time.zig"); const assert = std.debug.assert; -const regs = microzig.chip.registers; + +const UartRegs = microzig.chip.types.peripherals.UART0; pub const WordBits = enum { five, @@ -36,40 +41,6 @@ pub const Config = struct { parity: Parity = .none, }; -pub const UartRegs = extern struct { - dr: u32, - rsr: u32, - reserved0: [4]u32, - fr: @typeInfo(@TypeOf(regs.UART0.UARTFR)).Pointer.child, - reserved1: [1]u32, - ilpr: u32, - ibrd: u32, - fbrd: u32, - lcr_h: @typeInfo(@TypeOf(regs.UART0.UARTLCR_H)).Pointer.child, - cr: @typeInfo(@TypeOf(regs.UART0.UARTCR)).Pointer.child, - ifls: u32, - imsc: u32, - ris: u32, - mis: u32, - icr: u32, - dmacr: @typeInfo(@TypeOf(regs.UART0.UARTDMACR)).Pointer.child, - periphid0: u32, - periphid1: u32, - periphid2: u32, - periphid3: u32, - cellid0: u32, - cellid1: u32, - cellid2: u32, - cellid3: u32, - - padding: [4069]u32, -}; - -const uarts = @intToPtr(*volatile [2]UartRegs, regs.UART0.base_address); -comptime { - assert(@sizeOf(UartRegs) == (regs.UART1.base_address - regs.UART0.base_address)); -} - pub const UART = enum { uart0, uart1, @@ -87,8 +58,11 @@ pub const UART = enum { return .{ .context = uart }; } - fn getRegs(uart: UART) *volatile UartRegs { - return &uarts[@enumToInt(uart)]; + fn get_regs(uart: UART) *volatile UartRegs { + return switch (uart) { + .uart0 => UART0, + .uart1 => UART1, + }; } pub fn init(comptime id: u32, comptime config: Config) UART { @@ -102,66 +76,69 @@ pub const UART = enum { uart.reset(); - const uart_regs = uart.getRegs(); + const uart_regs = uart.get_regs(); const peri_freq = config.clock_config.peri.?.output_freq; - uart.setBaudRate(config.baud_rate, peri_freq); - uart.setFormat(config.word_bits, config.stop_bits, config.parity); + uart.set_baudrate(config.baud_rate, peri_freq); + uart.set_format(config.word_bits, config.stop_bits, config.parity); - uart_regs.cr.modify(.{ + uart_regs.UARTCR.modify(.{ .UARTEN = 1, .TXE = 1, .RXE = 1, }); - uart_regs.lcr_h.modify(.{ .FEN = 1 }); + uart_regs.UARTLCR_H.modify(.{ .FEN = 1 }); // - always enable DREQ signals -- no harm if dma isn't listening - uart_regs.dmacr.modify(.{ + uart_regs.UARTDMACR.modify(.{ .TXDMAE = 1, .RXDMAE = 1, }); // TODO comptime assertions - if (config.tx_pin) |tx_pin| gpio.setFunction(tx_pin, .uart); - if (config.rx_pin) |rx_pin| gpio.setFunction(rx_pin, .uart); + if (config.tx_pin) |tx_pin| gpio.set_function(tx_pin, .uart); + if (config.rx_pin) |rx_pin| gpio.set_function(rx_pin, .uart); return uart; } - pub fn isReadable(uart: UART) bool { - return (0 == uart.getRegs().fr.read().RXFE); + pub fn is_readable(uart: UART) bool { + return (0 == uart.get_regs().UARTFR.read().RXFE); } - pub fn isWritable(uart: UART) bool { - return (0 == uart.getRegs().fr.read().TXFF); + pub fn is_writeable(uart: UART) bool { + return (0 == uart.get_regs().UARTFR.read().TXFF); } // TODO: implement tx fifo pub fn write(uart: UART, payload: []const u8) WriteError!usize { - const uart_regs = uart.getRegs(); + const uart_regs = uart.get_regs(); for (payload) |byte| { - while (!uart.isWritable()) {} + while (!uart.is_writeable()) {} - uart_regs.dr = byte; + uart_regs.UARTDR.raw = byte; } return payload.len; } pub fn read(uart: UART, buffer: []u8) ReadError!usize { - const uart_regs = uart.getRegs(); + const uart_regs = uart.get_regs(); for (buffer) |*byte| { - while (!uart.isReadable()) {} - byte.* = @truncate(u8, uart_regs.dr); + while (!uart.is_readable()) {} + + // TODO: error checking + byte.* = uart_regs.UARTDR.read().DATA; } return buffer.len; } - pub fn readWord(uart: UART) u8 { - const uart_regs = uart.getRegs(); - while (!uart.isReadable()) {} + pub fn read_word(uart: UART) u8 { + const uart_regs = uart.get_regs(); + while (!uart.is_readable()) {} - return @truncate(u8, uart_regs.dr); + // TODO: error checking + return uart_regs.UARTDR.read().DATA; } pub fn reset(uart: UART) void { @@ -171,14 +148,14 @@ pub const UART = enum { } } - pub fn setFormat( + pub fn set_format( uart: UART, word_bits: WordBits, stop_bits: StopBits, parity: Parity, ) void { - const uart_regs = uart.getRegs(); - uart_regs.lcr_h.modify(.{ + const uart_regs = uart.get_regs(); + uart_regs.UARTLCR_H.modify(.{ .WLEN = switch (word_bits) { .eight => @as(u2, 0b11), .seven => @as(u2, 0b10), @@ -200,31 +177,31 @@ pub const UART = enum { }); } - fn setBaudRate(uart: UART, baud_rate: u32, peri_freq: u32) void { + fn set_baudrate(uart: UART, baud_rate: u32, peri_freq: u32) void { assert(baud_rate > 0); - const uart_regs = uart.getRegs(); + const uart_regs = uart.get_regs(); const baud_rate_div = (8 * peri_freq / baud_rate); - var baud_ibrd = baud_rate_div >> 7; + var baud_ibrd = @intCast(u16, baud_rate_div >> 7); - const baud_fbrd = if (baud_ibrd == 0) baud_fbrd: { + const baud_fbrd: u6 = if (baud_ibrd == 0) baud_fbrd: { baud_ibrd = 1; break :baud_fbrd 0; } else if (baud_ibrd >= 65535) baud_fbrd: { baud_ibrd = 65535; break :baud_fbrd 0; - } else ((baud_rate_div & 0x7f) + 1) / 2; + } else @intCast(u6, ((@truncate(u7, baud_rate_div)) + 1) / 2); - uart_regs.ibrd = baud_ibrd; - uart_regs.fbrd = baud_fbrd; + uart_regs.UARTIBRD.write(.{ .BAUD_DIVINT = baud_ibrd, .padding = 0 }); + uart_regs.UARTFBRD.write(.{ .BAUD_DIVFRAC = baud_fbrd, .padding = 0 }); // just want a write, don't want to change these values - uart_regs.lcr_h.modify(.{}); + uart_regs.UARTLCR_H.modify(.{}); } }; var uart_logger: ?UART.Writer = null; -pub fn initLogger(uart: UART) void { +pub fn init_logger(uart: UART) void { uart_logger = uart.writer(); uart_logger.?.writeAll("\r\n================ STARTING NEW LOGGER ================\r\n") catch {}; } @@ -242,7 +219,7 @@ pub fn log( }; if (uart_logger) |uart| { - const current_time = time.getTimeSinceBoot(); + const current_time = time.get_time_since_boot(); const seconds = current_time.us_since_boot / std.time.us_per_s; const microseconds = current_time.us_since_boot % std.time.us_per_s; diff --git a/src/hal/util.zig b/src/hal/util.zig index 9d7863c..4f0d71c 100644 --- a/src/hal/util.zig +++ b/src/hal/util.zig @@ -1,18 +1,18 @@ -pub fn xorAlias(ptr: anytype) @TypeOf(ptr) { +pub fn xor_alias(ptr: anytype) @TypeOf(ptr) { const xor_addr = @ptrToInt(ptr) | (1 << 12); return @ptrCast(@TypeOf(ptr), xor_addr); } -pub fn setAlias(ptr: anytype) @TypeOf(ptr) { +pub fn set_alias(ptr: anytype) @TypeOf(ptr) { const set_addr = @ptrToInt(ptr) | (2 << 12); return @ptrCast(@TypeOf(ptr), set_addr); } -pub fn clearAlias(ptr: anytype) @TypeOf(ptr) { +pub fn clear_alias(ptr: anytype) @TypeOf(ptr) { const clear_addr = @ptrToInt(ptr) | (3 << 12); return @ptrCast(@TypeOf(ptr), clear_addr); } -pub inline fn tightLoopContents() void { +pub inline fn tight_loop_contents() void { asm volatile ("" ::: "memory"); } diff --git a/src/rp2040.zig b/src/rp2040.zig deleted file mode 100644 index d3c2e18..0000000 --- a/src/rp2040.zig +++ /dev/null @@ -1,28794 +0,0 @@ -// this file was generated by regz: https://github.com/ZigEmbeddedGroup/regz -// commit: 644b9d6f61ba1e49d90e4f606f82727f3d6581f2 -// -// vendor: Raspberry Pi -// device: RP2040 -// cpu: CM0PLUS - -pub const VectorTable = extern struct { - initial_stack_pointer: u32, - Reset: InterruptVector = unhandled, - NMI: InterruptVector = unhandled, - HardFault: InterruptVector = unhandled, - reserved0: [7]u32 = undefined, - SVCall: InterruptVector = unhandled, - reserved1: [2]u32 = undefined, - PendSV: InterruptVector = unhandled, - SysTick: InterruptVector = unhandled, - TIMER_IRQ_0: InterruptVector = unhandled, - TIMER_IRQ_1: InterruptVector = unhandled, - TIMER_IRQ_2: InterruptVector = unhandled, - TIMER_IRQ_3: InterruptVector = unhandled, - PWM_IRQ_WRAP: InterruptVector = unhandled, - USBCTRL_IRQ: InterruptVector = unhandled, - XIP_IRQ: InterruptVector = unhandled, - PIO0_IRQ_0: InterruptVector = unhandled, - PIO0_IRQ_1: InterruptVector = unhandled, - PIO1_IRQ_0: InterruptVector = unhandled, - PIO1_IRQ_1: InterruptVector = unhandled, - DMA_IRQ_0: InterruptVector = unhandled, - DMA_IRQ_1: InterruptVector = unhandled, - IO_IRQ_BANK0: InterruptVector = unhandled, - IO_IRQ_QSPI: InterruptVector = unhandled, - SIO_IRQ_PROC0: InterruptVector = unhandled, - SIO_IRQ_PROC1: InterruptVector = unhandled, - CLOCKS_IRQ: InterruptVector = unhandled, - SPI0_IRQ: InterruptVector = unhandled, - SPI1_IRQ: InterruptVector = unhandled, - UART0_IRQ: InterruptVector = unhandled, - UART1_IRQ: InterruptVector = unhandled, - ADC_IRQ_FIFO: InterruptVector = unhandled, - I2C0_IRQ: InterruptVector = unhandled, - I2C1_IRQ: InterruptVector = unhandled, - RTC_IRQ: InterruptVector = unhandled, -}; - -pub const registers = struct { - /// System Control Space - pub const SCS = struct { - pub const base_address = 0xe000e000; - - /// System Tick Timer - pub const SysTick = struct { - /// address: 0xe000e010 - /// SysTick Control and Status Register - pub const CTRL = @intToPtr(*volatile Mmio(32, packed struct { - ENABLE: u1, - TICKINT: u1, - CLKSOURCE: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - COUNTFLAG: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - }), base_address + 0x10); - - /// address: 0xe000e014 - /// SysTick Reload Value Register - pub const LOAD = @intToPtr(*volatile Mmio(32, packed struct { - RELOAD: u24, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x14); - - /// address: 0xe000e018 - /// SysTick Current Value Register - pub const VAL = @intToPtr(*volatile Mmio(32, packed struct { - CURRENT: u24, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x18); - - /// address: 0xe000e01c - /// SysTick Calibration Register - pub const CALIB = @intToPtr(*volatile Mmio(32, packed struct { - TENMS: u24, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - SKEW: u1, - NOREF: u1, - }), base_address + 0x1c); - }; - - /// Nested Vectored Interrupt Controller - pub const NVIC = struct { - /// address: 0xe000e100 - /// Interrupt Set Enable Register - pub const ISER = @intToPtr(*volatile Mmio(32, packed struct { - TIMER_IRQ_0: u1, - TIMER_IRQ_1: u1, - TIMER_IRQ_2: u1, - TIMER_IRQ_3: u1, - PWM_IRQ_WRAP: u1, - USBCTRL_IRQ: u1, - XIP_IRQ: u1, - PIO0_IRQ_0: u1, - PIO0_IRQ_1: u1, - PIO1_IRQ_0: u1, - PIO1_IRQ_1: u1, - DMA_IRQ_0: u1, - DMA_IRQ_1: u1, - IO_IRQ_BANK0: u1, - IO_IRQ_QSPI: u1, - SIO_IRQ_PROC0: u1, - SIO_IRQ_PROC1: u1, - CLOCKS_IRQ: u1, - SPI0_IRQ: u1, - SPI1_IRQ: u1, - UART0_IRQ: u1, - UART1_IRQ: u1, - ADC_IRQ_FIFO: u1, - I2C0_IRQ: u1, - I2C1_IRQ: u1, - RTC_IRQ: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - }), base_address + 0x100); - - /// address: 0xe000e180 - /// Interrupt Clear Enable Register - pub const ICER = @intToPtr(*volatile Mmio(32, packed struct { - TIMER_IRQ_0: u1, - TIMER_IRQ_1: u1, - TIMER_IRQ_2: u1, - TIMER_IRQ_3: u1, - PWM_IRQ_WRAP: u1, - USBCTRL_IRQ: u1, - XIP_IRQ: u1, - PIO0_IRQ_0: u1, - PIO0_IRQ_1: u1, - PIO1_IRQ_0: u1, - PIO1_IRQ_1: u1, - DMA_IRQ_0: u1, - DMA_IRQ_1: u1, - IO_IRQ_BANK0: u1, - IO_IRQ_QSPI: u1, - SIO_IRQ_PROC0: u1, - SIO_IRQ_PROC1: u1, - CLOCKS_IRQ: u1, - SPI0_IRQ: u1, - SPI1_IRQ: u1, - UART0_IRQ: u1, - UART1_IRQ: u1, - ADC_IRQ_FIFO: u1, - I2C0_IRQ: u1, - I2C1_IRQ: u1, - RTC_IRQ: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - }), base_address + 0x180); - - /// address: 0xe000e200 - /// Interrupt Set Pending Register - pub const ISPR = @intToPtr(*volatile Mmio(32, packed struct { - TIMER_IRQ_0: u1, - TIMER_IRQ_1: u1, - TIMER_IRQ_2: u1, - TIMER_IRQ_3: u1, - PWM_IRQ_WRAP: u1, - USBCTRL_IRQ: u1, - XIP_IRQ: u1, - PIO0_IRQ_0: u1, - PIO0_IRQ_1: u1, - PIO1_IRQ_0: u1, - PIO1_IRQ_1: u1, - DMA_IRQ_0: u1, - DMA_IRQ_1: u1, - IO_IRQ_BANK0: u1, - IO_IRQ_QSPI: u1, - SIO_IRQ_PROC0: u1, - SIO_IRQ_PROC1: u1, - CLOCKS_IRQ: u1, - SPI0_IRQ: u1, - SPI1_IRQ: u1, - UART0_IRQ: u1, - UART1_IRQ: u1, - ADC_IRQ_FIFO: u1, - I2C0_IRQ: u1, - I2C1_IRQ: u1, - RTC_IRQ: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - }), base_address + 0x200); - - /// address: 0xe000e280 - /// Interrupt Clear Pending Register - pub const ICPR = @intToPtr(*volatile Mmio(32, packed struct { - TIMER_IRQ_0: u1, - TIMER_IRQ_1: u1, - TIMER_IRQ_2: u1, - TIMER_IRQ_3: u1, - PWM_IRQ_WRAP: u1, - USBCTRL_IRQ: u1, - XIP_IRQ: u1, - PIO0_IRQ_0: u1, - PIO0_IRQ_1: u1, - PIO1_IRQ_0: u1, - PIO1_IRQ_1: u1, - DMA_IRQ_0: u1, - DMA_IRQ_1: u1, - IO_IRQ_BANK0: u1, - IO_IRQ_QSPI: u1, - SIO_IRQ_PROC0: u1, - SIO_IRQ_PROC1: u1, - CLOCKS_IRQ: u1, - SPI0_IRQ: u1, - SPI1_IRQ: u1, - UART0_IRQ: u1, - UART1_IRQ: u1, - ADC_IRQ_FIFO: u1, - I2C0_IRQ: u1, - I2C1_IRQ: u1, - RTC_IRQ: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - }), base_address + 0x280); - - /// address: 0xe000e400 - /// Interrupt Priority Register - pub const IP0 = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - TIMER_IRQ_0: u2, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - TIMER_IRQ_1: u2, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - TIMER_IRQ_2: u2, - reserved18: u1 = 0, - reserved19: u1 = 0, - reserved20: u1 = 0, - reserved21: u1 = 0, - reserved22: u1 = 0, - reserved23: u1 = 0, - TIMER_IRQ_3: u2, - }), base_address + 0x400); - - /// address: 0xe000e404 - /// Interrupt Priority Register - pub const IP1 = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - PWM_IRQ_WRAP: u2, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - USBCTRL_IRQ: u2, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - XIP_IRQ: u2, - reserved18: u1 = 0, - reserved19: u1 = 0, - reserved20: u1 = 0, - reserved21: u1 = 0, - reserved22: u1 = 0, - reserved23: u1 = 0, - PIO0_IRQ_0: u2, - }), base_address + 0x404); - - /// address: 0xe000e408 - /// Interrupt Priority Register - pub const IP2 = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - PIO0_IRQ_1: u2, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - PIO1_IRQ_0: u2, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - PIO1_IRQ_1: u2, - reserved18: u1 = 0, - reserved19: u1 = 0, - reserved20: u1 = 0, - reserved21: u1 = 0, - reserved22: u1 = 0, - reserved23: u1 = 0, - DMA_IRQ_0: u2, - }), base_address + 0x408); - - /// address: 0xe000e40c - /// Interrupt Priority Register - pub const IP3 = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - DMA_IRQ_1: u2, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - IO_IRQ_BANK0: u2, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - IO_IRQ_QSPI: u2, - reserved18: u1 = 0, - reserved19: u1 = 0, - reserved20: u1 = 0, - reserved21: u1 = 0, - reserved22: u1 = 0, - reserved23: u1 = 0, - SIO_IRQ_PROC0: u2, - }), base_address + 0x40c); - - /// address: 0xe000e410 - /// Interrupt Priority Register - pub const IP4 = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - SIO_IRQ_PROC1: u2, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - CLOCKS_IRQ: u2, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - SPI0_IRQ: u2, - reserved18: u1 = 0, - reserved19: u1 = 0, - reserved20: u1 = 0, - reserved21: u1 = 0, - reserved22: u1 = 0, - reserved23: u1 = 0, - SPI1_IRQ: u2, - }), base_address + 0x410); - - /// address: 0xe000e414 - /// Interrupt Priority Register - pub const IP5 = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - UART0_IRQ: u2, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - UART1_IRQ: u2, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - ADC_IRQ_FIFO: u2, - reserved18: u1 = 0, - reserved19: u1 = 0, - reserved20: u1 = 0, - reserved21: u1 = 0, - reserved22: u1 = 0, - reserved23: u1 = 0, - I2C0_IRQ: u2, - }), base_address + 0x414); - - /// address: 0xe000e418 - /// Interrupt Priority Register - pub const IP6 = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - I2C1_IRQ: u2, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - RTC_IRQ: u2, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - }), base_address + 0x418); - - /// address: 0xe000e41c - /// Interrupt Priority Register - pub const IP7 = @intToPtr(*volatile u32, base_address + 0x41c); - }; - - /// System Control Block - pub const SCB = struct { - /// address: 0xe000ed00 - pub const CPUID = @intToPtr(*volatile Mmio(32, packed struct { - REVISION: u4, - PARTNO: u12, - ARCHITECTURE: u4, - VARIANT: u4, - IMPLEMENTER: u8, - }), base_address + 0xd00); - - /// address: 0xe000ed04 - /// Interrupt Control and State Register - pub const ICSR = @intToPtr(*volatile Mmio(32, packed struct { - VECTACTIVE: u9, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - VECTPENDING: u9, - reserved3: u1 = 0, - ISRPENDING: u1, - ISRPREEMPT: u1, - reserved4: u1 = 0, - PENDSTCLR: u1, - PENDSTSET: u1, - PENDSVCLR: u1, - PENDSVSET: u1, - reserved5: u1 = 0, - reserved6: u1 = 0, - NMIPENDSET: u1, - }), base_address + 0xd04); - - /// address: 0xe000ed0c - /// Application Interrupt and Reset Control Register - pub const AIRCR = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - VECTCLRACTIVE: u1, - SYSRESETREQ: u1, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - ENDIANESS: u1, - VECTKEY: u16, - }), base_address + 0xd0c); - - /// address: 0xe000ed10 - /// System Control Register - pub const SCR = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - SLEEPONEXIT: u1, - SLEEPDEEP: u1, - reserved1: u1 = 0, - SEVONPEND: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - }), base_address + 0xd10); - - /// address: 0xe000ed14 - /// Configuration Control Register - pub const CCR = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - UNALIGN_TRP: u1, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - STKALIGN: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - }), base_address + 0xd14); - - /// address: 0xe000ed1c - /// System Handlers Priority Registers. [0] is RESERVED - pub const SHP = @intToPtr(*volatile u32, base_address + 0xd1c); - - /// address: 0xe000ed24 - /// System Handler Control and State Register - pub const SHCSR = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - SVCALLPENDED: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - }), base_address + 0xd24); - - /// address: 0xe000ed08 - /// Vector Table Offset Register - pub const VTOR = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - TBLOFF: u24, - }), base_address + 0xd08); - }; - - /// Memory Protection Unit - pub const MPU = struct { - /// address: 0xe000ed90 - /// MPU Type Register - pub const TYPE = @intToPtr(*volatile Mmio(32, packed struct { - SEPARATE: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - DREGION: u8, - IREGION: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0xd90); - - /// address: 0xe000ed94 - /// MPU Control Register - pub const CTRL = @intToPtr(*volatile Mmio(32, packed struct { - ENABLE: u1, - HFNMIENA: u1, - PRIVDEFENA: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - }), base_address + 0xd94); - - /// address: 0xe000ed98 - /// MPU Region RNRber Register - pub const RNR = @intToPtr(*volatile Mmio(32, packed struct { - REGION: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0xd98); - - /// address: 0xe000ed9c - /// MPU Region Base Address Register - pub const RBAR = @intToPtr(*volatile Mmio(32, packed struct { - REGION: u4, - VALID: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - ADDR: u24, - }), base_address + 0xd9c); - - /// address: 0xe000eda0 - /// MPU Region Attribute and Size Register - pub const RASR = @intToPtr(*volatile Mmio(32, packed struct { - ENABLE: u1, - SIZE: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - SRD: u8, - B: u1, - C: u1, - S: u1, - TEX: u3, - reserved2: u1 = 0, - reserved3: u1 = 0, - AP: u3, - reserved4: u1 = 0, - XN: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - }), base_address + 0xda0); - }; - }; - - /// QSPI flash execute-in-place block - pub const XIP_CTRL = struct { - pub const base_address = 0x14000000; - pub const version = "1"; - - /// address: 0x14000000 - /// Cache control - pub const CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// When 1, enable the cache. When the cache is disabled, all XIP accesses\n - /// will go straight to the flash, without querying the cache. When enabled,\n - /// cacheable XIP accesses will query the cache, and the flash will\n - /// not be accessed if the tag matches and the valid bit is set.\n\n - /// If the cache is enabled, cache-as-SRAM accesses have no effect on the\n - /// cache data RAM, and will produce a bus error response. - EN: u1, - /// When 1, writes to any alias other than 0x0 (caching, allocating)\n - /// will produce a bus fault. When 0, these writes are silently ignored.\n - /// In either case, writes to the 0x0 alias will deallocate on tag match,\n - /// as usual. - ERR_BADWRITE: u1, - reserved0: u1 = 0, - /// When 1, the cache memories are powered down. They retain state,\n - /// but can not be accessed. This reduces static power dissipation.\n - /// Writing 1 to this bit forces CTRL_EN to 0, i.e. the cache cannot\n - /// be enabled when powered down.\n - /// Cache-as-SRAM accesses will produce a bus error response when\n - /// the cache is powered down. - POWER_DOWN: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - }), base_address + 0x0); - - /// address: 0x14000004 - /// Cache Flush control - pub const FLUSH = @intToPtr(*volatile MmioInt(32, u1), base_address + 0x4); - - /// address: 0x14000008 - /// Cache Status - pub const STAT = @intToPtr(*volatile Mmio(32, packed struct { - /// Reads as 0 while a cache flush is in progress, and 1 otherwise.\n - /// The cache is flushed whenever the XIP block is reset, and also\n - /// when requested via the FLUSH register. - FLUSH_READY: u1, - /// When 1, indicates the XIP streaming FIFO is completely empty. - FIFO_EMPTY: u1, - /// When 1, indicates the XIP streaming FIFO is completely full.\n - /// The streaming FIFO is 2 entries deep, so the full and empty\n - /// flag allow its level to be ascertained. - FIFO_FULL: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - }), base_address + 0x8); - - /// address: 0x1400000c - /// Cache Hit counter\n - /// A 32 bit saturating counter that increments upon each cache hit,\n - /// i.e. when an XIP access is serviced directly from cached data.\n - /// Write any value to clear. - pub const CTR_HIT = @intToPtr(*volatile u32, base_address + 0xc); - - /// address: 0x14000010 - /// Cache Access counter\n - /// A 32 bit saturating counter that increments upon each XIP access,\n - /// whether the cache is hit or not. This includes noncacheable accesses.\n - /// Write any value to clear. - pub const CTR_ACC = @intToPtr(*volatile u32, base_address + 0x10); - - /// address: 0x14000014 - /// FIFO stream address - pub const STREAM_ADDR = @intToPtr(*volatile MmioInt(32, u30), base_address + 0x14); - - /// address: 0x14000018 - /// FIFO stream control - pub const STREAM_CTR = @intToPtr(*volatile MmioInt(32, u22), base_address + 0x18); - - /// address: 0x1400001c - /// FIFO stream data\n - /// Streamed data is buffered here, for retrieval by the system DMA.\n - /// This FIFO can also be accessed via the XIP_AUX slave, to avoid exposing\n - /// the DMA to bus stalls caused by other XIP traffic. - pub const STREAM_FIFO = @intToPtr(*volatile u32, base_address + 0x1c); - }; - - /// DW_apb_ssi has the following features:\n - /// * APB interface – Allows for easy integration into a DesignWare Synthesizable - /// Components for AMBA 2 implementation.\n - /// * APB3 and APB4 protocol support.\n - /// * Scalable APB data bus width – Supports APB data bus widths of 8, 16, and 32 - /// bits.\n - /// * Serial-master or serial-slave operation – Enables serial communication with - /// serial-master or serial-slave peripheral devices.\n - /// * Programmable Dual/Quad/Octal SPI support in Master Mode.\n - /// * Dual Data Rate (DDR) and Read Data Strobe (RDS) Support - Enables the - /// DW_apb_ssi master to perform operations with the device in DDR and RDS modes - /// when working in Dual/Quad/Octal mode of operation.\n - /// * Data Mask Support - Enables the DW_apb_ssi to selectively update the bytes in - /// the device. This feature is applicable only in enhanced SPI modes.\n - /// * eXecute-In-Place (XIP) support - Enables the DW_apb_ssi master to behave as a - /// memory mapped I/O and fetches the data from the device based on the APB read - /// request. This feature is applicable only in enhanced SPI modes.\n - /// * DMA Controller Interface – Enables the DW_apb_ssi to interface to a DMA - /// controller over the bus using a handshaking interface for transfer requests.\n - /// * Independent masking of interrupts – Master collision, transmit FIFO - /// overflow, transmit FIFO empty, receive FIFO full, receive FIFO underflow, and - /// receive FIFO overflow interrupts can all be masked independently.\n - /// * Multi-master contention detection – Informs the processor of multiple - /// serial-master accesses on the serial bus.\n - /// * Bypass of meta-stability flip-flops for synchronous clocks – When the APB - /// clock (pclk) and the DW_apb_ssi serial clock (ssi_clk) are synchronous, - /// meta-stable flip-flops are not used when transferring control signals across - /// these clock domains.\n - /// * Programmable delay on the sample time of the received serial data bit (rxd); - /// enables programmable control of routing delays resulting in higher serial - /// data-bit rates.\n - /// * Programmable features:\n - /// - Serial interface operation – Choice of Motorola SPI, Texas Instruments - /// Synchronous Serial Protocol or National Semiconductor Microwire.\n - /// - Clock bit-rate – Dynamic control of the serial bit rate of the data - /// transfer; used in only serial-master mode of operation.\n - /// - Data Item size (4 to 32 bits) – Item size of each data transfer under the - /// control of the programmer.\n - /// * Configured features:\n - /// - FIFO depth – 16 words deep. The FIFO width is fixed at 32 bits.\n - /// - 1 slave select output.\n - /// - Hardware slave-select – Dedicated hardware slave-select line.\n - /// - Combined interrupt line - one combined interrupt line from the DW_apb_ssi to - /// the interrupt controller.\n - /// - Interrupt polarity – active high interrupt lines.\n - /// - Serial clock polarity – low serial-clock polarity directly after reset.\n - /// - Serial clock phase – capture on first edge of serial-clock directly after - /// reset. - pub const XIP_SSI = struct { - pub const base_address = 0x18000000; - pub const version = "1"; - - /// address: 0x18000000 - /// Control register 0 - pub const CTRLR0 = @intToPtr(*volatile Mmio(32, packed struct { - /// Data frame size - DFS: u4, - /// Frame format - FRF: u2, - /// Serial clock phase - SCPH: u1, - /// Serial clock polarity - SCPOL: u1, - /// Transfer mode - TMOD: u2, - /// Slave output enable - SLV_OE: u1, - /// Shift register loop (test mode) - SRL: u1, - /// Control frame size\n - /// Value of n -> n+1 clocks per frame. - CFS: u4, - /// Data frame size in 32b transfer mode\n - /// Value of n -> n+1 clocks per frame. - DFS_32: u5, - /// SPI frame format - SPI_FRF: u2, - reserved0: u1 = 0, - /// Slave select toggle enable - SSTE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - }), base_address + 0x0); - - /// address: 0x18000004 - /// Master Control register 1 - pub const CTRLR1 = @intToPtr(*volatile Mmio(32, packed struct { - /// Number of data frames - NDF: u16, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - }), base_address + 0x4); - - /// address: 0x18000008 - /// SSI Enable - pub const SSIENR = @intToPtr(*volatile Mmio(32, packed struct { - /// SSI enable - SSI_EN: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x8); - - /// address: 0x1800000c - /// Microwire Control - pub const MWCR = @intToPtr(*volatile Mmio(32, packed struct { - /// Microwire transfer mode - MWMOD: u1, - /// Microwire control - MDD: u1, - /// Microwire handshaking - MHS: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - }), base_address + 0xc); - - /// address: 0x18000010 - /// Slave enable - pub const SER = @intToPtr(*volatile MmioInt(32, u1), base_address + 0x10); - - /// address: 0x18000014 - /// Baud rate - pub const BAUDR = @intToPtr(*volatile Mmio(32, packed struct { - /// SSI clock divider - SCKDV: u16, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - }), base_address + 0x14); - - /// address: 0x18000018 - /// TX FIFO threshold level - pub const TXFTLR = @intToPtr(*volatile Mmio(32, packed struct { - /// Transmit FIFO threshold - TFT: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x18); - - /// address: 0x1800001c - /// RX FIFO threshold level - pub const RXFTLR = @intToPtr(*volatile Mmio(32, packed struct { - /// Receive FIFO threshold - RFT: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x1c); - - /// address: 0x18000020 - /// TX FIFO level - pub const TXFLR = @intToPtr(*volatile Mmio(32, packed struct { - /// Transmit FIFO level - TFTFL: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x20); - - /// address: 0x18000024 - /// RX FIFO level - pub const RXFLR = @intToPtr(*volatile Mmio(32, packed struct { - /// Receive FIFO level - RXTFL: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x24); - - /// address: 0x18000028 - /// Status register - pub const SR = @intToPtr(*volatile Mmio(32, packed struct { - /// SSI busy flag - BUSY: u1, - /// Transmit FIFO not full - TFNF: u1, - /// Transmit FIFO empty - TFE: u1, - /// Receive FIFO not empty - RFNE: u1, - /// Receive FIFO full - RFF: u1, - /// Transmission error - TXE: u1, - /// Data collision error - DCOL: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - }), base_address + 0x28); - - /// address: 0x1800002c - /// Interrupt mask - pub const IMR = @intToPtr(*volatile Mmio(32, packed struct { - /// Transmit FIFO empty interrupt mask - TXEIM: u1, - /// Transmit FIFO overflow interrupt mask - TXOIM: u1, - /// Receive FIFO underflow interrupt mask - RXUIM: u1, - /// Receive FIFO overflow interrupt mask - RXOIM: u1, - /// Receive FIFO full interrupt mask - RXFIM: u1, - /// Multi-master contention interrupt mask - MSTIM: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - }), base_address + 0x2c); - - /// address: 0x18000030 - /// Interrupt status - pub const ISR = @intToPtr(*volatile Mmio(32, packed struct { - /// Transmit FIFO empty interrupt status - TXEIS: u1, - /// Transmit FIFO overflow interrupt status - TXOIS: u1, - /// Receive FIFO underflow interrupt status - RXUIS: u1, - /// Receive FIFO overflow interrupt status - RXOIS: u1, - /// Receive FIFO full interrupt status - RXFIS: u1, - /// Multi-master contention interrupt status - MSTIS: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - }), base_address + 0x30); - - /// address: 0x18000034 - /// Raw interrupt status - pub const RISR = @intToPtr(*volatile Mmio(32, packed struct { - /// Transmit FIFO empty raw interrupt status - TXEIR: u1, - /// Transmit FIFO overflow raw interrupt status - TXOIR: u1, - /// Receive FIFO underflow raw interrupt status - RXUIR: u1, - /// Receive FIFO overflow raw interrupt status - RXOIR: u1, - /// Receive FIFO full raw interrupt status - RXFIR: u1, - /// Multi-master contention raw interrupt status - MSTIR: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - }), base_address + 0x34); - - /// address: 0x18000038 - /// TX FIFO overflow interrupt clear - pub const TXOICR = @intToPtr(*volatile MmioInt(32, u1), base_address + 0x38); - - /// address: 0x1800003c - /// RX FIFO overflow interrupt clear - pub const RXOICR = @intToPtr(*volatile MmioInt(32, u1), base_address + 0x3c); - - /// address: 0x18000040 - /// RX FIFO underflow interrupt clear - pub const RXUICR = @intToPtr(*volatile MmioInt(32, u1), base_address + 0x40); - - /// address: 0x18000044 - /// Multi-master interrupt clear - pub const MSTICR = @intToPtr(*volatile MmioInt(32, u1), base_address + 0x44); - - /// address: 0x18000048 - /// Interrupt clear - pub const ICR = @intToPtr(*volatile MmioInt(32, u1), base_address + 0x48); - - /// address: 0x1800004c - /// DMA control - pub const DMACR = @intToPtr(*volatile Mmio(32, packed struct { - /// Receive DMA enable - RDMAE: u1, - /// Transmit DMA enable - TDMAE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - }), base_address + 0x4c); - - /// address: 0x18000050 - /// DMA TX data level - pub const DMATDLR = @intToPtr(*volatile Mmio(32, packed struct { - /// Transmit data watermark level - DMATDL: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x50); - - /// address: 0x18000054 - /// DMA RX data level - pub const DMARDLR = @intToPtr(*volatile Mmio(32, packed struct { - /// Receive data watermark level (DMARDLR+1) - DMARDL: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x54); - - /// address: 0x18000058 - /// Identification register - pub const IDR = @intToPtr(*volatile Mmio(32, packed struct { - /// Peripheral dentification code - IDCODE: u32, - }), base_address + 0x58); - - /// address: 0x1800005c - /// Version ID - pub const SSI_VERSION_ID = @intToPtr(*volatile Mmio(32, packed struct { - /// SNPS component version (format X.YY) - SSI_COMP_VERSION: u32, - }), base_address + 0x5c); - - /// address: 0x18000060 - /// Data Register 0 (of 36) - pub const DR0 = @intToPtr(*volatile Mmio(32, packed struct { - /// First data register of 36 - DR: u32, - }), base_address + 0x60); - - /// address: 0x180000f0 - /// RX sample delay - pub const RX_SAMPLE_DLY = @intToPtr(*volatile Mmio(32, packed struct { - /// RXD sample delay (in SCLK cycles) - RSD: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0xf0); - - /// address: 0x180000f4 - /// SPI control - pub const SPI_CTRLR0 = @intToPtr(*volatile Mmio(32, packed struct { - /// Address and instruction transfer format - TRANS_TYPE: u2, - /// Address length (0b-60b in 4b increments) - ADDR_L: u4, - reserved0: u1 = 0, - reserved1: u1 = 0, - /// Instruction length (0/4/8/16b) - INST_L: u2, - reserved2: u1 = 0, - /// Wait cycles between control frame transmit and data reception (in SCLK cycles) - WAIT_CYCLES: u5, - /// SPI DDR transfer enable - SPI_DDR_EN: u1, - /// Instruction DDR transfer enable - INST_DDR_EN: u1, - /// Read data strobe enable - SPI_RXDS_EN: u1, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// SPI Command to send in XIP mode (INST_L = 8-bit) or to append to Address (INST_L - /// = 0-bit) - XIP_CMD: u8, - }), base_address + 0xf4); - - /// address: 0x180000f8 - /// TX drive edge - pub const TXD_DRIVE_EDGE = @intToPtr(*volatile Mmio(32, packed struct { - /// TXD drive edge - TDE: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0xf8); - }; - pub const SYSINFO = struct { - pub const base_address = 0x40000000; - pub const version = "1"; - - /// address: 0x40000000 - /// JEDEC JEP-106 compliant chip identifier. - pub const CHIP_ID = @intToPtr(*volatile Mmio(32, packed struct { - MANUFACTURER: u12, - PART: u16, - REVISION: u4, - }), base_address + 0x0); - - /// address: 0x40000004 - /// Platform register. Allows software to know what environment it is running in. - pub const PLATFORM = @intToPtr(*volatile Mmio(32, packed struct { - FPGA: u1, - ASIC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - }), base_address + 0x4); - - /// address: 0x40000040 - /// Git hash of the chip source. Used to identify chip version. - pub const GITREF_RP2040 = @intToPtr(*volatile u32, base_address + 0x40); - }; - - /// Register block for various chip control signals - pub const SYSCFG = struct { - pub const base_address = 0x40004000; - pub const version = "1"; - - /// address: 0x40004000 - /// Processor core 0 NMI source mask\n - /// Set a bit high to enable NMI from that IRQ - pub const PROC0_NMI_MASK = @intToPtr(*volatile u32, base_address + 0x0); - - /// address: 0x40004004 - /// Processor core 1 NMI source mask\n - /// Set a bit high to enable NMI from that IRQ - pub const PROC1_NMI_MASK = @intToPtr(*volatile u32, base_address + 0x4); - - /// address: 0x40004008 - /// Configuration for processors - pub const PROC_CONFIG = @intToPtr(*volatile Mmio(32, packed struct { - /// Indication that proc0 has halted - PROC0_HALTED: u1, - /// Indication that proc1 has halted - PROC1_HALTED: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - reserved18: u1 = 0, - reserved19: u1 = 0, - reserved20: u1 = 0, - reserved21: u1 = 0, - /// Configure proc0 DAP instance ID.\n - /// Recommend that this is NOT changed until you require debug access in multi-chip - /// environment\n - /// WARNING: do not set to 15 as this is reserved for RescueDP - PROC0_DAP_INSTID: u4, - /// Configure proc1 DAP instance ID.\n - /// Recommend that this is NOT changed until you require debug access in multi-chip - /// environment\n - /// WARNING: do not set to 15 as this is reserved for RescueDP - PROC1_DAP_INSTID: u4, - }), base_address + 0x8); - - /// address: 0x4000400c - /// For each bit, if 1, bypass the input synchronizer between that GPIO\n - /// and the GPIO input register in the SIO. The input synchronizers should\n - /// generally be unbypassed, to avoid injecting metastabilities into processors.\n - /// If you're feeling brave, you can bypass to save two cycles of input\n - /// latency. This register applies to GPIO 0...29. - pub const PROC_IN_SYNC_BYPASS = @intToPtr(*volatile MmioInt(32, u30), base_address + 0xc); - - /// address: 0x40004010 - /// For each bit, if 1, bypass the input synchronizer between that GPIO\n - /// and the GPIO input register in the SIO. The input synchronizers should\n - /// generally be unbypassed, to avoid injecting metastabilities into processors.\n - /// If you're feeling brave, you can bypass to save two cycles of input\n - /// latency. This register applies to GPIO 30...35 (the QSPI IOs). - pub const PROC_IN_SYNC_BYPASS_HI = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x10); - - /// address: 0x40004014 - /// Directly control the SWD debug port of either processor - pub const DBGFORCE = @intToPtr(*volatile Mmio(32, packed struct { - /// Observe the value of processor 0 SWDIO output. - PROC0_SWDO: u1, - /// Directly drive processor 0 SWDIO input, if PROC0_ATTACH is set - PROC0_SWDI: u1, - /// Directly drive processor 0 SWCLK, if PROC0_ATTACH is set - PROC0_SWCLK: u1, - /// Attach processor 0 debug port to syscfg controls, and disconnect it from - /// external SWD pads. - PROC0_ATTACH: u1, - /// Observe the value of processor 1 SWDIO output. - PROC1_SWDO: u1, - /// Directly drive processor 1 SWDIO input, if PROC1_ATTACH is set - PROC1_SWDI: u1, - /// Directly drive processor 1 SWCLK, if PROC1_ATTACH is set - PROC1_SWCLK: u1, - /// Attach processor 1 debug port to syscfg controls, and disconnect it from - /// external SWD pads. - PROC1_ATTACH: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x14); - - /// address: 0x40004018 - /// Control power downs to memories. Set high to power down memories.\n - /// Use with extreme caution - pub const MEMPOWERDOWN = @intToPtr(*volatile Mmio(32, packed struct { - SRAM0: u1, - SRAM1: u1, - SRAM2: u1, - SRAM3: u1, - SRAM4: u1, - SRAM5: u1, - USB: u1, - ROM: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x18); - }; - pub const CLOCKS = struct { - pub const base_address = 0x40008000; - pub const version = "1"; - - /// address: 0x40008000 - /// Clock control, can be changed on-the-fly (except for auxsrc) - pub const CLK_GPOUT0_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - /// Selects the auxiliary clock source, will glitch when switching - AUXSRC: u4, - reserved5: u1 = 0, - /// Asynchronously kills the clock generator - KILL: u1, - /// Starts and stops the clock generator cleanly - ENABLE: u1, - /// Enables duty cycle correction for odd divisors - DC50: u1, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - /// This delays the enable signal by up to 3 cycles of the input clock\n - /// This must be set before the clock is enabled to have any effect - PHASE: u2, - reserved9: u1 = 0, - reserved10: u1 = 0, - /// An edge on this signal shifts the phase of the output by 1 cycle of the input - /// clock\n - /// This can be done at any time - NUDGE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - }), base_address + 0x0); - - /// address: 0x40008004 - /// Clock divisor, can be changed on-the-fly - pub const CLK_GPOUT0_DIV = @intToPtr(*volatile Mmio(32, packed struct { - /// Fractional component of the divisor - FRAC: u8, - /// Integer component of the divisor, 0 -> divide by 2^16 - INT: u24, - }), base_address + 0x4); - - /// address: 0x40008008 - /// Indicates which SRC is currently selected by the glitchless mux (one-hot).\n - /// This slice does not have a glitchless mux (only the AUX_SRC field is present, - /// not SRC) so this register is hardwired to 0x1. - pub const CLK_GPOUT0_SELECTED = @intToPtr(*volatile u32, base_address + 0x8); - - /// address: 0x4000800c - /// Clock control, can be changed on-the-fly (except for auxsrc) - pub const CLK_GPOUT1_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - /// Selects the auxiliary clock source, will glitch when switching - AUXSRC: u4, - reserved5: u1 = 0, - /// Asynchronously kills the clock generator - KILL: u1, - /// Starts and stops the clock generator cleanly - ENABLE: u1, - /// Enables duty cycle correction for odd divisors - DC50: u1, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - /// This delays the enable signal by up to 3 cycles of the input clock\n - /// This must be set before the clock is enabled to have any effect - PHASE: u2, - reserved9: u1 = 0, - reserved10: u1 = 0, - /// An edge on this signal shifts the phase of the output by 1 cycle of the input - /// clock\n - /// This can be done at any time - NUDGE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - }), base_address + 0xc); - - /// address: 0x40008010 - /// Clock divisor, can be changed on-the-fly - pub const CLK_GPOUT1_DIV = @intToPtr(*volatile Mmio(32, packed struct { - /// Fractional component of the divisor - FRAC: u8, - /// Integer component of the divisor, 0 -> divide by 2^16 - INT: u24, - }), base_address + 0x10); - - /// address: 0x40008014 - /// Indicates which SRC is currently selected by the glitchless mux (one-hot).\n - /// This slice does not have a glitchless mux (only the AUX_SRC field is present, - /// not SRC) so this register is hardwired to 0x1. - pub const CLK_GPOUT1_SELECTED = @intToPtr(*volatile u32, base_address + 0x14); - - /// address: 0x40008018 - /// Clock control, can be changed on-the-fly (except for auxsrc) - pub const CLK_GPOUT2_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - /// Selects the auxiliary clock source, will glitch when switching - AUXSRC: u4, - reserved5: u1 = 0, - /// Asynchronously kills the clock generator - KILL: u1, - /// Starts and stops the clock generator cleanly - ENABLE: u1, - /// Enables duty cycle correction for odd divisors - DC50: u1, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - /// This delays the enable signal by up to 3 cycles of the input clock\n - /// This must be set before the clock is enabled to have any effect - PHASE: u2, - reserved9: u1 = 0, - reserved10: u1 = 0, - /// An edge on this signal shifts the phase of the output by 1 cycle of the input - /// clock\n - /// This can be done at any time - NUDGE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - }), base_address + 0x18); - - /// address: 0x4000801c - /// Clock divisor, can be changed on-the-fly - pub const CLK_GPOUT2_DIV = @intToPtr(*volatile Mmio(32, packed struct { - /// Fractional component of the divisor - FRAC: u8, - /// Integer component of the divisor, 0 -> divide by 2^16 - INT: u24, - }), base_address + 0x1c); - - /// address: 0x40008020 - /// Indicates which SRC is currently selected by the glitchless mux (one-hot).\n - /// This slice does not have a glitchless mux (only the AUX_SRC field is present, - /// not SRC) so this register is hardwired to 0x1. - pub const CLK_GPOUT2_SELECTED = @intToPtr(*volatile u32, base_address + 0x20); - - /// address: 0x40008024 - /// Clock control, can be changed on-the-fly (except for auxsrc) - pub const CLK_GPOUT3_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - /// Selects the auxiliary clock source, will glitch when switching - AUXSRC: u4, - reserved5: u1 = 0, - /// Asynchronously kills the clock generator - KILL: u1, - /// Starts and stops the clock generator cleanly - ENABLE: u1, - /// Enables duty cycle correction for odd divisors - DC50: u1, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - /// This delays the enable signal by up to 3 cycles of the input clock\n - /// This must be set before the clock is enabled to have any effect - PHASE: u2, - reserved9: u1 = 0, - reserved10: u1 = 0, - /// An edge on this signal shifts the phase of the output by 1 cycle of the input - /// clock\n - /// This can be done at any time - NUDGE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - }), base_address + 0x24); - - /// address: 0x40008028 - /// Clock divisor, can be changed on-the-fly - pub const CLK_GPOUT3_DIV = @intToPtr(*volatile Mmio(32, packed struct { - /// Fractional component of the divisor - FRAC: u8, - /// Integer component of the divisor, 0 -> divide by 2^16 - INT: u24, - }), base_address + 0x28); - - /// address: 0x4000802c - /// Indicates which SRC is currently selected by the glitchless mux (one-hot).\n - /// This slice does not have a glitchless mux (only the AUX_SRC field is present, - /// not SRC) so this register is hardwired to 0x1. - pub const CLK_GPOUT3_SELECTED = @intToPtr(*volatile u32, base_address + 0x2c); - - /// address: 0x40008030 - /// Clock control, can be changed on-the-fly (except for auxsrc) - pub const CLK_REF_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// Selects the clock source glitchlessly, can be changed on-the-fly - SRC: u2, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - /// Selects the auxiliary clock source, will glitch when switching - AUXSRC: u2, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - }), base_address + 0x30); - - /// address: 0x40008034 - /// Clock divisor, can be changed on-the-fly - pub const CLK_REF_DIV = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// Integer component of the divisor, 0 -> divide by 2^16 - INT: u2, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - }), base_address + 0x34); - - /// address: 0x40008038 - /// Indicates which SRC is currently selected by the glitchless mux (one-hot).\n - /// The glitchless multiplexer does not switch instantaneously (to avoid glitches), - /// so software should poll this register to wait for the switch to complete. This - /// register contains one decoded bit for each of the clock sources enumerated in - /// the CTRL SRC field. At most one of these bits will be set at any time, - /// indicating that clock is currently present at the output of the glitchless mux. - /// Whilst switching is in progress, this register may briefly show all-0s. - pub const CLK_REF_SELECTED = @intToPtr(*volatile u32, base_address + 0x38); - - /// address: 0x4000803c - /// Clock control, can be changed on-the-fly (except for auxsrc) - pub const CLK_SYS_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// Selects the clock source glitchlessly, can be changed on-the-fly - SRC: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - /// Selects the auxiliary clock source, will glitch when switching - AUXSRC: u3, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x3c); - - /// address: 0x40008040 - /// Clock divisor, can be changed on-the-fly - pub const CLK_SYS_DIV = @intToPtr(*volatile Mmio(32, packed struct { - /// Fractional component of the divisor - FRAC: u8, - /// Integer component of the divisor, 0 -> divide by 2^16 - INT: u24, - }), base_address + 0x40); - - /// address: 0x40008044 - /// Indicates which SRC is currently selected by the glitchless mux (one-hot).\n - /// The glitchless multiplexer does not switch instantaneously (to avoid glitches), - /// so software should poll this register to wait for the switch to complete. This - /// register contains one decoded bit for each of the clock sources enumerated in - /// the CTRL SRC field. At most one of these bits will be set at any time, - /// indicating that clock is currently present at the output of the glitchless mux. - /// Whilst switching is in progress, this register may briefly show all-0s. - pub const CLK_SYS_SELECTED = @intToPtr(*volatile u32, base_address + 0x44); - - /// address: 0x40008048 - /// Clock control, can be changed on-the-fly (except for auxsrc) - pub const CLK_PERI_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - /// Selects the auxiliary clock source, will glitch when switching - AUXSRC: u3, - reserved5: u1 = 0, - reserved6: u1 = 0, - /// Asynchronously kills the clock generator - KILL: u1, - /// Starts and stops the clock generator cleanly - ENABLE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x48); - - /// address: 0x40008050 - /// Indicates which SRC is currently selected by the glitchless mux (one-hot).\n - /// This slice does not have a glitchless mux (only the AUX_SRC field is present, - /// not SRC) so this register is hardwired to 0x1. - pub const CLK_PERI_SELECTED = @intToPtr(*volatile u32, base_address + 0x50); - - /// address: 0x40008054 - /// Clock control, can be changed on-the-fly (except for auxsrc) - pub const CLK_USB_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - /// Selects the auxiliary clock source, will glitch when switching - AUXSRC: u3, - reserved5: u1 = 0, - reserved6: u1 = 0, - /// Asynchronously kills the clock generator - KILL: u1, - /// Starts and stops the clock generator cleanly - ENABLE: u1, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - /// This delays the enable signal by up to 3 cycles of the input clock\n - /// This must be set before the clock is enabled to have any effect - PHASE: u2, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// An edge on this signal shifts the phase of the output by 1 cycle of the input - /// clock\n - /// This can be done at any time - NUDGE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - }), base_address + 0x54); - - /// address: 0x40008058 - /// Clock divisor, can be changed on-the-fly - pub const CLK_USB_DIV = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// Integer component of the divisor, 0 -> divide by 2^16 - INT: u2, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - }), base_address + 0x58); - - /// address: 0x4000805c - /// Indicates which SRC is currently selected by the glitchless mux (one-hot).\n - /// This slice does not have a glitchless mux (only the AUX_SRC field is present, - /// not SRC) so this register is hardwired to 0x1. - pub const CLK_USB_SELECTED = @intToPtr(*volatile u32, base_address + 0x5c); - - /// address: 0x40008060 - /// Clock control, can be changed on-the-fly (except for auxsrc) - pub const CLK_ADC_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - /// Selects the auxiliary clock source, will glitch when switching - AUXSRC: u3, - reserved5: u1 = 0, - reserved6: u1 = 0, - /// Asynchronously kills the clock generator - KILL: u1, - /// Starts and stops the clock generator cleanly - ENABLE: u1, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - /// This delays the enable signal by up to 3 cycles of the input clock\n - /// This must be set before the clock is enabled to have any effect - PHASE: u2, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// An edge on this signal shifts the phase of the output by 1 cycle of the input - /// clock\n - /// This can be done at any time - NUDGE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - }), base_address + 0x60); - - /// address: 0x40008064 - /// Clock divisor, can be changed on-the-fly - pub const CLK_ADC_DIV = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// Integer component of the divisor, 0 -> divide by 2^16 - INT: u2, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - }), base_address + 0x64); - - /// address: 0x40008068 - /// Indicates which SRC is currently selected by the glitchless mux (one-hot).\n - /// This slice does not have a glitchless mux (only the AUX_SRC field is present, - /// not SRC) so this register is hardwired to 0x1. - pub const CLK_ADC_SELECTED = @intToPtr(*volatile u32, base_address + 0x68); - - /// address: 0x4000806c - /// Clock control, can be changed on-the-fly (except for auxsrc) - pub const CLK_RTC_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - /// Selects the auxiliary clock source, will glitch when switching - AUXSRC: u3, - reserved5: u1 = 0, - reserved6: u1 = 0, - /// Asynchronously kills the clock generator - KILL: u1, - /// Starts and stops the clock generator cleanly - ENABLE: u1, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - /// This delays the enable signal by up to 3 cycles of the input clock\n - /// This must be set before the clock is enabled to have any effect - PHASE: u2, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// An edge on this signal shifts the phase of the output by 1 cycle of the input - /// clock\n - /// This can be done at any time - NUDGE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - }), base_address + 0x6c); - - /// address: 0x40008070 - /// Clock divisor, can be changed on-the-fly - pub const CLK_RTC_DIV = @intToPtr(*volatile Mmio(32, packed struct { - /// Fractional component of the divisor - FRAC: u8, - /// Integer component of the divisor, 0 -> divide by 2^16 - INT: u24, - }), base_address + 0x70); - - /// address: 0x40008074 - /// Indicates which SRC is currently selected by the glitchless mux (one-hot).\n - /// This slice does not have a glitchless mux (only the AUX_SRC field is present, - /// not SRC) so this register is hardwired to 0x1. - pub const CLK_RTC_SELECTED = @intToPtr(*volatile u32, base_address + 0x74); - - /// address: 0x40008078 - pub const CLK_SYS_RESUS_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// This is expressed as a number of clk_ref cycles\n - /// and must be >= 2x clk_ref_freq/min_clk_tst_freq - TIMEOUT: u8, - /// Enable resus - ENABLE: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - /// Force a resus, for test purposes only - FRCE: u1, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - /// For clearing the resus after the fault that triggered it has been corrected - CLEAR: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - }), base_address + 0x78); - - /// address: 0x4000807c - pub const CLK_SYS_RESUS_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - /// Clock has been resuscitated, correct the error then send ctrl_clear=1 - RESUSSED: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x7c); - - /// address: 0x40008080 - /// Reference clock frequency in kHz - pub const FC0_REF_KHZ = @intToPtr(*volatile MmioInt(32, u20), base_address + 0x80); - - /// address: 0x40008084 - /// Minimum pass frequency in kHz. This is optional. Set to 0 if you are not using - /// the pass/fail flags - pub const FC0_MIN_KHZ = @intToPtr(*volatile MmioInt(32, u25), base_address + 0x84); - - /// address: 0x40008088 - /// Maximum pass frequency in kHz. This is optional. Set to 0x1ffffff if you are not - /// using the pass/fail flags - pub const FC0_MAX_KHZ = @intToPtr(*volatile MmioInt(32, u25), base_address + 0x88); - - /// address: 0x4000808c - /// Delays the start of frequency counting to allow the mux to settle\n - /// Delay is measured in multiples of the reference clock period - pub const FC0_DELAY = @intToPtr(*volatile MmioInt(32, u3), base_address + 0x8c); - - /// address: 0x40008090 - /// The test interval is 0.98us * 2**interval, but let's call it 1us * 2**interval\n - /// The default gives a test interval of 250us - pub const FC0_INTERVAL = @intToPtr(*volatile MmioInt(32, u4), base_address + 0x90); - - /// address: 0x40008094 - /// Clock sent to frequency counter, set to 0 when not required\n - /// Writing to this register initiates the frequency count - pub const FC0_SRC = @intToPtr(*volatile MmioInt(32, u8), base_address + 0x94); - - /// address: 0x40008098 - /// Frequency counter status - pub const FC0_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - /// Test passed - PASS: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - /// Test complete - DONE: u1, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - /// Test running - RUNNING: u1, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - /// Waiting for test clock to start - WAITING: u1, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - /// Test failed - FAIL: u1, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - /// Test clock slower than expected, only valid when status_done=1 - SLOW: u1, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// Test clock faster than expected, only valid when status_done=1 - FAST: u1, - reserved18: u1 = 0, - reserved19: u1 = 0, - reserved20: u1 = 0, - /// Test clock stopped during test - DIED: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - }), base_address + 0x98); - - /// address: 0x4000809c - /// Result of frequency measurement, only valid when status_done=1 - pub const FC0_RESULT = @intToPtr(*volatile Mmio(32, packed struct { - FRAC: u5, - KHZ: u25, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0x9c); - - /// address: 0x400080a0 - /// enable clock in wake mode - pub const WAKE_EN0 = @intToPtr(*volatile Mmio(32, packed struct { - clk_sys_clocks: u1, - clk_adc_adc: u1, - clk_sys_adc: u1, - clk_sys_busctrl: u1, - clk_sys_busfabric: u1, - clk_sys_dma: u1, - clk_sys_i2c0: u1, - clk_sys_i2c1: u1, - clk_sys_io: u1, - clk_sys_jtag: u1, - clk_sys_vreg_and_chip_reset: u1, - clk_sys_pads: u1, - clk_sys_pio0: u1, - clk_sys_pio1: u1, - clk_sys_pll_sys: u1, - clk_sys_pll_usb: u1, - clk_sys_psm: u1, - clk_sys_pwm: u1, - clk_sys_resets: u1, - clk_sys_rom: u1, - clk_sys_rosc: u1, - clk_rtc_rtc: u1, - clk_sys_rtc: u1, - clk_sys_sio: u1, - clk_peri_spi0: u1, - clk_sys_spi0: u1, - clk_peri_spi1: u1, - clk_sys_spi1: u1, - clk_sys_sram0: u1, - clk_sys_sram1: u1, - clk_sys_sram2: u1, - clk_sys_sram3: u1, - }), base_address + 0xa0); - - /// address: 0x400080a4 - /// enable clock in wake mode - pub const WAKE_EN1 = @intToPtr(*volatile Mmio(32, packed struct { - clk_sys_sram4: u1, - clk_sys_sram5: u1, - clk_sys_syscfg: u1, - clk_sys_sysinfo: u1, - clk_sys_tbman: u1, - clk_sys_timer: u1, - clk_peri_uart0: u1, - clk_sys_uart0: u1, - clk_peri_uart1: u1, - clk_sys_uart1: u1, - clk_sys_usbctrl: u1, - clk_usb_usbctrl: u1, - clk_sys_watchdog: u1, - clk_sys_xip: u1, - clk_sys_xosc: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - }), base_address + 0xa4); - - /// address: 0x400080a8 - /// enable clock in sleep mode - pub const SLEEP_EN0 = @intToPtr(*volatile Mmio(32, packed struct { - clk_sys_clocks: u1, - clk_adc_adc: u1, - clk_sys_adc: u1, - clk_sys_busctrl: u1, - clk_sys_busfabric: u1, - clk_sys_dma: u1, - clk_sys_i2c0: u1, - clk_sys_i2c1: u1, - clk_sys_io: u1, - clk_sys_jtag: u1, - clk_sys_vreg_and_chip_reset: u1, - clk_sys_pads: u1, - clk_sys_pio0: u1, - clk_sys_pio1: u1, - clk_sys_pll_sys: u1, - clk_sys_pll_usb: u1, - clk_sys_psm: u1, - clk_sys_pwm: u1, - clk_sys_resets: u1, - clk_sys_rom: u1, - clk_sys_rosc: u1, - clk_rtc_rtc: u1, - clk_sys_rtc: u1, - clk_sys_sio: u1, - clk_peri_spi0: u1, - clk_sys_spi0: u1, - clk_peri_spi1: u1, - clk_sys_spi1: u1, - clk_sys_sram0: u1, - clk_sys_sram1: u1, - clk_sys_sram2: u1, - clk_sys_sram3: u1, - }), base_address + 0xa8); - - /// address: 0x400080ac - /// enable clock in sleep mode - pub const SLEEP_EN1 = @intToPtr(*volatile Mmio(32, packed struct { - clk_sys_sram4: u1, - clk_sys_sram5: u1, - clk_sys_syscfg: u1, - clk_sys_sysinfo: u1, - clk_sys_tbman: u1, - clk_sys_timer: u1, - clk_peri_uart0: u1, - clk_sys_uart0: u1, - clk_peri_uart1: u1, - clk_sys_uart1: u1, - clk_sys_usbctrl: u1, - clk_usb_usbctrl: u1, - clk_sys_watchdog: u1, - clk_sys_xip: u1, - clk_sys_xosc: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - }), base_address + 0xac); - - /// address: 0x400080b0 - /// indicates the state of the clock enable - pub const ENABLED0 = @intToPtr(*volatile Mmio(32, packed struct { - clk_sys_clocks: u1, - clk_adc_adc: u1, - clk_sys_adc: u1, - clk_sys_busctrl: u1, - clk_sys_busfabric: u1, - clk_sys_dma: u1, - clk_sys_i2c0: u1, - clk_sys_i2c1: u1, - clk_sys_io: u1, - clk_sys_jtag: u1, - clk_sys_vreg_and_chip_reset: u1, - clk_sys_pads: u1, - clk_sys_pio0: u1, - clk_sys_pio1: u1, - clk_sys_pll_sys: u1, - clk_sys_pll_usb: u1, - clk_sys_psm: u1, - clk_sys_pwm: u1, - clk_sys_resets: u1, - clk_sys_rom: u1, - clk_sys_rosc: u1, - clk_rtc_rtc: u1, - clk_sys_rtc: u1, - clk_sys_sio: u1, - clk_peri_spi0: u1, - clk_sys_spi0: u1, - clk_peri_spi1: u1, - clk_sys_spi1: u1, - clk_sys_sram0: u1, - clk_sys_sram1: u1, - clk_sys_sram2: u1, - clk_sys_sram3: u1, - }), base_address + 0xb0); - - /// address: 0x400080b4 - /// indicates the state of the clock enable - pub const ENABLED1 = @intToPtr(*volatile Mmio(32, packed struct { - clk_sys_sram4: u1, - clk_sys_sram5: u1, - clk_sys_syscfg: u1, - clk_sys_sysinfo: u1, - clk_sys_tbman: u1, - clk_sys_timer: u1, - clk_peri_uart0: u1, - clk_sys_uart0: u1, - clk_peri_uart1: u1, - clk_sys_uart1: u1, - clk_sys_usbctrl: u1, - clk_usb_usbctrl: u1, - clk_sys_watchdog: u1, - clk_sys_xip: u1, - clk_sys_xosc: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - }), base_address + 0xb4); - - /// address: 0x400080b8 - /// Raw Interrupts - pub const INTR = @intToPtr(*volatile Mmio(32, packed struct { - CLK_SYS_RESUS: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0xb8); - - /// address: 0x400080bc - /// Interrupt Enable - pub const INTE = @intToPtr(*volatile Mmio(32, packed struct { - CLK_SYS_RESUS: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0xbc); - - /// address: 0x400080c0 - /// Interrupt Force - pub const INTF = @intToPtr(*volatile Mmio(32, packed struct { - CLK_SYS_RESUS: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0xc0); - - /// address: 0x400080c4 - /// Interrupt status after masking & forcing - pub const INTS = @intToPtr(*volatile Mmio(32, packed struct { - CLK_SYS_RESUS: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0xc4); - }; - pub const RESETS = struct { - pub const base_address = 0x4000c000; - pub const version = "1"; - - /// address: 0x4000c000 - /// Reset control. If a bit is set it means the peripheral is in reset. 0 means the - /// peripheral's reset is deasserted. - pub const RESET = @intToPtr(*volatile Mmio(32, packed struct { - adc: u1, - busctrl: u1, - dma: u1, - i2c0: u1, - i2c1: u1, - io_bank0: u1, - io_qspi: u1, - jtag: u1, - pads_bank0: u1, - pads_qspi: u1, - pio0: u1, - pio1: u1, - pll_sys: u1, - pll_usb: u1, - pwm: u1, - rtc: u1, - spi0: u1, - spi1: u1, - syscfg: u1, - sysinfo: u1, - tbman: u1, - timer: u1, - uart0: u1, - uart1: u1, - usbctrl: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - }), base_address + 0x0); - - /// address: 0x4000c004 - /// Watchdog select. If a bit is set then the watchdog will reset this peripheral - /// when the watchdog fires. - pub const WDSEL = @intToPtr(*volatile Mmio(32, packed struct { - adc: u1, - busctrl: u1, - dma: u1, - i2c0: u1, - i2c1: u1, - io_bank0: u1, - io_qspi: u1, - jtag: u1, - pads_bank0: u1, - pads_qspi: u1, - pio0: u1, - pio1: u1, - pll_sys: u1, - pll_usb: u1, - pwm: u1, - rtc: u1, - spi0: u1, - spi1: u1, - syscfg: u1, - sysinfo: u1, - tbman: u1, - timer: u1, - uart0: u1, - uart1: u1, - usbctrl: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - }), base_address + 0x4); - - /// address: 0x4000c008 - /// Reset done. If a bit is set then a reset done signal has been returned by the - /// peripheral. This indicates that the peripheral's registers are ready to be - /// accessed. - pub const RESET_DONE = @intToPtr(*volatile Mmio(32, packed struct { - adc: u1, - busctrl: u1, - dma: u1, - i2c0: u1, - i2c1: u1, - io_bank0: u1, - io_qspi: u1, - jtag: u1, - pads_bank0: u1, - pads_qspi: u1, - pio0: u1, - pio1: u1, - pll_sys: u1, - pll_usb: u1, - pwm: u1, - rtc: u1, - spi0: u1, - spi1: u1, - syscfg: u1, - sysinfo: u1, - tbman: u1, - timer: u1, - uart0: u1, - uart1: u1, - usbctrl: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - }), base_address + 0x8); - }; - pub const PSM = struct { - pub const base_address = 0x40010000; - pub const version = "1"; - - /// address: 0x40010000 - /// Force block out of reset (i.e. power it on) - pub const FRCE_ON = @intToPtr(*volatile Mmio(32, packed struct { - rosc: u1, - xosc: u1, - clocks: u1, - resets: u1, - busfabric: u1, - rom: u1, - sram0: u1, - sram1: u1, - sram2: u1, - sram3: u1, - sram4: u1, - sram5: u1, - xip: u1, - vreg_and_chip_reset: u1, - sio: u1, - proc0: u1, - proc1: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - }), base_address + 0x0); - - /// address: 0x40010004 - /// Force into reset (i.e. power it off) - pub const FRCE_OFF = @intToPtr(*volatile Mmio(32, packed struct { - rosc: u1, - xosc: u1, - clocks: u1, - resets: u1, - busfabric: u1, - rom: u1, - sram0: u1, - sram1: u1, - sram2: u1, - sram3: u1, - sram4: u1, - sram5: u1, - xip: u1, - vreg_and_chip_reset: u1, - sio: u1, - proc0: u1, - proc1: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - }), base_address + 0x4); - - /// address: 0x40010008 - /// Set to 1 if this peripheral should be reset when the watchdog fires. - pub const WDSEL = @intToPtr(*volatile Mmio(32, packed struct { - rosc: u1, - xosc: u1, - clocks: u1, - resets: u1, - busfabric: u1, - rom: u1, - sram0: u1, - sram1: u1, - sram2: u1, - sram3: u1, - sram4: u1, - sram5: u1, - xip: u1, - vreg_and_chip_reset: u1, - sio: u1, - proc0: u1, - proc1: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - }), base_address + 0x8); - - /// address: 0x4001000c - /// Indicates the peripheral's registers are ready to access. - pub const DONE = @intToPtr(*volatile Mmio(32, packed struct { - rosc: u1, - xosc: u1, - clocks: u1, - resets: u1, - busfabric: u1, - rom: u1, - sram0: u1, - sram1: u1, - sram2: u1, - sram3: u1, - sram4: u1, - sram5: u1, - xip: u1, - vreg_and_chip_reset: u1, - sio: u1, - proc0: u1, - proc1: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - }), base_address + 0xc); - }; - pub const IO_BANK0 = struct { - pub const base_address = 0x40014000; - pub const version = "1"; - - /// address: 0x40014000 - /// GPIO status - pub const GPIO0_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x0); - - /// address: 0x40014004 - /// GPIO control including function select and overrides. - pub const GPIO0_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0x4); - - /// address: 0x40014008 - /// GPIO status - pub const GPIO1_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x8); - - /// address: 0x4001400c - /// GPIO control including function select and overrides. - pub const GPIO1_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0xc); - - /// address: 0x40014010 - /// GPIO status - pub const GPIO2_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x10); - - /// address: 0x40014014 - /// GPIO control including function select and overrides. - pub const GPIO2_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0x14); - - /// address: 0x40014018 - /// GPIO status - pub const GPIO3_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x18); - - /// address: 0x4001401c - /// GPIO control including function select and overrides. - pub const GPIO3_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0x1c); - - /// address: 0x40014020 - /// GPIO status - pub const GPIO4_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x20); - - /// address: 0x40014024 - /// GPIO control including function select and overrides. - pub const GPIO4_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0x24); - - /// address: 0x40014028 - /// GPIO status - pub const GPIO5_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x28); - - /// address: 0x4001402c - /// GPIO control including function select and overrides. - pub const GPIO5_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0x2c); - - /// address: 0x40014030 - /// GPIO status - pub const GPIO6_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x30); - - /// address: 0x40014034 - /// GPIO control including function select and overrides. - pub const GPIO6_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0x34); - - /// address: 0x40014038 - /// GPIO status - pub const GPIO7_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x38); - - /// address: 0x4001403c - /// GPIO control including function select and overrides. - pub const GPIO7_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0x3c); - - /// address: 0x40014040 - /// GPIO status - pub const GPIO8_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x40); - - /// address: 0x40014044 - /// GPIO control including function select and overrides. - pub const GPIO8_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0x44); - - /// address: 0x40014048 - /// GPIO status - pub const GPIO9_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x48); - - /// address: 0x4001404c - /// GPIO control including function select and overrides. - pub const GPIO9_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0x4c); - - /// address: 0x40014050 - /// GPIO status - pub const GPIO10_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x50); - - /// address: 0x40014054 - /// GPIO control including function select and overrides. - pub const GPIO10_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0x54); - - /// address: 0x40014058 - /// GPIO status - pub const GPIO11_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x58); - - /// address: 0x4001405c - /// GPIO control including function select and overrides. - pub const GPIO11_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0x5c); - - /// address: 0x40014060 - /// GPIO status - pub const GPIO12_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x60); - - /// address: 0x40014064 - /// GPIO control including function select and overrides. - pub const GPIO12_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0x64); - - /// address: 0x40014068 - /// GPIO status - pub const GPIO13_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x68); - - /// address: 0x4001406c - /// GPIO control including function select and overrides. - pub const GPIO13_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0x6c); - - /// address: 0x40014070 - /// GPIO status - pub const GPIO14_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x70); - - /// address: 0x40014074 - /// GPIO control including function select and overrides. - pub const GPIO14_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0x74); - - /// address: 0x40014078 - /// GPIO status - pub const GPIO15_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x78); - - /// address: 0x4001407c - /// GPIO control including function select and overrides. - pub const GPIO15_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0x7c); - - /// address: 0x40014080 - /// GPIO status - pub const GPIO16_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x80); - - /// address: 0x40014084 - /// GPIO control including function select and overrides. - pub const GPIO16_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0x84); - - /// address: 0x40014088 - /// GPIO status - pub const GPIO17_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x88); - - /// address: 0x4001408c - /// GPIO control including function select and overrides. - pub const GPIO17_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0x8c); - - /// address: 0x40014090 - /// GPIO status - pub const GPIO18_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x90); - - /// address: 0x40014094 - /// GPIO control including function select and overrides. - pub const GPIO18_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0x94); - - /// address: 0x40014098 - /// GPIO status - pub const GPIO19_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x98); - - /// address: 0x4001409c - /// GPIO control including function select and overrides. - pub const GPIO19_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0x9c); - - /// address: 0x400140a0 - /// GPIO status - pub const GPIO20_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0xa0); - - /// address: 0x400140a4 - /// GPIO control including function select and overrides. - pub const GPIO20_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0xa4); - - /// address: 0x400140a8 - /// GPIO status - pub const GPIO21_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0xa8); - - /// address: 0x400140ac - /// GPIO control including function select and overrides. - pub const GPIO21_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0xac); - - /// address: 0x400140b0 - /// GPIO status - pub const GPIO22_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0xb0); - - /// address: 0x400140b4 - /// GPIO control including function select and overrides. - pub const GPIO22_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0xb4); - - /// address: 0x400140b8 - /// GPIO status - pub const GPIO23_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0xb8); - - /// address: 0x400140bc - /// GPIO control including function select and overrides. - pub const GPIO23_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0xbc); - - /// address: 0x400140c0 - /// GPIO status - pub const GPIO24_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0xc0); - - /// address: 0x400140c4 - /// GPIO control including function select and overrides. - pub const GPIO24_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0xc4); - - /// address: 0x400140c8 - /// GPIO status - pub const GPIO25_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0xc8); - - /// address: 0x400140cc - /// GPIO control including function select and overrides. - pub const GPIO25_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0xcc); - - /// address: 0x400140d0 - /// GPIO status - pub const GPIO26_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0xd0); - - /// address: 0x400140d4 - /// GPIO control including function select and overrides. - pub const GPIO26_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0xd4); - - /// address: 0x400140d8 - /// GPIO status - pub const GPIO27_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0xd8); - - /// address: 0x400140dc - /// GPIO control including function select and overrides. - pub const GPIO27_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0xdc); - - /// address: 0x400140e0 - /// GPIO status - pub const GPIO28_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0xe0); - - /// address: 0x400140e4 - /// GPIO control including function select and overrides. - pub const GPIO28_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0xe4); - - /// address: 0x400140e8 - /// GPIO status - pub const GPIO29_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0xe8); - - /// address: 0x400140ec - /// GPIO control including function select and overrides. - pub const GPIO29_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0xec); - - /// address: 0x400140f0 - /// Raw Interrupts - pub const INTR0 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO0_LEVEL_LOW: u1, - GPIO0_LEVEL_HIGH: u1, - GPIO0_EDGE_LOW: u1, - GPIO0_EDGE_HIGH: u1, - GPIO1_LEVEL_LOW: u1, - GPIO1_LEVEL_HIGH: u1, - GPIO1_EDGE_LOW: u1, - GPIO1_EDGE_HIGH: u1, - GPIO2_LEVEL_LOW: u1, - GPIO2_LEVEL_HIGH: u1, - GPIO2_EDGE_LOW: u1, - GPIO2_EDGE_HIGH: u1, - GPIO3_LEVEL_LOW: u1, - GPIO3_LEVEL_HIGH: u1, - GPIO3_EDGE_LOW: u1, - GPIO3_EDGE_HIGH: u1, - GPIO4_LEVEL_LOW: u1, - GPIO4_LEVEL_HIGH: u1, - GPIO4_EDGE_LOW: u1, - GPIO4_EDGE_HIGH: u1, - GPIO5_LEVEL_LOW: u1, - GPIO5_LEVEL_HIGH: u1, - GPIO5_EDGE_LOW: u1, - GPIO5_EDGE_HIGH: u1, - GPIO6_LEVEL_LOW: u1, - GPIO6_LEVEL_HIGH: u1, - GPIO6_EDGE_LOW: u1, - GPIO6_EDGE_HIGH: u1, - GPIO7_LEVEL_LOW: u1, - GPIO7_LEVEL_HIGH: u1, - GPIO7_EDGE_LOW: u1, - GPIO7_EDGE_HIGH: u1, - }), base_address + 0xf0); - - /// address: 0x400140f4 - /// Raw Interrupts - pub const INTR1 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO8_LEVEL_LOW: u1, - GPIO8_LEVEL_HIGH: u1, - GPIO8_EDGE_LOW: u1, - GPIO8_EDGE_HIGH: u1, - GPIO9_LEVEL_LOW: u1, - GPIO9_LEVEL_HIGH: u1, - GPIO9_EDGE_LOW: u1, - GPIO9_EDGE_HIGH: u1, - GPIO10_LEVEL_LOW: u1, - GPIO10_LEVEL_HIGH: u1, - GPIO10_EDGE_LOW: u1, - GPIO10_EDGE_HIGH: u1, - GPIO11_LEVEL_LOW: u1, - GPIO11_LEVEL_HIGH: u1, - GPIO11_EDGE_LOW: u1, - GPIO11_EDGE_HIGH: u1, - GPIO12_LEVEL_LOW: u1, - GPIO12_LEVEL_HIGH: u1, - GPIO12_EDGE_LOW: u1, - GPIO12_EDGE_HIGH: u1, - GPIO13_LEVEL_LOW: u1, - GPIO13_LEVEL_HIGH: u1, - GPIO13_EDGE_LOW: u1, - GPIO13_EDGE_HIGH: u1, - GPIO14_LEVEL_LOW: u1, - GPIO14_LEVEL_HIGH: u1, - GPIO14_EDGE_LOW: u1, - GPIO14_EDGE_HIGH: u1, - GPIO15_LEVEL_LOW: u1, - GPIO15_LEVEL_HIGH: u1, - GPIO15_EDGE_LOW: u1, - GPIO15_EDGE_HIGH: u1, - }), base_address + 0xf4); - - /// address: 0x400140f8 - /// Raw Interrupts - pub const INTR2 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO16_LEVEL_LOW: u1, - GPIO16_LEVEL_HIGH: u1, - GPIO16_EDGE_LOW: u1, - GPIO16_EDGE_HIGH: u1, - GPIO17_LEVEL_LOW: u1, - GPIO17_LEVEL_HIGH: u1, - GPIO17_EDGE_LOW: u1, - GPIO17_EDGE_HIGH: u1, - GPIO18_LEVEL_LOW: u1, - GPIO18_LEVEL_HIGH: u1, - GPIO18_EDGE_LOW: u1, - GPIO18_EDGE_HIGH: u1, - GPIO19_LEVEL_LOW: u1, - GPIO19_LEVEL_HIGH: u1, - GPIO19_EDGE_LOW: u1, - GPIO19_EDGE_HIGH: u1, - GPIO20_LEVEL_LOW: u1, - GPIO20_LEVEL_HIGH: u1, - GPIO20_EDGE_LOW: u1, - GPIO20_EDGE_HIGH: u1, - GPIO21_LEVEL_LOW: u1, - GPIO21_LEVEL_HIGH: u1, - GPIO21_EDGE_LOW: u1, - GPIO21_EDGE_HIGH: u1, - GPIO22_LEVEL_LOW: u1, - GPIO22_LEVEL_HIGH: u1, - GPIO22_EDGE_LOW: u1, - GPIO22_EDGE_HIGH: u1, - GPIO23_LEVEL_LOW: u1, - GPIO23_LEVEL_HIGH: u1, - GPIO23_EDGE_LOW: u1, - GPIO23_EDGE_HIGH: u1, - }), base_address + 0xf8); - - /// address: 0x400140fc - /// Raw Interrupts - pub const INTR3 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO24_LEVEL_LOW: u1, - GPIO24_LEVEL_HIGH: u1, - GPIO24_EDGE_LOW: u1, - GPIO24_EDGE_HIGH: u1, - GPIO25_LEVEL_LOW: u1, - GPIO25_LEVEL_HIGH: u1, - GPIO25_EDGE_LOW: u1, - GPIO25_EDGE_HIGH: u1, - GPIO26_LEVEL_LOW: u1, - GPIO26_LEVEL_HIGH: u1, - GPIO26_EDGE_LOW: u1, - GPIO26_EDGE_HIGH: u1, - GPIO27_LEVEL_LOW: u1, - GPIO27_LEVEL_HIGH: u1, - GPIO27_EDGE_LOW: u1, - GPIO27_EDGE_HIGH: u1, - GPIO28_LEVEL_LOW: u1, - GPIO28_LEVEL_HIGH: u1, - GPIO28_EDGE_LOW: u1, - GPIO28_EDGE_HIGH: u1, - GPIO29_LEVEL_LOW: u1, - GPIO29_LEVEL_HIGH: u1, - GPIO29_EDGE_LOW: u1, - GPIO29_EDGE_HIGH: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0xfc); - - /// address: 0x40014100 - /// Interrupt Enable for proc0 - pub const PROC0_INTE0 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO0_LEVEL_LOW: u1, - GPIO0_LEVEL_HIGH: u1, - GPIO0_EDGE_LOW: u1, - GPIO0_EDGE_HIGH: u1, - GPIO1_LEVEL_LOW: u1, - GPIO1_LEVEL_HIGH: u1, - GPIO1_EDGE_LOW: u1, - GPIO1_EDGE_HIGH: u1, - GPIO2_LEVEL_LOW: u1, - GPIO2_LEVEL_HIGH: u1, - GPIO2_EDGE_LOW: u1, - GPIO2_EDGE_HIGH: u1, - GPIO3_LEVEL_LOW: u1, - GPIO3_LEVEL_HIGH: u1, - GPIO3_EDGE_LOW: u1, - GPIO3_EDGE_HIGH: u1, - GPIO4_LEVEL_LOW: u1, - GPIO4_LEVEL_HIGH: u1, - GPIO4_EDGE_LOW: u1, - GPIO4_EDGE_HIGH: u1, - GPIO5_LEVEL_LOW: u1, - GPIO5_LEVEL_HIGH: u1, - GPIO5_EDGE_LOW: u1, - GPIO5_EDGE_HIGH: u1, - GPIO6_LEVEL_LOW: u1, - GPIO6_LEVEL_HIGH: u1, - GPIO6_EDGE_LOW: u1, - GPIO6_EDGE_HIGH: u1, - GPIO7_LEVEL_LOW: u1, - GPIO7_LEVEL_HIGH: u1, - GPIO7_EDGE_LOW: u1, - GPIO7_EDGE_HIGH: u1, - }), base_address + 0x100); - - /// address: 0x40014104 - /// Interrupt Enable for proc0 - pub const PROC0_INTE1 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO8_LEVEL_LOW: u1, - GPIO8_LEVEL_HIGH: u1, - GPIO8_EDGE_LOW: u1, - GPIO8_EDGE_HIGH: u1, - GPIO9_LEVEL_LOW: u1, - GPIO9_LEVEL_HIGH: u1, - GPIO9_EDGE_LOW: u1, - GPIO9_EDGE_HIGH: u1, - GPIO10_LEVEL_LOW: u1, - GPIO10_LEVEL_HIGH: u1, - GPIO10_EDGE_LOW: u1, - GPIO10_EDGE_HIGH: u1, - GPIO11_LEVEL_LOW: u1, - GPIO11_LEVEL_HIGH: u1, - GPIO11_EDGE_LOW: u1, - GPIO11_EDGE_HIGH: u1, - GPIO12_LEVEL_LOW: u1, - GPIO12_LEVEL_HIGH: u1, - GPIO12_EDGE_LOW: u1, - GPIO12_EDGE_HIGH: u1, - GPIO13_LEVEL_LOW: u1, - GPIO13_LEVEL_HIGH: u1, - GPIO13_EDGE_LOW: u1, - GPIO13_EDGE_HIGH: u1, - GPIO14_LEVEL_LOW: u1, - GPIO14_LEVEL_HIGH: u1, - GPIO14_EDGE_LOW: u1, - GPIO14_EDGE_HIGH: u1, - GPIO15_LEVEL_LOW: u1, - GPIO15_LEVEL_HIGH: u1, - GPIO15_EDGE_LOW: u1, - GPIO15_EDGE_HIGH: u1, - }), base_address + 0x104); - - /// address: 0x40014108 - /// Interrupt Enable for proc0 - pub const PROC0_INTE2 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO16_LEVEL_LOW: u1, - GPIO16_LEVEL_HIGH: u1, - GPIO16_EDGE_LOW: u1, - GPIO16_EDGE_HIGH: u1, - GPIO17_LEVEL_LOW: u1, - GPIO17_LEVEL_HIGH: u1, - GPIO17_EDGE_LOW: u1, - GPIO17_EDGE_HIGH: u1, - GPIO18_LEVEL_LOW: u1, - GPIO18_LEVEL_HIGH: u1, - GPIO18_EDGE_LOW: u1, - GPIO18_EDGE_HIGH: u1, - GPIO19_LEVEL_LOW: u1, - GPIO19_LEVEL_HIGH: u1, - GPIO19_EDGE_LOW: u1, - GPIO19_EDGE_HIGH: u1, - GPIO20_LEVEL_LOW: u1, - GPIO20_LEVEL_HIGH: u1, - GPIO20_EDGE_LOW: u1, - GPIO20_EDGE_HIGH: u1, - GPIO21_LEVEL_LOW: u1, - GPIO21_LEVEL_HIGH: u1, - GPIO21_EDGE_LOW: u1, - GPIO21_EDGE_HIGH: u1, - GPIO22_LEVEL_LOW: u1, - GPIO22_LEVEL_HIGH: u1, - GPIO22_EDGE_LOW: u1, - GPIO22_EDGE_HIGH: u1, - GPIO23_LEVEL_LOW: u1, - GPIO23_LEVEL_HIGH: u1, - GPIO23_EDGE_LOW: u1, - GPIO23_EDGE_HIGH: u1, - }), base_address + 0x108); - - /// address: 0x4001410c - /// Interrupt Enable for proc0 - pub const PROC0_INTE3 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO24_LEVEL_LOW: u1, - GPIO24_LEVEL_HIGH: u1, - GPIO24_EDGE_LOW: u1, - GPIO24_EDGE_HIGH: u1, - GPIO25_LEVEL_LOW: u1, - GPIO25_LEVEL_HIGH: u1, - GPIO25_EDGE_LOW: u1, - GPIO25_EDGE_HIGH: u1, - GPIO26_LEVEL_LOW: u1, - GPIO26_LEVEL_HIGH: u1, - GPIO26_EDGE_LOW: u1, - GPIO26_EDGE_HIGH: u1, - GPIO27_LEVEL_LOW: u1, - GPIO27_LEVEL_HIGH: u1, - GPIO27_EDGE_LOW: u1, - GPIO27_EDGE_HIGH: u1, - GPIO28_LEVEL_LOW: u1, - GPIO28_LEVEL_HIGH: u1, - GPIO28_EDGE_LOW: u1, - GPIO28_EDGE_HIGH: u1, - GPIO29_LEVEL_LOW: u1, - GPIO29_LEVEL_HIGH: u1, - GPIO29_EDGE_LOW: u1, - GPIO29_EDGE_HIGH: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x10c); - - /// address: 0x40014110 - /// Interrupt Force for proc0 - pub const PROC0_INTF0 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO0_LEVEL_LOW: u1, - GPIO0_LEVEL_HIGH: u1, - GPIO0_EDGE_LOW: u1, - GPIO0_EDGE_HIGH: u1, - GPIO1_LEVEL_LOW: u1, - GPIO1_LEVEL_HIGH: u1, - GPIO1_EDGE_LOW: u1, - GPIO1_EDGE_HIGH: u1, - GPIO2_LEVEL_LOW: u1, - GPIO2_LEVEL_HIGH: u1, - GPIO2_EDGE_LOW: u1, - GPIO2_EDGE_HIGH: u1, - GPIO3_LEVEL_LOW: u1, - GPIO3_LEVEL_HIGH: u1, - GPIO3_EDGE_LOW: u1, - GPIO3_EDGE_HIGH: u1, - GPIO4_LEVEL_LOW: u1, - GPIO4_LEVEL_HIGH: u1, - GPIO4_EDGE_LOW: u1, - GPIO4_EDGE_HIGH: u1, - GPIO5_LEVEL_LOW: u1, - GPIO5_LEVEL_HIGH: u1, - GPIO5_EDGE_LOW: u1, - GPIO5_EDGE_HIGH: u1, - GPIO6_LEVEL_LOW: u1, - GPIO6_LEVEL_HIGH: u1, - GPIO6_EDGE_LOW: u1, - GPIO6_EDGE_HIGH: u1, - GPIO7_LEVEL_LOW: u1, - GPIO7_LEVEL_HIGH: u1, - GPIO7_EDGE_LOW: u1, - GPIO7_EDGE_HIGH: u1, - }), base_address + 0x110); - - /// address: 0x40014114 - /// Interrupt Force for proc0 - pub const PROC0_INTF1 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO8_LEVEL_LOW: u1, - GPIO8_LEVEL_HIGH: u1, - GPIO8_EDGE_LOW: u1, - GPIO8_EDGE_HIGH: u1, - GPIO9_LEVEL_LOW: u1, - GPIO9_LEVEL_HIGH: u1, - GPIO9_EDGE_LOW: u1, - GPIO9_EDGE_HIGH: u1, - GPIO10_LEVEL_LOW: u1, - GPIO10_LEVEL_HIGH: u1, - GPIO10_EDGE_LOW: u1, - GPIO10_EDGE_HIGH: u1, - GPIO11_LEVEL_LOW: u1, - GPIO11_LEVEL_HIGH: u1, - GPIO11_EDGE_LOW: u1, - GPIO11_EDGE_HIGH: u1, - GPIO12_LEVEL_LOW: u1, - GPIO12_LEVEL_HIGH: u1, - GPIO12_EDGE_LOW: u1, - GPIO12_EDGE_HIGH: u1, - GPIO13_LEVEL_LOW: u1, - GPIO13_LEVEL_HIGH: u1, - GPIO13_EDGE_LOW: u1, - GPIO13_EDGE_HIGH: u1, - GPIO14_LEVEL_LOW: u1, - GPIO14_LEVEL_HIGH: u1, - GPIO14_EDGE_LOW: u1, - GPIO14_EDGE_HIGH: u1, - GPIO15_LEVEL_LOW: u1, - GPIO15_LEVEL_HIGH: u1, - GPIO15_EDGE_LOW: u1, - GPIO15_EDGE_HIGH: u1, - }), base_address + 0x114); - - /// address: 0x40014118 - /// Interrupt Force for proc0 - pub const PROC0_INTF2 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO16_LEVEL_LOW: u1, - GPIO16_LEVEL_HIGH: u1, - GPIO16_EDGE_LOW: u1, - GPIO16_EDGE_HIGH: u1, - GPIO17_LEVEL_LOW: u1, - GPIO17_LEVEL_HIGH: u1, - GPIO17_EDGE_LOW: u1, - GPIO17_EDGE_HIGH: u1, - GPIO18_LEVEL_LOW: u1, - GPIO18_LEVEL_HIGH: u1, - GPIO18_EDGE_LOW: u1, - GPIO18_EDGE_HIGH: u1, - GPIO19_LEVEL_LOW: u1, - GPIO19_LEVEL_HIGH: u1, - GPIO19_EDGE_LOW: u1, - GPIO19_EDGE_HIGH: u1, - GPIO20_LEVEL_LOW: u1, - GPIO20_LEVEL_HIGH: u1, - GPIO20_EDGE_LOW: u1, - GPIO20_EDGE_HIGH: u1, - GPIO21_LEVEL_LOW: u1, - GPIO21_LEVEL_HIGH: u1, - GPIO21_EDGE_LOW: u1, - GPIO21_EDGE_HIGH: u1, - GPIO22_LEVEL_LOW: u1, - GPIO22_LEVEL_HIGH: u1, - GPIO22_EDGE_LOW: u1, - GPIO22_EDGE_HIGH: u1, - GPIO23_LEVEL_LOW: u1, - GPIO23_LEVEL_HIGH: u1, - GPIO23_EDGE_LOW: u1, - GPIO23_EDGE_HIGH: u1, - }), base_address + 0x118); - - /// address: 0x4001411c - /// Interrupt Force for proc0 - pub const PROC0_INTF3 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO24_LEVEL_LOW: u1, - GPIO24_LEVEL_HIGH: u1, - GPIO24_EDGE_LOW: u1, - GPIO24_EDGE_HIGH: u1, - GPIO25_LEVEL_LOW: u1, - GPIO25_LEVEL_HIGH: u1, - GPIO25_EDGE_LOW: u1, - GPIO25_EDGE_HIGH: u1, - GPIO26_LEVEL_LOW: u1, - GPIO26_LEVEL_HIGH: u1, - GPIO26_EDGE_LOW: u1, - GPIO26_EDGE_HIGH: u1, - GPIO27_LEVEL_LOW: u1, - GPIO27_LEVEL_HIGH: u1, - GPIO27_EDGE_LOW: u1, - GPIO27_EDGE_HIGH: u1, - GPIO28_LEVEL_LOW: u1, - GPIO28_LEVEL_HIGH: u1, - GPIO28_EDGE_LOW: u1, - GPIO28_EDGE_HIGH: u1, - GPIO29_LEVEL_LOW: u1, - GPIO29_LEVEL_HIGH: u1, - GPIO29_EDGE_LOW: u1, - GPIO29_EDGE_HIGH: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x11c); - - /// address: 0x40014120 - /// Interrupt status after masking & forcing for proc0 - pub const PROC0_INTS0 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO0_LEVEL_LOW: u1, - GPIO0_LEVEL_HIGH: u1, - GPIO0_EDGE_LOW: u1, - GPIO0_EDGE_HIGH: u1, - GPIO1_LEVEL_LOW: u1, - GPIO1_LEVEL_HIGH: u1, - GPIO1_EDGE_LOW: u1, - GPIO1_EDGE_HIGH: u1, - GPIO2_LEVEL_LOW: u1, - GPIO2_LEVEL_HIGH: u1, - GPIO2_EDGE_LOW: u1, - GPIO2_EDGE_HIGH: u1, - GPIO3_LEVEL_LOW: u1, - GPIO3_LEVEL_HIGH: u1, - GPIO3_EDGE_LOW: u1, - GPIO3_EDGE_HIGH: u1, - GPIO4_LEVEL_LOW: u1, - GPIO4_LEVEL_HIGH: u1, - GPIO4_EDGE_LOW: u1, - GPIO4_EDGE_HIGH: u1, - GPIO5_LEVEL_LOW: u1, - GPIO5_LEVEL_HIGH: u1, - GPIO5_EDGE_LOW: u1, - GPIO5_EDGE_HIGH: u1, - GPIO6_LEVEL_LOW: u1, - GPIO6_LEVEL_HIGH: u1, - GPIO6_EDGE_LOW: u1, - GPIO6_EDGE_HIGH: u1, - GPIO7_LEVEL_LOW: u1, - GPIO7_LEVEL_HIGH: u1, - GPIO7_EDGE_LOW: u1, - GPIO7_EDGE_HIGH: u1, - }), base_address + 0x120); - - /// address: 0x40014124 - /// Interrupt status after masking & forcing for proc0 - pub const PROC0_INTS1 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO8_LEVEL_LOW: u1, - GPIO8_LEVEL_HIGH: u1, - GPIO8_EDGE_LOW: u1, - GPIO8_EDGE_HIGH: u1, - GPIO9_LEVEL_LOW: u1, - GPIO9_LEVEL_HIGH: u1, - GPIO9_EDGE_LOW: u1, - GPIO9_EDGE_HIGH: u1, - GPIO10_LEVEL_LOW: u1, - GPIO10_LEVEL_HIGH: u1, - GPIO10_EDGE_LOW: u1, - GPIO10_EDGE_HIGH: u1, - GPIO11_LEVEL_LOW: u1, - GPIO11_LEVEL_HIGH: u1, - GPIO11_EDGE_LOW: u1, - GPIO11_EDGE_HIGH: u1, - GPIO12_LEVEL_LOW: u1, - GPIO12_LEVEL_HIGH: u1, - GPIO12_EDGE_LOW: u1, - GPIO12_EDGE_HIGH: u1, - GPIO13_LEVEL_LOW: u1, - GPIO13_LEVEL_HIGH: u1, - GPIO13_EDGE_LOW: u1, - GPIO13_EDGE_HIGH: u1, - GPIO14_LEVEL_LOW: u1, - GPIO14_LEVEL_HIGH: u1, - GPIO14_EDGE_LOW: u1, - GPIO14_EDGE_HIGH: u1, - GPIO15_LEVEL_LOW: u1, - GPIO15_LEVEL_HIGH: u1, - GPIO15_EDGE_LOW: u1, - GPIO15_EDGE_HIGH: u1, - }), base_address + 0x124); - - /// address: 0x40014128 - /// Interrupt status after masking & forcing for proc0 - pub const PROC0_INTS2 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO16_LEVEL_LOW: u1, - GPIO16_LEVEL_HIGH: u1, - GPIO16_EDGE_LOW: u1, - GPIO16_EDGE_HIGH: u1, - GPIO17_LEVEL_LOW: u1, - GPIO17_LEVEL_HIGH: u1, - GPIO17_EDGE_LOW: u1, - GPIO17_EDGE_HIGH: u1, - GPIO18_LEVEL_LOW: u1, - GPIO18_LEVEL_HIGH: u1, - GPIO18_EDGE_LOW: u1, - GPIO18_EDGE_HIGH: u1, - GPIO19_LEVEL_LOW: u1, - GPIO19_LEVEL_HIGH: u1, - GPIO19_EDGE_LOW: u1, - GPIO19_EDGE_HIGH: u1, - GPIO20_LEVEL_LOW: u1, - GPIO20_LEVEL_HIGH: u1, - GPIO20_EDGE_LOW: u1, - GPIO20_EDGE_HIGH: u1, - GPIO21_LEVEL_LOW: u1, - GPIO21_LEVEL_HIGH: u1, - GPIO21_EDGE_LOW: u1, - GPIO21_EDGE_HIGH: u1, - GPIO22_LEVEL_LOW: u1, - GPIO22_LEVEL_HIGH: u1, - GPIO22_EDGE_LOW: u1, - GPIO22_EDGE_HIGH: u1, - GPIO23_LEVEL_LOW: u1, - GPIO23_LEVEL_HIGH: u1, - GPIO23_EDGE_LOW: u1, - GPIO23_EDGE_HIGH: u1, - }), base_address + 0x128); - - /// address: 0x4001412c - /// Interrupt status after masking & forcing for proc0 - pub const PROC0_INTS3 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO24_LEVEL_LOW: u1, - GPIO24_LEVEL_HIGH: u1, - GPIO24_EDGE_LOW: u1, - GPIO24_EDGE_HIGH: u1, - GPIO25_LEVEL_LOW: u1, - GPIO25_LEVEL_HIGH: u1, - GPIO25_EDGE_LOW: u1, - GPIO25_EDGE_HIGH: u1, - GPIO26_LEVEL_LOW: u1, - GPIO26_LEVEL_HIGH: u1, - GPIO26_EDGE_LOW: u1, - GPIO26_EDGE_HIGH: u1, - GPIO27_LEVEL_LOW: u1, - GPIO27_LEVEL_HIGH: u1, - GPIO27_EDGE_LOW: u1, - GPIO27_EDGE_HIGH: u1, - GPIO28_LEVEL_LOW: u1, - GPIO28_LEVEL_HIGH: u1, - GPIO28_EDGE_LOW: u1, - GPIO28_EDGE_HIGH: u1, - GPIO29_LEVEL_LOW: u1, - GPIO29_LEVEL_HIGH: u1, - GPIO29_EDGE_LOW: u1, - GPIO29_EDGE_HIGH: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x12c); - - /// address: 0x40014130 - /// Interrupt Enable for proc1 - pub const PROC1_INTE0 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO0_LEVEL_LOW: u1, - GPIO0_LEVEL_HIGH: u1, - GPIO0_EDGE_LOW: u1, - GPIO0_EDGE_HIGH: u1, - GPIO1_LEVEL_LOW: u1, - GPIO1_LEVEL_HIGH: u1, - GPIO1_EDGE_LOW: u1, - GPIO1_EDGE_HIGH: u1, - GPIO2_LEVEL_LOW: u1, - GPIO2_LEVEL_HIGH: u1, - GPIO2_EDGE_LOW: u1, - GPIO2_EDGE_HIGH: u1, - GPIO3_LEVEL_LOW: u1, - GPIO3_LEVEL_HIGH: u1, - GPIO3_EDGE_LOW: u1, - GPIO3_EDGE_HIGH: u1, - GPIO4_LEVEL_LOW: u1, - GPIO4_LEVEL_HIGH: u1, - GPIO4_EDGE_LOW: u1, - GPIO4_EDGE_HIGH: u1, - GPIO5_LEVEL_LOW: u1, - GPIO5_LEVEL_HIGH: u1, - GPIO5_EDGE_LOW: u1, - GPIO5_EDGE_HIGH: u1, - GPIO6_LEVEL_LOW: u1, - GPIO6_LEVEL_HIGH: u1, - GPIO6_EDGE_LOW: u1, - GPIO6_EDGE_HIGH: u1, - GPIO7_LEVEL_LOW: u1, - GPIO7_LEVEL_HIGH: u1, - GPIO7_EDGE_LOW: u1, - GPIO7_EDGE_HIGH: u1, - }), base_address + 0x130); - - /// address: 0x40014134 - /// Interrupt Enable for proc1 - pub const PROC1_INTE1 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO8_LEVEL_LOW: u1, - GPIO8_LEVEL_HIGH: u1, - GPIO8_EDGE_LOW: u1, - GPIO8_EDGE_HIGH: u1, - GPIO9_LEVEL_LOW: u1, - GPIO9_LEVEL_HIGH: u1, - GPIO9_EDGE_LOW: u1, - GPIO9_EDGE_HIGH: u1, - GPIO10_LEVEL_LOW: u1, - GPIO10_LEVEL_HIGH: u1, - GPIO10_EDGE_LOW: u1, - GPIO10_EDGE_HIGH: u1, - GPIO11_LEVEL_LOW: u1, - GPIO11_LEVEL_HIGH: u1, - GPIO11_EDGE_LOW: u1, - GPIO11_EDGE_HIGH: u1, - GPIO12_LEVEL_LOW: u1, - GPIO12_LEVEL_HIGH: u1, - GPIO12_EDGE_LOW: u1, - GPIO12_EDGE_HIGH: u1, - GPIO13_LEVEL_LOW: u1, - GPIO13_LEVEL_HIGH: u1, - GPIO13_EDGE_LOW: u1, - GPIO13_EDGE_HIGH: u1, - GPIO14_LEVEL_LOW: u1, - GPIO14_LEVEL_HIGH: u1, - GPIO14_EDGE_LOW: u1, - GPIO14_EDGE_HIGH: u1, - GPIO15_LEVEL_LOW: u1, - GPIO15_LEVEL_HIGH: u1, - GPIO15_EDGE_LOW: u1, - GPIO15_EDGE_HIGH: u1, - }), base_address + 0x134); - - /// address: 0x40014138 - /// Interrupt Enable for proc1 - pub const PROC1_INTE2 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO16_LEVEL_LOW: u1, - GPIO16_LEVEL_HIGH: u1, - GPIO16_EDGE_LOW: u1, - GPIO16_EDGE_HIGH: u1, - GPIO17_LEVEL_LOW: u1, - GPIO17_LEVEL_HIGH: u1, - GPIO17_EDGE_LOW: u1, - GPIO17_EDGE_HIGH: u1, - GPIO18_LEVEL_LOW: u1, - GPIO18_LEVEL_HIGH: u1, - GPIO18_EDGE_LOW: u1, - GPIO18_EDGE_HIGH: u1, - GPIO19_LEVEL_LOW: u1, - GPIO19_LEVEL_HIGH: u1, - GPIO19_EDGE_LOW: u1, - GPIO19_EDGE_HIGH: u1, - GPIO20_LEVEL_LOW: u1, - GPIO20_LEVEL_HIGH: u1, - GPIO20_EDGE_LOW: u1, - GPIO20_EDGE_HIGH: u1, - GPIO21_LEVEL_LOW: u1, - GPIO21_LEVEL_HIGH: u1, - GPIO21_EDGE_LOW: u1, - GPIO21_EDGE_HIGH: u1, - GPIO22_LEVEL_LOW: u1, - GPIO22_LEVEL_HIGH: u1, - GPIO22_EDGE_LOW: u1, - GPIO22_EDGE_HIGH: u1, - GPIO23_LEVEL_LOW: u1, - GPIO23_LEVEL_HIGH: u1, - GPIO23_EDGE_LOW: u1, - GPIO23_EDGE_HIGH: u1, - }), base_address + 0x138); - - /// address: 0x4001413c - /// Interrupt Enable for proc1 - pub const PROC1_INTE3 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO24_LEVEL_LOW: u1, - GPIO24_LEVEL_HIGH: u1, - GPIO24_EDGE_LOW: u1, - GPIO24_EDGE_HIGH: u1, - GPIO25_LEVEL_LOW: u1, - GPIO25_LEVEL_HIGH: u1, - GPIO25_EDGE_LOW: u1, - GPIO25_EDGE_HIGH: u1, - GPIO26_LEVEL_LOW: u1, - GPIO26_LEVEL_HIGH: u1, - GPIO26_EDGE_LOW: u1, - GPIO26_EDGE_HIGH: u1, - GPIO27_LEVEL_LOW: u1, - GPIO27_LEVEL_HIGH: u1, - GPIO27_EDGE_LOW: u1, - GPIO27_EDGE_HIGH: u1, - GPIO28_LEVEL_LOW: u1, - GPIO28_LEVEL_HIGH: u1, - GPIO28_EDGE_LOW: u1, - GPIO28_EDGE_HIGH: u1, - GPIO29_LEVEL_LOW: u1, - GPIO29_LEVEL_HIGH: u1, - GPIO29_EDGE_LOW: u1, - GPIO29_EDGE_HIGH: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x13c); - - /// address: 0x40014140 - /// Interrupt Force for proc1 - pub const PROC1_INTF0 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO0_LEVEL_LOW: u1, - GPIO0_LEVEL_HIGH: u1, - GPIO0_EDGE_LOW: u1, - GPIO0_EDGE_HIGH: u1, - GPIO1_LEVEL_LOW: u1, - GPIO1_LEVEL_HIGH: u1, - GPIO1_EDGE_LOW: u1, - GPIO1_EDGE_HIGH: u1, - GPIO2_LEVEL_LOW: u1, - GPIO2_LEVEL_HIGH: u1, - GPIO2_EDGE_LOW: u1, - GPIO2_EDGE_HIGH: u1, - GPIO3_LEVEL_LOW: u1, - GPIO3_LEVEL_HIGH: u1, - GPIO3_EDGE_LOW: u1, - GPIO3_EDGE_HIGH: u1, - GPIO4_LEVEL_LOW: u1, - GPIO4_LEVEL_HIGH: u1, - GPIO4_EDGE_LOW: u1, - GPIO4_EDGE_HIGH: u1, - GPIO5_LEVEL_LOW: u1, - GPIO5_LEVEL_HIGH: u1, - GPIO5_EDGE_LOW: u1, - GPIO5_EDGE_HIGH: u1, - GPIO6_LEVEL_LOW: u1, - GPIO6_LEVEL_HIGH: u1, - GPIO6_EDGE_LOW: u1, - GPIO6_EDGE_HIGH: u1, - GPIO7_LEVEL_LOW: u1, - GPIO7_LEVEL_HIGH: u1, - GPIO7_EDGE_LOW: u1, - GPIO7_EDGE_HIGH: u1, - }), base_address + 0x140); - - /// address: 0x40014144 - /// Interrupt Force for proc1 - pub const PROC1_INTF1 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO8_LEVEL_LOW: u1, - GPIO8_LEVEL_HIGH: u1, - GPIO8_EDGE_LOW: u1, - GPIO8_EDGE_HIGH: u1, - GPIO9_LEVEL_LOW: u1, - GPIO9_LEVEL_HIGH: u1, - GPIO9_EDGE_LOW: u1, - GPIO9_EDGE_HIGH: u1, - GPIO10_LEVEL_LOW: u1, - GPIO10_LEVEL_HIGH: u1, - GPIO10_EDGE_LOW: u1, - GPIO10_EDGE_HIGH: u1, - GPIO11_LEVEL_LOW: u1, - GPIO11_LEVEL_HIGH: u1, - GPIO11_EDGE_LOW: u1, - GPIO11_EDGE_HIGH: u1, - GPIO12_LEVEL_LOW: u1, - GPIO12_LEVEL_HIGH: u1, - GPIO12_EDGE_LOW: u1, - GPIO12_EDGE_HIGH: u1, - GPIO13_LEVEL_LOW: u1, - GPIO13_LEVEL_HIGH: u1, - GPIO13_EDGE_LOW: u1, - GPIO13_EDGE_HIGH: u1, - GPIO14_LEVEL_LOW: u1, - GPIO14_LEVEL_HIGH: u1, - GPIO14_EDGE_LOW: u1, - GPIO14_EDGE_HIGH: u1, - GPIO15_LEVEL_LOW: u1, - GPIO15_LEVEL_HIGH: u1, - GPIO15_EDGE_LOW: u1, - GPIO15_EDGE_HIGH: u1, - }), base_address + 0x144); - - /// address: 0x40014148 - /// Interrupt Force for proc1 - pub const PROC1_INTF2 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO16_LEVEL_LOW: u1, - GPIO16_LEVEL_HIGH: u1, - GPIO16_EDGE_LOW: u1, - GPIO16_EDGE_HIGH: u1, - GPIO17_LEVEL_LOW: u1, - GPIO17_LEVEL_HIGH: u1, - GPIO17_EDGE_LOW: u1, - GPIO17_EDGE_HIGH: u1, - GPIO18_LEVEL_LOW: u1, - GPIO18_LEVEL_HIGH: u1, - GPIO18_EDGE_LOW: u1, - GPIO18_EDGE_HIGH: u1, - GPIO19_LEVEL_LOW: u1, - GPIO19_LEVEL_HIGH: u1, - GPIO19_EDGE_LOW: u1, - GPIO19_EDGE_HIGH: u1, - GPIO20_LEVEL_LOW: u1, - GPIO20_LEVEL_HIGH: u1, - GPIO20_EDGE_LOW: u1, - GPIO20_EDGE_HIGH: u1, - GPIO21_LEVEL_LOW: u1, - GPIO21_LEVEL_HIGH: u1, - GPIO21_EDGE_LOW: u1, - GPIO21_EDGE_HIGH: u1, - GPIO22_LEVEL_LOW: u1, - GPIO22_LEVEL_HIGH: u1, - GPIO22_EDGE_LOW: u1, - GPIO22_EDGE_HIGH: u1, - GPIO23_LEVEL_LOW: u1, - GPIO23_LEVEL_HIGH: u1, - GPIO23_EDGE_LOW: u1, - GPIO23_EDGE_HIGH: u1, - }), base_address + 0x148); - - /// address: 0x4001414c - /// Interrupt Force for proc1 - pub const PROC1_INTF3 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO24_LEVEL_LOW: u1, - GPIO24_LEVEL_HIGH: u1, - GPIO24_EDGE_LOW: u1, - GPIO24_EDGE_HIGH: u1, - GPIO25_LEVEL_LOW: u1, - GPIO25_LEVEL_HIGH: u1, - GPIO25_EDGE_LOW: u1, - GPIO25_EDGE_HIGH: u1, - GPIO26_LEVEL_LOW: u1, - GPIO26_LEVEL_HIGH: u1, - GPIO26_EDGE_LOW: u1, - GPIO26_EDGE_HIGH: u1, - GPIO27_LEVEL_LOW: u1, - GPIO27_LEVEL_HIGH: u1, - GPIO27_EDGE_LOW: u1, - GPIO27_EDGE_HIGH: u1, - GPIO28_LEVEL_LOW: u1, - GPIO28_LEVEL_HIGH: u1, - GPIO28_EDGE_LOW: u1, - GPIO28_EDGE_HIGH: u1, - GPIO29_LEVEL_LOW: u1, - GPIO29_LEVEL_HIGH: u1, - GPIO29_EDGE_LOW: u1, - GPIO29_EDGE_HIGH: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x14c); - - /// address: 0x40014150 - /// Interrupt status after masking & forcing for proc1 - pub const PROC1_INTS0 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO0_LEVEL_LOW: u1, - GPIO0_LEVEL_HIGH: u1, - GPIO0_EDGE_LOW: u1, - GPIO0_EDGE_HIGH: u1, - GPIO1_LEVEL_LOW: u1, - GPIO1_LEVEL_HIGH: u1, - GPIO1_EDGE_LOW: u1, - GPIO1_EDGE_HIGH: u1, - GPIO2_LEVEL_LOW: u1, - GPIO2_LEVEL_HIGH: u1, - GPIO2_EDGE_LOW: u1, - GPIO2_EDGE_HIGH: u1, - GPIO3_LEVEL_LOW: u1, - GPIO3_LEVEL_HIGH: u1, - GPIO3_EDGE_LOW: u1, - GPIO3_EDGE_HIGH: u1, - GPIO4_LEVEL_LOW: u1, - GPIO4_LEVEL_HIGH: u1, - GPIO4_EDGE_LOW: u1, - GPIO4_EDGE_HIGH: u1, - GPIO5_LEVEL_LOW: u1, - GPIO5_LEVEL_HIGH: u1, - GPIO5_EDGE_LOW: u1, - GPIO5_EDGE_HIGH: u1, - GPIO6_LEVEL_LOW: u1, - GPIO6_LEVEL_HIGH: u1, - GPIO6_EDGE_LOW: u1, - GPIO6_EDGE_HIGH: u1, - GPIO7_LEVEL_LOW: u1, - GPIO7_LEVEL_HIGH: u1, - GPIO7_EDGE_LOW: u1, - GPIO7_EDGE_HIGH: u1, - }), base_address + 0x150); - - /// address: 0x40014154 - /// Interrupt status after masking & forcing for proc1 - pub const PROC1_INTS1 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO8_LEVEL_LOW: u1, - GPIO8_LEVEL_HIGH: u1, - GPIO8_EDGE_LOW: u1, - GPIO8_EDGE_HIGH: u1, - GPIO9_LEVEL_LOW: u1, - GPIO9_LEVEL_HIGH: u1, - GPIO9_EDGE_LOW: u1, - GPIO9_EDGE_HIGH: u1, - GPIO10_LEVEL_LOW: u1, - GPIO10_LEVEL_HIGH: u1, - GPIO10_EDGE_LOW: u1, - GPIO10_EDGE_HIGH: u1, - GPIO11_LEVEL_LOW: u1, - GPIO11_LEVEL_HIGH: u1, - GPIO11_EDGE_LOW: u1, - GPIO11_EDGE_HIGH: u1, - GPIO12_LEVEL_LOW: u1, - GPIO12_LEVEL_HIGH: u1, - GPIO12_EDGE_LOW: u1, - GPIO12_EDGE_HIGH: u1, - GPIO13_LEVEL_LOW: u1, - GPIO13_LEVEL_HIGH: u1, - GPIO13_EDGE_LOW: u1, - GPIO13_EDGE_HIGH: u1, - GPIO14_LEVEL_LOW: u1, - GPIO14_LEVEL_HIGH: u1, - GPIO14_EDGE_LOW: u1, - GPIO14_EDGE_HIGH: u1, - GPIO15_LEVEL_LOW: u1, - GPIO15_LEVEL_HIGH: u1, - GPIO15_EDGE_LOW: u1, - GPIO15_EDGE_HIGH: u1, - }), base_address + 0x154); - - /// address: 0x40014158 - /// Interrupt status after masking & forcing for proc1 - pub const PROC1_INTS2 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO16_LEVEL_LOW: u1, - GPIO16_LEVEL_HIGH: u1, - GPIO16_EDGE_LOW: u1, - GPIO16_EDGE_HIGH: u1, - GPIO17_LEVEL_LOW: u1, - GPIO17_LEVEL_HIGH: u1, - GPIO17_EDGE_LOW: u1, - GPIO17_EDGE_HIGH: u1, - GPIO18_LEVEL_LOW: u1, - GPIO18_LEVEL_HIGH: u1, - GPIO18_EDGE_LOW: u1, - GPIO18_EDGE_HIGH: u1, - GPIO19_LEVEL_LOW: u1, - GPIO19_LEVEL_HIGH: u1, - GPIO19_EDGE_LOW: u1, - GPIO19_EDGE_HIGH: u1, - GPIO20_LEVEL_LOW: u1, - GPIO20_LEVEL_HIGH: u1, - GPIO20_EDGE_LOW: u1, - GPIO20_EDGE_HIGH: u1, - GPIO21_LEVEL_LOW: u1, - GPIO21_LEVEL_HIGH: u1, - GPIO21_EDGE_LOW: u1, - GPIO21_EDGE_HIGH: u1, - GPIO22_LEVEL_LOW: u1, - GPIO22_LEVEL_HIGH: u1, - GPIO22_EDGE_LOW: u1, - GPIO22_EDGE_HIGH: u1, - GPIO23_LEVEL_LOW: u1, - GPIO23_LEVEL_HIGH: u1, - GPIO23_EDGE_LOW: u1, - GPIO23_EDGE_HIGH: u1, - }), base_address + 0x158); - - /// address: 0x4001415c - /// Interrupt status after masking & forcing for proc1 - pub const PROC1_INTS3 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO24_LEVEL_LOW: u1, - GPIO24_LEVEL_HIGH: u1, - GPIO24_EDGE_LOW: u1, - GPIO24_EDGE_HIGH: u1, - GPIO25_LEVEL_LOW: u1, - GPIO25_LEVEL_HIGH: u1, - GPIO25_EDGE_LOW: u1, - GPIO25_EDGE_HIGH: u1, - GPIO26_LEVEL_LOW: u1, - GPIO26_LEVEL_HIGH: u1, - GPIO26_EDGE_LOW: u1, - GPIO26_EDGE_HIGH: u1, - GPIO27_LEVEL_LOW: u1, - GPIO27_LEVEL_HIGH: u1, - GPIO27_EDGE_LOW: u1, - GPIO27_EDGE_HIGH: u1, - GPIO28_LEVEL_LOW: u1, - GPIO28_LEVEL_HIGH: u1, - GPIO28_EDGE_LOW: u1, - GPIO28_EDGE_HIGH: u1, - GPIO29_LEVEL_LOW: u1, - GPIO29_LEVEL_HIGH: u1, - GPIO29_EDGE_LOW: u1, - GPIO29_EDGE_HIGH: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x15c); - - /// address: 0x40014160 - /// Interrupt Enable for dormant_wake - pub const DORMANT_WAKE_INTE0 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO0_LEVEL_LOW: u1, - GPIO0_LEVEL_HIGH: u1, - GPIO0_EDGE_LOW: u1, - GPIO0_EDGE_HIGH: u1, - GPIO1_LEVEL_LOW: u1, - GPIO1_LEVEL_HIGH: u1, - GPIO1_EDGE_LOW: u1, - GPIO1_EDGE_HIGH: u1, - GPIO2_LEVEL_LOW: u1, - GPIO2_LEVEL_HIGH: u1, - GPIO2_EDGE_LOW: u1, - GPIO2_EDGE_HIGH: u1, - GPIO3_LEVEL_LOW: u1, - GPIO3_LEVEL_HIGH: u1, - GPIO3_EDGE_LOW: u1, - GPIO3_EDGE_HIGH: u1, - GPIO4_LEVEL_LOW: u1, - GPIO4_LEVEL_HIGH: u1, - GPIO4_EDGE_LOW: u1, - GPIO4_EDGE_HIGH: u1, - GPIO5_LEVEL_LOW: u1, - GPIO5_LEVEL_HIGH: u1, - GPIO5_EDGE_LOW: u1, - GPIO5_EDGE_HIGH: u1, - GPIO6_LEVEL_LOW: u1, - GPIO6_LEVEL_HIGH: u1, - GPIO6_EDGE_LOW: u1, - GPIO6_EDGE_HIGH: u1, - GPIO7_LEVEL_LOW: u1, - GPIO7_LEVEL_HIGH: u1, - GPIO7_EDGE_LOW: u1, - GPIO7_EDGE_HIGH: u1, - }), base_address + 0x160); - - /// address: 0x40014164 - /// Interrupt Enable for dormant_wake - pub const DORMANT_WAKE_INTE1 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO8_LEVEL_LOW: u1, - GPIO8_LEVEL_HIGH: u1, - GPIO8_EDGE_LOW: u1, - GPIO8_EDGE_HIGH: u1, - GPIO9_LEVEL_LOW: u1, - GPIO9_LEVEL_HIGH: u1, - GPIO9_EDGE_LOW: u1, - GPIO9_EDGE_HIGH: u1, - GPIO10_LEVEL_LOW: u1, - GPIO10_LEVEL_HIGH: u1, - GPIO10_EDGE_LOW: u1, - GPIO10_EDGE_HIGH: u1, - GPIO11_LEVEL_LOW: u1, - GPIO11_LEVEL_HIGH: u1, - GPIO11_EDGE_LOW: u1, - GPIO11_EDGE_HIGH: u1, - GPIO12_LEVEL_LOW: u1, - GPIO12_LEVEL_HIGH: u1, - GPIO12_EDGE_LOW: u1, - GPIO12_EDGE_HIGH: u1, - GPIO13_LEVEL_LOW: u1, - GPIO13_LEVEL_HIGH: u1, - GPIO13_EDGE_LOW: u1, - GPIO13_EDGE_HIGH: u1, - GPIO14_LEVEL_LOW: u1, - GPIO14_LEVEL_HIGH: u1, - GPIO14_EDGE_LOW: u1, - GPIO14_EDGE_HIGH: u1, - GPIO15_LEVEL_LOW: u1, - GPIO15_LEVEL_HIGH: u1, - GPIO15_EDGE_LOW: u1, - GPIO15_EDGE_HIGH: u1, - }), base_address + 0x164); - - /// address: 0x40014168 - /// Interrupt Enable for dormant_wake - pub const DORMANT_WAKE_INTE2 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO16_LEVEL_LOW: u1, - GPIO16_LEVEL_HIGH: u1, - GPIO16_EDGE_LOW: u1, - GPIO16_EDGE_HIGH: u1, - GPIO17_LEVEL_LOW: u1, - GPIO17_LEVEL_HIGH: u1, - GPIO17_EDGE_LOW: u1, - GPIO17_EDGE_HIGH: u1, - GPIO18_LEVEL_LOW: u1, - GPIO18_LEVEL_HIGH: u1, - GPIO18_EDGE_LOW: u1, - GPIO18_EDGE_HIGH: u1, - GPIO19_LEVEL_LOW: u1, - GPIO19_LEVEL_HIGH: u1, - GPIO19_EDGE_LOW: u1, - GPIO19_EDGE_HIGH: u1, - GPIO20_LEVEL_LOW: u1, - GPIO20_LEVEL_HIGH: u1, - GPIO20_EDGE_LOW: u1, - GPIO20_EDGE_HIGH: u1, - GPIO21_LEVEL_LOW: u1, - GPIO21_LEVEL_HIGH: u1, - GPIO21_EDGE_LOW: u1, - GPIO21_EDGE_HIGH: u1, - GPIO22_LEVEL_LOW: u1, - GPIO22_LEVEL_HIGH: u1, - GPIO22_EDGE_LOW: u1, - GPIO22_EDGE_HIGH: u1, - GPIO23_LEVEL_LOW: u1, - GPIO23_LEVEL_HIGH: u1, - GPIO23_EDGE_LOW: u1, - GPIO23_EDGE_HIGH: u1, - }), base_address + 0x168); - - /// address: 0x4001416c - /// Interrupt Enable for dormant_wake - pub const DORMANT_WAKE_INTE3 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO24_LEVEL_LOW: u1, - GPIO24_LEVEL_HIGH: u1, - GPIO24_EDGE_LOW: u1, - GPIO24_EDGE_HIGH: u1, - GPIO25_LEVEL_LOW: u1, - GPIO25_LEVEL_HIGH: u1, - GPIO25_EDGE_LOW: u1, - GPIO25_EDGE_HIGH: u1, - GPIO26_LEVEL_LOW: u1, - GPIO26_LEVEL_HIGH: u1, - GPIO26_EDGE_LOW: u1, - GPIO26_EDGE_HIGH: u1, - GPIO27_LEVEL_LOW: u1, - GPIO27_LEVEL_HIGH: u1, - GPIO27_EDGE_LOW: u1, - GPIO27_EDGE_HIGH: u1, - GPIO28_LEVEL_LOW: u1, - GPIO28_LEVEL_HIGH: u1, - GPIO28_EDGE_LOW: u1, - GPIO28_EDGE_HIGH: u1, - GPIO29_LEVEL_LOW: u1, - GPIO29_LEVEL_HIGH: u1, - GPIO29_EDGE_LOW: u1, - GPIO29_EDGE_HIGH: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x16c); - - /// address: 0x40014170 - /// Interrupt Force for dormant_wake - pub const DORMANT_WAKE_INTF0 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO0_LEVEL_LOW: u1, - GPIO0_LEVEL_HIGH: u1, - GPIO0_EDGE_LOW: u1, - GPIO0_EDGE_HIGH: u1, - GPIO1_LEVEL_LOW: u1, - GPIO1_LEVEL_HIGH: u1, - GPIO1_EDGE_LOW: u1, - GPIO1_EDGE_HIGH: u1, - GPIO2_LEVEL_LOW: u1, - GPIO2_LEVEL_HIGH: u1, - GPIO2_EDGE_LOW: u1, - GPIO2_EDGE_HIGH: u1, - GPIO3_LEVEL_LOW: u1, - GPIO3_LEVEL_HIGH: u1, - GPIO3_EDGE_LOW: u1, - GPIO3_EDGE_HIGH: u1, - GPIO4_LEVEL_LOW: u1, - GPIO4_LEVEL_HIGH: u1, - GPIO4_EDGE_LOW: u1, - GPIO4_EDGE_HIGH: u1, - GPIO5_LEVEL_LOW: u1, - GPIO5_LEVEL_HIGH: u1, - GPIO5_EDGE_LOW: u1, - GPIO5_EDGE_HIGH: u1, - GPIO6_LEVEL_LOW: u1, - GPIO6_LEVEL_HIGH: u1, - GPIO6_EDGE_LOW: u1, - GPIO6_EDGE_HIGH: u1, - GPIO7_LEVEL_LOW: u1, - GPIO7_LEVEL_HIGH: u1, - GPIO7_EDGE_LOW: u1, - GPIO7_EDGE_HIGH: u1, - }), base_address + 0x170); - - /// address: 0x40014174 - /// Interrupt Force for dormant_wake - pub const DORMANT_WAKE_INTF1 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO8_LEVEL_LOW: u1, - GPIO8_LEVEL_HIGH: u1, - GPIO8_EDGE_LOW: u1, - GPIO8_EDGE_HIGH: u1, - GPIO9_LEVEL_LOW: u1, - GPIO9_LEVEL_HIGH: u1, - GPIO9_EDGE_LOW: u1, - GPIO9_EDGE_HIGH: u1, - GPIO10_LEVEL_LOW: u1, - GPIO10_LEVEL_HIGH: u1, - GPIO10_EDGE_LOW: u1, - GPIO10_EDGE_HIGH: u1, - GPIO11_LEVEL_LOW: u1, - GPIO11_LEVEL_HIGH: u1, - GPIO11_EDGE_LOW: u1, - GPIO11_EDGE_HIGH: u1, - GPIO12_LEVEL_LOW: u1, - GPIO12_LEVEL_HIGH: u1, - GPIO12_EDGE_LOW: u1, - GPIO12_EDGE_HIGH: u1, - GPIO13_LEVEL_LOW: u1, - GPIO13_LEVEL_HIGH: u1, - GPIO13_EDGE_LOW: u1, - GPIO13_EDGE_HIGH: u1, - GPIO14_LEVEL_LOW: u1, - GPIO14_LEVEL_HIGH: u1, - GPIO14_EDGE_LOW: u1, - GPIO14_EDGE_HIGH: u1, - GPIO15_LEVEL_LOW: u1, - GPIO15_LEVEL_HIGH: u1, - GPIO15_EDGE_LOW: u1, - GPIO15_EDGE_HIGH: u1, - }), base_address + 0x174); - - /// address: 0x40014178 - /// Interrupt Force for dormant_wake - pub const DORMANT_WAKE_INTF2 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO16_LEVEL_LOW: u1, - GPIO16_LEVEL_HIGH: u1, - GPIO16_EDGE_LOW: u1, - GPIO16_EDGE_HIGH: u1, - GPIO17_LEVEL_LOW: u1, - GPIO17_LEVEL_HIGH: u1, - GPIO17_EDGE_LOW: u1, - GPIO17_EDGE_HIGH: u1, - GPIO18_LEVEL_LOW: u1, - GPIO18_LEVEL_HIGH: u1, - GPIO18_EDGE_LOW: u1, - GPIO18_EDGE_HIGH: u1, - GPIO19_LEVEL_LOW: u1, - GPIO19_LEVEL_HIGH: u1, - GPIO19_EDGE_LOW: u1, - GPIO19_EDGE_HIGH: u1, - GPIO20_LEVEL_LOW: u1, - GPIO20_LEVEL_HIGH: u1, - GPIO20_EDGE_LOW: u1, - GPIO20_EDGE_HIGH: u1, - GPIO21_LEVEL_LOW: u1, - GPIO21_LEVEL_HIGH: u1, - GPIO21_EDGE_LOW: u1, - GPIO21_EDGE_HIGH: u1, - GPIO22_LEVEL_LOW: u1, - GPIO22_LEVEL_HIGH: u1, - GPIO22_EDGE_LOW: u1, - GPIO22_EDGE_HIGH: u1, - GPIO23_LEVEL_LOW: u1, - GPIO23_LEVEL_HIGH: u1, - GPIO23_EDGE_LOW: u1, - GPIO23_EDGE_HIGH: u1, - }), base_address + 0x178); - - /// address: 0x4001417c - /// Interrupt Force for dormant_wake - pub const DORMANT_WAKE_INTF3 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO24_LEVEL_LOW: u1, - GPIO24_LEVEL_HIGH: u1, - GPIO24_EDGE_LOW: u1, - GPIO24_EDGE_HIGH: u1, - GPIO25_LEVEL_LOW: u1, - GPIO25_LEVEL_HIGH: u1, - GPIO25_EDGE_LOW: u1, - GPIO25_EDGE_HIGH: u1, - GPIO26_LEVEL_LOW: u1, - GPIO26_LEVEL_HIGH: u1, - GPIO26_EDGE_LOW: u1, - GPIO26_EDGE_HIGH: u1, - GPIO27_LEVEL_LOW: u1, - GPIO27_LEVEL_HIGH: u1, - GPIO27_EDGE_LOW: u1, - GPIO27_EDGE_HIGH: u1, - GPIO28_LEVEL_LOW: u1, - GPIO28_LEVEL_HIGH: u1, - GPIO28_EDGE_LOW: u1, - GPIO28_EDGE_HIGH: u1, - GPIO29_LEVEL_LOW: u1, - GPIO29_LEVEL_HIGH: u1, - GPIO29_EDGE_LOW: u1, - GPIO29_EDGE_HIGH: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x17c); - - /// address: 0x40014180 - /// Interrupt status after masking & forcing for dormant_wake - pub const DORMANT_WAKE_INTS0 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO0_LEVEL_LOW: u1, - GPIO0_LEVEL_HIGH: u1, - GPIO0_EDGE_LOW: u1, - GPIO0_EDGE_HIGH: u1, - GPIO1_LEVEL_LOW: u1, - GPIO1_LEVEL_HIGH: u1, - GPIO1_EDGE_LOW: u1, - GPIO1_EDGE_HIGH: u1, - GPIO2_LEVEL_LOW: u1, - GPIO2_LEVEL_HIGH: u1, - GPIO2_EDGE_LOW: u1, - GPIO2_EDGE_HIGH: u1, - GPIO3_LEVEL_LOW: u1, - GPIO3_LEVEL_HIGH: u1, - GPIO3_EDGE_LOW: u1, - GPIO3_EDGE_HIGH: u1, - GPIO4_LEVEL_LOW: u1, - GPIO4_LEVEL_HIGH: u1, - GPIO4_EDGE_LOW: u1, - GPIO4_EDGE_HIGH: u1, - GPIO5_LEVEL_LOW: u1, - GPIO5_LEVEL_HIGH: u1, - GPIO5_EDGE_LOW: u1, - GPIO5_EDGE_HIGH: u1, - GPIO6_LEVEL_LOW: u1, - GPIO6_LEVEL_HIGH: u1, - GPIO6_EDGE_LOW: u1, - GPIO6_EDGE_HIGH: u1, - GPIO7_LEVEL_LOW: u1, - GPIO7_LEVEL_HIGH: u1, - GPIO7_EDGE_LOW: u1, - GPIO7_EDGE_HIGH: u1, - }), base_address + 0x180); - - /// address: 0x40014184 - /// Interrupt status after masking & forcing for dormant_wake - pub const DORMANT_WAKE_INTS1 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO8_LEVEL_LOW: u1, - GPIO8_LEVEL_HIGH: u1, - GPIO8_EDGE_LOW: u1, - GPIO8_EDGE_HIGH: u1, - GPIO9_LEVEL_LOW: u1, - GPIO9_LEVEL_HIGH: u1, - GPIO9_EDGE_LOW: u1, - GPIO9_EDGE_HIGH: u1, - GPIO10_LEVEL_LOW: u1, - GPIO10_LEVEL_HIGH: u1, - GPIO10_EDGE_LOW: u1, - GPIO10_EDGE_HIGH: u1, - GPIO11_LEVEL_LOW: u1, - GPIO11_LEVEL_HIGH: u1, - GPIO11_EDGE_LOW: u1, - GPIO11_EDGE_HIGH: u1, - GPIO12_LEVEL_LOW: u1, - GPIO12_LEVEL_HIGH: u1, - GPIO12_EDGE_LOW: u1, - GPIO12_EDGE_HIGH: u1, - GPIO13_LEVEL_LOW: u1, - GPIO13_LEVEL_HIGH: u1, - GPIO13_EDGE_LOW: u1, - GPIO13_EDGE_HIGH: u1, - GPIO14_LEVEL_LOW: u1, - GPIO14_LEVEL_HIGH: u1, - GPIO14_EDGE_LOW: u1, - GPIO14_EDGE_HIGH: u1, - GPIO15_LEVEL_LOW: u1, - GPIO15_LEVEL_HIGH: u1, - GPIO15_EDGE_LOW: u1, - GPIO15_EDGE_HIGH: u1, - }), base_address + 0x184); - - /// address: 0x40014188 - /// Interrupt status after masking & forcing for dormant_wake - pub const DORMANT_WAKE_INTS2 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO16_LEVEL_LOW: u1, - GPIO16_LEVEL_HIGH: u1, - GPIO16_EDGE_LOW: u1, - GPIO16_EDGE_HIGH: u1, - GPIO17_LEVEL_LOW: u1, - GPIO17_LEVEL_HIGH: u1, - GPIO17_EDGE_LOW: u1, - GPIO17_EDGE_HIGH: u1, - GPIO18_LEVEL_LOW: u1, - GPIO18_LEVEL_HIGH: u1, - GPIO18_EDGE_LOW: u1, - GPIO18_EDGE_HIGH: u1, - GPIO19_LEVEL_LOW: u1, - GPIO19_LEVEL_HIGH: u1, - GPIO19_EDGE_LOW: u1, - GPIO19_EDGE_HIGH: u1, - GPIO20_LEVEL_LOW: u1, - GPIO20_LEVEL_HIGH: u1, - GPIO20_EDGE_LOW: u1, - GPIO20_EDGE_HIGH: u1, - GPIO21_LEVEL_LOW: u1, - GPIO21_LEVEL_HIGH: u1, - GPIO21_EDGE_LOW: u1, - GPIO21_EDGE_HIGH: u1, - GPIO22_LEVEL_LOW: u1, - GPIO22_LEVEL_HIGH: u1, - GPIO22_EDGE_LOW: u1, - GPIO22_EDGE_HIGH: u1, - GPIO23_LEVEL_LOW: u1, - GPIO23_LEVEL_HIGH: u1, - GPIO23_EDGE_LOW: u1, - GPIO23_EDGE_HIGH: u1, - }), base_address + 0x188); - - /// address: 0x4001418c - /// Interrupt status after masking & forcing for dormant_wake - pub const DORMANT_WAKE_INTS3 = @intToPtr(*volatile Mmio(32, packed struct { - GPIO24_LEVEL_LOW: u1, - GPIO24_LEVEL_HIGH: u1, - GPIO24_EDGE_LOW: u1, - GPIO24_EDGE_HIGH: u1, - GPIO25_LEVEL_LOW: u1, - GPIO25_LEVEL_HIGH: u1, - GPIO25_EDGE_LOW: u1, - GPIO25_EDGE_HIGH: u1, - GPIO26_LEVEL_LOW: u1, - GPIO26_LEVEL_HIGH: u1, - GPIO26_EDGE_LOW: u1, - GPIO26_EDGE_HIGH: u1, - GPIO27_LEVEL_LOW: u1, - GPIO27_LEVEL_HIGH: u1, - GPIO27_EDGE_LOW: u1, - GPIO27_EDGE_HIGH: u1, - GPIO28_LEVEL_LOW: u1, - GPIO28_LEVEL_HIGH: u1, - GPIO28_EDGE_LOW: u1, - GPIO28_EDGE_HIGH: u1, - GPIO29_LEVEL_LOW: u1, - GPIO29_LEVEL_HIGH: u1, - GPIO29_EDGE_LOW: u1, - GPIO29_EDGE_HIGH: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x18c); - }; - pub const IO_QSPI = struct { - pub const base_address = 0x40018000; - pub const version = "1"; - - /// address: 0x40018000 - /// GPIO status - pub const GPIO_QSPI_SCLK_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x0); - - /// address: 0x40018004 - /// GPIO control including function select and overrides. - pub const GPIO_QSPI_SCLK_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0x4); - - /// address: 0x40018008 - /// GPIO status - pub const GPIO_QSPI_SS_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x8); - - /// address: 0x4001800c - /// GPIO control including function select and overrides. - pub const GPIO_QSPI_SS_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0xc); - - /// address: 0x40018010 - /// GPIO status - pub const GPIO_QSPI_SD0_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x10); - - /// address: 0x40018014 - /// GPIO control including function select and overrides. - pub const GPIO_QSPI_SD0_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0x14); - - /// address: 0x40018018 - /// GPIO status - pub const GPIO_QSPI_SD1_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x18); - - /// address: 0x4001801c - /// GPIO control including function select and overrides. - pub const GPIO_QSPI_SD1_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0x1c); - - /// address: 0x40018020 - /// GPIO status - pub const GPIO_QSPI_SD2_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x20); - - /// address: 0x40018024 - /// GPIO control including function select and overrides. - pub const GPIO_QSPI_SD2_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0x24); - - /// address: 0x40018028 - /// GPIO status - pub const GPIO_QSPI_SD3_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved13: u1 = 0, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved18: u1 = 0, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x28); - - /// address: 0x4001802c - /// GPIO control including function select and overrides. - pub const GPIO_QSPI_SD3_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// 0-31 -> selects pin function according to the gpio table\n - /// 31 == NULL - FUNCSEL: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - OUTOVER: u2, - reserved3: u1 = 0, - reserved4: u1 = 0, - OEOVER: u2, - reserved5: u1 = 0, - reserved6: u1 = 0, - INOVER: u2, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - IRQOVER: u2, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0x2c); - - /// address: 0x40018030 - /// Raw Interrupts - pub const INTR = @intToPtr(*volatile Mmio(32, packed struct { - GPIO_QSPI_SCLK_LEVEL_LOW: u1, - GPIO_QSPI_SCLK_LEVEL_HIGH: u1, - GPIO_QSPI_SCLK_EDGE_LOW: u1, - GPIO_QSPI_SCLK_EDGE_HIGH: u1, - GPIO_QSPI_SS_LEVEL_LOW: u1, - GPIO_QSPI_SS_LEVEL_HIGH: u1, - GPIO_QSPI_SS_EDGE_LOW: u1, - GPIO_QSPI_SS_EDGE_HIGH: u1, - GPIO_QSPI_SD0_LEVEL_LOW: u1, - GPIO_QSPI_SD0_LEVEL_HIGH: u1, - GPIO_QSPI_SD0_EDGE_LOW: u1, - GPIO_QSPI_SD0_EDGE_HIGH: u1, - GPIO_QSPI_SD1_LEVEL_LOW: u1, - GPIO_QSPI_SD1_LEVEL_HIGH: u1, - GPIO_QSPI_SD1_EDGE_LOW: u1, - GPIO_QSPI_SD1_EDGE_HIGH: u1, - GPIO_QSPI_SD2_LEVEL_LOW: u1, - GPIO_QSPI_SD2_LEVEL_HIGH: u1, - GPIO_QSPI_SD2_EDGE_LOW: u1, - GPIO_QSPI_SD2_EDGE_HIGH: u1, - GPIO_QSPI_SD3_LEVEL_LOW: u1, - GPIO_QSPI_SD3_LEVEL_HIGH: u1, - GPIO_QSPI_SD3_EDGE_LOW: u1, - GPIO_QSPI_SD3_EDGE_HIGH: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x30); - - /// address: 0x40018034 - /// Interrupt Enable for proc0 - pub const PROC0_INTE = @intToPtr(*volatile Mmio(32, packed struct { - GPIO_QSPI_SCLK_LEVEL_LOW: u1, - GPIO_QSPI_SCLK_LEVEL_HIGH: u1, - GPIO_QSPI_SCLK_EDGE_LOW: u1, - GPIO_QSPI_SCLK_EDGE_HIGH: u1, - GPIO_QSPI_SS_LEVEL_LOW: u1, - GPIO_QSPI_SS_LEVEL_HIGH: u1, - GPIO_QSPI_SS_EDGE_LOW: u1, - GPIO_QSPI_SS_EDGE_HIGH: u1, - GPIO_QSPI_SD0_LEVEL_LOW: u1, - GPIO_QSPI_SD0_LEVEL_HIGH: u1, - GPIO_QSPI_SD0_EDGE_LOW: u1, - GPIO_QSPI_SD0_EDGE_HIGH: u1, - GPIO_QSPI_SD1_LEVEL_LOW: u1, - GPIO_QSPI_SD1_LEVEL_HIGH: u1, - GPIO_QSPI_SD1_EDGE_LOW: u1, - GPIO_QSPI_SD1_EDGE_HIGH: u1, - GPIO_QSPI_SD2_LEVEL_LOW: u1, - GPIO_QSPI_SD2_LEVEL_HIGH: u1, - GPIO_QSPI_SD2_EDGE_LOW: u1, - GPIO_QSPI_SD2_EDGE_HIGH: u1, - GPIO_QSPI_SD3_LEVEL_LOW: u1, - GPIO_QSPI_SD3_LEVEL_HIGH: u1, - GPIO_QSPI_SD3_EDGE_LOW: u1, - GPIO_QSPI_SD3_EDGE_HIGH: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x34); - - /// address: 0x40018038 - /// Interrupt Force for proc0 - pub const PROC0_INTF = @intToPtr(*volatile Mmio(32, packed struct { - GPIO_QSPI_SCLK_LEVEL_LOW: u1, - GPIO_QSPI_SCLK_LEVEL_HIGH: u1, - GPIO_QSPI_SCLK_EDGE_LOW: u1, - GPIO_QSPI_SCLK_EDGE_HIGH: u1, - GPIO_QSPI_SS_LEVEL_LOW: u1, - GPIO_QSPI_SS_LEVEL_HIGH: u1, - GPIO_QSPI_SS_EDGE_LOW: u1, - GPIO_QSPI_SS_EDGE_HIGH: u1, - GPIO_QSPI_SD0_LEVEL_LOW: u1, - GPIO_QSPI_SD0_LEVEL_HIGH: u1, - GPIO_QSPI_SD0_EDGE_LOW: u1, - GPIO_QSPI_SD0_EDGE_HIGH: u1, - GPIO_QSPI_SD1_LEVEL_LOW: u1, - GPIO_QSPI_SD1_LEVEL_HIGH: u1, - GPIO_QSPI_SD1_EDGE_LOW: u1, - GPIO_QSPI_SD1_EDGE_HIGH: u1, - GPIO_QSPI_SD2_LEVEL_LOW: u1, - GPIO_QSPI_SD2_LEVEL_HIGH: u1, - GPIO_QSPI_SD2_EDGE_LOW: u1, - GPIO_QSPI_SD2_EDGE_HIGH: u1, - GPIO_QSPI_SD3_LEVEL_LOW: u1, - GPIO_QSPI_SD3_LEVEL_HIGH: u1, - GPIO_QSPI_SD3_EDGE_LOW: u1, - GPIO_QSPI_SD3_EDGE_HIGH: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x38); - - /// address: 0x4001803c - /// Interrupt status after masking & forcing for proc0 - pub const PROC0_INTS = @intToPtr(*volatile Mmio(32, packed struct { - GPIO_QSPI_SCLK_LEVEL_LOW: u1, - GPIO_QSPI_SCLK_LEVEL_HIGH: u1, - GPIO_QSPI_SCLK_EDGE_LOW: u1, - GPIO_QSPI_SCLK_EDGE_HIGH: u1, - GPIO_QSPI_SS_LEVEL_LOW: u1, - GPIO_QSPI_SS_LEVEL_HIGH: u1, - GPIO_QSPI_SS_EDGE_LOW: u1, - GPIO_QSPI_SS_EDGE_HIGH: u1, - GPIO_QSPI_SD0_LEVEL_LOW: u1, - GPIO_QSPI_SD0_LEVEL_HIGH: u1, - GPIO_QSPI_SD0_EDGE_LOW: u1, - GPIO_QSPI_SD0_EDGE_HIGH: u1, - GPIO_QSPI_SD1_LEVEL_LOW: u1, - GPIO_QSPI_SD1_LEVEL_HIGH: u1, - GPIO_QSPI_SD1_EDGE_LOW: u1, - GPIO_QSPI_SD1_EDGE_HIGH: u1, - GPIO_QSPI_SD2_LEVEL_LOW: u1, - GPIO_QSPI_SD2_LEVEL_HIGH: u1, - GPIO_QSPI_SD2_EDGE_LOW: u1, - GPIO_QSPI_SD2_EDGE_HIGH: u1, - GPIO_QSPI_SD3_LEVEL_LOW: u1, - GPIO_QSPI_SD3_LEVEL_HIGH: u1, - GPIO_QSPI_SD3_EDGE_LOW: u1, - GPIO_QSPI_SD3_EDGE_HIGH: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x3c); - - /// address: 0x40018040 - /// Interrupt Enable for proc1 - pub const PROC1_INTE = @intToPtr(*volatile Mmio(32, packed struct { - GPIO_QSPI_SCLK_LEVEL_LOW: u1, - GPIO_QSPI_SCLK_LEVEL_HIGH: u1, - GPIO_QSPI_SCLK_EDGE_LOW: u1, - GPIO_QSPI_SCLK_EDGE_HIGH: u1, - GPIO_QSPI_SS_LEVEL_LOW: u1, - GPIO_QSPI_SS_LEVEL_HIGH: u1, - GPIO_QSPI_SS_EDGE_LOW: u1, - GPIO_QSPI_SS_EDGE_HIGH: u1, - GPIO_QSPI_SD0_LEVEL_LOW: u1, - GPIO_QSPI_SD0_LEVEL_HIGH: u1, - GPIO_QSPI_SD0_EDGE_LOW: u1, - GPIO_QSPI_SD0_EDGE_HIGH: u1, - GPIO_QSPI_SD1_LEVEL_LOW: u1, - GPIO_QSPI_SD1_LEVEL_HIGH: u1, - GPIO_QSPI_SD1_EDGE_LOW: u1, - GPIO_QSPI_SD1_EDGE_HIGH: u1, - GPIO_QSPI_SD2_LEVEL_LOW: u1, - GPIO_QSPI_SD2_LEVEL_HIGH: u1, - GPIO_QSPI_SD2_EDGE_LOW: u1, - GPIO_QSPI_SD2_EDGE_HIGH: u1, - GPIO_QSPI_SD3_LEVEL_LOW: u1, - GPIO_QSPI_SD3_LEVEL_HIGH: u1, - GPIO_QSPI_SD3_EDGE_LOW: u1, - GPIO_QSPI_SD3_EDGE_HIGH: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x40); - - /// address: 0x40018044 - /// Interrupt Force for proc1 - pub const PROC1_INTF = @intToPtr(*volatile Mmio(32, packed struct { - GPIO_QSPI_SCLK_LEVEL_LOW: u1, - GPIO_QSPI_SCLK_LEVEL_HIGH: u1, - GPIO_QSPI_SCLK_EDGE_LOW: u1, - GPIO_QSPI_SCLK_EDGE_HIGH: u1, - GPIO_QSPI_SS_LEVEL_LOW: u1, - GPIO_QSPI_SS_LEVEL_HIGH: u1, - GPIO_QSPI_SS_EDGE_LOW: u1, - GPIO_QSPI_SS_EDGE_HIGH: u1, - GPIO_QSPI_SD0_LEVEL_LOW: u1, - GPIO_QSPI_SD0_LEVEL_HIGH: u1, - GPIO_QSPI_SD0_EDGE_LOW: u1, - GPIO_QSPI_SD0_EDGE_HIGH: u1, - GPIO_QSPI_SD1_LEVEL_LOW: u1, - GPIO_QSPI_SD1_LEVEL_HIGH: u1, - GPIO_QSPI_SD1_EDGE_LOW: u1, - GPIO_QSPI_SD1_EDGE_HIGH: u1, - GPIO_QSPI_SD2_LEVEL_LOW: u1, - GPIO_QSPI_SD2_LEVEL_HIGH: u1, - GPIO_QSPI_SD2_EDGE_LOW: u1, - GPIO_QSPI_SD2_EDGE_HIGH: u1, - GPIO_QSPI_SD3_LEVEL_LOW: u1, - GPIO_QSPI_SD3_LEVEL_HIGH: u1, - GPIO_QSPI_SD3_EDGE_LOW: u1, - GPIO_QSPI_SD3_EDGE_HIGH: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x44); - - /// address: 0x40018048 - /// Interrupt status after masking & forcing for proc1 - pub const PROC1_INTS = @intToPtr(*volatile Mmio(32, packed struct { - GPIO_QSPI_SCLK_LEVEL_LOW: u1, - GPIO_QSPI_SCLK_LEVEL_HIGH: u1, - GPIO_QSPI_SCLK_EDGE_LOW: u1, - GPIO_QSPI_SCLK_EDGE_HIGH: u1, - GPIO_QSPI_SS_LEVEL_LOW: u1, - GPIO_QSPI_SS_LEVEL_HIGH: u1, - GPIO_QSPI_SS_EDGE_LOW: u1, - GPIO_QSPI_SS_EDGE_HIGH: u1, - GPIO_QSPI_SD0_LEVEL_LOW: u1, - GPIO_QSPI_SD0_LEVEL_HIGH: u1, - GPIO_QSPI_SD0_EDGE_LOW: u1, - GPIO_QSPI_SD0_EDGE_HIGH: u1, - GPIO_QSPI_SD1_LEVEL_LOW: u1, - GPIO_QSPI_SD1_LEVEL_HIGH: u1, - GPIO_QSPI_SD1_EDGE_LOW: u1, - GPIO_QSPI_SD1_EDGE_HIGH: u1, - GPIO_QSPI_SD2_LEVEL_LOW: u1, - GPIO_QSPI_SD2_LEVEL_HIGH: u1, - GPIO_QSPI_SD2_EDGE_LOW: u1, - GPIO_QSPI_SD2_EDGE_HIGH: u1, - GPIO_QSPI_SD3_LEVEL_LOW: u1, - GPIO_QSPI_SD3_LEVEL_HIGH: u1, - GPIO_QSPI_SD3_EDGE_LOW: u1, - GPIO_QSPI_SD3_EDGE_HIGH: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x48); - - /// address: 0x4001804c - /// Interrupt Enable for dormant_wake - pub const DORMANT_WAKE_INTE = @intToPtr(*volatile Mmio(32, packed struct { - GPIO_QSPI_SCLK_LEVEL_LOW: u1, - GPIO_QSPI_SCLK_LEVEL_HIGH: u1, - GPIO_QSPI_SCLK_EDGE_LOW: u1, - GPIO_QSPI_SCLK_EDGE_HIGH: u1, - GPIO_QSPI_SS_LEVEL_LOW: u1, - GPIO_QSPI_SS_LEVEL_HIGH: u1, - GPIO_QSPI_SS_EDGE_LOW: u1, - GPIO_QSPI_SS_EDGE_HIGH: u1, - GPIO_QSPI_SD0_LEVEL_LOW: u1, - GPIO_QSPI_SD0_LEVEL_HIGH: u1, - GPIO_QSPI_SD0_EDGE_LOW: u1, - GPIO_QSPI_SD0_EDGE_HIGH: u1, - GPIO_QSPI_SD1_LEVEL_LOW: u1, - GPIO_QSPI_SD1_LEVEL_HIGH: u1, - GPIO_QSPI_SD1_EDGE_LOW: u1, - GPIO_QSPI_SD1_EDGE_HIGH: u1, - GPIO_QSPI_SD2_LEVEL_LOW: u1, - GPIO_QSPI_SD2_LEVEL_HIGH: u1, - GPIO_QSPI_SD2_EDGE_LOW: u1, - GPIO_QSPI_SD2_EDGE_HIGH: u1, - GPIO_QSPI_SD3_LEVEL_LOW: u1, - GPIO_QSPI_SD3_LEVEL_HIGH: u1, - GPIO_QSPI_SD3_EDGE_LOW: u1, - GPIO_QSPI_SD3_EDGE_HIGH: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x4c); - - /// address: 0x40018050 - /// Interrupt Force for dormant_wake - pub const DORMANT_WAKE_INTF = @intToPtr(*volatile Mmio(32, packed struct { - GPIO_QSPI_SCLK_LEVEL_LOW: u1, - GPIO_QSPI_SCLK_LEVEL_HIGH: u1, - GPIO_QSPI_SCLK_EDGE_LOW: u1, - GPIO_QSPI_SCLK_EDGE_HIGH: u1, - GPIO_QSPI_SS_LEVEL_LOW: u1, - GPIO_QSPI_SS_LEVEL_HIGH: u1, - GPIO_QSPI_SS_EDGE_LOW: u1, - GPIO_QSPI_SS_EDGE_HIGH: u1, - GPIO_QSPI_SD0_LEVEL_LOW: u1, - GPIO_QSPI_SD0_LEVEL_HIGH: u1, - GPIO_QSPI_SD0_EDGE_LOW: u1, - GPIO_QSPI_SD0_EDGE_HIGH: u1, - GPIO_QSPI_SD1_LEVEL_LOW: u1, - GPIO_QSPI_SD1_LEVEL_HIGH: u1, - GPIO_QSPI_SD1_EDGE_LOW: u1, - GPIO_QSPI_SD1_EDGE_HIGH: u1, - GPIO_QSPI_SD2_LEVEL_LOW: u1, - GPIO_QSPI_SD2_LEVEL_HIGH: u1, - GPIO_QSPI_SD2_EDGE_LOW: u1, - GPIO_QSPI_SD2_EDGE_HIGH: u1, - GPIO_QSPI_SD3_LEVEL_LOW: u1, - GPIO_QSPI_SD3_LEVEL_HIGH: u1, - GPIO_QSPI_SD3_EDGE_LOW: u1, - GPIO_QSPI_SD3_EDGE_HIGH: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x50); - - /// address: 0x40018054 - /// Interrupt status after masking & forcing for dormant_wake - pub const DORMANT_WAKE_INTS = @intToPtr(*volatile Mmio(32, packed struct { - GPIO_QSPI_SCLK_LEVEL_LOW: u1, - GPIO_QSPI_SCLK_LEVEL_HIGH: u1, - GPIO_QSPI_SCLK_EDGE_LOW: u1, - GPIO_QSPI_SCLK_EDGE_HIGH: u1, - GPIO_QSPI_SS_LEVEL_LOW: u1, - GPIO_QSPI_SS_LEVEL_HIGH: u1, - GPIO_QSPI_SS_EDGE_LOW: u1, - GPIO_QSPI_SS_EDGE_HIGH: u1, - GPIO_QSPI_SD0_LEVEL_LOW: u1, - GPIO_QSPI_SD0_LEVEL_HIGH: u1, - GPIO_QSPI_SD0_EDGE_LOW: u1, - GPIO_QSPI_SD0_EDGE_HIGH: u1, - GPIO_QSPI_SD1_LEVEL_LOW: u1, - GPIO_QSPI_SD1_LEVEL_HIGH: u1, - GPIO_QSPI_SD1_EDGE_LOW: u1, - GPIO_QSPI_SD1_EDGE_HIGH: u1, - GPIO_QSPI_SD2_LEVEL_LOW: u1, - GPIO_QSPI_SD2_LEVEL_HIGH: u1, - GPIO_QSPI_SD2_EDGE_LOW: u1, - GPIO_QSPI_SD2_EDGE_HIGH: u1, - GPIO_QSPI_SD3_LEVEL_LOW: u1, - GPIO_QSPI_SD3_LEVEL_HIGH: u1, - GPIO_QSPI_SD3_EDGE_LOW: u1, - GPIO_QSPI_SD3_EDGE_HIGH: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x54); - }; - pub const PADS_BANK0 = struct { - pub const base_address = 0x4001c000; - pub const version = "1"; - - /// address: 0x4001c000 - /// Voltage select. Per bank control - pub const VOLTAGE_SELECT = @intToPtr(*volatile MmioInt(32, u1), base_address + 0x0); - - /// address: 0x4001c004 - /// Pad control register - pub const GPIO0 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x4); - - /// address: 0x4001c008 - /// Pad control register - pub const GPIO1 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x8); - - /// address: 0x4001c00c - /// Pad control register - pub const GPIO2 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0xc); - - /// address: 0x4001c010 - /// Pad control register - pub const GPIO3 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x10); - - /// address: 0x4001c014 - /// Pad control register - pub const GPIO4 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x14); - - /// address: 0x4001c018 - /// Pad control register - pub const GPIO5 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x18); - - /// address: 0x4001c01c - /// Pad control register - pub const GPIO6 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x1c); - - /// address: 0x4001c020 - /// Pad control register - pub const GPIO7 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x20); - - /// address: 0x4001c024 - /// Pad control register - pub const GPIO8 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x24); - - /// address: 0x4001c028 - /// Pad control register - pub const GPIO9 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x28); - - /// address: 0x4001c02c - /// Pad control register - pub const GPIO10 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x2c); - - /// address: 0x4001c030 - /// Pad control register - pub const GPIO11 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x30); - - /// address: 0x4001c034 - /// Pad control register - pub const GPIO12 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x34); - - /// address: 0x4001c038 - /// Pad control register - pub const GPIO13 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x38); - - /// address: 0x4001c03c - /// Pad control register - pub const GPIO14 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x3c); - - /// address: 0x4001c040 - /// Pad control register - pub const GPIO15 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x40); - - /// address: 0x4001c044 - /// Pad control register - pub const GPIO16 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x44); - - /// address: 0x4001c048 - /// Pad control register - pub const GPIO17 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x48); - - /// address: 0x4001c04c - /// Pad control register - pub const GPIO18 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x4c); - - /// address: 0x4001c050 - /// Pad control register - pub const GPIO19 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x50); - - /// address: 0x4001c054 - /// Pad control register - pub const GPIO20 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x54); - - /// address: 0x4001c058 - /// Pad control register - pub const GPIO21 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x58); - - /// address: 0x4001c05c - /// Pad control register - pub const GPIO22 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x5c); - - /// address: 0x4001c060 - /// Pad control register - pub const GPIO23 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x60); - - /// address: 0x4001c064 - /// Pad control register - pub const GPIO24 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x64); - - /// address: 0x4001c068 - /// Pad control register - pub const GPIO25 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x68); - - /// address: 0x4001c06c - /// Pad control register - pub const GPIO26 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x6c); - - /// address: 0x4001c070 - /// Pad control register - pub const GPIO27 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x70); - - /// address: 0x4001c074 - /// Pad control register - pub const GPIO28 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x74); - - /// address: 0x4001c078 - /// Pad control register - pub const GPIO29 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x78); - - /// address: 0x4001c07c - /// Pad control register - pub const SWCLK = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x7c); - - /// address: 0x4001c080 - /// Pad control register - pub const SWD = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x80); - }; - pub const PADS_QSPI = struct { - pub const base_address = 0x40020000; - pub const version = "1"; - - /// address: 0x40020000 - /// Voltage select. Per bank control - pub const VOLTAGE_SELECT = @intToPtr(*volatile MmioInt(32, u1), base_address + 0x0); - - /// address: 0x40020004 - /// Pad control register - pub const GPIO_QSPI_SCLK = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x4); - - /// address: 0x40020008 - /// Pad control register - pub const GPIO_QSPI_SD0 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x8); - - /// address: 0x4002000c - /// Pad control register - pub const GPIO_QSPI_SD1 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0xc); - - /// address: 0x40020010 - /// Pad control register - pub const GPIO_QSPI_SD2 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x10); - - /// address: 0x40020014 - /// Pad control register - pub const GPIO_QSPI_SD3 = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x14); - - /// address: 0x40020018 - /// Pad control register - pub const GPIO_QSPI_SS = @intToPtr(*volatile Mmio(32, packed struct { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: u2, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x18); - }; - - /// Controls the crystal oscillator - pub const XOSC = struct { - pub const base_address = 0x40024000; - pub const version = "1"; - - /// address: 0x40024000 - /// Crystal Oscillator Control - pub const CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// Frequency range. This resets to 0xAA0 and cannot be changed. - FREQ_RANGE: u12, - /// On power-up this field is initialised to DISABLE and the chip runs from the - /// ROSC.\n - /// If the chip has subsequently been programmed to run from the XOSC then setting - /// this field to DISABLE may lock-up the chip. If this is a concern then run the - /// clk_ref from the ROSC and enable the clk_sys RESUS feature.\n - /// The 12-bit code is intended to give some protection against accidental writes. - /// An invalid setting will enable the oscillator. - ENABLE: u12, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x0); - - /// address: 0x40024004 - /// Crystal Oscillator Status - pub const STATUS = @intToPtr(*volatile Mmio(32, packed struct { - /// The current frequency range setting, always reads 0 - FREQ_RANGE: u2, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - /// Oscillator is enabled but not necessarily running and stable, resets to 0 - ENABLED: u1, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - reserved18: u1 = 0, - reserved19: u1 = 0, - reserved20: u1 = 0, - /// An invalid value has been written to CTRL_ENABLE or CTRL_FREQ_RANGE or DORMANT - BADWRITE: u1, - reserved21: u1 = 0, - reserved22: u1 = 0, - reserved23: u1 = 0, - reserved24: u1 = 0, - reserved25: u1 = 0, - reserved26: u1 = 0, - /// Oscillator is running and stable - STABLE: u1, - }), base_address + 0x4); - - /// address: 0x40024008 - /// Crystal Oscillator pause control\n - /// This is used to save power by pausing the XOSC\n - /// On power-up this field is initialised to WAKE\n - /// An invalid write will also select WAKE\n - /// WARNING: stop the PLLs before selecting dormant mode\n - /// WARNING: setup the irq before selecting dormant mode - pub const DORMANT = @intToPtr(*volatile u32, base_address + 0x8); - - /// address: 0x4002400c - /// Controls the startup delay - pub const STARTUP = @intToPtr(*volatile Mmio(32, packed struct { - /// in multiples of 256*xtal_period. The reset value of 0xc4 corresponds to approx - /// 50 000 cycles. - DELAY: u14, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - /// Multiplies the startup_delay by 4. This is of little value to the user given - /// that the delay can be programmed directly. - X4: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - }), base_address + 0xc); - - /// address: 0x4002401c - /// A down counter running at the xosc frequency which counts to zero and stops.\n - /// To start the counter write a non-zero value.\n - /// Can be used for short software pauses when setting up time sensitive hardware. - pub const COUNT = @intToPtr(*volatile MmioInt(32, u8), base_address + 0x1c); - }; - pub const PLL_SYS = struct { - pub const base_address = 0x40028000; - pub const version = "1"; - - /// address: 0x40028000 - /// Control and Status\n - /// GENERAL CONSTRAINTS:\n - /// Reference clock frequency min=5MHz, max=800MHz\n - /// Feedback divider min=16, max=320\n - /// VCO frequency min=400MHz, max=1600MHz - pub const CS = @intToPtr(*volatile Mmio(32, packed struct { - /// Divides the PLL input reference clock.\n - /// Behaviour is undefined for div=0.\n - /// PLL output will be unpredictable during refdiv changes, wait for lock=1 before - /// using it. - REFDIV: u6, - reserved0: u1 = 0, - reserved1: u1 = 0, - /// Passes the reference clock to the output instead of the divided VCO. The VCO - /// continues to run so the user can switch between the reference clock and the - /// divided VCO but the output will glitch when doing so. - BYPASS: u1, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - reserved18: u1 = 0, - reserved19: u1 = 0, - reserved20: u1 = 0, - reserved21: u1 = 0, - reserved22: u1 = 0, - reserved23: u1 = 0, - /// PLL is locked - LOCK: u1, - }), base_address + 0x0); - - /// address: 0x40028004 - /// Controls the PLL power modes. - pub const PWR = @intToPtr(*volatile Mmio(32, packed struct { - /// PLL powerdown\n - /// To save power set high when PLL output not required. - PD: u1, - reserved0: u1 = 0, - /// PLL DSM powerdown\n - /// Nothing is achieved by setting this low. - DSMPD: u1, - /// PLL post divider powerdown\n - /// To save power set high when PLL output not required or bypass=1. - POSTDIVPD: u1, - reserved1: u1 = 0, - /// PLL VCO powerdown\n - /// To save power set high when PLL output not required or bypass=1. - VCOPD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - }), base_address + 0x4); - - /// address: 0x40028008 - /// Feedback divisor\n - /// (note: this PLL does not support fractional division) - pub const FBDIV_INT = @intToPtr(*volatile MmioInt(32, u12), base_address + 0x8); - - /// address: 0x4002800c - /// Controls the PLL post dividers for the primary output\n - /// (note: this PLL does not have a secondary output)\n - /// the primary output is driven from VCO divided by postdiv1*postdiv2 - pub const PRIM = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - /// divide by 1-7 - POSTDIV2: u3, - reserved12: u1 = 0, - /// divide by 1-7 - POSTDIV1: u3, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - }), base_address + 0xc); - }; - pub const PLL_USB = struct { - pub const base_address = 0x4002c000; - - /// address: 0x4002c000 - /// Control and Status\n - /// GENERAL CONSTRAINTS:\n - /// Reference clock frequency min=5MHz, max=800MHz\n - /// Feedback divider min=16, max=320\n - /// VCO frequency min=400MHz, max=1600MHz - pub const CS = @intToPtr(*volatile Mmio(32, packed struct { - /// Divides the PLL input reference clock.\n - /// Behaviour is undefined for div=0.\n - /// PLL output will be unpredictable during refdiv changes, wait for lock=1 before - /// using it. - REFDIV: u6, - reserved0: u1 = 0, - reserved1: u1 = 0, - /// Passes the reference clock to the output instead of the divided VCO. The VCO - /// continues to run so the user can switch between the reference clock and the - /// divided VCO but the output will glitch when doing so. - BYPASS: u1, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - reserved18: u1 = 0, - reserved19: u1 = 0, - reserved20: u1 = 0, - reserved21: u1 = 0, - reserved22: u1 = 0, - reserved23: u1 = 0, - /// PLL is locked - LOCK: u1, - }), base_address + 0x0); - - /// address: 0x4002c004 - /// Controls the PLL power modes. - pub const PWR = @intToPtr(*volatile Mmio(32, packed struct { - /// PLL powerdown\n - /// To save power set high when PLL output not required. - PD: u1, - reserved0: u1 = 0, - /// PLL DSM powerdown\n - /// Nothing is achieved by setting this low. - DSMPD: u1, - /// PLL post divider powerdown\n - /// To save power set high when PLL output not required or bypass=1. - POSTDIVPD: u1, - reserved1: u1 = 0, - /// PLL VCO powerdown\n - /// To save power set high when PLL output not required or bypass=1. - VCOPD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - }), base_address + 0x4); - - /// address: 0x4002c008 - /// Feedback divisor\n - /// (note: this PLL does not support fractional division) - pub const FBDIV_INT = @intToPtr(*volatile MmioInt(32, u12), base_address + 0x8); - - /// address: 0x4002c00c - /// Controls the PLL post dividers for the primary output\n - /// (note: this PLL does not have a secondary output)\n - /// the primary output is driven from VCO divided by postdiv1*postdiv2 - pub const PRIM = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - /// divide by 1-7 - POSTDIV2: u3, - reserved12: u1 = 0, - /// divide by 1-7 - POSTDIV1: u3, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - }), base_address + 0xc); - }; - - /// Register block for busfabric control signals and performance counters - pub const BUSCTRL = struct { - pub const base_address = 0x40030000; - pub const version = "1"; - - /// address: 0x40030000 - /// Set the priority of each master for bus arbitration. - pub const BUS_PRIORITY = @intToPtr(*volatile Mmio(32, packed struct { - /// 0 - low priority, 1 - high priority - PROC0: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - /// 0 - low priority, 1 - high priority - PROC1: u1, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - /// 0 - low priority, 1 - high priority - DMA_R: u1, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - /// 0 - low priority, 1 - high priority - DMA_W: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - }), base_address + 0x0); - - /// address: 0x40030004 - /// Bus priority acknowledge - pub const BUS_PRIORITY_ACK = @intToPtr(*volatile MmioInt(32, u1), base_address + 0x4); - - /// address: 0x40030008 - /// Bus fabric performance counter 0 - pub const PERFCTR0 = @intToPtr(*volatile MmioInt(32, u24), base_address + 0x8); - - /// address: 0x4003000c - /// Bus fabric performance event select for PERFCTR0 - pub const PERFSEL0 = @intToPtr(*volatile MmioInt(32, u5), base_address + 0xc); - - /// address: 0x40030010 - /// Bus fabric performance counter 1 - pub const PERFCTR1 = @intToPtr(*volatile MmioInt(32, u24), base_address + 0x10); - - /// address: 0x40030014 - /// Bus fabric performance event select for PERFCTR1 - pub const PERFSEL1 = @intToPtr(*volatile MmioInt(32, u5), base_address + 0x14); - - /// address: 0x40030018 - /// Bus fabric performance counter 2 - pub const PERFCTR2 = @intToPtr(*volatile MmioInt(32, u24), base_address + 0x18); - - /// address: 0x4003001c - /// Bus fabric performance event select for PERFCTR2 - pub const PERFSEL2 = @intToPtr(*volatile MmioInt(32, u5), base_address + 0x1c); - - /// address: 0x40030020 - /// Bus fabric performance counter 3 - pub const PERFCTR3 = @intToPtr(*volatile MmioInt(32, u24), base_address + 0x20); - - /// address: 0x40030024 - /// Bus fabric performance event select for PERFCTR3 - pub const PERFSEL3 = @intToPtr(*volatile MmioInt(32, u5), base_address + 0x24); - }; - pub const UART0 = struct { - pub const base_address = 0x40034000; - pub const version = "1"; - - /// address: 0x40034000 - /// Data Register, UARTDR - pub const UARTDR = @intToPtr(*volatile Mmio(32, packed struct { - /// Receive (read) data character. Transmit (write) data character. - DATA: u8, - /// Framing error. When set to 1, it indicates that the received character did not - /// have a valid stop bit (a valid stop bit is 1). In FIFO mode, this error is - /// associated with the character at the top of the FIFO. - FE: u1, - /// Parity error. When set to 1, it indicates that the parity of the received data - /// character does not match the parity that the EPS and SPS bits in the Line - /// Control Register, UARTLCR_H. In FIFO mode, this error is associated with the - /// character at the top of the FIFO. - PE: u1, - /// Break error. This bit is set to 1 if a break condition was detected, indicating - /// that the received data input was held LOW for longer than a full-word - /// transmission time (defined as start, data, parity and stop bits). In FIFO mode, - /// this error is associated with the character at the top of the FIFO. When a break - /// occurs, only one 0 character is loaded into the FIFO. The next character is only - /// enabled after the receive data input goes to a 1 (marking state), and the next - /// valid start bit is received. - BE: u1, - /// Overrun error. This bit is set to 1 if data is received and the receive FIFO is - /// already full. This is cleared to 0 once there is an empty space in the FIFO and - /// a new character can be written to it. - OE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x0); - - /// address: 0x40034004 - /// Receive Status Register/Error Clear Register, UARTRSR/UARTECR - pub const UARTRSR = @intToPtr(*volatile Mmio(32, packed struct { - /// Framing error. When set to 1, it indicates that the received character did not - /// have a valid stop bit (a valid stop bit is 1). This bit is cleared to 0 by a - /// write to UARTECR. In FIFO mode, this error is associated with the character at - /// the top of the FIFO. - FE: u1, - /// Parity error. When set to 1, it indicates that the parity of the received data - /// character does not match the parity that the EPS and SPS bits in the Line - /// Control Register, UARTLCR_H. This bit is cleared to 0 by a write to UARTECR. In - /// FIFO mode, this error is associated with the character at the top of the FIFO. - PE: u1, - /// Break error. This bit is set to 1 if a break condition was detected, indicating - /// that the received data input was held LOW for longer than a full-word - /// transmission time (defined as start, data, parity, and stop bits). This bit is - /// cleared to 0 after a write to UARTECR. In FIFO mode, this error is associated - /// with the character at the top of the FIFO. When a break occurs, only one 0 - /// character is loaded into the FIFO. The next character is only enabled after the - /// receive data input goes to a 1 (marking state) and the next valid start bit is - /// received. - BE: u1, - /// Overrun error. This bit is set to 1 if data is received and the FIFO is already - /// full. This bit is cleared to 0 by a write to UARTECR. The FIFO contents remain - /// valid because no more data is written when the FIFO is full, only the contents - /// of the shift register are overwritten. The CPU must now read the data, to empty - /// the FIFO. - OE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - }), base_address + 0x4); - - /// address: 0x40034018 - /// Flag Register, UARTFR - pub const UARTFR = @intToPtr(*volatile Mmio(32, packed struct { - /// Clear to send. This bit is the complement of the UART clear to send, nUARTCTS, - /// modem status input. That is, the bit is 1 when nUARTCTS is LOW. - CTS: u1, - /// Data set ready. This bit is the complement of the UART data set ready, nUARTDSR, - /// modem status input. That is, the bit is 1 when nUARTDSR is LOW. - DSR: u1, - /// Data carrier detect. This bit is the complement of the UART data carrier detect, - /// nUARTDCD, modem status input. That is, the bit is 1 when nUARTDCD is LOW. - DCD: u1, - /// UART busy. If this bit is set to 1, the UART is busy transmitting data. This bit - /// remains set until the complete byte, including all the stop bits, has been sent - /// from the shift register. This bit is set as soon as the transmit FIFO becomes - /// non-empty, regardless of whether the UART is enabled or not. - BUSY: u1, - /// Receive FIFO empty. The meaning of this bit depends on the state of the FEN bit - /// in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the - /// receive holding register is empty. If the FIFO is enabled, the RXFE bit is set - /// when the receive FIFO is empty. - RXFE: u1, - /// Transmit FIFO full. The meaning of this bit depends on the state of the FEN bit - /// in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the - /// transmit holding register is full. If the FIFO is enabled, the TXFF bit is set - /// when the transmit FIFO is full. - TXFF: u1, - /// Receive FIFO full. The meaning of this bit depends on the state of the FEN bit - /// in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the - /// receive holding register is full. If the FIFO is enabled, the RXFF bit is set - /// when the receive FIFO is full. - RXFF: u1, - /// Transmit FIFO empty. The meaning of this bit depends on the state of the FEN bit - /// in the Line Control Register, UARTLCR_H. If the FIFO is disabled, this bit is - /// set when the transmit holding register is empty. If the FIFO is enabled, the - /// TXFE bit is set when the transmit FIFO is empty. This bit does not indicate if - /// there is data in the transmit shift register. - TXFE: u1, - /// Ring indicator. This bit is the complement of the UART ring indicator, nUARTRI, - /// modem status input. That is, the bit is 1 when nUARTRI is LOW. - RI: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - }), base_address + 0x18); - - /// address: 0x40034020 - /// IrDA Low-Power Counter Register, UARTILPR - pub const UARTILPR = @intToPtr(*volatile Mmio(32, packed struct { - /// 8-bit low-power divisor value. These bits are cleared to 0 at reset. - ILPDVSR: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x20); - - /// address: 0x40034024 - /// Integer Baud Rate Register, UARTIBRD - pub const UARTIBRD = @intToPtr(*volatile Mmio(32, packed struct { - /// The integer baud rate divisor. These bits are cleared to 0 on reset. - BAUD_DIVINT: u16, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - }), base_address + 0x24); - - /// address: 0x40034028 - /// Fractional Baud Rate Register, UARTFBRD - pub const UARTFBRD = @intToPtr(*volatile Mmio(32, packed struct { - /// The fractional baud rate divisor. These bits are cleared to 0 on reset. - BAUD_DIVFRAC: u6, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - }), base_address + 0x28); - - /// address: 0x4003402c - /// Line Control Register, UARTLCR_H - pub const UARTLCR_H = @intToPtr(*volatile Mmio(32, packed struct { - /// Send break. If this bit is set to 1, a low-level is continually output on the - /// UARTTXD output, after completing transmission of the current character. For the - /// proper execution of the break command, the software must set this bit for at - /// least two complete frames. For normal use, this bit must be cleared to 0. - BRK: u1, - /// Parity enable: 0 = parity is disabled and no parity bit added to the data frame - /// 1 = parity checking and generation is enabled. - PEN: u1, - /// Even parity select. Controls the type of parity the UART uses during - /// transmission and reception: 0 = odd parity. The UART generates or checks for an - /// odd number of 1s in the data and parity bits. 1 = even parity. The UART - /// generates or checks for an even number of 1s in the data and parity bits. This - /// bit has no effect when the PEN bit disables parity checking and generation. - EPS: u1, - /// Two stop bits select. If this bit is set to 1, two stop bits are transmitted at - /// the end of the frame. The receive logic does not check for two stop bits being - /// received. - STP2: u1, - /// Enable FIFOs: 0 = FIFOs are disabled (character mode) that is, the FIFOs become - /// 1-byte-deep holding registers 1 = transmit and receive FIFO buffers are enabled - /// (FIFO mode). - FEN: u1, - /// Word length. These bits indicate the number of data bits transmitted or received - /// in a frame as follows: b11 = 8 bits b10 = 7 bits b01 = 6 bits b00 = 5 bits. - WLEN: u2, - /// Stick parity select. 0 = stick parity is disabled 1 = either: * if the EPS bit - /// is 0 then the parity bit is transmitted and checked as a 1 * if the EPS bit is 1 - /// then the parity bit is transmitted and checked as a 0. This bit has no effect - /// when the PEN bit disables parity checking and generation. - SPS: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x2c); - - /// address: 0x40034030 - /// Control Register, UARTCR - pub const UARTCR = @intToPtr(*volatile Mmio(32, packed struct { - /// UART enable: 0 = UART is disabled. If the UART is disabled in the middle of - /// transmission or reception, it completes the current character before stopping. 1 - /// = the UART is enabled. Data transmission and reception occurs for either UART - /// signals or SIR signals depending on the setting of the SIREN bit. - UARTEN: u1, - /// SIR enable: 0 = IrDA SIR ENDEC is disabled. nSIROUT remains LOW (no light pulse - /// generated), and signal transitions on SIRIN have no effect. 1 = IrDA SIR ENDEC - /// is enabled. Data is transmitted and received on nSIROUT and SIRIN. UARTTXD - /// remains HIGH, in the marking state. Signal transitions on UARTRXD or modem - /// status inputs have no effect. This bit has no effect if the UARTEN bit disables - /// the UART. - SIREN: u1, - /// SIR low-power IrDA mode. This bit selects the IrDA encoding mode. If this bit is - /// cleared to 0, low-level bits are transmitted as an active high pulse with a - /// width of 3 / 16th of the bit period. If this bit is set to 1, low-level bits are - /// transmitted with a pulse width that is 3 times the period of the IrLPBaud16 - /// input signal, regardless of the selected bit rate. Setting this bit uses less - /// power, but might reduce transmission distances. - SIRLP: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - /// Loopback enable. If this bit is set to 1 and the SIREN bit is set to 1 and the - /// SIRTEST bit in the Test Control Register, UARTTCR is set to 1, then the nSIROUT - /// path is inverted, and fed through to the SIRIN path. The SIRTEST bit in the test - /// register must be set to 1 to override the normal half-duplex SIR operation. This - /// must be the requirement for accessing the test registers during normal - /// operation, and SIRTEST must be cleared to 0 when loopback testing is finished. - /// This feature reduces the amount of external coupling required during system - /// test. If this bit is set to 1, and the SIRTEST bit is set to 0, the UARTTXD path - /// is fed through to the UARTRXD path. In either SIR mode or UART mode, when this - /// bit is set, the modem outputs are also fed through to the modem inputs. This bit - /// is cleared to 0 on reset, to disable loopback. - LBE: u1, - /// Transmit enable. If this bit is set to 1, the transmit section of the UART is - /// enabled. Data transmission occurs for either UART signals, or SIR signals - /// depending on the setting of the SIREN bit. When the UART is disabled in the - /// middle of transmission, it completes the current character before stopping. - TXE: u1, - /// Receive enable. If this bit is set to 1, the receive section of the UART is - /// enabled. Data reception occurs for either UART signals or SIR signals depending - /// on the setting of the SIREN bit. When the UART is disabled in the middle of - /// reception, it completes the current character before stopping. - RXE: u1, - /// Data transmit ready. This bit is the complement of the UART data transmit ready, - /// nUARTDTR, modem status output. That is, when the bit is programmed to a 1 then - /// nUARTDTR is LOW. - DTR: u1, - /// Request to send. This bit is the complement of the UART request to send, - /// nUARTRTS, modem status output. That is, when the bit is programmed to a 1 then - /// nUARTRTS is LOW. - RTS: u1, - /// This bit is the complement of the UART Out1 (nUARTOut1) modem status output. - /// That is, when the bit is programmed to a 1 the output is 0. For DTE this can be - /// used as Data Carrier Detect (DCD). - OUT1: u1, - /// This bit is the complement of the UART Out2 (nUARTOut2) modem status output. - /// That is, when the bit is programmed to a 1, the output is 0. For DTE this can be - /// used as Ring Indicator (RI). - OUT2: u1, - /// RTS hardware flow control enable. If this bit is set to 1, RTS hardware flow - /// control is enabled. Data is only requested when there is space in the receive - /// FIFO for it to be received. - RTSEN: u1, - /// CTS hardware flow control enable. If this bit is set to 1, CTS hardware flow - /// control is enabled. Data is only transmitted when the nUARTCTS signal is - /// asserted. - CTSEN: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - }), base_address + 0x30); - - /// address: 0x40034034 - /// Interrupt FIFO Level Select Register, UARTIFLS - pub const UARTIFLS = @intToPtr(*volatile Mmio(32, packed struct { - /// Transmit interrupt FIFO level select. The trigger points for the transmit - /// interrupt are as follows: b000 = Transmit FIFO becomes <= 1 / 8 full b001 = - /// Transmit FIFO becomes <= 1 / 4 full b010 = Transmit FIFO becomes <= 1 / 2 full - /// b011 = Transmit FIFO becomes <= 3 / 4 full b100 = Transmit FIFO becomes <= 7 / 8 - /// full b101-b111 = reserved. - TXIFLSEL: u3, - /// Receive interrupt FIFO level select. The trigger points for the receive - /// interrupt are as follows: b000 = Receive FIFO becomes >= 1 / 8 full b001 = - /// Receive FIFO becomes >= 1 / 4 full b010 = Receive FIFO becomes >= 1 / 2 full - /// b011 = Receive FIFO becomes >= 3 / 4 full b100 = Receive FIFO becomes >= 7 / 8 - /// full b101-b111 = reserved. - RXIFLSEL: u3, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - }), base_address + 0x34); - - /// address: 0x40034038 - /// Interrupt Mask Set/Clear Register, UARTIMSC - pub const UARTIMSC = @intToPtr(*volatile Mmio(32, packed struct { - /// nUARTRI modem interrupt mask. A read returns the current mask for the UARTRIINTR - /// interrupt. On a write of 1, the mask of the UARTRIINTR interrupt is set. A write - /// of 0 clears the mask. - RIMIM: u1, - /// nUARTCTS modem interrupt mask. A read returns the current mask for the - /// UARTCTSINTR interrupt. On a write of 1, the mask of the UARTCTSINTR interrupt is - /// set. A write of 0 clears the mask. - CTSMIM: u1, - /// nUARTDCD modem interrupt mask. A read returns the current mask for the - /// UARTDCDINTR interrupt. On a write of 1, the mask of the UARTDCDINTR interrupt is - /// set. A write of 0 clears the mask. - DCDMIM: u1, - /// nUARTDSR modem interrupt mask. A read returns the current mask for the - /// UARTDSRINTR interrupt. On a write of 1, the mask of the UARTDSRINTR interrupt is - /// set. A write of 0 clears the mask. - DSRMIM: u1, - /// Receive interrupt mask. A read returns the current mask for the UARTRXINTR - /// interrupt. On a write of 1, the mask of the UARTRXINTR interrupt is set. A write - /// of 0 clears the mask. - RXIM: u1, - /// Transmit interrupt mask. A read returns the current mask for the UARTTXINTR - /// interrupt. On a write of 1, the mask of the UARTTXINTR interrupt is set. A write - /// of 0 clears the mask. - TXIM: u1, - /// Receive timeout interrupt mask. A read returns the current mask for the - /// UARTRTINTR interrupt. On a write of 1, the mask of the UARTRTINTR interrupt is - /// set. A write of 0 clears the mask. - RTIM: u1, - /// Framing error interrupt mask. A read returns the current mask for the UARTFEINTR - /// interrupt. On a write of 1, the mask of the UARTFEINTR interrupt is set. A write - /// of 0 clears the mask. - FEIM: u1, - /// Parity error interrupt mask. A read returns the current mask for the UARTPEINTR - /// interrupt. On a write of 1, the mask of the UARTPEINTR interrupt is set. A write - /// of 0 clears the mask. - PEIM: u1, - /// Break error interrupt mask. A read returns the current mask for the UARTBEINTR - /// interrupt. On a write of 1, the mask of the UARTBEINTR interrupt is set. A write - /// of 0 clears the mask. - BEIM: u1, - /// Overrun error interrupt mask. A read returns the current mask for the UARTOEINTR - /// interrupt. On a write of 1, the mask of the UARTOEINTR interrupt is set. A write - /// of 0 clears the mask. - OEIM: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - }), base_address + 0x38); - - /// address: 0x4003403c - /// Raw Interrupt Status Register, UARTRIS - pub const UARTRIS = @intToPtr(*volatile Mmio(32, packed struct { - /// nUARTRI modem interrupt status. Returns the raw interrupt state of the - /// UARTRIINTR interrupt. - RIRMIS: u1, - /// nUARTCTS modem interrupt status. Returns the raw interrupt state of the - /// UARTCTSINTR interrupt. - CTSRMIS: u1, - /// nUARTDCD modem interrupt status. Returns the raw interrupt state of the - /// UARTDCDINTR interrupt. - DCDRMIS: u1, - /// nUARTDSR modem interrupt status. Returns the raw interrupt state of the - /// UARTDSRINTR interrupt. - DSRRMIS: u1, - /// Receive interrupt status. Returns the raw interrupt state of the UARTRXINTR - /// interrupt. - RXRIS: u1, - /// Transmit interrupt status. Returns the raw interrupt state of the UARTTXINTR - /// interrupt. - TXRIS: u1, - /// Receive timeout interrupt status. Returns the raw interrupt state of the - /// UARTRTINTR interrupt. a - RTRIS: u1, - /// Framing error interrupt status. Returns the raw interrupt state of the - /// UARTFEINTR interrupt. - FERIS: u1, - /// Parity error interrupt status. Returns the raw interrupt state of the UARTPEINTR - /// interrupt. - PERIS: u1, - /// Break error interrupt status. Returns the raw interrupt state of the UARTBEINTR - /// interrupt. - BERIS: u1, - /// Overrun error interrupt status. Returns the raw interrupt state of the - /// UARTOEINTR interrupt. - OERIS: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - }), base_address + 0x3c); - - /// address: 0x40034040 - /// Masked Interrupt Status Register, UARTMIS - pub const UARTMIS = @intToPtr(*volatile Mmio(32, packed struct { - /// nUARTRI modem masked interrupt status. Returns the masked interrupt state of the - /// UARTRIINTR interrupt. - RIMMIS: u1, - /// nUARTCTS modem masked interrupt status. Returns the masked interrupt state of - /// the UARTCTSINTR interrupt. - CTSMMIS: u1, - /// nUARTDCD modem masked interrupt status. Returns the masked interrupt state of - /// the UARTDCDINTR interrupt. - DCDMMIS: u1, - /// nUARTDSR modem masked interrupt status. Returns the masked interrupt state of - /// the UARTDSRINTR interrupt. - DSRMMIS: u1, - /// Receive masked interrupt status. Returns the masked interrupt state of the - /// UARTRXINTR interrupt. - RXMIS: u1, - /// Transmit masked interrupt status. Returns the masked interrupt state of the - /// UARTTXINTR interrupt. - TXMIS: u1, - /// Receive timeout masked interrupt status. Returns the masked interrupt state of - /// the UARTRTINTR interrupt. - RTMIS: u1, - /// Framing error masked interrupt status. Returns the masked interrupt state of the - /// UARTFEINTR interrupt. - FEMIS: u1, - /// Parity error masked interrupt status. Returns the masked interrupt state of the - /// UARTPEINTR interrupt. - PEMIS: u1, - /// Break error masked interrupt status. Returns the masked interrupt state of the - /// UARTBEINTR interrupt. - BEMIS: u1, - /// Overrun error masked interrupt status. Returns the masked interrupt state of the - /// UARTOEINTR interrupt. - OEMIS: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - }), base_address + 0x40); - - /// address: 0x40034044 - /// Interrupt Clear Register, UARTICR - pub const UARTICR = @intToPtr(*volatile Mmio(32, packed struct { - /// nUARTRI modem interrupt clear. Clears the UARTRIINTR interrupt. - RIMIC: u1, - /// nUARTCTS modem interrupt clear. Clears the UARTCTSINTR interrupt. - CTSMIC: u1, - /// nUARTDCD modem interrupt clear. Clears the UARTDCDINTR interrupt. - DCDMIC: u1, - /// nUARTDSR modem interrupt clear. Clears the UARTDSRINTR interrupt. - DSRMIC: u1, - /// Receive interrupt clear. Clears the UARTRXINTR interrupt. - RXIC: u1, - /// Transmit interrupt clear. Clears the UARTTXINTR interrupt. - TXIC: u1, - /// Receive timeout interrupt clear. Clears the UARTRTINTR interrupt. - RTIC: u1, - /// Framing error interrupt clear. Clears the UARTFEINTR interrupt. - FEIC: u1, - /// Parity error interrupt clear. Clears the UARTPEINTR interrupt. - PEIC: u1, - /// Break error interrupt clear. Clears the UARTBEINTR interrupt. - BEIC: u1, - /// Overrun error interrupt clear. Clears the UARTOEINTR interrupt. - OEIC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - }), base_address + 0x44); - - /// address: 0x40034048 - /// DMA Control Register, UARTDMACR - pub const UARTDMACR = @intToPtr(*volatile Mmio(32, packed struct { - /// Receive DMA enable. If this bit is set to 1, DMA for the receive FIFO is - /// enabled. - RXDMAE: u1, - /// Transmit DMA enable. If this bit is set to 1, DMA for the transmit FIFO is - /// enabled. - TXDMAE: u1, - /// DMA on error. If this bit is set to 1, the DMA receive request outputs, - /// UARTRXDMASREQ or UARTRXDMABREQ, are disabled when the UART error interrupt is - /// asserted. - DMAONERR: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - }), base_address + 0x48); - - /// address: 0x40034fe0 - /// UARTPeriphID0 Register - pub const UARTPERIPHID0 = @intToPtr(*volatile Mmio(32, packed struct { - /// These bits read back as 0x11 - PARTNUMBER0: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0xfe0); - - /// address: 0x40034fe4 - /// UARTPeriphID1 Register - pub const UARTPERIPHID1 = @intToPtr(*volatile Mmio(32, packed struct { - /// These bits read back as 0x0 - PARTNUMBER1: u4, - /// These bits read back as 0x1 - DESIGNER0: u4, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0xfe4); - - /// address: 0x40034fe8 - /// UARTPeriphID2 Register - pub const UARTPERIPHID2 = @intToPtr(*volatile Mmio(32, packed struct { - /// These bits read back as 0x4 - DESIGNER1: u4, - /// This field depends on the revision of the UART: r1p0 0x0 r1p1 0x1 r1p3 0x2 r1p4 - /// 0x2 r1p5 0x3 - REVISION: u4, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0xfe8); - - /// address: 0x40034fec - /// UARTPeriphID3 Register - pub const UARTPERIPHID3 = @intToPtr(*volatile Mmio(32, packed struct { - /// These bits read back as 0x00 - CONFIGURATION: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0xfec); - - /// address: 0x40034ff0 - /// UARTPCellID0 Register - pub const UARTPCELLID0 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xff0); - - /// address: 0x40034ff4 - /// UARTPCellID1 Register - pub const UARTPCELLID1 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xff4); - - /// address: 0x40034ff8 - /// UARTPCellID2 Register - pub const UARTPCELLID2 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xff8); - - /// address: 0x40034ffc - /// UARTPCellID3 Register - pub const UARTPCELLID3 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xffc); - }; - pub const UART1 = struct { - pub const base_address = 0x40038000; - - /// address: 0x40038000 - /// Data Register, UARTDR - pub const UARTDR = @intToPtr(*volatile Mmio(32, packed struct { - /// Receive (read) data character. Transmit (write) data character. - DATA: u8, - /// Framing error. When set to 1, it indicates that the received character did not - /// have a valid stop bit (a valid stop bit is 1). In FIFO mode, this error is - /// associated with the character at the top of the FIFO. - FE: u1, - /// Parity error. When set to 1, it indicates that the parity of the received data - /// character does not match the parity that the EPS and SPS bits in the Line - /// Control Register, UARTLCR_H. In FIFO mode, this error is associated with the - /// character at the top of the FIFO. - PE: u1, - /// Break error. This bit is set to 1 if a break condition was detected, indicating - /// that the received data input was held LOW for longer than a full-word - /// transmission time (defined as start, data, parity and stop bits). In FIFO mode, - /// this error is associated with the character at the top of the FIFO. When a break - /// occurs, only one 0 character is loaded into the FIFO. The next character is only - /// enabled after the receive data input goes to a 1 (marking state), and the next - /// valid start bit is received. - BE: u1, - /// Overrun error. This bit is set to 1 if data is received and the receive FIFO is - /// already full. This is cleared to 0 once there is an empty space in the FIFO and - /// a new character can be written to it. - OE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x0); - - /// address: 0x40038004 - /// Receive Status Register/Error Clear Register, UARTRSR/UARTECR - pub const UARTRSR = @intToPtr(*volatile Mmio(32, packed struct { - /// Framing error. When set to 1, it indicates that the received character did not - /// have a valid stop bit (a valid stop bit is 1). This bit is cleared to 0 by a - /// write to UARTECR. In FIFO mode, this error is associated with the character at - /// the top of the FIFO. - FE: u1, - /// Parity error. When set to 1, it indicates that the parity of the received data - /// character does not match the parity that the EPS and SPS bits in the Line - /// Control Register, UARTLCR_H. This bit is cleared to 0 by a write to UARTECR. In - /// FIFO mode, this error is associated with the character at the top of the FIFO. - PE: u1, - /// Break error. This bit is set to 1 if a break condition was detected, indicating - /// that the received data input was held LOW for longer than a full-word - /// transmission time (defined as start, data, parity, and stop bits). This bit is - /// cleared to 0 after a write to UARTECR. In FIFO mode, this error is associated - /// with the character at the top of the FIFO. When a break occurs, only one 0 - /// character is loaded into the FIFO. The next character is only enabled after the - /// receive data input goes to a 1 (marking state) and the next valid start bit is - /// received. - BE: u1, - /// Overrun error. This bit is set to 1 if data is received and the FIFO is already - /// full. This bit is cleared to 0 by a write to UARTECR. The FIFO contents remain - /// valid because no more data is written when the FIFO is full, only the contents - /// of the shift register are overwritten. The CPU must now read the data, to empty - /// the FIFO. - OE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - }), base_address + 0x4); - - /// address: 0x40038018 - /// Flag Register, UARTFR - pub const UARTFR = @intToPtr(*volatile Mmio(32, packed struct { - /// Clear to send. This bit is the complement of the UART clear to send, nUARTCTS, - /// modem status input. That is, the bit is 1 when nUARTCTS is LOW. - CTS: u1, - /// Data set ready. This bit is the complement of the UART data set ready, nUARTDSR, - /// modem status input. That is, the bit is 1 when nUARTDSR is LOW. - DSR: u1, - /// Data carrier detect. This bit is the complement of the UART data carrier detect, - /// nUARTDCD, modem status input. That is, the bit is 1 when nUARTDCD is LOW. - DCD: u1, - /// UART busy. If this bit is set to 1, the UART is busy transmitting data. This bit - /// remains set until the complete byte, including all the stop bits, has been sent - /// from the shift register. This bit is set as soon as the transmit FIFO becomes - /// non-empty, regardless of whether the UART is enabled or not. - BUSY: u1, - /// Receive FIFO empty. The meaning of this bit depends on the state of the FEN bit - /// in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the - /// receive holding register is empty. If the FIFO is enabled, the RXFE bit is set - /// when the receive FIFO is empty. - RXFE: u1, - /// Transmit FIFO full. The meaning of this bit depends on the state of the FEN bit - /// in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the - /// transmit holding register is full. If the FIFO is enabled, the TXFF bit is set - /// when the transmit FIFO is full. - TXFF: u1, - /// Receive FIFO full. The meaning of this bit depends on the state of the FEN bit - /// in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the - /// receive holding register is full. If the FIFO is enabled, the RXFF bit is set - /// when the receive FIFO is full. - RXFF: u1, - /// Transmit FIFO empty. The meaning of this bit depends on the state of the FEN bit - /// in the Line Control Register, UARTLCR_H. If the FIFO is disabled, this bit is - /// set when the transmit holding register is empty. If the FIFO is enabled, the - /// TXFE bit is set when the transmit FIFO is empty. This bit does not indicate if - /// there is data in the transmit shift register. - TXFE: u1, - /// Ring indicator. This bit is the complement of the UART ring indicator, nUARTRI, - /// modem status input. That is, the bit is 1 when nUARTRI is LOW. - RI: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - }), base_address + 0x18); - - /// address: 0x40038020 - /// IrDA Low-Power Counter Register, UARTILPR - pub const UARTILPR = @intToPtr(*volatile Mmio(32, packed struct { - /// 8-bit low-power divisor value. These bits are cleared to 0 at reset. - ILPDVSR: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x20); - - /// address: 0x40038024 - /// Integer Baud Rate Register, UARTIBRD - pub const UARTIBRD = @intToPtr(*volatile Mmio(32, packed struct { - /// The integer baud rate divisor. These bits are cleared to 0 on reset. - BAUD_DIVINT: u16, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - }), base_address + 0x24); - - /// address: 0x40038028 - /// Fractional Baud Rate Register, UARTFBRD - pub const UARTFBRD = @intToPtr(*volatile Mmio(32, packed struct { - /// The fractional baud rate divisor. These bits are cleared to 0 on reset. - BAUD_DIVFRAC: u6, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - }), base_address + 0x28); - - /// address: 0x4003802c - /// Line Control Register, UARTLCR_H - pub const UARTLCR_H = @intToPtr(*volatile Mmio(32, packed struct { - /// Send break. If this bit is set to 1, a low-level is continually output on the - /// UARTTXD output, after completing transmission of the current character. For the - /// proper execution of the break command, the software must set this bit for at - /// least two complete frames. For normal use, this bit must be cleared to 0. - BRK: u1, - /// Parity enable: 0 = parity is disabled and no parity bit added to the data frame - /// 1 = parity checking and generation is enabled. - PEN: u1, - /// Even parity select. Controls the type of parity the UART uses during - /// transmission and reception: 0 = odd parity. The UART generates or checks for an - /// odd number of 1s in the data and parity bits. 1 = even parity. The UART - /// generates or checks for an even number of 1s in the data and parity bits. This - /// bit has no effect when the PEN bit disables parity checking and generation. - EPS: u1, - /// Two stop bits select. If this bit is set to 1, two stop bits are transmitted at - /// the end of the frame. The receive logic does not check for two stop bits being - /// received. - STP2: u1, - /// Enable FIFOs: 0 = FIFOs are disabled (character mode) that is, the FIFOs become - /// 1-byte-deep holding registers 1 = transmit and receive FIFO buffers are enabled - /// (FIFO mode). - FEN: u1, - /// Word length. These bits indicate the number of data bits transmitted or received - /// in a frame as follows: b11 = 8 bits b10 = 7 bits b01 = 6 bits b00 = 5 bits. - WLEN: u2, - /// Stick parity select. 0 = stick parity is disabled 1 = either: * if the EPS bit - /// is 0 then the parity bit is transmitted and checked as a 1 * if the EPS bit is 1 - /// then the parity bit is transmitted and checked as a 0. This bit has no effect - /// when the PEN bit disables parity checking and generation. - SPS: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x2c); - - /// address: 0x40038030 - /// Control Register, UARTCR - pub const UARTCR = @intToPtr(*volatile Mmio(32, packed struct { - /// UART enable: 0 = UART is disabled. If the UART is disabled in the middle of - /// transmission or reception, it completes the current character before stopping. 1 - /// = the UART is enabled. Data transmission and reception occurs for either UART - /// signals or SIR signals depending on the setting of the SIREN bit. - UARTEN: u1, - /// SIR enable: 0 = IrDA SIR ENDEC is disabled. nSIROUT remains LOW (no light pulse - /// generated), and signal transitions on SIRIN have no effect. 1 = IrDA SIR ENDEC - /// is enabled. Data is transmitted and received on nSIROUT and SIRIN. UARTTXD - /// remains HIGH, in the marking state. Signal transitions on UARTRXD or modem - /// status inputs have no effect. This bit has no effect if the UARTEN bit disables - /// the UART. - SIREN: u1, - /// SIR low-power IrDA mode. This bit selects the IrDA encoding mode. If this bit is - /// cleared to 0, low-level bits are transmitted as an active high pulse with a - /// width of 3 / 16th of the bit period. If this bit is set to 1, low-level bits are - /// transmitted with a pulse width that is 3 times the period of the IrLPBaud16 - /// input signal, regardless of the selected bit rate. Setting this bit uses less - /// power, but might reduce transmission distances. - SIRLP: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - /// Loopback enable. If this bit is set to 1 and the SIREN bit is set to 1 and the - /// SIRTEST bit in the Test Control Register, UARTTCR is set to 1, then the nSIROUT - /// path is inverted, and fed through to the SIRIN path. The SIRTEST bit in the test - /// register must be set to 1 to override the normal half-duplex SIR operation. This - /// must be the requirement for accessing the test registers during normal - /// operation, and SIRTEST must be cleared to 0 when loopback testing is finished. - /// This feature reduces the amount of external coupling required during system - /// test. If this bit is set to 1, and the SIRTEST bit is set to 0, the UARTTXD path - /// is fed through to the UARTRXD path. In either SIR mode or UART mode, when this - /// bit is set, the modem outputs are also fed through to the modem inputs. This bit - /// is cleared to 0 on reset, to disable loopback. - LBE: u1, - /// Transmit enable. If this bit is set to 1, the transmit section of the UART is - /// enabled. Data transmission occurs for either UART signals, or SIR signals - /// depending on the setting of the SIREN bit. When the UART is disabled in the - /// middle of transmission, it completes the current character before stopping. - TXE: u1, - /// Receive enable. If this bit is set to 1, the receive section of the UART is - /// enabled. Data reception occurs for either UART signals or SIR signals depending - /// on the setting of the SIREN bit. When the UART is disabled in the middle of - /// reception, it completes the current character before stopping. - RXE: u1, - /// Data transmit ready. This bit is the complement of the UART data transmit ready, - /// nUARTDTR, modem status output. That is, when the bit is programmed to a 1 then - /// nUARTDTR is LOW. - DTR: u1, - /// Request to send. This bit is the complement of the UART request to send, - /// nUARTRTS, modem status output. That is, when the bit is programmed to a 1 then - /// nUARTRTS is LOW. - RTS: u1, - /// This bit is the complement of the UART Out1 (nUARTOut1) modem status output. - /// That is, when the bit is programmed to a 1 the output is 0. For DTE this can be - /// used as Data Carrier Detect (DCD). - OUT1: u1, - /// This bit is the complement of the UART Out2 (nUARTOut2) modem status output. - /// That is, when the bit is programmed to a 1, the output is 0. For DTE this can be - /// used as Ring Indicator (RI). - OUT2: u1, - /// RTS hardware flow control enable. If this bit is set to 1, RTS hardware flow - /// control is enabled. Data is only requested when there is space in the receive - /// FIFO for it to be received. - RTSEN: u1, - /// CTS hardware flow control enable. If this bit is set to 1, CTS hardware flow - /// control is enabled. Data is only transmitted when the nUARTCTS signal is - /// asserted. - CTSEN: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - }), base_address + 0x30); - - /// address: 0x40038034 - /// Interrupt FIFO Level Select Register, UARTIFLS - pub const UARTIFLS = @intToPtr(*volatile Mmio(32, packed struct { - /// Transmit interrupt FIFO level select. The trigger points for the transmit - /// interrupt are as follows: b000 = Transmit FIFO becomes <= 1 / 8 full b001 = - /// Transmit FIFO becomes <= 1 / 4 full b010 = Transmit FIFO becomes <= 1 / 2 full - /// b011 = Transmit FIFO becomes <= 3 / 4 full b100 = Transmit FIFO becomes <= 7 / 8 - /// full b101-b111 = reserved. - TXIFLSEL: u3, - /// Receive interrupt FIFO level select. The trigger points for the receive - /// interrupt are as follows: b000 = Receive FIFO becomes >= 1 / 8 full b001 = - /// Receive FIFO becomes >= 1 / 4 full b010 = Receive FIFO becomes >= 1 / 2 full - /// b011 = Receive FIFO becomes >= 3 / 4 full b100 = Receive FIFO becomes >= 7 / 8 - /// full b101-b111 = reserved. - RXIFLSEL: u3, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - }), base_address + 0x34); - - /// address: 0x40038038 - /// Interrupt Mask Set/Clear Register, UARTIMSC - pub const UARTIMSC = @intToPtr(*volatile Mmio(32, packed struct { - /// nUARTRI modem interrupt mask. A read returns the current mask for the UARTRIINTR - /// interrupt. On a write of 1, the mask of the UARTRIINTR interrupt is set. A write - /// of 0 clears the mask. - RIMIM: u1, - /// nUARTCTS modem interrupt mask. A read returns the current mask for the - /// UARTCTSINTR interrupt. On a write of 1, the mask of the UARTCTSINTR interrupt is - /// set. A write of 0 clears the mask. - CTSMIM: u1, - /// nUARTDCD modem interrupt mask. A read returns the current mask for the - /// UARTDCDINTR interrupt. On a write of 1, the mask of the UARTDCDINTR interrupt is - /// set. A write of 0 clears the mask. - DCDMIM: u1, - /// nUARTDSR modem interrupt mask. A read returns the current mask for the - /// UARTDSRINTR interrupt. On a write of 1, the mask of the UARTDSRINTR interrupt is - /// set. A write of 0 clears the mask. - DSRMIM: u1, - /// Receive interrupt mask. A read returns the current mask for the UARTRXINTR - /// interrupt. On a write of 1, the mask of the UARTRXINTR interrupt is set. A write - /// of 0 clears the mask. - RXIM: u1, - /// Transmit interrupt mask. A read returns the current mask for the UARTTXINTR - /// interrupt. On a write of 1, the mask of the UARTTXINTR interrupt is set. A write - /// of 0 clears the mask. - TXIM: u1, - /// Receive timeout interrupt mask. A read returns the current mask for the - /// UARTRTINTR interrupt. On a write of 1, the mask of the UARTRTINTR interrupt is - /// set. A write of 0 clears the mask. - RTIM: u1, - /// Framing error interrupt mask. A read returns the current mask for the UARTFEINTR - /// interrupt. On a write of 1, the mask of the UARTFEINTR interrupt is set. A write - /// of 0 clears the mask. - FEIM: u1, - /// Parity error interrupt mask. A read returns the current mask for the UARTPEINTR - /// interrupt. On a write of 1, the mask of the UARTPEINTR interrupt is set. A write - /// of 0 clears the mask. - PEIM: u1, - /// Break error interrupt mask. A read returns the current mask for the UARTBEINTR - /// interrupt. On a write of 1, the mask of the UARTBEINTR interrupt is set. A write - /// of 0 clears the mask. - BEIM: u1, - /// Overrun error interrupt mask. A read returns the current mask for the UARTOEINTR - /// interrupt. On a write of 1, the mask of the UARTOEINTR interrupt is set. A write - /// of 0 clears the mask. - OEIM: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - }), base_address + 0x38); - - /// address: 0x4003803c - /// Raw Interrupt Status Register, UARTRIS - pub const UARTRIS = @intToPtr(*volatile Mmio(32, packed struct { - /// nUARTRI modem interrupt status. Returns the raw interrupt state of the - /// UARTRIINTR interrupt. - RIRMIS: u1, - /// nUARTCTS modem interrupt status. Returns the raw interrupt state of the - /// UARTCTSINTR interrupt. - CTSRMIS: u1, - /// nUARTDCD modem interrupt status. Returns the raw interrupt state of the - /// UARTDCDINTR interrupt. - DCDRMIS: u1, - /// nUARTDSR modem interrupt status. Returns the raw interrupt state of the - /// UARTDSRINTR interrupt. - DSRRMIS: u1, - /// Receive interrupt status. Returns the raw interrupt state of the UARTRXINTR - /// interrupt. - RXRIS: u1, - /// Transmit interrupt status. Returns the raw interrupt state of the UARTTXINTR - /// interrupt. - TXRIS: u1, - /// Receive timeout interrupt status. Returns the raw interrupt state of the - /// UARTRTINTR interrupt. a - RTRIS: u1, - /// Framing error interrupt status. Returns the raw interrupt state of the - /// UARTFEINTR interrupt. - FERIS: u1, - /// Parity error interrupt status. Returns the raw interrupt state of the UARTPEINTR - /// interrupt. - PERIS: u1, - /// Break error interrupt status. Returns the raw interrupt state of the UARTBEINTR - /// interrupt. - BERIS: u1, - /// Overrun error interrupt status. Returns the raw interrupt state of the - /// UARTOEINTR interrupt. - OERIS: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - }), base_address + 0x3c); - - /// address: 0x40038040 - /// Masked Interrupt Status Register, UARTMIS - pub const UARTMIS = @intToPtr(*volatile Mmio(32, packed struct { - /// nUARTRI modem masked interrupt status. Returns the masked interrupt state of the - /// UARTRIINTR interrupt. - RIMMIS: u1, - /// nUARTCTS modem masked interrupt status. Returns the masked interrupt state of - /// the UARTCTSINTR interrupt. - CTSMMIS: u1, - /// nUARTDCD modem masked interrupt status. Returns the masked interrupt state of - /// the UARTDCDINTR interrupt. - DCDMMIS: u1, - /// nUARTDSR modem masked interrupt status. Returns the masked interrupt state of - /// the UARTDSRINTR interrupt. - DSRMMIS: u1, - /// Receive masked interrupt status. Returns the masked interrupt state of the - /// UARTRXINTR interrupt. - RXMIS: u1, - /// Transmit masked interrupt status. Returns the masked interrupt state of the - /// UARTTXINTR interrupt. - TXMIS: u1, - /// Receive timeout masked interrupt status. Returns the masked interrupt state of - /// the UARTRTINTR interrupt. - RTMIS: u1, - /// Framing error masked interrupt status. Returns the masked interrupt state of the - /// UARTFEINTR interrupt. - FEMIS: u1, - /// Parity error masked interrupt status. Returns the masked interrupt state of the - /// UARTPEINTR interrupt. - PEMIS: u1, - /// Break error masked interrupt status. Returns the masked interrupt state of the - /// UARTBEINTR interrupt. - BEMIS: u1, - /// Overrun error masked interrupt status. Returns the masked interrupt state of the - /// UARTOEINTR interrupt. - OEMIS: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - }), base_address + 0x40); - - /// address: 0x40038044 - /// Interrupt Clear Register, UARTICR - pub const UARTICR = @intToPtr(*volatile Mmio(32, packed struct { - /// nUARTRI modem interrupt clear. Clears the UARTRIINTR interrupt. - RIMIC: u1, - /// nUARTCTS modem interrupt clear. Clears the UARTCTSINTR interrupt. - CTSMIC: u1, - /// nUARTDCD modem interrupt clear. Clears the UARTDCDINTR interrupt. - DCDMIC: u1, - /// nUARTDSR modem interrupt clear. Clears the UARTDSRINTR interrupt. - DSRMIC: u1, - /// Receive interrupt clear. Clears the UARTRXINTR interrupt. - RXIC: u1, - /// Transmit interrupt clear. Clears the UARTTXINTR interrupt. - TXIC: u1, - /// Receive timeout interrupt clear. Clears the UARTRTINTR interrupt. - RTIC: u1, - /// Framing error interrupt clear. Clears the UARTFEINTR interrupt. - FEIC: u1, - /// Parity error interrupt clear. Clears the UARTPEINTR interrupt. - PEIC: u1, - /// Break error interrupt clear. Clears the UARTBEINTR interrupt. - BEIC: u1, - /// Overrun error interrupt clear. Clears the UARTOEINTR interrupt. - OEIC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - }), base_address + 0x44); - - /// address: 0x40038048 - /// DMA Control Register, UARTDMACR - pub const UARTDMACR = @intToPtr(*volatile Mmio(32, packed struct { - /// Receive DMA enable. If this bit is set to 1, DMA for the receive FIFO is - /// enabled. - RXDMAE: u1, - /// Transmit DMA enable. If this bit is set to 1, DMA for the transmit FIFO is - /// enabled. - TXDMAE: u1, - /// DMA on error. If this bit is set to 1, the DMA receive request outputs, - /// UARTRXDMASREQ or UARTRXDMABREQ, are disabled when the UART error interrupt is - /// asserted. - DMAONERR: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - }), base_address + 0x48); - - /// address: 0x40038fe0 - /// UARTPeriphID0 Register - pub const UARTPERIPHID0 = @intToPtr(*volatile Mmio(32, packed struct { - /// These bits read back as 0x11 - PARTNUMBER0: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0xfe0); - - /// address: 0x40038fe4 - /// UARTPeriphID1 Register - pub const UARTPERIPHID1 = @intToPtr(*volatile Mmio(32, packed struct { - /// These bits read back as 0x0 - PARTNUMBER1: u4, - /// These bits read back as 0x1 - DESIGNER0: u4, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0xfe4); - - /// address: 0x40038fe8 - /// UARTPeriphID2 Register - pub const UARTPERIPHID2 = @intToPtr(*volatile Mmio(32, packed struct { - /// These bits read back as 0x4 - DESIGNER1: u4, - /// This field depends on the revision of the UART: r1p0 0x0 r1p1 0x1 r1p3 0x2 r1p4 - /// 0x2 r1p5 0x3 - REVISION: u4, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0xfe8); - - /// address: 0x40038fec - /// UARTPeriphID3 Register - pub const UARTPERIPHID3 = @intToPtr(*volatile Mmio(32, packed struct { - /// These bits read back as 0x00 - CONFIGURATION: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0xfec); - - /// address: 0x40038ff0 - /// UARTPCellID0 Register - pub const UARTPCELLID0 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xff0); - - /// address: 0x40038ff4 - /// UARTPCellID1 Register - pub const UARTPCELLID1 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xff4); - - /// address: 0x40038ff8 - /// UARTPCellID2 Register - pub const UARTPCELLID2 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xff8); - - /// address: 0x40038ffc - /// UARTPCellID3 Register - pub const UARTPCELLID3 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xffc); - }; - pub const SPI0 = struct { - pub const base_address = 0x4003c000; - pub const version = "1"; - - /// address: 0x4003c000 - /// Control register 0, SSPCR0 on page 3-4 - pub const SSPCR0 = @intToPtr(*volatile Mmio(32, packed struct { - /// Data Size Select: 0000 Reserved, undefined operation. 0001 Reserved, undefined - /// operation. 0010 Reserved, undefined operation. 0011 4-bit data. 0100 5-bit data. - /// 0101 6-bit data. 0110 7-bit data. 0111 8-bit data. 1000 9-bit data. 1001 10-bit - /// data. 1010 11-bit data. 1011 12-bit data. 1100 13-bit data. 1101 14-bit data. - /// 1110 15-bit data. 1111 16-bit data. - DSS: u4, - /// Frame format: 00 Motorola SPI frame format. 01 TI synchronous serial frame - /// format. 10 National Microwire frame format. 11 Reserved, undefined operation. - FRF: u2, - /// SSPCLKOUT polarity, applicable to Motorola SPI frame format only. See Motorola - /// SPI frame format on page 2-10. - SPO: u1, - /// SSPCLKOUT phase, applicable to Motorola SPI frame format only. See Motorola SPI - /// frame format on page 2-10. - SPH: u1, - /// Serial clock rate. The value SCR is used to generate the transmit and receive - /// bit rate of the PrimeCell SSP. The bit rate is: F SSPCLK CPSDVSR x (1+SCR) where - /// CPSDVSR is an even value from 2-254, programmed through the SSPCPSR register and - /// SCR is a value from 0-255. - SCR: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - }), base_address + 0x0); - - /// address: 0x4003c004 - /// Control register 1, SSPCR1 on page 3-5 - pub const SSPCR1 = @intToPtr(*volatile Mmio(32, packed struct { - /// Loop back mode: 0 Normal serial port operation enabled. 1 Output of transmit - /// serial shifter is connected to input of receive serial shifter internally. - LBM: u1, - /// Synchronous serial port enable: 0 SSP operation disabled. 1 SSP operation - /// enabled. - SSE: u1, - /// Master or slave mode select. This bit can be modified only when the PrimeCell - /// SSP is disabled, SSE=0: 0 Device configured as master, default. 1 Device - /// configured as slave. - MS: u1, - /// Slave-mode output disable. This bit is relevant only in the slave mode, MS=1. In - /// multiple-slave systems, it is possible for an PrimeCell SSP master to broadcast - /// a message to all slaves in the system while ensuring that only one slave drives - /// data onto its serial output line. In such systems the RXD lines from multiple - /// slaves could be tied together. To operate in such systems, the SOD bit can be - /// set if the PrimeCell SSP slave is not supposed to drive the SSPTXD line: 0 SSP - /// can drive the SSPTXD output in slave mode. 1 SSP must not drive the SSPTXD - /// output in slave mode. - SOD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - }), base_address + 0x4); - - /// address: 0x4003c008 - /// Data register, SSPDR on page 3-6 - pub const SSPDR = @intToPtr(*volatile Mmio(32, packed struct { - /// Transmit/Receive FIFO: Read Receive FIFO. Write Transmit FIFO. You must - /// right-justify data when the PrimeCell SSP is programmed for a data size that is - /// less than 16 bits. Unused bits at the top are ignored by transmit logic. The - /// receive logic automatically right-justifies. - DATA: u16, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - }), base_address + 0x8); - - /// address: 0x4003c00c - /// Status register, SSPSR on page 3-7 - pub const SSPSR = @intToPtr(*volatile Mmio(32, packed struct { - /// Transmit FIFO empty, RO: 0 Transmit FIFO is not empty. 1 Transmit FIFO is empty. - TFE: u1, - /// Transmit FIFO not full, RO: 0 Transmit FIFO is full. 1 Transmit FIFO is not - /// full. - TNF: u1, - /// Receive FIFO not empty, RO: 0 Receive FIFO is empty. 1 Receive FIFO is not - /// empty. - RNE: u1, - /// Receive FIFO full, RO: 0 Receive FIFO is not full. 1 Receive FIFO is full. - RFF: u1, - /// PrimeCell SSP busy flag, RO: 0 SSP is idle. 1 SSP is currently transmitting - /// and/or receiving a frame or the transmit FIFO is not empty. - BSY: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - }), base_address + 0xc); - - /// address: 0x4003c010 - /// Clock prescale register, SSPCPSR on page 3-8 - pub const SSPCPSR = @intToPtr(*volatile Mmio(32, packed struct { - /// Clock prescale divisor. Must be an even number from 2-254, depending on the - /// frequency of SSPCLK. The least significant bit always returns zero on reads. - CPSDVSR: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x10); - - /// address: 0x4003c014 - /// Interrupt mask set or clear register, SSPIMSC on page 3-9 - pub const SSPIMSC = @intToPtr(*volatile Mmio(32, packed struct { - /// Receive overrun interrupt mask: 0 Receive FIFO written to while full condition - /// interrupt is masked. 1 Receive FIFO written to while full condition interrupt is - /// not masked. - RORIM: u1, - /// Receive timeout interrupt mask: 0 Receive FIFO not empty and no read prior to - /// timeout period interrupt is masked. 1 Receive FIFO not empty and no read prior - /// to timeout period interrupt is not masked. - RTIM: u1, - /// Receive FIFO interrupt mask: 0 Receive FIFO half full or less condition - /// interrupt is masked. 1 Receive FIFO half full or less condition interrupt is not - /// masked. - RXIM: u1, - /// Transmit FIFO interrupt mask: 0 Transmit FIFO half empty or less condition - /// interrupt is masked. 1 Transmit FIFO half empty or less condition interrupt is - /// not masked. - TXIM: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - }), base_address + 0x14); - - /// address: 0x4003c018 - /// Raw interrupt status register, SSPRIS on page 3-10 - pub const SSPRIS = @intToPtr(*volatile Mmio(32, packed struct { - /// Gives the raw interrupt state, prior to masking, of the SSPRORINTR interrupt - RORRIS: u1, - /// Gives the raw interrupt state, prior to masking, of the SSPRTINTR interrupt - RTRIS: u1, - /// Gives the raw interrupt state, prior to masking, of the SSPRXINTR interrupt - RXRIS: u1, - /// Gives the raw interrupt state, prior to masking, of the SSPTXINTR interrupt - TXRIS: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - }), base_address + 0x18); - - /// address: 0x4003c01c - /// Masked interrupt status register, SSPMIS on page 3-11 - pub const SSPMIS = @intToPtr(*volatile Mmio(32, packed struct { - /// Gives the receive over run masked interrupt status, after masking, of the - /// SSPRORINTR interrupt - RORMIS: u1, - /// Gives the receive timeout masked interrupt state, after masking, of the - /// SSPRTINTR interrupt - RTMIS: u1, - /// Gives the receive FIFO masked interrupt state, after masking, of the SSPRXINTR - /// interrupt - RXMIS: u1, - /// Gives the transmit FIFO masked interrupt state, after masking, of the SSPTXINTR - /// interrupt - TXMIS: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - }), base_address + 0x1c); - - /// address: 0x4003c020 - /// Interrupt clear register, SSPICR on page 3-11 - pub const SSPICR = @intToPtr(*volatile Mmio(32, packed struct { - /// Clears the SSPRORINTR interrupt - RORIC: u1, - /// Clears the SSPRTINTR interrupt - RTIC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - }), base_address + 0x20); - - /// address: 0x4003c024 - /// DMA control register, SSPDMACR on page 3-12 - pub const SSPDMACR = @intToPtr(*volatile Mmio(32, packed struct { - /// Receive DMA Enable. If this bit is set to 1, DMA for the receive FIFO is - /// enabled. - RXDMAE: u1, - /// Transmit DMA Enable. If this bit is set to 1, DMA for the transmit FIFO is - /// enabled. - TXDMAE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - }), base_address + 0x24); - - /// address: 0x4003cfe0 - /// Peripheral identification registers, SSPPeriphID0-3 on page 3-13 - pub const SSPPERIPHID0 = @intToPtr(*volatile Mmio(32, packed struct { - /// These bits read back as 0x22 - PARTNUMBER0: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0xfe0); - - /// address: 0x4003cfe4 - /// Peripheral identification registers, SSPPeriphID0-3 on page 3-13 - pub const SSPPERIPHID1 = @intToPtr(*volatile Mmio(32, packed struct { - /// These bits read back as 0x0 - PARTNUMBER1: u4, - /// These bits read back as 0x1 - DESIGNER0: u4, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0xfe4); - - /// address: 0x4003cfe8 - /// Peripheral identification registers, SSPPeriphID0-3 on page 3-13 - pub const SSPPERIPHID2 = @intToPtr(*volatile Mmio(32, packed struct { - /// These bits read back as 0x4 - DESIGNER1: u4, - /// These bits return the peripheral revision - REVISION: u4, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0xfe8); - - /// address: 0x4003cfec - /// Peripheral identification registers, SSPPeriphID0-3 on page 3-13 - pub const SSPPERIPHID3 = @intToPtr(*volatile Mmio(32, packed struct { - /// These bits read back as 0x00 - CONFIGURATION: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0xfec); - - /// address: 0x4003cff0 - /// PrimeCell identification registers, SSPPCellID0-3 on page 3-16 - pub const SSPPCELLID0 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xff0); - - /// address: 0x4003cff4 - /// PrimeCell identification registers, SSPPCellID0-3 on page 3-16 - pub const SSPPCELLID1 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xff4); - - /// address: 0x4003cff8 - /// PrimeCell identification registers, SSPPCellID0-3 on page 3-16 - pub const SSPPCELLID2 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xff8); - - /// address: 0x4003cffc - /// PrimeCell identification registers, SSPPCellID0-3 on page 3-16 - pub const SSPPCELLID3 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xffc); - }; - pub const SPI1 = struct { - pub const base_address = 0x40040000; - - /// address: 0x40040000 - /// Control register 0, SSPCR0 on page 3-4 - pub const SSPCR0 = @intToPtr(*volatile Mmio(32, packed struct { - /// Data Size Select: 0000 Reserved, undefined operation. 0001 Reserved, undefined - /// operation. 0010 Reserved, undefined operation. 0011 4-bit data. 0100 5-bit data. - /// 0101 6-bit data. 0110 7-bit data. 0111 8-bit data. 1000 9-bit data. 1001 10-bit - /// data. 1010 11-bit data. 1011 12-bit data. 1100 13-bit data. 1101 14-bit data. - /// 1110 15-bit data. 1111 16-bit data. - DSS: u4, - /// Frame format: 00 Motorola SPI frame format. 01 TI synchronous serial frame - /// format. 10 National Microwire frame format. 11 Reserved, undefined operation. - FRF: u2, - /// SSPCLKOUT polarity, applicable to Motorola SPI frame format only. See Motorola - /// SPI frame format on page 2-10. - SPO: u1, - /// SSPCLKOUT phase, applicable to Motorola SPI frame format only. See Motorola SPI - /// frame format on page 2-10. - SPH: u1, - /// Serial clock rate. The value SCR is used to generate the transmit and receive - /// bit rate of the PrimeCell SSP. The bit rate is: F SSPCLK CPSDVSR x (1+SCR) where - /// CPSDVSR is an even value from 2-254, programmed through the SSPCPSR register and - /// SCR is a value from 0-255. - SCR: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - }), base_address + 0x0); - - /// address: 0x40040004 - /// Control register 1, SSPCR1 on page 3-5 - pub const SSPCR1 = @intToPtr(*volatile Mmio(32, packed struct { - /// Loop back mode: 0 Normal serial port operation enabled. 1 Output of transmit - /// serial shifter is connected to input of receive serial shifter internally. - LBM: u1, - /// Synchronous serial port enable: 0 SSP operation disabled. 1 SSP operation - /// enabled. - SSE: u1, - /// Master or slave mode select. This bit can be modified only when the PrimeCell - /// SSP is disabled, SSE=0: 0 Device configured as master, default. 1 Device - /// configured as slave. - MS: u1, - /// Slave-mode output disable. This bit is relevant only in the slave mode, MS=1. In - /// multiple-slave systems, it is possible for an PrimeCell SSP master to broadcast - /// a message to all slaves in the system while ensuring that only one slave drives - /// data onto its serial output line. In such systems the RXD lines from multiple - /// slaves could be tied together. To operate in such systems, the SOD bit can be - /// set if the PrimeCell SSP slave is not supposed to drive the SSPTXD line: 0 SSP - /// can drive the SSPTXD output in slave mode. 1 SSP must not drive the SSPTXD - /// output in slave mode. - SOD: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - }), base_address + 0x4); - - /// address: 0x40040008 - /// Data register, SSPDR on page 3-6 - pub const SSPDR = @intToPtr(*volatile Mmio(32, packed struct { - /// Transmit/Receive FIFO: Read Receive FIFO. Write Transmit FIFO. You must - /// right-justify data when the PrimeCell SSP is programmed for a data size that is - /// less than 16 bits. Unused bits at the top are ignored by transmit logic. The - /// receive logic automatically right-justifies. - DATA: u16, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - }), base_address + 0x8); - - /// address: 0x4004000c - /// Status register, SSPSR on page 3-7 - pub const SSPSR = @intToPtr(*volatile Mmio(32, packed struct { - /// Transmit FIFO empty, RO: 0 Transmit FIFO is not empty. 1 Transmit FIFO is empty. - TFE: u1, - /// Transmit FIFO not full, RO: 0 Transmit FIFO is full. 1 Transmit FIFO is not - /// full. - TNF: u1, - /// Receive FIFO not empty, RO: 0 Receive FIFO is empty. 1 Receive FIFO is not - /// empty. - RNE: u1, - /// Receive FIFO full, RO: 0 Receive FIFO is not full. 1 Receive FIFO is full. - RFF: u1, - /// PrimeCell SSP busy flag, RO: 0 SSP is idle. 1 SSP is currently transmitting - /// and/or receiving a frame or the transmit FIFO is not empty. - BSY: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - }), base_address + 0xc); - - /// address: 0x40040010 - /// Clock prescale register, SSPCPSR on page 3-8 - pub const SSPCPSR = @intToPtr(*volatile Mmio(32, packed struct { - /// Clock prescale divisor. Must be an even number from 2-254, depending on the - /// frequency of SSPCLK. The least significant bit always returns zero on reads. - CPSDVSR: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x10); - - /// address: 0x40040014 - /// Interrupt mask set or clear register, SSPIMSC on page 3-9 - pub const SSPIMSC = @intToPtr(*volatile Mmio(32, packed struct { - /// Receive overrun interrupt mask: 0 Receive FIFO written to while full condition - /// interrupt is masked. 1 Receive FIFO written to while full condition interrupt is - /// not masked. - RORIM: u1, - /// Receive timeout interrupt mask: 0 Receive FIFO not empty and no read prior to - /// timeout period interrupt is masked. 1 Receive FIFO not empty and no read prior - /// to timeout period interrupt is not masked. - RTIM: u1, - /// Receive FIFO interrupt mask: 0 Receive FIFO half full or less condition - /// interrupt is masked. 1 Receive FIFO half full or less condition interrupt is not - /// masked. - RXIM: u1, - /// Transmit FIFO interrupt mask: 0 Transmit FIFO half empty or less condition - /// interrupt is masked. 1 Transmit FIFO half empty or less condition interrupt is - /// not masked. - TXIM: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - }), base_address + 0x14); - - /// address: 0x40040018 - /// Raw interrupt status register, SSPRIS on page 3-10 - pub const SSPRIS = @intToPtr(*volatile Mmio(32, packed struct { - /// Gives the raw interrupt state, prior to masking, of the SSPRORINTR interrupt - RORRIS: u1, - /// Gives the raw interrupt state, prior to masking, of the SSPRTINTR interrupt - RTRIS: u1, - /// Gives the raw interrupt state, prior to masking, of the SSPRXINTR interrupt - RXRIS: u1, - /// Gives the raw interrupt state, prior to masking, of the SSPTXINTR interrupt - TXRIS: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - }), base_address + 0x18); - - /// address: 0x4004001c - /// Masked interrupt status register, SSPMIS on page 3-11 - pub const SSPMIS = @intToPtr(*volatile Mmio(32, packed struct { - /// Gives the receive over run masked interrupt status, after masking, of the - /// SSPRORINTR interrupt - RORMIS: u1, - /// Gives the receive timeout masked interrupt state, after masking, of the - /// SSPRTINTR interrupt - RTMIS: u1, - /// Gives the receive FIFO masked interrupt state, after masking, of the SSPRXINTR - /// interrupt - RXMIS: u1, - /// Gives the transmit FIFO masked interrupt state, after masking, of the SSPTXINTR - /// interrupt - TXMIS: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - }), base_address + 0x1c); - - /// address: 0x40040020 - /// Interrupt clear register, SSPICR on page 3-11 - pub const SSPICR = @intToPtr(*volatile Mmio(32, packed struct { - /// Clears the SSPRORINTR interrupt - RORIC: u1, - /// Clears the SSPRTINTR interrupt - RTIC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - }), base_address + 0x20); - - /// address: 0x40040024 - /// DMA control register, SSPDMACR on page 3-12 - pub const SSPDMACR = @intToPtr(*volatile Mmio(32, packed struct { - /// Receive DMA Enable. If this bit is set to 1, DMA for the receive FIFO is - /// enabled. - RXDMAE: u1, - /// Transmit DMA Enable. If this bit is set to 1, DMA for the transmit FIFO is - /// enabled. - TXDMAE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - }), base_address + 0x24); - - /// address: 0x40040fe0 - /// Peripheral identification registers, SSPPeriphID0-3 on page 3-13 - pub const SSPPERIPHID0 = @intToPtr(*volatile Mmio(32, packed struct { - /// These bits read back as 0x22 - PARTNUMBER0: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0xfe0); - - /// address: 0x40040fe4 - /// Peripheral identification registers, SSPPeriphID0-3 on page 3-13 - pub const SSPPERIPHID1 = @intToPtr(*volatile Mmio(32, packed struct { - /// These bits read back as 0x0 - PARTNUMBER1: u4, - /// These bits read back as 0x1 - DESIGNER0: u4, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0xfe4); - - /// address: 0x40040fe8 - /// Peripheral identification registers, SSPPeriphID0-3 on page 3-13 - pub const SSPPERIPHID2 = @intToPtr(*volatile Mmio(32, packed struct { - /// These bits read back as 0x4 - DESIGNER1: u4, - /// These bits return the peripheral revision - REVISION: u4, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0xfe8); - - /// address: 0x40040fec - /// Peripheral identification registers, SSPPeriphID0-3 on page 3-13 - pub const SSPPERIPHID3 = @intToPtr(*volatile Mmio(32, packed struct { - /// These bits read back as 0x00 - CONFIGURATION: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0xfec); - - /// address: 0x40040ff0 - /// PrimeCell identification registers, SSPPCellID0-3 on page 3-16 - pub const SSPPCELLID0 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xff0); - - /// address: 0x40040ff4 - /// PrimeCell identification registers, SSPPCellID0-3 on page 3-16 - pub const SSPPCELLID1 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xff4); - - /// address: 0x40040ff8 - /// PrimeCell identification registers, SSPPCellID0-3 on page 3-16 - pub const SSPPCELLID2 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xff8); - - /// address: 0x40040ffc - /// PrimeCell identification registers, SSPPCellID0-3 on page 3-16 - pub const SSPPCELLID3 = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xffc); - }; - - /// DW_apb_i2c address block\n\n - /// List of configuration constants for the Synopsys I2C hardware (you may see - /// references to these in I2C register header; these are *fixed* values, set at - /// hardware design time):\n\n - /// IC_ULTRA_FAST_MODE ................ 0x0\n - /// IC_UFM_TBUF_CNT_DEFAULT ........... 0x8\n - /// IC_UFM_SCL_LOW_COUNT .............. 0x0008\n - /// IC_UFM_SCL_HIGH_COUNT ............. 0x0006\n - /// IC_TX_TL .......................... 0x0\n - /// IC_TX_CMD_BLOCK ................... 0x1\n - /// IC_HAS_DMA ........................ 0x1\n - /// IC_HAS_ASYNC_FIFO ................. 0x0\n - /// IC_SMBUS_ARP ...................... 0x0\n - /// IC_FIRST_DATA_BYTE_STATUS ......... 0x1\n - /// IC_INTR_IO ........................ 0x1\n - /// IC_MASTER_MODE .................... 0x1\n - /// IC_DEFAULT_ACK_GENERAL_CALL ....... 0x1\n - /// IC_INTR_POL ....................... 0x1\n - /// IC_OPTIONAL_SAR ................... 0x0\n - /// IC_DEFAULT_TAR_SLAVE_ADDR ......... 0x055\n - /// IC_DEFAULT_SLAVE_ADDR ............. 0x055\n - /// IC_DEFAULT_HS_SPKLEN .............. 0x1\n - /// IC_FS_SCL_HIGH_COUNT .............. 0x0006\n - /// IC_HS_SCL_LOW_COUNT ............... 0x0008\n - /// IC_DEVICE_ID_VALUE ................ 0x0\n - /// IC_10BITADDR_MASTER ............... 0x0\n - /// IC_CLK_FREQ_OPTIMIZATION .......... 0x0\n - /// IC_DEFAULT_FS_SPKLEN .............. 0x7\n - /// IC_ADD_ENCODED_PARAMS ............. 0x0\n - /// IC_DEFAULT_SDA_HOLD ............... 0x000001\n - /// IC_DEFAULT_SDA_SETUP .............. 0x64\n - /// IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT . 0x0\n - /// IC_CLOCK_PERIOD ................... 100\n - /// IC_EMPTYFIFO_HOLD_MASTER_EN ....... 1\n - /// IC_RESTART_EN ..................... 0x1\n - /// IC_TX_CMD_BLOCK_DEFAULT ........... 0x0\n - /// IC_BUS_CLEAR_FEATURE .............. 0x0\n - /// IC_CAP_LOADING .................... 100\n - /// IC_FS_SCL_LOW_COUNT ............... 0x000d\n - /// APB_DATA_WIDTH .................... 32\n - /// IC_SDA_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff\n - /// IC_SLV_DATA_NACK_ONLY ............. 0x1\n - /// IC_10BITADDR_SLAVE ................ 0x0\n - /// IC_CLK_TYPE ....................... 0x0\n - /// IC_SMBUS_UDID_MSB ................. 0x0\n - /// IC_SMBUS_SUSPEND_ALERT ............ 0x0\n - /// IC_HS_SCL_HIGH_COUNT .............. 0x0006\n - /// IC_SLV_RESTART_DET_EN ............. 0x1\n - /// IC_SMBUS .......................... 0x0\n - /// IC_OPTIONAL_SAR_DEFAULT ........... 0x0\n - /// IC_PERSISTANT_SLV_ADDR_DEFAULT .... 0x0\n - /// IC_USE_COUNTS ..................... 0x0\n - /// IC_RX_BUFFER_DEPTH ................ 16\n - /// IC_SCL_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff\n - /// IC_RX_FULL_HLD_BUS_EN ............. 0x1\n - /// IC_SLAVE_DISABLE .................. 0x1\n - /// IC_RX_TL .......................... 0x0\n - /// IC_DEVICE_ID ...................... 0x0\n - /// IC_HC_COUNT_VALUES ................ 0x0\n - /// I2C_DYNAMIC_TAR_UPDATE ............ 0\n - /// IC_SMBUS_CLK_LOW_MEXT_DEFAULT ..... 0xffffffff\n - /// IC_SMBUS_CLK_LOW_SEXT_DEFAULT ..... 0xffffffff\n - /// IC_HS_MASTER_CODE ................. 0x1\n - /// IC_SMBUS_RST_IDLE_CNT_DEFAULT ..... 0xffff\n - /// IC_SMBUS_UDID_LSB_DEFAULT ......... 0xffffffff\n - /// IC_SS_SCL_HIGH_COUNT .............. 0x0028\n - /// IC_SS_SCL_LOW_COUNT ............... 0x002f\n - /// IC_MAX_SPEED_MODE ................. 0x2\n - /// IC_STAT_FOR_CLK_STRETCH ........... 0x0\n - /// IC_STOP_DET_IF_MASTER_ACTIVE ...... 0x0\n - /// IC_DEFAULT_UFM_SPKLEN ............. 0x1\n - /// IC_TX_BUFFER_DEPTH ................ 16 - pub const I2C0 = struct { - pub const base_address = 0x40044000; - pub const version = "1"; - - /// address: 0x40044000 - /// I2C Control Register. This register can be written only when the DW_apb_i2c is - /// disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes - /// at other times have no effect.\n\n - /// Read/Write Access: - bit 10 is read only. - bit 11 is read only - bit 16 is read - /// only - bit 17 is read only - bits 18 and 19 are read only. - pub const IC_CON = @intToPtr(*volatile Mmio(32, packed struct { - /// This bit controls whether the DW_apb_i2c master is enabled.\n\n - /// NOTE: Software should ensure that if this bit is written with '1' then bit 6 - /// should also be written with a '1'. - MASTER_MODE: u1, - /// These bits control at which speed the DW_apb_i2c operates; its setting is - /// relevant only if one is operating the DW_apb_i2c in master mode. Hardware - /// protects against illegal values being programmed by software. These bits must be - /// programmed appropriately for slave mode also, as it is used to capture correct - /// value of spike filter as per the speed mode.\n\n - /// This register should be programmed only with a value in the range of 1 to - /// IC_MAX_SPEED_MODE; otherwise, hardware updates this register with the value of - /// IC_MAX_SPEED_MODE.\n\n - /// 1: standard mode (100 kbit/s)\n\n - /// 2: fast mode (<=400 kbit/s) or fast mode plus (<=1000Kbit/s)\n\n - /// 3: high speed mode (3.4 Mbit/s)\n\n - /// Note: This field is not applicable when IC_ULTRA_FAST_MODE=1 - SPEED: u2, - /// When acting as a slave, this bit controls whether the DW_apb_i2c responds to 7- - /// or 10-bit addresses. - 0: 7-bit addressing. The DW_apb_i2c ignores transactions - /// that involve 10-bit addressing; for 7-bit addressing, only the lower 7 bits of - /// the IC_SAR register are compared. - 1: 10-bit addressing. The DW_apb_i2c - /// responds to only 10-bit addressing transfers that match the full 10 bits of the - /// IC_SAR register. - IC_10BITADDR_SLAVE: u1, - /// Controls whether the DW_apb_i2c starts its transfers in 7- or 10-bit addressing - /// mode when acting as a master. - 0: 7-bit addressing - 1: 10-bit addressing - IC_10BITADDR_MASTER: u1, - /// Determines whether RESTART conditions may be sent when acting as a master. Some - /// older slaves do not support handling RESTART conditions; however, RESTART - /// conditions are used in several DW_apb_i2c operations. When RESTART is disabled, - /// the master is prohibited from performing the following functions: - Sending a - /// START BYTE - Performing any high-speed mode operation - High-speed mode - /// operation - Performing direction changes in combined format mode - Performing a - /// read operation with a 10-bit address By replacing RESTART condition followed by - /// a STOP and a subsequent START condition, split operations are broken down into - /// multiple DW_apb_i2c transfers. If the above operations are performed, it will - /// result in setting bit 6 (TX_ABRT) of the IC_RAW_INTR_STAT register.\n\n - /// Reset value: ENABLED - IC_RESTART_EN: u1, - /// This bit controls whether I2C has its slave disabled, which means once the - /// presetn signal is applied, then this bit is set and the slave is disabled.\n\n - /// If this bit is set (slave is disabled), DW_apb_i2c functions only as a master - /// and does not perform any action that requires a slave.\n\n - /// NOTE: Software should ensure that if this bit is written with 0, then bit 0 - /// should also be written with a 0. - IC_SLAVE_DISABLE: u1, - /// In slave mode: - 1'b1: issues the STOP_DET interrupt only when it is addressed. - /// - 1'b0: issues the STOP_DET irrespective of whether it's addressed or not. Reset - /// value: 0x0\n\n - /// NOTE: During a general call address, this slave does not issue the STOP_DET - /// interrupt if STOP_DET_IF_ADDRESSED = 1'b1, even if the slave responds to the - /// general call address by generating ACK. The STOP_DET interrupt is generated only - /// when the transmitted address matches the slave address (SAR). - STOP_DET_IFADDRESSED: u1, - /// This bit controls the generation of the TX_EMPTY interrupt, as described in the - /// IC_RAW_INTR_STAT register.\n\n - /// Reset value: 0x0. - TX_EMPTY_CTRL: u1, - /// This bit controls whether DW_apb_i2c should hold the bus when the Rx FIFO is - /// physically full to its RX_BUFFER_DEPTH, as described in the - /// IC_RX_FULL_HLD_BUS_EN parameter.\n\n - /// Reset value: 0x0. - RX_FIFO_FULL_HLD_CTRL: u1, - /// Master issues the STOP_DET interrupt irrespective of whether master is active or - /// not - STOP_DET_IF_MASTER_ACTIVE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - }), base_address + 0x0); - - /// address: 0x40044004 - /// I2C Target Address Register\n\n - /// This register is 12 bits wide, and bits 31:12 are reserved. This register can be - /// written to only when IC_ENABLE[0] is set to 0.\n\n - /// Note: If the software or application is aware that the DW_apb_i2c is not using - /// the TAR address for the pending commands in the Tx FIFO, then it is possible to - /// update the TAR address even while the Tx FIFO has entries (IC_STATUS[2]= 0). - - /// It is not necessary to perform any write to this register if DW_apb_i2c is - /// enabled as an I2C slave only. - pub const IC_TAR = @intToPtr(*volatile Mmio(32, packed struct { - /// This is the target address for any master transaction. When transmitting a - /// General Call, these bits are ignored. To generate a START BYTE, the CPU needs to - /// write only once into these bits.\n\n - /// If the IC_TAR and IC_SAR are the same, loopback exists but the FIFOs are shared - /// between master and slave, so full loopback is not feasible. Only one direction - /// loopback mode is supported (simplex), not duplex. A master cannot transmit to - /// itself; it can transmit to only a slave. - IC_TAR: u10, - /// If bit 11 (SPECIAL) is set to 1 and bit 13(Device-ID) is set to 0, then this bit - /// indicates whether a General Call or START byte command is to be performed by the - /// DW_apb_i2c. - 0: General Call Address - after issuing a General Call, only - /// writes may be performed. Attempting to issue a read command results in setting - /// bit 6 (TX_ABRT) of the IC_RAW_INTR_STAT register. The DW_apb_i2c remains in - /// General Call mode until the SPECIAL bit value (bit 11) is cleared. - 1: START - /// BYTE Reset value: 0x0 - GC_OR_START: u1, - /// This bit indicates whether software performs a Device-ID or General Call or - /// START BYTE command. - 0: ignore bit 10 GC_OR_START and use IC_TAR normally - 1: - /// perform special I2C command as specified in Device_ID or GC_OR_START bit Reset - /// value: 0x0 - SPECIAL: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x4); - - /// address: 0x40044008 - /// I2C Slave Address Register - pub const IC_SAR = @intToPtr(*volatile MmioInt(32, u10), base_address + 0x8); - - /// address: 0x40044010 - /// I2C Rx/Tx Data Buffer and Command Register; this is the register the CPU writes - /// to when filling the TX FIFO and the CPU reads from when retrieving bytes from RX - /// FIFO.\n\n - /// The size of the register changes as follows:\n\n - /// Write: - 11 bits when IC_EMPTYFIFO_HOLD_MASTER_EN=1 - 9 bits when - /// IC_EMPTYFIFO_HOLD_MASTER_EN=0 Read: - 12 bits when IC_FIRST_DATA_BYTE_STATUS = 1 - /// - 8 bits when IC_FIRST_DATA_BYTE_STATUS = 0 Note: In order for the DW_apb_i2c to - /// continue acknowledging reads, a read command should be written for every byte - /// that is to be received; otherwise the DW_apb_i2c will stop acknowledging. - pub const IC_DATA_CMD = @intToPtr(*volatile Mmio(32, packed struct { - /// This register contains the data to be transmitted or received on the I2C bus. If - /// you are writing to this register and want to perform a read, bits 7:0 (DAT) are - /// ignored by the DW_apb_i2c. However, when you read this register, these bits - /// return the value of data received on the DW_apb_i2c interface.\n\n - /// Reset value: 0x0 - DAT: u8, - /// This bit controls whether a read or a write is performed. This bit does not - /// control the direction when the DW_apb_i2con acts as a slave. It controls only - /// the direction when it acts as a master.\n\n - /// When a command is entered in the TX FIFO, this bit distinguishes the write and - /// read commands. In slave-receiver mode, this bit is a 'don't care' because writes - /// to this register are not required. In slave-transmitter mode, a '0' indicates - /// that the data in IC_DATA_CMD is to be transmitted.\n\n - /// When programming this bit, you should remember the following: attempting to - /// perform a read operation after a General Call command has been sent results in a - /// TX_ABRT interrupt (bit 6 of the IC_RAW_INTR_STAT register), unless bit 11 - /// (SPECIAL) in the IC_TAR register has been cleared. If a '1' is written to this - /// bit after receiving a RD_REQ interrupt, then a TX_ABRT interrupt occurs.\n\n - /// Reset value: 0x0 - CMD: u1, - /// This bit controls whether a STOP is issued after the byte is sent or - /// received.\n\n - /// - 1 - STOP is issued after this byte, regardless of whether or not the Tx FIFO - /// is empty. If the Tx FIFO is not empty, the master immediately tries to start a - /// new transfer by issuing a START and arbitrating for the bus. - 0 - STOP is not - /// issued after this byte, regardless of whether or not the Tx FIFO is empty. If - /// the Tx FIFO is not empty, the master continues the current transfer by - /// sending/receiving data bytes according to the value of the CMD bit. If the Tx - /// FIFO is empty, the master holds the SCL line low and stalls the bus until a new - /// command is available in the Tx FIFO. Reset value: 0x0 - STOP: u1, - /// This bit controls whether a RESTART is issued before the byte is sent or - /// received.\n\n - /// 1 - If IC_RESTART_EN is 1, a RESTART is issued before the data is sent/received - /// (according to the value of CMD), regardless of whether or not the transfer - /// direction is changing from the previous command; if IC_RESTART_EN is 0, a STOP - /// followed by a START is issued instead.\n\n - /// 0 - If IC_RESTART_EN is 1, a RESTART is issued only if the transfer direction is - /// changing from the previous command; if IC_RESTART_EN is 0, a STOP followed by a - /// START is issued instead.\n\n - /// Reset value: 0x0 - RESTART: u1, - /// Indicates the first data byte received after the address phase for receive - /// transfer in Master receiver or Slave receiver mode.\n\n - /// Reset value : 0x0\n\n - /// NOTE: In case of APB_DATA_WIDTH=8,\n\n - /// 1. The user has to perform two APB Reads to IC_DATA_CMD in order to get status - /// on 11 bit.\n\n - /// 2. In order to read the 11 bit, the user has to perform the first data byte read - /// [7:0] (offset 0x10) and then perform the second read [15:8] (offset 0x11) in - /// order to know the status of 11 bit (whether the data received in previous read - /// is a first data byte or not).\n\n - /// 3. The 11th bit is an optional read field, user can ignore 2nd byte read [15:8] - /// (offset 0x11) if not interested in FIRST_DATA_BYTE status. - FIRST_DATA_BYTE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x10); - - /// address: 0x40044014 - /// Standard Speed I2C Clock SCL High Count Register - pub const IC_SS_SCL_HCNT = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x14); - - /// address: 0x40044018 - /// Standard Speed I2C Clock SCL Low Count Register - pub const IC_SS_SCL_LCNT = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x18); - - /// address: 0x4004401c - /// Fast Mode or Fast Mode Plus I2C Clock SCL High Count Register - pub const IC_FS_SCL_HCNT = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x1c); - - /// address: 0x40044020 - /// Fast Mode or Fast Mode Plus I2C Clock SCL Low Count Register - pub const IC_FS_SCL_LCNT = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x20); - - /// address: 0x4004402c - /// I2C Interrupt Status Register\n\n - /// Each bit in this register has a corresponding mask bit in the IC_INTR_MASK - /// register. These bits are cleared by reading the matching interrupt clear - /// register. The unmasked raw versions of these bits are available in the - /// IC_RAW_INTR_STAT register. - pub const IC_INTR_STAT = @intToPtr(*volatile Mmio(32, packed struct { - /// See IC_RAW_INTR_STAT for a detailed description of R_RX_UNDER bit.\n\n - /// Reset value: 0x0 - R_RX_UNDER: u1, - /// See IC_RAW_INTR_STAT for a detailed description of R_RX_OVER bit.\n\n - /// Reset value: 0x0 - R_RX_OVER: u1, - /// See IC_RAW_INTR_STAT for a detailed description of R_RX_FULL bit.\n\n - /// Reset value: 0x0 - R_RX_FULL: u1, - /// See IC_RAW_INTR_STAT for a detailed description of R_TX_OVER bit.\n\n - /// Reset value: 0x0 - R_TX_OVER: u1, - /// See IC_RAW_INTR_STAT for a detailed description of R_TX_EMPTY bit.\n\n - /// Reset value: 0x0 - R_TX_EMPTY: u1, - /// See IC_RAW_INTR_STAT for a detailed description of R_RD_REQ bit.\n\n - /// Reset value: 0x0 - R_RD_REQ: u1, - /// See IC_RAW_INTR_STAT for a detailed description of R_TX_ABRT bit.\n\n - /// Reset value: 0x0 - R_TX_ABRT: u1, - /// See IC_RAW_INTR_STAT for a detailed description of R_RX_DONE bit.\n\n - /// Reset value: 0x0 - R_RX_DONE: u1, - /// See IC_RAW_INTR_STAT for a detailed description of R_ACTIVITY bit.\n\n - /// Reset value: 0x0 - R_ACTIVITY: u1, - /// See IC_RAW_INTR_STAT for a detailed description of R_STOP_DET bit.\n\n - /// Reset value: 0x0 - R_STOP_DET: u1, - /// See IC_RAW_INTR_STAT for a detailed description of R_START_DET bit.\n\n - /// Reset value: 0x0 - R_START_DET: u1, - /// See IC_RAW_INTR_STAT for a detailed description of R_GEN_CALL bit.\n\n - /// Reset value: 0x0 - R_GEN_CALL: u1, - /// See IC_RAW_INTR_STAT for a detailed description of R_RESTART_DET bit.\n\n - /// Reset value: 0x0 - R_RESTART_DET: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - }), base_address + 0x2c); - - /// address: 0x40044030 - /// I2C Interrupt Mask Register.\n\n - /// These bits mask their corresponding interrupt status bits. This register is - /// active low; a value of 0 masks the interrupt, whereas a value of 1 unmasks the - /// interrupt. - pub const IC_INTR_MASK = @intToPtr(*volatile Mmio(32, packed struct { - /// This bit masks the R_RX_UNDER interrupt in IC_INTR_STAT register.\n\n - /// Reset value: 0x1 - M_RX_UNDER: u1, - /// This bit masks the R_RX_OVER interrupt in IC_INTR_STAT register.\n\n - /// Reset value: 0x1 - M_RX_OVER: u1, - /// This bit masks the R_RX_FULL interrupt in IC_INTR_STAT register.\n\n - /// Reset value: 0x1 - M_RX_FULL: u1, - /// This bit masks the R_TX_OVER interrupt in IC_INTR_STAT register.\n\n - /// Reset value: 0x1 - M_TX_OVER: u1, - /// This bit masks the R_TX_EMPTY interrupt in IC_INTR_STAT register.\n\n - /// Reset value: 0x1 - M_TX_EMPTY: u1, - /// This bit masks the R_RD_REQ interrupt in IC_INTR_STAT register.\n\n - /// Reset value: 0x1 - M_RD_REQ: u1, - /// This bit masks the R_TX_ABRT interrupt in IC_INTR_STAT register.\n\n - /// Reset value: 0x1 - M_TX_ABRT: u1, - /// This bit masks the R_RX_DONE interrupt in IC_INTR_STAT register.\n\n - /// Reset value: 0x1 - M_RX_DONE: u1, - /// This bit masks the R_ACTIVITY interrupt in IC_INTR_STAT register.\n\n - /// Reset value: 0x0 - M_ACTIVITY: u1, - /// This bit masks the R_STOP_DET interrupt in IC_INTR_STAT register.\n\n - /// Reset value: 0x0 - M_STOP_DET: u1, - /// This bit masks the R_START_DET interrupt in IC_INTR_STAT register.\n\n - /// Reset value: 0x0 - M_START_DET: u1, - /// This bit masks the R_GEN_CALL interrupt in IC_INTR_STAT register.\n\n - /// Reset value: 0x1 - M_GEN_CALL: u1, - /// This bit masks the R_RESTART_DET interrupt in IC_INTR_STAT register.\n\n - /// Reset value: 0x0 - M_RESTART_DET: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - }), base_address + 0x30); - - /// address: 0x40044034 - /// I2C Raw Interrupt Status Register\n\n - /// Unlike the IC_INTR_STAT register, these bits are not masked so they always show - /// the true status of the DW_apb_i2c. - pub const IC_RAW_INTR_STAT = @intToPtr(*volatile Mmio(32, packed struct { - /// Set if the processor attempts to read the receive buffer when it is empty by - /// reading from the IC_DATA_CMD register. If the module is disabled - /// (IC_ENABLE[0]=0), this bit keeps its level until the master or slave state - /// machines go into idle, and when ic_en goes to 0, this interrupt is cleared.\n\n - /// Reset value: 0x0 - RX_UNDER: u1, - /// Set if the receive buffer is completely filled to IC_RX_BUFFER_DEPTH and an - /// additional byte is received from an external I2C device. The DW_apb_i2c - /// acknowledges this, but any data bytes received after the FIFO is full are lost. - /// If the module is disabled (IC_ENABLE[0]=0), this bit keeps its level until the - /// master or slave state machines go into idle, and when ic_en goes to 0, this - /// interrupt is cleared.\n\n - /// Note: If bit 9 of the IC_CON register (RX_FIFO_FULL_HLD_CTRL) is programmed to - /// HIGH, then the RX_OVER interrupt never occurs, because the Rx FIFO never - /// overflows.\n\n - /// Reset value: 0x0 - RX_OVER: u1, - /// Set when the receive buffer reaches or goes above the RX_TL threshold in the - /// IC_RX_TL register. It is automatically cleared by hardware when buffer level - /// goes below the threshold. If the module is disabled (IC_ENABLE[0]=0), the RX - /// FIFO is flushed and held in reset; therefore the RX FIFO is not full. So this - /// bit is cleared once the IC_ENABLE bit 0 is programmed with a 0, regardless of - /// the activity that continues.\n\n - /// Reset value: 0x0 - RX_FULL: u1, - /// Set during transmit if the transmit buffer is filled to IC_TX_BUFFER_DEPTH and - /// the processor attempts to issue another I2C command by writing to the - /// IC_DATA_CMD register. When the module is disabled, this bit keeps its level - /// until the master or slave state machines go into idle, and when ic_en goes to 0, - /// this interrupt is cleared.\n\n - /// Reset value: 0x0 - TX_OVER: u1, - /// The behavior of the TX_EMPTY interrupt status differs based on the TX_EMPTY_CTRL - /// selection in the IC_CON register. - When TX_EMPTY_CTRL = 0: This bit is set to 1 - /// when the transmit buffer is at or below the threshold value set in the IC_TX_TL - /// register. - When TX_EMPTY_CTRL = 1: This bit is set to 1 when the transmit - /// buffer is at or below the threshold value set in the IC_TX_TL register and the - /// transmission of the address/data from the internal shift register for the most - /// recently popped command is completed. It is automatically cleared by hardware - /// when the buffer level goes above the threshold. When IC_ENABLE[0] is set to 0, - /// the TX FIFO is flushed and held in reset. There the TX FIFO looks like it has no - /// data within it, so this bit is set to 1, provided there is activity in the - /// master or slave state machines. When there is no longer any activity, then with - /// ic_en=0, this bit is set to 0.\n\n - /// Reset value: 0x0. - TX_EMPTY: u1, - /// This bit is set to 1 when DW_apb_i2c is acting as a slave and another I2C master - /// is attempting to read data from DW_apb_i2c. The DW_apb_i2c holds the I2C bus in - /// a wait state (SCL=0) until this interrupt is serviced, which means that the - /// slave has been addressed by a remote master that is asking for data to be - /// transferred. The processor must respond to this interrupt and then write the - /// requested data to the IC_DATA_CMD register. This bit is set to 0 just after the - /// processor reads the IC_CLR_RD_REQ register.\n\n - /// Reset value: 0x0 - RD_REQ: u1, - /// This bit indicates if DW_apb_i2c, as an I2C transmitter, is unable to complete - /// the intended actions on the contents of the transmit FIFO. This situation can - /// occur both as an I2C master or an I2C slave, and is referred to as a 'transmit - /// abort'. When this bit is set to 1, the IC_TX_ABRT_SOURCE register indicates the - /// reason why the transmit abort takes places.\n\n - /// Note: The DW_apb_i2c flushes/resets/empties the TX_FIFO and RX_FIFO whenever - /// there is a transmit abort caused by any of the events tracked by the - /// IC_TX_ABRT_SOURCE register. The FIFOs remains in this flushed state until the - /// register IC_CLR_TX_ABRT is read. Once this read is performed, the Tx FIFO is - /// then ready to accept more data bytes from the APB interface.\n\n - /// Reset value: 0x0 - TX_ABRT: u1, - /// When the DW_apb_i2c is acting as a slave-transmitter, this bit is set to 1 if - /// the master does not acknowledge a transmitted byte. This occurs on the last byte - /// of the transmission, indicating that the transmission is done.\n\n - /// Reset value: 0x0 - RX_DONE: u1, - /// This bit captures DW_apb_i2c activity and stays set until it is cleared. There - /// are four ways to clear it: - Disabling the DW_apb_i2c - Reading the - /// IC_CLR_ACTIVITY register - Reading the IC_CLR_INTR register - System reset Once - /// this bit is set, it stays set unless one of the four methods is used to clear - /// it. Even if the DW_apb_i2c module is idle, this bit remains set until cleared, - /// indicating that there was activity on the bus.\n\n - /// Reset value: 0x0 - ACTIVITY: u1, - /// Indicates whether a STOP condition has occurred on the I2C interface regardless - /// of whether DW_apb_i2c is operating in slave or master mode.\n\n - /// In Slave Mode: - If IC_CON[7]=1'b1 (STOP_DET_IFADDRESSED), the STOP_DET - /// interrupt will be issued only if slave is addressed. Note: During a general call - /// address, this slave does not issue a STOP_DET interrupt if - /// STOP_DET_IF_ADDRESSED=1'b1, even if the slave responds to the general call - /// address by generating ACK. The STOP_DET interrupt is generated only when the - /// transmitted address matches the slave address (SAR). - If IC_CON[7]=1'b0 - /// (STOP_DET_IFADDRESSED), the STOP_DET interrupt is issued irrespective of whether - /// it is being addressed. In Master Mode: - If IC_CON[10]=1'b1 - /// (STOP_DET_IF_MASTER_ACTIVE),the STOP_DET interrupt will be issued only if Master - /// is active. - If IC_CON[10]=1'b0 (STOP_DET_IFADDRESSED),the STOP_DET interrupt - /// will be issued irrespective of whether master is active or not. Reset value: 0x0 - STOP_DET: u1, - /// Indicates whether a START or RESTART condition has occurred on the I2C interface - /// regardless of whether DW_apb_i2c is operating in slave or master mode.\n\n - /// Reset value: 0x0 - START_DET: u1, - /// Set only when a General Call address is received and it is acknowledged. It - /// stays set until it is cleared either by disabling DW_apb_i2c or when the CPU - /// reads bit 0 of the IC_CLR_GEN_CALL register. DW_apb_i2c stores the received data - /// in the Rx buffer.\n\n - /// Reset value: 0x0 - GEN_CALL: u1, - /// Indicates whether a RESTART condition has occurred on the I2C interface when - /// DW_apb_i2c is operating in Slave mode and the slave is being addressed. Enabled - /// only when IC_SLV_RESTART_DET_EN=1.\n\n - /// Note: However, in high-speed mode or during a START BYTE transfer, the RESTART - /// comes before the address field as per the I2C protocol. In this case, the slave - /// is not the addressed slave when the RESTART is issued, therefore DW_apb_i2c does - /// not generate the RESTART_DET interrupt.\n\n - /// Reset value: 0x0 - RESTART_DET: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - }), base_address + 0x34); - - /// address: 0x40044038 - /// I2C Receive FIFO Threshold Register - pub const IC_RX_TL = @intToPtr(*volatile Mmio(32, packed struct { - /// Receive FIFO Threshold Level.\n\n - /// Controls the level of entries (or above) that triggers the RX_FULL interrupt - /// (bit 2 in IC_RAW_INTR_STAT register). The valid range is 0-255, with the - /// additional restriction that hardware does not allow this value to be set to a - /// value larger than the depth of the buffer. If an attempt is made to do that, the - /// actual value set will be the maximum depth of the buffer. A value of 0 sets the - /// threshold for 1 entry, and a value of 255 sets the threshold for 256 entries. - RX_TL: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x38); - - /// address: 0x4004403c - /// I2C Transmit FIFO Threshold Register - pub const IC_TX_TL = @intToPtr(*volatile Mmio(32, packed struct { - /// Transmit FIFO Threshold Level.\n\n - /// Controls the level of entries (or below) that trigger the TX_EMPTY interrupt - /// (bit 4 in IC_RAW_INTR_STAT register). The valid range is 0-255, with the - /// additional restriction that it may not be set to value larger than the depth of - /// the buffer. If an attempt is made to do that, the actual value set will be the - /// maximum depth of the buffer. A value of 0 sets the threshold for 0 entries, and - /// a value of 255 sets the threshold for 255 entries. - TX_TL: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x3c); - - /// address: 0x40044040 - /// Clear Combined and Individual Interrupt Register - pub const IC_CLR_INTR = @intToPtr(*volatile Mmio(32, packed struct { - /// Read this register to clear the combined interrupt, all individual interrupts, - /// and the IC_TX_ABRT_SOURCE register. This bit does not clear hardware clearable - /// interrupts but software clearable interrupts. Refer to Bit 9 of the - /// IC_TX_ABRT_SOURCE register for an exception to clearing IC_TX_ABRT_SOURCE.\n\n - /// Reset value: 0x0 - CLR_INTR: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x40); - - /// address: 0x40044044 - /// Clear RX_UNDER Interrupt Register - pub const IC_CLR_RX_UNDER = @intToPtr(*volatile Mmio(32, packed struct { - /// Read this register to clear the RX_UNDER interrupt (bit 0) of the - /// IC_RAW_INTR_STAT register.\n\n - /// Reset value: 0x0 - CLR_RX_UNDER: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x44); - - /// address: 0x40044048 - /// Clear RX_OVER Interrupt Register - pub const IC_CLR_RX_OVER = @intToPtr(*volatile Mmio(32, packed struct { - /// Read this register to clear the RX_OVER interrupt (bit 1) of the - /// IC_RAW_INTR_STAT register.\n\n - /// Reset value: 0x0 - CLR_RX_OVER: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x48); - - /// address: 0x4004404c - /// Clear TX_OVER Interrupt Register - pub const IC_CLR_TX_OVER = @intToPtr(*volatile Mmio(32, packed struct { - /// Read this register to clear the TX_OVER interrupt (bit 3) of the - /// IC_RAW_INTR_STAT register.\n\n - /// Reset value: 0x0 - CLR_TX_OVER: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x4c); - - /// address: 0x40044050 - /// Clear RD_REQ Interrupt Register - pub const IC_CLR_RD_REQ = @intToPtr(*volatile Mmio(32, packed struct { - /// Read this register to clear the RD_REQ interrupt (bit 5) of the IC_RAW_INTR_STAT - /// register.\n\n - /// Reset value: 0x0 - CLR_RD_REQ: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x50); - - /// address: 0x40044054 - /// Clear TX_ABRT Interrupt Register - pub const IC_CLR_TX_ABRT = @intToPtr(*volatile Mmio(32, packed struct { - /// Read this register to clear the TX_ABRT interrupt (bit 6) of the - /// IC_RAW_INTR_STAT register, and the IC_TX_ABRT_SOURCE register. This also - /// releases the TX FIFO from the flushed/reset state, allowing more writes to the - /// TX FIFO. Refer to Bit 9 of the IC_TX_ABRT_SOURCE register for an exception to - /// clearing IC_TX_ABRT_SOURCE.\n\n - /// Reset value: 0x0 - CLR_TX_ABRT: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x54); - - /// address: 0x40044058 - /// Clear RX_DONE Interrupt Register - pub const IC_CLR_RX_DONE = @intToPtr(*volatile Mmio(32, packed struct { - /// Read this register to clear the RX_DONE interrupt (bit 7) of the - /// IC_RAW_INTR_STAT register.\n\n - /// Reset value: 0x0 - CLR_RX_DONE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x58); - - /// address: 0x4004405c - /// Clear ACTIVITY Interrupt Register - pub const IC_CLR_ACTIVITY = @intToPtr(*volatile Mmio(32, packed struct { - /// Reading this register clears the ACTIVITY interrupt if the I2C is not active - /// anymore. If the I2C module is still active on the bus, the ACTIVITY interrupt - /// bit continues to be set. It is automatically cleared by hardware if the module - /// is disabled and if there is no further activity on the bus. The value read from - /// this register to get status of the ACTIVITY interrupt (bit 8) of the - /// IC_RAW_INTR_STAT register.\n\n - /// Reset value: 0x0 - CLR_ACTIVITY: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x5c); - - /// address: 0x40044060 - /// Clear STOP_DET Interrupt Register - pub const IC_CLR_STOP_DET = @intToPtr(*volatile Mmio(32, packed struct { - /// Read this register to clear the STOP_DET interrupt (bit 9) of the - /// IC_RAW_INTR_STAT register.\n\n - /// Reset value: 0x0 - CLR_STOP_DET: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x60); - - /// address: 0x40044064 - /// Clear START_DET Interrupt Register - pub const IC_CLR_START_DET = @intToPtr(*volatile Mmio(32, packed struct { - /// Read this register to clear the START_DET interrupt (bit 10) of the - /// IC_RAW_INTR_STAT register.\n\n - /// Reset value: 0x0 - CLR_START_DET: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x64); - - /// address: 0x40044068 - /// Clear GEN_CALL Interrupt Register - pub const IC_CLR_GEN_CALL = @intToPtr(*volatile Mmio(32, packed struct { - /// Read this register to clear the GEN_CALL interrupt (bit 11) of IC_RAW_INTR_STAT - /// register.\n\n - /// Reset value: 0x0 - CLR_GEN_CALL: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x68); - - /// address: 0x4004406c - /// I2C Enable Register - pub const IC_ENABLE = @intToPtr(*volatile Mmio(32, packed struct { - /// Controls whether the DW_apb_i2c is enabled. - 0: Disables DW_apb_i2c (TX and RX - /// FIFOs are held in an erased state) - 1: Enables DW_apb_i2c Software can disable - /// DW_apb_i2c while it is active. However, it is important that care be taken to - /// ensure that DW_apb_i2c is disabled properly. A recommended procedure is - /// described in 'Disabling DW_apb_i2c'.\n\n - /// When DW_apb_i2c is disabled, the following occurs: - The TX FIFO and RX FIFO get - /// flushed. - Status bits in the IC_INTR_STAT register are still active until - /// DW_apb_i2c goes into IDLE state. If the module is transmitting, it stops as well - /// as deletes the contents of the transmit buffer after the current transfer is - /// complete. If the module is receiving, the DW_apb_i2c stops the current transfer - /// at the end of the current byte and does not acknowledge the transfer.\n\n - /// In systems with asynchronous pclk and ic_clk when IC_CLK_TYPE parameter set to - /// asynchronous (1), there is a two ic_clk delay when enabling or disabling the - /// DW_apb_i2c. For a detailed description on how to disable DW_apb_i2c, refer to - /// 'Disabling DW_apb_i2c'\n\n - /// Reset value: 0x0 - ENABLE: u1, - /// When set, the controller initiates the transfer abort. - 0: ABORT not initiated - /// or ABORT done - 1: ABORT operation in progress The software can abort the I2C - /// transfer in master mode by setting this bit. The software can set this bit only - /// when ENABLE is already set; otherwise, the controller ignores any write to ABORT - /// bit. The software cannot clear the ABORT bit once set. In response to an ABORT, - /// the controller issues a STOP and flushes the Tx FIFO after completing the - /// current transfer, then sets the TX_ABORT interrupt after the abort operation. - /// The ABORT bit is cleared automatically after the abort operation.\n\n - /// For a detailed description on how to abort I2C transfers, refer to 'Aborting I2C - /// Transfers'.\n\n - /// Reset value: 0x0 - ABORT: u1, - /// In Master mode: - 1'b1: Blocks the transmission of data on I2C bus even if Tx - /// FIFO has data to transmit. - 1'b0: The transmission of data starts on I2C bus - /// automatically, as soon as the first data is available in the Tx FIFO. Note: To - /// block the execution of Master commands, set the TX_CMD_BLOCK bit only when Tx - /// FIFO is empty (IC_STATUS[2]==1) and Master is in Idle state (IC_STATUS[5] == 0). - /// Any further commands put in the Tx FIFO are not executed until TX_CMD_BLOCK bit - /// is unset. Reset value: IC_TX_CMD_BLOCK_DEFAULT - TX_CMD_BLOCK: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - }), base_address + 0x6c); - - /// address: 0x40044070 - /// I2C Status Register\n\n - /// This is a read-only register used to indicate the current transfer status and - /// FIFO status. The status register may be read at any time. None of the bits in - /// this register request an interrupt.\n\n - /// When the I2C is disabled by writing 0 in bit 0 of the IC_ENABLE register: - Bits - /// 1 and 2 are set to 1 - Bits 3 and 10 are set to 0 When the master or slave state - /// machines goes to idle and ic_en=0: - Bits 5 and 6 are set to 0 - pub const IC_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - /// I2C Activity Status. Reset value: 0x0 - ACTIVITY: u1, - /// Transmit FIFO Not Full. Set when the transmit FIFO contains one or more empty - /// locations, and is cleared when the FIFO is full. - 0: Transmit FIFO is full - 1: - /// Transmit FIFO is not full Reset value: 0x1 - TFNF: u1, - /// Transmit FIFO Completely Empty. When the transmit FIFO is completely empty, this - /// bit is set. When it contains one or more valid entries, this bit is cleared. - /// This bit field does not request an interrupt. - 0: Transmit FIFO is not empty - - /// 1: Transmit FIFO is empty Reset value: 0x1 - TFE: u1, - /// Receive FIFO Not Empty. This bit is set when the receive FIFO contains one or - /// more entries; it is cleared when the receive FIFO is empty. - 0: Receive FIFO is - /// empty - 1: Receive FIFO is not empty Reset value: 0x0 - RFNE: u1, - /// Receive FIFO Completely Full. When the receive FIFO is completely full, this bit - /// is set. When the receive FIFO contains one or more empty location, this bit is - /// cleared. - 0: Receive FIFO is not full - 1: Receive FIFO is full Reset value: - /// 0x0 - RFF: u1, - /// Master FSM Activity Status. When the Master Finite State Machine (FSM) is not in - /// the IDLE state, this bit is set. - 0: Master FSM is in IDLE state so the Master - /// part of DW_apb_i2c is not Active - 1: Master FSM is not in IDLE state so the - /// Master part of DW_apb_i2c is Active Note: IC_STATUS[0]-that is, ACTIVITY bit-is - /// the OR of SLV_ACTIVITY and MST_ACTIVITY bits.\n\n - /// Reset value: 0x0 - MST_ACTIVITY: u1, - /// Slave FSM Activity Status. When the Slave Finite State Machine (FSM) is not in - /// the IDLE state, this bit is set. - 0: Slave FSM is in IDLE state so the Slave - /// part of DW_apb_i2c is not Active - 1: Slave FSM is not in IDLE state so the - /// Slave part of DW_apb_i2c is Active Reset value: 0x0 - SLV_ACTIVITY: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - }), base_address + 0x70); - - /// address: 0x40044074 - /// I2C Transmit FIFO Level Register This register contains the number of valid data - /// entries in the transmit FIFO buffer. It is cleared whenever: - The I2C is - /// disabled - There is a transmit abort - that is, TX_ABRT bit is set in the - /// IC_RAW_INTR_STAT register - The slave bulk transmit mode is aborted The register - /// increments whenever data is placed into the transmit FIFO and decrements when - /// data is taken from the transmit FIFO. - pub const IC_TXFLR = @intToPtr(*volatile Mmio(32, packed struct { - /// Transmit FIFO Level. Contains the number of valid data entries in the transmit - /// FIFO.\n\n - /// Reset value: 0x0 - TXFLR: u5, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - }), base_address + 0x74); - - /// address: 0x40044078 - /// I2C Receive FIFO Level Register This register contains the number of valid data - /// entries in the receive FIFO buffer. It is cleared whenever: - The I2C is - /// disabled - Whenever there is a transmit abort caused by any of the events - /// tracked in IC_TX_ABRT_SOURCE The register increments whenever data is placed - /// into the receive FIFO and decrements when data is taken from the receive FIFO. - pub const IC_RXFLR = @intToPtr(*volatile Mmio(32, packed struct { - /// Receive FIFO Level. Contains the number of valid data entries in the receive - /// FIFO.\n\n - /// Reset value: 0x0 - RXFLR: u5, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - }), base_address + 0x78); - - /// address: 0x4004407c - /// I2C SDA Hold Time Length Register\n\n - /// The bits [15:0] of this register are used to control the hold time of SDA during - /// transmit in both slave and master mode (after SCL goes from HIGH to LOW).\n\n - /// The bits [23:16] of this register are used to extend the SDA transition (if any) - /// whenever SCL is HIGH in the receiver in either master or slave mode.\n\n - /// Writes to this register succeed only when IC_ENABLE[0]=0.\n\n - /// The values in this register are in units of ic_clk period. The value programmed - /// in IC_SDA_TX_HOLD must be greater than the minimum hold time in each mode (one - /// cycle in master mode, seven cycles in slave mode) for the value to be - /// implemented.\n\n - /// The programmed SDA hold time during transmit (IC_SDA_TX_HOLD) cannot exceed at - /// any time the duration of the low part of scl. Therefore the programmed value - /// cannot be larger than N_SCL_LOW-2, where N_SCL_LOW is the duration of the low - /// part of the scl period measured in ic_clk cycles. - pub const IC_SDA_HOLD = @intToPtr(*volatile Mmio(32, packed struct { - /// Sets the required SDA hold time in units of ic_clk period, when DW_apb_i2c acts - /// as a transmitter.\n\n - /// Reset value: IC_DEFAULT_SDA_HOLD[15:0]. - IC_SDA_TX_HOLD: u16, - /// Sets the required SDA hold time in units of ic_clk period, when DW_apb_i2c acts - /// as a receiver.\n\n - /// Reset value: IC_DEFAULT_SDA_HOLD[23:16]. - IC_SDA_RX_HOLD: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x7c); - - /// address: 0x40044080 - /// I2C Transmit Abort Source Register\n\n - /// This register has 32 bits that indicate the source of the TX_ABRT bit. Except - /// for Bit 9, this register is cleared whenever the IC_CLR_TX_ABRT register or the - /// IC_CLR_INTR register is read. To clear Bit 9, the source of the - /// ABRT_SBYTE_NORSTRT must be fixed first; RESTART must be enabled (IC_CON[5]=1), - /// the SPECIAL bit must be cleared (IC_TAR[11]), or the GC_OR_START bit must be - /// cleared (IC_TAR[10]).\n\n - /// Once the source of the ABRT_SBYTE_NORSTRT is fixed, then this bit can be cleared - /// in the same manner as other bits in this register. If the source of the - /// ABRT_SBYTE_NORSTRT is not fixed before attempting to clear this bit, Bit 9 - /// clears for one cycle and is then re-asserted. - pub const IC_TX_ABRT_SOURCE = @intToPtr(*volatile Mmio(32, packed struct { - /// This field indicates that the Master is in 7-bit addressing mode and the address - /// sent was not acknowledged by any slave.\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver - ABRT_7B_ADDR_NOACK: u1, - /// This field indicates that the Master is in 10-bit address mode and the first - /// 10-bit address byte was not acknowledged by any slave.\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver - ABRT_10ADDR1_NOACK: u1, - /// This field indicates that the Master is in 10-bit address mode and that the - /// second address byte of the 10-bit address was not acknowledged by any slave.\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver - ABRT_10ADDR2_NOACK: u1, - /// This field indicates the master-mode only bit. When the master receives an - /// acknowledgement for the address, but when it sends data byte(s) following the - /// address, it did not receive an acknowledge from the remote slave(s).\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master-Transmitter - ABRT_TXDATA_NOACK: u1, - /// This field indicates that DW_apb_i2c in master mode has sent a General Call and - /// no slave on the bus acknowledged the General Call.\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master-Transmitter - ABRT_GCALL_NOACK: u1, - /// This field indicates that DW_apb_i2c in the master mode has sent a General Call - /// but the user programmed the byte following the General Call to be a read from - /// the bus (IC_DATA_CMD[9] is set to 1).\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master-Transmitter - ABRT_GCALL_READ: u1, - /// This field indicates that the Master is in High Speed mode and the High Speed - /// Master code was acknowledged (wrong behavior).\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master - ABRT_HS_ACKDET: u1, - /// This field indicates that the Master has sent a START Byte and the START Byte - /// was acknowledged (wrong behavior).\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master - ABRT_SBYTE_ACKDET: u1, - /// This field indicates that the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) - /// =0) and the user is trying to use the master to transfer data in High Speed - /// mode.\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver - ABRT_HS_NORSTRT: u1, - /// To clear Bit 9, the source of the ABRT_SBYTE_NORSTRT must be fixed first; - /// restart must be enabled (IC_CON[5]=1), the SPECIAL bit must be cleared - /// (IC_TAR[11]), or the GC_OR_START bit must be cleared (IC_TAR[10]). Once the - /// source of the ABRT_SBYTE_NORSTRT is fixed, then this bit can be cleared in the - /// same manner as other bits in this register. If the source of the - /// ABRT_SBYTE_NORSTRT is not fixed before attempting to clear this bit, bit 9 - /// clears for one cycle and then gets reasserted. When this field is set to 1, the - /// restart is disabled (IC_RESTART_EN bit (IC_CON[5]) =0) and the user is trying to - /// send a START Byte.\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master - ABRT_SBYTE_NORSTRT: u1, - /// This field indicates that the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) - /// =0) and the master sends a read command in 10-bit addressing mode.\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master-Receiver - ABRT_10B_RD_NORSTRT: u1, - /// This field indicates that the User tries to initiate a Master operation with the - /// Master mode disabled.\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver - ABRT_MASTER_DIS: u1, - /// This field specifies that the Master has lost arbitration, or if - /// IC_TX_ABRT_SOURCE[14] is also set, then the slave transmitter has lost - /// arbitration.\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master-Transmitter or Slave-Transmitter - ARB_LOST: u1, - /// This field specifies that the Slave has received a read command and some data - /// exists in the TX FIFO, so the slave issues a TX_ABRT interrupt to flush old data - /// in TX FIFO.\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Slave-Transmitter - ABRT_SLVFLUSH_TXFIFO: u1, - /// This field indicates that a Slave has lost the bus while transmitting data to a - /// remote master. IC_TX_ABRT_SOURCE[12] is set at the same time. Note: Even though - /// the slave never 'owns' the bus, something could go wrong on the bus. This is a - /// fail safe check. For instance, during a data transmission at the low-to-high - /// transition of SCL, if what is on the data bus is not what is supposed to be - /// transmitted, then DW_apb_i2c no longer own the bus.\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Slave-Transmitter - ABRT_SLV_ARBLOST: u1, - /// 1: When the processor side responds to a slave mode request for data to be - /// transmitted to a remote master and user writes a 1 in CMD (bit 8) of IC_DATA_CMD - /// register.\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Slave-Transmitter - ABRT_SLVRD_INTX: u1, - /// This is a master-mode-only bit. Master has detected the transfer abort - /// (IC_ENABLE[1])\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master-Transmitter - ABRT_USER_ABRT: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - /// This field indicates the number of Tx FIFO Data Commands which are flushed due - /// to TX_ABRT interrupt. It is cleared whenever I2C is disabled.\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master-Transmitter or Slave-Transmitter - TX_FLUSH_CNT: u9, - }), base_address + 0x80); - - /// address: 0x40044084 - /// Generate Slave Data NACK Register\n\n - /// The register is used to generate a NACK for the data part of a transfer when - /// DW_apb_i2c is acting as a slave-receiver. This register only exists when the - /// IC_SLV_DATA_NACK_ONLY parameter is set to 1. When this parameter disabled, this - /// register does not exist and writing to the register's address has no effect.\n\n - /// A write can occur on this register if both of the following conditions are met: - /// - DW_apb_i2c is disabled (IC_ENABLE[0] = 0) - Slave part is inactive - /// (IC_STATUS[6] = 0) Note: The IC_STATUS[6] is a register read-back location for - /// the internal slv_activity signal; the user should poll this before writing the - /// ic_slv_data_nack_only bit. - pub const IC_SLV_DATA_NACK_ONLY = @intToPtr(*volatile Mmio(32, packed struct { - /// Generate NACK. This NACK generation only occurs when DW_apb_i2c is a - /// slave-receiver. If this register is set to a value of 1, it can only generate a - /// NACK after a data byte is received; hence, the data transfer is aborted and the - /// data received is not pushed to the receive buffer.\n\n - /// When the register is set to a value of 0, it generates NACK/ACK, depending on - /// normal criteria. - 1: generate NACK after data byte received - 0: generate - /// NACK/ACK normally Reset value: 0x0 - NACK: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x84); - - /// address: 0x40044088 - /// DMA Control Register\n\n - /// The register is used to enable the DMA Controller interface operation. There is - /// a separate bit for transmit and receive. This can be programmed regardless of - /// the state of IC_ENABLE. - pub const IC_DMA_CR = @intToPtr(*volatile Mmio(32, packed struct { - /// Receive DMA Enable. This bit enables/disables the receive FIFO DMA channel. - /// Reset value: 0x0 - RDMAE: u1, - /// Transmit DMA Enable. This bit enables/disables the transmit FIFO DMA channel. - /// Reset value: 0x0 - TDMAE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - }), base_address + 0x88); - - /// address: 0x4004408c - /// DMA Transmit Data Level Register - pub const IC_DMA_TDLR = @intToPtr(*volatile Mmio(32, packed struct { - /// Transmit Data Level. This bit field controls the level at which a DMA request is - /// made by the transmit logic. It is equal to the watermark level; that is, the - /// dma_tx_req signal is generated when the number of valid data entries in the - /// transmit FIFO is equal to or below this field value, and TDMAE = 1.\n\n - /// Reset value: 0x0 - DMATDL: u4, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - }), base_address + 0x8c); - - /// address: 0x40044090 - /// I2C Receive Data Level Register - pub const IC_DMA_RDLR = @intToPtr(*volatile Mmio(32, packed struct { - /// Receive Data Level. This bit field controls the level at which a DMA request is - /// made by the receive logic. The watermark level = DMARDL+1; that is, dma_rx_req - /// is generated when the number of valid data entries in the receive FIFO is equal - /// to or more than this field value + 1, and RDMAE =1. For instance, when DMARDL is - /// 0, then dma_rx_req is asserted when 1 or more data entries are present in the - /// receive FIFO.\n\n - /// Reset value: 0x0 - DMARDL: u4, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - }), base_address + 0x90); - - /// address: 0x40044094 - /// I2C SDA Setup Register\n\n - /// This register controls the amount of time delay (in terms of number of ic_clk - /// clock periods) introduced in the rising edge of SCL - relative to SDA changing - - /// when DW_apb_i2c services a read request in a slave-transmitter operation. The - /// relevant I2C requirement is tSU:DAT (note 4) as detailed in the I2C Bus - /// Specification. This register must be programmed with a value equal to or greater - /// than 2.\n\n - /// Writes to this register succeed only when IC_ENABLE[0] = 0.\n\n - /// Note: The length of setup time is calculated using [(IC_SDA_SETUP - 1) * - /// (ic_clk_period)], so if the user requires 10 ic_clk periods of setup time, they - /// should program a value of 11. The IC_SDA_SETUP register is only used by the - /// DW_apb_i2c when operating as a slave transmitter. - pub const IC_SDA_SETUP = @intToPtr(*volatile Mmio(32, packed struct { - /// SDA Setup. It is recommended that if the required delay is 1000ns, then for an - /// ic_clk frequency of 10 MHz, IC_SDA_SETUP should be programmed to a value of 11. - /// IC_SDA_SETUP must be programmed with a minimum value of 2. - SDA_SETUP: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x94); - - /// address: 0x40044098 - /// I2C ACK General Call Register\n\n - /// The register controls whether DW_apb_i2c responds with a ACK or NACK when it - /// receives an I2C General Call address.\n\n - /// This register is applicable only when the DW_apb_i2c is in slave mode. - pub const IC_ACK_GENERAL_CALL = @intToPtr(*volatile Mmio(32, packed struct { - /// ACK General Call. When set to 1, DW_apb_i2c responds with a ACK (by asserting - /// ic_data_oe) when it receives a General Call. Otherwise, DW_apb_i2c responds with - /// a NACK (by negating ic_data_oe). - ACK_GEN_CALL: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x98); - - /// address: 0x4004409c - /// I2C Enable Status Register\n\n - /// The register is used to report the DW_apb_i2c hardware status when the - /// IC_ENABLE[0] register is set from 1 to 0; that is, when DW_apb_i2c is - /// disabled.\n\n - /// If IC_ENABLE[0] has been set to 1, bits 2:1 are forced to 0, and bit 0 is forced - /// to 1.\n\n - /// If IC_ENABLE[0] has been set to 0, bits 2:1 is only be valid as soon as bit 0 is - /// read as '0'.\n\n - /// Note: When IC_ENABLE[0] has been set to 0, a delay occurs for bit 0 to be read - /// as 0 because disabling the DW_apb_i2c depends on I2C bus activities. - pub const IC_ENABLE_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - /// ic_en Status. This bit always reflects the value driven on the output port - /// ic_en. - When read as 1, DW_apb_i2c is deemed to be in an enabled state. - When - /// read as 0, DW_apb_i2c is deemed completely inactive. Note: The CPU can safely - /// read this bit anytime. When this bit is read as 0, the CPU can safely read - /// SLV_RX_DATA_LOST (bit 2) and SLV_DISABLED_WHILE_BUSY (bit 1).\n\n - /// Reset value: 0x0 - IC_EN: u1, - /// Slave Disabled While Busy (Transmit, Receive). This bit indicates if a potential - /// or active Slave operation has been aborted due to the setting bit 0 of the - /// IC_ENABLE register from 1 to 0. This bit is set when the CPU writes a 0 to the - /// IC_ENABLE register while:\n\n - /// (a) DW_apb_i2c is receiving the address byte of the Slave-Transmitter operation - /// from a remote master;\n\n - /// OR,\n\n - /// (b) address and data bytes of the Slave-Receiver operation from a remote - /// master.\n\n - /// When read as 1, DW_apb_i2c is deemed to have forced a NACK during any part of an - /// I2C transfer, irrespective of whether the I2C address matches the slave address - /// set in DW_apb_i2c (IC_SAR register) OR if the transfer is completed before - /// IC_ENABLE is set to 0 but has not taken effect.\n\n - /// Note: If the remote I2C master terminates the transfer with a STOP condition - /// before the DW_apb_i2c has a chance to NACK a transfer, and IC_ENABLE[0] has been - /// set to 0, then this bit will also be set to 1.\n\n - /// When read as 0, DW_apb_i2c is deemed to have been disabled when there is master - /// activity, or when the I2C bus is idle.\n\n - /// Note: The CPU can safely read this bit when IC_EN (bit 0) is read as 0.\n\n - /// Reset value: 0x0 - SLV_DISABLED_WHILE_BUSY: u1, - /// Slave Received Data Lost. This bit indicates if a Slave-Receiver operation has - /// been aborted with at least one data byte received from an I2C transfer due to - /// the setting bit 0 of IC_ENABLE from 1 to 0. When read as 1, DW_apb_i2c is deemed - /// to have been actively engaged in an aborted I2C transfer (with matching address) - /// and the data phase of the I2C transfer has been entered, even though a data byte - /// has been responded with a NACK.\n\n - /// Note: If the remote I2C master terminates the transfer with a STOP condition - /// before the DW_apb_i2c has a chance to NACK a transfer, and IC_ENABLE[0] has been - /// set to 0, then this bit is also set to 1.\n\n - /// When read as 0, DW_apb_i2c is deemed to have been disabled without being - /// actively involved in the data phase of a Slave-Receiver transfer.\n\n - /// Note: The CPU can safely read this bit when IC_EN (bit 0) is read as 0.\n\n - /// Reset value: 0x0 - SLV_RX_DATA_LOST: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - }), base_address + 0x9c); - - /// address: 0x400440a0 - /// I2C SS, FS or FM+ spike suppression limit\n\n - /// This register is used to store the duration, measured in ic_clk cycles, of the - /// longest spike that is filtered out by the spike suppression logic when the - /// component is operating in SS, FS or FM+ modes. The relevant I2C requirement is - /// tSP (table 4) as detailed in the I2C Bus Specification. This register must be - /// programmed with a minimum value of 1. - pub const IC_FS_SPKLEN = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xa0); - - /// address: 0x400440a8 - /// Clear RESTART_DET Interrupt Register - pub const IC_CLR_RESTART_DET = @intToPtr(*volatile Mmio(32, packed struct { - /// Read this register to clear the RESTART_DET interrupt (bit 12) of - /// IC_RAW_INTR_STAT register.\n\n - /// Reset value: 0x0 - CLR_RESTART_DET: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0xa8); - - /// address: 0x400440f4 - /// Component Parameter Register 1\n\n - /// Note This register is not implemented and therefore reads as 0. If it was - /// implemented it would be a constant read-only register that contains encoded - /// information about the component's parameter settings. Fields shown below are the - /// settings for those parameters - pub const IC_COMP_PARAM_1 = @intToPtr(*volatile Mmio(32, packed struct { - /// APB data bus width is 32 bits - APB_DATA_WIDTH: u2, - /// MAX SPEED MODE = FAST MODE - MAX_SPEED_MODE: u2, - /// Programmable count values for each mode. - HC_COUNT_VALUES: u1, - /// COMBINED Interrupt outputs - INTR_IO: u1, - /// DMA handshaking signals are enabled - HAS_DMA: u1, - /// Encoded parameters not visible - ADD_ENCODED_PARAMS: u1, - /// RX Buffer Depth = 16 - RX_BUFFER_DEPTH: u8, - /// TX Buffer Depth = 16 - TX_BUFFER_DEPTH: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0xf4); - - /// address: 0x400440f8 - /// I2C Component Version Register - pub const IC_COMP_VERSION = @intToPtr(*volatile u32, base_address + 0xf8); - - /// address: 0x400440fc - /// I2C Component Type Register - pub const IC_COMP_TYPE = @intToPtr(*volatile u32, base_address + 0xfc); - }; - pub const I2C1 = struct { - pub const base_address = 0x40048000; - - /// address: 0x40048000 - /// I2C Control Register. This register can be written only when the DW_apb_i2c is - /// disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes - /// at other times have no effect.\n\n - /// Read/Write Access: - bit 10 is read only. - bit 11 is read only - bit 16 is read - /// only - bit 17 is read only - bits 18 and 19 are read only. - pub const IC_CON = @intToPtr(*volatile Mmio(32, packed struct { - /// This bit controls whether the DW_apb_i2c master is enabled.\n\n - /// NOTE: Software should ensure that if this bit is written with '1' then bit 6 - /// should also be written with a '1'. - MASTER_MODE: u1, - /// These bits control at which speed the DW_apb_i2c operates; its setting is - /// relevant only if one is operating the DW_apb_i2c in master mode. Hardware - /// protects against illegal values being programmed by software. These bits must be - /// programmed appropriately for slave mode also, as it is used to capture correct - /// value of spike filter as per the speed mode.\n\n - /// This register should be programmed only with a value in the range of 1 to - /// IC_MAX_SPEED_MODE; otherwise, hardware updates this register with the value of - /// IC_MAX_SPEED_MODE.\n\n - /// 1: standard mode (100 kbit/s)\n\n - /// 2: fast mode (<=400 kbit/s) or fast mode plus (<=1000Kbit/s)\n\n - /// 3: high speed mode (3.4 Mbit/s)\n\n - /// Note: This field is not applicable when IC_ULTRA_FAST_MODE=1 - SPEED: u2, - /// When acting as a slave, this bit controls whether the DW_apb_i2c responds to 7- - /// or 10-bit addresses. - 0: 7-bit addressing. The DW_apb_i2c ignores transactions - /// that involve 10-bit addressing; for 7-bit addressing, only the lower 7 bits of - /// the IC_SAR register are compared. - 1: 10-bit addressing. The DW_apb_i2c - /// responds to only 10-bit addressing transfers that match the full 10 bits of the - /// IC_SAR register. - IC_10BITADDR_SLAVE: u1, - /// Controls whether the DW_apb_i2c starts its transfers in 7- or 10-bit addressing - /// mode when acting as a master. - 0: 7-bit addressing - 1: 10-bit addressing - IC_10BITADDR_MASTER: u1, - /// Determines whether RESTART conditions may be sent when acting as a master. Some - /// older slaves do not support handling RESTART conditions; however, RESTART - /// conditions are used in several DW_apb_i2c operations. When RESTART is disabled, - /// the master is prohibited from performing the following functions: - Sending a - /// START BYTE - Performing any high-speed mode operation - High-speed mode - /// operation - Performing direction changes in combined format mode - Performing a - /// read operation with a 10-bit address By replacing RESTART condition followed by - /// a STOP and a subsequent START condition, split operations are broken down into - /// multiple DW_apb_i2c transfers. If the above operations are performed, it will - /// result in setting bit 6 (TX_ABRT) of the IC_RAW_INTR_STAT register.\n\n - /// Reset value: ENABLED - IC_RESTART_EN: u1, - /// This bit controls whether I2C has its slave disabled, which means once the - /// presetn signal is applied, then this bit is set and the slave is disabled.\n\n - /// If this bit is set (slave is disabled), DW_apb_i2c functions only as a master - /// and does not perform any action that requires a slave.\n\n - /// NOTE: Software should ensure that if this bit is written with 0, then bit 0 - /// should also be written with a 0. - IC_SLAVE_DISABLE: u1, - /// In slave mode: - 1'b1: issues the STOP_DET interrupt only when it is addressed. - /// - 1'b0: issues the STOP_DET irrespective of whether it's addressed or not. Reset - /// value: 0x0\n\n - /// NOTE: During a general call address, this slave does not issue the STOP_DET - /// interrupt if STOP_DET_IF_ADDRESSED = 1'b1, even if the slave responds to the - /// general call address by generating ACK. The STOP_DET interrupt is generated only - /// when the transmitted address matches the slave address (SAR). - STOP_DET_IFADDRESSED: u1, - /// This bit controls the generation of the TX_EMPTY interrupt, as described in the - /// IC_RAW_INTR_STAT register.\n\n - /// Reset value: 0x0. - TX_EMPTY_CTRL: u1, - /// This bit controls whether DW_apb_i2c should hold the bus when the Rx FIFO is - /// physically full to its RX_BUFFER_DEPTH, as described in the - /// IC_RX_FULL_HLD_BUS_EN parameter.\n\n - /// Reset value: 0x0. - RX_FIFO_FULL_HLD_CTRL: u1, - /// Master issues the STOP_DET interrupt irrespective of whether master is active or - /// not - STOP_DET_IF_MASTER_ACTIVE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - }), base_address + 0x0); - - /// address: 0x40048004 - /// I2C Target Address Register\n\n - /// This register is 12 bits wide, and bits 31:12 are reserved. This register can be - /// written to only when IC_ENABLE[0] is set to 0.\n\n - /// Note: If the software or application is aware that the DW_apb_i2c is not using - /// the TAR address for the pending commands in the Tx FIFO, then it is possible to - /// update the TAR address even while the Tx FIFO has entries (IC_STATUS[2]= 0). - - /// It is not necessary to perform any write to this register if DW_apb_i2c is - /// enabled as an I2C slave only. - pub const IC_TAR = @intToPtr(*volatile Mmio(32, packed struct { - /// This is the target address for any master transaction. When transmitting a - /// General Call, these bits are ignored. To generate a START BYTE, the CPU needs to - /// write only once into these bits.\n\n - /// If the IC_TAR and IC_SAR are the same, loopback exists but the FIFOs are shared - /// between master and slave, so full loopback is not feasible. Only one direction - /// loopback mode is supported (simplex), not duplex. A master cannot transmit to - /// itself; it can transmit to only a slave. - IC_TAR: u10, - /// If bit 11 (SPECIAL) is set to 1 and bit 13(Device-ID) is set to 0, then this bit - /// indicates whether a General Call or START byte command is to be performed by the - /// DW_apb_i2c. - 0: General Call Address - after issuing a General Call, only - /// writes may be performed. Attempting to issue a read command results in setting - /// bit 6 (TX_ABRT) of the IC_RAW_INTR_STAT register. The DW_apb_i2c remains in - /// General Call mode until the SPECIAL bit value (bit 11) is cleared. - 1: START - /// BYTE Reset value: 0x0 - GC_OR_START: u1, - /// This bit indicates whether software performs a Device-ID or General Call or - /// START BYTE command. - 0: ignore bit 10 GC_OR_START and use IC_TAR normally - 1: - /// perform special I2C command as specified in Device_ID or GC_OR_START bit Reset - /// value: 0x0 - SPECIAL: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x4); - - /// address: 0x40048008 - /// I2C Slave Address Register - pub const IC_SAR = @intToPtr(*volatile MmioInt(32, u10), base_address + 0x8); - - /// address: 0x40048010 - /// I2C Rx/Tx Data Buffer and Command Register; this is the register the CPU writes - /// to when filling the TX FIFO and the CPU reads from when retrieving bytes from RX - /// FIFO.\n\n - /// The size of the register changes as follows:\n\n - /// Write: - 11 bits when IC_EMPTYFIFO_HOLD_MASTER_EN=1 - 9 bits when - /// IC_EMPTYFIFO_HOLD_MASTER_EN=0 Read: - 12 bits when IC_FIRST_DATA_BYTE_STATUS = 1 - /// - 8 bits when IC_FIRST_DATA_BYTE_STATUS = 0 Note: In order for the DW_apb_i2c to - /// continue acknowledging reads, a read command should be written for every byte - /// that is to be received; otherwise the DW_apb_i2c will stop acknowledging. - pub const IC_DATA_CMD = @intToPtr(*volatile Mmio(32, packed struct { - /// This register contains the data to be transmitted or received on the I2C bus. If - /// you are writing to this register and want to perform a read, bits 7:0 (DAT) are - /// ignored by the DW_apb_i2c. However, when you read this register, these bits - /// return the value of data received on the DW_apb_i2c interface.\n\n - /// Reset value: 0x0 - DAT: u8, - /// This bit controls whether a read or a write is performed. This bit does not - /// control the direction when the DW_apb_i2con acts as a slave. It controls only - /// the direction when it acts as a master.\n\n - /// When a command is entered in the TX FIFO, this bit distinguishes the write and - /// read commands. In slave-receiver mode, this bit is a 'don't care' because writes - /// to this register are not required. In slave-transmitter mode, a '0' indicates - /// that the data in IC_DATA_CMD is to be transmitted.\n\n - /// When programming this bit, you should remember the following: attempting to - /// perform a read operation after a General Call command has been sent results in a - /// TX_ABRT interrupt (bit 6 of the IC_RAW_INTR_STAT register), unless bit 11 - /// (SPECIAL) in the IC_TAR register has been cleared. If a '1' is written to this - /// bit after receiving a RD_REQ interrupt, then a TX_ABRT interrupt occurs.\n\n - /// Reset value: 0x0 - CMD: u1, - /// This bit controls whether a STOP is issued after the byte is sent or - /// received.\n\n - /// - 1 - STOP is issued after this byte, regardless of whether or not the Tx FIFO - /// is empty. If the Tx FIFO is not empty, the master immediately tries to start a - /// new transfer by issuing a START and arbitrating for the bus. - 0 - STOP is not - /// issued after this byte, regardless of whether or not the Tx FIFO is empty. If - /// the Tx FIFO is not empty, the master continues the current transfer by - /// sending/receiving data bytes according to the value of the CMD bit. If the Tx - /// FIFO is empty, the master holds the SCL line low and stalls the bus until a new - /// command is available in the Tx FIFO. Reset value: 0x0 - STOP: u1, - /// This bit controls whether a RESTART is issued before the byte is sent or - /// received.\n\n - /// 1 - If IC_RESTART_EN is 1, a RESTART is issued before the data is sent/received - /// (according to the value of CMD), regardless of whether or not the transfer - /// direction is changing from the previous command; if IC_RESTART_EN is 0, a STOP - /// followed by a START is issued instead.\n\n - /// 0 - If IC_RESTART_EN is 1, a RESTART is issued only if the transfer direction is - /// changing from the previous command; if IC_RESTART_EN is 0, a STOP followed by a - /// START is issued instead.\n\n - /// Reset value: 0x0 - RESTART: u1, - /// Indicates the first data byte received after the address phase for receive - /// transfer in Master receiver or Slave receiver mode.\n\n - /// Reset value : 0x0\n\n - /// NOTE: In case of APB_DATA_WIDTH=8,\n\n - /// 1. The user has to perform two APB Reads to IC_DATA_CMD in order to get status - /// on 11 bit.\n\n - /// 2. In order to read the 11 bit, the user has to perform the first data byte read - /// [7:0] (offset 0x10) and then perform the second read [15:8] (offset 0x11) in - /// order to know the status of 11 bit (whether the data received in previous read - /// is a first data byte or not).\n\n - /// 3. The 11th bit is an optional read field, user can ignore 2nd byte read [15:8] - /// (offset 0x11) if not interested in FIRST_DATA_BYTE status. - FIRST_DATA_BYTE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x10); - - /// address: 0x40048014 - /// Standard Speed I2C Clock SCL High Count Register - pub const IC_SS_SCL_HCNT = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x14); - - /// address: 0x40048018 - /// Standard Speed I2C Clock SCL Low Count Register - pub const IC_SS_SCL_LCNT = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x18); - - /// address: 0x4004801c - /// Fast Mode or Fast Mode Plus I2C Clock SCL High Count Register - pub const IC_FS_SCL_HCNT = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x1c); - - /// address: 0x40048020 - /// Fast Mode or Fast Mode Plus I2C Clock SCL Low Count Register - pub const IC_FS_SCL_LCNT = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x20); - - /// address: 0x4004802c - /// I2C Interrupt Status Register\n\n - /// Each bit in this register has a corresponding mask bit in the IC_INTR_MASK - /// register. These bits are cleared by reading the matching interrupt clear - /// register. The unmasked raw versions of these bits are available in the - /// IC_RAW_INTR_STAT register. - pub const IC_INTR_STAT = @intToPtr(*volatile Mmio(32, packed struct { - /// See IC_RAW_INTR_STAT for a detailed description of R_RX_UNDER bit.\n\n - /// Reset value: 0x0 - R_RX_UNDER: u1, - /// See IC_RAW_INTR_STAT for a detailed description of R_RX_OVER bit.\n\n - /// Reset value: 0x0 - R_RX_OVER: u1, - /// See IC_RAW_INTR_STAT for a detailed description of R_RX_FULL bit.\n\n - /// Reset value: 0x0 - R_RX_FULL: u1, - /// See IC_RAW_INTR_STAT for a detailed description of R_TX_OVER bit.\n\n - /// Reset value: 0x0 - R_TX_OVER: u1, - /// See IC_RAW_INTR_STAT for a detailed description of R_TX_EMPTY bit.\n\n - /// Reset value: 0x0 - R_TX_EMPTY: u1, - /// See IC_RAW_INTR_STAT for a detailed description of R_RD_REQ bit.\n\n - /// Reset value: 0x0 - R_RD_REQ: u1, - /// See IC_RAW_INTR_STAT for a detailed description of R_TX_ABRT bit.\n\n - /// Reset value: 0x0 - R_TX_ABRT: u1, - /// See IC_RAW_INTR_STAT for a detailed description of R_RX_DONE bit.\n\n - /// Reset value: 0x0 - R_RX_DONE: u1, - /// See IC_RAW_INTR_STAT for a detailed description of R_ACTIVITY bit.\n\n - /// Reset value: 0x0 - R_ACTIVITY: u1, - /// See IC_RAW_INTR_STAT for a detailed description of R_STOP_DET bit.\n\n - /// Reset value: 0x0 - R_STOP_DET: u1, - /// See IC_RAW_INTR_STAT for a detailed description of R_START_DET bit.\n\n - /// Reset value: 0x0 - R_START_DET: u1, - /// See IC_RAW_INTR_STAT for a detailed description of R_GEN_CALL bit.\n\n - /// Reset value: 0x0 - R_GEN_CALL: u1, - /// See IC_RAW_INTR_STAT for a detailed description of R_RESTART_DET bit.\n\n - /// Reset value: 0x0 - R_RESTART_DET: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - }), base_address + 0x2c); - - /// address: 0x40048030 - /// I2C Interrupt Mask Register.\n\n - /// These bits mask their corresponding interrupt status bits. This register is - /// active low; a value of 0 masks the interrupt, whereas a value of 1 unmasks the - /// interrupt. - pub const IC_INTR_MASK = @intToPtr(*volatile Mmio(32, packed struct { - /// This bit masks the R_RX_UNDER interrupt in IC_INTR_STAT register.\n\n - /// Reset value: 0x1 - M_RX_UNDER: u1, - /// This bit masks the R_RX_OVER interrupt in IC_INTR_STAT register.\n\n - /// Reset value: 0x1 - M_RX_OVER: u1, - /// This bit masks the R_RX_FULL interrupt in IC_INTR_STAT register.\n\n - /// Reset value: 0x1 - M_RX_FULL: u1, - /// This bit masks the R_TX_OVER interrupt in IC_INTR_STAT register.\n\n - /// Reset value: 0x1 - M_TX_OVER: u1, - /// This bit masks the R_TX_EMPTY interrupt in IC_INTR_STAT register.\n\n - /// Reset value: 0x1 - M_TX_EMPTY: u1, - /// This bit masks the R_RD_REQ interrupt in IC_INTR_STAT register.\n\n - /// Reset value: 0x1 - M_RD_REQ: u1, - /// This bit masks the R_TX_ABRT interrupt in IC_INTR_STAT register.\n\n - /// Reset value: 0x1 - M_TX_ABRT: u1, - /// This bit masks the R_RX_DONE interrupt in IC_INTR_STAT register.\n\n - /// Reset value: 0x1 - M_RX_DONE: u1, - /// This bit masks the R_ACTIVITY interrupt in IC_INTR_STAT register.\n\n - /// Reset value: 0x0 - M_ACTIVITY: u1, - /// This bit masks the R_STOP_DET interrupt in IC_INTR_STAT register.\n\n - /// Reset value: 0x0 - M_STOP_DET: u1, - /// This bit masks the R_START_DET interrupt in IC_INTR_STAT register.\n\n - /// Reset value: 0x0 - M_START_DET: u1, - /// This bit masks the R_GEN_CALL interrupt in IC_INTR_STAT register.\n\n - /// Reset value: 0x1 - M_GEN_CALL: u1, - /// This bit masks the R_RESTART_DET interrupt in IC_INTR_STAT register.\n\n - /// Reset value: 0x0 - M_RESTART_DET: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - }), base_address + 0x30); - - /// address: 0x40048034 - /// I2C Raw Interrupt Status Register\n\n - /// Unlike the IC_INTR_STAT register, these bits are not masked so they always show - /// the true status of the DW_apb_i2c. - pub const IC_RAW_INTR_STAT = @intToPtr(*volatile Mmio(32, packed struct { - /// Set if the processor attempts to read the receive buffer when it is empty by - /// reading from the IC_DATA_CMD register. If the module is disabled - /// (IC_ENABLE[0]=0), this bit keeps its level until the master or slave state - /// machines go into idle, and when ic_en goes to 0, this interrupt is cleared.\n\n - /// Reset value: 0x0 - RX_UNDER: u1, - /// Set if the receive buffer is completely filled to IC_RX_BUFFER_DEPTH and an - /// additional byte is received from an external I2C device. The DW_apb_i2c - /// acknowledges this, but any data bytes received after the FIFO is full are lost. - /// If the module is disabled (IC_ENABLE[0]=0), this bit keeps its level until the - /// master or slave state machines go into idle, and when ic_en goes to 0, this - /// interrupt is cleared.\n\n - /// Note: If bit 9 of the IC_CON register (RX_FIFO_FULL_HLD_CTRL) is programmed to - /// HIGH, then the RX_OVER interrupt never occurs, because the Rx FIFO never - /// overflows.\n\n - /// Reset value: 0x0 - RX_OVER: u1, - /// Set when the receive buffer reaches or goes above the RX_TL threshold in the - /// IC_RX_TL register. It is automatically cleared by hardware when buffer level - /// goes below the threshold. If the module is disabled (IC_ENABLE[0]=0), the RX - /// FIFO is flushed and held in reset; therefore the RX FIFO is not full. So this - /// bit is cleared once the IC_ENABLE bit 0 is programmed with a 0, regardless of - /// the activity that continues.\n\n - /// Reset value: 0x0 - RX_FULL: u1, - /// Set during transmit if the transmit buffer is filled to IC_TX_BUFFER_DEPTH and - /// the processor attempts to issue another I2C command by writing to the - /// IC_DATA_CMD register. When the module is disabled, this bit keeps its level - /// until the master or slave state machines go into idle, and when ic_en goes to 0, - /// this interrupt is cleared.\n\n - /// Reset value: 0x0 - TX_OVER: u1, - /// The behavior of the TX_EMPTY interrupt status differs based on the TX_EMPTY_CTRL - /// selection in the IC_CON register. - When TX_EMPTY_CTRL = 0: This bit is set to 1 - /// when the transmit buffer is at or below the threshold value set in the IC_TX_TL - /// register. - When TX_EMPTY_CTRL = 1: This bit is set to 1 when the transmit - /// buffer is at or below the threshold value set in the IC_TX_TL register and the - /// transmission of the address/data from the internal shift register for the most - /// recently popped command is completed. It is automatically cleared by hardware - /// when the buffer level goes above the threshold. When IC_ENABLE[0] is set to 0, - /// the TX FIFO is flushed and held in reset. There the TX FIFO looks like it has no - /// data within it, so this bit is set to 1, provided there is activity in the - /// master or slave state machines. When there is no longer any activity, then with - /// ic_en=0, this bit is set to 0.\n\n - /// Reset value: 0x0. - TX_EMPTY: u1, - /// This bit is set to 1 when DW_apb_i2c is acting as a slave and another I2C master - /// is attempting to read data from DW_apb_i2c. The DW_apb_i2c holds the I2C bus in - /// a wait state (SCL=0) until this interrupt is serviced, which means that the - /// slave has been addressed by a remote master that is asking for data to be - /// transferred. The processor must respond to this interrupt and then write the - /// requested data to the IC_DATA_CMD register. This bit is set to 0 just after the - /// processor reads the IC_CLR_RD_REQ register.\n\n - /// Reset value: 0x0 - RD_REQ: u1, - /// This bit indicates if DW_apb_i2c, as an I2C transmitter, is unable to complete - /// the intended actions on the contents of the transmit FIFO. This situation can - /// occur both as an I2C master or an I2C slave, and is referred to as a 'transmit - /// abort'. When this bit is set to 1, the IC_TX_ABRT_SOURCE register indicates the - /// reason why the transmit abort takes places.\n\n - /// Note: The DW_apb_i2c flushes/resets/empties the TX_FIFO and RX_FIFO whenever - /// there is a transmit abort caused by any of the events tracked by the - /// IC_TX_ABRT_SOURCE register. The FIFOs remains in this flushed state until the - /// register IC_CLR_TX_ABRT is read. Once this read is performed, the Tx FIFO is - /// then ready to accept more data bytes from the APB interface.\n\n - /// Reset value: 0x0 - TX_ABRT: u1, - /// When the DW_apb_i2c is acting as a slave-transmitter, this bit is set to 1 if - /// the master does not acknowledge a transmitted byte. This occurs on the last byte - /// of the transmission, indicating that the transmission is done.\n\n - /// Reset value: 0x0 - RX_DONE: u1, - /// This bit captures DW_apb_i2c activity and stays set until it is cleared. There - /// are four ways to clear it: - Disabling the DW_apb_i2c - Reading the - /// IC_CLR_ACTIVITY register - Reading the IC_CLR_INTR register - System reset Once - /// this bit is set, it stays set unless one of the four methods is used to clear - /// it. Even if the DW_apb_i2c module is idle, this bit remains set until cleared, - /// indicating that there was activity on the bus.\n\n - /// Reset value: 0x0 - ACTIVITY: u1, - /// Indicates whether a STOP condition has occurred on the I2C interface regardless - /// of whether DW_apb_i2c is operating in slave or master mode.\n\n - /// In Slave Mode: - If IC_CON[7]=1'b1 (STOP_DET_IFADDRESSED), the STOP_DET - /// interrupt will be issued only if slave is addressed. Note: During a general call - /// address, this slave does not issue a STOP_DET interrupt if - /// STOP_DET_IF_ADDRESSED=1'b1, even if the slave responds to the general call - /// address by generating ACK. The STOP_DET interrupt is generated only when the - /// transmitted address matches the slave address (SAR). - If IC_CON[7]=1'b0 - /// (STOP_DET_IFADDRESSED), the STOP_DET interrupt is issued irrespective of whether - /// it is being addressed. In Master Mode: - If IC_CON[10]=1'b1 - /// (STOP_DET_IF_MASTER_ACTIVE),the STOP_DET interrupt will be issued only if Master - /// is active. - If IC_CON[10]=1'b0 (STOP_DET_IFADDRESSED),the STOP_DET interrupt - /// will be issued irrespective of whether master is active or not. Reset value: 0x0 - STOP_DET: u1, - /// Indicates whether a START or RESTART condition has occurred on the I2C interface - /// regardless of whether DW_apb_i2c is operating in slave or master mode.\n\n - /// Reset value: 0x0 - START_DET: u1, - /// Set only when a General Call address is received and it is acknowledged. It - /// stays set until it is cleared either by disabling DW_apb_i2c or when the CPU - /// reads bit 0 of the IC_CLR_GEN_CALL register. DW_apb_i2c stores the received data - /// in the Rx buffer.\n\n - /// Reset value: 0x0 - GEN_CALL: u1, - /// Indicates whether a RESTART condition has occurred on the I2C interface when - /// DW_apb_i2c is operating in Slave mode and the slave is being addressed. Enabled - /// only when IC_SLV_RESTART_DET_EN=1.\n\n - /// Note: However, in high-speed mode or during a START BYTE transfer, the RESTART - /// comes before the address field as per the I2C protocol. In this case, the slave - /// is not the addressed slave when the RESTART is issued, therefore DW_apb_i2c does - /// not generate the RESTART_DET interrupt.\n\n - /// Reset value: 0x0 - RESTART_DET: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - }), base_address + 0x34); - - /// address: 0x40048038 - /// I2C Receive FIFO Threshold Register - pub const IC_RX_TL = @intToPtr(*volatile Mmio(32, packed struct { - /// Receive FIFO Threshold Level.\n\n - /// Controls the level of entries (or above) that triggers the RX_FULL interrupt - /// (bit 2 in IC_RAW_INTR_STAT register). The valid range is 0-255, with the - /// additional restriction that hardware does not allow this value to be set to a - /// value larger than the depth of the buffer. If an attempt is made to do that, the - /// actual value set will be the maximum depth of the buffer. A value of 0 sets the - /// threshold for 1 entry, and a value of 255 sets the threshold for 256 entries. - RX_TL: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x38); - - /// address: 0x4004803c - /// I2C Transmit FIFO Threshold Register - pub const IC_TX_TL = @intToPtr(*volatile Mmio(32, packed struct { - /// Transmit FIFO Threshold Level.\n\n - /// Controls the level of entries (or below) that trigger the TX_EMPTY interrupt - /// (bit 4 in IC_RAW_INTR_STAT register). The valid range is 0-255, with the - /// additional restriction that it may not be set to value larger than the depth of - /// the buffer. If an attempt is made to do that, the actual value set will be the - /// maximum depth of the buffer. A value of 0 sets the threshold for 0 entries, and - /// a value of 255 sets the threshold for 255 entries. - TX_TL: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x3c); - - /// address: 0x40048040 - /// Clear Combined and Individual Interrupt Register - pub const IC_CLR_INTR = @intToPtr(*volatile Mmio(32, packed struct { - /// Read this register to clear the combined interrupt, all individual interrupts, - /// and the IC_TX_ABRT_SOURCE register. This bit does not clear hardware clearable - /// interrupts but software clearable interrupts. Refer to Bit 9 of the - /// IC_TX_ABRT_SOURCE register for an exception to clearing IC_TX_ABRT_SOURCE.\n\n - /// Reset value: 0x0 - CLR_INTR: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x40); - - /// address: 0x40048044 - /// Clear RX_UNDER Interrupt Register - pub const IC_CLR_RX_UNDER = @intToPtr(*volatile Mmio(32, packed struct { - /// Read this register to clear the RX_UNDER interrupt (bit 0) of the - /// IC_RAW_INTR_STAT register.\n\n - /// Reset value: 0x0 - CLR_RX_UNDER: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x44); - - /// address: 0x40048048 - /// Clear RX_OVER Interrupt Register - pub const IC_CLR_RX_OVER = @intToPtr(*volatile Mmio(32, packed struct { - /// Read this register to clear the RX_OVER interrupt (bit 1) of the - /// IC_RAW_INTR_STAT register.\n\n - /// Reset value: 0x0 - CLR_RX_OVER: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x48); - - /// address: 0x4004804c - /// Clear TX_OVER Interrupt Register - pub const IC_CLR_TX_OVER = @intToPtr(*volatile Mmio(32, packed struct { - /// Read this register to clear the TX_OVER interrupt (bit 3) of the - /// IC_RAW_INTR_STAT register.\n\n - /// Reset value: 0x0 - CLR_TX_OVER: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x4c); - - /// address: 0x40048050 - /// Clear RD_REQ Interrupt Register - pub const IC_CLR_RD_REQ = @intToPtr(*volatile Mmio(32, packed struct { - /// Read this register to clear the RD_REQ interrupt (bit 5) of the IC_RAW_INTR_STAT - /// register.\n\n - /// Reset value: 0x0 - CLR_RD_REQ: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x50); - - /// address: 0x40048054 - /// Clear TX_ABRT Interrupt Register - pub const IC_CLR_TX_ABRT = @intToPtr(*volatile Mmio(32, packed struct { - /// Read this register to clear the TX_ABRT interrupt (bit 6) of the - /// IC_RAW_INTR_STAT register, and the IC_TX_ABRT_SOURCE register. This also - /// releases the TX FIFO from the flushed/reset state, allowing more writes to the - /// TX FIFO. Refer to Bit 9 of the IC_TX_ABRT_SOURCE register for an exception to - /// clearing IC_TX_ABRT_SOURCE.\n\n - /// Reset value: 0x0 - CLR_TX_ABRT: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x54); - - /// address: 0x40048058 - /// Clear RX_DONE Interrupt Register - pub const IC_CLR_RX_DONE = @intToPtr(*volatile Mmio(32, packed struct { - /// Read this register to clear the RX_DONE interrupt (bit 7) of the - /// IC_RAW_INTR_STAT register.\n\n - /// Reset value: 0x0 - CLR_RX_DONE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x58); - - /// address: 0x4004805c - /// Clear ACTIVITY Interrupt Register - pub const IC_CLR_ACTIVITY = @intToPtr(*volatile Mmio(32, packed struct { - /// Reading this register clears the ACTIVITY interrupt if the I2C is not active - /// anymore. If the I2C module is still active on the bus, the ACTIVITY interrupt - /// bit continues to be set. It is automatically cleared by hardware if the module - /// is disabled and if there is no further activity on the bus. The value read from - /// this register to get status of the ACTIVITY interrupt (bit 8) of the - /// IC_RAW_INTR_STAT register.\n\n - /// Reset value: 0x0 - CLR_ACTIVITY: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x5c); - - /// address: 0x40048060 - /// Clear STOP_DET Interrupt Register - pub const IC_CLR_STOP_DET = @intToPtr(*volatile Mmio(32, packed struct { - /// Read this register to clear the STOP_DET interrupt (bit 9) of the - /// IC_RAW_INTR_STAT register.\n\n - /// Reset value: 0x0 - CLR_STOP_DET: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x60); - - /// address: 0x40048064 - /// Clear START_DET Interrupt Register - pub const IC_CLR_START_DET = @intToPtr(*volatile Mmio(32, packed struct { - /// Read this register to clear the START_DET interrupt (bit 10) of the - /// IC_RAW_INTR_STAT register.\n\n - /// Reset value: 0x0 - CLR_START_DET: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x64); - - /// address: 0x40048068 - /// Clear GEN_CALL Interrupt Register - pub const IC_CLR_GEN_CALL = @intToPtr(*volatile Mmio(32, packed struct { - /// Read this register to clear the GEN_CALL interrupt (bit 11) of IC_RAW_INTR_STAT - /// register.\n\n - /// Reset value: 0x0 - CLR_GEN_CALL: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x68); - - /// address: 0x4004806c - /// I2C Enable Register - pub const IC_ENABLE = @intToPtr(*volatile Mmio(32, packed struct { - /// Controls whether the DW_apb_i2c is enabled. - 0: Disables DW_apb_i2c (TX and RX - /// FIFOs are held in an erased state) - 1: Enables DW_apb_i2c Software can disable - /// DW_apb_i2c while it is active. However, it is important that care be taken to - /// ensure that DW_apb_i2c is disabled properly. A recommended procedure is - /// described in 'Disabling DW_apb_i2c'.\n\n - /// When DW_apb_i2c is disabled, the following occurs: - The TX FIFO and RX FIFO get - /// flushed. - Status bits in the IC_INTR_STAT register are still active until - /// DW_apb_i2c goes into IDLE state. If the module is transmitting, it stops as well - /// as deletes the contents of the transmit buffer after the current transfer is - /// complete. If the module is receiving, the DW_apb_i2c stops the current transfer - /// at the end of the current byte and does not acknowledge the transfer.\n\n - /// In systems with asynchronous pclk and ic_clk when IC_CLK_TYPE parameter set to - /// asynchronous (1), there is a two ic_clk delay when enabling or disabling the - /// DW_apb_i2c. For a detailed description on how to disable DW_apb_i2c, refer to - /// 'Disabling DW_apb_i2c'\n\n - /// Reset value: 0x0 - ENABLE: u1, - /// When set, the controller initiates the transfer abort. - 0: ABORT not initiated - /// or ABORT done - 1: ABORT operation in progress The software can abort the I2C - /// transfer in master mode by setting this bit. The software can set this bit only - /// when ENABLE is already set; otherwise, the controller ignores any write to ABORT - /// bit. The software cannot clear the ABORT bit once set. In response to an ABORT, - /// the controller issues a STOP and flushes the Tx FIFO after completing the - /// current transfer, then sets the TX_ABORT interrupt after the abort operation. - /// The ABORT bit is cleared automatically after the abort operation.\n\n - /// For a detailed description on how to abort I2C transfers, refer to 'Aborting I2C - /// Transfers'.\n\n - /// Reset value: 0x0 - ABORT: u1, - /// In Master mode: - 1'b1: Blocks the transmission of data on I2C bus even if Tx - /// FIFO has data to transmit. - 1'b0: The transmission of data starts on I2C bus - /// automatically, as soon as the first data is available in the Tx FIFO. Note: To - /// block the execution of Master commands, set the TX_CMD_BLOCK bit only when Tx - /// FIFO is empty (IC_STATUS[2]==1) and Master is in Idle state (IC_STATUS[5] == 0). - /// Any further commands put in the Tx FIFO are not executed until TX_CMD_BLOCK bit - /// is unset. Reset value: IC_TX_CMD_BLOCK_DEFAULT - TX_CMD_BLOCK: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - }), base_address + 0x6c); - - /// address: 0x40048070 - /// I2C Status Register\n\n - /// This is a read-only register used to indicate the current transfer status and - /// FIFO status. The status register may be read at any time. None of the bits in - /// this register request an interrupt.\n\n - /// When the I2C is disabled by writing 0 in bit 0 of the IC_ENABLE register: - Bits - /// 1 and 2 are set to 1 - Bits 3 and 10 are set to 0 When the master or slave state - /// machines goes to idle and ic_en=0: - Bits 5 and 6 are set to 0 - pub const IC_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - /// I2C Activity Status. Reset value: 0x0 - ACTIVITY: u1, - /// Transmit FIFO Not Full. Set when the transmit FIFO contains one or more empty - /// locations, and is cleared when the FIFO is full. - 0: Transmit FIFO is full - 1: - /// Transmit FIFO is not full Reset value: 0x1 - TFNF: u1, - /// Transmit FIFO Completely Empty. When the transmit FIFO is completely empty, this - /// bit is set. When it contains one or more valid entries, this bit is cleared. - /// This bit field does not request an interrupt. - 0: Transmit FIFO is not empty - - /// 1: Transmit FIFO is empty Reset value: 0x1 - TFE: u1, - /// Receive FIFO Not Empty. This bit is set when the receive FIFO contains one or - /// more entries; it is cleared when the receive FIFO is empty. - 0: Receive FIFO is - /// empty - 1: Receive FIFO is not empty Reset value: 0x0 - RFNE: u1, - /// Receive FIFO Completely Full. When the receive FIFO is completely full, this bit - /// is set. When the receive FIFO contains one or more empty location, this bit is - /// cleared. - 0: Receive FIFO is not full - 1: Receive FIFO is full Reset value: - /// 0x0 - RFF: u1, - /// Master FSM Activity Status. When the Master Finite State Machine (FSM) is not in - /// the IDLE state, this bit is set. - 0: Master FSM is in IDLE state so the Master - /// part of DW_apb_i2c is not Active - 1: Master FSM is not in IDLE state so the - /// Master part of DW_apb_i2c is Active Note: IC_STATUS[0]-that is, ACTIVITY bit-is - /// the OR of SLV_ACTIVITY and MST_ACTIVITY bits.\n\n - /// Reset value: 0x0 - MST_ACTIVITY: u1, - /// Slave FSM Activity Status. When the Slave Finite State Machine (FSM) is not in - /// the IDLE state, this bit is set. - 0: Slave FSM is in IDLE state so the Slave - /// part of DW_apb_i2c is not Active - 1: Slave FSM is not in IDLE state so the - /// Slave part of DW_apb_i2c is Active Reset value: 0x0 - SLV_ACTIVITY: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - }), base_address + 0x70); - - /// address: 0x40048074 - /// I2C Transmit FIFO Level Register This register contains the number of valid data - /// entries in the transmit FIFO buffer. It is cleared whenever: - The I2C is - /// disabled - There is a transmit abort - that is, TX_ABRT bit is set in the - /// IC_RAW_INTR_STAT register - The slave bulk transmit mode is aborted The register - /// increments whenever data is placed into the transmit FIFO and decrements when - /// data is taken from the transmit FIFO. - pub const IC_TXFLR = @intToPtr(*volatile Mmio(32, packed struct { - /// Transmit FIFO Level. Contains the number of valid data entries in the transmit - /// FIFO.\n\n - /// Reset value: 0x0 - TXFLR: u5, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - }), base_address + 0x74); - - /// address: 0x40048078 - /// I2C Receive FIFO Level Register This register contains the number of valid data - /// entries in the receive FIFO buffer. It is cleared whenever: - The I2C is - /// disabled - Whenever there is a transmit abort caused by any of the events - /// tracked in IC_TX_ABRT_SOURCE The register increments whenever data is placed - /// into the receive FIFO and decrements when data is taken from the receive FIFO. - pub const IC_RXFLR = @intToPtr(*volatile Mmio(32, packed struct { - /// Receive FIFO Level. Contains the number of valid data entries in the receive - /// FIFO.\n\n - /// Reset value: 0x0 - RXFLR: u5, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - }), base_address + 0x78); - - /// address: 0x4004807c - /// I2C SDA Hold Time Length Register\n\n - /// The bits [15:0] of this register are used to control the hold time of SDA during - /// transmit in both slave and master mode (after SCL goes from HIGH to LOW).\n\n - /// The bits [23:16] of this register are used to extend the SDA transition (if any) - /// whenever SCL is HIGH in the receiver in either master or slave mode.\n\n - /// Writes to this register succeed only when IC_ENABLE[0]=0.\n\n - /// The values in this register are in units of ic_clk period. The value programmed - /// in IC_SDA_TX_HOLD must be greater than the minimum hold time in each mode (one - /// cycle in master mode, seven cycles in slave mode) for the value to be - /// implemented.\n\n - /// The programmed SDA hold time during transmit (IC_SDA_TX_HOLD) cannot exceed at - /// any time the duration of the low part of scl. Therefore the programmed value - /// cannot be larger than N_SCL_LOW-2, where N_SCL_LOW is the duration of the low - /// part of the scl period measured in ic_clk cycles. - pub const IC_SDA_HOLD = @intToPtr(*volatile Mmio(32, packed struct { - /// Sets the required SDA hold time in units of ic_clk period, when DW_apb_i2c acts - /// as a transmitter.\n\n - /// Reset value: IC_DEFAULT_SDA_HOLD[15:0]. - IC_SDA_TX_HOLD: u16, - /// Sets the required SDA hold time in units of ic_clk period, when DW_apb_i2c acts - /// as a receiver.\n\n - /// Reset value: IC_DEFAULT_SDA_HOLD[23:16]. - IC_SDA_RX_HOLD: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x7c); - - /// address: 0x40048080 - /// I2C Transmit Abort Source Register\n\n - /// This register has 32 bits that indicate the source of the TX_ABRT bit. Except - /// for Bit 9, this register is cleared whenever the IC_CLR_TX_ABRT register or the - /// IC_CLR_INTR register is read. To clear Bit 9, the source of the - /// ABRT_SBYTE_NORSTRT must be fixed first; RESTART must be enabled (IC_CON[5]=1), - /// the SPECIAL bit must be cleared (IC_TAR[11]), or the GC_OR_START bit must be - /// cleared (IC_TAR[10]).\n\n - /// Once the source of the ABRT_SBYTE_NORSTRT is fixed, then this bit can be cleared - /// in the same manner as other bits in this register. If the source of the - /// ABRT_SBYTE_NORSTRT is not fixed before attempting to clear this bit, Bit 9 - /// clears for one cycle and is then re-asserted. - pub const IC_TX_ABRT_SOURCE = @intToPtr(*volatile Mmio(32, packed struct { - /// This field indicates that the Master is in 7-bit addressing mode and the address - /// sent was not acknowledged by any slave.\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver - ABRT_7B_ADDR_NOACK: u1, - /// This field indicates that the Master is in 10-bit address mode and the first - /// 10-bit address byte was not acknowledged by any slave.\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver - ABRT_10ADDR1_NOACK: u1, - /// This field indicates that the Master is in 10-bit address mode and that the - /// second address byte of the 10-bit address was not acknowledged by any slave.\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver - ABRT_10ADDR2_NOACK: u1, - /// This field indicates the master-mode only bit. When the master receives an - /// acknowledgement for the address, but when it sends data byte(s) following the - /// address, it did not receive an acknowledge from the remote slave(s).\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master-Transmitter - ABRT_TXDATA_NOACK: u1, - /// This field indicates that DW_apb_i2c in master mode has sent a General Call and - /// no slave on the bus acknowledged the General Call.\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master-Transmitter - ABRT_GCALL_NOACK: u1, - /// This field indicates that DW_apb_i2c in the master mode has sent a General Call - /// but the user programmed the byte following the General Call to be a read from - /// the bus (IC_DATA_CMD[9] is set to 1).\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master-Transmitter - ABRT_GCALL_READ: u1, - /// This field indicates that the Master is in High Speed mode and the High Speed - /// Master code was acknowledged (wrong behavior).\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master - ABRT_HS_ACKDET: u1, - /// This field indicates that the Master has sent a START Byte and the START Byte - /// was acknowledged (wrong behavior).\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master - ABRT_SBYTE_ACKDET: u1, - /// This field indicates that the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) - /// =0) and the user is trying to use the master to transfer data in High Speed - /// mode.\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver - ABRT_HS_NORSTRT: u1, - /// To clear Bit 9, the source of the ABRT_SBYTE_NORSTRT must be fixed first; - /// restart must be enabled (IC_CON[5]=1), the SPECIAL bit must be cleared - /// (IC_TAR[11]), or the GC_OR_START bit must be cleared (IC_TAR[10]). Once the - /// source of the ABRT_SBYTE_NORSTRT is fixed, then this bit can be cleared in the - /// same manner as other bits in this register. If the source of the - /// ABRT_SBYTE_NORSTRT is not fixed before attempting to clear this bit, bit 9 - /// clears for one cycle and then gets reasserted. When this field is set to 1, the - /// restart is disabled (IC_RESTART_EN bit (IC_CON[5]) =0) and the user is trying to - /// send a START Byte.\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master - ABRT_SBYTE_NORSTRT: u1, - /// This field indicates that the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) - /// =0) and the master sends a read command in 10-bit addressing mode.\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master-Receiver - ABRT_10B_RD_NORSTRT: u1, - /// This field indicates that the User tries to initiate a Master operation with the - /// Master mode disabled.\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver - ABRT_MASTER_DIS: u1, - /// This field specifies that the Master has lost arbitration, or if - /// IC_TX_ABRT_SOURCE[14] is also set, then the slave transmitter has lost - /// arbitration.\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master-Transmitter or Slave-Transmitter - ARB_LOST: u1, - /// This field specifies that the Slave has received a read command and some data - /// exists in the TX FIFO, so the slave issues a TX_ABRT interrupt to flush old data - /// in TX FIFO.\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Slave-Transmitter - ABRT_SLVFLUSH_TXFIFO: u1, - /// This field indicates that a Slave has lost the bus while transmitting data to a - /// remote master. IC_TX_ABRT_SOURCE[12] is set at the same time. Note: Even though - /// the slave never 'owns' the bus, something could go wrong on the bus. This is a - /// fail safe check. For instance, during a data transmission at the low-to-high - /// transition of SCL, if what is on the data bus is not what is supposed to be - /// transmitted, then DW_apb_i2c no longer own the bus.\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Slave-Transmitter - ABRT_SLV_ARBLOST: u1, - /// 1: When the processor side responds to a slave mode request for data to be - /// transmitted to a remote master and user writes a 1 in CMD (bit 8) of IC_DATA_CMD - /// register.\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Slave-Transmitter - ABRT_SLVRD_INTX: u1, - /// This is a master-mode-only bit. Master has detected the transfer abort - /// (IC_ENABLE[1])\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master-Transmitter - ABRT_USER_ABRT: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - /// This field indicates the number of Tx FIFO Data Commands which are flushed due - /// to TX_ABRT interrupt. It is cleared whenever I2C is disabled.\n\n - /// Reset value: 0x0\n\n - /// Role of DW_apb_i2c: Master-Transmitter or Slave-Transmitter - TX_FLUSH_CNT: u9, - }), base_address + 0x80); - - /// address: 0x40048084 - /// Generate Slave Data NACK Register\n\n - /// The register is used to generate a NACK for the data part of a transfer when - /// DW_apb_i2c is acting as a slave-receiver. This register only exists when the - /// IC_SLV_DATA_NACK_ONLY parameter is set to 1. When this parameter disabled, this - /// register does not exist and writing to the register's address has no effect.\n\n - /// A write can occur on this register if both of the following conditions are met: - /// - DW_apb_i2c is disabled (IC_ENABLE[0] = 0) - Slave part is inactive - /// (IC_STATUS[6] = 0) Note: The IC_STATUS[6] is a register read-back location for - /// the internal slv_activity signal; the user should poll this before writing the - /// ic_slv_data_nack_only bit. - pub const IC_SLV_DATA_NACK_ONLY = @intToPtr(*volatile Mmio(32, packed struct { - /// Generate NACK. This NACK generation only occurs when DW_apb_i2c is a - /// slave-receiver. If this register is set to a value of 1, it can only generate a - /// NACK after a data byte is received; hence, the data transfer is aborted and the - /// data received is not pushed to the receive buffer.\n\n - /// When the register is set to a value of 0, it generates NACK/ACK, depending on - /// normal criteria. - 1: generate NACK after data byte received - 0: generate - /// NACK/ACK normally Reset value: 0x0 - NACK: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x84); - - /// address: 0x40048088 - /// DMA Control Register\n\n - /// The register is used to enable the DMA Controller interface operation. There is - /// a separate bit for transmit and receive. This can be programmed regardless of - /// the state of IC_ENABLE. - pub const IC_DMA_CR = @intToPtr(*volatile Mmio(32, packed struct { - /// Receive DMA Enable. This bit enables/disables the receive FIFO DMA channel. - /// Reset value: 0x0 - RDMAE: u1, - /// Transmit DMA Enable. This bit enables/disables the transmit FIFO DMA channel. - /// Reset value: 0x0 - TDMAE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - }), base_address + 0x88); - - /// address: 0x4004808c - /// DMA Transmit Data Level Register - pub const IC_DMA_TDLR = @intToPtr(*volatile Mmio(32, packed struct { - /// Transmit Data Level. This bit field controls the level at which a DMA request is - /// made by the transmit logic. It is equal to the watermark level; that is, the - /// dma_tx_req signal is generated when the number of valid data entries in the - /// transmit FIFO is equal to or below this field value, and TDMAE = 1.\n\n - /// Reset value: 0x0 - DMATDL: u4, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - }), base_address + 0x8c); - - /// address: 0x40048090 - /// I2C Receive Data Level Register - pub const IC_DMA_RDLR = @intToPtr(*volatile Mmio(32, packed struct { - /// Receive Data Level. This bit field controls the level at which a DMA request is - /// made by the receive logic. The watermark level = DMARDL+1; that is, dma_rx_req - /// is generated when the number of valid data entries in the receive FIFO is equal - /// to or more than this field value + 1, and RDMAE =1. For instance, when DMARDL is - /// 0, then dma_rx_req is asserted when 1 or more data entries are present in the - /// receive FIFO.\n\n - /// Reset value: 0x0 - DMARDL: u4, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - }), base_address + 0x90); - - /// address: 0x40048094 - /// I2C SDA Setup Register\n\n - /// This register controls the amount of time delay (in terms of number of ic_clk - /// clock periods) introduced in the rising edge of SCL - relative to SDA changing - - /// when DW_apb_i2c services a read request in a slave-transmitter operation. The - /// relevant I2C requirement is tSU:DAT (note 4) as detailed in the I2C Bus - /// Specification. This register must be programmed with a value equal to or greater - /// than 2.\n\n - /// Writes to this register succeed only when IC_ENABLE[0] = 0.\n\n - /// Note: The length of setup time is calculated using [(IC_SDA_SETUP - 1) * - /// (ic_clk_period)], so if the user requires 10 ic_clk periods of setup time, they - /// should program a value of 11. The IC_SDA_SETUP register is only used by the - /// DW_apb_i2c when operating as a slave transmitter. - pub const IC_SDA_SETUP = @intToPtr(*volatile Mmio(32, packed struct { - /// SDA Setup. It is recommended that if the required delay is 1000ns, then for an - /// ic_clk frequency of 10 MHz, IC_SDA_SETUP should be programmed to a value of 11. - /// IC_SDA_SETUP must be programmed with a minimum value of 2. - SDA_SETUP: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x94); - - /// address: 0x40048098 - /// I2C ACK General Call Register\n\n - /// The register controls whether DW_apb_i2c responds with a ACK or NACK when it - /// receives an I2C General Call address.\n\n - /// This register is applicable only when the DW_apb_i2c is in slave mode. - pub const IC_ACK_GENERAL_CALL = @intToPtr(*volatile Mmio(32, packed struct { - /// ACK General Call. When set to 1, DW_apb_i2c responds with a ACK (by asserting - /// ic_data_oe) when it receives a General Call. Otherwise, DW_apb_i2c responds with - /// a NACK (by negating ic_data_oe). - ACK_GEN_CALL: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x98); - - /// address: 0x4004809c - /// I2C Enable Status Register\n\n - /// The register is used to report the DW_apb_i2c hardware status when the - /// IC_ENABLE[0] register is set from 1 to 0; that is, when DW_apb_i2c is - /// disabled.\n\n - /// If IC_ENABLE[0] has been set to 1, bits 2:1 are forced to 0, and bit 0 is forced - /// to 1.\n\n - /// If IC_ENABLE[0] has been set to 0, bits 2:1 is only be valid as soon as bit 0 is - /// read as '0'.\n\n - /// Note: When IC_ENABLE[0] has been set to 0, a delay occurs for bit 0 to be read - /// as 0 because disabling the DW_apb_i2c depends on I2C bus activities. - pub const IC_ENABLE_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - /// ic_en Status. This bit always reflects the value driven on the output port - /// ic_en. - When read as 1, DW_apb_i2c is deemed to be in an enabled state. - When - /// read as 0, DW_apb_i2c is deemed completely inactive. Note: The CPU can safely - /// read this bit anytime. When this bit is read as 0, the CPU can safely read - /// SLV_RX_DATA_LOST (bit 2) and SLV_DISABLED_WHILE_BUSY (bit 1).\n\n - /// Reset value: 0x0 - IC_EN: u1, - /// Slave Disabled While Busy (Transmit, Receive). This bit indicates if a potential - /// or active Slave operation has been aborted due to the setting bit 0 of the - /// IC_ENABLE register from 1 to 0. This bit is set when the CPU writes a 0 to the - /// IC_ENABLE register while:\n\n - /// (a) DW_apb_i2c is receiving the address byte of the Slave-Transmitter operation - /// from a remote master;\n\n - /// OR,\n\n - /// (b) address and data bytes of the Slave-Receiver operation from a remote - /// master.\n\n - /// When read as 1, DW_apb_i2c is deemed to have forced a NACK during any part of an - /// I2C transfer, irrespective of whether the I2C address matches the slave address - /// set in DW_apb_i2c (IC_SAR register) OR if the transfer is completed before - /// IC_ENABLE is set to 0 but has not taken effect.\n\n - /// Note: If the remote I2C master terminates the transfer with a STOP condition - /// before the DW_apb_i2c has a chance to NACK a transfer, and IC_ENABLE[0] has been - /// set to 0, then this bit will also be set to 1.\n\n - /// When read as 0, DW_apb_i2c is deemed to have been disabled when there is master - /// activity, or when the I2C bus is idle.\n\n - /// Note: The CPU can safely read this bit when IC_EN (bit 0) is read as 0.\n\n - /// Reset value: 0x0 - SLV_DISABLED_WHILE_BUSY: u1, - /// Slave Received Data Lost. This bit indicates if a Slave-Receiver operation has - /// been aborted with at least one data byte received from an I2C transfer due to - /// the setting bit 0 of IC_ENABLE from 1 to 0. When read as 1, DW_apb_i2c is deemed - /// to have been actively engaged in an aborted I2C transfer (with matching address) - /// and the data phase of the I2C transfer has been entered, even though a data byte - /// has been responded with a NACK.\n\n - /// Note: If the remote I2C master terminates the transfer with a STOP condition - /// before the DW_apb_i2c has a chance to NACK a transfer, and IC_ENABLE[0] has been - /// set to 0, then this bit is also set to 1.\n\n - /// When read as 0, DW_apb_i2c is deemed to have been disabled without being - /// actively involved in the data phase of a Slave-Receiver transfer.\n\n - /// Note: The CPU can safely read this bit when IC_EN (bit 0) is read as 0.\n\n - /// Reset value: 0x0 - SLV_RX_DATA_LOST: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - }), base_address + 0x9c); - - /// address: 0x400480a0 - /// I2C SS, FS or FM+ spike suppression limit\n\n - /// This register is used to store the duration, measured in ic_clk cycles, of the - /// longest spike that is filtered out by the spike suppression logic when the - /// component is operating in SS, FS or FM+ modes. The relevant I2C requirement is - /// tSP (table 4) as detailed in the I2C Bus Specification. This register must be - /// programmed with a minimum value of 1. - pub const IC_FS_SPKLEN = @intToPtr(*volatile MmioInt(32, u8), base_address + 0xa0); - - /// address: 0x400480a8 - /// Clear RESTART_DET Interrupt Register - pub const IC_CLR_RESTART_DET = @intToPtr(*volatile Mmio(32, packed struct { - /// Read this register to clear the RESTART_DET interrupt (bit 12) of - /// IC_RAW_INTR_STAT register.\n\n - /// Reset value: 0x0 - CLR_RESTART_DET: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0xa8); - - /// address: 0x400480f4 - /// Component Parameter Register 1\n\n - /// Note This register is not implemented and therefore reads as 0. If it was - /// implemented it would be a constant read-only register that contains encoded - /// information about the component's parameter settings. Fields shown below are the - /// settings for those parameters - pub const IC_COMP_PARAM_1 = @intToPtr(*volatile Mmio(32, packed struct { - /// APB data bus width is 32 bits - APB_DATA_WIDTH: u2, - /// MAX SPEED MODE = FAST MODE - MAX_SPEED_MODE: u2, - /// Programmable count values for each mode. - HC_COUNT_VALUES: u1, - /// COMBINED Interrupt outputs - INTR_IO: u1, - /// DMA handshaking signals are enabled - HAS_DMA: u1, - /// Encoded parameters not visible - ADD_ENCODED_PARAMS: u1, - /// RX Buffer Depth = 16 - RX_BUFFER_DEPTH: u8, - /// TX Buffer Depth = 16 - TX_BUFFER_DEPTH: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0xf4); - - /// address: 0x400480f8 - /// I2C Component Version Register - pub const IC_COMP_VERSION = @intToPtr(*volatile u32, base_address + 0xf8); - - /// address: 0x400480fc - /// I2C Component Type Register - pub const IC_COMP_TYPE = @intToPtr(*volatile u32, base_address + 0xfc); - }; - - /// Control and data interface to SAR ADC - pub const ADC = struct { - pub const base_address = 0x4004c000; - pub const version = "2"; - - /// address: 0x4004c000 - /// ADC Control and Status - pub const CS = @intToPtr(*volatile Mmio(32, packed struct { - /// Power on ADC and enable its clock.\n - /// 1 - enabled. 0 - disabled. - EN: u1, - /// Power on temperature sensor. 1 - enabled. 0 - disabled. - TS_EN: u1, - /// Start a single conversion. Self-clearing. Ignored if start_many is asserted. - START_ONCE: u1, - /// Continuously perform conversions whilst this bit is 1. A new conversion will - /// start immediately after the previous finishes. - START_MANY: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - /// 1 if the ADC is ready to start a new conversion. Implies any previous conversion - /// has completed.\n - /// 0 whilst conversion in progress. - READY: u1, - /// The most recent ADC conversion encountered an error; result is undefined or - /// noisy. - ERR: u1, - /// Some past ADC conversion encountered an error. Write 1 to clear. - ERR_STICKY: u1, - reserved4: u1 = 0, - /// Select analog mux input. Updated automatically in round-robin mode. - AINSEL: u3, - reserved5: u1 = 0, - /// Round-robin sampling. 1 bit per channel. Set all bits to 0 to disable.\n - /// Otherwise, the ADC will cycle through each enabled channel in a round-robin - /// fashion.\n - /// The first channel to be sampled will be the one currently indicated by AINSEL.\n - /// AINSEL will be updated after each conversion with the newly-selected channel. - RROBIN: u5, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - }), base_address + 0x0); - - /// address: 0x4004c004 - /// Result of most recent ADC conversion - pub const RESULT = @intToPtr(*volatile MmioInt(32, u12), base_address + 0x4); - - /// address: 0x4004c008 - /// FIFO control and status - pub const FCS = @intToPtr(*volatile Mmio(32, packed struct { - /// If 1: write result to the FIFO after each conversion. - EN: u1, - /// If 1: FIFO results are right-shifted to be one byte in size. Enables DMA to byte - /// buffers. - SHIFT: u1, - /// If 1: conversion error bit appears in the FIFO alongside the result - ERR: u1, - /// If 1: assert DMA requests when FIFO contains data - DREQ_EN: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - EMPTY: u1, - FULL: u1, - /// 1 if the FIFO has been underflowed. Write 1 to clear. - UNDER: u1, - /// 1 if the FIFO has been overflowed. Write 1 to clear. - OVER: u1, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// The number of conversion results currently waiting in the FIFO - LEVEL: u4, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - /// DREQ/IRQ asserted when level >= threshold - THRESH: u4, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - }), base_address + 0x8); - - /// address: 0x4004c00c - /// Conversion result FIFO - pub const FIFO = @intToPtr(*volatile Mmio(32, packed struct { - VAL: u12, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - /// 1 if this particular sample experienced a conversion error. Remains in the same - /// location if the sample is shifted. - ERR: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - }), base_address + 0xc); - - /// address: 0x4004c010 - /// Clock divider. If non-zero, CS_START_MANY will start conversions\n - /// at regular intervals rather than back-to-back.\n - /// The divider is reset when either of these fields are written.\n - /// Total period is 1 + INT + FRAC / 256 - pub const DIV = @intToPtr(*volatile Mmio(32, packed struct { - /// Fractional part of clock divisor. First-order delta-sigma. - FRAC: u8, - /// Integer part of clock divisor. - INT: u16, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x10); - - /// address: 0x4004c014 - /// Raw Interrupts - pub const INTR = @intToPtr(*volatile Mmio(32, packed struct { - /// Triggered when the sample FIFO reaches a certain level.\n - /// This level can be programmed via the FCS_THRESH field. - FIFO: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x14); - - /// address: 0x4004c018 - /// Interrupt Enable - pub const INTE = @intToPtr(*volatile Mmio(32, packed struct { - /// Triggered when the sample FIFO reaches a certain level.\n - /// This level can be programmed via the FCS_THRESH field. - FIFO: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x18); - - /// address: 0x4004c01c - /// Interrupt Force - pub const INTF = @intToPtr(*volatile Mmio(32, packed struct { - /// Triggered when the sample FIFO reaches a certain level.\n - /// This level can be programmed via the FCS_THRESH field. - FIFO: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x1c); - - /// address: 0x4004c020 - /// Interrupt status after masking & forcing - pub const INTS = @intToPtr(*volatile Mmio(32, packed struct { - /// Triggered when the sample FIFO reaches a certain level.\n - /// This level can be programmed via the FCS_THRESH field. - FIFO: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x20); - }; - - /// Simple PWM - pub const PWM = struct { - pub const base_address = 0x40050000; - pub const version = "1"; - - /// address: 0x40050000 - /// Control and status register - pub const CH0_CSR = @intToPtr(*volatile Mmio(32, packed struct { - /// Enable the PWM channel. - EN: u1, - /// 1: Enable phase-correct modulation. 0: Trailing-edge - PH_CORRECT: u1, - /// Invert output A - A_INV: u1, - /// Invert output B - B_INV: u1, - DIVMODE: u2, - /// Retard the phase of the counter by 1 count, while it is running.\n - /// Self-clearing. Write a 1, and poll until low. Counter must be running. - PH_RET: u1, - /// Advance the phase of the counter by 1 count, while it is running.\n - /// Self-clearing. Write a 1, and poll until low. Counter must be running\n - /// at less than full speed (div_int + div_frac / 16 > 1) - PH_ADV: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x0); - - /// address: 0x40050004 - /// INT and FRAC form a fixed-point fractional number.\n - /// Counting rate is system clock frequency divided by this number.\n - /// Fractional division uses simple 1st-order sigma-delta. - pub const CH0_DIV = @intToPtr(*volatile Mmio(32, packed struct { - FRAC: u4, - INT: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x4); - - /// address: 0x40050008 - /// Direct access to the PWM counter - pub const CH0_CTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x8); - - /// address: 0x4005000c - /// Counter compare values - pub const CH0_CC = @intToPtr(*volatile Mmio(32, packed struct { - A: u16, - B: u16, - }), base_address + 0xc); - - /// address: 0x40050010 - /// Counter wrap value - pub const CH0_TOP = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x10); - - /// address: 0x40050014 - /// Control and status register - pub const CH1_CSR = @intToPtr(*volatile Mmio(32, packed struct { - /// Enable the PWM channel. - EN: u1, - /// 1: Enable phase-correct modulation. 0: Trailing-edge - PH_CORRECT: u1, - /// Invert output A - A_INV: u1, - /// Invert output B - B_INV: u1, - DIVMODE: u2, - /// Retard the phase of the counter by 1 count, while it is running.\n - /// Self-clearing. Write a 1, and poll until low. Counter must be running. - PH_RET: u1, - /// Advance the phase of the counter by 1 count, while it is running.\n - /// Self-clearing. Write a 1, and poll until low. Counter must be running\n - /// at less than full speed (div_int + div_frac / 16 > 1) - PH_ADV: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x14); - - /// address: 0x40050018 - /// INT and FRAC form a fixed-point fractional number.\n - /// Counting rate is system clock frequency divided by this number.\n - /// Fractional division uses simple 1st-order sigma-delta. - pub const CH1_DIV = @intToPtr(*volatile Mmio(32, packed struct { - FRAC: u4, - INT: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x18); - - /// address: 0x4005001c - /// Direct access to the PWM counter - pub const CH1_CTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x1c); - - /// address: 0x40050020 - /// Counter compare values - pub const CH1_CC = @intToPtr(*volatile Mmio(32, packed struct { - A: u16, - B: u16, - }), base_address + 0x20); - - /// address: 0x40050024 - /// Counter wrap value - pub const CH1_TOP = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x24); - - /// address: 0x40050028 - /// Control and status register - pub const CH2_CSR = @intToPtr(*volatile Mmio(32, packed struct { - /// Enable the PWM channel. - EN: u1, - /// 1: Enable phase-correct modulation. 0: Trailing-edge - PH_CORRECT: u1, - /// Invert output A - A_INV: u1, - /// Invert output B - B_INV: u1, - DIVMODE: u2, - /// Retard the phase of the counter by 1 count, while it is running.\n - /// Self-clearing. Write a 1, and poll until low. Counter must be running. - PH_RET: u1, - /// Advance the phase of the counter by 1 count, while it is running.\n - /// Self-clearing. Write a 1, and poll until low. Counter must be running\n - /// at less than full speed (div_int + div_frac / 16 > 1) - PH_ADV: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x28); - - /// address: 0x4005002c - /// INT and FRAC form a fixed-point fractional number.\n - /// Counting rate is system clock frequency divided by this number.\n - /// Fractional division uses simple 1st-order sigma-delta. - pub const CH2_DIV = @intToPtr(*volatile Mmio(32, packed struct { - FRAC: u4, - INT: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x2c); - - /// address: 0x40050030 - /// Direct access to the PWM counter - pub const CH2_CTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x30); - - /// address: 0x40050034 - /// Counter compare values - pub const CH2_CC = @intToPtr(*volatile Mmio(32, packed struct { - A: u16, - B: u16, - }), base_address + 0x34); - - /// address: 0x40050038 - /// Counter wrap value - pub const CH2_TOP = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x38); - - /// address: 0x4005003c - /// Control and status register - pub const CH3_CSR = @intToPtr(*volatile Mmio(32, packed struct { - /// Enable the PWM channel. - EN: u1, - /// 1: Enable phase-correct modulation. 0: Trailing-edge - PH_CORRECT: u1, - /// Invert output A - A_INV: u1, - /// Invert output B - B_INV: u1, - DIVMODE: u2, - /// Retard the phase of the counter by 1 count, while it is running.\n - /// Self-clearing. Write a 1, and poll until low. Counter must be running. - PH_RET: u1, - /// Advance the phase of the counter by 1 count, while it is running.\n - /// Self-clearing. Write a 1, and poll until low. Counter must be running\n - /// at less than full speed (div_int + div_frac / 16 > 1) - PH_ADV: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x3c); - - /// address: 0x40050040 - /// INT and FRAC form a fixed-point fractional number.\n - /// Counting rate is system clock frequency divided by this number.\n - /// Fractional division uses simple 1st-order sigma-delta. - pub const CH3_DIV = @intToPtr(*volatile Mmio(32, packed struct { - FRAC: u4, - INT: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x40); - - /// address: 0x40050044 - /// Direct access to the PWM counter - pub const CH3_CTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x44); - - /// address: 0x40050048 - /// Counter compare values - pub const CH3_CC = @intToPtr(*volatile Mmio(32, packed struct { - A: u16, - B: u16, - }), base_address + 0x48); - - /// address: 0x4005004c - /// Counter wrap value - pub const CH3_TOP = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x4c); - - /// address: 0x40050050 - /// Control and status register - pub const CH4_CSR = @intToPtr(*volatile Mmio(32, packed struct { - /// Enable the PWM channel. - EN: u1, - /// 1: Enable phase-correct modulation. 0: Trailing-edge - PH_CORRECT: u1, - /// Invert output A - A_INV: u1, - /// Invert output B - B_INV: u1, - DIVMODE: u2, - /// Retard the phase of the counter by 1 count, while it is running.\n - /// Self-clearing. Write a 1, and poll until low. Counter must be running. - PH_RET: u1, - /// Advance the phase of the counter by 1 count, while it is running.\n - /// Self-clearing. Write a 1, and poll until low. Counter must be running\n - /// at less than full speed (div_int + div_frac / 16 > 1) - PH_ADV: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x50); - - /// address: 0x40050054 - /// INT and FRAC form a fixed-point fractional number.\n - /// Counting rate is system clock frequency divided by this number.\n - /// Fractional division uses simple 1st-order sigma-delta. - pub const CH4_DIV = @intToPtr(*volatile Mmio(32, packed struct { - FRAC: u4, - INT: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x54); - - /// address: 0x40050058 - /// Direct access to the PWM counter - pub const CH4_CTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x58); - - /// address: 0x4005005c - /// Counter compare values - pub const CH4_CC = @intToPtr(*volatile Mmio(32, packed struct { - A: u16, - B: u16, - }), base_address + 0x5c); - - /// address: 0x40050060 - /// Counter wrap value - pub const CH4_TOP = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x60); - - /// address: 0x40050064 - /// Control and status register - pub const CH5_CSR = @intToPtr(*volatile Mmio(32, packed struct { - /// Enable the PWM channel. - EN: u1, - /// 1: Enable phase-correct modulation. 0: Trailing-edge - PH_CORRECT: u1, - /// Invert output A - A_INV: u1, - /// Invert output B - B_INV: u1, - DIVMODE: u2, - /// Retard the phase of the counter by 1 count, while it is running.\n - /// Self-clearing. Write a 1, and poll until low. Counter must be running. - PH_RET: u1, - /// Advance the phase of the counter by 1 count, while it is running.\n - /// Self-clearing. Write a 1, and poll until low. Counter must be running\n - /// at less than full speed (div_int + div_frac / 16 > 1) - PH_ADV: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x64); - - /// address: 0x40050068 - /// INT and FRAC form a fixed-point fractional number.\n - /// Counting rate is system clock frequency divided by this number.\n - /// Fractional division uses simple 1st-order sigma-delta. - pub const CH5_DIV = @intToPtr(*volatile Mmio(32, packed struct { - FRAC: u4, - INT: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x68); - - /// address: 0x4005006c - /// Direct access to the PWM counter - pub const CH5_CTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x6c); - - /// address: 0x40050070 - /// Counter compare values - pub const CH5_CC = @intToPtr(*volatile Mmio(32, packed struct { - A: u16, - B: u16, - }), base_address + 0x70); - - /// address: 0x40050074 - /// Counter wrap value - pub const CH5_TOP = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x74); - - /// address: 0x40050078 - /// Control and status register - pub const CH6_CSR = @intToPtr(*volatile Mmio(32, packed struct { - /// Enable the PWM channel. - EN: u1, - /// 1: Enable phase-correct modulation. 0: Trailing-edge - PH_CORRECT: u1, - /// Invert output A - A_INV: u1, - /// Invert output B - B_INV: u1, - DIVMODE: u2, - /// Retard the phase of the counter by 1 count, while it is running.\n - /// Self-clearing. Write a 1, and poll until low. Counter must be running. - PH_RET: u1, - /// Advance the phase of the counter by 1 count, while it is running.\n - /// Self-clearing. Write a 1, and poll until low. Counter must be running\n - /// at less than full speed (div_int + div_frac / 16 > 1) - PH_ADV: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x78); - - /// address: 0x4005007c - /// INT and FRAC form a fixed-point fractional number.\n - /// Counting rate is system clock frequency divided by this number.\n - /// Fractional division uses simple 1st-order sigma-delta. - pub const CH6_DIV = @intToPtr(*volatile Mmio(32, packed struct { - FRAC: u4, - INT: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x7c); - - /// address: 0x40050080 - /// Direct access to the PWM counter - pub const CH6_CTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x80); - - /// address: 0x40050084 - /// Counter compare values - pub const CH6_CC = @intToPtr(*volatile Mmio(32, packed struct { - A: u16, - B: u16, - }), base_address + 0x84); - - /// address: 0x40050088 - /// Counter wrap value - pub const CH6_TOP = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x88); - - /// address: 0x4005008c - /// Control and status register - pub const CH7_CSR = @intToPtr(*volatile Mmio(32, packed struct { - /// Enable the PWM channel. - EN: u1, - /// 1: Enable phase-correct modulation. 0: Trailing-edge - PH_CORRECT: u1, - /// Invert output A - A_INV: u1, - /// Invert output B - B_INV: u1, - DIVMODE: u2, - /// Retard the phase of the counter by 1 count, while it is running.\n - /// Self-clearing. Write a 1, and poll until low. Counter must be running. - PH_RET: u1, - /// Advance the phase of the counter by 1 count, while it is running.\n - /// Self-clearing. Write a 1, and poll until low. Counter must be running\n - /// at less than full speed (div_int + div_frac / 16 > 1) - PH_ADV: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x8c); - - /// address: 0x40050090 - /// INT and FRAC form a fixed-point fractional number.\n - /// Counting rate is system clock frequency divided by this number.\n - /// Fractional division uses simple 1st-order sigma-delta. - pub const CH7_DIV = @intToPtr(*volatile Mmio(32, packed struct { - FRAC: u4, - INT: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x90); - - /// address: 0x40050094 - /// Direct access to the PWM counter - pub const CH7_CTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x94); - - /// address: 0x40050098 - /// Counter compare values - pub const CH7_CC = @intToPtr(*volatile Mmio(32, packed struct { - A: u16, - B: u16, - }), base_address + 0x98); - - /// address: 0x4005009c - /// Counter wrap value - pub const CH7_TOP = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x9c); - - /// address: 0x400500a0 - /// This register aliases the CSR_EN bits for all channels.\n - /// Writing to this register allows multiple channels to be enabled\n - /// or disabled simultaneously, so they can run in perfect sync.\n - /// For each channel, there is only one physical EN register bit,\n - /// which can be accessed through here or CHx_CSR. - pub const EN = @intToPtr(*volatile Mmio(32, packed struct { - CH0: u1, - CH1: u1, - CH2: u1, - CH3: u1, - CH4: u1, - CH5: u1, - CH6: u1, - CH7: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0xa0); - - /// address: 0x400500a4 - /// Raw Interrupts - pub const INTR = @intToPtr(*volatile Mmio(32, packed struct { - CH0: u1, - CH1: u1, - CH2: u1, - CH3: u1, - CH4: u1, - CH5: u1, - CH6: u1, - CH7: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0xa4); - - /// address: 0x400500a8 - /// Interrupt Enable - pub const INTE = @intToPtr(*volatile Mmio(32, packed struct { - CH0: u1, - CH1: u1, - CH2: u1, - CH3: u1, - CH4: u1, - CH5: u1, - CH6: u1, - CH7: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0xa8); - - /// address: 0x400500ac - /// Interrupt Force - pub const INTF = @intToPtr(*volatile Mmio(32, packed struct { - CH0: u1, - CH1: u1, - CH2: u1, - CH3: u1, - CH4: u1, - CH5: u1, - CH6: u1, - CH7: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0xac); - - /// address: 0x400500b0 - /// Interrupt status after masking & forcing - pub const INTS = @intToPtr(*volatile Mmio(32, packed struct { - CH0: u1, - CH1: u1, - CH2: u1, - CH3: u1, - CH4: u1, - CH5: u1, - CH6: u1, - CH7: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0xb0); - }; - - /// Controls time and alarms\n - /// time is a 64 bit value indicating the time in usec since power-on\n - /// timeh is the top 32 bits of time & timel is the bottom 32 bits\n - /// to change time write to timelw before timehw\n - /// to read time read from timelr before timehr\n - /// An alarm is set by setting alarm_enable and writing to the corresponding alarm - /// register\n - /// When an alarm is pending, the corresponding alarm_running signal will be high\n - /// An alarm can be cancelled before it has finished by clearing the alarm_enable\n - /// When an alarm fires, the corresponding alarm_irq is set and alarm_running is - /// cleared\n - /// To clear the interrupt write a 1 to the corresponding alarm_irq - pub const TIMER = struct { - pub const base_address = 0x40054000; - pub const version = "1"; - - /// address: 0x40054000 - /// Write to bits 63:32 of time\n - /// always write timelw before timehw - pub const TIMEHW = @intToPtr(*volatile u32, base_address + 0x0); - - /// address: 0x40054004 - /// Write to bits 31:0 of time\n - /// writes do not get copied to time until timehw is written - pub const TIMELW = @intToPtr(*volatile u32, base_address + 0x4); - - /// address: 0x40054008 - /// Read from bits 63:32 of time\n - /// always read timelr before timehr - pub const TIMEHR = @intToPtr(*volatile u32, base_address + 0x8); - - /// address: 0x4005400c - /// Read from bits 31:0 of time - pub const TIMELR = @intToPtr(*volatile u32, base_address + 0xc); - - /// address: 0x40054010 - /// Arm alarm 0, and configure the time it will fire.\n - /// Once armed, the alarm fires when TIMER_ALARM0 == TIMELR.\n - /// The alarm will disarm itself once it fires, and can\n - /// be disarmed early using the ARMED status register. - pub const ALARM0 = @intToPtr(*volatile u32, base_address + 0x10); - - /// address: 0x40054014 - /// Arm alarm 1, and configure the time it will fire.\n - /// Once armed, the alarm fires when TIMER_ALARM1 == TIMELR.\n - /// The alarm will disarm itself once it fires, and can\n - /// be disarmed early using the ARMED status register. - pub const ALARM1 = @intToPtr(*volatile u32, base_address + 0x14); - - /// address: 0x40054018 - /// Arm alarm 2, and configure the time it will fire.\n - /// Once armed, the alarm fires when TIMER_ALARM2 == TIMELR.\n - /// The alarm will disarm itself once it fires, and can\n - /// be disarmed early using the ARMED status register. - pub const ALARM2 = @intToPtr(*volatile u32, base_address + 0x18); - - /// address: 0x4005401c - /// Arm alarm 3, and configure the time it will fire.\n - /// Once armed, the alarm fires when TIMER_ALARM3 == TIMELR.\n - /// The alarm will disarm itself once it fires, and can\n - /// be disarmed early using the ARMED status register. - pub const ALARM3 = @intToPtr(*volatile u32, base_address + 0x1c); - - /// address: 0x40054020 - /// Indicates the armed/disarmed status of each alarm.\n - /// A write to the corresponding ALARMx register arms the alarm.\n - /// Alarms automatically disarm upon firing, but writing ones here\n - /// will disarm immediately without waiting to fire. - pub const ARMED = @intToPtr(*volatile MmioInt(32, u4), base_address + 0x20); - - /// address: 0x40054024 - /// Raw read from bits 63:32 of time (no side effects) - pub const TIMERAWH = @intToPtr(*volatile u32, base_address + 0x24); - - /// address: 0x40054028 - /// Raw read from bits 31:0 of time (no side effects) - pub const TIMERAWL = @intToPtr(*volatile u32, base_address + 0x28); - - /// address: 0x4005402c - /// Set bits high to enable pause when the corresponding debug ports are active - pub const DBGPAUSE = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - /// Pause when processor 0 is in debug mode - DBG0: u1, - /// Pause when processor 1 is in debug mode - DBG1: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - }), base_address + 0x2c); - - /// address: 0x40054030 - /// Set high to pause the timer - pub const PAUSE = @intToPtr(*volatile MmioInt(32, u1), base_address + 0x30); - - /// address: 0x40054034 - /// Raw Interrupts - pub const INTR = @intToPtr(*volatile Mmio(32, packed struct { - ALARM_0: u1, - ALARM_1: u1, - ALARM_2: u1, - ALARM_3: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - }), base_address + 0x34); - - /// address: 0x40054038 - /// Interrupt Enable - pub const INTE = @intToPtr(*volatile Mmio(32, packed struct { - ALARM_0: u1, - ALARM_1: u1, - ALARM_2: u1, - ALARM_3: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - }), base_address + 0x38); - - /// address: 0x4005403c - /// Interrupt Force - pub const INTF = @intToPtr(*volatile Mmio(32, packed struct { - ALARM_0: u1, - ALARM_1: u1, - ALARM_2: u1, - ALARM_3: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - }), base_address + 0x3c); - - /// address: 0x40054040 - /// Interrupt status after masking & forcing - pub const INTS = @intToPtr(*volatile Mmio(32, packed struct { - ALARM_0: u1, - ALARM_1: u1, - ALARM_2: u1, - ALARM_3: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - }), base_address + 0x40); - }; - pub const WATCHDOG = struct { - pub const base_address = 0x40058000; - pub const version = "1"; - - /// address: 0x40058000 - /// Watchdog control\n - /// The rst_wdsel register determines which subsystems are reset when the watchdog - /// is triggered.\n - /// The watchdog can be triggered in software. - pub const CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// Indicates the number of ticks / 2 (see errata RP2040-E1) before a watchdog reset - /// will be triggered - TIME: u24, - /// Pause the watchdog timer when JTAG is accessing the bus fabric - PAUSE_JTAG: u1, - /// Pause the watchdog timer when processor 0 is in debug mode - PAUSE_DBG0: u1, - /// Pause the watchdog timer when processor 1 is in debug mode - PAUSE_DBG1: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - /// When not enabled the watchdog timer is paused - ENABLE: u1, - /// Trigger a watchdog reset - TRIGGER: u1, - }), base_address + 0x0); - - /// address: 0x40058004 - /// Load the watchdog timer. The maximum setting is 0xffffff which corresponds to - /// 0xffffff / 2 ticks before triggering a watchdog reset (see errata RP2040-E1). - pub const LOAD = @intToPtr(*volatile MmioInt(32, u24), base_address + 0x4); - - /// address: 0x40058008 - /// Logs the reason for the last reset. Both bits are zero for the case of a - /// hardware reset. - pub const REASON = @intToPtr(*volatile Mmio(32, packed struct { - TIMER: u1, - FORCE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - }), base_address + 0x8); - - /// address: 0x4005800c - /// Scratch register. Information persists through soft reset of the chip. - pub const SCRATCH0 = @intToPtr(*volatile u32, base_address + 0xc); - - /// address: 0x40058010 - /// Scratch register. Information persists through soft reset of the chip. - pub const SCRATCH1 = @intToPtr(*volatile u32, base_address + 0x10); - - /// address: 0x40058014 - /// Scratch register. Information persists through soft reset of the chip. - pub const SCRATCH2 = @intToPtr(*volatile u32, base_address + 0x14); - - /// address: 0x40058018 - /// Scratch register. Information persists through soft reset of the chip. - pub const SCRATCH3 = @intToPtr(*volatile u32, base_address + 0x18); - - /// address: 0x4005801c - /// Scratch register. Information persists through soft reset of the chip. - pub const SCRATCH4 = @intToPtr(*volatile u32, base_address + 0x1c); - - /// address: 0x40058020 - /// Scratch register. Information persists through soft reset of the chip. - pub const SCRATCH5 = @intToPtr(*volatile u32, base_address + 0x20); - - /// address: 0x40058024 - /// Scratch register. Information persists through soft reset of the chip. - pub const SCRATCH6 = @intToPtr(*volatile u32, base_address + 0x24); - - /// address: 0x40058028 - /// Scratch register. Information persists through soft reset of the chip. - pub const SCRATCH7 = @intToPtr(*volatile u32, base_address + 0x28); - - /// address: 0x4005802c - /// Controls the tick generator - pub const TICK = @intToPtr(*volatile Mmio(32, packed struct { - /// Total number of clk_tick cycles before the next tick. - CYCLES: u9, - /// start / stop tick generation - ENABLE: u1, - /// Is the tick generator running? - RUNNING: u1, - /// Count down timer: the remaining number clk_tick cycles before the next tick is - /// generated. - COUNT: u9, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - }), base_address + 0x2c); - }; - - /// Register block to control RTC - pub const RTC = struct { - pub const base_address = 0x4005c000; - pub const version = "1"; - - /// address: 0x4005c000 - /// Divider minus 1 for the 1 second counter. Safe to change the value when RTC is - /// not enabled. - pub const CLKDIV_M1 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x0); - - /// address: 0x4005c004 - /// RTC setup register 0 - pub const SETUP_0 = @intToPtr(*volatile Mmio(32, packed struct { - /// Day of the month (1..31) - DAY: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - /// Month (1..12) - MONTH: u4, - /// Year - YEAR: u12, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x4); - - /// address: 0x4005c008 - /// RTC setup register 1 - pub const SETUP_1 = @intToPtr(*volatile Mmio(32, packed struct { - /// Seconds - SEC: u6, - reserved0: u1 = 0, - reserved1: u1 = 0, - /// Minutes - MIN: u6, - reserved2: u1 = 0, - reserved3: u1 = 0, - /// Hours - HOUR: u5, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - /// Day of the week: 1-Monday...0-Sunday ISO 8601 mod 7 - DOTW: u3, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x8); - - /// address: 0x4005c00c - /// RTC Control and status - pub const CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// Enable RTC - RTC_ENABLE: u1, - /// RTC enabled (running) - RTC_ACTIVE: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - /// Load RTC - LOAD: u1, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - /// If set, leapyear is forced off.\n - /// Useful for years divisible by 100 but not by 400 - FORCE_NOTLEAPYEAR: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - }), base_address + 0xc); - - /// address: 0x4005c010 - /// Interrupt setup register 0 - pub const IRQ_SETUP_0 = @intToPtr(*volatile Mmio(32, packed struct { - /// Day of the month (1..31) - DAY: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - /// Month (1..12) - MONTH: u4, - /// Year - YEAR: u12, - /// Enable day matching - DAY_ENA: u1, - /// Enable month matching - MONTH_ENA: u1, - /// Enable year matching - YEAR_ENA: u1, - reserved3: u1 = 0, - /// Global match enable. Don't change any other value while this one is enabled - MATCH_ENA: u1, - MATCH_ACTIVE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - }), base_address + 0x10); - - /// address: 0x4005c014 - /// Interrupt setup register 1 - pub const IRQ_SETUP_1 = @intToPtr(*volatile Mmio(32, packed struct { - /// Seconds - SEC: u6, - reserved0: u1 = 0, - reserved1: u1 = 0, - /// Minutes - MIN: u6, - reserved2: u1 = 0, - reserved3: u1 = 0, - /// Hours - HOUR: u5, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - /// Day of the week - DOTW: u3, - reserved7: u1 = 0, - /// Enable second matching - SEC_ENA: u1, - /// Enable minute matching - MIN_ENA: u1, - /// Enable hour matching - HOUR_ENA: u1, - /// Enable day of the week matching - DOTW_ENA: u1, - }), base_address + 0x14); - - /// address: 0x4005c018 - /// RTC register 1. - pub const RTC_1 = @intToPtr(*volatile Mmio(32, packed struct { - /// Day of the month (1..31) - DAY: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - /// Month (1..12) - MONTH: u4, - /// Year - YEAR: u12, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x18); - - /// address: 0x4005c01c - /// RTC register 0\n - /// Read this before RTC 1! - pub const RTC_0 = @intToPtr(*volatile Mmio(32, packed struct { - /// Seconds - SEC: u6, - reserved0: u1 = 0, - reserved1: u1 = 0, - /// Minutes - MIN: u6, - reserved2: u1 = 0, - reserved3: u1 = 0, - /// Hours - HOUR: u5, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - /// Day of the week - DOTW: u3, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x1c); - - /// address: 0x4005c020 - /// Raw Interrupts - pub const INTR = @intToPtr(*volatile Mmio(32, packed struct { - RTC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x20); - - /// address: 0x4005c024 - /// Interrupt Enable - pub const INTE = @intToPtr(*volatile Mmio(32, packed struct { - RTC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x24); - - /// address: 0x4005c028 - /// Interrupt Force - pub const INTF = @intToPtr(*volatile Mmio(32, packed struct { - RTC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x28); - - /// address: 0x4005c02c - /// Interrupt status after masking & forcing - pub const INTS = @intToPtr(*volatile Mmio(32, packed struct { - RTC: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - padding30: u1 = 0, - }), base_address + 0x2c); - }; - pub const ROSC = struct { - pub const base_address = 0x40060000; - pub const version = "1"; - - /// address: 0x40060000 - /// Ring Oscillator control - pub const CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// Controls the number of delay stages in the ROSC ring\n - /// LOW uses stages 0 to 7\n - /// MEDIUM uses stages 0 to 5\n - /// HIGH uses stages 0 to 3\n - /// TOOHIGH uses stages 0 to 1 and should not be used because its frequency exceeds - /// design specifications\n - /// The clock output will not glitch when changing the range up one step at a time\n - /// The clock output will glitch when changing the range down\n - /// Note: the values here are gray coded which is why HIGH comes before TOOHIGH - FREQ_RANGE: u12, - /// On power-up this field is initialised to ENABLE\n - /// The system clock must be switched to another source before setting this field to - /// DISABLE otherwise the chip will lock up\n - /// The 12-bit code is intended to give some protection against accidental writes. - /// An invalid setting will enable the oscillator. - ENABLE: u12, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x0); - - /// address: 0x40060004 - /// The FREQA & FREQB registers control the frequency by controlling the drive - /// strength of each stage\n - /// The drive strength has 4 levels determined by the number of bits set\n - /// Increasing the number of bits set increases the drive strength and increases the - /// oscillation frequency\n - /// 0 bits set is the default drive strength\n - /// 1 bit set doubles the drive strength\n - /// 2 bits set triples drive strength\n - /// 3 bits set quadruples drive strength - pub const FREQA = @intToPtr(*volatile Mmio(32, packed struct { - /// Stage 0 drive strength - DS0: u3, - reserved0: u1 = 0, - /// Stage 1 drive strength - DS1: u3, - reserved1: u1 = 0, - /// Stage 2 drive strength - DS2: u3, - reserved2: u1 = 0, - /// Stage 3 drive strength - DS3: u3, - reserved3: u1 = 0, - /// Set to 0x9696 to apply the settings\n - /// Any other value in this field will set all drive strengths to 0 - PASSWD: u16, - }), base_address + 0x4); - - /// address: 0x40060008 - /// For a detailed description see freqa register - pub const FREQB = @intToPtr(*volatile Mmio(32, packed struct { - /// Stage 4 drive strength - DS4: u3, - reserved0: u1 = 0, - /// Stage 5 drive strength - DS5: u3, - reserved1: u1 = 0, - /// Stage 6 drive strength - DS6: u3, - reserved2: u1 = 0, - /// Stage 7 drive strength - DS7: u3, - reserved3: u1 = 0, - /// Set to 0x9696 to apply the settings\n - /// Any other value in this field will set all drive strengths to 0 - PASSWD: u16, - }), base_address + 0x8); - - /// address: 0x4006000c - /// Ring Oscillator pause control\n - /// This is used to save power by pausing the ROSC\n - /// On power-up this field is initialised to WAKE\n - /// An invalid write will also select WAKE\n - /// Warning: setup the irq before selecting dormant mode - pub const DORMANT = @intToPtr(*volatile u32, base_address + 0xc); - - /// address: 0x40060010 - /// Controls the output divider - pub const DIV = @intToPtr(*volatile MmioInt(32, u12), base_address + 0x10); - - /// address: 0x40060014 - /// Controls the phase shifted output - pub const PHASE = @intToPtr(*volatile Mmio(32, packed struct { - /// phase shift the phase-shifted output by SHIFT input clocks\n - /// this can be changed on-the-fly\n - /// must be set to 0 before setting div=1 - SHIFT: u2, - /// invert the phase-shifted output\n - /// this is ignored when div=1 - FLIP: u1, - /// enable the phase-shifted output\n - /// this can be changed on-the-fly - ENABLE: u1, - /// set to 0xaa\n - /// any other value enables the output with shift=0 - PASSWD: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x14); - - /// address: 0x40060018 - /// Ring Oscillator Status - pub const STATUS = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - /// Oscillator is enabled but not necessarily running and stable\n - /// this resets to 0 but transitions to 1 during chip startup - ENABLED: u1, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - /// post-divider is running\n - /// this resets to 0 but transitions to 1 during chip startup - DIV_RUNNING: u1, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - reserved18: u1 = 0, - reserved19: u1 = 0, - reserved20: u1 = 0, - reserved21: u1 = 0, - /// An invalid value has been written to CTRL_ENABLE or CTRL_FREQ_RANGE or FREQA or - /// FREQB or DIV or PHASE or DORMANT - BADWRITE: u1, - reserved22: u1 = 0, - reserved23: u1 = 0, - reserved24: u1 = 0, - reserved25: u1 = 0, - reserved26: u1 = 0, - reserved27: u1 = 0, - /// Oscillator is running and stable - STABLE: u1, - }), base_address + 0x18); - - /// address: 0x4006001c - /// This just reads the state of the oscillator output so randomness is compromised - /// if the ring oscillator is stopped or run at a harmonic of the bus frequency - pub const RANDOMBIT = @intToPtr(*volatile MmioInt(32, u1), base_address + 0x1c); - - /// address: 0x40060020 - /// A down counter running at the ROSC frequency which counts to zero and stops.\n - /// To start the counter write a non-zero value.\n - /// Can be used for short software pauses when setting up time sensitive hardware. - pub const COUNT = @intToPtr(*volatile MmioInt(32, u8), base_address + 0x20); - }; - - /// control and status for on-chip voltage regulator and chip level reset subsystem - pub const VREG_AND_CHIP_RESET = struct { - pub const base_address = 0x40064000; - pub const version = "1"; - - /// address: 0x40064000 - /// Voltage regulator control and status - pub const VREG = @intToPtr(*volatile Mmio(32, packed struct { - /// enable\n - /// 0=not enabled, 1=enabled - EN: u1, - /// high impedance mode select\n - /// 0=not in high impedance mode, 1=in high impedance mode - HIZ: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - /// output voltage select\n - /// 0000 to 0101 - 0.80V\n - /// 0110 - 0.85V\n - /// 0111 - 0.90V\n - /// 1000 - 0.95V\n - /// 1001 - 1.00V\n - /// 1010 - 1.05V\n - /// 1011 - 1.10V (default)\n - /// 1100 - 1.15V\n - /// 1101 - 1.20V\n - /// 1110 - 1.25V\n - /// 1111 - 1.30V - VSEL: u4, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - /// regulation status\n - /// 0=not in regulation, 1=in regulation - ROK: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - }), base_address + 0x0); - - /// address: 0x40064004 - /// brown-out detection control - pub const BOD = @intToPtr(*volatile Mmio(32, packed struct { - /// enable\n - /// 0=not enabled, 1=enabled - EN: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - /// threshold select\n - /// 0000 - 0.473V\n - /// 0001 - 0.516V\n - /// 0010 - 0.559V\n - /// 0011 - 0.602V\n - /// 0100 - 0.645V\n - /// 0101 - 0.688V\n - /// 0110 - 0.731V\n - /// 0111 - 0.774V\n - /// 1000 - 0.817V\n - /// 1001 - 0.860V (default)\n - /// 1010 - 0.903V\n - /// 1011 - 0.946V\n - /// 1100 - 0.989V\n - /// 1101 - 1.032V\n - /// 1110 - 1.075V\n - /// 1111 - 1.118V - VSEL: u4, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - }), base_address + 0x4); - - /// address: 0x40064008 - /// Chip reset control and status - pub const CHIP_RESET = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// Last reset was from the power-on reset or brown-out detection blocks - HAD_POR: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - /// Last reset was from the RUN pin - HAD_RUN: u1, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - /// Last reset was from the debug port - HAD_PSM_RESTART: u1, - reserved18: u1 = 0, - reserved19: u1 = 0, - reserved20: u1 = 0, - /// This is set by psm_restart from the debugger.\n - /// Its purpose is to branch bootcode to a safe mode when the debugger has issued a - /// psm_restart in order to recover from a boot lock-up.\n - /// In the safe mode the debugger can repair the boot code, clear this flag then - /// reboot the processor. - PSM_RESTART_FLAG: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - }), base_address + 0x8); - }; - - /// Testbench manager. Allows the programmer to know what platform their software is - /// running on. - pub const TBMAN = struct { - pub const base_address = 0x4006c000; - pub const version = "1"; - - /// address: 0x4006c000 - /// Indicates the type of platform in use - pub const PLATFORM = @intToPtr(*volatile Mmio(32, packed struct { - /// Indicates the platform is an ASIC - ASIC: u1, - /// Indicates the platform is an FPGA - FPGA: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - }), base_address + 0x0); - }; - - /// DMA with separate read and write masters - pub const DMA = struct { - pub const base_address = 0x50000000; - pub const version = "1"; - - /// address: 0x50000000 - /// DMA Channel 0 Read Address pointer\n - /// This register updates automatically each time a read completes. The current - /// value is the next address to be read by this channel. - pub const CH0_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x0); - - /// address: 0x50000004 - /// DMA Channel 0 Write Address pointer\n - /// This register updates automatically each time a write completes. The current - /// value is the next address to be written by this channel. - pub const CH0_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x4); - - /// address: 0x50000008 - /// DMA Channel 0 Transfer Count\n - /// Program the number of bus transfers a channel will perform before halting. Note - /// that, if transfers are larger than one byte in size, this is not equal to the - /// number of bytes transferred (see CTRL_DATA_SIZE).\n\n - /// When the channel is active, reading this register shows the number of transfers - /// remaining, updating automatically each time a write transfer completes.\n\n - /// Writing this register sets the RELOAD value for the transfer counter. Each time - /// this channel is triggered, the RELOAD value is copied into the live transfer - /// counter. The channel can be started multiple times, and will perform the same - /// number of transfers each time, as programmed by most recent write.\n\n - /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a - /// trigger, the written value is used immediately as the length of the new transfer - /// sequence, as well as being written to RELOAD. - pub const CH0_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x8); - - /// address: 0x5000000c - /// DMA Channel 0 Control and Status - pub const CH0_CTRL_TRIG = @intToPtr(*volatile Mmio(32, packed struct { - /// DMA Channel Enable.\n - /// When 1, the channel will respond to triggering events, which will cause it to - /// become BUSY and start transferring data. When 0, the channel will ignore - /// triggers, stop issuing transfers, and pause the current transfer sequence (i.e. - /// BUSY will remain high if already high) - EN: u1, - /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in - /// each scheduling round, all high priority channels are considered first, and then - /// only a single low priority channel, before returning to the high priority - /// channels.\n\n - /// This only affects the order in which the DMA schedules channels. The DMA's bus - /// priority is not changed. If the DMA is not saturated then a low priority channel - /// will see no loss of throughput. - HIGH_PRIORITY: u1, - /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR - /// advance by this amount (1/2/4 bytes) with each transfer. - DATA_SIZE: u2, - /// If 1, the read address increments with each transfer. If 0, each read is - /// directed to the same, initial address.\n\n - /// Generally this should be disabled for peripheral-to-memory transfers. - INCR_READ: u1, - /// If 1, the write address increments with each transfer. If 0, each write is - /// directed to the same, initial address.\n\n - /// Generally this should be disabled for memory-to-peripheral transfers. - INCR_WRITE: u1, - /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower - /// n bits of the address will change. This wraps the address on a (1 << n) byte - /// boundary, facilitating access to naturally-aligned ring buffers.\n\n - /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read - /// or write addresses, based on value of RING_SEL. - RING_SIZE: u4, - /// Select whether RING_SIZE applies to read or write addresses.\n - /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write - /// addresses are wrapped. - RING_SEL: u1, - /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. - /// Disable by setting CHAIN_TO = _(this channel)_.\n - /// Reset value is equal to channel number (0). - CHAIN_TO: u4, - /// Select a Transfer Request signal.\n - /// The channel uses the transfer request signal to pace its data transfer rate. - /// Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request - /// from the system).\n - /// 0x0 to 0x3a -> select DREQ n as TREQ - TREQ_SEL: u6, - /// In QUIET mode, the channel does not generate IRQs at the end of every transfer - /// block. Instead, an IRQ is raised when NULL is written to a trigger register, - /// indicating the end of a control block chain.\n\n - /// This reduces the number of interrupts to be serviced by the CPU when - /// transferring a DMA chain of many small control blocks. - IRQ_QUIET: u1, - /// Apply byte-swap transformation to DMA data.\n - /// For byte data, this has no effect. For halfword data, the two bytes of each - /// halfword are swapped. For word data, the four bytes of each word are swapped to - /// reverse order. - BSWAP: u1, - /// If 1, this channel's data transfers are visible to the sniff hardware, and each - /// transfer will advance the state of the checksum. This only applies if the sniff - /// hardware is enabled, and has this channel selected.\n\n - /// This allows checksum to be enabled or disabled on a per-control- block basis. - SNIFF_EN: u1, - /// This flag goes high when the channel starts a new transfer sequence, and low - /// when the last transfer of that sequence completes. Clearing EN while BUSY is - /// high pauses the channel, and BUSY will stay high while paused.\n\n - /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. - BUSY: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - /// If 1, the channel received a write bus error. Write one to clear.\n - /// WRITE_ADDR shows the approximate address where the bus error was encountered - /// (will not to be earlier, or more than 5 transfers later) - WRITE_ERROR: u1, - /// If 1, the channel received a read bus error. Write one to clear.\n - /// READ_ADDR shows the approximate address where the bus error was encountered - /// (will not to be earlier, or more than 3 transfers later) - READ_ERROR: u1, - /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it - /// encounters any bus error, and always raises its channel IRQ flag. - AHB_ERROR: u1, - }), base_address + 0xc); - - /// address: 0x50000010 - /// Alias for channel 0 CTRL register - pub const CH0_AL1_CTRL = @intToPtr(*volatile u32, base_address + 0x10); - - /// address: 0x50000014 - /// Alias for channel 0 READ_ADDR register - pub const CH0_AL1_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x14); - - /// address: 0x50000018 - /// Alias for channel 0 WRITE_ADDR register - pub const CH0_AL1_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x18); - - /// address: 0x5000001c - /// Alias for channel 0 TRANS_COUNT register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH0_AL1_TRANS_COUNT_TRIG = @intToPtr(*volatile u32, base_address + 0x1c); - - /// address: 0x50000020 - /// Alias for channel 0 CTRL register - pub const CH0_AL2_CTRL = @intToPtr(*volatile u32, base_address + 0x20); - - /// address: 0x50000024 - /// Alias for channel 0 TRANS_COUNT register - pub const CH0_AL2_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x24); - - /// address: 0x50000028 - /// Alias for channel 0 READ_ADDR register - pub const CH0_AL2_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x28); - - /// address: 0x5000002c - /// Alias for channel 0 WRITE_ADDR register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH0_AL2_WRITE_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x2c); - - /// address: 0x50000030 - /// Alias for channel 0 CTRL register - pub const CH0_AL3_CTRL = @intToPtr(*volatile u32, base_address + 0x30); - - /// address: 0x50000034 - /// Alias for channel 0 WRITE_ADDR register - pub const CH0_AL3_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x34); - - /// address: 0x50000038 - /// Alias for channel 0 TRANS_COUNT register - pub const CH0_AL3_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x38); - - /// address: 0x5000003c - /// Alias for channel 0 READ_ADDR register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH0_AL3_READ_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x3c); - - /// address: 0x50000040 - /// DMA Channel 1 Read Address pointer\n - /// This register updates automatically each time a read completes. The current - /// value is the next address to be read by this channel. - pub const CH1_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x40); - - /// address: 0x50000044 - /// DMA Channel 1 Write Address pointer\n - /// This register updates automatically each time a write completes. The current - /// value is the next address to be written by this channel. - pub const CH1_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x44); - - /// address: 0x50000048 - /// DMA Channel 1 Transfer Count\n - /// Program the number of bus transfers a channel will perform before halting. Note - /// that, if transfers are larger than one byte in size, this is not equal to the - /// number of bytes transferred (see CTRL_DATA_SIZE).\n\n - /// When the channel is active, reading this register shows the number of transfers - /// remaining, updating automatically each time a write transfer completes.\n\n - /// Writing this register sets the RELOAD value for the transfer counter. Each time - /// this channel is triggered, the RELOAD value is copied into the live transfer - /// counter. The channel can be started multiple times, and will perform the same - /// number of transfers each time, as programmed by most recent write.\n\n - /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a - /// trigger, the written value is used immediately as the length of the new transfer - /// sequence, as well as being written to RELOAD. - pub const CH1_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x48); - - /// address: 0x5000004c - /// DMA Channel 1 Control and Status - pub const CH1_CTRL_TRIG = @intToPtr(*volatile Mmio(32, packed struct { - /// DMA Channel Enable.\n - /// When 1, the channel will respond to triggering events, which will cause it to - /// become BUSY and start transferring data. When 0, the channel will ignore - /// triggers, stop issuing transfers, and pause the current transfer sequence (i.e. - /// BUSY will remain high if already high) - EN: u1, - /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in - /// each scheduling round, all high priority channels are considered first, and then - /// only a single low priority channel, before returning to the high priority - /// channels.\n\n - /// This only affects the order in which the DMA schedules channels. The DMA's bus - /// priority is not changed. If the DMA is not saturated then a low priority channel - /// will see no loss of throughput. - HIGH_PRIORITY: u1, - /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR - /// advance by this amount (1/2/4 bytes) with each transfer. - DATA_SIZE: u2, - /// If 1, the read address increments with each transfer. If 0, each read is - /// directed to the same, initial address.\n\n - /// Generally this should be disabled for peripheral-to-memory transfers. - INCR_READ: u1, - /// If 1, the write address increments with each transfer. If 0, each write is - /// directed to the same, initial address.\n\n - /// Generally this should be disabled for memory-to-peripheral transfers. - INCR_WRITE: u1, - /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower - /// n bits of the address will change. This wraps the address on a (1 << n) byte - /// boundary, facilitating access to naturally-aligned ring buffers.\n\n - /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read - /// or write addresses, based on value of RING_SEL. - RING_SIZE: u4, - /// Select whether RING_SIZE applies to read or write addresses.\n - /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write - /// addresses are wrapped. - RING_SEL: u1, - /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. - /// Disable by setting CHAIN_TO = _(this channel)_.\n - /// Reset value is equal to channel number (1). - CHAIN_TO: u4, - /// Select a Transfer Request signal.\n - /// The channel uses the transfer request signal to pace its data transfer rate. - /// Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request - /// from the system).\n - /// 0x0 to 0x3a -> select DREQ n as TREQ - TREQ_SEL: u6, - /// In QUIET mode, the channel does not generate IRQs at the end of every transfer - /// block. Instead, an IRQ is raised when NULL is written to a trigger register, - /// indicating the end of a control block chain.\n\n - /// This reduces the number of interrupts to be serviced by the CPU when - /// transferring a DMA chain of many small control blocks. - IRQ_QUIET: u1, - /// Apply byte-swap transformation to DMA data.\n - /// For byte data, this has no effect. For halfword data, the two bytes of each - /// halfword are swapped. For word data, the four bytes of each word are swapped to - /// reverse order. - BSWAP: u1, - /// If 1, this channel's data transfers are visible to the sniff hardware, and each - /// transfer will advance the state of the checksum. This only applies if the sniff - /// hardware is enabled, and has this channel selected.\n\n - /// This allows checksum to be enabled or disabled on a per-control- block basis. - SNIFF_EN: u1, - /// This flag goes high when the channel starts a new transfer sequence, and low - /// when the last transfer of that sequence completes. Clearing EN while BUSY is - /// high pauses the channel, and BUSY will stay high while paused.\n\n - /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. - BUSY: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - /// If 1, the channel received a write bus error. Write one to clear.\n - /// WRITE_ADDR shows the approximate address where the bus error was encountered - /// (will not to be earlier, or more than 5 transfers later) - WRITE_ERROR: u1, - /// If 1, the channel received a read bus error. Write one to clear.\n - /// READ_ADDR shows the approximate address where the bus error was encountered - /// (will not to be earlier, or more than 3 transfers later) - READ_ERROR: u1, - /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it - /// encounters any bus error, and always raises its channel IRQ flag. - AHB_ERROR: u1, - }), base_address + 0x4c); - - /// address: 0x50000050 - /// Alias for channel 1 CTRL register - pub const CH1_AL1_CTRL = @intToPtr(*volatile u32, base_address + 0x50); - - /// address: 0x50000054 - /// Alias for channel 1 READ_ADDR register - pub const CH1_AL1_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x54); - - /// address: 0x50000058 - /// Alias for channel 1 WRITE_ADDR register - pub const CH1_AL1_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x58); - - /// address: 0x5000005c - /// Alias for channel 1 TRANS_COUNT register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH1_AL1_TRANS_COUNT_TRIG = @intToPtr(*volatile u32, base_address + 0x5c); - - /// address: 0x50000060 - /// Alias for channel 1 CTRL register - pub const CH1_AL2_CTRL = @intToPtr(*volatile u32, base_address + 0x60); - - /// address: 0x50000064 - /// Alias for channel 1 TRANS_COUNT register - pub const CH1_AL2_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x64); - - /// address: 0x50000068 - /// Alias for channel 1 READ_ADDR register - pub const CH1_AL2_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x68); - - /// address: 0x5000006c - /// Alias for channel 1 WRITE_ADDR register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH1_AL2_WRITE_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x6c); - - /// address: 0x50000070 - /// Alias for channel 1 CTRL register - pub const CH1_AL3_CTRL = @intToPtr(*volatile u32, base_address + 0x70); - - /// address: 0x50000074 - /// Alias for channel 1 WRITE_ADDR register - pub const CH1_AL3_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x74); - - /// address: 0x50000078 - /// Alias for channel 1 TRANS_COUNT register - pub const CH1_AL3_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x78); - - /// address: 0x5000007c - /// Alias for channel 1 READ_ADDR register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH1_AL3_READ_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x7c); - - /// address: 0x50000080 - /// DMA Channel 2 Read Address pointer\n - /// This register updates automatically each time a read completes. The current - /// value is the next address to be read by this channel. - pub const CH2_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x80); - - /// address: 0x50000084 - /// DMA Channel 2 Write Address pointer\n - /// This register updates automatically each time a write completes. The current - /// value is the next address to be written by this channel. - pub const CH2_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x84); - - /// address: 0x50000088 - /// DMA Channel 2 Transfer Count\n - /// Program the number of bus transfers a channel will perform before halting. Note - /// that, if transfers are larger than one byte in size, this is not equal to the - /// number of bytes transferred (see CTRL_DATA_SIZE).\n\n - /// When the channel is active, reading this register shows the number of transfers - /// remaining, updating automatically each time a write transfer completes.\n\n - /// Writing this register sets the RELOAD value for the transfer counter. Each time - /// this channel is triggered, the RELOAD value is copied into the live transfer - /// counter. The channel can be started multiple times, and will perform the same - /// number of transfers each time, as programmed by most recent write.\n\n - /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a - /// trigger, the written value is used immediately as the length of the new transfer - /// sequence, as well as being written to RELOAD. - pub const CH2_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x88); - - /// address: 0x5000008c - /// DMA Channel 2 Control and Status - pub const CH2_CTRL_TRIG = @intToPtr(*volatile Mmio(32, packed struct { - /// DMA Channel Enable.\n - /// When 1, the channel will respond to triggering events, which will cause it to - /// become BUSY and start transferring data. When 0, the channel will ignore - /// triggers, stop issuing transfers, and pause the current transfer sequence (i.e. - /// BUSY will remain high if already high) - EN: u1, - /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in - /// each scheduling round, all high priority channels are considered first, and then - /// only a single low priority channel, before returning to the high priority - /// channels.\n\n - /// This only affects the order in which the DMA schedules channels. The DMA's bus - /// priority is not changed. If the DMA is not saturated then a low priority channel - /// will see no loss of throughput. - HIGH_PRIORITY: u1, - /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR - /// advance by this amount (1/2/4 bytes) with each transfer. - DATA_SIZE: u2, - /// If 1, the read address increments with each transfer. If 0, each read is - /// directed to the same, initial address.\n\n - /// Generally this should be disabled for peripheral-to-memory transfers. - INCR_READ: u1, - /// If 1, the write address increments with each transfer. If 0, each write is - /// directed to the same, initial address.\n\n - /// Generally this should be disabled for memory-to-peripheral transfers. - INCR_WRITE: u1, - /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower - /// n bits of the address will change. This wraps the address on a (1 << n) byte - /// boundary, facilitating access to naturally-aligned ring buffers.\n\n - /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read - /// or write addresses, based on value of RING_SEL. - RING_SIZE: u4, - /// Select whether RING_SIZE applies to read or write addresses.\n - /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write - /// addresses are wrapped. - RING_SEL: u1, - /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. - /// Disable by setting CHAIN_TO = _(this channel)_.\n - /// Reset value is equal to channel number (2). - CHAIN_TO: u4, - /// Select a Transfer Request signal.\n - /// The channel uses the transfer request signal to pace its data transfer rate. - /// Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request - /// from the system).\n - /// 0x0 to 0x3a -> select DREQ n as TREQ - TREQ_SEL: u6, - /// In QUIET mode, the channel does not generate IRQs at the end of every transfer - /// block. Instead, an IRQ is raised when NULL is written to a trigger register, - /// indicating the end of a control block chain.\n\n - /// This reduces the number of interrupts to be serviced by the CPU when - /// transferring a DMA chain of many small control blocks. - IRQ_QUIET: u1, - /// Apply byte-swap transformation to DMA data.\n - /// For byte data, this has no effect. For halfword data, the two bytes of each - /// halfword are swapped. For word data, the four bytes of each word are swapped to - /// reverse order. - BSWAP: u1, - /// If 1, this channel's data transfers are visible to the sniff hardware, and each - /// transfer will advance the state of the checksum. This only applies if the sniff - /// hardware is enabled, and has this channel selected.\n\n - /// This allows checksum to be enabled or disabled on a per-control- block basis. - SNIFF_EN: u1, - /// This flag goes high when the channel starts a new transfer sequence, and low - /// when the last transfer of that sequence completes. Clearing EN while BUSY is - /// high pauses the channel, and BUSY will stay high while paused.\n\n - /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. - BUSY: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - /// If 1, the channel received a write bus error. Write one to clear.\n - /// WRITE_ADDR shows the approximate address where the bus error was encountered - /// (will not to be earlier, or more than 5 transfers later) - WRITE_ERROR: u1, - /// If 1, the channel received a read bus error. Write one to clear.\n - /// READ_ADDR shows the approximate address where the bus error was encountered - /// (will not to be earlier, or more than 3 transfers later) - READ_ERROR: u1, - /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it - /// encounters any bus error, and always raises its channel IRQ flag. - AHB_ERROR: u1, - }), base_address + 0x8c); - - /// address: 0x50000090 - /// Alias for channel 2 CTRL register - pub const CH2_AL1_CTRL = @intToPtr(*volatile u32, base_address + 0x90); - - /// address: 0x50000094 - /// Alias for channel 2 READ_ADDR register - pub const CH2_AL1_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x94); - - /// address: 0x50000098 - /// Alias for channel 2 WRITE_ADDR register - pub const CH2_AL1_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x98); - - /// address: 0x5000009c - /// Alias for channel 2 TRANS_COUNT register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH2_AL1_TRANS_COUNT_TRIG = @intToPtr(*volatile u32, base_address + 0x9c); - - /// address: 0x500000a0 - /// Alias for channel 2 CTRL register - pub const CH2_AL2_CTRL = @intToPtr(*volatile u32, base_address + 0xa0); - - /// address: 0x500000a4 - /// Alias for channel 2 TRANS_COUNT register - pub const CH2_AL2_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0xa4); - - /// address: 0x500000a8 - /// Alias for channel 2 READ_ADDR register - pub const CH2_AL2_READ_ADDR = @intToPtr(*volatile u32, base_address + 0xa8); - - /// address: 0x500000ac - /// Alias for channel 2 WRITE_ADDR register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH2_AL2_WRITE_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0xac); - - /// address: 0x500000b0 - /// Alias for channel 2 CTRL register - pub const CH2_AL3_CTRL = @intToPtr(*volatile u32, base_address + 0xb0); - - /// address: 0x500000b4 - /// Alias for channel 2 WRITE_ADDR register - pub const CH2_AL3_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0xb4); - - /// address: 0x500000b8 - /// Alias for channel 2 TRANS_COUNT register - pub const CH2_AL3_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0xb8); - - /// address: 0x500000bc - /// Alias for channel 2 READ_ADDR register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH2_AL3_READ_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0xbc); - - /// address: 0x500000c0 - /// DMA Channel 3 Read Address pointer\n - /// This register updates automatically each time a read completes. The current - /// value is the next address to be read by this channel. - pub const CH3_READ_ADDR = @intToPtr(*volatile u32, base_address + 0xc0); - - /// address: 0x500000c4 - /// DMA Channel 3 Write Address pointer\n - /// This register updates automatically each time a write completes. The current - /// value is the next address to be written by this channel. - pub const CH3_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0xc4); - - /// address: 0x500000c8 - /// DMA Channel 3 Transfer Count\n - /// Program the number of bus transfers a channel will perform before halting. Note - /// that, if transfers are larger than one byte in size, this is not equal to the - /// number of bytes transferred (see CTRL_DATA_SIZE).\n\n - /// When the channel is active, reading this register shows the number of transfers - /// remaining, updating automatically each time a write transfer completes.\n\n - /// Writing this register sets the RELOAD value for the transfer counter. Each time - /// this channel is triggered, the RELOAD value is copied into the live transfer - /// counter. The channel can be started multiple times, and will perform the same - /// number of transfers each time, as programmed by most recent write.\n\n - /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a - /// trigger, the written value is used immediately as the length of the new transfer - /// sequence, as well as being written to RELOAD. - pub const CH3_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0xc8); - - /// address: 0x500000cc - /// DMA Channel 3 Control and Status - pub const CH3_CTRL_TRIG = @intToPtr(*volatile Mmio(32, packed struct { - /// DMA Channel Enable.\n - /// When 1, the channel will respond to triggering events, which will cause it to - /// become BUSY and start transferring data. When 0, the channel will ignore - /// triggers, stop issuing transfers, and pause the current transfer sequence (i.e. - /// BUSY will remain high if already high) - EN: u1, - /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in - /// each scheduling round, all high priority channels are considered first, and then - /// only a single low priority channel, before returning to the high priority - /// channels.\n\n - /// This only affects the order in which the DMA schedules channels. The DMA's bus - /// priority is not changed. If the DMA is not saturated then a low priority channel - /// will see no loss of throughput. - HIGH_PRIORITY: u1, - /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR - /// advance by this amount (1/2/4 bytes) with each transfer. - DATA_SIZE: u2, - /// If 1, the read address increments with each transfer. If 0, each read is - /// directed to the same, initial address.\n\n - /// Generally this should be disabled for peripheral-to-memory transfers. - INCR_READ: u1, - /// If 1, the write address increments with each transfer. If 0, each write is - /// directed to the same, initial address.\n\n - /// Generally this should be disabled for memory-to-peripheral transfers. - INCR_WRITE: u1, - /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower - /// n bits of the address will change. This wraps the address on a (1 << n) byte - /// boundary, facilitating access to naturally-aligned ring buffers.\n\n - /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read - /// or write addresses, based on value of RING_SEL. - RING_SIZE: u4, - /// Select whether RING_SIZE applies to read or write addresses.\n - /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write - /// addresses are wrapped. - RING_SEL: u1, - /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. - /// Disable by setting CHAIN_TO = _(this channel)_.\n - /// Reset value is equal to channel number (3). - CHAIN_TO: u4, - /// Select a Transfer Request signal.\n - /// The channel uses the transfer request signal to pace its data transfer rate. - /// Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request - /// from the system).\n - /// 0x0 to 0x3a -> select DREQ n as TREQ - TREQ_SEL: u6, - /// In QUIET mode, the channel does not generate IRQs at the end of every transfer - /// block. Instead, an IRQ is raised when NULL is written to a trigger register, - /// indicating the end of a control block chain.\n\n - /// This reduces the number of interrupts to be serviced by the CPU when - /// transferring a DMA chain of many small control blocks. - IRQ_QUIET: u1, - /// Apply byte-swap transformation to DMA data.\n - /// For byte data, this has no effect. For halfword data, the two bytes of each - /// halfword are swapped. For word data, the four bytes of each word are swapped to - /// reverse order. - BSWAP: u1, - /// If 1, this channel's data transfers are visible to the sniff hardware, and each - /// transfer will advance the state of the checksum. This only applies if the sniff - /// hardware is enabled, and has this channel selected.\n\n - /// This allows checksum to be enabled or disabled on a per-control- block basis. - SNIFF_EN: u1, - /// This flag goes high when the channel starts a new transfer sequence, and low - /// when the last transfer of that sequence completes. Clearing EN while BUSY is - /// high pauses the channel, and BUSY will stay high while paused.\n\n - /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. - BUSY: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - /// If 1, the channel received a write bus error. Write one to clear.\n - /// WRITE_ADDR shows the approximate address where the bus error was encountered - /// (will not to be earlier, or more than 5 transfers later) - WRITE_ERROR: u1, - /// If 1, the channel received a read bus error. Write one to clear.\n - /// READ_ADDR shows the approximate address where the bus error was encountered - /// (will not to be earlier, or more than 3 transfers later) - READ_ERROR: u1, - /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it - /// encounters any bus error, and always raises its channel IRQ flag. - AHB_ERROR: u1, - }), base_address + 0xcc); - - /// address: 0x500000d0 - /// Alias for channel 3 CTRL register - pub const CH3_AL1_CTRL = @intToPtr(*volatile u32, base_address + 0xd0); - - /// address: 0x500000d4 - /// Alias for channel 3 READ_ADDR register - pub const CH3_AL1_READ_ADDR = @intToPtr(*volatile u32, base_address + 0xd4); - - /// address: 0x500000d8 - /// Alias for channel 3 WRITE_ADDR register - pub const CH3_AL1_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0xd8); - - /// address: 0x500000dc - /// Alias for channel 3 TRANS_COUNT register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH3_AL1_TRANS_COUNT_TRIG = @intToPtr(*volatile u32, base_address + 0xdc); - - /// address: 0x500000e0 - /// Alias for channel 3 CTRL register - pub const CH3_AL2_CTRL = @intToPtr(*volatile u32, base_address + 0xe0); - - /// address: 0x500000e4 - /// Alias for channel 3 TRANS_COUNT register - pub const CH3_AL2_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0xe4); - - /// address: 0x500000e8 - /// Alias for channel 3 READ_ADDR register - pub const CH3_AL2_READ_ADDR = @intToPtr(*volatile u32, base_address + 0xe8); - - /// address: 0x500000ec - /// Alias for channel 3 WRITE_ADDR register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH3_AL2_WRITE_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0xec); - - /// address: 0x500000f0 - /// Alias for channel 3 CTRL register - pub const CH3_AL3_CTRL = @intToPtr(*volatile u32, base_address + 0xf0); - - /// address: 0x500000f4 - /// Alias for channel 3 WRITE_ADDR register - pub const CH3_AL3_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0xf4); - - /// address: 0x500000f8 - /// Alias for channel 3 TRANS_COUNT register - pub const CH3_AL3_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0xf8); - - /// address: 0x500000fc - /// Alias for channel 3 READ_ADDR register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH3_AL3_READ_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0xfc); - - /// address: 0x50000100 - /// DMA Channel 4 Read Address pointer\n - /// This register updates automatically each time a read completes. The current - /// value is the next address to be read by this channel. - pub const CH4_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x100); - - /// address: 0x50000104 - /// DMA Channel 4 Write Address pointer\n - /// This register updates automatically each time a write completes. The current - /// value is the next address to be written by this channel. - pub const CH4_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x104); - - /// address: 0x50000108 - /// DMA Channel 4 Transfer Count\n - /// Program the number of bus transfers a channel will perform before halting. Note - /// that, if transfers are larger than one byte in size, this is not equal to the - /// number of bytes transferred (see CTRL_DATA_SIZE).\n\n - /// When the channel is active, reading this register shows the number of transfers - /// remaining, updating automatically each time a write transfer completes.\n\n - /// Writing this register sets the RELOAD value for the transfer counter. Each time - /// this channel is triggered, the RELOAD value is copied into the live transfer - /// counter. The channel can be started multiple times, and will perform the same - /// number of transfers each time, as programmed by most recent write.\n\n - /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a - /// trigger, the written value is used immediately as the length of the new transfer - /// sequence, as well as being written to RELOAD. - pub const CH4_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x108); - - /// address: 0x5000010c - /// DMA Channel 4 Control and Status - pub const CH4_CTRL_TRIG = @intToPtr(*volatile Mmio(32, packed struct { - /// DMA Channel Enable.\n - /// When 1, the channel will respond to triggering events, which will cause it to - /// become BUSY and start transferring data. When 0, the channel will ignore - /// triggers, stop issuing transfers, and pause the current transfer sequence (i.e. - /// BUSY will remain high if already high) - EN: u1, - /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in - /// each scheduling round, all high priority channels are considered first, and then - /// only a single low priority channel, before returning to the high priority - /// channels.\n\n - /// This only affects the order in which the DMA schedules channels. The DMA's bus - /// priority is not changed. If the DMA is not saturated then a low priority channel - /// will see no loss of throughput. - HIGH_PRIORITY: u1, - /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR - /// advance by this amount (1/2/4 bytes) with each transfer. - DATA_SIZE: u2, - /// If 1, the read address increments with each transfer. If 0, each read is - /// directed to the same, initial address.\n\n - /// Generally this should be disabled for peripheral-to-memory transfers. - INCR_READ: u1, - /// If 1, the write address increments with each transfer. If 0, each write is - /// directed to the same, initial address.\n\n - /// Generally this should be disabled for memory-to-peripheral transfers. - INCR_WRITE: u1, - /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower - /// n bits of the address will change. This wraps the address on a (1 << n) byte - /// boundary, facilitating access to naturally-aligned ring buffers.\n\n - /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read - /// or write addresses, based on value of RING_SEL. - RING_SIZE: u4, - /// Select whether RING_SIZE applies to read or write addresses.\n - /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write - /// addresses are wrapped. - RING_SEL: u1, - /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. - /// Disable by setting CHAIN_TO = _(this channel)_.\n - /// Reset value is equal to channel number (4). - CHAIN_TO: u4, - /// Select a Transfer Request signal.\n - /// The channel uses the transfer request signal to pace its data transfer rate. - /// Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request - /// from the system).\n - /// 0x0 to 0x3a -> select DREQ n as TREQ - TREQ_SEL: u6, - /// In QUIET mode, the channel does not generate IRQs at the end of every transfer - /// block. Instead, an IRQ is raised when NULL is written to a trigger register, - /// indicating the end of a control block chain.\n\n - /// This reduces the number of interrupts to be serviced by the CPU when - /// transferring a DMA chain of many small control blocks. - IRQ_QUIET: u1, - /// Apply byte-swap transformation to DMA data.\n - /// For byte data, this has no effect. For halfword data, the two bytes of each - /// halfword are swapped. For word data, the four bytes of each word are swapped to - /// reverse order. - BSWAP: u1, - /// If 1, this channel's data transfers are visible to the sniff hardware, and each - /// transfer will advance the state of the checksum. This only applies if the sniff - /// hardware is enabled, and has this channel selected.\n\n - /// This allows checksum to be enabled or disabled on a per-control- block basis. - SNIFF_EN: u1, - /// This flag goes high when the channel starts a new transfer sequence, and low - /// when the last transfer of that sequence completes. Clearing EN while BUSY is - /// high pauses the channel, and BUSY will stay high while paused.\n\n - /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. - BUSY: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - /// If 1, the channel received a write bus error. Write one to clear.\n - /// WRITE_ADDR shows the approximate address where the bus error was encountered - /// (will not to be earlier, or more than 5 transfers later) - WRITE_ERROR: u1, - /// If 1, the channel received a read bus error. Write one to clear.\n - /// READ_ADDR shows the approximate address where the bus error was encountered - /// (will not to be earlier, or more than 3 transfers later) - READ_ERROR: u1, - /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it - /// encounters any bus error, and always raises its channel IRQ flag. - AHB_ERROR: u1, - }), base_address + 0x10c); - - /// address: 0x50000110 - /// Alias for channel 4 CTRL register - pub const CH4_AL1_CTRL = @intToPtr(*volatile u32, base_address + 0x110); - - /// address: 0x50000114 - /// Alias for channel 4 READ_ADDR register - pub const CH4_AL1_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x114); - - /// address: 0x50000118 - /// Alias for channel 4 WRITE_ADDR register - pub const CH4_AL1_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x118); - - /// address: 0x5000011c - /// Alias for channel 4 TRANS_COUNT register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH4_AL1_TRANS_COUNT_TRIG = @intToPtr(*volatile u32, base_address + 0x11c); - - /// address: 0x50000120 - /// Alias for channel 4 CTRL register - pub const CH4_AL2_CTRL = @intToPtr(*volatile u32, base_address + 0x120); - - /// address: 0x50000124 - /// Alias for channel 4 TRANS_COUNT register - pub const CH4_AL2_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x124); - - /// address: 0x50000128 - /// Alias for channel 4 READ_ADDR register - pub const CH4_AL2_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x128); - - /// address: 0x5000012c - /// Alias for channel 4 WRITE_ADDR register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH4_AL2_WRITE_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x12c); - - /// address: 0x50000130 - /// Alias for channel 4 CTRL register - pub const CH4_AL3_CTRL = @intToPtr(*volatile u32, base_address + 0x130); - - /// address: 0x50000134 - /// Alias for channel 4 WRITE_ADDR register - pub const CH4_AL3_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x134); - - /// address: 0x50000138 - /// Alias for channel 4 TRANS_COUNT register - pub const CH4_AL3_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x138); - - /// address: 0x5000013c - /// Alias for channel 4 READ_ADDR register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH4_AL3_READ_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x13c); - - /// address: 0x50000140 - /// DMA Channel 5 Read Address pointer\n - /// This register updates automatically each time a read completes. The current - /// value is the next address to be read by this channel. - pub const CH5_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x140); - - /// address: 0x50000144 - /// DMA Channel 5 Write Address pointer\n - /// This register updates automatically each time a write completes. The current - /// value is the next address to be written by this channel. - pub const CH5_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x144); - - /// address: 0x50000148 - /// DMA Channel 5 Transfer Count\n - /// Program the number of bus transfers a channel will perform before halting. Note - /// that, if transfers are larger than one byte in size, this is not equal to the - /// number of bytes transferred (see CTRL_DATA_SIZE).\n\n - /// When the channel is active, reading this register shows the number of transfers - /// remaining, updating automatically each time a write transfer completes.\n\n - /// Writing this register sets the RELOAD value for the transfer counter. Each time - /// this channel is triggered, the RELOAD value is copied into the live transfer - /// counter. The channel can be started multiple times, and will perform the same - /// number of transfers each time, as programmed by most recent write.\n\n - /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a - /// trigger, the written value is used immediately as the length of the new transfer - /// sequence, as well as being written to RELOAD. - pub const CH5_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x148); - - /// address: 0x5000014c - /// DMA Channel 5 Control and Status - pub const CH5_CTRL_TRIG = @intToPtr(*volatile Mmio(32, packed struct { - /// DMA Channel Enable.\n - /// When 1, the channel will respond to triggering events, which will cause it to - /// become BUSY and start transferring data. When 0, the channel will ignore - /// triggers, stop issuing transfers, and pause the current transfer sequence (i.e. - /// BUSY will remain high if already high) - EN: u1, - /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in - /// each scheduling round, all high priority channels are considered first, and then - /// only a single low priority channel, before returning to the high priority - /// channels.\n\n - /// This only affects the order in which the DMA schedules channels. The DMA's bus - /// priority is not changed. If the DMA is not saturated then a low priority channel - /// will see no loss of throughput. - HIGH_PRIORITY: u1, - /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR - /// advance by this amount (1/2/4 bytes) with each transfer. - DATA_SIZE: u2, - /// If 1, the read address increments with each transfer. If 0, each read is - /// directed to the same, initial address.\n\n - /// Generally this should be disabled for peripheral-to-memory transfers. - INCR_READ: u1, - /// If 1, the write address increments with each transfer. If 0, each write is - /// directed to the same, initial address.\n\n - /// Generally this should be disabled for memory-to-peripheral transfers. - INCR_WRITE: u1, - /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower - /// n bits of the address will change. This wraps the address on a (1 << n) byte - /// boundary, facilitating access to naturally-aligned ring buffers.\n\n - /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read - /// or write addresses, based on value of RING_SEL. - RING_SIZE: u4, - /// Select whether RING_SIZE applies to read or write addresses.\n - /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write - /// addresses are wrapped. - RING_SEL: u1, - /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. - /// Disable by setting CHAIN_TO = _(this channel)_.\n - /// Reset value is equal to channel number (5). - CHAIN_TO: u4, - /// Select a Transfer Request signal.\n - /// The channel uses the transfer request signal to pace its data transfer rate. - /// Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request - /// from the system).\n - /// 0x0 to 0x3a -> select DREQ n as TREQ - TREQ_SEL: u6, - /// In QUIET mode, the channel does not generate IRQs at the end of every transfer - /// block. Instead, an IRQ is raised when NULL is written to a trigger register, - /// indicating the end of a control block chain.\n\n - /// This reduces the number of interrupts to be serviced by the CPU when - /// transferring a DMA chain of many small control blocks. - IRQ_QUIET: u1, - /// Apply byte-swap transformation to DMA data.\n - /// For byte data, this has no effect. For halfword data, the two bytes of each - /// halfword are swapped. For word data, the four bytes of each word are swapped to - /// reverse order. - BSWAP: u1, - /// If 1, this channel's data transfers are visible to the sniff hardware, and each - /// transfer will advance the state of the checksum. This only applies if the sniff - /// hardware is enabled, and has this channel selected.\n\n - /// This allows checksum to be enabled or disabled on a per-control- block basis. - SNIFF_EN: u1, - /// This flag goes high when the channel starts a new transfer sequence, and low - /// when the last transfer of that sequence completes. Clearing EN while BUSY is - /// high pauses the channel, and BUSY will stay high while paused.\n\n - /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. - BUSY: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - /// If 1, the channel received a write bus error. Write one to clear.\n - /// WRITE_ADDR shows the approximate address where the bus error was encountered - /// (will not to be earlier, or more than 5 transfers later) - WRITE_ERROR: u1, - /// If 1, the channel received a read bus error. Write one to clear.\n - /// READ_ADDR shows the approximate address where the bus error was encountered - /// (will not to be earlier, or more than 3 transfers later) - READ_ERROR: u1, - /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it - /// encounters any bus error, and always raises its channel IRQ flag. - AHB_ERROR: u1, - }), base_address + 0x14c); - - /// address: 0x50000150 - /// Alias for channel 5 CTRL register - pub const CH5_AL1_CTRL = @intToPtr(*volatile u32, base_address + 0x150); - - /// address: 0x50000154 - /// Alias for channel 5 READ_ADDR register - pub const CH5_AL1_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x154); - - /// address: 0x50000158 - /// Alias for channel 5 WRITE_ADDR register - pub const CH5_AL1_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x158); - - /// address: 0x5000015c - /// Alias for channel 5 TRANS_COUNT register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH5_AL1_TRANS_COUNT_TRIG = @intToPtr(*volatile u32, base_address + 0x15c); - - /// address: 0x50000160 - /// Alias for channel 5 CTRL register - pub const CH5_AL2_CTRL = @intToPtr(*volatile u32, base_address + 0x160); - - /// address: 0x50000164 - /// Alias for channel 5 TRANS_COUNT register - pub const CH5_AL2_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x164); - - /// address: 0x50000168 - /// Alias for channel 5 READ_ADDR register - pub const CH5_AL2_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x168); - - /// address: 0x5000016c - /// Alias for channel 5 WRITE_ADDR register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH5_AL2_WRITE_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x16c); - - /// address: 0x50000170 - /// Alias for channel 5 CTRL register - pub const CH5_AL3_CTRL = @intToPtr(*volatile u32, base_address + 0x170); - - /// address: 0x50000174 - /// Alias for channel 5 WRITE_ADDR register - pub const CH5_AL3_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x174); - - /// address: 0x50000178 - /// Alias for channel 5 TRANS_COUNT register - pub const CH5_AL3_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x178); - - /// address: 0x5000017c - /// Alias for channel 5 READ_ADDR register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH5_AL3_READ_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x17c); - - /// address: 0x50000180 - /// DMA Channel 6 Read Address pointer\n - /// This register updates automatically each time a read completes. The current - /// value is the next address to be read by this channel. - pub const CH6_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x180); - - /// address: 0x50000184 - /// DMA Channel 6 Write Address pointer\n - /// This register updates automatically each time a write completes. The current - /// value is the next address to be written by this channel. - pub const CH6_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x184); - - /// address: 0x50000188 - /// DMA Channel 6 Transfer Count\n - /// Program the number of bus transfers a channel will perform before halting. Note - /// that, if transfers are larger than one byte in size, this is not equal to the - /// number of bytes transferred (see CTRL_DATA_SIZE).\n\n - /// When the channel is active, reading this register shows the number of transfers - /// remaining, updating automatically each time a write transfer completes.\n\n - /// Writing this register sets the RELOAD value for the transfer counter. Each time - /// this channel is triggered, the RELOAD value is copied into the live transfer - /// counter. The channel can be started multiple times, and will perform the same - /// number of transfers each time, as programmed by most recent write.\n\n - /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a - /// trigger, the written value is used immediately as the length of the new transfer - /// sequence, as well as being written to RELOAD. - pub const CH6_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x188); - - /// address: 0x5000018c - /// DMA Channel 6 Control and Status - pub const CH6_CTRL_TRIG = @intToPtr(*volatile Mmio(32, packed struct { - /// DMA Channel Enable.\n - /// When 1, the channel will respond to triggering events, which will cause it to - /// become BUSY and start transferring data. When 0, the channel will ignore - /// triggers, stop issuing transfers, and pause the current transfer sequence (i.e. - /// BUSY will remain high if already high) - EN: u1, - /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in - /// each scheduling round, all high priority channels are considered first, and then - /// only a single low priority channel, before returning to the high priority - /// channels.\n\n - /// This only affects the order in which the DMA schedules channels. The DMA's bus - /// priority is not changed. If the DMA is not saturated then a low priority channel - /// will see no loss of throughput. - HIGH_PRIORITY: u1, - /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR - /// advance by this amount (1/2/4 bytes) with each transfer. - DATA_SIZE: u2, - /// If 1, the read address increments with each transfer. If 0, each read is - /// directed to the same, initial address.\n\n - /// Generally this should be disabled for peripheral-to-memory transfers. - INCR_READ: u1, - /// If 1, the write address increments with each transfer. If 0, each write is - /// directed to the same, initial address.\n\n - /// Generally this should be disabled for memory-to-peripheral transfers. - INCR_WRITE: u1, - /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower - /// n bits of the address will change. This wraps the address on a (1 << n) byte - /// boundary, facilitating access to naturally-aligned ring buffers.\n\n - /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read - /// or write addresses, based on value of RING_SEL. - RING_SIZE: u4, - /// Select whether RING_SIZE applies to read or write addresses.\n - /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write - /// addresses are wrapped. - RING_SEL: u1, - /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. - /// Disable by setting CHAIN_TO = _(this channel)_.\n - /// Reset value is equal to channel number (6). - CHAIN_TO: u4, - /// Select a Transfer Request signal.\n - /// The channel uses the transfer request signal to pace its data transfer rate. - /// Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request - /// from the system).\n - /// 0x0 to 0x3a -> select DREQ n as TREQ - TREQ_SEL: u6, - /// In QUIET mode, the channel does not generate IRQs at the end of every transfer - /// block. Instead, an IRQ is raised when NULL is written to a trigger register, - /// indicating the end of a control block chain.\n\n - /// This reduces the number of interrupts to be serviced by the CPU when - /// transferring a DMA chain of many small control blocks. - IRQ_QUIET: u1, - /// Apply byte-swap transformation to DMA data.\n - /// For byte data, this has no effect. For halfword data, the two bytes of each - /// halfword are swapped. For word data, the four bytes of each word are swapped to - /// reverse order. - BSWAP: u1, - /// If 1, this channel's data transfers are visible to the sniff hardware, and each - /// transfer will advance the state of the checksum. This only applies if the sniff - /// hardware is enabled, and has this channel selected.\n\n - /// This allows checksum to be enabled or disabled on a per-control- block basis. - SNIFF_EN: u1, - /// This flag goes high when the channel starts a new transfer sequence, and low - /// when the last transfer of that sequence completes. Clearing EN while BUSY is - /// high pauses the channel, and BUSY will stay high while paused.\n\n - /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. - BUSY: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - /// If 1, the channel received a write bus error. Write one to clear.\n - /// WRITE_ADDR shows the approximate address where the bus error was encountered - /// (will not to be earlier, or more than 5 transfers later) - WRITE_ERROR: u1, - /// If 1, the channel received a read bus error. Write one to clear.\n - /// READ_ADDR shows the approximate address where the bus error was encountered - /// (will not to be earlier, or more than 3 transfers later) - READ_ERROR: u1, - /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it - /// encounters any bus error, and always raises its channel IRQ flag. - AHB_ERROR: u1, - }), base_address + 0x18c); - - /// address: 0x50000190 - /// Alias for channel 6 CTRL register - pub const CH6_AL1_CTRL = @intToPtr(*volatile u32, base_address + 0x190); - - /// address: 0x50000194 - /// Alias for channel 6 READ_ADDR register - pub const CH6_AL1_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x194); - - /// address: 0x50000198 - /// Alias for channel 6 WRITE_ADDR register - pub const CH6_AL1_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x198); - - /// address: 0x5000019c - /// Alias for channel 6 TRANS_COUNT register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH6_AL1_TRANS_COUNT_TRIG = @intToPtr(*volatile u32, base_address + 0x19c); - - /// address: 0x500001a0 - /// Alias for channel 6 CTRL register - pub const CH6_AL2_CTRL = @intToPtr(*volatile u32, base_address + 0x1a0); - - /// address: 0x500001a4 - /// Alias for channel 6 TRANS_COUNT register - pub const CH6_AL2_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x1a4); - - /// address: 0x500001a8 - /// Alias for channel 6 READ_ADDR register - pub const CH6_AL2_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x1a8); - - /// address: 0x500001ac - /// Alias for channel 6 WRITE_ADDR register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH6_AL2_WRITE_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x1ac); - - /// address: 0x500001b0 - /// Alias for channel 6 CTRL register - pub const CH6_AL3_CTRL = @intToPtr(*volatile u32, base_address + 0x1b0); - - /// address: 0x500001b4 - /// Alias for channel 6 WRITE_ADDR register - pub const CH6_AL3_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x1b4); - - /// address: 0x500001b8 - /// Alias for channel 6 TRANS_COUNT register - pub const CH6_AL3_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x1b8); - - /// address: 0x500001bc - /// Alias for channel 6 READ_ADDR register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH6_AL3_READ_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x1bc); - - /// address: 0x500001c0 - /// DMA Channel 7 Read Address pointer\n - /// This register updates automatically each time a read completes. The current - /// value is the next address to be read by this channel. - pub const CH7_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x1c0); - - /// address: 0x500001c4 - /// DMA Channel 7 Write Address pointer\n - /// This register updates automatically each time a write completes. The current - /// value is the next address to be written by this channel. - pub const CH7_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x1c4); - - /// address: 0x500001c8 - /// DMA Channel 7 Transfer Count\n - /// Program the number of bus transfers a channel will perform before halting. Note - /// that, if transfers are larger than one byte in size, this is not equal to the - /// number of bytes transferred (see CTRL_DATA_SIZE).\n\n - /// When the channel is active, reading this register shows the number of transfers - /// remaining, updating automatically each time a write transfer completes.\n\n - /// Writing this register sets the RELOAD value for the transfer counter. Each time - /// this channel is triggered, the RELOAD value is copied into the live transfer - /// counter. The channel can be started multiple times, and will perform the same - /// number of transfers each time, as programmed by most recent write.\n\n - /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a - /// trigger, the written value is used immediately as the length of the new transfer - /// sequence, as well as being written to RELOAD. - pub const CH7_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x1c8); - - /// address: 0x500001cc - /// DMA Channel 7 Control and Status - pub const CH7_CTRL_TRIG = @intToPtr(*volatile Mmio(32, packed struct { - /// DMA Channel Enable.\n - /// When 1, the channel will respond to triggering events, which will cause it to - /// become BUSY and start transferring data. When 0, the channel will ignore - /// triggers, stop issuing transfers, and pause the current transfer sequence (i.e. - /// BUSY will remain high if already high) - EN: u1, - /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in - /// each scheduling round, all high priority channels are considered first, and then - /// only a single low priority channel, before returning to the high priority - /// channels.\n\n - /// This only affects the order in which the DMA schedules channels. The DMA's bus - /// priority is not changed. If the DMA is not saturated then a low priority channel - /// will see no loss of throughput. - HIGH_PRIORITY: u1, - /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR - /// advance by this amount (1/2/4 bytes) with each transfer. - DATA_SIZE: u2, - /// If 1, the read address increments with each transfer. If 0, each read is - /// directed to the same, initial address.\n\n - /// Generally this should be disabled for peripheral-to-memory transfers. - INCR_READ: u1, - /// If 1, the write address increments with each transfer. If 0, each write is - /// directed to the same, initial address.\n\n - /// Generally this should be disabled for memory-to-peripheral transfers. - INCR_WRITE: u1, - /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower - /// n bits of the address will change. This wraps the address on a (1 << n) byte - /// boundary, facilitating access to naturally-aligned ring buffers.\n\n - /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read - /// or write addresses, based on value of RING_SEL. - RING_SIZE: u4, - /// Select whether RING_SIZE applies to read or write addresses.\n - /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write - /// addresses are wrapped. - RING_SEL: u1, - /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. - /// Disable by setting CHAIN_TO = _(this channel)_.\n - /// Reset value is equal to channel number (7). - CHAIN_TO: u4, - /// Select a Transfer Request signal.\n - /// The channel uses the transfer request signal to pace its data transfer rate. - /// Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request - /// from the system).\n - /// 0x0 to 0x3a -> select DREQ n as TREQ - TREQ_SEL: u6, - /// In QUIET mode, the channel does not generate IRQs at the end of every transfer - /// block. Instead, an IRQ is raised when NULL is written to a trigger register, - /// indicating the end of a control block chain.\n\n - /// This reduces the number of interrupts to be serviced by the CPU when - /// transferring a DMA chain of many small control blocks. - IRQ_QUIET: u1, - /// Apply byte-swap transformation to DMA data.\n - /// For byte data, this has no effect. For halfword data, the two bytes of each - /// halfword are swapped. For word data, the four bytes of each word are swapped to - /// reverse order. - BSWAP: u1, - /// If 1, this channel's data transfers are visible to the sniff hardware, and each - /// transfer will advance the state of the checksum. This only applies if the sniff - /// hardware is enabled, and has this channel selected.\n\n - /// This allows checksum to be enabled or disabled on a per-control- block basis. - SNIFF_EN: u1, - /// This flag goes high when the channel starts a new transfer sequence, and low - /// when the last transfer of that sequence completes. Clearing EN while BUSY is - /// high pauses the channel, and BUSY will stay high while paused.\n\n - /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. - BUSY: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - /// If 1, the channel received a write bus error. Write one to clear.\n - /// WRITE_ADDR shows the approximate address where the bus error was encountered - /// (will not to be earlier, or more than 5 transfers later) - WRITE_ERROR: u1, - /// If 1, the channel received a read bus error. Write one to clear.\n - /// READ_ADDR shows the approximate address where the bus error was encountered - /// (will not to be earlier, or more than 3 transfers later) - READ_ERROR: u1, - /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it - /// encounters any bus error, and always raises its channel IRQ flag. - AHB_ERROR: u1, - }), base_address + 0x1cc); - - /// address: 0x500001d0 - /// Alias for channel 7 CTRL register - pub const CH7_AL1_CTRL = @intToPtr(*volatile u32, base_address + 0x1d0); - - /// address: 0x500001d4 - /// Alias for channel 7 READ_ADDR register - pub const CH7_AL1_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x1d4); - - /// address: 0x500001d8 - /// Alias for channel 7 WRITE_ADDR register - pub const CH7_AL1_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x1d8); - - /// address: 0x500001dc - /// Alias for channel 7 TRANS_COUNT register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH7_AL1_TRANS_COUNT_TRIG = @intToPtr(*volatile u32, base_address + 0x1dc); - - /// address: 0x500001e0 - /// Alias for channel 7 CTRL register - pub const CH7_AL2_CTRL = @intToPtr(*volatile u32, base_address + 0x1e0); - - /// address: 0x500001e4 - /// Alias for channel 7 TRANS_COUNT register - pub const CH7_AL2_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x1e4); - - /// address: 0x500001e8 - /// Alias for channel 7 READ_ADDR register - pub const CH7_AL2_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x1e8); - - /// address: 0x500001ec - /// Alias for channel 7 WRITE_ADDR register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH7_AL2_WRITE_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x1ec); - - /// address: 0x500001f0 - /// Alias for channel 7 CTRL register - pub const CH7_AL3_CTRL = @intToPtr(*volatile u32, base_address + 0x1f0); - - /// address: 0x500001f4 - /// Alias for channel 7 WRITE_ADDR register - pub const CH7_AL3_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x1f4); - - /// address: 0x500001f8 - /// Alias for channel 7 TRANS_COUNT register - pub const CH7_AL3_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x1f8); - - /// address: 0x500001fc - /// Alias for channel 7 READ_ADDR register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH7_AL3_READ_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x1fc); - - /// address: 0x50000200 - /// DMA Channel 8 Read Address pointer\n - /// This register updates automatically each time a read completes. The current - /// value is the next address to be read by this channel. - pub const CH8_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x200); - - /// address: 0x50000204 - /// DMA Channel 8 Write Address pointer\n - /// This register updates automatically each time a write completes. The current - /// value is the next address to be written by this channel. - pub const CH8_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x204); - - /// address: 0x50000208 - /// DMA Channel 8 Transfer Count\n - /// Program the number of bus transfers a channel will perform before halting. Note - /// that, if transfers are larger than one byte in size, this is not equal to the - /// number of bytes transferred (see CTRL_DATA_SIZE).\n\n - /// When the channel is active, reading this register shows the number of transfers - /// remaining, updating automatically each time a write transfer completes.\n\n - /// Writing this register sets the RELOAD value for the transfer counter. Each time - /// this channel is triggered, the RELOAD value is copied into the live transfer - /// counter. The channel can be started multiple times, and will perform the same - /// number of transfers each time, as programmed by most recent write.\n\n - /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a - /// trigger, the written value is used immediately as the length of the new transfer - /// sequence, as well as being written to RELOAD. - pub const CH8_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x208); - - /// address: 0x5000020c - /// DMA Channel 8 Control and Status - pub const CH8_CTRL_TRIG = @intToPtr(*volatile Mmio(32, packed struct { - /// DMA Channel Enable.\n - /// When 1, the channel will respond to triggering events, which will cause it to - /// become BUSY and start transferring data. When 0, the channel will ignore - /// triggers, stop issuing transfers, and pause the current transfer sequence (i.e. - /// BUSY will remain high if already high) - EN: u1, - /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in - /// each scheduling round, all high priority channels are considered first, and then - /// only a single low priority channel, before returning to the high priority - /// channels.\n\n - /// This only affects the order in which the DMA schedules channels. The DMA's bus - /// priority is not changed. If the DMA is not saturated then a low priority channel - /// will see no loss of throughput. - HIGH_PRIORITY: u1, - /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR - /// advance by this amount (1/2/4 bytes) with each transfer. - DATA_SIZE: u2, - /// If 1, the read address increments with each transfer. If 0, each read is - /// directed to the same, initial address.\n\n - /// Generally this should be disabled for peripheral-to-memory transfers. - INCR_READ: u1, - /// If 1, the write address increments with each transfer. If 0, each write is - /// directed to the same, initial address.\n\n - /// Generally this should be disabled for memory-to-peripheral transfers. - INCR_WRITE: u1, - /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower - /// n bits of the address will change. This wraps the address on a (1 << n) byte - /// boundary, facilitating access to naturally-aligned ring buffers.\n\n - /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read - /// or write addresses, based on value of RING_SEL. - RING_SIZE: u4, - /// Select whether RING_SIZE applies to read or write addresses.\n - /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write - /// addresses are wrapped. - RING_SEL: u1, - /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. - /// Disable by setting CHAIN_TO = _(this channel)_.\n - /// Reset value is equal to channel number (8). - CHAIN_TO: u4, - /// Select a Transfer Request signal.\n - /// The channel uses the transfer request signal to pace its data transfer rate. - /// Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request - /// from the system).\n - /// 0x0 to 0x3a -> select DREQ n as TREQ - TREQ_SEL: u6, - /// In QUIET mode, the channel does not generate IRQs at the end of every transfer - /// block. Instead, an IRQ is raised when NULL is written to a trigger register, - /// indicating the end of a control block chain.\n\n - /// This reduces the number of interrupts to be serviced by the CPU when - /// transferring a DMA chain of many small control blocks. - IRQ_QUIET: u1, - /// Apply byte-swap transformation to DMA data.\n - /// For byte data, this has no effect. For halfword data, the two bytes of each - /// halfword are swapped. For word data, the four bytes of each word are swapped to - /// reverse order. - BSWAP: u1, - /// If 1, this channel's data transfers are visible to the sniff hardware, and each - /// transfer will advance the state of the checksum. This only applies if the sniff - /// hardware is enabled, and has this channel selected.\n\n - /// This allows checksum to be enabled or disabled on a per-control- block basis. - SNIFF_EN: u1, - /// This flag goes high when the channel starts a new transfer sequence, and low - /// when the last transfer of that sequence completes. Clearing EN while BUSY is - /// high pauses the channel, and BUSY will stay high while paused.\n\n - /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. - BUSY: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - /// If 1, the channel received a write bus error. Write one to clear.\n - /// WRITE_ADDR shows the approximate address where the bus error was encountered - /// (will not to be earlier, or more than 5 transfers later) - WRITE_ERROR: u1, - /// If 1, the channel received a read bus error. Write one to clear.\n - /// READ_ADDR shows the approximate address where the bus error was encountered - /// (will not to be earlier, or more than 3 transfers later) - READ_ERROR: u1, - /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it - /// encounters any bus error, and always raises its channel IRQ flag. - AHB_ERROR: u1, - }), base_address + 0x20c); - - /// address: 0x50000210 - /// Alias for channel 8 CTRL register - pub const CH8_AL1_CTRL = @intToPtr(*volatile u32, base_address + 0x210); - - /// address: 0x50000214 - /// Alias for channel 8 READ_ADDR register - pub const CH8_AL1_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x214); - - /// address: 0x50000218 - /// Alias for channel 8 WRITE_ADDR register - pub const CH8_AL1_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x218); - - /// address: 0x5000021c - /// Alias for channel 8 TRANS_COUNT register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH8_AL1_TRANS_COUNT_TRIG = @intToPtr(*volatile u32, base_address + 0x21c); - - /// address: 0x50000220 - /// Alias for channel 8 CTRL register - pub const CH8_AL2_CTRL = @intToPtr(*volatile u32, base_address + 0x220); - - /// address: 0x50000224 - /// Alias for channel 8 TRANS_COUNT register - pub const CH8_AL2_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x224); - - /// address: 0x50000228 - /// Alias for channel 8 READ_ADDR register - pub const CH8_AL2_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x228); - - /// address: 0x5000022c - /// Alias for channel 8 WRITE_ADDR register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH8_AL2_WRITE_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x22c); - - /// address: 0x50000230 - /// Alias for channel 8 CTRL register - pub const CH8_AL3_CTRL = @intToPtr(*volatile u32, base_address + 0x230); - - /// address: 0x50000234 - /// Alias for channel 8 WRITE_ADDR register - pub const CH8_AL3_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x234); - - /// address: 0x50000238 - /// Alias for channel 8 TRANS_COUNT register - pub const CH8_AL3_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x238); - - /// address: 0x5000023c - /// Alias for channel 8 READ_ADDR register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH8_AL3_READ_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x23c); - - /// address: 0x50000240 - /// DMA Channel 9 Read Address pointer\n - /// This register updates automatically each time a read completes. The current - /// value is the next address to be read by this channel. - pub const CH9_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x240); - - /// address: 0x50000244 - /// DMA Channel 9 Write Address pointer\n - /// This register updates automatically each time a write completes. The current - /// value is the next address to be written by this channel. - pub const CH9_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x244); - - /// address: 0x50000248 - /// DMA Channel 9 Transfer Count\n - /// Program the number of bus transfers a channel will perform before halting. Note - /// that, if transfers are larger than one byte in size, this is not equal to the - /// number of bytes transferred (see CTRL_DATA_SIZE).\n\n - /// When the channel is active, reading this register shows the number of transfers - /// remaining, updating automatically each time a write transfer completes.\n\n - /// Writing this register sets the RELOAD value for the transfer counter. Each time - /// this channel is triggered, the RELOAD value is copied into the live transfer - /// counter. The channel can be started multiple times, and will perform the same - /// number of transfers each time, as programmed by most recent write.\n\n - /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a - /// trigger, the written value is used immediately as the length of the new transfer - /// sequence, as well as being written to RELOAD. - pub const CH9_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x248); - - /// address: 0x5000024c - /// DMA Channel 9 Control and Status - pub const CH9_CTRL_TRIG = @intToPtr(*volatile Mmio(32, packed struct { - /// DMA Channel Enable.\n - /// When 1, the channel will respond to triggering events, which will cause it to - /// become BUSY and start transferring data. When 0, the channel will ignore - /// triggers, stop issuing transfers, and pause the current transfer sequence (i.e. - /// BUSY will remain high if already high) - EN: u1, - /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in - /// each scheduling round, all high priority channels are considered first, and then - /// only a single low priority channel, before returning to the high priority - /// channels.\n\n - /// This only affects the order in which the DMA schedules channels. The DMA's bus - /// priority is not changed. If the DMA is not saturated then a low priority channel - /// will see no loss of throughput. - HIGH_PRIORITY: u1, - /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR - /// advance by this amount (1/2/4 bytes) with each transfer. - DATA_SIZE: u2, - /// If 1, the read address increments with each transfer. If 0, each read is - /// directed to the same, initial address.\n\n - /// Generally this should be disabled for peripheral-to-memory transfers. - INCR_READ: u1, - /// If 1, the write address increments with each transfer. If 0, each write is - /// directed to the same, initial address.\n\n - /// Generally this should be disabled for memory-to-peripheral transfers. - INCR_WRITE: u1, - /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower - /// n bits of the address will change. This wraps the address on a (1 << n) byte - /// boundary, facilitating access to naturally-aligned ring buffers.\n\n - /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read - /// or write addresses, based on value of RING_SEL. - RING_SIZE: u4, - /// Select whether RING_SIZE applies to read or write addresses.\n - /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write - /// addresses are wrapped. - RING_SEL: u1, - /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. - /// Disable by setting CHAIN_TO = _(this channel)_.\n - /// Reset value is equal to channel number (9). - CHAIN_TO: u4, - /// Select a Transfer Request signal.\n - /// The channel uses the transfer request signal to pace its data transfer rate. - /// Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request - /// from the system).\n - /// 0x0 to 0x3a -> select DREQ n as TREQ - TREQ_SEL: u6, - /// In QUIET mode, the channel does not generate IRQs at the end of every transfer - /// block. Instead, an IRQ is raised when NULL is written to a trigger register, - /// indicating the end of a control block chain.\n\n - /// This reduces the number of interrupts to be serviced by the CPU when - /// transferring a DMA chain of many small control blocks. - IRQ_QUIET: u1, - /// Apply byte-swap transformation to DMA data.\n - /// For byte data, this has no effect. For halfword data, the two bytes of each - /// halfword are swapped. For word data, the four bytes of each word are swapped to - /// reverse order. - BSWAP: u1, - /// If 1, this channel's data transfers are visible to the sniff hardware, and each - /// transfer will advance the state of the checksum. This only applies if the sniff - /// hardware is enabled, and has this channel selected.\n\n - /// This allows checksum to be enabled or disabled on a per-control- block basis. - SNIFF_EN: u1, - /// This flag goes high when the channel starts a new transfer sequence, and low - /// when the last transfer of that sequence completes. Clearing EN while BUSY is - /// high pauses the channel, and BUSY will stay high while paused.\n\n - /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. - BUSY: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - /// If 1, the channel received a write bus error. Write one to clear.\n - /// WRITE_ADDR shows the approximate address where the bus error was encountered - /// (will not to be earlier, or more than 5 transfers later) - WRITE_ERROR: u1, - /// If 1, the channel received a read bus error. Write one to clear.\n - /// READ_ADDR shows the approximate address where the bus error was encountered - /// (will not to be earlier, or more than 3 transfers later) - READ_ERROR: u1, - /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it - /// encounters any bus error, and always raises its channel IRQ flag. - AHB_ERROR: u1, - }), base_address + 0x24c); - - /// address: 0x50000250 - /// Alias for channel 9 CTRL register - pub const CH9_AL1_CTRL = @intToPtr(*volatile u32, base_address + 0x250); - - /// address: 0x50000254 - /// Alias for channel 9 READ_ADDR register - pub const CH9_AL1_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x254); - - /// address: 0x50000258 - /// Alias for channel 9 WRITE_ADDR register - pub const CH9_AL1_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x258); - - /// address: 0x5000025c - /// Alias for channel 9 TRANS_COUNT register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH9_AL1_TRANS_COUNT_TRIG = @intToPtr(*volatile u32, base_address + 0x25c); - - /// address: 0x50000260 - /// Alias for channel 9 CTRL register - pub const CH9_AL2_CTRL = @intToPtr(*volatile u32, base_address + 0x260); - - /// address: 0x50000264 - /// Alias for channel 9 TRANS_COUNT register - pub const CH9_AL2_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x264); - - /// address: 0x50000268 - /// Alias for channel 9 READ_ADDR register - pub const CH9_AL2_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x268); - - /// address: 0x5000026c - /// Alias for channel 9 WRITE_ADDR register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH9_AL2_WRITE_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x26c); - - /// address: 0x50000270 - /// Alias for channel 9 CTRL register - pub const CH9_AL3_CTRL = @intToPtr(*volatile u32, base_address + 0x270); - - /// address: 0x50000274 - /// Alias for channel 9 WRITE_ADDR register - pub const CH9_AL3_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x274); - - /// address: 0x50000278 - /// Alias for channel 9 TRANS_COUNT register - pub const CH9_AL3_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x278); - - /// address: 0x5000027c - /// Alias for channel 9 READ_ADDR register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH9_AL3_READ_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x27c); - - /// address: 0x50000280 - /// DMA Channel 10 Read Address pointer\n - /// This register updates automatically each time a read completes. The current - /// value is the next address to be read by this channel. - pub const CH10_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x280); - - /// address: 0x50000284 - /// DMA Channel 10 Write Address pointer\n - /// This register updates automatically each time a write completes. The current - /// value is the next address to be written by this channel. - pub const CH10_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x284); - - /// address: 0x50000288 - /// DMA Channel 10 Transfer Count\n - /// Program the number of bus transfers a channel will perform before halting. Note - /// that, if transfers are larger than one byte in size, this is not equal to the - /// number of bytes transferred (see CTRL_DATA_SIZE).\n\n - /// When the channel is active, reading this register shows the number of transfers - /// remaining, updating automatically each time a write transfer completes.\n\n - /// Writing this register sets the RELOAD value for the transfer counter. Each time - /// this channel is triggered, the RELOAD value is copied into the live transfer - /// counter. The channel can be started multiple times, and will perform the same - /// number of transfers each time, as programmed by most recent write.\n\n - /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a - /// trigger, the written value is used immediately as the length of the new transfer - /// sequence, as well as being written to RELOAD. - pub const CH10_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x288); - - /// address: 0x5000028c - /// DMA Channel 10 Control and Status - pub const CH10_CTRL_TRIG = @intToPtr(*volatile Mmio(32, packed struct { - /// DMA Channel Enable.\n - /// When 1, the channel will respond to triggering events, which will cause it to - /// become BUSY and start transferring data. When 0, the channel will ignore - /// triggers, stop issuing transfers, and pause the current transfer sequence (i.e. - /// BUSY will remain high if already high) - EN: u1, - /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in - /// each scheduling round, all high priority channels are considered first, and then - /// only a single low priority channel, before returning to the high priority - /// channels.\n\n - /// This only affects the order in which the DMA schedules channels. The DMA's bus - /// priority is not changed. If the DMA is not saturated then a low priority channel - /// will see no loss of throughput. - HIGH_PRIORITY: u1, - /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR - /// advance by this amount (1/2/4 bytes) with each transfer. - DATA_SIZE: u2, - /// If 1, the read address increments with each transfer. If 0, each read is - /// directed to the same, initial address.\n\n - /// Generally this should be disabled for peripheral-to-memory transfers. - INCR_READ: u1, - /// If 1, the write address increments with each transfer. If 0, each write is - /// directed to the same, initial address.\n\n - /// Generally this should be disabled for memory-to-peripheral transfers. - INCR_WRITE: u1, - /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower - /// n bits of the address will change. This wraps the address on a (1 << n) byte - /// boundary, facilitating access to naturally-aligned ring buffers.\n\n - /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read - /// or write addresses, based on value of RING_SEL. - RING_SIZE: u4, - /// Select whether RING_SIZE applies to read or write addresses.\n - /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write - /// addresses are wrapped. - RING_SEL: u1, - /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. - /// Disable by setting CHAIN_TO = _(this channel)_.\n - /// Reset value is equal to channel number (10). - CHAIN_TO: u4, - /// Select a Transfer Request signal.\n - /// The channel uses the transfer request signal to pace its data transfer rate. - /// Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request - /// from the system).\n - /// 0x0 to 0x3a -> select DREQ n as TREQ - TREQ_SEL: u6, - /// In QUIET mode, the channel does not generate IRQs at the end of every transfer - /// block. Instead, an IRQ is raised when NULL is written to a trigger register, - /// indicating the end of a control block chain.\n\n - /// This reduces the number of interrupts to be serviced by the CPU when - /// transferring a DMA chain of many small control blocks. - IRQ_QUIET: u1, - /// Apply byte-swap transformation to DMA data.\n - /// For byte data, this has no effect. For halfword data, the two bytes of each - /// halfword are swapped. For word data, the four bytes of each word are swapped to - /// reverse order. - BSWAP: u1, - /// If 1, this channel's data transfers are visible to the sniff hardware, and each - /// transfer will advance the state of the checksum. This only applies if the sniff - /// hardware is enabled, and has this channel selected.\n\n - /// This allows checksum to be enabled or disabled on a per-control- block basis. - SNIFF_EN: u1, - /// This flag goes high when the channel starts a new transfer sequence, and low - /// when the last transfer of that sequence completes. Clearing EN while BUSY is - /// high pauses the channel, and BUSY will stay high while paused.\n\n - /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. - BUSY: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - /// If 1, the channel received a write bus error. Write one to clear.\n - /// WRITE_ADDR shows the approximate address where the bus error was encountered - /// (will not to be earlier, or more than 5 transfers later) - WRITE_ERROR: u1, - /// If 1, the channel received a read bus error. Write one to clear.\n - /// READ_ADDR shows the approximate address where the bus error was encountered - /// (will not to be earlier, or more than 3 transfers later) - READ_ERROR: u1, - /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it - /// encounters any bus error, and always raises its channel IRQ flag. - AHB_ERROR: u1, - }), base_address + 0x28c); - - /// address: 0x50000290 - /// Alias for channel 10 CTRL register - pub const CH10_AL1_CTRL = @intToPtr(*volatile u32, base_address + 0x290); - - /// address: 0x50000294 - /// Alias for channel 10 READ_ADDR register - pub const CH10_AL1_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x294); - - /// address: 0x50000298 - /// Alias for channel 10 WRITE_ADDR register - pub const CH10_AL1_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x298); - - /// address: 0x5000029c - /// Alias for channel 10 TRANS_COUNT register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH10_AL1_TRANS_COUNT_TRIG = @intToPtr(*volatile u32, base_address + 0x29c); - - /// address: 0x500002a0 - /// Alias for channel 10 CTRL register - pub const CH10_AL2_CTRL = @intToPtr(*volatile u32, base_address + 0x2a0); - - /// address: 0x500002a4 - /// Alias for channel 10 TRANS_COUNT register - pub const CH10_AL2_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x2a4); - - /// address: 0x500002a8 - /// Alias for channel 10 READ_ADDR register - pub const CH10_AL2_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x2a8); - - /// address: 0x500002ac - /// Alias for channel 10 WRITE_ADDR register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH10_AL2_WRITE_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x2ac); - - /// address: 0x500002b0 - /// Alias for channel 10 CTRL register - pub const CH10_AL3_CTRL = @intToPtr(*volatile u32, base_address + 0x2b0); - - /// address: 0x500002b4 - /// Alias for channel 10 WRITE_ADDR register - pub const CH10_AL3_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x2b4); - - /// address: 0x500002b8 - /// Alias for channel 10 TRANS_COUNT register - pub const CH10_AL3_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x2b8); - - /// address: 0x500002bc - /// Alias for channel 10 READ_ADDR register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH10_AL3_READ_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x2bc); - - /// address: 0x500002c0 - /// DMA Channel 11 Read Address pointer\n - /// This register updates automatically each time a read completes. The current - /// value is the next address to be read by this channel. - pub const CH11_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x2c0); - - /// address: 0x500002c4 - /// DMA Channel 11 Write Address pointer\n - /// This register updates automatically each time a write completes. The current - /// value is the next address to be written by this channel. - pub const CH11_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x2c4); - - /// address: 0x500002c8 - /// DMA Channel 11 Transfer Count\n - /// Program the number of bus transfers a channel will perform before halting. Note - /// that, if transfers are larger than one byte in size, this is not equal to the - /// number of bytes transferred (see CTRL_DATA_SIZE).\n\n - /// When the channel is active, reading this register shows the number of transfers - /// remaining, updating automatically each time a write transfer completes.\n\n - /// Writing this register sets the RELOAD value for the transfer counter. Each time - /// this channel is triggered, the RELOAD value is copied into the live transfer - /// counter. The channel can be started multiple times, and will perform the same - /// number of transfers each time, as programmed by most recent write.\n\n - /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a - /// trigger, the written value is used immediately as the length of the new transfer - /// sequence, as well as being written to RELOAD. - pub const CH11_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x2c8); - - /// address: 0x500002cc - /// DMA Channel 11 Control and Status - pub const CH11_CTRL_TRIG = @intToPtr(*volatile Mmio(32, packed struct { - /// DMA Channel Enable.\n - /// When 1, the channel will respond to triggering events, which will cause it to - /// become BUSY and start transferring data. When 0, the channel will ignore - /// triggers, stop issuing transfers, and pause the current transfer sequence (i.e. - /// BUSY will remain high if already high) - EN: u1, - /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in - /// each scheduling round, all high priority channels are considered first, and then - /// only a single low priority channel, before returning to the high priority - /// channels.\n\n - /// This only affects the order in which the DMA schedules channels. The DMA's bus - /// priority is not changed. If the DMA is not saturated then a low priority channel - /// will see no loss of throughput. - HIGH_PRIORITY: u1, - /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR - /// advance by this amount (1/2/4 bytes) with each transfer. - DATA_SIZE: u2, - /// If 1, the read address increments with each transfer. If 0, each read is - /// directed to the same, initial address.\n\n - /// Generally this should be disabled for peripheral-to-memory transfers. - INCR_READ: u1, - /// If 1, the write address increments with each transfer. If 0, each write is - /// directed to the same, initial address.\n\n - /// Generally this should be disabled for memory-to-peripheral transfers. - INCR_WRITE: u1, - /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower - /// n bits of the address will change. This wraps the address on a (1 << n) byte - /// boundary, facilitating access to naturally-aligned ring buffers.\n\n - /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read - /// or write addresses, based on value of RING_SEL. - RING_SIZE: u4, - /// Select whether RING_SIZE applies to read or write addresses.\n - /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write - /// addresses are wrapped. - RING_SEL: u1, - /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. - /// Disable by setting CHAIN_TO = _(this channel)_.\n - /// Reset value is equal to channel number (11). - CHAIN_TO: u4, - /// Select a Transfer Request signal.\n - /// The channel uses the transfer request signal to pace its data transfer rate. - /// Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request - /// from the system).\n - /// 0x0 to 0x3a -> select DREQ n as TREQ - TREQ_SEL: u6, - /// In QUIET mode, the channel does not generate IRQs at the end of every transfer - /// block. Instead, an IRQ is raised when NULL is written to a trigger register, - /// indicating the end of a control block chain.\n\n - /// This reduces the number of interrupts to be serviced by the CPU when - /// transferring a DMA chain of many small control blocks. - IRQ_QUIET: u1, - /// Apply byte-swap transformation to DMA data.\n - /// For byte data, this has no effect. For halfword data, the two bytes of each - /// halfword are swapped. For word data, the four bytes of each word are swapped to - /// reverse order. - BSWAP: u1, - /// If 1, this channel's data transfers are visible to the sniff hardware, and each - /// transfer will advance the state of the checksum. This only applies if the sniff - /// hardware is enabled, and has this channel selected.\n\n - /// This allows checksum to be enabled or disabled on a per-control- block basis. - SNIFF_EN: u1, - /// This flag goes high when the channel starts a new transfer sequence, and low - /// when the last transfer of that sequence completes. Clearing EN while BUSY is - /// high pauses the channel, and BUSY will stay high while paused.\n\n - /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. - BUSY: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - /// If 1, the channel received a write bus error. Write one to clear.\n - /// WRITE_ADDR shows the approximate address where the bus error was encountered - /// (will not to be earlier, or more than 5 transfers later) - WRITE_ERROR: u1, - /// If 1, the channel received a read bus error. Write one to clear.\n - /// READ_ADDR shows the approximate address where the bus error was encountered - /// (will not to be earlier, or more than 3 transfers later) - READ_ERROR: u1, - /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it - /// encounters any bus error, and always raises its channel IRQ flag. - AHB_ERROR: u1, - }), base_address + 0x2cc); - - /// address: 0x500002d0 - /// Alias for channel 11 CTRL register - pub const CH11_AL1_CTRL = @intToPtr(*volatile u32, base_address + 0x2d0); - - /// address: 0x500002d4 - /// Alias for channel 11 READ_ADDR register - pub const CH11_AL1_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x2d4); - - /// address: 0x500002d8 - /// Alias for channel 11 WRITE_ADDR register - pub const CH11_AL1_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x2d8); - - /// address: 0x500002dc - /// Alias for channel 11 TRANS_COUNT register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH11_AL1_TRANS_COUNT_TRIG = @intToPtr(*volatile u32, base_address + 0x2dc); - - /// address: 0x500002e0 - /// Alias for channel 11 CTRL register - pub const CH11_AL2_CTRL = @intToPtr(*volatile u32, base_address + 0x2e0); - - /// address: 0x500002e4 - /// Alias for channel 11 TRANS_COUNT register - pub const CH11_AL2_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x2e4); - - /// address: 0x500002e8 - /// Alias for channel 11 READ_ADDR register - pub const CH11_AL2_READ_ADDR = @intToPtr(*volatile u32, base_address + 0x2e8); - - /// address: 0x500002ec - /// Alias for channel 11 WRITE_ADDR register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH11_AL2_WRITE_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x2ec); - - /// address: 0x500002f0 - /// Alias for channel 11 CTRL register - pub const CH11_AL3_CTRL = @intToPtr(*volatile u32, base_address + 0x2f0); - - /// address: 0x500002f4 - /// Alias for channel 11 WRITE_ADDR register - pub const CH11_AL3_WRITE_ADDR = @intToPtr(*volatile u32, base_address + 0x2f4); - - /// address: 0x500002f8 - /// Alias for channel 11 TRANS_COUNT register - pub const CH11_AL3_TRANS_COUNT = @intToPtr(*volatile u32, base_address + 0x2f8); - - /// address: 0x500002fc - /// Alias for channel 11 READ_ADDR register\n - /// This is a trigger register (0xc). Writing a nonzero value will\n - /// reload the channel counter and start the channel. - pub const CH11_AL3_READ_ADDR_TRIG = @intToPtr(*volatile u32, base_address + 0x2fc); - - /// address: 0x50000400 - /// Interrupt Status (raw) - pub const INTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x400); - - /// address: 0x50000404 - /// Interrupt Enables for IRQ 0 - pub const INTE0 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x404); - - /// address: 0x50000408 - /// Force Interrupts - pub const INTF0 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x408); - - /// address: 0x5000040c - /// Interrupt Status for IRQ 0 - pub const INTS0 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x40c); - - /// address: 0x50000414 - /// Interrupt Enables for IRQ 1 - pub const INTE1 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x414); - - /// address: 0x50000418 - /// Force Interrupts for IRQ 1 - pub const INTF1 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x418); - - /// address: 0x5000041c - /// Interrupt Status (masked) for IRQ 1 - pub const INTS1 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x41c); - - /// address: 0x50000420 - /// Pacing (X/Y) Fractional Timer\n - /// The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). - /// This equation is evaluated every sys_clk cycles and therefore can only generate - /// TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. - pub const TIMER0 = @intToPtr(*volatile Mmio(32, packed struct { - /// Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. - Y: u16, - /// Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. - X: u16, - }), base_address + 0x420); - - /// address: 0x50000424 - /// Pacing (X/Y) Fractional Timer\n - /// The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). - /// This equation is evaluated every sys_clk cycles and therefore can only generate - /// TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. - pub const TIMER1 = @intToPtr(*volatile Mmio(32, packed struct { - /// Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. - Y: u16, - /// Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. - X: u16, - }), base_address + 0x424); - - /// address: 0x50000428 - /// Pacing (X/Y) Fractional Timer\n - /// The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). - /// This equation is evaluated every sys_clk cycles and therefore can only generate - /// TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. - pub const TIMER2 = @intToPtr(*volatile Mmio(32, packed struct { - /// Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. - Y: u16, - /// Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. - X: u16, - }), base_address + 0x428); - - /// address: 0x5000042c - /// Pacing (X/Y) Fractional Timer\n - /// The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). - /// This equation is evaluated every sys_clk cycles and therefore can only generate - /// TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. - pub const TIMER3 = @intToPtr(*volatile Mmio(32, packed struct { - /// Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. - Y: u16, - /// Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. - X: u16, - }), base_address + 0x42c); - - /// address: 0x50000430 - /// Trigger one or more channels simultaneously - pub const MULTI_CHAN_TRIGGER = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x430); - - /// address: 0x50000434 - /// Sniffer Control - pub const SNIFF_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// Enable sniffer - EN: u1, - /// DMA channel for Sniffer to observe - DMACH: u4, - CALC: u4, - /// Locally perform a byte reverse on the sniffed data, before feeding into - /// checksum.\n\n - /// Note that the sniff hardware is downstream of the DMA channel byteswap performed - /// in the read master: if channel CTRL_BSWAP and SNIFF_CTRL_BSWAP are both enabled, - /// their effects cancel from the sniffer's point of view. - BSWAP: u1, - /// If set, the result appears bit-reversed when read. This does not affect the way - /// the checksum is calculated; the result is transformed on-the-fly between the - /// result register and the bus. - OUT_REV: u1, - /// If set, the result appears inverted (bitwise complement) when read. This does - /// not affect the way the checksum is calculated; the result is transformed - /// on-the-fly between the result register and the bus. - OUT_INV: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x434); - - /// address: 0x50000438 - /// Data accumulator for sniff hardware\n - /// Write an initial seed value here before starting a DMA transfer on the channel - /// indicated by SNIFF_CTRL_DMACH. The hardware will update this register each time - /// it observes a read from the indicated channel. Once the channel completes, the - /// final result can be read from this register. - pub const SNIFF_DATA = @intToPtr(*volatile u32, base_address + 0x438); - - /// address: 0x50000440 - /// Debug RAF, WAF, TDF levels - pub const FIFO_LEVELS = @intToPtr(*volatile Mmio(32, packed struct { - /// Current Transfer-Data-FIFO fill level - TDF_LVL: u8, - /// Current Write-Address-FIFO fill level - WAF_LVL: u8, - /// Current Read-Address-FIFO fill level - RAF_LVL: u8, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - }), base_address + 0x440); - - /// address: 0x50000444 - /// Abort an in-progress transfer sequence on one or more channels - pub const CHAN_ABORT = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x444); - - /// address: 0x50000448 - /// The number of channels this DMA instance is equipped with. This DMA supports up - /// to 16 hardware channels, but can be configured with as few as one, to minimise - /// silicon area. - pub const N_CHANNELS = @intToPtr(*volatile MmioInt(32, u5), base_address + 0x448); - - /// address: 0x50000800 - /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can - /// perform on the peripheral without overflow/underflow. Write any value: clears - /// the counter, and cause channel to re-initiate DREQ handshake. - pub const CH0_DBG_CTDREQ = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x800); - - /// address: 0x50000804 - /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next - /// transfer - pub const CH0_DBG_TCR = @intToPtr(*volatile u32, base_address + 0x804); - - /// address: 0x50000840 - /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can - /// perform on the peripheral without overflow/underflow. Write any value: clears - /// the counter, and cause channel to re-initiate DREQ handshake. - pub const CH1_DBG_CTDREQ = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x840); - - /// address: 0x50000844 - /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next - /// transfer - pub const CH1_DBG_TCR = @intToPtr(*volatile u32, base_address + 0x844); - - /// address: 0x50000880 - /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can - /// perform on the peripheral without overflow/underflow. Write any value: clears - /// the counter, and cause channel to re-initiate DREQ handshake. - pub const CH2_DBG_CTDREQ = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x880); - - /// address: 0x50000884 - /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next - /// transfer - pub const CH2_DBG_TCR = @intToPtr(*volatile u32, base_address + 0x884); - - /// address: 0x500008c0 - /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can - /// perform on the peripheral without overflow/underflow. Write any value: clears - /// the counter, and cause channel to re-initiate DREQ handshake. - pub const CH3_DBG_CTDREQ = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x8c0); - - /// address: 0x500008c4 - /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next - /// transfer - pub const CH3_DBG_TCR = @intToPtr(*volatile u32, base_address + 0x8c4); - - /// address: 0x50000900 - /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can - /// perform on the peripheral without overflow/underflow. Write any value: clears - /// the counter, and cause channel to re-initiate DREQ handshake. - pub const CH4_DBG_CTDREQ = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x900); - - /// address: 0x50000904 - /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next - /// transfer - pub const CH4_DBG_TCR = @intToPtr(*volatile u32, base_address + 0x904); - - /// address: 0x50000940 - /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can - /// perform on the peripheral without overflow/underflow. Write any value: clears - /// the counter, and cause channel to re-initiate DREQ handshake. - pub const CH5_DBG_CTDREQ = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x940); - - /// address: 0x50000944 - /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next - /// transfer - pub const CH5_DBG_TCR = @intToPtr(*volatile u32, base_address + 0x944); - - /// address: 0x50000980 - /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can - /// perform on the peripheral without overflow/underflow. Write any value: clears - /// the counter, and cause channel to re-initiate DREQ handshake. - pub const CH6_DBG_CTDREQ = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x980); - - /// address: 0x50000984 - /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next - /// transfer - pub const CH6_DBG_TCR = @intToPtr(*volatile u32, base_address + 0x984); - - /// address: 0x500009c0 - /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can - /// perform on the peripheral without overflow/underflow. Write any value: clears - /// the counter, and cause channel to re-initiate DREQ handshake. - pub const CH7_DBG_CTDREQ = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x9c0); - - /// address: 0x500009c4 - /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next - /// transfer - pub const CH7_DBG_TCR = @intToPtr(*volatile u32, base_address + 0x9c4); - - /// address: 0x50000a00 - /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can - /// perform on the peripheral without overflow/underflow. Write any value: clears - /// the counter, and cause channel to re-initiate DREQ handshake. - pub const CH8_DBG_CTDREQ = @intToPtr(*volatile MmioInt(32, u6), base_address + 0xa00); - - /// address: 0x50000a04 - /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next - /// transfer - pub const CH8_DBG_TCR = @intToPtr(*volatile u32, base_address + 0xa04); - - /// address: 0x50000a40 - /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can - /// perform on the peripheral without overflow/underflow. Write any value: clears - /// the counter, and cause channel to re-initiate DREQ handshake. - pub const CH9_DBG_CTDREQ = @intToPtr(*volatile MmioInt(32, u6), base_address + 0xa40); - - /// address: 0x50000a44 - /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next - /// transfer - pub const CH9_DBG_TCR = @intToPtr(*volatile u32, base_address + 0xa44); - - /// address: 0x50000a80 - /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can - /// perform on the peripheral without overflow/underflow. Write any value: clears - /// the counter, and cause channel to re-initiate DREQ handshake. - pub const CH10_DBG_CTDREQ = @intToPtr(*volatile MmioInt(32, u6), base_address + 0xa80); - - /// address: 0x50000a84 - /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next - /// transfer - pub const CH10_DBG_TCR = @intToPtr(*volatile u32, base_address + 0xa84); - - /// address: 0x50000ac0 - /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can - /// perform on the peripheral without overflow/underflow. Write any value: clears - /// the counter, and cause channel to re-initiate DREQ handshake. - pub const CH11_DBG_CTDREQ = @intToPtr(*volatile MmioInt(32, u6), base_address + 0xac0); - - /// address: 0x50000ac4 - /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next - /// transfer - pub const CH11_DBG_TCR = @intToPtr(*volatile u32, base_address + 0xac4); - }; - - /// DPRAM layout for USB device. - pub const USBCTRL_DPRAM = struct { - pub const base_address = 0x50100000; - pub const version = "1"; - - /// address: 0x50100000 - /// Bytes 0-3 of the SETUP packet from the host. - pub const SETUP_PACKET_LOW = @intToPtr(*volatile Mmio(32, packed struct { - BMREQUESTTYPE: u8, - BREQUEST: u8, - WVALUE: u16, - }), base_address + 0x0); - - /// address: 0x50100004 - /// Bytes 4-7 of the setup packet from the host. - pub const SETUP_PACKET_HIGH = @intToPtr(*volatile Mmio(32, packed struct { - WINDEX: u16, - WLENGTH: u16, - }), base_address + 0x4); - - /// address: 0x50100008 - pub const EP1_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x8); - - /// address: 0x5010000c - pub const EP1_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0xc); - - /// address: 0x50100010 - pub const EP2_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x10); - - /// address: 0x50100014 - pub const EP2_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x14); - - /// address: 0x50100018 - pub const EP3_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x18); - - /// address: 0x5010001c - pub const EP3_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x1c); - - /// address: 0x50100020 - pub const EP4_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x20); - - /// address: 0x50100024 - pub const EP4_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x24); - - /// address: 0x50100028 - pub const EP5_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x28); - - /// address: 0x5010002c - pub const EP5_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x2c); - - /// address: 0x50100030 - pub const EP6_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x30); - - /// address: 0x50100034 - pub const EP6_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x34); - - /// address: 0x50100038 - pub const EP7_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x38); - - /// address: 0x5010003c - pub const EP7_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x3c); - - /// address: 0x50100040 - pub const EP8_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x40); - - /// address: 0x50100044 - pub const EP8_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x44); - - /// address: 0x50100048 - pub const EP9_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x48); - - /// address: 0x5010004c - pub const EP9_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x4c); - - /// address: 0x50100050 - pub const EP10_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x50); - - /// address: 0x50100054 - pub const EP10_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x54); - - /// address: 0x50100058 - pub const EP11_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x58); - - /// address: 0x5010005c - pub const EP11_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x5c); - - /// address: 0x50100060 - pub const EP12_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x60); - - /// address: 0x50100064 - pub const EP12_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x64); - - /// address: 0x50100068 - pub const EP13_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x68); - - /// address: 0x5010006c - pub const EP13_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x6c); - - /// address: 0x50100070 - pub const EP14_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x70); - - /// address: 0x50100074 - pub const EP14_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x74); - - /// address: 0x50100078 - pub const EP15_IN_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x78); - - /// address: 0x5010007c - pub const EP15_OUT_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to - /// the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - ENDPOINT_TYPE: u2, - /// Trigger an interrupt each time both buffers are done. Only valid in double - /// buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint - /// if this bit is not set. - ENABLE: u1, - }), base_address + 0x7c); - - /// address: 0x50100080 - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP0_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0x80); - - /// address: 0x50100084 - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP0_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0x84); - - /// address: 0x50100088 - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP1_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0x88); - - /// address: 0x5010008c - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP1_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0x8c); - - /// address: 0x50100090 - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP2_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0x90); - - /// address: 0x50100094 - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP2_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0x94); - - /// address: 0x50100098 - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP3_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0x98); - - /// address: 0x5010009c - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP3_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0x9c); - - /// address: 0x501000a0 - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP4_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0xa0); - - /// address: 0x501000a4 - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP4_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0xa4); - - /// address: 0x501000a8 - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP5_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0xa8); - - /// address: 0x501000ac - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP5_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0xac); - - /// address: 0x501000b0 - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP6_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0xb0); - - /// address: 0x501000b4 - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP6_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0xb4); - - /// address: 0x501000b8 - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP7_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0xb8); - - /// address: 0x501000bc - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP7_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0xbc); - - /// address: 0x501000c0 - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP8_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0xc0); - - /// address: 0x501000c4 - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP8_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0xc4); - - /// address: 0x501000c8 - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP9_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0xc8); - - /// address: 0x501000cc - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP9_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0xcc); - - /// address: 0x501000d0 - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP10_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0xd0); - - /// address: 0x501000d4 - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP10_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0xd4); - - /// address: 0x501000d8 - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP11_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0xd8); - - /// address: 0x501000dc - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP11_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0xdc); - - /// address: 0x501000e0 - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP12_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0xe0); - - /// address: 0x501000e4 - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP12_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0xe4); - - /// address: 0x501000e8 - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP13_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0xe8); - - /// address: 0x501000ec - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP13_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0xec); - - /// address: 0x501000f0 - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP14_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0xf0); - - /// address: 0x501000f4 - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP14_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0xf4); - - /// address: 0x501000f8 - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP15_IN_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0xf8); - - /// address: 0x501000fc - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for - /// buffer 1.\n - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the - /// endpoint is in double buffered mode. - pub const EP15_OUT_BUFFER_CONTROL = @intToPtr(*volatile Mmio(32, packed struct { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the - /// controller. The controller clears the available bit when writing the status - /// back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only - /// valid in double buffered mode for an Isochronous endpoint.\n - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: u2, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate - /// the data is valid. For an OUT transfer (RX from the host) this bit should be - /// left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), base_address + 0xfc); - }; - - /// USB FS/LS controller device registers - pub const USBCTRL_REGS = struct { - pub const base_address = 0x50110000; - pub const version = "1"; - - /// address: 0x50110000 - /// Device address and endpoint control - pub const ADDR_ENDP = @intToPtr(*volatile Mmio(32, packed struct { - /// In device mode, the address that the device should respond to. Set in response - /// to a SET_ADDR setup packet from the host. In host mode set to the address of the - /// device to communicate with. - ADDRESS: u7, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - /// Device endpoint to send data to. Only valid for HOST mode. - ENDPOINT: u4, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - }), base_address + 0x0); - - /// address: 0x50110004 - /// Interrupt endpoint 1. Only valid for HOST mode. - pub const ADDR_ENDP1 = @intToPtr(*volatile Mmio(32, packed struct { - /// Device address - ADDRESS: u7, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x4); - - /// address: 0x50110008 - /// Interrupt endpoint 2. Only valid for HOST mode. - pub const ADDR_ENDP2 = @intToPtr(*volatile Mmio(32, packed struct { - /// Device address - ADDRESS: u7, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x8); - - /// address: 0x5011000c - /// Interrupt endpoint 3. Only valid for HOST mode. - pub const ADDR_ENDP3 = @intToPtr(*volatile Mmio(32, packed struct { - /// Device address - ADDRESS: u7, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0xc); - - /// address: 0x50110010 - /// Interrupt endpoint 4. Only valid for HOST mode. - pub const ADDR_ENDP4 = @intToPtr(*volatile Mmio(32, packed struct { - /// Device address - ADDRESS: u7, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x10); - - /// address: 0x50110014 - /// Interrupt endpoint 5. Only valid for HOST mode. - pub const ADDR_ENDP5 = @intToPtr(*volatile Mmio(32, packed struct { - /// Device address - ADDRESS: u7, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x14); - - /// address: 0x50110018 - /// Interrupt endpoint 6. Only valid for HOST mode. - pub const ADDR_ENDP6 = @intToPtr(*volatile Mmio(32, packed struct { - /// Device address - ADDRESS: u7, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x18); - - /// address: 0x5011001c - /// Interrupt endpoint 7. Only valid for HOST mode. - pub const ADDR_ENDP7 = @intToPtr(*volatile Mmio(32, packed struct { - /// Device address - ADDRESS: u7, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x1c); - - /// address: 0x50110020 - /// Interrupt endpoint 8. Only valid for HOST mode. - pub const ADDR_ENDP8 = @intToPtr(*volatile Mmio(32, packed struct { - /// Device address - ADDRESS: u7, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x20); - - /// address: 0x50110024 - /// Interrupt endpoint 9. Only valid for HOST mode. - pub const ADDR_ENDP9 = @intToPtr(*volatile Mmio(32, packed struct { - /// Device address - ADDRESS: u7, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x24); - - /// address: 0x50110028 - /// Interrupt endpoint 10. Only valid for HOST mode. - pub const ADDR_ENDP10 = @intToPtr(*volatile Mmio(32, packed struct { - /// Device address - ADDRESS: u7, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x28); - - /// address: 0x5011002c - /// Interrupt endpoint 11. Only valid for HOST mode. - pub const ADDR_ENDP11 = @intToPtr(*volatile Mmio(32, packed struct { - /// Device address - ADDRESS: u7, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x2c); - - /// address: 0x50110030 - /// Interrupt endpoint 12. Only valid for HOST mode. - pub const ADDR_ENDP12 = @intToPtr(*volatile Mmio(32, packed struct { - /// Device address - ADDRESS: u7, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x30); - - /// address: 0x50110034 - /// Interrupt endpoint 13. Only valid for HOST mode. - pub const ADDR_ENDP13 = @intToPtr(*volatile Mmio(32, packed struct { - /// Device address - ADDRESS: u7, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x34); - - /// address: 0x50110038 - /// Interrupt endpoint 14. Only valid for HOST mode. - pub const ADDR_ENDP14 = @intToPtr(*volatile Mmio(32, packed struct { - /// Device address - ADDRESS: u7, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x38); - - /// address: 0x5011003c - /// Interrupt endpoint 15. Only valid for HOST mode. - pub const ADDR_ENDP15 = @intToPtr(*volatile Mmio(32, packed struct { - /// Device address - ADDRESS: u7, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - }), base_address + 0x3c); - - /// address: 0x50110040 - /// Main control register - pub const MAIN_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// Enable controller - CONTROLLER_EN: u1, - /// Device mode = 0, Host mode = 1 - HOST_NDEVICE: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - reserved18: u1 = 0, - reserved19: u1 = 0, - reserved20: u1 = 0, - reserved21: u1 = 0, - reserved22: u1 = 0, - reserved23: u1 = 0, - reserved24: u1 = 0, - reserved25: u1 = 0, - reserved26: u1 = 0, - reserved27: u1 = 0, - reserved28: u1 = 0, - /// Reduced timings for simulation - SIM_TIMING: u1, - }), base_address + 0x40); - - /// address: 0x50110044 - /// Set the SOF (Start of Frame) frame number in the host controller. The SOF packet - /// is sent every 1ms and the host will increment the frame number by 1 each time. - pub const SOF_WR = @intToPtr(*volatile Mmio(32, packed struct { - COUNT: u11, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - }), base_address + 0x44); - - /// address: 0x50110048 - /// Read the last SOF (Start of Frame) frame number seen. In device mode the last - /// SOF received from the host. In host mode the last SOF sent by the host. - pub const SOF_RD = @intToPtr(*volatile Mmio(32, packed struct { - COUNT: u11, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - }), base_address + 0x48); - - /// address: 0x5011004c - /// SIE control register - pub const SIE_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// Host: Start transaction - START_TRANS: u1, - /// Host: Send Setup packet - SEND_SETUP: u1, - /// Host: Send transaction (OUT from host) - SEND_DATA: u1, - /// Host: Receive transaction (IN to host) - RECEIVE_DATA: u1, - /// Host: Stop transaction - STOP_TRANS: u1, - reserved0: u1 = 0, - /// Host: Preable enable for LS device on FS hub - PREAMBLE_EN: u1, - reserved1: u1 = 0, - /// Host: Delay packet(s) until after SOF - SOF_SYNC: u1, - /// Host: Enable SOF generation (for full speed bus) - SOF_EN: u1, - /// Host: Enable keep alive packet (for low speed bus) - KEEP_ALIVE_EN: u1, - /// Host: Enable VBUS - VBUS_EN: u1, - /// Device: Remote wakeup. Device can initiate its own resume after suspend. - RESUME: u1, - /// Host: Reset bus - RESET_BUS: u1, - reserved2: u1 = 0, - /// Host: Enable pull down resistors - PULLDOWN_EN: u1, - /// Device: Enable pull up resistor - PULLUP_EN: u1, - /// Device: Pull-up strength (0=1K2, 1=2k3) - RPU_OPT: u1, - /// Power down bus transceiver - TRANSCEIVER_PD: u1, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// Direct control of DM - DIRECT_DM: u1, - /// Direct control of DP - DIRECT_DP: u1, - /// Direct bus drive enable - DIRECT_EN: u1, - /// Device: Set bit in EP_STATUS_STALL_NAK when EP0 sends a NAK - EP0_INT_NAK: u1, - /// Device: Set bit in BUFF_STATUS for every 2 buffers completed on EP0 - EP0_INT_2BUF: u1, - /// Device: Set bit in BUFF_STATUS for every buffer completed on EP0 - EP0_INT_1BUF: u1, - /// Device: EP0 single buffered = 0, double buffered = 1 - EP0_DOUBLE_BUF: u1, - /// Device: Set bit in EP_STATUS_STALL_NAK when EP0 sends a STALL - EP0_INT_STALL: u1, - }), base_address + 0x4c); - - /// address: 0x50110050 - /// SIE status register - pub const SIE_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - /// Device: VBUS Detected - VBUS_DETECTED: u1, - reserved0: u1 = 0, - /// USB bus line state - LINE_STATE: u2, - /// Bus in suspended state. Valid for device and host. Host and device will go into - /// suspend if neither Keep Alive / SOF frames are enabled. - SUSPENDED: u1, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - /// Host: device speed. Disconnected = 00, LS = 01, FS = 10 - SPEED: u2, - /// VBUS over current detected - VBUS_OVER_CURR: u1, - /// Host: Device has initiated a remote resume. Device: host has initiated a resume. - RESUME: u1, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// Device: connected - CONNECTED: u1, - /// Device: Setup packet received - SETUP_REC: u1, - /// Transaction complete.\n\n - /// Raised by device if:\n\n - /// * An IN or OUT packet is sent with the `LAST_BUFF` bit set in the buffer control - /// register\n\n - /// Raised by host if:\n\n - /// * A setup packet is sent when no data in or data out transaction follows * An IN - /// packet is received and the `LAST_BUFF` bit is set in the buffer control register - /// * An IN packet is received with zero length * An OUT packet is sent and the - /// `LAST_BUFF` bit is set - TRANS_COMPLETE: u1, - /// Device: bus reset received - BUS_RESET: u1, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - /// CRC Error. Raised by the Serial RX engine. - CRC_ERROR: u1, - /// Bit Stuff Error. Raised by the Serial RX engine. - BIT_STUFF_ERROR: u1, - /// RX overflow is raised by the Serial RX engine if the incoming data is too fast. - RX_OVERFLOW: u1, - /// RX timeout is raised by both the host and device if an ACK is not received in - /// the maximum time specified by the USB spec. - RX_TIMEOUT: u1, - /// Host: NAK received - NAK_REC: u1, - /// Host: STALL received - STALL_REC: u1, - /// ACK received. Raised by both host and device. - ACK_REC: u1, - /// Data Sequence Error.\n\n - /// The device can raise a sequence error in the following conditions:\n\n - /// * A SETUP packet is received followed by a DATA1 packet (data phase should - /// always be DATA0) * An OUT packet is received from the host but doesn't match the - /// data pid in the buffer control register read from DPSRAM\n\n - /// The host can raise a data sequence error in the following conditions:\n\n - /// * An IN packet from the device has the wrong data PID - DATA_SEQ_ERROR: u1, - }), base_address + 0x50); - - /// address: 0x50110054 - /// interrupt endpoint control register - pub const INT_EP_CTRL = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - /// Host: Enable interrupt endpoint 1 -> 15 - INT_EP_ACTIVE: u15, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - }), base_address + 0x54); - - /// address: 0x50110058 - /// Buffer status register. A bit set here indicates that a buffer has completed on - /// the endpoint (if the buffer interrupt is enabled). It is possible for 2 buffers - /// to be completed, so clearing the buffer status bit may instantly re set it on - /// the next clock cycle. - pub const BUFF_STATUS = @intToPtr(*volatile Mmio(32, packed struct { - EP0_IN: u1, - EP0_OUT: u1, - EP1_IN: u1, - EP1_OUT: u1, - EP2_IN: u1, - EP2_OUT: u1, - EP3_IN: u1, - EP3_OUT: u1, - EP4_IN: u1, - EP4_OUT: u1, - EP5_IN: u1, - EP5_OUT: u1, - EP6_IN: u1, - EP6_OUT: u1, - EP7_IN: u1, - EP7_OUT: u1, - EP8_IN: u1, - EP8_OUT: u1, - EP9_IN: u1, - EP9_OUT: u1, - EP10_IN: u1, - EP10_OUT: u1, - EP11_IN: u1, - EP11_OUT: u1, - EP12_IN: u1, - EP12_OUT: u1, - EP13_IN: u1, - EP13_OUT: u1, - EP14_IN: u1, - EP14_OUT: u1, - EP15_IN: u1, - EP15_OUT: u1, - }), base_address + 0x58); - - /// address: 0x5011005c - /// Which of the double buffers should be handled. Only valid if using an interrupt - /// per buffer (i.e. not per 2 buffers). Not valid for host interrupt endpoint - /// polling because they are only single buffered. - pub const BUFF_CPU_SHOULD_HANDLE = @intToPtr(*volatile Mmio(32, packed struct { - EP0_IN: u1, - EP0_OUT: u1, - EP1_IN: u1, - EP1_OUT: u1, - EP2_IN: u1, - EP2_OUT: u1, - EP3_IN: u1, - EP3_OUT: u1, - EP4_IN: u1, - EP4_OUT: u1, - EP5_IN: u1, - EP5_OUT: u1, - EP6_IN: u1, - EP6_OUT: u1, - EP7_IN: u1, - EP7_OUT: u1, - EP8_IN: u1, - EP8_OUT: u1, - EP9_IN: u1, - EP9_OUT: u1, - EP10_IN: u1, - EP10_OUT: u1, - EP11_IN: u1, - EP11_OUT: u1, - EP12_IN: u1, - EP12_OUT: u1, - EP13_IN: u1, - EP13_OUT: u1, - EP14_IN: u1, - EP14_OUT: u1, - EP15_IN: u1, - EP15_OUT: u1, - }), base_address + 0x5c); - - /// address: 0x50110060 - /// Device only: Can be set to ignore the buffer control register for this endpoint - /// in case you would like to revoke a buffer. A NAK will be sent for every access - /// to the endpoint until this bit is cleared. A corresponding bit in - /// `EP_ABORT_DONE` is set when it is safe to modify the buffer control register. - pub const EP_ABORT = @intToPtr(*volatile Mmio(32, packed struct { - EP0_IN: u1, - EP0_OUT: u1, - EP1_IN: u1, - EP1_OUT: u1, - EP2_IN: u1, - EP2_OUT: u1, - EP3_IN: u1, - EP3_OUT: u1, - EP4_IN: u1, - EP4_OUT: u1, - EP5_IN: u1, - EP5_OUT: u1, - EP6_IN: u1, - EP6_OUT: u1, - EP7_IN: u1, - EP7_OUT: u1, - EP8_IN: u1, - EP8_OUT: u1, - EP9_IN: u1, - EP9_OUT: u1, - EP10_IN: u1, - EP10_OUT: u1, - EP11_IN: u1, - EP11_OUT: u1, - EP12_IN: u1, - EP12_OUT: u1, - EP13_IN: u1, - EP13_OUT: u1, - EP14_IN: u1, - EP14_OUT: u1, - EP15_IN: u1, - EP15_OUT: u1, - }), base_address + 0x60); - - /// address: 0x50110064 - /// Device only: Used in conjunction with `EP_ABORT`. Set once an endpoint is idle - /// so the programmer knows it is safe to modify the buffer control register. - pub const EP_ABORT_DONE = @intToPtr(*volatile Mmio(32, packed struct { - EP0_IN: u1, - EP0_OUT: u1, - EP1_IN: u1, - EP1_OUT: u1, - EP2_IN: u1, - EP2_OUT: u1, - EP3_IN: u1, - EP3_OUT: u1, - EP4_IN: u1, - EP4_OUT: u1, - EP5_IN: u1, - EP5_OUT: u1, - EP6_IN: u1, - EP6_OUT: u1, - EP7_IN: u1, - EP7_OUT: u1, - EP8_IN: u1, - EP8_OUT: u1, - EP9_IN: u1, - EP9_OUT: u1, - EP10_IN: u1, - EP10_OUT: u1, - EP11_IN: u1, - EP11_OUT: u1, - EP12_IN: u1, - EP12_OUT: u1, - EP13_IN: u1, - EP13_OUT: u1, - EP14_IN: u1, - EP14_OUT: u1, - EP15_IN: u1, - EP15_OUT: u1, - }), base_address + 0x64); - - /// address: 0x50110068 - /// Device: this bit must be set in conjunction with the `STALL` bit in the buffer - /// control register to send a STALL on EP0. The device controller clears these bits - /// when a SETUP packet is received because the USB spec requires that a STALL - /// condition is cleared when a SETUP packet is received. - pub const EP_STALL_ARM = @intToPtr(*volatile Mmio(32, packed struct { - EP0_IN: u1, - EP0_OUT: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - }), base_address + 0x68); - - /// address: 0x5011006c - /// Used by the host controller. Sets the wait time in microseconds before trying - /// again if the device replies with a NAK. - pub const NAK_POLL = @intToPtr(*volatile Mmio(32, packed struct { - /// NAK polling interval for a low speed device - DELAY_LS: u10, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - /// NAK polling interval for a full speed device - DELAY_FS: u10, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - }), base_address + 0x6c); - - /// address: 0x50110070 - /// Device: bits are set when the `IRQ_ON_NAK` or `IRQ_ON_STALL` bits are set. For - /// EP0 this comes from `SIE_CTRL`. For all other endpoints it comes from the - /// endpoint control register. - pub const EP_STATUS_STALL_NAK = @intToPtr(*volatile Mmio(32, packed struct { - EP0_IN: u1, - EP0_OUT: u1, - EP1_IN: u1, - EP1_OUT: u1, - EP2_IN: u1, - EP2_OUT: u1, - EP3_IN: u1, - EP3_OUT: u1, - EP4_IN: u1, - EP4_OUT: u1, - EP5_IN: u1, - EP5_OUT: u1, - EP6_IN: u1, - EP6_OUT: u1, - EP7_IN: u1, - EP7_OUT: u1, - EP8_IN: u1, - EP8_OUT: u1, - EP9_IN: u1, - EP9_OUT: u1, - EP10_IN: u1, - EP10_OUT: u1, - EP11_IN: u1, - EP11_OUT: u1, - EP12_IN: u1, - EP12_OUT: u1, - EP13_IN: u1, - EP13_OUT: u1, - EP14_IN: u1, - EP14_OUT: u1, - EP15_IN: u1, - EP15_OUT: u1, - }), base_address + 0x70); - - /// address: 0x50110074 - /// Where to connect the USB controller. Should be to_phy by default. - pub const USB_MUXING = @intToPtr(*volatile Mmio(32, packed struct { - TO_PHY: u1, - TO_EXTPHY: u1, - TO_DIGITAL_PAD: u1, - SOFTCON: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - }), base_address + 0x74); - - /// address: 0x50110078 - /// Overrides for the power signals in the event that the VBUS signals are not - /// hooked up to GPIO. Set the value of the override and then the override enable to - /// switch over to the override value. - pub const USB_PWR = @intToPtr(*volatile Mmio(32, packed struct { - VBUS_EN: u1, - VBUS_EN_OVERRIDE_EN: u1, - VBUS_DETECT: u1, - VBUS_DETECT_OVERRIDE_EN: u1, - OVERCURR_DETECT: u1, - OVERCURR_DETECT_EN: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - }), base_address + 0x78); - - /// address: 0x5011007c - /// This register allows for direct control of the USB phy. Use in conjunction with - /// usbphy_direct_override register to enable each override bit. - pub const USBPHY_DIRECT = @intToPtr(*volatile Mmio(32, packed struct { - /// Enable the second DP pull up resistor. 0 - Pull = Rpu2; 1 - Pull = Rpu1 + Rpu2 - DP_PULLUP_HISEL: u1, - /// DP pull up enable - DP_PULLUP_EN: u1, - /// DP pull down enable - DP_PULLDN_EN: u1, - reserved0: u1 = 0, - /// Enable the second DM pull up resistor. 0 - Pull = Rpu2; 1 - Pull = Rpu1 + Rpu2 - DM_PULLUP_HISEL: u1, - /// DM pull up enable - DM_PULLUP_EN: u1, - /// DM pull down enable - DM_PULLDN_EN: u1, - reserved1: u1 = 0, - /// Output enable. If TX_DIFFMODE=1, OE for DPP/DPM diff pair. 0 - DPP/DPM in Hi-Z - /// state; 1 - DPP/DPM driving\n - /// If TX_DIFFMODE=0, OE for DPP only. 0 - DPP in Hi-Z state; 1 - DPP driving - TX_DP_OE: u1, - /// Output enable. If TX_DIFFMODE=1, Ignored.\n - /// If TX_DIFFMODE=0, OE for DPM only. 0 - DPM in Hi-Z state; 1 - DPM driving - TX_DM_OE: u1, - /// Output data. If TX_DIFFMODE=1, Drives DPP/DPM diff pair. TX_DP_OE=1 to enable - /// drive. DPP=TX_DP, DPM=~TX_DP\n - /// If TX_DIFFMODE=0, Drives DPP only. TX_DP_OE=1 to enable drive. DPP=TX_DP - TX_DP: u1, - /// Output data. TX_DIFFMODE=1, Ignored\n - /// TX_DIFFMODE=0, Drives DPM only. TX_DM_OE=1 to enable drive. DPM=TX_DM - TX_DM: u1, - /// RX power down override (if override enable is set). 1 = powered down. - RX_PD: u1, - /// TX power down override (if override enable is set). 1 = powered down. - TX_PD: u1, - /// TX_FSSLEW=0: Low speed slew rate\n - /// TX_FSSLEW=1: Full speed slew rate - TX_FSSLEW: u1, - /// TX_DIFFMODE=0: Single ended mode\n - /// TX_DIFFMODE=1: Differential drive mode (TX_DM, TX_DM_OE ignored) - TX_DIFFMODE: u1, - /// Differential RX - RX_DD: u1, - /// DPP pin state - RX_DP: u1, - /// DPM pin state - RX_DM: u1, - /// DP overcurrent - DP_OVCN: u1, - /// DM overcurrent - DM_OVCN: u1, - /// DP over voltage - DP_OVV: u1, - /// DM over voltage - DM_OVV: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - }), base_address + 0x7c); - - /// address: 0x50110080 - /// Override enable for each control in usbphy_direct - pub const USBPHY_DIRECT_OVERRIDE = @intToPtr(*volatile Mmio(32, packed struct { - DP_PULLUP_HISEL_OVERRIDE_EN: u1, - DM_PULLUP_HISEL_OVERRIDE_EN: u1, - DP_PULLUP_EN_OVERRIDE_EN: u1, - DP_PULLDN_EN_OVERRIDE_EN: u1, - DM_PULLDN_EN_OVERRIDE_EN: u1, - TX_DP_OE_OVERRIDE_EN: u1, - TX_DM_OE_OVERRIDE_EN: u1, - TX_DP_OVERRIDE_EN: u1, - TX_DM_OVERRIDE_EN: u1, - RX_PD_OVERRIDE_EN: u1, - TX_PD_OVERRIDE_EN: u1, - TX_FSSLEW_OVERRIDE_EN: u1, - DM_PULLUP_OVERRIDE_EN: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - TX_DIFFMODE_OVERRIDE_EN: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - }), base_address + 0x80); - - /// address: 0x50110084 - /// Used to adjust trim values of USB phy pull down resistors. - pub const USBPHY_TRIM = @intToPtr(*volatile Mmio(32, packed struct { - /// Value to drive to USB PHY\n - /// DP pulldown resistor trim control\n - /// Experimental data suggests that the reset value will work, but this register - /// allows adjustment if required - DP_PULLDN_TRIM: u5, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - /// Value to drive to USB PHY\n - /// DM pulldown resistor trim control\n - /// Experimental data suggests that the reset value will work, but this register - /// allows adjustment if required - DM_PULLDN_TRIM: u5, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - }), base_address + 0x84); - - /// address: 0x5011008c - /// Raw Interrupts - pub const INTR = @intToPtr(*volatile Mmio(32, packed struct { - /// Host: raised when a device is connected or disconnected (i.e. when - /// SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED - HOST_CONN_DIS: u1, - /// Host: raised when a device wakes up the host. Cleared by writing to - /// SIE_STATUS.RESUME - HOST_RESUME: u1, - /// Host: raised every time the host sends a SOF (Start of Frame). Cleared by - /// reading SOF_RD - HOST_SOF: u1, - /// Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this - /// bit. - TRANS_COMPLETE: u1, - /// Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in - /// BUFF_STATUS. - BUFF_STATUS: u1, - /// Source: SIE_STATUS.DATA_SEQ_ERROR - ERROR_DATA_SEQ: u1, - /// Source: SIE_STATUS.RX_TIMEOUT - ERROR_RX_TIMEOUT: u1, - /// Source: SIE_STATUS.RX_OVERFLOW - ERROR_RX_OVERFLOW: u1, - /// Source: SIE_STATUS.BIT_STUFF_ERROR - ERROR_BIT_STUFF: u1, - /// Source: SIE_STATUS.CRC_ERROR - ERROR_CRC: u1, - /// Source: SIE_STATUS.STALL_REC - STALL: u1, - /// Source: SIE_STATUS.VBUS_DETECTED - VBUS_DETECT: u1, - /// Source: SIE_STATUS.BUS_RESET - BUS_RESET: u1, - /// Set when the device connection state changes. Cleared by writing to - /// SIE_STATUS.CONNECTED - DEV_CONN_DIS: u1, - /// Set when the device suspend state changes. Cleared by writing to - /// SIE_STATUS.SUSPENDED - DEV_SUSPEND: u1, - /// Set when the device receives a resume from the host. Cleared by writing to - /// SIE_STATUS.RESUME - DEV_RESUME_FROM_HOST: u1, - /// Device. Source: SIE_STATUS.SETUP_REC - SETUP_REQ: u1, - /// Set every time the device receives a SOF (Start of Frame) packet. Cleared by - /// reading SOF_RD - DEV_SOF: u1, - /// Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in - /// ABORT_DONE. - ABORT_DONE: u1, - /// Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in - /// EP_STATUS_STALL_NAK. - EP_STALL_NAK: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - }), base_address + 0x8c); - - /// address: 0x50110090 - /// Interrupt Enable - pub const INTE = @intToPtr(*volatile Mmio(32, packed struct { - /// Host: raised when a device is connected or disconnected (i.e. when - /// SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED - HOST_CONN_DIS: u1, - /// Host: raised when a device wakes up the host. Cleared by writing to - /// SIE_STATUS.RESUME - HOST_RESUME: u1, - /// Host: raised every time the host sends a SOF (Start of Frame). Cleared by - /// reading SOF_RD - HOST_SOF: u1, - /// Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this - /// bit. - TRANS_COMPLETE: u1, - /// Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in - /// BUFF_STATUS. - BUFF_STATUS: u1, - /// Source: SIE_STATUS.DATA_SEQ_ERROR - ERROR_DATA_SEQ: u1, - /// Source: SIE_STATUS.RX_TIMEOUT - ERROR_RX_TIMEOUT: u1, - /// Source: SIE_STATUS.RX_OVERFLOW - ERROR_RX_OVERFLOW: u1, - /// Source: SIE_STATUS.BIT_STUFF_ERROR - ERROR_BIT_STUFF: u1, - /// Source: SIE_STATUS.CRC_ERROR - ERROR_CRC: u1, - /// Source: SIE_STATUS.STALL_REC - STALL: u1, - /// Source: SIE_STATUS.VBUS_DETECTED - VBUS_DETECT: u1, - /// Source: SIE_STATUS.BUS_RESET - BUS_RESET: u1, - /// Set when the device connection state changes. Cleared by writing to - /// SIE_STATUS.CONNECTED - DEV_CONN_DIS: u1, - /// Set when the device suspend state changes. Cleared by writing to - /// SIE_STATUS.SUSPENDED - DEV_SUSPEND: u1, - /// Set when the device receives a resume from the host. Cleared by writing to - /// SIE_STATUS.RESUME - DEV_RESUME_FROM_HOST: u1, - /// Device. Source: SIE_STATUS.SETUP_REC - SETUP_REQ: u1, - /// Set every time the device receives a SOF (Start of Frame) packet. Cleared by - /// reading SOF_RD - DEV_SOF: u1, - /// Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in - /// ABORT_DONE. - ABORT_DONE: u1, - /// Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in - /// EP_STATUS_STALL_NAK. - EP_STALL_NAK: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - }), base_address + 0x90); - - /// address: 0x50110094 - /// Interrupt Force - pub const INTF = @intToPtr(*volatile Mmio(32, packed struct { - /// Host: raised when a device is connected or disconnected (i.e. when - /// SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED - HOST_CONN_DIS: u1, - /// Host: raised when a device wakes up the host. Cleared by writing to - /// SIE_STATUS.RESUME - HOST_RESUME: u1, - /// Host: raised every time the host sends a SOF (Start of Frame). Cleared by - /// reading SOF_RD - HOST_SOF: u1, - /// Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this - /// bit. - TRANS_COMPLETE: u1, - /// Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in - /// BUFF_STATUS. - BUFF_STATUS: u1, - /// Source: SIE_STATUS.DATA_SEQ_ERROR - ERROR_DATA_SEQ: u1, - /// Source: SIE_STATUS.RX_TIMEOUT - ERROR_RX_TIMEOUT: u1, - /// Source: SIE_STATUS.RX_OVERFLOW - ERROR_RX_OVERFLOW: u1, - /// Source: SIE_STATUS.BIT_STUFF_ERROR - ERROR_BIT_STUFF: u1, - /// Source: SIE_STATUS.CRC_ERROR - ERROR_CRC: u1, - /// Source: SIE_STATUS.STALL_REC - STALL: u1, - /// Source: SIE_STATUS.VBUS_DETECTED - VBUS_DETECT: u1, - /// Source: SIE_STATUS.BUS_RESET - BUS_RESET: u1, - /// Set when the device connection state changes. Cleared by writing to - /// SIE_STATUS.CONNECTED - DEV_CONN_DIS: u1, - /// Set when the device suspend state changes. Cleared by writing to - /// SIE_STATUS.SUSPENDED - DEV_SUSPEND: u1, - /// Set when the device receives a resume from the host. Cleared by writing to - /// SIE_STATUS.RESUME - DEV_RESUME_FROM_HOST: u1, - /// Device. Source: SIE_STATUS.SETUP_REC - SETUP_REQ: u1, - /// Set every time the device receives a SOF (Start of Frame) packet. Cleared by - /// reading SOF_RD - DEV_SOF: u1, - /// Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in - /// ABORT_DONE. - ABORT_DONE: u1, - /// Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in - /// EP_STATUS_STALL_NAK. - EP_STALL_NAK: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - }), base_address + 0x94); - - /// address: 0x50110098 - /// Interrupt status after masking & forcing - pub const INTS = @intToPtr(*volatile Mmio(32, packed struct { - /// Host: raised when a device is connected or disconnected (i.e. when - /// SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED - HOST_CONN_DIS: u1, - /// Host: raised when a device wakes up the host. Cleared by writing to - /// SIE_STATUS.RESUME - HOST_RESUME: u1, - /// Host: raised every time the host sends a SOF (Start of Frame). Cleared by - /// reading SOF_RD - HOST_SOF: u1, - /// Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this - /// bit. - TRANS_COMPLETE: u1, - /// Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in - /// BUFF_STATUS. - BUFF_STATUS: u1, - /// Source: SIE_STATUS.DATA_SEQ_ERROR - ERROR_DATA_SEQ: u1, - /// Source: SIE_STATUS.RX_TIMEOUT - ERROR_RX_TIMEOUT: u1, - /// Source: SIE_STATUS.RX_OVERFLOW - ERROR_RX_OVERFLOW: u1, - /// Source: SIE_STATUS.BIT_STUFF_ERROR - ERROR_BIT_STUFF: u1, - /// Source: SIE_STATUS.CRC_ERROR - ERROR_CRC: u1, - /// Source: SIE_STATUS.STALL_REC - STALL: u1, - /// Source: SIE_STATUS.VBUS_DETECTED - VBUS_DETECT: u1, - /// Source: SIE_STATUS.BUS_RESET - BUS_RESET: u1, - /// Set when the device connection state changes. Cleared by writing to - /// SIE_STATUS.CONNECTED - DEV_CONN_DIS: u1, - /// Set when the device suspend state changes. Cleared by writing to - /// SIE_STATUS.SUSPENDED - DEV_SUSPEND: u1, - /// Set when the device receives a resume from the host. Cleared by writing to - /// SIE_STATUS.RESUME - DEV_RESUME_FROM_HOST: u1, - /// Device. Source: SIE_STATUS.SETUP_REC - SETUP_REQ: u1, - /// Set every time the device receives a SOF (Start of Frame) packet. Cleared by - /// reading SOF_RD - DEV_SOF: u1, - /// Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in - /// ABORT_DONE. - ABORT_DONE: u1, - /// Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in - /// EP_STATUS_STALL_NAK. - EP_STALL_NAK: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - }), base_address + 0x98); - }; - - /// Programmable IO block - pub const PIO0 = struct { - pub const base_address = 0x50200000; - pub const version = "1"; - - /// address: 0x50200000 - /// PIO control register - pub const CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// Enable/disable each of the four state machines by writing 1/0 to each of these - /// four bits. When disabled, a state machine will cease executing instructions, - /// except those written directly to SMx_INSTR by the system. Multiple bits can be - /// set/cleared at once to run/halt multiple state machines simultaneously. - SM_ENABLE: u4, - /// Write 1 to instantly clear internal SM state which may be otherwise difficult to - /// access and will affect future execution.\n\n - /// Specifically, the following are cleared: input and output shift counters; the - /// contents of the input shift register; the delay counter; the waiting-on-IRQ - /// state; any stalled instruction written to SMx_INSTR or run by OUT/MOV EXEC; any - /// pin write left asserted due to OUT_STICKY. - SM_RESTART: u4, - /// Restart a state machine's clock divider from an initial phase of 0. Clock - /// dividers are free-running, so once started, their output (including fractional - /// jitter) is completely determined by the integer/fractional divisor configured in - /// SMx_CLKDIV. This means that, if multiple clock dividers with the same divisor - /// are restarted simultaneously, by writing multiple 1 bits to this field, the - /// execution clocks of those state machines will run in precise lockstep.\n\n - /// Note that setting/clearing SM_ENABLE does not stop the clock divider from - /// running, so once multiple state machines' clocks are synchronised, it is safe to - /// disable/reenable a state machine, whilst keeping the clock dividers in sync.\n\n - /// Note also that CLKDIV_RESTART can be written to whilst the state machine is - /// running, and this is useful to resynchronise clock dividers after the divisors - /// (SMx_CLKDIV) have been changed on-the-fly. - CLKDIV_RESTART: u4, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x0); - - /// address: 0x50200004 - /// FIFO status register - pub const FSTAT = @intToPtr(*volatile Mmio(32, packed struct { - /// State machine RX FIFO is full - RXFULL: u4, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - /// State machine RX FIFO is empty - RXEMPTY: u4, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// State machine TX FIFO is full - TXFULL: u4, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - /// State machine TX FIFO is empty - TXEMPTY: u4, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - }), base_address + 0x4); - - /// address: 0x50200008 - /// FIFO debug register - pub const FDEBUG = @intToPtr(*volatile Mmio(32, packed struct { - /// State machine has stalled on full RX FIFO during a blocking PUSH, or an IN with - /// autopush enabled. This flag is also set when a nonblocking PUSH to a full FIFO - /// took place, in which case the state machine has dropped data. Write 1 to clear. - RXSTALL: u4, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - /// RX FIFO underflow (i.e. read-on-empty by the system) has occurred. Write 1 to - /// clear. Note that read-on-empty does not perturb the state of the FIFO in any - /// way, but the data returned by reading from an empty FIFO is undefined, so this - /// flag generally only becomes set due to some kind of software error. - RXUNDER: u4, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// TX FIFO overflow (i.e. write-on-full by the system) has occurred. Write 1 to - /// clear. Note that write-on-full does not alter the state or contents of the FIFO - /// in any way, but the data that the system attempted to write is dropped, so if - /// this flag is set, your software has quite likely dropped some data on the floor. - TXOVER: u4, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - /// State machine has stalled on empty TX FIFO during a blocking PULL, or an OUT - /// with autopull enabled. Write 1 to clear. - TXSTALL: u4, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - }), base_address + 0x8); - - /// address: 0x5020000c - /// FIFO levels - pub const FLEVEL = @intToPtr(*volatile Mmio(32, packed struct { - TX0: u4, - RX0: u4, - TX1: u4, - RX1: u4, - TX2: u4, - RX2: u4, - TX3: u4, - RX3: u4, - }), base_address + 0xc); - - /// address: 0x50200010 - /// Direct write access to the TX FIFO for this state machine. Each write pushes one - /// word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO - /// state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. - pub const TXF0 = @intToPtr(*volatile u32, base_address + 0x10); - - /// address: 0x50200014 - /// Direct write access to the TX FIFO for this state machine. Each write pushes one - /// word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO - /// state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. - pub const TXF1 = @intToPtr(*volatile u32, base_address + 0x14); - - /// address: 0x50200018 - /// Direct write access to the TX FIFO for this state machine. Each write pushes one - /// word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO - /// state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. - pub const TXF2 = @intToPtr(*volatile u32, base_address + 0x18); - - /// address: 0x5020001c - /// Direct write access to the TX FIFO for this state machine. Each write pushes one - /// word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO - /// state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. - pub const TXF3 = @intToPtr(*volatile u32, base_address + 0x1c); - - /// address: 0x50200020 - /// Direct read access to the RX FIFO for this state machine. Each read pops one - /// word from the FIFO. Attempting to read from an empty FIFO has no effect on the - /// FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The - /// data returned to the system on a read from an empty FIFO is undefined. - pub const RXF0 = @intToPtr(*volatile u32, base_address + 0x20); - - /// address: 0x50200024 - /// Direct read access to the RX FIFO for this state machine. Each read pops one - /// word from the FIFO. Attempting to read from an empty FIFO has no effect on the - /// FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The - /// data returned to the system on a read from an empty FIFO is undefined. - pub const RXF1 = @intToPtr(*volatile u32, base_address + 0x24); - - /// address: 0x50200028 - /// Direct read access to the RX FIFO for this state machine. Each read pops one - /// word from the FIFO. Attempting to read from an empty FIFO has no effect on the - /// FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The - /// data returned to the system on a read from an empty FIFO is undefined. - pub const RXF2 = @intToPtr(*volatile u32, base_address + 0x28); - - /// address: 0x5020002c - /// Direct read access to the RX FIFO for this state machine. Each read pops one - /// word from the FIFO. Attempting to read from an empty FIFO has no effect on the - /// FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The - /// data returned to the system on a read from an empty FIFO is undefined. - pub const RXF3 = @intToPtr(*volatile u32, base_address + 0x2c); - - /// address: 0x50200030 - /// State machine IRQ flags register. Write 1 to clear. There are 8 state machine - /// IRQ flags, which can be set, cleared, and waited on by the state machines. - /// There's no fixed association between flags and state machines -- any state - /// machine can use any flag.\n\n - /// Any of the 8 flags can be used for timing synchronisation between state - /// machines, using IRQ and WAIT instructions. The lower four of these flags are - /// also routed out to system-level interrupt requests, alongside FIFO status - /// interrupts -- see e.g. IRQ0_INTE. - pub const IRQ = @intToPtr(*volatile MmioInt(32, u8), base_address + 0x30); - - /// address: 0x50200034 - /// Writing a 1 to each of these bits will forcibly assert the corresponding IRQ. - /// Note this is different to the INTF register: writing here affects PIO internal - /// state. INTF just asserts the processor-facing IRQ signal for testing ISRs, and - /// is not visible to the state machines. - pub const IRQ_FORCE = @intToPtr(*volatile MmioInt(32, u8), base_address + 0x34); - - /// address: 0x50200038 - /// There is a 2-flipflop synchronizer on each GPIO input, which protects PIO logic - /// from metastabilities. This increases input delay, and for fast synchronous IO - /// (e.g. SPI) these synchronizers may need to be bypassed. Each bit in this - /// register corresponds to one GPIO.\n - /// 0 -> input is synchronized (default)\n - /// 1 -> synchronizer is bypassed\n - /// If in doubt, leave this register as all zeroes. - pub const INPUT_SYNC_BYPASS = @intToPtr(*volatile u32, base_address + 0x38); - - /// address: 0x5020003c - /// Read to sample the pad output values PIO is currently driving to the GPIOs. On - /// RP2040 there are 30 GPIOs, so the two most significant bits are hardwired to 0. - pub const DBG_PADOUT = @intToPtr(*volatile u32, base_address + 0x3c); - - /// address: 0x50200040 - /// Read to sample the pad output enables (direction) PIO is currently driving to - /// the GPIOs. On RP2040 there are 30 GPIOs, so the two most significant bits are - /// hardwired to 0. - pub const DBG_PADOE = @intToPtr(*volatile u32, base_address + 0x40); - - /// address: 0x50200044 - /// The PIO hardware has some free parameters that may vary between chip products.\n - /// These should be provided in the chip datasheet, but are also exposed here. - pub const DBG_CFGINFO = @intToPtr(*volatile Mmio(32, packed struct { - /// The depth of the state machine TX/RX FIFOs, measured in words.\n - /// Joining fifos via SHIFTCTRL_FJOIN gives one FIFO with double\n - /// this depth. - FIFO_DEPTH: u6, - reserved0: u1 = 0, - reserved1: u1 = 0, - /// The number of state machines this PIO instance is equipped with. - SM_COUNT: u4, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - /// The size of the instruction memory, measured in units of one instruction - IMEM_SIZE: u6, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - }), base_address + 0x44); - - /// address: 0x50200048 - /// Write-only access to instruction memory location 0 - pub const INSTR_MEM0 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x48); - - /// address: 0x5020004c - /// Write-only access to instruction memory location 1 - pub const INSTR_MEM1 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x4c); - - /// address: 0x50200050 - /// Write-only access to instruction memory location 2 - pub const INSTR_MEM2 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x50); - - /// address: 0x50200054 - /// Write-only access to instruction memory location 3 - pub const INSTR_MEM3 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x54); - - /// address: 0x50200058 - /// Write-only access to instruction memory location 4 - pub const INSTR_MEM4 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x58); - - /// address: 0x5020005c - /// Write-only access to instruction memory location 5 - pub const INSTR_MEM5 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x5c); - - /// address: 0x50200060 - /// Write-only access to instruction memory location 6 - pub const INSTR_MEM6 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x60); - - /// address: 0x50200064 - /// Write-only access to instruction memory location 7 - pub const INSTR_MEM7 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x64); - - /// address: 0x50200068 - /// Write-only access to instruction memory location 8 - pub const INSTR_MEM8 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x68); - - /// address: 0x5020006c - /// Write-only access to instruction memory location 9 - pub const INSTR_MEM9 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x6c); - - /// address: 0x50200070 - /// Write-only access to instruction memory location 10 - pub const INSTR_MEM10 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x70); - - /// address: 0x50200074 - /// Write-only access to instruction memory location 11 - pub const INSTR_MEM11 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x74); - - /// address: 0x50200078 - /// Write-only access to instruction memory location 12 - pub const INSTR_MEM12 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x78); - - /// address: 0x5020007c - /// Write-only access to instruction memory location 13 - pub const INSTR_MEM13 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x7c); - - /// address: 0x50200080 - /// Write-only access to instruction memory location 14 - pub const INSTR_MEM14 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x80); - - /// address: 0x50200084 - /// Write-only access to instruction memory location 15 - pub const INSTR_MEM15 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x84); - - /// address: 0x50200088 - /// Write-only access to instruction memory location 16 - pub const INSTR_MEM16 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x88); - - /// address: 0x5020008c - /// Write-only access to instruction memory location 17 - pub const INSTR_MEM17 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x8c); - - /// address: 0x50200090 - /// Write-only access to instruction memory location 18 - pub const INSTR_MEM18 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x90); - - /// address: 0x50200094 - /// Write-only access to instruction memory location 19 - pub const INSTR_MEM19 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x94); - - /// address: 0x50200098 - /// Write-only access to instruction memory location 20 - pub const INSTR_MEM20 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x98); - - /// address: 0x5020009c - /// Write-only access to instruction memory location 21 - pub const INSTR_MEM21 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x9c); - - /// address: 0x502000a0 - /// Write-only access to instruction memory location 22 - pub const INSTR_MEM22 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xa0); - - /// address: 0x502000a4 - /// Write-only access to instruction memory location 23 - pub const INSTR_MEM23 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xa4); - - /// address: 0x502000a8 - /// Write-only access to instruction memory location 24 - pub const INSTR_MEM24 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xa8); - - /// address: 0x502000ac - /// Write-only access to instruction memory location 25 - pub const INSTR_MEM25 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xac); - - /// address: 0x502000b0 - /// Write-only access to instruction memory location 26 - pub const INSTR_MEM26 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xb0); - - /// address: 0x502000b4 - /// Write-only access to instruction memory location 27 - pub const INSTR_MEM27 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xb4); - - /// address: 0x502000b8 - /// Write-only access to instruction memory location 28 - pub const INSTR_MEM28 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xb8); - - /// address: 0x502000bc - /// Write-only access to instruction memory location 29 - pub const INSTR_MEM29 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xbc); - - /// address: 0x502000c0 - /// Write-only access to instruction memory location 30 - pub const INSTR_MEM30 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xc0); - - /// address: 0x502000c4 - /// Write-only access to instruction memory location 31 - pub const INSTR_MEM31 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xc4); - - /// address: 0x502000c8 - /// Clock divisor register for state machine 0\n - /// Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) - pub const SM0_CLKDIV = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// Fractional part of clock divisor - FRAC: u8, - /// Effective frequency is sysclk/(int + frac/256).\n - /// Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. - INT: u16, - }), base_address + 0xc8); - - /// address: 0x502000cc - /// Execution/behavioural settings for state machine 0 - pub const SM0_EXECCTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// Comparison level for the MOV x, STATUS instruction - STATUS_N: u4, - /// Comparison used for the MOV x, STATUS instruction. - STATUS_SEL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - /// After reaching wrap_top, execution is wrapped to this address. - WRAP_BOTTOM: u5, - /// After reaching this address, execution is wrapped to wrap_bottom.\n - /// If the instruction is a jump, and the jump condition is true, the jump takes - /// priority. - WRAP_TOP: u5, - /// Continuously assert the most recent OUT/SET to the pins - OUT_STICKY: u1, - /// If 1, use a bit of OUT data as an auxiliary write enable\n - /// When used in conjunction with OUT_STICKY, writes with an enable of 0 will\n - /// deassert the latest pin write. This can create useful masking/override - /// behaviour\n - /// due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) - INLINE_OUT_EN: u1, - /// Which data bit to use for inline OUT enable - OUT_EN_SEL: u5, - /// The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. - JMP_PIN: u5, - /// If 1, side-set data is asserted to pin directions, instead of pin values - SIDE_PINDIR: u1, - /// If 1, the MSB of the Delay/Side-set instruction field is used as side-set - /// enable, rather than a side-set data bit. This allows instructions to perform - /// side-set optionally, rather than on every instruction, but the maximum possible - /// side-set width is reduced from 5 to 4. Note that the value of - /// PINCTRL_SIDESET_COUNT is inclusive of this enable bit. - SIDE_EN: u1, - /// If 1, an instruction written to SMx_INSTR is stalled, and latched by the state - /// machine. Will clear to 0 once this instruction completes. - EXEC_STALLED: u1, - }), base_address + 0xcc); - - /// address: 0x502000d0 - /// Control behaviour of the input/output shift registers for state machine 0 - pub const SM0_SHIFTCTRL = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - /// Push automatically when the input shift register is filled, i.e. on an IN - /// instruction which causes the input shift counter to reach or exceed PUSH_THRESH. - AUTOPUSH: u1, - /// Pull automatically when the output shift register is emptied, i.e. on or - /// following an OUT instruction which causes the output shift counter to reach or - /// exceed PULL_THRESH. - AUTOPULL: u1, - /// 1 = shift input shift register to right (data enters from left). 0 = to left. - IN_SHIFTDIR: u1, - /// 1 = shift out of output shift register to right. 0 = to left. - OUT_SHIFTDIR: u1, - /// Number of bits shifted into ISR before autopush, or conditional push (PUSH - /// IFFULL), will take place.\n - /// Write 0 for value of 32. - PUSH_THRESH: u5, - /// Number of bits shifted out of OSR before autopull, or conditional pull (PULL - /// IFEMPTY), will take place.\n - /// Write 0 for value of 32. - PULL_THRESH: u5, - /// When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep.\n - /// RX FIFO is disabled as a result (always reads as both full and empty).\n - /// FIFOs are flushed when this bit is changed. - FJOIN_TX: u1, - /// When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep.\n - /// TX FIFO is disabled as a result (always reads as both full and empty).\n - /// FIFOs are flushed when this bit is changed. - FJOIN_RX: u1, - }), base_address + 0xd0); - - /// address: 0x502000d4 - /// Current instruction address of state machine 0 - pub const SM0_ADDR = @intToPtr(*volatile MmioInt(32, u5), base_address + 0xd4); - - /// address: 0x502000d8 - /// Read to see the instruction currently addressed by state machine 0's program - /// counter\n - /// Write to execute an instruction immediately (including jumps) and then resume - /// execution. - pub const SM0_INSTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xd8); - - /// address: 0x502000dc - /// State machine pin control - pub const SM0_PINCTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV - /// PINS instruction. The data written to this pin will always be the - /// least-significant bit of the OUT or MOV data. - OUT_BASE: u5, - /// The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS - /// instruction. The data written to this pin is the least-significant bit of the - /// SET data. - SET_BASE: u5, - /// The lowest-numbered pin that will be affected by a side-set operation. The MSBs - /// of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) - /// are used for side-set data, with the remaining LSBs used for delay. The - /// least-significant bit of the side-set portion is the bit written to this pin, - /// with more-significant bits written to higher-numbered pins. - SIDESET_BASE: u5, - /// The pin which is mapped to the least-significant bit of a state machine's IN - /// data bus. Higher-numbered pins are mapped to consecutively more-significant data - /// bits, with a modulo of 32 applied to pin number. - IN_BASE: u5, - /// The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. - /// In the range 0 to 32 inclusive. - OUT_COUNT: u6, - /// The number of pins asserted by a SET. In the range 0 to 5 inclusive. - SET_COUNT: u3, - /// The number of MSBs of the Delay/Side-set instruction field which are used for - /// side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, - /// no side-set) and maximum of 5 (all side-set, no delay). - SIDESET_COUNT: u3, - }), base_address + 0xdc); - - /// address: 0x502000e0 - /// Clock divisor register for state machine 1\n - /// Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) - pub const SM1_CLKDIV = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// Fractional part of clock divisor - FRAC: u8, - /// Effective frequency is sysclk/(int + frac/256).\n - /// Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. - INT: u16, - }), base_address + 0xe0); - - /// address: 0x502000e4 - /// Execution/behavioural settings for state machine 1 - pub const SM1_EXECCTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// Comparison level for the MOV x, STATUS instruction - STATUS_N: u4, - /// Comparison used for the MOV x, STATUS instruction. - STATUS_SEL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - /// After reaching wrap_top, execution is wrapped to this address. - WRAP_BOTTOM: u5, - /// After reaching this address, execution is wrapped to wrap_bottom.\n - /// If the instruction is a jump, and the jump condition is true, the jump takes - /// priority. - WRAP_TOP: u5, - /// Continuously assert the most recent OUT/SET to the pins - OUT_STICKY: u1, - /// If 1, use a bit of OUT data as an auxiliary write enable\n - /// When used in conjunction with OUT_STICKY, writes with an enable of 0 will\n - /// deassert the latest pin write. This can create useful masking/override - /// behaviour\n - /// due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) - INLINE_OUT_EN: u1, - /// Which data bit to use for inline OUT enable - OUT_EN_SEL: u5, - /// The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. - JMP_PIN: u5, - /// If 1, side-set data is asserted to pin directions, instead of pin values - SIDE_PINDIR: u1, - /// If 1, the MSB of the Delay/Side-set instruction field is used as side-set - /// enable, rather than a side-set data bit. This allows instructions to perform - /// side-set optionally, rather than on every instruction, but the maximum possible - /// side-set width is reduced from 5 to 4. Note that the value of - /// PINCTRL_SIDESET_COUNT is inclusive of this enable bit. - SIDE_EN: u1, - /// If 1, an instruction written to SMx_INSTR is stalled, and latched by the state - /// machine. Will clear to 0 once this instruction completes. - EXEC_STALLED: u1, - }), base_address + 0xe4); - - /// address: 0x502000e8 - /// Control behaviour of the input/output shift registers for state machine 1 - pub const SM1_SHIFTCTRL = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - /// Push automatically when the input shift register is filled, i.e. on an IN - /// instruction which causes the input shift counter to reach or exceed PUSH_THRESH. - AUTOPUSH: u1, - /// Pull automatically when the output shift register is emptied, i.e. on or - /// following an OUT instruction which causes the output shift counter to reach or - /// exceed PULL_THRESH. - AUTOPULL: u1, - /// 1 = shift input shift register to right (data enters from left). 0 = to left. - IN_SHIFTDIR: u1, - /// 1 = shift out of output shift register to right. 0 = to left. - OUT_SHIFTDIR: u1, - /// Number of bits shifted into ISR before autopush, or conditional push (PUSH - /// IFFULL), will take place.\n - /// Write 0 for value of 32. - PUSH_THRESH: u5, - /// Number of bits shifted out of OSR before autopull, or conditional pull (PULL - /// IFEMPTY), will take place.\n - /// Write 0 for value of 32. - PULL_THRESH: u5, - /// When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep.\n - /// RX FIFO is disabled as a result (always reads as both full and empty).\n - /// FIFOs are flushed when this bit is changed. - FJOIN_TX: u1, - /// When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep.\n - /// TX FIFO is disabled as a result (always reads as both full and empty).\n - /// FIFOs are flushed when this bit is changed. - FJOIN_RX: u1, - }), base_address + 0xe8); - - /// address: 0x502000ec - /// Current instruction address of state machine 1 - pub const SM1_ADDR = @intToPtr(*volatile MmioInt(32, u5), base_address + 0xec); - - /// address: 0x502000f0 - /// Read to see the instruction currently addressed by state machine 1's program - /// counter\n - /// Write to execute an instruction immediately (including jumps) and then resume - /// execution. - pub const SM1_INSTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xf0); - - /// address: 0x502000f4 - /// State machine pin control - pub const SM1_PINCTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV - /// PINS instruction. The data written to this pin will always be the - /// least-significant bit of the OUT or MOV data. - OUT_BASE: u5, - /// The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS - /// instruction. The data written to this pin is the least-significant bit of the - /// SET data. - SET_BASE: u5, - /// The lowest-numbered pin that will be affected by a side-set operation. The MSBs - /// of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) - /// are used for side-set data, with the remaining LSBs used for delay. The - /// least-significant bit of the side-set portion is the bit written to this pin, - /// with more-significant bits written to higher-numbered pins. - SIDESET_BASE: u5, - /// The pin which is mapped to the least-significant bit of a state machine's IN - /// data bus. Higher-numbered pins are mapped to consecutively more-significant data - /// bits, with a modulo of 32 applied to pin number. - IN_BASE: u5, - /// The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. - /// In the range 0 to 32 inclusive. - OUT_COUNT: u6, - /// The number of pins asserted by a SET. In the range 0 to 5 inclusive. - SET_COUNT: u3, - /// The number of MSBs of the Delay/Side-set instruction field which are used for - /// side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, - /// no side-set) and maximum of 5 (all side-set, no delay). - SIDESET_COUNT: u3, - }), base_address + 0xf4); - - /// address: 0x502000f8 - /// Clock divisor register for state machine 2\n - /// Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) - pub const SM2_CLKDIV = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// Fractional part of clock divisor - FRAC: u8, - /// Effective frequency is sysclk/(int + frac/256).\n - /// Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. - INT: u16, - }), base_address + 0xf8); - - /// address: 0x502000fc - /// Execution/behavioural settings for state machine 2 - pub const SM2_EXECCTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// Comparison level for the MOV x, STATUS instruction - STATUS_N: u4, - /// Comparison used for the MOV x, STATUS instruction. - STATUS_SEL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - /// After reaching wrap_top, execution is wrapped to this address. - WRAP_BOTTOM: u5, - /// After reaching this address, execution is wrapped to wrap_bottom.\n - /// If the instruction is a jump, and the jump condition is true, the jump takes - /// priority. - WRAP_TOP: u5, - /// Continuously assert the most recent OUT/SET to the pins - OUT_STICKY: u1, - /// If 1, use a bit of OUT data as an auxiliary write enable\n - /// When used in conjunction with OUT_STICKY, writes with an enable of 0 will\n - /// deassert the latest pin write. This can create useful masking/override - /// behaviour\n - /// due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) - INLINE_OUT_EN: u1, - /// Which data bit to use for inline OUT enable - OUT_EN_SEL: u5, - /// The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. - JMP_PIN: u5, - /// If 1, side-set data is asserted to pin directions, instead of pin values - SIDE_PINDIR: u1, - /// If 1, the MSB of the Delay/Side-set instruction field is used as side-set - /// enable, rather than a side-set data bit. This allows instructions to perform - /// side-set optionally, rather than on every instruction, but the maximum possible - /// side-set width is reduced from 5 to 4. Note that the value of - /// PINCTRL_SIDESET_COUNT is inclusive of this enable bit. - SIDE_EN: u1, - /// If 1, an instruction written to SMx_INSTR is stalled, and latched by the state - /// machine. Will clear to 0 once this instruction completes. - EXEC_STALLED: u1, - }), base_address + 0xfc); - - /// address: 0x50200100 - /// Control behaviour of the input/output shift registers for state machine 2 - pub const SM2_SHIFTCTRL = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - /// Push automatically when the input shift register is filled, i.e. on an IN - /// instruction which causes the input shift counter to reach or exceed PUSH_THRESH. - AUTOPUSH: u1, - /// Pull automatically when the output shift register is emptied, i.e. on or - /// following an OUT instruction which causes the output shift counter to reach or - /// exceed PULL_THRESH. - AUTOPULL: u1, - /// 1 = shift input shift register to right (data enters from left). 0 = to left. - IN_SHIFTDIR: u1, - /// 1 = shift out of output shift register to right. 0 = to left. - OUT_SHIFTDIR: u1, - /// Number of bits shifted into ISR before autopush, or conditional push (PUSH - /// IFFULL), will take place.\n - /// Write 0 for value of 32. - PUSH_THRESH: u5, - /// Number of bits shifted out of OSR before autopull, or conditional pull (PULL - /// IFEMPTY), will take place.\n - /// Write 0 for value of 32. - PULL_THRESH: u5, - /// When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep.\n - /// RX FIFO is disabled as a result (always reads as both full and empty).\n - /// FIFOs are flushed when this bit is changed. - FJOIN_TX: u1, - /// When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep.\n - /// TX FIFO is disabled as a result (always reads as both full and empty).\n - /// FIFOs are flushed when this bit is changed. - FJOIN_RX: u1, - }), base_address + 0x100); - - /// address: 0x50200104 - /// Current instruction address of state machine 2 - pub const SM2_ADDR = @intToPtr(*volatile MmioInt(32, u5), base_address + 0x104); - - /// address: 0x50200108 - /// Read to see the instruction currently addressed by state machine 2's program - /// counter\n - /// Write to execute an instruction immediately (including jumps) and then resume - /// execution. - pub const SM2_INSTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x108); - - /// address: 0x5020010c - /// State machine pin control - pub const SM2_PINCTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV - /// PINS instruction. The data written to this pin will always be the - /// least-significant bit of the OUT or MOV data. - OUT_BASE: u5, - /// The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS - /// instruction. The data written to this pin is the least-significant bit of the - /// SET data. - SET_BASE: u5, - /// The lowest-numbered pin that will be affected by a side-set operation. The MSBs - /// of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) - /// are used for side-set data, with the remaining LSBs used for delay. The - /// least-significant bit of the side-set portion is the bit written to this pin, - /// with more-significant bits written to higher-numbered pins. - SIDESET_BASE: u5, - /// The pin which is mapped to the least-significant bit of a state machine's IN - /// data bus. Higher-numbered pins are mapped to consecutively more-significant data - /// bits, with a modulo of 32 applied to pin number. - IN_BASE: u5, - /// The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. - /// In the range 0 to 32 inclusive. - OUT_COUNT: u6, - /// The number of pins asserted by a SET. In the range 0 to 5 inclusive. - SET_COUNT: u3, - /// The number of MSBs of the Delay/Side-set instruction field which are used for - /// side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, - /// no side-set) and maximum of 5 (all side-set, no delay). - SIDESET_COUNT: u3, - }), base_address + 0x10c); - - /// address: 0x50200110 - /// Clock divisor register for state machine 3\n - /// Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) - pub const SM3_CLKDIV = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// Fractional part of clock divisor - FRAC: u8, - /// Effective frequency is sysclk/(int + frac/256).\n - /// Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. - INT: u16, - }), base_address + 0x110); - - /// address: 0x50200114 - /// Execution/behavioural settings for state machine 3 - pub const SM3_EXECCTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// Comparison level for the MOV x, STATUS instruction - STATUS_N: u4, - /// Comparison used for the MOV x, STATUS instruction. - STATUS_SEL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - /// After reaching wrap_top, execution is wrapped to this address. - WRAP_BOTTOM: u5, - /// After reaching this address, execution is wrapped to wrap_bottom.\n - /// If the instruction is a jump, and the jump condition is true, the jump takes - /// priority. - WRAP_TOP: u5, - /// Continuously assert the most recent OUT/SET to the pins - OUT_STICKY: u1, - /// If 1, use a bit of OUT data as an auxiliary write enable\n - /// When used in conjunction with OUT_STICKY, writes with an enable of 0 will\n - /// deassert the latest pin write. This can create useful masking/override - /// behaviour\n - /// due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) - INLINE_OUT_EN: u1, - /// Which data bit to use for inline OUT enable - OUT_EN_SEL: u5, - /// The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. - JMP_PIN: u5, - /// If 1, side-set data is asserted to pin directions, instead of pin values - SIDE_PINDIR: u1, - /// If 1, the MSB of the Delay/Side-set instruction field is used as side-set - /// enable, rather than a side-set data bit. This allows instructions to perform - /// side-set optionally, rather than on every instruction, but the maximum possible - /// side-set width is reduced from 5 to 4. Note that the value of - /// PINCTRL_SIDESET_COUNT is inclusive of this enable bit. - SIDE_EN: u1, - /// If 1, an instruction written to SMx_INSTR is stalled, and latched by the state - /// machine. Will clear to 0 once this instruction completes. - EXEC_STALLED: u1, - }), base_address + 0x114); - - /// address: 0x50200118 - /// Control behaviour of the input/output shift registers for state machine 3 - pub const SM3_SHIFTCTRL = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - /// Push automatically when the input shift register is filled, i.e. on an IN - /// instruction which causes the input shift counter to reach or exceed PUSH_THRESH. - AUTOPUSH: u1, - /// Pull automatically when the output shift register is emptied, i.e. on or - /// following an OUT instruction which causes the output shift counter to reach or - /// exceed PULL_THRESH. - AUTOPULL: u1, - /// 1 = shift input shift register to right (data enters from left). 0 = to left. - IN_SHIFTDIR: u1, - /// 1 = shift out of output shift register to right. 0 = to left. - OUT_SHIFTDIR: u1, - /// Number of bits shifted into ISR before autopush, or conditional push (PUSH - /// IFFULL), will take place.\n - /// Write 0 for value of 32. - PUSH_THRESH: u5, - /// Number of bits shifted out of OSR before autopull, or conditional pull (PULL - /// IFEMPTY), will take place.\n - /// Write 0 for value of 32. - PULL_THRESH: u5, - /// When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep.\n - /// RX FIFO is disabled as a result (always reads as both full and empty).\n - /// FIFOs are flushed when this bit is changed. - FJOIN_TX: u1, - /// When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep.\n - /// TX FIFO is disabled as a result (always reads as both full and empty).\n - /// FIFOs are flushed when this bit is changed. - FJOIN_RX: u1, - }), base_address + 0x118); - - /// address: 0x5020011c - /// Current instruction address of state machine 3 - pub const SM3_ADDR = @intToPtr(*volatile MmioInt(32, u5), base_address + 0x11c); - - /// address: 0x50200120 - /// Read to see the instruction currently addressed by state machine 3's program - /// counter\n - /// Write to execute an instruction immediately (including jumps) and then resume - /// execution. - pub const SM3_INSTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x120); - - /// address: 0x50200124 - /// State machine pin control - pub const SM3_PINCTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV - /// PINS instruction. The data written to this pin will always be the - /// least-significant bit of the OUT or MOV data. - OUT_BASE: u5, - /// The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS - /// instruction. The data written to this pin is the least-significant bit of the - /// SET data. - SET_BASE: u5, - /// The lowest-numbered pin that will be affected by a side-set operation. The MSBs - /// of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) - /// are used for side-set data, with the remaining LSBs used for delay. The - /// least-significant bit of the side-set portion is the bit written to this pin, - /// with more-significant bits written to higher-numbered pins. - SIDESET_BASE: u5, - /// The pin which is mapped to the least-significant bit of a state machine's IN - /// data bus. Higher-numbered pins are mapped to consecutively more-significant data - /// bits, with a modulo of 32 applied to pin number. - IN_BASE: u5, - /// The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. - /// In the range 0 to 32 inclusive. - OUT_COUNT: u6, - /// The number of pins asserted by a SET. In the range 0 to 5 inclusive. - SET_COUNT: u3, - /// The number of MSBs of the Delay/Side-set instruction field which are used for - /// side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, - /// no side-set) and maximum of 5 (all side-set, no delay). - SIDESET_COUNT: u3, - }), base_address + 0x124); - - /// address: 0x50200128 - /// Raw Interrupts - pub const INTR = @intToPtr(*volatile Mmio(32, packed struct { - SM0_RXNEMPTY: u1, - SM1_RXNEMPTY: u1, - SM2_RXNEMPTY: u1, - SM3_RXNEMPTY: u1, - SM0_TXNFULL: u1, - SM1_TXNFULL: u1, - SM2_TXNFULL: u1, - SM3_TXNFULL: u1, - SM0: u1, - SM1: u1, - SM2: u1, - SM3: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x128); - - /// address: 0x5020012c - /// Interrupt Enable for irq0 - pub const IRQ0_INTE = @intToPtr(*volatile Mmio(32, packed struct { - SM0_RXNEMPTY: u1, - SM1_RXNEMPTY: u1, - SM2_RXNEMPTY: u1, - SM3_RXNEMPTY: u1, - SM0_TXNFULL: u1, - SM1_TXNFULL: u1, - SM2_TXNFULL: u1, - SM3_TXNFULL: u1, - SM0: u1, - SM1: u1, - SM2: u1, - SM3: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x12c); - - /// address: 0x50200130 - /// Interrupt Force for irq0 - pub const IRQ0_INTF = @intToPtr(*volatile Mmio(32, packed struct { - SM0_RXNEMPTY: u1, - SM1_RXNEMPTY: u1, - SM2_RXNEMPTY: u1, - SM3_RXNEMPTY: u1, - SM0_TXNFULL: u1, - SM1_TXNFULL: u1, - SM2_TXNFULL: u1, - SM3_TXNFULL: u1, - SM0: u1, - SM1: u1, - SM2: u1, - SM3: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x130); - - /// address: 0x50200134 - /// Interrupt status after masking & forcing for irq0 - pub const IRQ0_INTS = @intToPtr(*volatile Mmio(32, packed struct { - SM0_RXNEMPTY: u1, - SM1_RXNEMPTY: u1, - SM2_RXNEMPTY: u1, - SM3_RXNEMPTY: u1, - SM0_TXNFULL: u1, - SM1_TXNFULL: u1, - SM2_TXNFULL: u1, - SM3_TXNFULL: u1, - SM0: u1, - SM1: u1, - SM2: u1, - SM3: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x134); - - /// address: 0x50200138 - /// Interrupt Enable for irq1 - pub const IRQ1_INTE = @intToPtr(*volatile Mmio(32, packed struct { - SM0_RXNEMPTY: u1, - SM1_RXNEMPTY: u1, - SM2_RXNEMPTY: u1, - SM3_RXNEMPTY: u1, - SM0_TXNFULL: u1, - SM1_TXNFULL: u1, - SM2_TXNFULL: u1, - SM3_TXNFULL: u1, - SM0: u1, - SM1: u1, - SM2: u1, - SM3: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x138); - - /// address: 0x5020013c - /// Interrupt Force for irq1 - pub const IRQ1_INTF = @intToPtr(*volatile Mmio(32, packed struct { - SM0_RXNEMPTY: u1, - SM1_RXNEMPTY: u1, - SM2_RXNEMPTY: u1, - SM3_RXNEMPTY: u1, - SM0_TXNFULL: u1, - SM1_TXNFULL: u1, - SM2_TXNFULL: u1, - SM3_TXNFULL: u1, - SM0: u1, - SM1: u1, - SM2: u1, - SM3: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x13c); - - /// address: 0x50200140 - /// Interrupt status after masking & forcing for irq1 - pub const IRQ1_INTS = @intToPtr(*volatile Mmio(32, packed struct { - SM0_RXNEMPTY: u1, - SM1_RXNEMPTY: u1, - SM2_RXNEMPTY: u1, - SM3_RXNEMPTY: u1, - SM0_TXNFULL: u1, - SM1_TXNFULL: u1, - SM2_TXNFULL: u1, - SM3_TXNFULL: u1, - SM0: u1, - SM1: u1, - SM2: u1, - SM3: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x140); - }; - pub const PIO1 = struct { - pub const base_address = 0x50300000; - - /// address: 0x50300000 - /// PIO control register - pub const CTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// Enable/disable each of the four state machines by writing 1/0 to each of these - /// four bits. When disabled, a state machine will cease executing instructions, - /// except those written directly to SMx_INSTR by the system. Multiple bits can be - /// set/cleared at once to run/halt multiple state machines simultaneously. - SM_ENABLE: u4, - /// Write 1 to instantly clear internal SM state which may be otherwise difficult to - /// access and will affect future execution.\n\n - /// Specifically, the following are cleared: input and output shift counters; the - /// contents of the input shift register; the delay counter; the waiting-on-IRQ - /// state; any stalled instruction written to SMx_INSTR or run by OUT/MOV EXEC; any - /// pin write left asserted due to OUT_STICKY. - SM_RESTART: u4, - /// Restart a state machine's clock divider from an initial phase of 0. Clock - /// dividers are free-running, so once started, their output (including fractional - /// jitter) is completely determined by the integer/fractional divisor configured in - /// SMx_CLKDIV. This means that, if multiple clock dividers with the same divisor - /// are restarted simultaneously, by writing multiple 1 bits to this field, the - /// execution clocks of those state machines will run in precise lockstep.\n\n - /// Note that setting/clearing SM_ENABLE does not stop the clock divider from - /// running, so once multiple state machines' clocks are synchronised, it is safe to - /// disable/reenable a state machine, whilst keeping the clock dividers in sync.\n\n - /// Note also that CLKDIV_RESTART can be written to whilst the state machine is - /// running, and this is useful to resynchronise clock dividers after the divisors - /// (SMx_CLKDIV) have been changed on-the-fly. - CLKDIV_RESTART: u4, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x0); - - /// address: 0x50300004 - /// FIFO status register - pub const FSTAT = @intToPtr(*volatile Mmio(32, packed struct { - /// State machine RX FIFO is full - RXFULL: u4, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - /// State machine RX FIFO is empty - RXEMPTY: u4, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// State machine TX FIFO is full - TXFULL: u4, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - /// State machine TX FIFO is empty - TXEMPTY: u4, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - }), base_address + 0x4); - - /// address: 0x50300008 - /// FIFO debug register - pub const FDEBUG = @intToPtr(*volatile Mmio(32, packed struct { - /// State machine has stalled on full RX FIFO during a blocking PUSH, or an IN with - /// autopush enabled. This flag is also set when a nonblocking PUSH to a full FIFO - /// took place, in which case the state machine has dropped data. Write 1 to clear. - RXSTALL: u4, - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - /// RX FIFO underflow (i.e. read-on-empty by the system) has occurred. Write 1 to - /// clear. Note that read-on-empty does not perturb the state of the FIFO in any - /// way, but the data returned by reading from an empty FIFO is undefined, so this - /// flag generally only becomes set due to some kind of software error. - RXUNDER: u4, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// TX FIFO overflow (i.e. write-on-full by the system) has occurred. Write 1 to - /// clear. Note that write-on-full does not alter the state or contents of the FIFO - /// in any way, but the data that the system attempted to write is dropped, so if - /// this flag is set, your software has quite likely dropped some data on the floor. - TXOVER: u4, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - /// State machine has stalled on empty TX FIFO during a blocking PULL, or an OUT - /// with autopull enabled. Write 1 to clear. - TXSTALL: u4, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - }), base_address + 0x8); - - /// address: 0x5030000c - /// FIFO levels - pub const FLEVEL = @intToPtr(*volatile Mmio(32, packed struct { - TX0: u4, - RX0: u4, - TX1: u4, - RX1: u4, - TX2: u4, - RX2: u4, - TX3: u4, - RX3: u4, - }), base_address + 0xc); - - /// address: 0x50300010 - /// Direct write access to the TX FIFO for this state machine. Each write pushes one - /// word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO - /// state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. - pub const TXF0 = @intToPtr(*volatile u32, base_address + 0x10); - - /// address: 0x50300014 - /// Direct write access to the TX FIFO for this state machine. Each write pushes one - /// word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO - /// state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. - pub const TXF1 = @intToPtr(*volatile u32, base_address + 0x14); - - /// address: 0x50300018 - /// Direct write access to the TX FIFO for this state machine. Each write pushes one - /// word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO - /// state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. - pub const TXF2 = @intToPtr(*volatile u32, base_address + 0x18); - - /// address: 0x5030001c - /// Direct write access to the TX FIFO for this state machine. Each write pushes one - /// word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO - /// state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. - pub const TXF3 = @intToPtr(*volatile u32, base_address + 0x1c); - - /// address: 0x50300020 - /// Direct read access to the RX FIFO for this state machine. Each read pops one - /// word from the FIFO. Attempting to read from an empty FIFO has no effect on the - /// FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The - /// data returned to the system on a read from an empty FIFO is undefined. - pub const RXF0 = @intToPtr(*volatile u32, base_address + 0x20); - - /// address: 0x50300024 - /// Direct read access to the RX FIFO for this state machine. Each read pops one - /// word from the FIFO. Attempting to read from an empty FIFO has no effect on the - /// FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The - /// data returned to the system on a read from an empty FIFO is undefined. - pub const RXF1 = @intToPtr(*volatile u32, base_address + 0x24); - - /// address: 0x50300028 - /// Direct read access to the RX FIFO for this state machine. Each read pops one - /// word from the FIFO. Attempting to read from an empty FIFO has no effect on the - /// FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The - /// data returned to the system on a read from an empty FIFO is undefined. - pub const RXF2 = @intToPtr(*volatile u32, base_address + 0x28); - - /// address: 0x5030002c - /// Direct read access to the RX FIFO for this state machine. Each read pops one - /// word from the FIFO. Attempting to read from an empty FIFO has no effect on the - /// FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The - /// data returned to the system on a read from an empty FIFO is undefined. - pub const RXF3 = @intToPtr(*volatile u32, base_address + 0x2c); - - /// address: 0x50300030 - /// State machine IRQ flags register. Write 1 to clear. There are 8 state machine - /// IRQ flags, which can be set, cleared, and waited on by the state machines. - /// There's no fixed association between flags and state machines -- any state - /// machine can use any flag.\n\n - /// Any of the 8 flags can be used for timing synchronisation between state - /// machines, using IRQ and WAIT instructions. The lower four of these flags are - /// also routed out to system-level interrupt requests, alongside FIFO status - /// interrupts -- see e.g. IRQ0_INTE. - pub const IRQ = @intToPtr(*volatile MmioInt(32, u8), base_address + 0x30); - - /// address: 0x50300034 - /// Writing a 1 to each of these bits will forcibly assert the corresponding IRQ. - /// Note this is different to the INTF register: writing here affects PIO internal - /// state. INTF just asserts the processor-facing IRQ signal for testing ISRs, and - /// is not visible to the state machines. - pub const IRQ_FORCE = @intToPtr(*volatile MmioInt(32, u8), base_address + 0x34); - - /// address: 0x50300038 - /// There is a 2-flipflop synchronizer on each GPIO input, which protects PIO logic - /// from metastabilities. This increases input delay, and for fast synchronous IO - /// (e.g. SPI) these synchronizers may need to be bypassed. Each bit in this - /// register corresponds to one GPIO.\n - /// 0 -> input is synchronized (default)\n - /// 1 -> synchronizer is bypassed\n - /// If in doubt, leave this register as all zeroes. - pub const INPUT_SYNC_BYPASS = @intToPtr(*volatile u32, base_address + 0x38); - - /// address: 0x5030003c - /// Read to sample the pad output values PIO is currently driving to the GPIOs. On - /// RP2040 there are 30 GPIOs, so the two most significant bits are hardwired to 0. - pub const DBG_PADOUT = @intToPtr(*volatile u32, base_address + 0x3c); - - /// address: 0x50300040 - /// Read to sample the pad output enables (direction) PIO is currently driving to - /// the GPIOs. On RP2040 there are 30 GPIOs, so the two most significant bits are - /// hardwired to 0. - pub const DBG_PADOE = @intToPtr(*volatile u32, base_address + 0x40); - - /// address: 0x50300044 - /// The PIO hardware has some free parameters that may vary between chip products.\n - /// These should be provided in the chip datasheet, but are also exposed here. - pub const DBG_CFGINFO = @intToPtr(*volatile Mmio(32, packed struct { - /// The depth of the state machine TX/RX FIFOs, measured in words.\n - /// Joining fifos via SHIFTCTRL_FJOIN gives one FIFO with double\n - /// this depth. - FIFO_DEPTH: u6, - reserved0: u1 = 0, - reserved1: u1 = 0, - /// The number of state machines this PIO instance is equipped with. - SM_COUNT: u4, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - /// The size of the instruction memory, measured in units of one instruction - IMEM_SIZE: u6, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - }), base_address + 0x44); - - /// address: 0x50300048 - /// Write-only access to instruction memory location 0 - pub const INSTR_MEM0 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x48); - - /// address: 0x5030004c - /// Write-only access to instruction memory location 1 - pub const INSTR_MEM1 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x4c); - - /// address: 0x50300050 - /// Write-only access to instruction memory location 2 - pub const INSTR_MEM2 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x50); - - /// address: 0x50300054 - /// Write-only access to instruction memory location 3 - pub const INSTR_MEM3 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x54); - - /// address: 0x50300058 - /// Write-only access to instruction memory location 4 - pub const INSTR_MEM4 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x58); - - /// address: 0x5030005c - /// Write-only access to instruction memory location 5 - pub const INSTR_MEM5 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x5c); - - /// address: 0x50300060 - /// Write-only access to instruction memory location 6 - pub const INSTR_MEM6 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x60); - - /// address: 0x50300064 - /// Write-only access to instruction memory location 7 - pub const INSTR_MEM7 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x64); - - /// address: 0x50300068 - /// Write-only access to instruction memory location 8 - pub const INSTR_MEM8 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x68); - - /// address: 0x5030006c - /// Write-only access to instruction memory location 9 - pub const INSTR_MEM9 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x6c); - - /// address: 0x50300070 - /// Write-only access to instruction memory location 10 - pub const INSTR_MEM10 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x70); - - /// address: 0x50300074 - /// Write-only access to instruction memory location 11 - pub const INSTR_MEM11 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x74); - - /// address: 0x50300078 - /// Write-only access to instruction memory location 12 - pub const INSTR_MEM12 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x78); - - /// address: 0x5030007c - /// Write-only access to instruction memory location 13 - pub const INSTR_MEM13 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x7c); - - /// address: 0x50300080 - /// Write-only access to instruction memory location 14 - pub const INSTR_MEM14 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x80); - - /// address: 0x50300084 - /// Write-only access to instruction memory location 15 - pub const INSTR_MEM15 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x84); - - /// address: 0x50300088 - /// Write-only access to instruction memory location 16 - pub const INSTR_MEM16 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x88); - - /// address: 0x5030008c - /// Write-only access to instruction memory location 17 - pub const INSTR_MEM17 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x8c); - - /// address: 0x50300090 - /// Write-only access to instruction memory location 18 - pub const INSTR_MEM18 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x90); - - /// address: 0x50300094 - /// Write-only access to instruction memory location 19 - pub const INSTR_MEM19 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x94); - - /// address: 0x50300098 - /// Write-only access to instruction memory location 20 - pub const INSTR_MEM20 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x98); - - /// address: 0x5030009c - /// Write-only access to instruction memory location 21 - pub const INSTR_MEM21 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x9c); - - /// address: 0x503000a0 - /// Write-only access to instruction memory location 22 - pub const INSTR_MEM22 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xa0); - - /// address: 0x503000a4 - /// Write-only access to instruction memory location 23 - pub const INSTR_MEM23 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xa4); - - /// address: 0x503000a8 - /// Write-only access to instruction memory location 24 - pub const INSTR_MEM24 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xa8); - - /// address: 0x503000ac - /// Write-only access to instruction memory location 25 - pub const INSTR_MEM25 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xac); - - /// address: 0x503000b0 - /// Write-only access to instruction memory location 26 - pub const INSTR_MEM26 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xb0); - - /// address: 0x503000b4 - /// Write-only access to instruction memory location 27 - pub const INSTR_MEM27 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xb4); - - /// address: 0x503000b8 - /// Write-only access to instruction memory location 28 - pub const INSTR_MEM28 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xb8); - - /// address: 0x503000bc - /// Write-only access to instruction memory location 29 - pub const INSTR_MEM29 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xbc); - - /// address: 0x503000c0 - /// Write-only access to instruction memory location 30 - pub const INSTR_MEM30 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xc0); - - /// address: 0x503000c4 - /// Write-only access to instruction memory location 31 - pub const INSTR_MEM31 = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xc4); - - /// address: 0x503000c8 - /// Clock divisor register for state machine 0\n - /// Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) - pub const SM0_CLKDIV = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// Fractional part of clock divisor - FRAC: u8, - /// Effective frequency is sysclk/(int + frac/256).\n - /// Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. - INT: u16, - }), base_address + 0xc8); - - /// address: 0x503000cc - /// Execution/behavioural settings for state machine 0 - pub const SM0_EXECCTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// Comparison level for the MOV x, STATUS instruction - STATUS_N: u4, - /// Comparison used for the MOV x, STATUS instruction. - STATUS_SEL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - /// After reaching wrap_top, execution is wrapped to this address. - WRAP_BOTTOM: u5, - /// After reaching this address, execution is wrapped to wrap_bottom.\n - /// If the instruction is a jump, and the jump condition is true, the jump takes - /// priority. - WRAP_TOP: u5, - /// Continuously assert the most recent OUT/SET to the pins - OUT_STICKY: u1, - /// If 1, use a bit of OUT data as an auxiliary write enable\n - /// When used in conjunction with OUT_STICKY, writes with an enable of 0 will\n - /// deassert the latest pin write. This can create useful masking/override - /// behaviour\n - /// due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) - INLINE_OUT_EN: u1, - /// Which data bit to use for inline OUT enable - OUT_EN_SEL: u5, - /// The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. - JMP_PIN: u5, - /// If 1, side-set data is asserted to pin directions, instead of pin values - SIDE_PINDIR: u1, - /// If 1, the MSB of the Delay/Side-set instruction field is used as side-set - /// enable, rather than a side-set data bit. This allows instructions to perform - /// side-set optionally, rather than on every instruction, but the maximum possible - /// side-set width is reduced from 5 to 4. Note that the value of - /// PINCTRL_SIDESET_COUNT is inclusive of this enable bit. - SIDE_EN: u1, - /// If 1, an instruction written to SMx_INSTR is stalled, and latched by the state - /// machine. Will clear to 0 once this instruction completes. - EXEC_STALLED: u1, - }), base_address + 0xcc); - - /// address: 0x503000d0 - /// Control behaviour of the input/output shift registers for state machine 0 - pub const SM0_SHIFTCTRL = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - /// Push automatically when the input shift register is filled, i.e. on an IN - /// instruction which causes the input shift counter to reach or exceed PUSH_THRESH. - AUTOPUSH: u1, - /// Pull automatically when the output shift register is emptied, i.e. on or - /// following an OUT instruction which causes the output shift counter to reach or - /// exceed PULL_THRESH. - AUTOPULL: u1, - /// 1 = shift input shift register to right (data enters from left). 0 = to left. - IN_SHIFTDIR: u1, - /// 1 = shift out of output shift register to right. 0 = to left. - OUT_SHIFTDIR: u1, - /// Number of bits shifted into ISR before autopush, or conditional push (PUSH - /// IFFULL), will take place.\n - /// Write 0 for value of 32. - PUSH_THRESH: u5, - /// Number of bits shifted out of OSR before autopull, or conditional pull (PULL - /// IFEMPTY), will take place.\n - /// Write 0 for value of 32. - PULL_THRESH: u5, - /// When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep.\n - /// RX FIFO is disabled as a result (always reads as both full and empty).\n - /// FIFOs are flushed when this bit is changed. - FJOIN_TX: u1, - /// When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep.\n - /// TX FIFO is disabled as a result (always reads as both full and empty).\n - /// FIFOs are flushed when this bit is changed. - FJOIN_RX: u1, - }), base_address + 0xd0); - - /// address: 0x503000d4 - /// Current instruction address of state machine 0 - pub const SM0_ADDR = @intToPtr(*volatile MmioInt(32, u5), base_address + 0xd4); - - /// address: 0x503000d8 - /// Read to see the instruction currently addressed by state machine 0's program - /// counter\n - /// Write to execute an instruction immediately (including jumps) and then resume - /// execution. - pub const SM0_INSTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xd8); - - /// address: 0x503000dc - /// State machine pin control - pub const SM0_PINCTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV - /// PINS instruction. The data written to this pin will always be the - /// least-significant bit of the OUT or MOV data. - OUT_BASE: u5, - /// The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS - /// instruction. The data written to this pin is the least-significant bit of the - /// SET data. - SET_BASE: u5, - /// The lowest-numbered pin that will be affected by a side-set operation. The MSBs - /// of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) - /// are used for side-set data, with the remaining LSBs used for delay. The - /// least-significant bit of the side-set portion is the bit written to this pin, - /// with more-significant bits written to higher-numbered pins. - SIDESET_BASE: u5, - /// The pin which is mapped to the least-significant bit of a state machine's IN - /// data bus. Higher-numbered pins are mapped to consecutively more-significant data - /// bits, with a modulo of 32 applied to pin number. - IN_BASE: u5, - /// The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. - /// In the range 0 to 32 inclusive. - OUT_COUNT: u6, - /// The number of pins asserted by a SET. In the range 0 to 5 inclusive. - SET_COUNT: u3, - /// The number of MSBs of the Delay/Side-set instruction field which are used for - /// side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, - /// no side-set) and maximum of 5 (all side-set, no delay). - SIDESET_COUNT: u3, - }), base_address + 0xdc); - - /// address: 0x503000e0 - /// Clock divisor register for state machine 1\n - /// Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) - pub const SM1_CLKDIV = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// Fractional part of clock divisor - FRAC: u8, - /// Effective frequency is sysclk/(int + frac/256).\n - /// Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. - INT: u16, - }), base_address + 0xe0); - - /// address: 0x503000e4 - /// Execution/behavioural settings for state machine 1 - pub const SM1_EXECCTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// Comparison level for the MOV x, STATUS instruction - STATUS_N: u4, - /// Comparison used for the MOV x, STATUS instruction. - STATUS_SEL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - /// After reaching wrap_top, execution is wrapped to this address. - WRAP_BOTTOM: u5, - /// After reaching this address, execution is wrapped to wrap_bottom.\n - /// If the instruction is a jump, and the jump condition is true, the jump takes - /// priority. - WRAP_TOP: u5, - /// Continuously assert the most recent OUT/SET to the pins - OUT_STICKY: u1, - /// If 1, use a bit of OUT data as an auxiliary write enable\n - /// When used in conjunction with OUT_STICKY, writes with an enable of 0 will\n - /// deassert the latest pin write. This can create useful masking/override - /// behaviour\n - /// due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) - INLINE_OUT_EN: u1, - /// Which data bit to use for inline OUT enable - OUT_EN_SEL: u5, - /// The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. - JMP_PIN: u5, - /// If 1, side-set data is asserted to pin directions, instead of pin values - SIDE_PINDIR: u1, - /// If 1, the MSB of the Delay/Side-set instruction field is used as side-set - /// enable, rather than a side-set data bit. This allows instructions to perform - /// side-set optionally, rather than on every instruction, but the maximum possible - /// side-set width is reduced from 5 to 4. Note that the value of - /// PINCTRL_SIDESET_COUNT is inclusive of this enable bit. - SIDE_EN: u1, - /// If 1, an instruction written to SMx_INSTR is stalled, and latched by the state - /// machine. Will clear to 0 once this instruction completes. - EXEC_STALLED: u1, - }), base_address + 0xe4); - - /// address: 0x503000e8 - /// Control behaviour of the input/output shift registers for state machine 1 - pub const SM1_SHIFTCTRL = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - /// Push automatically when the input shift register is filled, i.e. on an IN - /// instruction which causes the input shift counter to reach or exceed PUSH_THRESH. - AUTOPUSH: u1, - /// Pull automatically when the output shift register is emptied, i.e. on or - /// following an OUT instruction which causes the output shift counter to reach or - /// exceed PULL_THRESH. - AUTOPULL: u1, - /// 1 = shift input shift register to right (data enters from left). 0 = to left. - IN_SHIFTDIR: u1, - /// 1 = shift out of output shift register to right. 0 = to left. - OUT_SHIFTDIR: u1, - /// Number of bits shifted into ISR before autopush, or conditional push (PUSH - /// IFFULL), will take place.\n - /// Write 0 for value of 32. - PUSH_THRESH: u5, - /// Number of bits shifted out of OSR before autopull, or conditional pull (PULL - /// IFEMPTY), will take place.\n - /// Write 0 for value of 32. - PULL_THRESH: u5, - /// When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep.\n - /// RX FIFO is disabled as a result (always reads as both full and empty).\n - /// FIFOs are flushed when this bit is changed. - FJOIN_TX: u1, - /// When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep.\n - /// TX FIFO is disabled as a result (always reads as both full and empty).\n - /// FIFOs are flushed when this bit is changed. - FJOIN_RX: u1, - }), base_address + 0xe8); - - /// address: 0x503000ec - /// Current instruction address of state machine 1 - pub const SM1_ADDR = @intToPtr(*volatile MmioInt(32, u5), base_address + 0xec); - - /// address: 0x503000f0 - /// Read to see the instruction currently addressed by state machine 1's program - /// counter\n - /// Write to execute an instruction immediately (including jumps) and then resume - /// execution. - pub const SM1_INSTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0xf0); - - /// address: 0x503000f4 - /// State machine pin control - pub const SM1_PINCTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV - /// PINS instruction. The data written to this pin will always be the - /// least-significant bit of the OUT or MOV data. - OUT_BASE: u5, - /// The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS - /// instruction. The data written to this pin is the least-significant bit of the - /// SET data. - SET_BASE: u5, - /// The lowest-numbered pin that will be affected by a side-set operation. The MSBs - /// of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) - /// are used for side-set data, with the remaining LSBs used for delay. The - /// least-significant bit of the side-set portion is the bit written to this pin, - /// with more-significant bits written to higher-numbered pins. - SIDESET_BASE: u5, - /// The pin which is mapped to the least-significant bit of a state machine's IN - /// data bus. Higher-numbered pins are mapped to consecutively more-significant data - /// bits, with a modulo of 32 applied to pin number. - IN_BASE: u5, - /// The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. - /// In the range 0 to 32 inclusive. - OUT_COUNT: u6, - /// The number of pins asserted by a SET. In the range 0 to 5 inclusive. - SET_COUNT: u3, - /// The number of MSBs of the Delay/Side-set instruction field which are used for - /// side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, - /// no side-set) and maximum of 5 (all side-set, no delay). - SIDESET_COUNT: u3, - }), base_address + 0xf4); - - /// address: 0x503000f8 - /// Clock divisor register for state machine 2\n - /// Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) - pub const SM2_CLKDIV = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// Fractional part of clock divisor - FRAC: u8, - /// Effective frequency is sysclk/(int + frac/256).\n - /// Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. - INT: u16, - }), base_address + 0xf8); - - /// address: 0x503000fc - /// Execution/behavioural settings for state machine 2 - pub const SM2_EXECCTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// Comparison level for the MOV x, STATUS instruction - STATUS_N: u4, - /// Comparison used for the MOV x, STATUS instruction. - STATUS_SEL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - /// After reaching wrap_top, execution is wrapped to this address. - WRAP_BOTTOM: u5, - /// After reaching this address, execution is wrapped to wrap_bottom.\n - /// If the instruction is a jump, and the jump condition is true, the jump takes - /// priority. - WRAP_TOP: u5, - /// Continuously assert the most recent OUT/SET to the pins - OUT_STICKY: u1, - /// If 1, use a bit of OUT data as an auxiliary write enable\n - /// When used in conjunction with OUT_STICKY, writes with an enable of 0 will\n - /// deassert the latest pin write. This can create useful masking/override - /// behaviour\n - /// due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) - INLINE_OUT_EN: u1, - /// Which data bit to use for inline OUT enable - OUT_EN_SEL: u5, - /// The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. - JMP_PIN: u5, - /// If 1, side-set data is asserted to pin directions, instead of pin values - SIDE_PINDIR: u1, - /// If 1, the MSB of the Delay/Side-set instruction field is used as side-set - /// enable, rather than a side-set data bit. This allows instructions to perform - /// side-set optionally, rather than on every instruction, but the maximum possible - /// side-set width is reduced from 5 to 4. Note that the value of - /// PINCTRL_SIDESET_COUNT is inclusive of this enable bit. - SIDE_EN: u1, - /// If 1, an instruction written to SMx_INSTR is stalled, and latched by the state - /// machine. Will clear to 0 once this instruction completes. - EXEC_STALLED: u1, - }), base_address + 0xfc); - - /// address: 0x50300100 - /// Control behaviour of the input/output shift registers for state machine 2 - pub const SM2_SHIFTCTRL = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - /// Push automatically when the input shift register is filled, i.e. on an IN - /// instruction which causes the input shift counter to reach or exceed PUSH_THRESH. - AUTOPUSH: u1, - /// Pull automatically when the output shift register is emptied, i.e. on or - /// following an OUT instruction which causes the output shift counter to reach or - /// exceed PULL_THRESH. - AUTOPULL: u1, - /// 1 = shift input shift register to right (data enters from left). 0 = to left. - IN_SHIFTDIR: u1, - /// 1 = shift out of output shift register to right. 0 = to left. - OUT_SHIFTDIR: u1, - /// Number of bits shifted into ISR before autopush, or conditional push (PUSH - /// IFFULL), will take place.\n - /// Write 0 for value of 32. - PUSH_THRESH: u5, - /// Number of bits shifted out of OSR before autopull, or conditional pull (PULL - /// IFEMPTY), will take place.\n - /// Write 0 for value of 32. - PULL_THRESH: u5, - /// When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep.\n - /// RX FIFO is disabled as a result (always reads as both full and empty).\n - /// FIFOs are flushed when this bit is changed. - FJOIN_TX: u1, - /// When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep.\n - /// TX FIFO is disabled as a result (always reads as both full and empty).\n - /// FIFOs are flushed when this bit is changed. - FJOIN_RX: u1, - }), base_address + 0x100); - - /// address: 0x50300104 - /// Current instruction address of state machine 2 - pub const SM2_ADDR = @intToPtr(*volatile MmioInt(32, u5), base_address + 0x104); - - /// address: 0x50300108 - /// Read to see the instruction currently addressed by state machine 2's program - /// counter\n - /// Write to execute an instruction immediately (including jumps) and then resume - /// execution. - pub const SM2_INSTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x108); - - /// address: 0x5030010c - /// State machine pin control - pub const SM2_PINCTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV - /// PINS instruction. The data written to this pin will always be the - /// least-significant bit of the OUT or MOV data. - OUT_BASE: u5, - /// The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS - /// instruction. The data written to this pin is the least-significant bit of the - /// SET data. - SET_BASE: u5, - /// The lowest-numbered pin that will be affected by a side-set operation. The MSBs - /// of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) - /// are used for side-set data, with the remaining LSBs used for delay. The - /// least-significant bit of the side-set portion is the bit written to this pin, - /// with more-significant bits written to higher-numbered pins. - SIDESET_BASE: u5, - /// The pin which is mapped to the least-significant bit of a state machine's IN - /// data bus. Higher-numbered pins are mapped to consecutively more-significant data - /// bits, with a modulo of 32 applied to pin number. - IN_BASE: u5, - /// The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. - /// In the range 0 to 32 inclusive. - OUT_COUNT: u6, - /// The number of pins asserted by a SET. In the range 0 to 5 inclusive. - SET_COUNT: u3, - /// The number of MSBs of the Delay/Side-set instruction field which are used for - /// side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, - /// no side-set) and maximum of 5 (all side-set, no delay). - SIDESET_COUNT: u3, - }), base_address + 0x10c); - - /// address: 0x50300110 - /// Clock divisor register for state machine 3\n - /// Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) - pub const SM3_CLKDIV = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - /// Fractional part of clock divisor - FRAC: u8, - /// Effective frequency is sysclk/(int + frac/256).\n - /// Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. - INT: u16, - }), base_address + 0x110); - - /// address: 0x50300114 - /// Execution/behavioural settings for state machine 3 - pub const SM3_EXECCTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// Comparison level for the MOV x, STATUS instruction - STATUS_N: u4, - /// Comparison used for the MOV x, STATUS instruction. - STATUS_SEL: u1, - reserved0: u1 = 0, - reserved1: u1 = 0, - /// After reaching wrap_top, execution is wrapped to this address. - WRAP_BOTTOM: u5, - /// After reaching this address, execution is wrapped to wrap_bottom.\n - /// If the instruction is a jump, and the jump condition is true, the jump takes - /// priority. - WRAP_TOP: u5, - /// Continuously assert the most recent OUT/SET to the pins - OUT_STICKY: u1, - /// If 1, use a bit of OUT data as an auxiliary write enable\n - /// When used in conjunction with OUT_STICKY, writes with an enable of 0 will\n - /// deassert the latest pin write. This can create useful masking/override - /// behaviour\n - /// due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) - INLINE_OUT_EN: u1, - /// Which data bit to use for inline OUT enable - OUT_EN_SEL: u5, - /// The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. - JMP_PIN: u5, - /// If 1, side-set data is asserted to pin directions, instead of pin values - SIDE_PINDIR: u1, - /// If 1, the MSB of the Delay/Side-set instruction field is used as side-set - /// enable, rather than a side-set data bit. This allows instructions to perform - /// side-set optionally, rather than on every instruction, but the maximum possible - /// side-set width is reduced from 5 to 4. Note that the value of - /// PINCTRL_SIDESET_COUNT is inclusive of this enable bit. - SIDE_EN: u1, - /// If 1, an instruction written to SMx_INSTR is stalled, and latched by the state - /// machine. Will clear to 0 once this instruction completes. - EXEC_STALLED: u1, - }), base_address + 0x114); - - /// address: 0x50300118 - /// Control behaviour of the input/output shift registers for state machine 3 - pub const SM3_SHIFTCTRL = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - /// Push automatically when the input shift register is filled, i.e. on an IN - /// instruction which causes the input shift counter to reach or exceed PUSH_THRESH. - AUTOPUSH: u1, - /// Pull automatically when the output shift register is emptied, i.e. on or - /// following an OUT instruction which causes the output shift counter to reach or - /// exceed PULL_THRESH. - AUTOPULL: u1, - /// 1 = shift input shift register to right (data enters from left). 0 = to left. - IN_SHIFTDIR: u1, - /// 1 = shift out of output shift register to right. 0 = to left. - OUT_SHIFTDIR: u1, - /// Number of bits shifted into ISR before autopush, or conditional push (PUSH - /// IFFULL), will take place.\n - /// Write 0 for value of 32. - PUSH_THRESH: u5, - /// Number of bits shifted out of OSR before autopull, or conditional pull (PULL - /// IFEMPTY), will take place.\n - /// Write 0 for value of 32. - PULL_THRESH: u5, - /// When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep.\n - /// RX FIFO is disabled as a result (always reads as both full and empty).\n - /// FIFOs are flushed when this bit is changed. - FJOIN_TX: u1, - /// When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep.\n - /// TX FIFO is disabled as a result (always reads as both full and empty).\n - /// FIFOs are flushed when this bit is changed. - FJOIN_RX: u1, - }), base_address + 0x118); - - /// address: 0x5030011c - /// Current instruction address of state machine 3 - pub const SM3_ADDR = @intToPtr(*volatile MmioInt(32, u5), base_address + 0x11c); - - /// address: 0x50300120 - /// Read to see the instruction currently addressed by state machine 3's program - /// counter\n - /// Write to execute an instruction immediately (including jumps) and then resume - /// execution. - pub const SM3_INSTR = @intToPtr(*volatile MmioInt(32, u16), base_address + 0x120); - - /// address: 0x50300124 - /// State machine pin control - pub const SM3_PINCTRL = @intToPtr(*volatile Mmio(32, packed struct { - /// The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV - /// PINS instruction. The data written to this pin will always be the - /// least-significant bit of the OUT or MOV data. - OUT_BASE: u5, - /// The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS - /// instruction. The data written to this pin is the least-significant bit of the - /// SET data. - SET_BASE: u5, - /// The lowest-numbered pin that will be affected by a side-set operation. The MSBs - /// of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) - /// are used for side-set data, with the remaining LSBs used for delay. The - /// least-significant bit of the side-set portion is the bit written to this pin, - /// with more-significant bits written to higher-numbered pins. - SIDESET_BASE: u5, - /// The pin which is mapped to the least-significant bit of a state machine's IN - /// data bus. Higher-numbered pins are mapped to consecutively more-significant data - /// bits, with a modulo of 32 applied to pin number. - IN_BASE: u5, - /// The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. - /// In the range 0 to 32 inclusive. - OUT_COUNT: u6, - /// The number of pins asserted by a SET. In the range 0 to 5 inclusive. - SET_COUNT: u3, - /// The number of MSBs of the Delay/Side-set instruction field which are used for - /// side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, - /// no side-set) and maximum of 5 (all side-set, no delay). - SIDESET_COUNT: u3, - }), base_address + 0x124); - - /// address: 0x50300128 - /// Raw Interrupts - pub const INTR = @intToPtr(*volatile Mmio(32, packed struct { - SM0_RXNEMPTY: u1, - SM1_RXNEMPTY: u1, - SM2_RXNEMPTY: u1, - SM3_RXNEMPTY: u1, - SM0_TXNFULL: u1, - SM1_TXNFULL: u1, - SM2_TXNFULL: u1, - SM3_TXNFULL: u1, - SM0: u1, - SM1: u1, - SM2: u1, - SM3: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x128); - - /// address: 0x5030012c - /// Interrupt Enable for irq0 - pub const IRQ0_INTE = @intToPtr(*volatile Mmio(32, packed struct { - SM0_RXNEMPTY: u1, - SM1_RXNEMPTY: u1, - SM2_RXNEMPTY: u1, - SM3_RXNEMPTY: u1, - SM0_TXNFULL: u1, - SM1_TXNFULL: u1, - SM2_TXNFULL: u1, - SM3_TXNFULL: u1, - SM0: u1, - SM1: u1, - SM2: u1, - SM3: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x12c); - - /// address: 0x50300130 - /// Interrupt Force for irq0 - pub const IRQ0_INTF = @intToPtr(*volatile Mmio(32, packed struct { - SM0_RXNEMPTY: u1, - SM1_RXNEMPTY: u1, - SM2_RXNEMPTY: u1, - SM3_RXNEMPTY: u1, - SM0_TXNFULL: u1, - SM1_TXNFULL: u1, - SM2_TXNFULL: u1, - SM3_TXNFULL: u1, - SM0: u1, - SM1: u1, - SM2: u1, - SM3: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x130); - - /// address: 0x50300134 - /// Interrupt status after masking & forcing for irq0 - pub const IRQ0_INTS = @intToPtr(*volatile Mmio(32, packed struct { - SM0_RXNEMPTY: u1, - SM1_RXNEMPTY: u1, - SM2_RXNEMPTY: u1, - SM3_RXNEMPTY: u1, - SM0_TXNFULL: u1, - SM1_TXNFULL: u1, - SM2_TXNFULL: u1, - SM3_TXNFULL: u1, - SM0: u1, - SM1: u1, - SM2: u1, - SM3: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x134); - - /// address: 0x50300138 - /// Interrupt Enable for irq1 - pub const IRQ1_INTE = @intToPtr(*volatile Mmio(32, packed struct { - SM0_RXNEMPTY: u1, - SM1_RXNEMPTY: u1, - SM2_RXNEMPTY: u1, - SM3_RXNEMPTY: u1, - SM0_TXNFULL: u1, - SM1_TXNFULL: u1, - SM2_TXNFULL: u1, - SM3_TXNFULL: u1, - SM0: u1, - SM1: u1, - SM2: u1, - SM3: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x138); - - /// address: 0x5030013c - /// Interrupt Force for irq1 - pub const IRQ1_INTF = @intToPtr(*volatile Mmio(32, packed struct { - SM0_RXNEMPTY: u1, - SM1_RXNEMPTY: u1, - SM2_RXNEMPTY: u1, - SM3_RXNEMPTY: u1, - SM0_TXNFULL: u1, - SM1_TXNFULL: u1, - SM2_TXNFULL: u1, - SM3_TXNFULL: u1, - SM0: u1, - SM1: u1, - SM2: u1, - SM3: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x13c); - - /// address: 0x50300140 - /// Interrupt status after masking & forcing for irq1 - pub const IRQ1_INTS = @intToPtr(*volatile Mmio(32, packed struct { - SM0_RXNEMPTY: u1, - SM1_RXNEMPTY: u1, - SM2_RXNEMPTY: u1, - SM3_RXNEMPTY: u1, - SM0_TXNFULL: u1, - SM1_TXNFULL: u1, - SM2_TXNFULL: u1, - SM3_TXNFULL: u1, - SM0: u1, - SM1: u1, - SM2: u1, - SM3: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - }), base_address + 0x140); - }; - - /// Single-cycle IO block\n - /// Provides core-local and inter-core hardware for the two processors, with - /// single-cycle access. - pub const SIO = struct { - pub const base_address = 0xd0000000; - pub const version = "1"; - - /// address: 0xd0000000 - /// Processor core identifier\n - /// Value is 0 when read from processor core 0, and 1 when read from processor core - /// 1. - pub const CPUID = @intToPtr(*volatile u32, base_address + 0x0); - - /// address: 0xd0000004 - /// Input value for GPIO pins - pub const GPIO_IN = @intToPtr(*volatile MmioInt(32, u30), base_address + 0x4); - - /// address: 0xd0000008 - /// Input value for QSPI pins - pub const GPIO_HI_IN = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x8); - - /// address: 0xd0000010 - /// GPIO output value - pub const GPIO_OUT = @intToPtr(*volatile MmioInt(32, u30), base_address + 0x10); - - /// address: 0xd0000014 - /// GPIO output value set - pub const GPIO_OUT_SET = @intToPtr(*volatile MmioInt(32, u30), base_address + 0x14); - - /// address: 0xd0000018 - /// GPIO output value clear - pub const GPIO_OUT_CLR = @intToPtr(*volatile MmioInt(32, u30), base_address + 0x18); - - /// address: 0xd000001c - /// GPIO output value XOR - pub const GPIO_OUT_XOR = @intToPtr(*volatile MmioInt(32, u30), base_address + 0x1c); - - /// address: 0xd0000020 - /// GPIO output enable - pub const GPIO_OE = @intToPtr(*volatile MmioInt(32, u30), base_address + 0x20); - - /// address: 0xd0000024 - /// GPIO output enable set - pub const GPIO_OE_SET = @intToPtr(*volatile MmioInt(32, u30), base_address + 0x24); - - /// address: 0xd0000028 - /// GPIO output enable clear - pub const GPIO_OE_CLR = @intToPtr(*volatile MmioInt(32, u30), base_address + 0x28); - - /// address: 0xd000002c - /// GPIO output enable XOR - pub const GPIO_OE_XOR = @intToPtr(*volatile MmioInt(32, u30), base_address + 0x2c); - - /// address: 0xd0000030 - /// QSPI output value - pub const GPIO_HI_OUT = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x30); - - /// address: 0xd0000034 - /// QSPI output value set - pub const GPIO_HI_OUT_SET = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x34); - - /// address: 0xd0000038 - /// QSPI output value clear - pub const GPIO_HI_OUT_CLR = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x38); - - /// address: 0xd000003c - /// QSPI output value XOR - pub const GPIO_HI_OUT_XOR = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x3c); - - /// address: 0xd0000040 - /// QSPI output enable - pub const GPIO_HI_OE = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x40); - - /// address: 0xd0000044 - /// QSPI output enable set - pub const GPIO_HI_OE_SET = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x44); - - /// address: 0xd0000048 - /// QSPI output enable clear - pub const GPIO_HI_OE_CLR = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x48); - - /// address: 0xd000004c - /// QSPI output enable XOR - pub const GPIO_HI_OE_XOR = @intToPtr(*volatile MmioInt(32, u6), base_address + 0x4c); - - /// address: 0xd0000050 - /// Status register for inter-core FIFOs (mailboxes).\n - /// There is one FIFO in the core 0 -> core 1 direction, and one core 1 -> core 0. - /// Both are 32 bits wide and 8 words deep.\n - /// Core 0 can see the read side of the 1->0 FIFO (RX), and the write side of 0->1 - /// FIFO (TX).\n - /// Core 1 can see the read side of the 0->1 FIFO (RX), and the write side of 1->0 - /// FIFO (TX).\n - /// The SIO IRQ for each core is the logical OR of the VLD, WOF and ROE fields of - /// its FIFO_ST register. - pub const FIFO_ST = @intToPtr(*volatile Mmio(32, packed struct { - /// Value is 1 if this core's RX FIFO is not empty (i.e. if FIFO_RD is valid) - VLD: u1, - /// Value is 1 if this core's TX FIFO is not full (i.e. if FIFO_WR is ready for more - /// data) - RDY: u1, - /// Sticky flag indicating the TX FIFO was written when full. This write was ignored - /// by the FIFO. - WOF: u1, - /// Sticky flag indicating the RX FIFO was read when empty. This read was ignored by - /// the FIFO. - ROE: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - }), base_address + 0x50); - - /// address: 0xd0000054 - /// Write access to this core's TX FIFO - pub const FIFO_WR = @intToPtr(*volatile u32, base_address + 0x54); - - /// address: 0xd0000058 - /// Read access to this core's RX FIFO - pub const FIFO_RD = @intToPtr(*volatile u32, base_address + 0x58); - - /// address: 0xd000005c - /// Spinlock state\n - /// A bitmap containing the state of all 32 spinlocks (1=locked).\n - /// Mainly intended for debugging. - pub const SPINLOCK_ST = @intToPtr(*volatile u32, base_address + 0x5c); - - /// address: 0xd0000060 - /// Divider unsigned dividend\n - /// Write to the DIVIDEND operand of the divider, i.e. the p in `p / q`.\n - /// Any operand write starts a new calculation. The results appear in QUOTIENT, - /// REMAINDER.\n - /// UDIVIDEND/SDIVIDEND are aliases of the same internal register. The U alias - /// starts an\n - /// unsigned calculation, and the S alias starts a signed calculation. - pub const DIV_UDIVIDEND = @intToPtr(*volatile u32, base_address + 0x60); - - /// address: 0xd0000064 - /// Divider unsigned divisor\n - /// Write to the DIVISOR operand of the divider, i.e. the q in `p / q`.\n - /// Any operand write starts a new calculation. The results appear in QUOTIENT, - /// REMAINDER.\n - /// UDIVIDEND/SDIVIDEND are aliases of the same internal register. The U alias - /// starts an\n - /// unsigned calculation, and the S alias starts a signed calculation. - pub const DIV_UDIVISOR = @intToPtr(*volatile u32, base_address + 0x64); - - /// address: 0xd0000068 - /// Divider signed dividend\n - /// The same as UDIVIDEND, but starts a signed calculation, rather than unsigned. - pub const DIV_SDIVIDEND = @intToPtr(*volatile u32, base_address + 0x68); - - /// address: 0xd000006c - /// Divider signed divisor\n - /// The same as UDIVISOR, but starts a signed calculation, rather than unsigned. - pub const DIV_SDIVISOR = @intToPtr(*volatile u32, base_address + 0x6c); - - /// address: 0xd0000070 - /// Divider result quotient\n - /// The result of `DIVIDEND / DIVISOR` (division). Contents undefined while - /// CSR_READY is low.\n - /// For signed calculations, QUOTIENT is negative when the signs of DIVIDEND and - /// DIVISOR differ.\n - /// This register can be written to directly, for context save/restore purposes. - /// This halts any\n - /// in-progress calculation and sets the CSR_READY and CSR_DIRTY flags.\n - /// Reading from QUOTIENT clears the CSR_DIRTY flag, so should read results in the - /// order\n - /// REMAINDER, QUOTIENT if CSR_DIRTY is used. - pub const DIV_QUOTIENT = @intToPtr(*volatile u32, base_address + 0x70); - - /// address: 0xd0000074 - /// Divider result remainder\n - /// The result of `DIVIDEND % DIVISOR` (modulo). Contents undefined while CSR_READY - /// is low.\n - /// For signed calculations, REMAINDER is negative only when DIVIDEND is negative.\n - /// This register can be written to directly, for context save/restore purposes. - /// This halts any\n - /// in-progress calculation and sets the CSR_READY and CSR_DIRTY flags. - pub const DIV_REMAINDER = @intToPtr(*volatile u32, base_address + 0x74); - - /// address: 0xd0000078 - /// Control and status register for divider. - pub const DIV_CSR = @intToPtr(*volatile Mmio(32, packed struct { - /// Reads as 0 when a calculation is in progress, 1 otherwise.\n - /// Writing an operand (xDIVIDEND, xDIVISOR) will immediately start a new - /// calculation, no\n - /// matter if one is already in progress.\n - /// Writing to a result register will immediately terminate any in-progress - /// calculation\n - /// and set the READY and DIRTY flags. - READY: u1, - /// Changes to 1 when any register is written, and back to 0 when QUOTIENT is - /// read.\n - /// Software can use this flag to make save/restore more efficient (skip if not - /// DIRTY).\n - /// If the flag is used in this way, it's recommended to either read QUOTIENT - /// only,\n - /// or REMAINDER and then QUOTIENT, to prevent data loss on context switch. - DIRTY: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - padding11: u1 = 0, - padding12: u1 = 0, - padding13: u1 = 0, - padding14: u1 = 0, - padding15: u1 = 0, - padding16: u1 = 0, - padding17: u1 = 0, - padding18: u1 = 0, - padding19: u1 = 0, - padding20: u1 = 0, - padding21: u1 = 0, - padding22: u1 = 0, - padding23: u1 = 0, - padding24: u1 = 0, - padding25: u1 = 0, - padding26: u1 = 0, - padding27: u1 = 0, - padding28: u1 = 0, - padding29: u1 = 0, - }), base_address + 0x78); - - /// address: 0xd0000080 - /// Read/write access to accumulator 0 - pub const INTERP0_ACCUM0 = @intToPtr(*volatile u32, base_address + 0x80); - - /// address: 0xd0000084 - /// Read/write access to accumulator 1 - pub const INTERP0_ACCUM1 = @intToPtr(*volatile u32, base_address + 0x84); - - /// address: 0xd0000088 - /// Read/write access to BASE0 register. - pub const INTERP0_BASE0 = @intToPtr(*volatile u32, base_address + 0x88); - - /// address: 0xd000008c - /// Read/write access to BASE1 register. - pub const INTERP0_BASE1 = @intToPtr(*volatile u32, base_address + 0x8c); - - /// address: 0xd0000090 - /// Read/write access to BASE2 register. - pub const INTERP0_BASE2 = @intToPtr(*volatile u32, base_address + 0x90); - - /// address: 0xd0000094 - /// Read LANE0 result, and simultaneously write lane results to both accumulators - /// (POP). - pub const INTERP0_POP_LANE0 = @intToPtr(*volatile u32, base_address + 0x94); - - /// address: 0xd0000098 - /// Read LANE1 result, and simultaneously write lane results to both accumulators - /// (POP). - pub const INTERP0_POP_LANE1 = @intToPtr(*volatile u32, base_address + 0x98); - - /// address: 0xd000009c - /// Read FULL result, and simultaneously write lane results to both accumulators - /// (POP). - pub const INTERP0_POP_FULL = @intToPtr(*volatile u32, base_address + 0x9c); - - /// address: 0xd00000a0 - /// Read LANE0 result, without altering any internal state (PEEK). - pub const INTERP0_PEEK_LANE0 = @intToPtr(*volatile u32, base_address + 0xa0); - - /// address: 0xd00000a4 - /// Read LANE1 result, without altering any internal state (PEEK). - pub const INTERP0_PEEK_LANE1 = @intToPtr(*volatile u32, base_address + 0xa4); - - /// address: 0xd00000a8 - /// Read FULL result, without altering any internal state (PEEK). - pub const INTERP0_PEEK_FULL = @intToPtr(*volatile u32, base_address + 0xa8); - - /// address: 0xd00000ac - /// Control register for lane 0 - pub const INTERP0_CTRL_LANE0 = @intToPtr(*volatile Mmio(32, packed struct { - /// Logical right-shift applied to accumulator before masking - SHIFT: u5, - /// The least-significant bit allowed to pass by the mask (inclusive) - MASK_LSB: u5, - /// The most-significant bit allowed to pass by the mask (inclusive)\n - /// Setting MSB < LSB may cause chip to turn inside-out - MASK_MSB: u5, - /// If SIGNED is set, the shifted and masked accumulator value is sign-extended to - /// 32 bits\n - /// before adding to BASE0, and LANE0 PEEK/POP appear extended to 32 bits when read - /// by processor. - SIGNED: u1, - /// If 1, feed the opposite lane's accumulator into this lane's shift + mask - /// hardware.\n - /// Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the - /// shift+mask bypass) - CROSS_INPUT: u1, - /// If 1, feed the opposite lane's result into this lane's accumulator on POP. - CROSS_RESULT: u1, - /// If 1, mask + shift is bypassed for LANE0 result. This does not affect FULL - /// result. - ADD_RAW: u1, - /// ORed into bits 29:28 of the lane result presented to the processor on the bus.\n - /// No effect on the internal 32-bit datapath. Handy for using a lane to generate - /// sequence\n - /// of pointers into flash or SRAM. - FORCE_MSB: u2, - /// Only present on INTERP0 on each core. If BLEND mode is enabled:\n - /// - LANE1 result is a linear interpolation between BASE0 and BASE1, controlled\n - /// by the 8 LSBs of lane 1 shift and mask value (a fractional number between\n - /// 0 and 255/256ths)\n - /// - LANE0 result does not have BASE0 added (yields only the 8 LSBs of lane 1 - /// shift+mask value)\n - /// - FULL result does not have lane 1 shift+mask value added (BASE2 + lane 0 - /// shift+mask)\n - /// LANE1 SIGNED flag controls whether the interpolation is signed or unsigned. - BLEND: u1, - reserved0: u1 = 0, - /// Indicates if any masked-off MSBs in ACCUM0 are set. - OVERF0: u1, - /// Indicates if any masked-off MSBs in ACCUM1 are set. - OVERF1: u1, - /// Set if either OVERF0 or OVERF1 is set. - OVERF: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - }), base_address + 0xac); - - /// address: 0xd00000b0 - /// Control register for lane 1 - pub const INTERP0_CTRL_LANE1 = @intToPtr(*volatile Mmio(32, packed struct { - /// Logical right-shift applied to accumulator before masking - SHIFT: u5, - /// The least-significant bit allowed to pass by the mask (inclusive) - MASK_LSB: u5, - /// The most-significant bit allowed to pass by the mask (inclusive)\n - /// Setting MSB < LSB may cause chip to turn inside-out - MASK_MSB: u5, - /// If SIGNED is set, the shifted and masked accumulator value is sign-extended to - /// 32 bits\n - /// before adding to BASE1, and LANE1 PEEK/POP appear extended to 32 bits when read - /// by processor. - SIGNED: u1, - /// If 1, feed the opposite lane's accumulator into this lane's shift + mask - /// hardware.\n - /// Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the - /// shift+mask bypass) - CROSS_INPUT: u1, - /// If 1, feed the opposite lane's result into this lane's accumulator on POP. - CROSS_RESULT: u1, - /// If 1, mask + shift is bypassed for LANE1 result. This does not affect FULL - /// result. - ADD_RAW: u1, - /// ORed into bits 29:28 of the lane result presented to the processor on the bus.\n - /// No effect on the internal 32-bit datapath. Handy for using a lane to generate - /// sequence\n - /// of pointers into flash or SRAM. - FORCE_MSB: u2, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - }), base_address + 0xb0); - - /// address: 0xd00000b4 - /// Values written here are atomically added to ACCUM0\n - /// Reading yields lane 0's raw shift and mask value (BASE0 not added). - pub const INTERP0_ACCUM0_ADD = @intToPtr(*volatile MmioInt(32, u24), base_address + 0xb4); - - /// address: 0xd00000b8 - /// Values written here are atomically added to ACCUM1\n - /// Reading yields lane 1's raw shift and mask value (BASE1 not added). - pub const INTERP0_ACCUM1_ADD = @intToPtr(*volatile MmioInt(32, u24), base_address + 0xb8); - - /// address: 0xd00000bc - /// On write, the lower 16 bits go to BASE0, upper bits to BASE1 simultaneously.\n - /// Each half is sign-extended to 32 bits if that lane's SIGNED flag is set. - pub const INTERP0_BASE_1AND0 = @intToPtr(*volatile u32, base_address + 0xbc); - - /// address: 0xd00000c0 - /// Read/write access to accumulator 0 - pub const INTERP1_ACCUM0 = @intToPtr(*volatile u32, base_address + 0xc0); - - /// address: 0xd00000c4 - /// Read/write access to accumulator 1 - pub const INTERP1_ACCUM1 = @intToPtr(*volatile u32, base_address + 0xc4); - - /// address: 0xd00000c8 - /// Read/write access to BASE0 register. - pub const INTERP1_BASE0 = @intToPtr(*volatile u32, base_address + 0xc8); - - /// address: 0xd00000cc - /// Read/write access to BASE1 register. - pub const INTERP1_BASE1 = @intToPtr(*volatile u32, base_address + 0xcc); - - /// address: 0xd00000d0 - /// Read/write access to BASE2 register. - pub const INTERP1_BASE2 = @intToPtr(*volatile u32, base_address + 0xd0); - - /// address: 0xd00000d4 - /// Read LANE0 result, and simultaneously write lane results to both accumulators - /// (POP). - pub const INTERP1_POP_LANE0 = @intToPtr(*volatile u32, base_address + 0xd4); - - /// address: 0xd00000d8 - /// Read LANE1 result, and simultaneously write lane results to both accumulators - /// (POP). - pub const INTERP1_POP_LANE1 = @intToPtr(*volatile u32, base_address + 0xd8); - - /// address: 0xd00000dc - /// Read FULL result, and simultaneously write lane results to both accumulators - /// (POP). - pub const INTERP1_POP_FULL = @intToPtr(*volatile u32, base_address + 0xdc); - - /// address: 0xd00000e0 - /// Read LANE0 result, without altering any internal state (PEEK). - pub const INTERP1_PEEK_LANE0 = @intToPtr(*volatile u32, base_address + 0xe0); - - /// address: 0xd00000e4 - /// Read LANE1 result, without altering any internal state (PEEK). - pub const INTERP1_PEEK_LANE1 = @intToPtr(*volatile u32, base_address + 0xe4); - - /// address: 0xd00000e8 - /// Read FULL result, without altering any internal state (PEEK). - pub const INTERP1_PEEK_FULL = @intToPtr(*volatile u32, base_address + 0xe8); - - /// address: 0xd00000ec - /// Control register for lane 0 - pub const INTERP1_CTRL_LANE0 = @intToPtr(*volatile Mmio(32, packed struct { - /// Logical right-shift applied to accumulator before masking - SHIFT: u5, - /// The least-significant bit allowed to pass by the mask (inclusive) - MASK_LSB: u5, - /// The most-significant bit allowed to pass by the mask (inclusive)\n - /// Setting MSB < LSB may cause chip to turn inside-out - MASK_MSB: u5, - /// If SIGNED is set, the shifted and masked accumulator value is sign-extended to - /// 32 bits\n - /// before adding to BASE0, and LANE0 PEEK/POP appear extended to 32 bits when read - /// by processor. - SIGNED: u1, - /// If 1, feed the opposite lane's accumulator into this lane's shift + mask - /// hardware.\n - /// Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the - /// shift+mask bypass) - CROSS_INPUT: u1, - /// If 1, feed the opposite lane's result into this lane's accumulator on POP. - CROSS_RESULT: u1, - /// If 1, mask + shift is bypassed for LANE0 result. This does not affect FULL - /// result. - ADD_RAW: u1, - /// ORed into bits 29:28 of the lane result presented to the processor on the bus.\n - /// No effect on the internal 32-bit datapath. Handy for using a lane to generate - /// sequence\n - /// of pointers into flash or SRAM. - FORCE_MSB: u2, - reserved0: u1 = 0, - /// Only present on INTERP1 on each core. If CLAMP mode is enabled:\n - /// - LANE0 result is shifted and masked ACCUM0, clamped by a lower bound of\n - /// BASE0 and an upper bound of BASE1.\n - /// - Signedness of these comparisons is determined by LANE0_CTRL_SIGNED - CLAMP: u1, - /// Indicates if any masked-off MSBs in ACCUM0 are set. - OVERF0: u1, - /// Indicates if any masked-off MSBs in ACCUM1 are set. - OVERF1: u1, - /// Set if either OVERF0 or OVERF1 is set. - OVERF: u1, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - }), base_address + 0xec); - - /// address: 0xd00000f0 - /// Control register for lane 1 - pub const INTERP1_CTRL_LANE1 = @intToPtr(*volatile Mmio(32, packed struct { - /// Logical right-shift applied to accumulator before masking - SHIFT: u5, - /// The least-significant bit allowed to pass by the mask (inclusive) - MASK_LSB: u5, - /// The most-significant bit allowed to pass by the mask (inclusive)\n - /// Setting MSB < LSB may cause chip to turn inside-out - MASK_MSB: u5, - /// If SIGNED is set, the shifted and masked accumulator value is sign-extended to - /// 32 bits\n - /// before adding to BASE1, and LANE1 PEEK/POP appear extended to 32 bits when read - /// by processor. - SIGNED: u1, - /// If 1, feed the opposite lane's accumulator into this lane's shift + mask - /// hardware.\n - /// Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the - /// shift+mask bypass) - CROSS_INPUT: u1, - /// If 1, feed the opposite lane's result into this lane's accumulator on POP. - CROSS_RESULT: u1, - /// If 1, mask + shift is bypassed for LANE1 result. This does not affect FULL - /// result. - ADD_RAW: u1, - /// ORed into bits 29:28 of the lane result presented to the processor on the bus.\n - /// No effect on the internal 32-bit datapath. Handy for using a lane to generate - /// sequence\n - /// of pointers into flash or SRAM. - FORCE_MSB: u2, - padding0: u1 = 0, - padding1: u1 = 0, - padding2: u1 = 0, - padding3: u1 = 0, - padding4: u1 = 0, - padding5: u1 = 0, - padding6: u1 = 0, - padding7: u1 = 0, - padding8: u1 = 0, - padding9: u1 = 0, - padding10: u1 = 0, - }), base_address + 0xf0); - - /// address: 0xd00000f4 - /// Values written here are atomically added to ACCUM0\n - /// Reading yields lane 0's raw shift and mask value (BASE0 not added). - pub const INTERP1_ACCUM0_ADD = @intToPtr(*volatile MmioInt(32, u24), base_address + 0xf4); - - /// address: 0xd00000f8 - /// Values written here are atomically added to ACCUM1\n - /// Reading yields lane 1's raw shift and mask value (BASE1 not added). - pub const INTERP1_ACCUM1_ADD = @intToPtr(*volatile MmioInt(32, u24), base_address + 0xf8); - - /// address: 0xd00000fc - /// On write, the lower 16 bits go to BASE0, upper bits to BASE1 simultaneously.\n - /// Each half is sign-extended to 32 bits if that lane's SIGNED flag is set. - pub const INTERP1_BASE_1AND0 = @intToPtr(*volatile u32, base_address + 0xfc); - - /// address: 0xd0000100 - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK0 = @intToPtr(*volatile u32, base_address + 0x100); - - /// address: 0xd0000104 - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK1 = @intToPtr(*volatile u32, base_address + 0x104); - - /// address: 0xd0000108 - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK2 = @intToPtr(*volatile u32, base_address + 0x108); - - /// address: 0xd000010c - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK3 = @intToPtr(*volatile u32, base_address + 0x10c); - - /// address: 0xd0000110 - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK4 = @intToPtr(*volatile u32, base_address + 0x110); - - /// address: 0xd0000114 - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK5 = @intToPtr(*volatile u32, base_address + 0x114); - - /// address: 0xd0000118 - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK6 = @intToPtr(*volatile u32, base_address + 0x118); - - /// address: 0xd000011c - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK7 = @intToPtr(*volatile u32, base_address + 0x11c); - - /// address: 0xd0000120 - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK8 = @intToPtr(*volatile u32, base_address + 0x120); - - /// address: 0xd0000124 - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK9 = @intToPtr(*volatile u32, base_address + 0x124); - - /// address: 0xd0000128 - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK10 = @intToPtr(*volatile u32, base_address + 0x128); - - /// address: 0xd000012c - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK11 = @intToPtr(*volatile u32, base_address + 0x12c); - - /// address: 0xd0000130 - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK12 = @intToPtr(*volatile u32, base_address + 0x130); - - /// address: 0xd0000134 - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK13 = @intToPtr(*volatile u32, base_address + 0x134); - - /// address: 0xd0000138 - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK14 = @intToPtr(*volatile u32, base_address + 0x138); - - /// address: 0xd000013c - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK15 = @intToPtr(*volatile u32, base_address + 0x13c); - - /// address: 0xd0000140 - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK16 = @intToPtr(*volatile u32, base_address + 0x140); - - /// address: 0xd0000144 - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK17 = @intToPtr(*volatile u32, base_address + 0x144); - - /// address: 0xd0000148 - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK18 = @intToPtr(*volatile u32, base_address + 0x148); - - /// address: 0xd000014c - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK19 = @intToPtr(*volatile u32, base_address + 0x14c); - - /// address: 0xd0000150 - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK20 = @intToPtr(*volatile u32, base_address + 0x150); - - /// address: 0xd0000154 - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK21 = @intToPtr(*volatile u32, base_address + 0x154); - - /// address: 0xd0000158 - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK22 = @intToPtr(*volatile u32, base_address + 0x158); - - /// address: 0xd000015c - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK23 = @intToPtr(*volatile u32, base_address + 0x15c); - - /// address: 0xd0000160 - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK24 = @intToPtr(*volatile u32, base_address + 0x160); - - /// address: 0xd0000164 - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK25 = @intToPtr(*volatile u32, base_address + 0x164); - - /// address: 0xd0000168 - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK26 = @intToPtr(*volatile u32, base_address + 0x168); - - /// address: 0xd000016c - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK27 = @intToPtr(*volatile u32, base_address + 0x16c); - - /// address: 0xd0000170 - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK28 = @intToPtr(*volatile u32, base_address + 0x170); - - /// address: 0xd0000174 - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK29 = @intToPtr(*volatile u32, base_address + 0x174); - - /// address: 0xd0000178 - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK30 = @intToPtr(*volatile u32, base_address + 0x178); - - /// address: 0xd000017c - /// Reading from a spinlock address will:\n - /// - Return 0 if lock is already locked\n - /// - Otherwise return nonzero, and simultaneously claim the lock\n\n - /// Writing (any value) releases the lock.\n - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 - /// wins.\n - /// The value returned on success is 0x1 << lock number. - pub const SPINLOCK31 = @intToPtr(*volatile u32, base_address + 0x17c); - }; - pub const PPB = struct { - pub const base_address = 0xe0000000; - pub const version = "1"; - - /// address: 0xe000ed20 - /// System handlers are a special class of exception handler that can have their - /// priority set to any of the priority levels. Use the System Handler Priority - /// Register 3 to set the priority of PendSV and SysTick. - pub const SHPR3 = @intToPtr(*volatile Mmio(32, packed struct { - reserved0: u1 = 0, - reserved1: u1 = 0, - reserved2: u1 = 0, - reserved3: u1 = 0, - reserved4: u1 = 0, - reserved5: u1 = 0, - reserved6: u1 = 0, - reserved7: u1 = 0, - reserved8: u1 = 0, - reserved9: u1 = 0, - reserved10: u1 = 0, - reserved11: u1 = 0, - reserved12: u1 = 0, - reserved13: u1 = 0, - reserved14: u1 = 0, - reserved15: u1 = 0, - reserved16: u1 = 0, - reserved17: u1 = 0, - reserved18: u1 = 0, - reserved19: u1 = 0, - reserved20: u1 = 0, - reserved21: u1 = 0, - /// Priority of system handler 14, PendSV - PRI_14: u2, - reserved22: u1 = 0, - reserved23: u1 = 0, - reserved24: u1 = 0, - reserved25: u1 = 0, - reserved26: u1 = 0, - reserved27: u1 = 0, - /// Priority of system handler 15, SysTick - PRI_15: u2, - }), base_address + 0xed20); - }; -}; - -const std = @import("std"); - -pub fn mmio(addr: usize, comptime size: u8, comptime PackedT: type) *volatile Mmio(size, PackedT) { - return @intToPtr(*volatile Mmio(size, PackedT), addr); -} - -pub fn Mmio(comptime size: u8, comptime PackedT: type) type { - if ((size % 8) != 0) - @compileError("size must be divisible by 8!"); - - if (!std.math.isPowerOfTwo(size / 8)) - @compileError("size must encode a power of two number of bytes!"); - - const IntT = std.meta.Int(.unsigned, size); - - if (@sizeOf(PackedT) != (size / 8)) - @compileError(std.fmt.comptimePrint("IntT and PackedT must have the same size!, they are {} and {} bytes respectively", .{ size / 8, @sizeOf(PackedT) })); - - return extern struct { - const Self = @This(); - - raw: IntT, - - pub const underlying_type = PackedT; - - pub inline fn read(addr: *volatile Self) PackedT { - return @bitCast(PackedT, addr.raw); - } - - pub inline fn write(addr: *volatile Self, val: PackedT) void { - // This is a workaround for a compiler bug related to miscompilation - // If the tmp var is not used, result location will fuck things up - var tmp = @bitCast(IntT, val); - addr.raw = tmp; - } - - pub inline fn modify(addr: *volatile Self, fields: anytype) void { - var val = read(addr); - inline for (@typeInfo(@TypeOf(fields)).Struct.fields) |field| { - @field(val, field.name) = @field(fields, field.name); - } - write(addr, val); - } - - pub inline fn toggle(addr: *volatile Self, fields: anytype) void { - var val = read(addr); - inline for (@typeInfo(@TypeOf(fields)).Struct.fields) |field| { - @field(val, @tagName(field.default_value.?)) = !@field(val, @tagName(field.default_value.?)); - } - write(addr, val); - } - }; -} - -pub fn MmioInt(comptime size: u8, comptime T: type) type { - return extern struct { - const Self = @This(); - - raw: std.meta.Int(.unsigned, size), - - pub inline fn read(addr: *volatile Self) T { - return @truncate(T, addr.raw); - } - - pub inline fn modify(addr: *volatile Self, val: T) void { - const Int = std.meta.Int(.unsigned, size); - const mask = ~@as(Int, (1 << @bitSizeOf(T)) - 1); - - var tmp = addr.raw; - addr.raw = (tmp & mask) | val; - } - }; -} - -pub fn mmioInt(addr: usize, comptime size: usize, comptime T: type) *volatile MmioInt(size, T) { - return @intToPtr(*volatile MmioInt(size, T), addr); -} - -pub const InterruptVector = extern union { - C: *const fn () callconv(.C) void, - Naked: *const fn () callconv(.Naked) void, - // Interrupt is not supported on arm -}; - -const unhandled = InterruptVector{ - .C = struct { - fn tmp() callconv(.C) noreturn { - @panic("unhandled interrupt"); - } - }.tmp, -}; From 026af75f81fa6ad0b5033e9c3ed1565ec9369b92 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Mon, 20 Feb 2023 11:09:54 -0800 Subject: [PATCH 29/74] update microzig (#22) Co-authored-by: mattnite --- deps/microzig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/microzig b/deps/microzig index 2d0ee5c..4bb6561 160000 --- a/deps/microzig +++ b/deps/microzig @@ -1 +1 @@ -Subproject commit 2d0ee5c4731de1d81afb9c8e08ba4e8c2c2cfbf3 +Subproject commit 4bb65617a47dc30282ffe340cc45d202b973650b From 58d73abc08952aac55301bd1ac66af49a3022711 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Fri, 24 Feb 2023 09:12:22 -0800 Subject: [PATCH 30/74] Update microzig (#24) * update microzig * update paths and for loops --------- Co-authored-by: mattnite --- build.zig | 2 +- deps/microzig | 2 +- src/boards.zig | 2 +- src/chips.zig | 2 +- src/hal/adc.zig | 4 ++-- src/hal/pins.zig | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build.zig b/build.zig index 51bb874..a0ed86c 100644 --- a/build.zig +++ b/build.zig @@ -3,7 +3,7 @@ const Builder = std.build.Builder; const Pkg = std.build.Pkg; const comptimePrint = std.fmt.comptimePrint; -pub const microzig = @import("deps/microzig/src/main.zig"); +pub const microzig = @import("deps/microzig/build.zig"); const chips = @import("src/chips.zig"); const boards = @import("src/boards.zig"); diff --git a/deps/microzig b/deps/microzig index 4bb6561..11214ed 160000 --- a/deps/microzig +++ b/deps/microzig @@ -1 +1 @@ -Subproject commit 4bb65617a47dc30282ffe340cc45d202b973650b +Subproject commit 11214ed8ba05e380a516beef3f3f594571a1c732 diff --git a/src/boards.zig b/src/boards.zig index 4329182..ebbf0d8 100644 --- a/src/boards.zig +++ b/src/boards.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const microzig = @import("../deps/microzig/src/main.zig"); +const microzig = @import("../deps/microzig/build.zig"); const chips = @import("chips.zig"); fn root_dir() []const u8 { diff --git a/src/chips.zig b/src/chips.zig index 5e0d39a..8363cea 100644 --- a/src/chips.zig +++ b/src/chips.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const microzig = @import("../deps/microzig/src/main.zig"); +const microzig = @import("../deps/microzig/build.zig"); fn root_dir() []const u8 { return std.fs.path.dirname(@src().file) orelse "."; diff --git a/src/hal/adc.zig b/src/hal/adc.zig index 1746ccc..ba293b0 100644 --- a/src/hal/adc.zig +++ b/src/hal/adc.zig @@ -83,8 +83,8 @@ pub const InputMask = InputMask: { var fields: [enum_fields.len]std.builtin.Type.StructField = undefined; const default_value: u1 = 0; - for (enum_fields) |enum_field, i| - fields[i] = std.builtin.Type.StructField{ + for (enum_fields, &fields) |enum_field, *field| + field = std.builtin.Type.StructField{ .name = enum_field.name, .field_type = u1, .default_value = &default_value, diff --git a/src/hal/pins.zig b/src/hal/pins.zig index 24b9d7a..7a204b8 100644 --- a/src/hal/pins.zig +++ b/src/hal/pins.zig @@ -237,7 +237,7 @@ pub const Function = enum { fn all() [30]u1 { var ret: [30]u1 = undefined; - for (ret) |*elem| + for (&ret) |*elem| elem.* = 1; return ret; From 3b129e1ca5ce7317e29f50cb1beaf67ce6281122 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Tue, 28 Feb 2023 01:32:34 -0800 Subject: [PATCH 31/74] Update microzig (#26) * update microzig * update to new api --------- Co-authored-by: mattnite --- build.zig | 45 ++++++++++++++++++++++----------------------- deps/microzig | 2 +- examples/adc.zig | 4 +++- examples/uart.zig | 6 ++++-- 4 files changed, 30 insertions(+), 27 deletions(-) diff --git a/build.zig b/build.zig index a0ed86c..5da87f7 100644 --- a/build.zig +++ b/build.zig @@ -2,11 +2,12 @@ const std = @import("std"); const Builder = std.build.Builder; const Pkg = std.build.Pkg; const comptimePrint = std.fmt.comptimePrint; +const FileSource = std.build.FileSource; pub const microzig = @import("deps/microzig/build.zig"); -const chips = @import("src/chips.zig"); -const boards = @import("src/boards.zig"); +pub const chips = @import("src/chips.zig"); +pub const boards = @import("src/boards.zig"); const linkerscript_path = root() ++ "rp2040.ld"; @@ -14,24 +15,23 @@ pub const BuildOptions = struct { optimize: std.builtin.OptimizeMode, }; +pub const PicoExecutableOptions = struct { + name: []const u8, + source_file: FileSource, + optimize: std.builtin.OptimizeMode = .Debug, +}; + pub fn addPiPicoExecutable( builder: *Builder, - name: []const u8, - source: []const u8, - options: BuildOptions, + opts: PicoExecutableOptions, ) *microzig.EmbeddedExecutable { - const ret = microzig.addEmbeddedExecutable( - builder, - name, - source, - .{ .board = boards.raspberry_pi_pico }, - .{ - .optimize = options.optimize, - }, - ); - ret.inner.setLinkerScriptPath(.{ .path = linkerscript_path }); - - return ret; + return microzig.addEmbeddedExecutable(builder, .{ + .name = opts.name, + .source_file = opts.source_file, + .backing = .{ .board = boards.raspberry_pi_pico }, + .optimize = opts.optimize, + .linkerscript_source_file = .{ .path = linkerscript_path }, + }); } // this build script is mostly for testing and verification of this @@ -61,12 +61,11 @@ pub const Examples = struct { inline for (@typeInfo(Examples).Struct.fields) |field| { const path = comptime root() ++ "examples/" ++ field.name ++ ".zig"; - @field(ret, field.name) = addPiPicoExecutable( - b, - field.name, - path, - .{ .optimize = optimize }, - ); + @field(ret, field.name) = addPiPicoExecutable(b, .{ + .name = field.name, + .source_file = .{ .path = path }, + .optimize = optimize, + }); } return ret; diff --git a/deps/microzig b/deps/microzig index 11214ed..b6fc3ab 160000 --- a/deps/microzig +++ b/deps/microzig @@ -1 +1 @@ -Subproject commit 11214ed8ba05e380a516beef3f3f594571a1c732 +Subproject commit b6fc3abbf7a91cb0cdafc7843ac7e6c26042ff84 diff --git a/examples/adc.zig b/examples/adc.zig index 9800e91..5d8f0c3 100644 --- a/examples/adc.zig +++ b/examples/adc.zig @@ -12,7 +12,9 @@ const baud_rate = 115200; const uart_tx_pin = 0; const uart_rx_pin = 1; -pub const log = rp2040.uart.log; +pub const std_options = struct { + pub const logFn = rp2040.uart.log; +}; pub fn init() void { rp2040.clock_config.apply(); diff --git a/examples/uart.zig b/examples/uart.zig index 6eb0864..57cf1c4 100644 --- a/examples/uart.zig +++ b/examples/uart.zig @@ -18,8 +18,10 @@ pub fn panic(message: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noretu while (true) {} } -pub const log_level = .debug; -pub const log = rp2040.uart.log; +pub const std_options = struct { + pub const log_level = .debug; + pub const logFn = rp2040.uart.log; +}; pub fn main() !void { gpio.reset(); From 9a47a0183e58d68ff3889147c99e0789292bdf7f Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Tue, 28 Feb 2023 01:47:34 -0800 Subject: [PATCH 32/74] update microzig (#27) Co-authored-by: mattnite --- deps/microzig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/microzig b/deps/microzig index b6fc3ab..08e7d5b 160000 --- a/deps/microzig +++ b/deps/microzig @@ -1 +1 @@ -Subproject commit b6fc3abbf7a91cb0cdafc7843ac7e6c26042ff84 +Subproject commit 08e7d5b01a8ca6a53e3892f763507f1ff3b07725 From 3cef64600605de66e36a37ec58cb2053c7314243 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Sun, 19 Mar 2023 16:32:34 -0700 Subject: [PATCH 33/74] update microzig (#29) --- deps/microzig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/microzig b/deps/microzig index 08e7d5b..6f5b726 160000 --- a/deps/microzig +++ b/deps/microzig @@ -1 +1 @@ -Subproject commit 08e7d5b01a8ca6a53e3892f763507f1ff3b07725 +Subproject commit 6f5b7268f68f001144bd5ebacc0c0203a7a50fde From 160bee73e0774ecf44e2d6a0f8494f48b0c8d0f2 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Wed, 22 Mar 2023 00:56:30 -0700 Subject: [PATCH 34/74] update microzig (#30) Co-authored-by: mattnite --- deps/microzig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/microzig b/deps/microzig index 6f5b726..dabc932 160000 --- a/deps/microzig +++ b/deps/microzig @@ -1 +1 @@ -Subproject commit 6f5b7268f68f001144bd5ebacc0c0203a7a50fde +Subproject commit dabc9325cdee394ff66e28c91803cb814954b157 From 7c781dc37730b448d78f5621b965b74bc3112680 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Thu, 23 Mar 2023 08:28:01 -0700 Subject: [PATCH 35/74] Update microzig (#31) * update microzig * add zig version --------- Co-authored-by: mattnite --- README.adoc | 7 +++++++ deps/microzig | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 README.adoc diff --git a/README.adoc b/README.adoc new file mode 100644 index 0000000..171c62d --- /dev/null +++ b/README.adoc @@ -0,0 +1,7 @@ += raspberrypi-rp2040 + +HAL and register definitions for the RP2040. + +== What version of Zig to use + +Right now we are following [master](https://ziglang.org/download/), but once 0.11.0 is released, we will be switching to the latest stable version of Zig. diff --git a/deps/microzig b/deps/microzig index dabc932..5b0176e 160000 --- a/deps/microzig +++ b/deps/microzig @@ -1 +1 @@ -Subproject commit dabc9325cdee394ff66e28c91803cb814954b157 +Subproject commit 5b0176e97781a77420be309b6505dc582713a2a5 From 623a7f24eecad9e5ef0bf3aab50d9671233380eb Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Thu, 23 Mar 2023 08:42:36 -0700 Subject: [PATCH 36/74] update microzig (#32) Co-authored-by: mattnite --- deps/microzig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/microzig b/deps/microzig index 5b0176e..ceaa9dd 160000 --- a/deps/microzig +++ b/deps/microzig @@ -1 +1 @@ -Subproject commit 5b0176e97781a77420be309b6505dc582713a2a5 +Subproject commit ceaa9ddcb080d0687ce2109f23db7db376ac911e From a4de9d2f3e332d6f49c192b8cbdf96cfb383cd8c Mon Sep 17 00:00:00 2001 From: Vlad Panazan Date: Thu, 23 Mar 2023 20:37:48 +0200 Subject: [PATCH 37/74] add SPI hal (#33) --- build.zig | 1 + examples/spi_master.zig | 25 +++++++ src/hal.zig | 1 + src/hal/spi.zig | 159 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 186 insertions(+) create mode 100644 examples/spi_master.zig create mode 100644 src/hal/spi.zig diff --git a/build.zig b/build.zig index 5da87f7..b1225d2 100644 --- a/build.zig +++ b/build.zig @@ -53,6 +53,7 @@ pub const Examples = struct { blinky_core1: *microzig.EmbeddedExecutable, gpio_clk: *microzig.EmbeddedExecutable, pwm: *microzig.EmbeddedExecutable, + spi_master: *microzig.EmbeddedExecutable, uart: *microzig.EmbeddedExecutable, //uart_pins: microzig.EmbeddedExecutable, diff --git a/examples/spi_master.zig b/examples/spi_master.zig new file mode 100644 index 0000000..ba1c0c2 --- /dev/null +++ b/examples/spi_master.zig @@ -0,0 +1,25 @@ +const std = @import("std"); +const microzig = @import("microzig"); + +const rp2040 = microzig.hal; +const time = rp2040.time; +const gpio = rp2040.gpio; +const clocks = rp2040.clocks; +const peripherals = microzig.chip.peripherals; + +const BUF_LEN = 0x100; + +// Communicate with another RP2040 over spi +// Slave implementation: https://github.com/raspberrypi/pico-examples/blob/master/spi/spi_master_slave/spi_slave/spi_slave.c +pub fn main() !void { + const spi = rp2040.spi.SPI.init(0, .{ + .clock_config = rp2040.clock_config, + }); + var out_buf: [BUF_LEN]u8 = .{ 0xAA, 0xBB, 0xCC, 0xDD } ** (BUF_LEN / 4); + var in_buf: [BUF_LEN]u8 = undefined; + + while (true) { + _ = spi.transceive(&out_buf, &in_buf); + time.sleep_ms(1 * 1000); + } +} diff --git a/src/hal.zig b/src/hal.zig index 21323de..568c691 100644 --- a/src/hal.zig +++ b/src/hal.zig @@ -9,6 +9,7 @@ pub const multicore = @import("hal/multicore.zig"); pub const time = @import("hal/time.zig"); pub const uart = @import("hal/uart.zig"); pub const pwm = @import("hal/pwm.zig"); +pub const spi = @import("hal/spi.zig"); pub const resets = @import("hal/resets.zig"); pub const irq = @import("hal/irq.zig"); diff --git a/src/hal/spi.zig b/src/hal/spi.zig new file mode 100644 index 0000000..ea96f40 --- /dev/null +++ b/src/hal/spi.zig @@ -0,0 +1,159 @@ +const std = @import("std"); +const microzig = @import("microzig"); +const peripherals = microzig.chip.peripherals; +const SPI0 = peripherals.SPI0; +const SPI1 = peripherals.SPI1; + +const gpio = @import("gpio.zig"); +const clocks = @import("clocks.zig"); +const resets = @import("resets.zig"); +const time = @import("time.zig"); + +const SpiRegs = microzig.chip.types.peripherals.SPI0; + +pub const Config = struct { + clock_config: clocks.GlobalConfiguration, + tx_pin: ?u32 = 19, + rx_pin: ?u32 = 16, + sck_pin: ?u32 = 18, + csn_pin: ?u32 = 17, + baud_rate: u32 = 1000 * 1000, +}; + +pub const SPI = enum { + spi0, + spi1, + + fn get_regs(spi: SPI) *volatile SpiRegs { + return switch (spi) { + .spi0 => SPI0, + .spi1 => SPI1, + }; + } + + pub fn reset(spi: SPI) void { + switch (spi) { + .spi0 => resets.reset(&.{.spi0}), + .spi1 => resets.reset(&.{.spi1}), + } + } + + pub fn init(comptime id: u32, comptime config: Config) SPI { + const spi: SPI = switch (id) { + 0 => .spi0, + 1 => .spi1, + else => @compileError("there is only spi0 and spi1"), + }; + + spi.reset(); + + const peri_freq = config.clock_config.peri.?.output_freq; + _ = spi.set_baudrate(config.baud_rate, peri_freq); + + const spi_regs = spi.get_regs(); + + // set fromat + spi_regs.SSPCR0.modify(.{ + .DSS = 0b0111, // 8 bits + .SPO = 0, + .SPH = 0, + }); + + // Always enable DREQ signals -- harmless if DMA is not listening + spi_regs.SSPDMACR.modify(.{ + .TXDMAE = 1, + .RXDMAE = 1, + }); + + // Finally enable the SPI + spi_regs.SSPCR1.modify(.{ + .SSE = 1, + }); + + if (config.tx_pin) |pin| gpio.set_function(pin, .spi); + if (config.rx_pin) |pin| gpio.set_function(pin, .spi); + if (config.sck_pin) |pin| gpio.set_function(pin, .spi); + if (config.csn_pin) |pin| gpio.set_function(pin, .spi); + + return spi; + } + + pub fn is_writable(spi: SPI) bool { + return spi.get_regs().SSPSR.read().TNF == 1; + } + + pub fn is_readable(spi: SPI) bool { + return spi.get_regs().SSPSR.read().RNE == 1; + } + pub fn transceive(spi: SPI, src: []const u8, dst: []u8) usize { + const spi_regs = spi.get_regs(); + std.debug.assert(src.len == dst.len); + const fifo_depth = 8; + var rx_remaining = dst.len; + var tx_remaining = src.len; + + while (rx_remaining > 0 or tx_remaining > 0) { + if (tx_remaining > 0 and spi.is_writable() and rx_remaining < tx_remaining + fifo_depth) { + spi_regs.SSPDR.write_raw(src[src.len - tx_remaining]); + tx_remaining -= 1; + } + if (rx_remaining > 0 and spi.is_readable()) { + const bytes = std.mem.asBytes(&spi_regs.SSPDR.read().DATA); + dst[dst.len - rx_remaining] = bytes[0]; + rx_remaining -= 1; + } + } + + return src.len; + } + // Write len bytes directly from src to the SPI, and discard any data received back + pub fn write(spi: SPI, src: []const u8) usize { + const spi_regs = spi.get_regs(); + // Write to TX FIFO whilst ignoring RX, then clean up afterward. When RX + // is full, PL022 inhibits RX pushes, and sets a sticky flag on + // push-on-full, but continues shifting. Safe if SSPIMSC_RORIM is not set. + for (src) |s| { + while (!spi.is_writable()) { + std.log.debug("SPI not writable!", .{}); + } + spi_regs.SSPDR.write_raw(s); + } + // Drain RX FIFO, then wait for shifting to finish (which may be *after* + // TX FIFO drains), then drain RX FIFO again + while (spi.is_readable()) { + _ = spi_regs.SSPDR.raw; + } + while (spi.get_regs().SSPSR.read().BSY == 1) { + std.log.debug("SPI busy!", .{}); + } + while (spi.is_readable()) { + _ = spi_regs.SSPDR.raw; + } + // Don't leave overrun flag set + peripherals.SPI0.SSPICR.modify(.{ .RORIC = 1 }); + return src.len; + } + + fn set_baudrate(spi: SPI, baudrate: u32, freq_in: u32) u64 { + const spi_regs = spi.get_regs(); + // Find smallest prescale value which puts output frequency in range of + // post-divide. Prescale is an even number from 2 to 254 inclusive. + var prescale: u64 = 2; + while (prescale <= 254) : (prescale += 2) { + if (freq_in < (prescale + 2) * 256 * baudrate) break; + } + std.debug.assert(prescale <= 254); //Freq too low + // Find largest post-divide which makes output <= baudrate. Post-divide is + // an integer in the range 1 to 256 inclusive. + + var postdiv: u64 = 256; + while (postdiv > 1) : (postdiv -= 1) { + if (freq_in / (prescale * (postdiv - 1)) > baudrate) break; + } + spi_regs.SSPCPSR.modify(.{ .CPSDVSR = @intCast(u8, prescale) }); + spi_regs.SSPCR0.modify(.{ .SCR = @intCast(u8, postdiv - 1) }); + + // Return the frequency we were able to achieve + return freq_in / (prescale * postdiv); + } +}; From f250134e2f0a142c26a0e34a95ed4a5140790312 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Wed, 5 Apr 2023 17:20:16 -0700 Subject: [PATCH 38/74] update microzig (#34) Co-authored-by: mattnite --- deps/microzig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/microzig b/deps/microzig index ceaa9dd..23482a6 160000 --- a/deps/microzig +++ b/deps/microzig @@ -1 +1 @@ -Subproject commit ceaa9ddcb080d0687ce2109f23db7db376ac911e +Subproject commit 23482a6986252e0eeff54a04abc0aac8a08d25d7 From 20e4c9f8f631d6525d40644142abd0ea773a8a0f Mon Sep 17 00:00:00 2001 From: David Sugar Date: Thu, 6 Apr 2023 02:29:08 +0200 Subject: [PATCH 39/74] Flash from user code (#35) * support for a subset of the bootrom functions added: fast bit count/ manipulation functions (tested), fast bulk memory fill/ copy functions (tested), flash access functions (NOT tested), debugging support functions (not implemented), miscellaneous functions (not implemented). * added support for erasing and programming flash from user code. between the first and last call in a programming sequence, the SSI is not in a state where it can handle XIP accesses, so the code that calls the intervening functions must be located in SRAM. this is why I added the time_critical section to rp2040.ld (maybe one should create a dedicated section in ram that is rwx and keep data rwNx). * flash_program.zig example added --- build.zig | 1 + examples/flash_program.zig | 82 +++++++++++ rp2040.ld | 3 +- src/hal.zig | 2 + src/hal/flash.zig | 81 +++++++++++ src/hal/rom.zig | 269 +++++++++++++++++++++++++++++++++++++ 6 files changed, 437 insertions(+), 1 deletion(-) create mode 100644 examples/flash_program.zig create mode 100644 src/hal/flash.zig create mode 100644 src/hal/rom.zig diff --git a/build.zig b/build.zig index b1225d2..5144b36 100644 --- a/build.zig +++ b/build.zig @@ -56,6 +56,7 @@ pub const Examples = struct { spi_master: *microzig.EmbeddedExecutable, uart: *microzig.EmbeddedExecutable, //uart_pins: microzig.EmbeddedExecutable, + flash_program: *microzig.EmbeddedExecutable, pub fn init(b: *Builder, optimize: std.builtin.OptimizeMode) Examples { var ret: Examples = undefined; diff --git a/examples/flash_program.zig b/examples/flash_program.zig new file mode 100644 index 0000000..2fc5cc0 --- /dev/null +++ b/examples/flash_program.zig @@ -0,0 +1,82 @@ +const std = @import("std"); +const microzig = @import("microzig"); + +const rp2040 = microzig.hal; +const flash = rp2040.flash; +const time = rp2040.time; +const gpio = rp2040.gpio; +const clocks = rp2040.clocks; + +const led = 25; +const uart_id = 0; +const baud_rate = 115200; +const uart_tx_pin = 0; +const uart_rx_pin = 1; + +const flash_target_offset: u32 = 256 * 1024; +const flash_target_contents = @intToPtr([*]const u8, rp2040.flash.XIP_BASE + flash_target_offset); + +pub fn panic(message: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { + std.log.err("panic: {s}", .{message}); + @breakpoint(); + while (true) {} +} + +pub const std_options = struct { + pub const log_level = .debug; + pub const logFn = rp2040.uart.log; +}; + +pub fn main() !void { + gpio.reset(); + gpio.init(led); + gpio.set_direction(led, .out); + gpio.put(led, 1); + + const uart = rp2040.uart.UART.init(uart_id, .{ + .baud_rate = baud_rate, + .tx_pin = uart_tx_pin, + .rx_pin = uart_rx_pin, + .clock_config = rp2040.clock_config, + }); + + rp2040.uart.init_logger(uart); + + var data: [flash.PAGE_SIZE]u8 = undefined; + var i: usize = 0; + var j: u8 = 0; + while (i < flash.PAGE_SIZE) : (i += 1) { + data[i] = j; + + if (j == 255) j = 0; + j += 1; + } + + std.log.info("Generate data", .{}); + std.log.info("data: {s}", .{&data}); + + // Note that a whole number of sectors (4096 bytes) must be erased at a time + std.log.info("Erasing target region...", .{}); + flash.range_erase(flash_target_offset, flash.SECTOR_SIZE); + std.log.info("Done. Read back target region:", .{}); + std.log.info("data: {s}", .{flash_target_contents[0..flash.PAGE_SIZE]}); + + // Note that a whole number of pages (256 bytes) must be written at a time + std.log.info("Programming target region...", .{}); + flash.range_program(flash_target_offset, &data); + std.log.info("Done. Read back target region:", .{}); + std.log.info("data: {s}", .{flash_target_contents[0..flash.PAGE_SIZE]}); + + var mismatch: bool = false; + i = 0; + while (i < flash.PAGE_SIZE) : (i += 1) { + if (data[i] != flash_target_contents[i]) + mismatch = true; + } + + if (mismatch) { + std.log.info("Programming failed!", .{}); + } else { + std.log.info("Programming successful!", .{}); + } +} diff --git a/rp2040.ld b/rp2040.ld index f293543..cac0892 100644 --- a/rp2040.ld +++ b/rp2040.ld @@ -10,7 +10,7 @@ ENTRY(microzig_main); MEMORY { flash0 (rx!w) : ORIGIN = 0x10000000, LENGTH = 0x00200000 - ram0 (rw!x) : ORIGIN = 0x20000000, LENGTH = 0x00040000 + ram0 (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00040000 } SECTIONS @@ -43,6 +43,7 @@ SECTIONS .data : { microzig_data_start = .; + *(.time_critical*) *(.data*) microzig_data_end = .; } > ram0 AT> flash0 diff --git a/src/hal.zig b/src/hal.zig index 568c691..f8a74d2 100644 --- a/src/hal.zig +++ b/src/hal.zig @@ -12,6 +12,8 @@ pub const pwm = @import("hal/pwm.zig"); pub const spi = @import("hal/spi.zig"); pub const resets = @import("hal/resets.zig"); pub const irq = @import("hal/irq.zig"); +pub const rom = @import("hal/rom.zig"); +pub const flash = @import("hal/flash.zig"); pub const clock_config = clocks.GlobalConfiguration.init(.{ .ref = .{ .source = .src_xosc }, diff --git a/src/hal/flash.zig b/src/hal/flash.zig new file mode 100644 index 0000000..a7404b1 --- /dev/null +++ b/src/hal/flash.zig @@ -0,0 +1,81 @@ +const rom = @import("rom.zig"); + +pub const Command = enum(u8) { + block_erase = 0xd8, + ruid_cmd = 0x4b, +}; + +pub const PAGE_SIZE = 256; +pub const SECTOR_SIZE = 4096; +pub const BLOCK_SIZE = 65536; + +/// Bus reads to a 16MB memory window start at this address +pub const XIP_BASE = 0x10000000; + +pub const boot2 = struct { + /// Size of the second stage bootloader in bytes + const BOOT2_SIZE_BYTES = 64; + + /// Buffer for the second stage bootloader + var copyout: [BOOT2_SIZE_BYTES]u32 = undefined; + var copyout_valid: bool = false; + + /// Copy the 2nd stage bootloader into memory + pub fn flash_init() linksection(".time_critical") void { + if (copyout_valid) return; + const bootloader = @intToPtr([*]u32, XIP_BASE); + var i: usize = 0; + while (i < BOOT2_SIZE_BYTES) : (i += 1) { + copyout[i] = bootloader[i]; + } + copyout_valid = true; + } + + pub fn flash_enable_xip() linksection(".time_critical") void { + // TODO: use the second stage bootloader instead of cmd_xip + //const bootloader: []u32 = copyout[1..]; + + //const f = @ptrCast(*fn () void, bootloader.ptr); + //f(); + + rom.flash_enter_cmd_xip()(); + } +}; + +/// Erase count bytes starting at offset (offset from start of flash) +/// +/// The offset must be aligned to a 4096-byte sector, and count must +/// be a multiple of 4096 bytes! +pub fn range_erase(offset: u32, count: u32) linksection(".time_critical") void { + // TODO: add sanity checks, e.g., offset + count < flash size + + boot2.flash_init(); + + // TODO: __compiler_memory_barrier + + rom.connect_internal_flash()(); + rom.flash_exit_xip()(); + rom.flash_range_erase()(offset, count, BLOCK_SIZE, @enumToInt(Command.block_erase)); + rom.flash_flush_cache()(); + + boot2.flash_enable_xip(); +} + +/// Program data to flash starting at offset (offset from the start of flash) +/// +/// The offset must be aligned to a 256-byte boundary, and the length of data +/// must be a multiple of 256! +pub fn range_program(offset: u32, data: []const u8) linksection(".time_critical") void { + // TODO: add sanity checks, e.g., offset + count < flash size + + boot2.flash_init(); + + // TODO: __compiler_memory_barrier + + rom.connect_internal_flash()(); + rom.flash_exit_xip()(); + rom.flash_range_program()(offset, data.ptr, data.len); + rom.flash_flush_cache()(); + + boot2.flash_enable_xip(); +} diff --git a/src/hal/rom.zig b/src/hal/rom.zig new file mode 100644 index 0000000..128c085 --- /dev/null +++ b/src/hal/rom.zig @@ -0,0 +1,269 @@ +//! Access to functions and data in the RP2040 bootrom +//! +//! The Bootrom contains a number of public functions that provide useful RP2040 functionality that might be needed in +//! the absence of any other code on the device, as well as highly optimized versions of certain key functionality that would +//! otherwise have to take up space in most user binaries. +//! +//! The functions include: +//! 1. Fast Bit Counting / Manipulation Functions +//! 2. Fast Bulk Memory Fill / Copy Functions +//! 3. Flash Access Functions +//! 4. Debugging Support Functions (TODO) +//! 5. Miscellaneous Functions (TODO) + +/// 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'), + connect_internal_flash = rom_table_code('I', 'F'), + flash_exit_xip = rom_table_code('E', 'X'), + flash_range_erase = rom_table_code('R', 'E'), + flash_range_program = rom_table_code('R', 'P'), + flash_flush_cache = rom_table_code('F', 'C'), + flash_enter_cmd_xip = rom_table_code('C', 'X'), +}; + +/// Signatures of all public bootrom functions +pub const signatures = struct { + /// Returns the 32 bit pointer into the ROM if found or NULL otherwise + const rom_table_lookup = fn (table: *u16, code: u32) *anyopaque; + /// Signature for popcount32: Return a count of the number of 1 bits in value + const popcount32 = fn (value: u32) u32; + /// Signature for reverse32: Return the bits of value in the reverse order + const reverse32 = fn (value: u32) u32; + /// Signature for clz32: Return the number of consecutive high order 0 bits of value + const clz32 = fn (value: u32) u32; + /// Signature for ctz32: Return the number of consecutive low order 0 bits of value + const ctz32 = fn (value: u32) u32; + /// Signature of memset: Sets n bytes start at ptr to the value c and returns ptr + const memset = fn (ptr: [*]u8, c: u8, n: u32) [*]u8; + /// Signature of memset4: Sets n bytes start at ptr to the value c and returns ptr; must be word (32-bit) aligned! + const memset4 = fn (ptr: [*]u32, c: u8, n: u32) [*]u32; + /// Signature of memcpy: Copies n bytes starting at src to dest and returns dest. The results are undefined if the regions overlap. + const memcpy = fn (dest: [*]u8, src: [*]u8, n: u32) [*]u8; + /// Signature of memcpy44: Copies n bytes starting at src to dest and returns dest; must be word (32-bit) aligned! + const memcpy44 = fn (dest: [*]u32, src: [*]u32, n: u32) [*]u8; + /// Signature of connect_internal_flash: Restore all QSPI pad controls to their default state, and connect the SSI to the QSPI pads + const connect_internal_flash = fn () void; + /// Signature of flash_exit_xip: First set up the SSI for serial-mode operations, then issue the fixed XIP exit sequence described in + /// Section 2.8.1.2. Note that the bootrom code uses the IO forcing logic to drive the CS pin, which must be + /// cleared before returning the SSI to XIP mode (e.g. by a call to _flash_flush_cache). This function + /// configures the SSI with a fixed SCK clock divisor of /6. + const flash_exit_xip = fn () void; + /// Signature of flash_range_erase: Erase a count bytes, starting at addr (offset from start of flash). Optionally, pass a block erase command + /// e.g. D8h block erase, and the size of the block erased by this command — this function will use the larger + /// block erase where possible, for much higher erase speed. addr must be aligned to a 4096-byte sector, and + /// count must be a multiple of 4096 bytes. + const flash_range_erase = fn (addr: u32, count: usize, block_size: u32, block_cmd: u8) void; + /// Signature of flash_range_program: Program data to a range of flash addresses starting at addr (offset from the start of flash) and count bytes + /// in size. addr must be aligned to a 256-byte boundary, and count must be a multiple of 256. + const flash_range_program = fn (addr: u32, data: [*]const u8, count: usize) void; + /// Signature of flash_flush_cache: Flush and enable the XIP cache. Also clears the IO forcing on QSPI CSn, so that the SSI can drive the + /// flash chip select as normal. + const flash_flush_cache = fn () void; + /// Signature of flash_enter_cmd_xip: Configure the SSI to generate a standard 03h serial read command, with 24 address bits, upon each XIP + /// access. This is a very slow XIP configuration, but is very widely supported. The debugger calls this + /// function after performing a flash erase/programming operation, so that the freshly-programmed code + /// and data is visible to the debug host, without having to know exactly what kind of flash device is + /// connected. + const flash_enter_cmd_xip = fn () void; +}; + +/// Return a bootrom lookup code based on two ASCII characters +/// +/// These codes are uses to lookup data or function addresses in the bootrom +/// +/// # Parameters +/// * `c1` - the first character +/// * `c2` - the second character +/// +/// # Returns +/// +/// A 32 bit address pointing into bootrom +pub fn rom_table_code(c1: u8, c2: u8) u32 { + return @intCast(u32, c1) | (@intCast(u32, c2) << 8); +} + +/// Convert a 16 bit pointer stored at the given rom address into a pointer +/// +/// # Parameters +/// * `rom_addr` - address of the 16-bit pointer in rom +/// +/// # Returns +/// +/// The converted pointer +pub inline fn rom_hword_as_ptr(rom_addr: u32) *anyopaque { + const ptr_to_ptr = @intToPtr(*u16, rom_addr); + return @intToPtr(*anyopaque, @intCast(usize, ptr_to_ptr.*)); +} + +/// Lookup a bootrom function by code (inline) +/// +/// # Parameters +/// * `code` - code of the function (see codes) +/// +/// # Returns +/// +/// A anyopaque pointer to the function; must be cast by the caller +pub inline fn _rom_func_lookup(code: Code) *anyopaque { + const rom_table_lookup = @ptrCast(*signatures.rom_table_lookup, rom_hword_as_ptr(0x18)); + const func_table = @ptrCast(*u16, @alignCast(2, rom_hword_as_ptr(0x14))); + return rom_table_lookup(func_table, @enumToInt(code)); +} + +/// Lookup a bootrom function by code +/// +/// # Parameters +/// * `code` - code of the function (see codes) +/// +/// # Returns +/// +/// A anyopaque pointer to the function; must be cast by the caller +pub fn rom_func_lookup(code: Code) *anyopaque { + return _rom_func_lookup(code); +} + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// Fast Bit Counting / Manipulation Functions (Datasheet p. 135) +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +/// Return a count of the number of 1 bits in value +pub fn popcount32(value: u32) u32 { + const S = struct { + var f: ?*signatures.popcount32 = null; + }; + + if (S.f == null) S.f = @ptrCast(*signatures.popcount32, _rom_func_lookup(Code.popcount32)); + return S.f.?(value); +} + +/// Return a count of the number of 1 bits in value +pub fn reverse32(value: u32) u32 { + const S = struct { + var f: ?*signatures.reverse32 = null; + }; + + if (S.f == null) S.f = @ptrCast(*signatures.reverse32, _rom_func_lookup(Code.reverse32)); + return S.f.?(value); +} + +/// Return the number of consecutive high order 0 bits of value +pub fn clz32(value: u32) u32 { + const S = struct { + var f: ?*signatures.clz32 = null; + }; + + if (S.f == null) S.f = @ptrCast(*signatures.clz32, _rom_func_lookup(Code.clz32)); + return S.f.?(value); +} + +/// Return the number of consecutive low order 0 bits of value +pub fn ctz32(value: u32) u32 { + const S = struct { + var f: ?*signatures.ctz32 = null; + }; + + if (S.f == null) S.f = @ptrCast(*signatures.ctz32, _rom_func_lookup(Code.ctz32)); + return S.f.?(value); +} + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// Fast Bulk Memory Fill / Copy Functions (Datasheet p. 136) +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +/// Sets all bytes of dest to the value c and returns ptr +pub fn memset(dest: []u8, c: u8) []u8 { + const S = struct { + var f: ?*signatures.memset = null; + }; + + if (S.f == null) S.f = @ptrCast(*signatures.memset, _rom_func_lookup(Code.memset)); + return S.f.?(dest.ptr, c, dest.len)[0..dest.len]; +} + +/// 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: []u8) []u8 { + const S = struct { + var f: ?*signatures.memcpy = null; + }; + + const n = if (dest.len <= src.len) dest.len else src.len; + + if (S.f == null) S.f = @ptrCast(*signatures.memcpy, _rom_func_lookup(Code.memcpy)); + return S.f.?(dest.ptr, src.ptr, n)[0..n]; +} + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// Flash Access Functions (Datasheet p. 137) +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +/// Restore all QSPI pad controls to their default state, and connect the SSI to the QSPI pads +pub inline fn connect_internal_flash() *signatures.connect_internal_flash { + return @ptrCast( + *signatures.connect_internal_flash, + _rom_func_lookup(Code.connect_internal_flash), + ); +} + +/// First set up the SSI for serial-mode operations, then issue the fixed XIP exit +/// sequence described in Section 2.8.1.2. Note that the bootrom code uses the IO +/// forcing logic to drive the CS pin, which must be cleared before returning the +/// SSI to XIP mode (e.g. by a call to _flash_flush_cache). This function configures +/// the SSI with a fixed SCK clock divisor of /6. +pub inline fn flash_exit_xip() *signatures.flash_exit_xip { + return @ptrCast( + *signatures.flash_exit_xip, + _rom_func_lookup(Code.flash_exit_xip), + ); +} + +/// Erase a count bytes, starting at addr (offset from start of flash). Optionally, +/// pass a block erase command e.g. D8h block erase, and the size of the block +/// erased by this command — this function will use the larger block erase where +/// possible, for much higher erase speed. addr must be aligned to a 4096-byte sector, +/// and count must be a multiple of 4096 bytes. +pub inline fn flash_range_erase() *signatures.flash_range_erase { + return @ptrCast( + *signatures.flash_range_erase, + _rom_func_lookup(Code.flash_range_erase), + ); +} + +/// Program data to a range of flash addresses starting at addr (offset from the +/// start of flash) and count bytes in size. addr must be aligned to a 256-byte +/// boundary, and the length of data must be a multiple of 256. +pub inline fn flash_range_program() *signatures.flash_range_program { + return @ptrCast( + *signatures.flash_range_program, + _rom_func_lookup(Code.flash_range_program), + ); +} + +/// Flush and enable the XIP cache. Also clears the IO forcing on QSPI CSn, so that +/// the SSI can drive the flash chip select as normal. +pub inline fn flash_flush_cache() *signatures.flash_flush_cache { + return @ptrCast( + *signatures.flash_flush_cache, + _rom_func_lookup(Code.flash_flush_cache), + ); +} + +/// Configure the SSI to generate a standard 03h serial read command, with 24 address +/// bits, upon each XIP access. This is a very slow XIP configuration, but is very +/// widely supported. The debugger calls this function after performing a flash +/// erase/programming operation, so that the freshly-programmed code and data is +/// visible to the debug host, without having to know exactly what kind of flash +/// device is connected. +pub inline fn flash_enter_cmd_xip() *signatures.flash_enter_cmd_xip { + return @ptrCast( + *signatures.flash_enter_cmd_xip, + _rom_func_lookup(Code.flash_enter_cmd_xip), + ); +} From 666f444037ebe2920912234c60b359fc122c8f83 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Fri, 7 Apr 2023 09:11:31 -0700 Subject: [PATCH 40/74] Readme fix (#37) * fix link --- .buildkite/pipeline.yml | 2 ++ README.adoc | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 .buildkite/pipeline.yml diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml new file mode 100644 index 0000000..b1f338d --- /dev/null +++ b/.buildkite/pipeline.yml @@ -0,0 +1,2 @@ +steps: + - command: zig build diff --git a/README.adoc b/README.adoc index 171c62d..fc0ca7f 100644 --- a/README.adoc +++ b/README.adoc @@ -4,4 +4,4 @@ HAL and register definitions for the RP2040. == What version of Zig to use -Right now we are following [master](https://ziglang.org/download/), but once 0.11.0 is released, we will be switching to the latest stable version of Zig. +Right now we are following https://ziglang.org/download/[master], but once 0.11.0 is released, we will be switching to the latest stable version of Zig. From b0e346608e4abef37302412c5f62c389cd04e5bd Mon Sep 17 00:00:00 2001 From: Vesim Date: Sat, 8 Apr 2023 19:22:19 +0200 Subject: [PATCH 41/74] PIO assembler (#25) * WIP pio assembler * add comparison tests against the official assembler * tokenizer passing tests * add buildkite pipeline * comparison tests * assembler now outputting a few programs similar to official * largely complete --------- Co-authored-by: Matt Knight --- .buildkite/pipeline.yml | 2 +- .gitignore | 3 + build.zig | 16 +- deps/microzig | 2 +- examples/squarewave.zig | 53 + src/hal.zig | 6 +- src/hal/gpio.zig | 2 +- src/hal/hw.zig | 11 + src/hal/irq.zig | 8 +- src/hal/pio.zig | 358 +++ src/hal/pio/assembler.zig | 140 ++ src/hal/pio/assembler/Expression.zig | 706 ++++++ src/hal/pio/assembler/comparison_tests.zig | 168 ++ .../assembler/comparison_tests/README.adoc | 4 + .../assembler/comparison_tests/addition.pio | 33 + .../assembler/comparison_tests/addition.pio.h | 52 + .../pio/assembler/comparison_tests/apa102.pio | 89 + .../assembler/comparison_tests/apa102.pio.h | 105 + .../pio/assembler/comparison_tests/blink.pio | 34 + .../assembler/comparison_tests/blink.pio.h | 54 + .../comparison_tests/clocked_input.pio | 51 + .../comparison_tests/clocked_input.pio.h | 64 + .../differential_manchester.pio | 104 + .../differential_manchester.pio.h | 120 + .../pio/assembler/comparison_tests/hello.pio | 34 + .../assembler/comparison_tests/hello.pio.h | 55 + .../pio/assembler/comparison_tests/hub75.pio | 128 ++ .../assembler/comparison_tests/hub75.pio.h | 138 ++ .../pio/assembler/comparison_tests/i2c.pio | 145 ++ .../pio/assembler/comparison_tests/i2c.pio.h | 136 ++ .../comparison_tests/manchester_encoding.pio | 94 + .../manchester_encoding.pio.h | 112 + .../comparison_tests/nec_carrier_burst.pio | 61 + .../comparison_tests/nec_carrier_burst.pio.h | 70 + .../comparison_tests/nec_carrier_control.pio | 79 + .../nec_carrier_control.pio.h | 73 + .../comparison_tests/nec_receive.pio | 96 + .../comparison_tests/nec_receive.pio.h | 84 + .../comparison_tests/pio_serialiser.pio | 27 + .../comparison_tests/pio_serialiser.pio.h | 50 + .../pio/assembler/comparison_tests/pwm.pio | 31 + .../pio/assembler/comparison_tests/pwm.pio.h | 53 + .../comparison_tests/quadrature_encoder.pio | 165 ++ .../comparison_tests/quadrature_encoder.pio.h | 116 + .../comparison_tests/resistor_dac.pio | 38 + .../comparison_tests/resistor_dac.pio.h | 57 + .../pio/assembler/comparison_tests/spi.pio | 168 ++ .../pio/assembler/comparison_tests/spi.pio.h | 198 ++ .../assembler/comparison_tests/squarewave.pio | 13 + .../comparison_tests/squarewave.pio.h | 40 + .../comparison_tests/squarewave_fast.pio | 19 + .../comparison_tests/squarewave_fast.pio.h | 39 + .../comparison_tests/squarewave_test.pio | 12 + .../comparison_tests/squarewave_wrap.pio | 19 + .../comparison_tests/squarewave_wrap.pio.h | 39 + .../assembler/comparison_tests/st7789_lcd.pio | 57 + .../comparison_tests/st7789_lcd.pio.h | 72 + .../assembler/comparison_tests/uart_rx.pio | 94 + .../assembler/comparison_tests/uart_rx.pio.h | 120 + .../assembler/comparison_tests/uart_tx.pio | 61 + .../assembler/comparison_tests/uart_tx.pio.h | 73 + .../pio/assembler/comparison_tests/ws2812.pio | 85 + .../assembler/comparison_tests/ws2812.pio.h | 114 + src/hal/pio/assembler/encoder.zig | 1005 +++++++++ src/hal/pio/assembler/tokenizer.zig | 1947 +++++++++++++++++ 65 files changed, 8191 insertions(+), 11 deletions(-) create mode 100644 examples/squarewave.zig create mode 100644 src/hal/hw.zig create mode 100644 src/hal/pio.zig create mode 100644 src/hal/pio/assembler.zig create mode 100644 src/hal/pio/assembler/Expression.zig create mode 100644 src/hal/pio/assembler/comparison_tests.zig create mode 100644 src/hal/pio/assembler/comparison_tests/README.adoc create mode 100644 src/hal/pio/assembler/comparison_tests/addition.pio create mode 100644 src/hal/pio/assembler/comparison_tests/addition.pio.h create mode 100644 src/hal/pio/assembler/comparison_tests/apa102.pio create mode 100644 src/hal/pio/assembler/comparison_tests/apa102.pio.h create mode 100644 src/hal/pio/assembler/comparison_tests/blink.pio create mode 100644 src/hal/pio/assembler/comparison_tests/blink.pio.h create mode 100644 src/hal/pio/assembler/comparison_tests/clocked_input.pio create mode 100644 src/hal/pio/assembler/comparison_tests/clocked_input.pio.h create mode 100644 src/hal/pio/assembler/comparison_tests/differential_manchester.pio create mode 100644 src/hal/pio/assembler/comparison_tests/differential_manchester.pio.h create mode 100644 src/hal/pio/assembler/comparison_tests/hello.pio create mode 100644 src/hal/pio/assembler/comparison_tests/hello.pio.h create mode 100644 src/hal/pio/assembler/comparison_tests/hub75.pio create mode 100644 src/hal/pio/assembler/comparison_tests/hub75.pio.h create mode 100644 src/hal/pio/assembler/comparison_tests/i2c.pio create mode 100644 src/hal/pio/assembler/comparison_tests/i2c.pio.h create mode 100644 src/hal/pio/assembler/comparison_tests/manchester_encoding.pio create mode 100644 src/hal/pio/assembler/comparison_tests/manchester_encoding.pio.h create mode 100644 src/hal/pio/assembler/comparison_tests/nec_carrier_burst.pio create mode 100644 src/hal/pio/assembler/comparison_tests/nec_carrier_burst.pio.h create mode 100644 src/hal/pio/assembler/comparison_tests/nec_carrier_control.pio create mode 100644 src/hal/pio/assembler/comparison_tests/nec_carrier_control.pio.h create mode 100644 src/hal/pio/assembler/comparison_tests/nec_receive.pio create mode 100644 src/hal/pio/assembler/comparison_tests/nec_receive.pio.h create mode 100644 src/hal/pio/assembler/comparison_tests/pio_serialiser.pio create mode 100644 src/hal/pio/assembler/comparison_tests/pio_serialiser.pio.h create mode 100644 src/hal/pio/assembler/comparison_tests/pwm.pio create mode 100644 src/hal/pio/assembler/comparison_tests/pwm.pio.h create mode 100644 src/hal/pio/assembler/comparison_tests/quadrature_encoder.pio create mode 100644 src/hal/pio/assembler/comparison_tests/quadrature_encoder.pio.h create mode 100644 src/hal/pio/assembler/comparison_tests/resistor_dac.pio create mode 100644 src/hal/pio/assembler/comparison_tests/resistor_dac.pio.h create mode 100644 src/hal/pio/assembler/comparison_tests/spi.pio create mode 100644 src/hal/pio/assembler/comparison_tests/spi.pio.h create mode 100644 src/hal/pio/assembler/comparison_tests/squarewave.pio create mode 100644 src/hal/pio/assembler/comparison_tests/squarewave.pio.h create mode 100644 src/hal/pio/assembler/comparison_tests/squarewave_fast.pio create mode 100644 src/hal/pio/assembler/comparison_tests/squarewave_fast.pio.h create mode 100644 src/hal/pio/assembler/comparison_tests/squarewave_test.pio create mode 100644 src/hal/pio/assembler/comparison_tests/squarewave_wrap.pio create mode 100644 src/hal/pio/assembler/comparison_tests/squarewave_wrap.pio.h create mode 100644 src/hal/pio/assembler/comparison_tests/st7789_lcd.pio create mode 100644 src/hal/pio/assembler/comparison_tests/st7789_lcd.pio.h create mode 100644 src/hal/pio/assembler/comparison_tests/uart_rx.pio create mode 100644 src/hal/pio/assembler/comparison_tests/uart_rx.pio.h create mode 100644 src/hal/pio/assembler/comparison_tests/uart_tx.pio create mode 100644 src/hal/pio/assembler/comparison_tests/uart_tx.pio.h create mode 100644 src/hal/pio/assembler/comparison_tests/ws2812.pio create mode 100644 src/hal/pio/assembler/comparison_tests/ws2812.pio.h create mode 100644 src/hal/pio/assembler/encoder.zig create mode 100644 src/hal/pio/assembler/tokenizer.zig diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index b1f338d..50f730f 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -1,2 +1,2 @@ steps: - - command: zig build + - command: zig build test diff --git a/.gitignore b/.gitignore index 4c82b07..c8366d4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ zig-cache zig-out +.DS_Store +.gdbinit +.lldbinit diff --git a/build.zig b/build.zig index 5144b36..21a91ff 100644 --- a/build.zig +++ b/build.zig @@ -39,8 +39,19 @@ pub fn addPiPicoExecutable( // project requires multiple HALs, it accepts microzig as a param pub fn build(b: *Builder) !void { const optimize = b.standardOptimizeOption(.{}); - var examples = Examples.init(b, optimize); - examples.install(); + //var examples = Examples.init(b, optimize); + //examples.install(); + + const pio_tests = b.addTest(.{ + .root_source_file = .{ + .path = "src/hal/pio.zig", + }, + .optimize = optimize, + }); + pio_tests.addIncludePath("src/hal/pio/assembler"); + + const test_step = b.step("test", "run unit tests"); + test_step.dependOn(&pio_tests.run().step); } fn root() []const u8 { @@ -55,6 +66,7 @@ pub const Examples = struct { pwm: *microzig.EmbeddedExecutable, spi_master: *microzig.EmbeddedExecutable, uart: *microzig.EmbeddedExecutable, + squarewave: *microzig.EmbeddedExecutable, //uart_pins: microzig.EmbeddedExecutable, flash_program: *microzig.EmbeddedExecutable, diff --git a/deps/microzig b/deps/microzig index 23482a6..dabc932 160000 --- a/deps/microzig +++ b/deps/microzig @@ -1 +1 @@ -Subproject commit 23482a6986252e0eeff54a04abc0aac8a08d25d7 +Subproject commit dabc9325cdee394ff66e28c91803cb814954b157 diff --git a/examples/squarewave.zig b/examples/squarewave.zig new file mode 100644 index 0000000..b320681 --- /dev/null +++ b/examples/squarewave.zig @@ -0,0 +1,53 @@ +//! Hello world for the PIO module: generating a square wave +const std = @import("std"); +const microzig = @import("microzig"); +const rp2040 = microzig.hal; +const gpio = rp2040.gpio; +const Pio = rp2040.pio.Pio; +const StateMachine = rp2040.pio.StateMachine; + +const squarewave_program = (rp2040.pio.assemble( + \\.program squarewave + \\ set pindirs, 1 ; Set pin to output + \\again: + \\ set pins, 1 [1] ; Drive pin high and then delay for one cycle + \\ set pins, 0 ; Drive pin low + \\ jmp again ; Set PC to label `again` +) catch + @panic("failed to assemble program")) + .get_program_by_name("squarewave"); + +pub fn main() void { + // Pick one PIO instance arbitrarily. We're also arbitrarily picking state + // machine 0 on this PIO instance (the state machines are numbered 0 to 3 + // inclusive). + const pio: Pio = .pio0; + const sm: StateMachine = .sm0; + + // Load the assembled program directly into the PIO's instruction memory. + // Each PIO instance has a 32-slot instruction memory, which all 4 state + // machines can see. The system has write-only access. + for (squarewave_program.instructions, 0..) |insn, i| + pio.get_instruction_memory()[i] = insn; + + // Configure state machine 0 to run at sysclk/2.5. The state machines can + // run as fast as one instruction per clock cycle, but we can scale their + // speed down uniformly to meet some precise frequency target, e.g. for a + // UART baud rate. This register has 16 integer divisor bits and 8 + // fractional divisor bits. + pio.set_clkdiv_int_frac(sm, 2, 0x80); + + // There are five pin mapping groups (out, in, set, side-set, jmp pin) + // which are used by different instructions or in different circumstances. + // Here we're just using SET instructions. Configure state machine 0 SETs + // to affect GPIO 0 only; then configure GPIO0 to be controlled by PIO0, + // as opposed to e.g. the processors. + pio.set_out_pins(sm, 0, 1); + gpio.set_function(0, .pio0); + + // Set the state machine running. The PIO CTRL register is global within a + // PIO instance, so you can start/stop multiple state machines + // simultaneously. We're using the register's hardware atomic set alias to + // make one bit high without doing a read-modify-write on the register. + pio.set_enabled(sm, true); +} diff --git a/src/hal.zig b/src/hal.zig index f8a74d2..5813cf9 100644 --- a/src/hal.zig +++ b/src/hal.zig @@ -1,5 +1,6 @@ +const std = @import("std"); const microzig = @import("microzig"); -const regs = microzig.chip.registers; +const SIO = microzig.chip.peripherals.SIO; pub const adc = @import("hal/adc.zig"); pub const pins = @import("hal/pins.zig"); @@ -14,6 +15,7 @@ pub const resets = @import("hal/resets.zig"); pub const irq = @import("hal/irq.zig"); pub const rom = @import("hal/rom.zig"); pub const flash = @import("hal/flash.zig"); +pub const pio = @import("hal/pio.zig"); pub const clock_config = clocks.GlobalConfiguration.init(.{ .ref = .{ .source = .src_xosc }, @@ -32,5 +34,5 @@ pub fn init() void { } pub fn get_cpu_id() u32 { - return regs.SIO.CPUID.*; + return SIO.CPUID.*; } diff --git a/src/hal/gpio.zig b/src/hal/gpio.zig index 1e333b1..c0b6bae 100644 --- a/src/hal/gpio.zig +++ b/src/hal/gpio.zig @@ -87,7 +87,7 @@ pub const PullUpDown = enum { pub inline fn set_pull(comptime gpio: u32, mode: ?PullUpDown) void { const gpio_name = comptime std.fmt.comptimePrint("GPIO{d}", .{gpio}); - const gpio_regs = @field(PADS_BANK0, gpio_name); + const gpio_regs = &@field(PADS_BANK0, gpio_name); if (mode == null) { gpio_regs.modify(.{ .PUE = 0, .PDE = 0 }); diff --git a/src/hal/hw.zig b/src/hal/hw.zig new file mode 100644 index 0000000..a44aff1 --- /dev/null +++ b/src/hal/hw.zig @@ -0,0 +1,11 @@ +pub const Lock = struct { + impl: u32, + + pub fn claim() Lock { + + } + + pub fn unlock(lock: Lock) void { + + } +}; diff --git a/src/hal/irq.zig b/src/hal/irq.zig index f3502be..2ff9a13 100644 --- a/src/hal/irq.zig +++ b/src/hal/irq.zig @@ -1,5 +1,5 @@ const microzig = @import("microzig"); -const regs = microzig.chip.registers; +const NVIC = microzig.chip.peripherals.NVIC; // TODO: the register definitions are improved now, use them instead of raw // writes/reads @@ -10,11 +10,11 @@ fn get_interrupt_mask(comptime interrupt_name: []const u8) u32 { } pub fn enable(comptime interrupt_name: []const u8) void { const mask = comptime get_interrupt_mask(interrupt_name); - regs.SCS.NVIC.ICPR.raw = mask; - regs.SCS.NVIC.ISER.raw = mask; + NVIC.ICPR.raw = mask; + NVIC.ISER.raw = mask; } pub fn disable(comptime interrupt_name: []const u8) void { const mask = comptime get_interrupt_mask(interrupt_name); - regs.SCS.NVIC.ICER.raw = mask; + NVIC.ICER.raw = mask; } diff --git a/src/hal/pio.zig b/src/hal/pio.zig new file mode 100644 index 0000000..e37d713 --- /dev/null +++ b/src/hal/pio.zig @@ -0,0 +1,358 @@ +//! A PIO instance can load a single `Bytecode`, it has to be loaded into memory +const std = @import("std"); + +const microzig = @import("microzig"); +const PIO = microzig.chip.types.peripherals.PIO0; +const PIO0 = microzig.chip.peripherals.PIO0; +const PIO1 = microzig.chip.peripherals.PIO1; + +const gpio = @import("gpio.zig"); +const assembler = @import("pio/assembler.zig"); +pub const Bytecode = Bytecode; +pub const Program = assembler.Program; +pub const assemble = assembler.assemble; + +var used_instruction_space: [2]u32 = [_]u32{ 0, 0 }; +var claimed_state_machines: [2]u4 = [_]u4{ 0, 0 }; + +pub const Join = enum { + none, + rx, + tx, +}; + +pub const Status = enum { + rx_lessthan, + tx_lessthan, +}; + +pub const Configuration = struct { + pin: u32, +}; + +pub const StateMachine = enum(u2) { + sm0, + sm1, + sm2, + sm3, +}; + +pub const Pio = enum(u1) { + pio0 = 0, + pio1 = 1, + + fn get_regs(self: Pio) *volatile PIO { + return switch (self) { + .pio0 => PIO0, + .pio1 => PIO1, + }; + } + + pub fn get_instruction_memory(self: Pio) *volatile [32]u32 { + const regs = self.get_regs(); + return @ptrCast(*volatile [32]u32, ®s.INSTR_MEM0); + } + + pub fn gpio_init(self: Pio, comptime pin: u5) void { + gpio.set_function(pin, switch (self) { + .pio0 => .pio0, + .pio1 => .pio1, + }); + } + + pub fn load(self: Pio, bytecode: Bytecode) !void { + _ = self; + _ = bytecode; + } + + fn can_add_program_at_offset(self: Pio, program: Program, offset: u5) bool { + if (program.origin) |origin| + if (origin != offset) + return false; + + const used_mask = used_instruction_space[@enumToInt(self)]; + const program_mask = program.get_mask(); + + // We can add the program if the masks don't overlap, if there is + // overlap the result of a bitwise AND will have a non-zero result + return (used_mask & program_mask) == 0; + } + + fn find_offset_for_program(self: Pio, program: Program) !u5 { + return if (program.origin) |origin| + if (self.can_add_program_at_offset(program, origin)) + origin + else + error.NoSpace + else for (0..32 - program.isntruction.len) |i| { + if (self.can_add_program_at_offset(program, i)) + break i; + } else error.NoSpace; + } + + fn add_program_at_offset_unlocked(self: Pio, program: Program, offset: u5) !void { + if (!self.can_add_program_at_offset(program, offset)) + return error.NoSpace; + + const instruction_memory = self.get_instruction_memory(); + for (program.instructions, offset..) |insn, i| + instruction_memory[i] = insn; + + const program_mask = program.get_mask(); + used_instruction_space[@enumToInt(self)] |= program_mask << offset; + } + + /// Public functions will need to lock independently, so only exposing this function for now + pub fn add_program(self: Pio, program: Program) !void { + // TODO: const lock = hw.Lock.claim() + // defer lock.unlock(); + + const offset = try self.find_offset_for_program_unlocked(); + try self.add_program_at_offset(program, offset); + } + + pub fn claim_unused_state_machine(self: Pio) !StateMachine { + // TODO: const lock = hw.Lock.claim() + // defer lock.unlock(); + + const claimed_mask = claimed_state_machines[@enumToInt(self)]; + return for (0..4) |i| { + const sm_mask = (@as(u4, 1) << @intCast(u2, i)); + if (0 == (claimed_mask & sm_mask)) { + claimed_state_machines[@enumToInt(self)] |= sm_mask; + break @intToEnum(StateMachine, i); + } + } else error.NoSpace; + } + + pub const StateMachineRegs = extern struct { + clkdiv: @TypeOf(PIO0.SM0_CLKDIV), + execctrl: @TypeOf(PIO0.SM0_EXECCTRL), + shiftctrl: @TypeOf(PIO0.SM0_SHIFTCTRL), + addr: @TypeOf(PIO0.SM0_ADDR), + instr: @TypeOf(PIO0.SM0_INSTR), + pinctrl: @TypeOf(PIO0.SM0_PINCTRL), + }; + + fn get_sm_regs(self: Pio, sm: StateMachine) *volatile StateMachineRegs { + const pio_regs = self.get_regs(); + return switch (sm) { + .sm0 => @ptrCast(*volatile StateMachineRegs, &pio_regs.SM0_CLKDIV), + .sm1 => @ptrCast(*volatile StateMachineRegs, &pio_regs.SM1_CLKDIV), + .sm2 => @ptrCast(*volatile StateMachineRegs, &pio_regs.SM2_CLKDIV), + .sm3 => @ptrCast(*volatile StateMachineRegs, &pio_regs.SM3_CLKDIV), + }; + } + + pub fn join_fifo(self: Pio, sm: StateMachine, join: Join) void { + const tx: u1 = switch (join) { + .tx => 1, + .rx => 0, + .none => 0, + }; + const rx: u1 = switch (join) { + .tx => 0, + .rx => 1, + .none => 0, + }; + + const sm_regs = self.get_sm_regs(sm); + sm_regs.shiftctrl.modify(.{ + .FJOIN_TX = tx, + .FJOIN_RX = rx, + }); + } + + pub fn set_clkdiv_int_frac(self: Pio, sm: StateMachine, div_int: u16, div_frac: u8) void { + if (div_int == 0 and div_frac != 0) + @panic("invalid params"); + + const sm_regs = self.get_sm_regs(sm); + sm_regs.clkdiv.write(.{ + .INT = div_int, + .FRAC = div_frac, + + .reserved8 = 0, + }); + } + + pub fn set_out_shift(self: Pio, sm: StateMachine, args: struct { + shift_right: bool, + autopull: bool, + pull_threshold: u5, + }) void { + const sm_regs = self.get_sm_regs(sm); + sm_regs.shiftctrl.modify(.{ + .OUT_SHIFTDIR = @boolToInt(args.shift_right), + .AUTOPULL = @boolToInt(args.autopull), + .PULL_THRESH = args.pull_threshold, + }); + } + + pub fn set_out_pins(self: Pio, sm: StateMachine, base: u5, count: u5) void { + const sm_regs = self.get_sm_regs(sm); + sm_regs.pinctrl.modify(.{ + .OUT_BASE = base, + .OUT_COUNT = count, + }); + } + + pub fn set_sideset_pins(self: Pio, sm: StateMachine, base: u5) void { + const sm_regs = self.get_sm_regs(sm); + sm_regs.pinctrl.modify(.{ .SIDESET_BASE = base }); + } + + pub fn is_tx_fifo_full(self: Pio, sm: StateMachine) bool { + const regs = self.get_regs(); + const txfull = regs.FSTAT.read().TXFULL; + return (txfull & (@as(u4, 1) << @enumToInt(sm))) != 0; + } + + pub fn get_tx_fifo(self: Pio, sm: StateMachine) *volatile u32 { + const regs = self.get_regs(); + return switch (sm) { + .sm0 => ®s.TXF0, + .sm1 => ®s.TXF1, + .sm2 => ®s.TXF2, + .sm3 => ®s.TXF3, + }; + } + + pub fn blocking_write(self: Pio, sm: StateMachine, value: u32) void { + while (self.is_tx_fifo_full(sm)) {} + + const fifo_ptr = self.get_tx_fifo(sm); + fifo_ptr.* = value; + } + + pub fn encode_jmp() void {} + + //static inline uint _pio_encode_instr_and_args(enum pio_instr_bits instr_bits, uint arg1, uint arg2) { + // valid_params_if(PIO_INSTRUCTIONS, arg1 <= 0x7); + //#if PARAM_ASSERTIONS_ENABLED(PIO_INSTRUCTIONS) + // uint32_t major = _pio_major_instr_bits(instr_bits); + // if (major == pio_instr_bits_in || major == pio_instr_bits_out) { + // assert(arg2 && arg2 <= 32); + // } else { + // assert(arg2 <= 31); + // } + //#endif + // return instr_bits | (arg1 << 5u) | (arg2 & 0x1fu); + //} + // + //static inline uint pio_encode_jmp(uint addr) { + // return _pio_encode_instr_and_args(pio_instr_bits_jmp, 0, addr); + //} + + pub fn set_enabled(self: Pio, sm: StateMachine, enabled: bool) void { + const regs = self.get_regs(); + + var value = regs.CTRL.read(); + if (enabled) + value.SM_ENABLE |= @as(u4, 1) << @enumToInt(sm) + else + value.SM_ENABLE &= ~(@as(u4, 1) << @enumToInt(sm)); + + regs.CTRL.write(value); + } + + pub fn sm_init(self: Pio, sm: StateMachine, initial_pc: u5, config: StateMachineRegs) void { + // Halt the machine, set some sensible defaults + self.set_enabled(sm, false); + + self.set_config(sm, config); + self.clear_fifos(sm); + + // Clear FIFO debug flags + //const uint32_t fdebug_sm_mask = + // (1u << PIO_FDEBUG_TXOVER_LSB) | + // (1u << PIO_FDEBUG_RXUNDER_LSB) | + // (1u << PIO_FDEBUG_TXSTALL_LSB) | + // (1u << PIO_FDEBUG_RXSTALL_LSB); + //pio->fdebug = fdebug_sm_mask << sm; + + // Finally, clear some internal SM state + self.restart(sm); + self.clkdiv_restart(sm); + self.exec(sm, encode_jmp(initial_pc)); + } + + // state machine configuration helpers: + // + // - set_out_pins + // - set_set_pins + // - set_in_pins + // - set_sideset_pins + // - set_sideset + // - calculate_clkdiv_from_float + // - set_clkdiv + // - set_wrap + // - set_jmp_pin + // - set_in_shift + // - set_out_shift + // - set_fifo_join + // - set_out_special + // - set_mov_status + // + // PIO: + // + // - can_add_program + // - add_program_at_offset + // - add_program + // - remove_program + // - clear_instruction_memory + // - sm_init + // - sm_set_enabled + // - sm_mask_enabled + // - sm_restart + // - restart_sm_mask + // - sm_clkdiv_restart + // - clkdiv_restart_sm_mask + // - enable_sm_mask_in_sync + // - set_irq0_source_enabled + // - set_irq1_source_enabled + // - set_irq0_source_mask_enabled + // - set_irq1_source_mask_enabled + // - set_irqn_source_enabled + // - set_irqn_source_mask_enabled + // - interrupt_get + // - interrupt_clear + // - sm_get_pc + // - sm_exec + // - sm_is_exec_stalled + // - sm_exec_wait_blocking + // - sm_set_wrap + // - sm_set_out_pins + // - sm_set_set_pins + // - sm_set_in_pins + // - sm_set_sideset_pins + // - sm_put + // - sm_get + // - sm_is_rx_fifo_full + // - sm_is_rx_fifo_empty + // - sm_is_rx_fifo_level + // - sm_is_tx_fifo_full + // - sm_is_tx_fifo_empty + // - sm_is_tx_fifo_level + // - sm_put_blocking + // - sm_get_blocking + // - sm_drain_tx_fifo + // - sm_set_clkdiv_int_frac + // - sm_set_clkdiv + // - sm_clear_fifos + // - sm_set_pins + // - sm_set_pins_with_mask + // - sm_set_pindirs_with_mask + // - sm_set_consecutive_pindirs + // - sm_claim + // - claim_sm_mask + // - sm_unclaim + // - claim_unused_sm + // - sm_is_claimed + // +}; + +test "pio" { + std.testing.refAllDecls(assembler); + //std.testing.refAllDecls(@import("pio/test.zig")); +} diff --git a/src/hal/pio/assembler.zig b/src/hal/pio/assembler.zig new file mode 100644 index 0000000..d3596fd --- /dev/null +++ b/src/hal/pio/assembler.zig @@ -0,0 +1,140 @@ +const std = @import("std"); +const assert = std.debug.assert; + +const tokenizer = @import("assembler/tokenizer.zig"); +const encoder = @import("assembler/encoder.zig"); + +pub const TokenizeOptions = tokenizer.Options; +pub const EncodeOptions = encoder.Options; + +pub const Define = struct { + name: []const u8, + value: i64, +}; + +pub const Program = struct { + name: []const u8, + defines: []const Define, + instructions: []const u16, + origin: ?u5, + side_set: ?encoder.SideSet, + wrap_target: ?u5, + wrap: ?u5, + + pub fn get_mask(program: Program) u32 { + return (1 << program.instructions.len) - 1; + } +}; + +pub const Output = struct { + defines: []const Define, + programs: []const Program, + + pub fn get_program_by_name( + comptime output: Output, + comptime name: []const u8, + ) Program { + return for (output.programs) |program| { + if (std.mem.eql(u8, program.name, program)) + break program; + } else @panic(std.fmt.comptimePrint("program '{s}' not found", .{name})); + } + + pub fn get_define_by_name( + comptime output: Output, + comptime name: []const u8, + ) u32 { + return for (output.defines) |define| { + if (std.mem.eql(u8, define.name, define)) + break define; + } else @panic(std.fmt.comptimePrint("define '{s}' not found", .{name})); + } +}; + +pub const AssembleOptions = struct { + tokenize: TokenizeOptions = .{}, + encode: EncodeOptions = .{}, +}; + +pub const Diagnostics = struct { + message: std.BoundedArray(u8, 256), + index: u32, + + pub fn init(index: u32, comptime fmt: []const u8, args: anytype) Diagnostics { + var ret = Diagnostics{ + .message = std.BoundedArray(u8, 256).init(0) catch unreachable, + .index = index, + }; + + ret.message.writer().print(fmt, args) catch unreachable; + return ret; + } +}; + +pub fn assemble_impl(comptime source: []const u8, diags: *?Diagnostics, options: AssembleOptions) !Output { + const tokens = try tokenizer.tokenize(source, diags, options.tokenize); + const encoder_output = try encoder.encode(tokens.slice(), diags, options.encode); + var programs = std.BoundedArray(Program, options.encode.max_programs).init(0) catch unreachable; + for (encoder_output.programs.slice()) |bounded| + try programs.append(bounded.to_exported_program()); + + return Output{ + .defines = blk: { + var tmp = std.BoundedArray(Define, options.encode.max_defines).init(0) catch unreachable; + for (encoder_output.global_defines.slice()) |define| + tmp.append(.{ + .name = define.name, + .value = define.value, + }) catch unreachable; + break :blk tmp.slice(); + }, + .programs = programs.slice(), + }; +} + +fn format_compile_error(comptime message: []const u8, comptime source: []const u8, comptime index: u32) []const u8 { + var line_str: []const u8 = ""; + var line_num: u32 = 1; + var column: u32 = 0; + var line_it = std.mem.tokenize(u8, source, "\n\r"); + while (line_it.next()) |line| : (line_num += 1) { + line_str = line_str ++ "\n" ++ line; + if (line_it.index > index) { + column = line.len - (line_it.index - index); + line_str = line; + break; + } + } + + return std.fmt.comptimePrint( + \\failed to assemble PIO code: + \\ + \\{s} + \\{s}^ + \\{s}{s} + \\ + , .{ + line_str, + [_]u8{' '} ** column, + [_]u8{' '} ** column, + message, + }); +} + +pub fn assemble(comptime source: []const u8, comptime options: AssembleOptions) !Output { + var diags: ?Diagnostics = null; + return assemble_impl(source, &diags, options) catch |err| if (diags) |d| + @compileError(format_compile_error(d.message.slice(), source, d.index)) + else + err; +} + +test "tokenizer and encoder" { + std.testing.refAllDecls(tokenizer); + std.testing.refAllDecls(@import("assembler/Expression.zig")); + std.testing.refAllDecls(encoder); +} + +test "comparison" { + //std.testing.refAllDecls(@import("assembler/comparison_tests.zig")); +} diff --git a/src/hal/pio/assembler/Expression.zig b/src/hal/pio/assembler/Expression.zig new file mode 100644 index 0000000..794b5c3 --- /dev/null +++ b/src/hal/pio/assembler/Expression.zig @@ -0,0 +1,706 @@ +//! Expressions for PIO are weird. The documentation states that an expression, +//! when used as a "value", requires parenthesis. However the official PIO +//! assembler allows for defines with a value of `::1` which is an expression. +//! +//! Annoyingly, looking at the parser, it seems that it supports a number of +//! other operations not covered in the documentation. +ops: BoundedOperations, +values: BoundedValues, + +const std = @import("std"); +const assert = std.debug.assert; + +const assembler = @import("../assembler.zig"); +const Diagnostics = assembler.Diagnostics; + +const encoder = @import("encoder.zig"); +const DefineWithIndex = encoder.DefineWithIndex; + +const Expression = @This(); +const BoundedOperations = std.BoundedArray(OperationWithIndex, 32); +const BoundedValues = std.BoundedArray(Value, 32); + +const Value = struct { + str: []const u8, + index: u32, +}; + +const OperationWithIndex = struct { + op: Operation, + index: u32, +}; + +const call_depth_max = 64; + +pub const Operation = enum { + add, + sub, + mul, + div, + negative, + bit_reverse, + value, + // operations shown in pioasm's parser: + // - OR + // - AND + // - XOR + + pub fn format( + op: Operation, + comptime fmt: []const u8, + options: std.fmt.FormatOptions, + writer: anytype, + ) !void { + _ = fmt; + _ = options; + try writer.print("{s}", .{switch (op) { + .add => "add", + .sub => "sub", + .mul => "mul", + .div => "div", + .negative => "neg", + .bit_reverse => "rev", + .value => "val", + }}); + } +}; + +pub fn tokenize( + str: []const u8, + /// starting index of the expression + index: u32, + diags: *?Diagnostics, +) !Expression { + var ops = BoundedOperations.init(0) catch unreachable; + var values = BoundedValues.init(0) catch unreachable; + + const call_depth: u32 = 0; + try recursive_tokenize(call_depth, &ops, &values, str, index, diags); + return Expression{ + .ops = ops, + .values = values, + }; +} + +const TrimResult = struct { + str: []const u8, + index: u32, + + fn default(str: []const u8) TrimResult { + return TrimResult{ + .str = str, + .index = 0, + }; + } +}; + +fn trim_outer_parenthesis(str: []const u8) TrimResult { + // if the outer characters (not including whitespace) are parenthesis, then include the inside string + + // scan the prefix + const start: usize = for (str, 0..) |c, i| { + switch (c) { + ' ', + '\t', + => {}, + '(' => break i + 1, + else => return TrimResult.default(str), + } + } else return TrimResult.default(str); + + const end: usize = blk: { + var i = str.len - 1; + break :blk while (i > 0) : (i -= 1) { + switch (str[i]) { + ' ', + '\t', + => {}, + ')' => break i, + else => return TrimResult.default(str), + } + } else return TrimResult.default(str); + }; + + return TrimResult{ + .str = str[start..end], + .index = @intCast(u32, start), + }; +} + +fn recursive_tokenize( + call_depth: u32, + ops: *BoundedOperations, + values: *BoundedValues, + str: []const u8, + index: u32, + diags: *?Diagnostics, +) !void { + assert(call_depth < call_depth_max); + const trim_result = trim_outer_parenthesis(str); + const expr_str = trim_result.str; + const expr_index = index + trim_result.index; + + var parenthesis_found = false; + var depth: u32 = 0; + var i = @intCast(i32, expr_str.len - 1); + outer: while (i >= 0) : (i -= 1) { + const idx = @intCast(u32, i); + // TODO: how about if the expression is fully enveloped in parenthesis? + switch (expr_str[idx]) { + ')' => { + depth += 1; + parenthesis_found = true; + continue :outer; + }, + '(' => { + if (depth == 0) { + diags.* = Diagnostics.init(expr_index + idx, "mismatched parenthesis", .{}); + return error.MismatchedParenthesis; + } + + depth -= 1; + parenthesis_found = true; + if (depth != 0) + continue :outer; + }, + else => if (depth > 0) + continue :outer, + } + + const op: Operation = switch (expr_str[idx]) { + '+' => .add, + // needs context to determine if it's a negative or subtraction + '-' => blk: { + // it's negative if we have nothing to the left. If an operator + // is found to the left we continue + const is_negative = (i == 0) or is_negative: { + var j = i - 1; + while (j >= 0) : (j -= 1) { + const jdx = @intCast(u32, j); + switch (expr_str[jdx]) { + ' ', '\t' => continue, + '+', '-', '*', '/' => continue :outer, + else => break :is_negative false, + } + } + + break :is_negative true; + }; + + if (is_negative) { + try ops.append(.{ + .op = .negative, + .index = expr_index + idx, + }); + try recursive_tokenize(call_depth + 1, ops, values, expr_str[idx + 1 ..], expr_index + idx + 1, diags); + return; + } + + break :blk .sub; + }, + '*' => .mul, + '/' => .div, + ':' => { + const is_bit_reverse = (i != 0) and expr_str[idx - 1] == ':'; + if (is_bit_reverse) { + try ops.append(.{ + .op = .bit_reverse, + .index = expr_index + idx - 1, + }); + try recursive_tokenize(call_depth + 1, ops, values, expr_str[idx + 1 ..], expr_index + idx + 1, diags); + i -= 1; + return; + } + + return error.InvalidBitReverse; + }, + else => continue, + }; + + try ops.append(.{ + .op = op, + .index = expr_index + idx, + }); + try recursive_tokenize(call_depth + 1, ops, values, expr_str[idx + 1 ..], expr_index + idx + 1, diags); + try recursive_tokenize(call_depth + 1, ops, values, expr_str[0..idx], expr_index, diags); + return; + } else if (parenthesis_found) { + try recursive_tokenize(call_depth + 1, ops, values, expr_str, expr_index, diags); + } else { + // if we hit this path, then the full string has been scanned, and no operators + const trimmed = std.mem.trim(u8, expr_str, " \t"); + const value_index = expr_index + @intCast(u32, std.mem.indexOf(u8, expr_str, trimmed).?); + try ops.append(.{ + .op = .value, + .index = value_index, + }); + + try values.append(.{ + .str = trimmed, + .index = value_index, + }); + } + + if (depth != 0) { + diags.* = Diagnostics.init(expr_index + @intCast(u32, i), "mismatched parenthesis", .{}); + return error.MismatchedParenthesis; + } +} + +const EvaluatedValue = struct { + num: i128, + index: u32, + + pub fn format( + eval_value: EvaluatedValue, + comptime fmt: []const u8, + options: std.fmt.FormatOptions, + writer: anytype, + ) !void { + _ = fmt; + _ = options; + try writer.print("{}", .{eval_value.num}); + } +}; + +pub fn evaluate( + self: Expression, + define_lists: []const []const DefineWithIndex, + diags: *?Diagnostics, +) !i128 { + var values = std.BoundedArray(EvaluatedValue, 32).init(0) catch unreachable; + // parse/extract values into numbers + for (self.values.slice()) |entry| { + const value: EvaluatedValue = if (std.fmt.parseInt(i128, entry.str, 0)) |num| .{ + .num = num, + .index = entry.index, + } else |_| blk: { + // if it fails, try looking up the strings in definitions + for (define_lists) |define_list| + for (define_list) |define| + if (std.mem.eql(u8, define.name, entry.str)) + break :blk .{ + .num = define.value, + .index = define.index, + }; + + diags.* = Diagnostics.init(entry.index, "value doesn't parse as an integer, or define not found", .{}); + return error.UnresolvedValue; + }; + + try values.append(value); + } + + return if (self.ops.len == 1) blk: { + assert(self.values.len == 1); + assert(self.ops.get(0).op == .value); + + break :blk values.get(0).num; + } else blk: { + const result = try recursive_evaluate(0, self.ops.slice(), values.slice(), diags); + assert(result.consumed.ops == self.ops.len); + assert(result.consumed.values == self.values.len); + break :blk result.value; + }; +} + +const RecursiveEvalResult = struct { + value: i128, + consumed: struct { + ops: u32, + values: u32, + }, + index: u32, +}; + +fn recursive_evaluate( + call_depth: u32, + owis: []const OperationWithIndex, + values: []const EvaluatedValue, + diags: *?Diagnostics, +) !RecursiveEvalResult { + assert(call_depth < call_depth_max); + assert(owis.len != 0); + assert(values.len != 0); + + return switch (owis[0].op) { + .value => .{ + .value = values[0].num, + .index = values[0].index, + .consumed = .{ + .ops = 1, + .values = 1, + }, + }, + .negative => .{ + .value = -values[0].num, + .index = values[0].index, + .consumed = .{ + .ops = 2, + .values = 1, + }, + }, + .bit_reverse => blk: { + if (values[0].num >= std.math.maxInt(u32) or + values[0].num < std.math.minInt(i32)) + { + diags.* = Diagnostics.init(owis[0].index, "Evaluated value does not fit in 32-bits: 0x{x}", .{values[0].num}); + return error.EvaluatedValueDoesntFit; + } + + break :blk .{ + .value = @bitCast(i128, @bitReverse(@bitCast(u128, values[0].num)) >> (128 - 32)), + .index = values[0].index, + .consumed = .{ + .ops = 2, + .values = 1, + }, + }; + }, + .add, .sub, .mul, .div => blk: { + const rhs = try recursive_evaluate(call_depth + 1, owis[1..], values, diags); + const lhs = try recursive_evaluate(call_depth + 1, owis[1 + rhs.consumed.ops ..], values[rhs.consumed.values..], diags); + break :blk .{ + .consumed = .{ + .ops = 1 + lhs.consumed.ops + rhs.consumed.ops, + .values = lhs.consumed.values + rhs.consumed.values, + }, + .index = lhs.index, + .value = switch (owis[0].op) { + .add => lhs.value + rhs.value, + .sub => lhs.value - rhs.value, + .mul => lhs.value * rhs.value, + .div => div: { + if (rhs.value == 0) { + diags.* = Diagnostics.init(owis[0].index, "divide by zero (denominator evaluates to zero)", .{}); + return error.DivideByZero; + } + + // TODO: other requirement for @divExact + break :div @divExact(lhs.value, rhs.value); + }, + else => unreachable, + }, + }; + }, + }; +} + +const expect = std.testing.expect; +const expectEqual = std.testing.expectEqual; +const expectEqualStrings = std.testing.expectEqualStrings; + +fn expect_equal_slices_of_values( + expected: []const Value, + actual: []const Value, +) !void { + for (expected, actual) |e, a| { + try expectEqualStrings(e.str, a.str); + try expectEqual(e.index, a.index); + } +} + +fn expect_equal_slices_of_ops( + expected: []const OperationWithIndex, + actual: []const OperationWithIndex, +) !void { + for (expected, actual) |e, a| { + try expectEqual(e.op, a.op); + try expectEqual(e.index, a.index); + } +} + +test "expr.tokenize.integer" { + var diags: ?Diagnostics = null; + const expr = try tokenize("1", 0, &diags); + + try expect_equal_slices_of_ops(&.{ + .{ .index = 0, .op = .value }, + }, expr.ops.slice()); + + try expect_equal_slices_of_values(&.{ + .{ .index = 0, .str = "1" }, + }, expr.values.slice()); +} + +test "expr.tokenize.integer.parenthesis" { + var diags: ?Diagnostics = null; + const expr = try tokenize("(1)", 0, &diags); + + try expect_equal_slices_of_ops(&.{ + .{ .index = 1, .op = .value }, + }, expr.ops.slice()); + + try expect_equal_slices_of_values(&.{ + .{ .index = 1, .str = "1" }, + }, expr.values.slice()); +} + +test "expr.tokenize.integer.double parenthesis" { + var diags: ?Diagnostics = null; + const expr = try tokenize("((1))", 0, &diags); + + try expect_equal_slices_of_ops(&.{ + .{ .index = 2, .op = .value }, + }, expr.ops.slice()); + + try expect_equal_slices_of_values(&.{ + .{ .index = 2, .str = "1" }, + }, expr.values.slice()); +} + +test "expr.tokenize.symbol" { + var diags: ?Diagnostics = null; + const expr = try tokenize("BAR", 0, &diags); + + try expect_equal_slices_of_ops(&.{ + .{ .index = 0, .op = .value }, + }, expr.ops.slice()); + + try expect_equal_slices_of_values(&.{ + .{ .index = 0, .str = "BAR" }, + }, expr.values.slice()); +} + +test "expr.tokenize.add" { + var diags: ?Diagnostics = null; + const expr = try tokenize("1 + 2", 0, &diags); + + try expect_equal_slices_of_ops(&.{ + .{ .index = 2, .op = .add }, + .{ .index = 4, .op = .value }, + .{ .index = 0, .op = .value }, + }, expr.ops.slice()); + + try expect_equal_slices_of_values(&.{ + .{ .index = 4, .str = "2" }, + .{ .index = 0, .str = "1" }, + }, expr.values.slice()); +} + +test "expr.tokenize.add.chain" { + var diags: ?Diagnostics = null; + const expr = try tokenize("1 + 2 + 3", 0, &diags); + + try expect_equal_slices_of_ops(&.{ + .{ .index = 6, .op = .add }, + .{ .index = 8, .op = .value }, + .{ .index = 2, .op = .add }, + .{ .index = 4, .op = .value }, + .{ .index = 0, .op = .value }, + }, expr.ops.slice()); + + try expect_equal_slices_of_values(&.{ + .{ .index = 8, .str = "3" }, + .{ .index = 4, .str = "2" }, + .{ .index = 0, .str = "1" }, + }, expr.values.slice()); +} + +test "expr.tokenize.sub" { + var diags: ?Diagnostics = null; + const expr = try tokenize("1 - 2", 0, &diags); + + try expect_equal_slices_of_ops(&.{ + .{ .index = 2, .op = .sub }, + .{ .index = 4, .op = .value }, + .{ .index = 0, .op = .value }, + }, expr.ops.slice()); + + try expect_equal_slices_of_values(&.{ + .{ .index = 4, .str = "2" }, + .{ .index = 0, .str = "1" }, + }, expr.values.slice()); +} + +test "expr.tokenize.sub.nospace" { + var diags: ?Diagnostics = null; + const expr = try tokenize("1-2", 0, &diags); + + try expect_equal_slices_of_ops(&.{ + .{ .index = 1, .op = .sub }, + .{ .index = 2, .op = .value }, + .{ .index = 0, .op = .value }, + }, expr.ops.slice()); + + try expect_equal_slices_of_values(&.{ + .{ .index = 2, .str = "2" }, + .{ .index = 0, .str = "1" }, + }, expr.values.slice()); +} + +test "expr.tokenize.sub.negative" { + var diags: ?Diagnostics = null; + const expr = try tokenize("1 - -2", 0, &diags); + + try expect_equal_slices_of_ops(&.{ + .{ .index = 2, .op = .sub }, + .{ .index = 4, .op = .negative }, + .{ .index = 5, .op = .value }, + .{ .index = 0, .op = .value }, + }, expr.ops.slice()); + + try expect_equal_slices_of_values(&.{ + .{ .index = 5, .str = "2" }, + .{ .index = 0, .str = "1" }, + }, expr.values.slice()); +} + +test "expr.tokenize.mul" { + var diags: ?Diagnostics = null; + const expr = try tokenize("1 * 2", 0, &diags); + + try expect_equal_slices_of_ops(&.{ + .{ .index = 2, .op = .mul }, + .{ .index = 4, .op = .value }, + .{ .index = 0, .op = .value }, + }, expr.ops.slice()); + + try expect_equal_slices_of_values(&.{ + .{ .index = 4, .str = "2" }, + .{ .index = 0, .str = "1" }, + }, expr.values.slice()); +} + +test "expr.tokenize.div" { + var diags: ?Diagnostics = null; + const expr = try tokenize("1 / 2", 0, &diags); + + try expect_equal_slices_of_ops(&.{ + .{ .index = 2, .op = .div }, + .{ .index = 4, .op = .value }, + .{ .index = 0, .op = .value }, + }, expr.ops.slice()); + + try expect_equal_slices_of_values(&.{ + .{ .index = 4, .str = "2" }, + .{ .index = 0, .str = "1" }, + }, expr.values.slice()); +} + +test "expr.tokenize.negative" { + var diags: ?Diagnostics = null; + const expr = try tokenize("-1", 0, &diags); + + try expect_equal_slices_of_ops(&.{ + .{ .index = 0, .op = .negative }, + .{ .index = 1, .op = .value }, + }, expr.ops.slice()); + + try expect_equal_slices_of_values(&.{ + .{ .index = 1, .str = "1" }, + }, expr.values.slice()); +} + +test "expr.tokenize.bit reverse" { + var diags: ?Diagnostics = null; + const expr = try tokenize("::1", 0, &diags); + + try expect_equal_slices_of_ops(&.{ + .{ .index = 0, .op = .bit_reverse }, + .{ .index = 2, .op = .value }, + }, expr.ops.slice()); + + try expect_equal_slices_of_values(&.{ + .{ .index = 2, .str = "1" }, + }, expr.values.slice()); +} + +test "expr.tokenzie.parenthesis" { + var diags: ?Diagnostics = null; + const expr = try tokenize("1 * (::2 + (12 / 3)) - 5", 0, &diags); + + try expect_equal_slices_of_ops(&.{ + .{ .index = 21, .op = .sub }, + .{ .index = 23, .op = .value }, + .{ .index = 2, .op = .mul }, + .{ .index = 9, .op = .add }, + .{ .index = 15, .op = .div }, + .{ .index = 17, .op = .value }, + .{ .index = 12, .op = .value }, + .{ .index = 5, .op = .bit_reverse }, + .{ .index = 7, .op = .value }, + .{ .index = 0, .op = .value }, + }, expr.ops.slice()); + + try expect_equal_slices_of_values(&.{ + .{ .index = 23, .str = "5" }, + .{ .index = 17, .str = "3" }, + .{ .index = 12, .str = "12" }, + .{ .index = 7, .str = "2" }, + .{ .index = 0, .str = "1" }, + }, expr.values.slice()); +} + +fn evaluate_test(expected: i128, str: []const u8, define_list: []const DefineWithIndex) !void { + var diags: ?Diagnostics = null; + const expr = tokenize(str, 0, &diags) catch |err| { + if (diags) |d| + std.log.err("{}: {s}", .{ err, d.message.slice() }); + + return err; + }; + + const actual = expr.evaluate(&.{define_list}, &diags) catch |err| { + if (diags) |d| + std.log.err("{}: {s}", .{ err, d.message.slice() }) + else + std.log.err("{}", .{err}); + + return err; + }; + + try expectEqual(expected, actual); +} + +test "expr.evaluate.integer" { + try evaluate_test(1, "1", &.{}); +} + +test "expr.evaluate.symbol" { + try evaluate_test(5, "BAR", &.{ + .{ + .name = "BAR", + .value = 5, + .index = 0, + }, + }); +} + +test "expr.evaluate.add" { + try evaluate_test(3, "1 + 2", &.{}); + try evaluate_test(6, "1 + 2 + 3", &.{}); +} + +test "expr.evaluate.sub" { + try evaluate_test(1, "2 - 1", &.{}); + try evaluate_test(1, "(NUM_CYCLES - 1)", &.{ + .{ + .name = "NUM_CYCLES", + .value = 2, + .index = 1, + }, + }); +} + +test "expr.evaluate.mul" { + try evaluate_test(9, "3 * 3", &.{}); +} + +test "expr.evaluate.div" { + try evaluate_test(3, "9 / 3", &.{}); + try evaluate_test(3, "9 / 3", &.{}); +} + +test "expr.evaluate.negative" { + try evaluate_test(-3, "-3", &.{}); +} + +test "expr.evaluate.bit reverse" { + try evaluate_test(0x80000000, "::1", &.{}); +} + +test "expr.evaluate.parenthesis" { + try evaluate_test(15, "5 * (1 + 2)", &.{}); + try evaluate_test(1 * (@bitReverse(@as(u32, 2)) + (12 / 3)) - 5, "1 * (::2 + (12 / 3)) - 5", &.{}); +} diff --git a/src/hal/pio/assembler/comparison_tests.zig b/src/hal/pio/assembler/comparison_tests.zig new file mode 100644 index 0000000..4a39465 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests.zig @@ -0,0 +1,168 @@ +const std = @import("std"); +const assembler = @import("../assembler.zig"); +const tokenizer = @import("tokenizer.zig"); +const c = @cImport({ + @cDefine("PICO_NO_HARDWARE", "1"); + @cInclude("stdint.h"); + @cInclude("comparison_tests/addition.pio.h"); + @cInclude("comparison_tests/apa102.pio.h"); + @cInclude("comparison_tests/blink.pio.h"); + @cInclude("comparison_tests/clocked_input.pio.h"); + @cInclude("comparison_tests/differential_manchester.pio.h"); + @cInclude("comparison_tests/hello.pio.h"); + @cInclude("comparison_tests/hub75.pio.h"); + @cInclude("comparison_tests/i2c.pio.h"); + @cInclude("comparison_tests/manchester_encoding.pio.h"); + @cInclude("comparison_tests/nec_carrier_burst.pio.h"); + @cInclude("comparison_tests/nec_carrier_control.pio.h"); + @cInclude("comparison_tests/nec_receive.pio.h"); + @cInclude("comparison_tests/pio_serialiser.pio.h"); + @cInclude("comparison_tests/pwm.pio.h"); + @cInclude("comparison_tests/quadrature_encoder.pio.h"); + @cInclude("comparison_tests/resistor_dac.pio.h"); + @cInclude("comparison_tests/spi.pio.h"); + @cInclude("comparison_tests/squarewave.pio.h"); + @cInclude("comparison_tests/squarewave_fast.pio.h"); + @cInclude("comparison_tests/squarewave_wrap.pio.h"); + @cInclude("comparison_tests/st7789_lcd.pio.h"); + @cInclude("comparison_tests/uart_rx.pio.h"); + @cInclude("comparison_tests/uart_tx.pio.h"); + @cInclude("comparison_tests/ws2812.pio.h"); +}); + +fn pio_comparison(comptime source: []const u8) !void { + const output = comptime assembler.assemble(source, .{}) catch unreachable; + try std.testing.expect(output.programs.len > 0); + + inline for (output.programs) |program| { + const expected_insns = @field(c, program.name ++ "_program_instructions"); + for (program.instructions, expected_insns) |actual, expected| { + std.log.debug("expected: 0x{x}", .{expected}); + std.log.debug(" actual: 0x{x}", .{actual}); + std.log.debug("", .{}); + } + + for (program.instructions, expected_insns) |actual, expected| + try std.testing.expectEqual(expected, actual); + } +} + +test "pio.comparison.addition" { + @setEvalBranchQuota(4000); + try pio_comparison(@embedFile("comparison_tests/addition.pio")); +} + +test "pio.comparison.apa102" { + @setEvalBranchQuota(10000); + try pio_comparison(@embedFile("comparison_tests/apa102.pio")); +} + +test "pio.comparison.blink" { + @setEvalBranchQuota(4000); + try pio_comparison(@embedFile("comparison_tests/blink.pio")); +} + +test "pio.comparison.clocked_input" { + @setEvalBranchQuota(5000); + try pio_comparison(@embedFile("comparison_tests/clocked_input.pio")); +} + +test "pio.comparison.differential_manchester" { + @setEvalBranchQuota(14000); + try pio_comparison(@embedFile("comparison_tests/differential_manchester.pio")); +} + +test "pio.comparison.hello" { + @setEvalBranchQuota(3000); + try pio_comparison(@embedFile("comparison_tests/hello.pio")); +} + +test "pio.comparison.hub75" { + @setEvalBranchQuota(17000); + try pio_comparison(@embedFile("comparison_tests/hub75.pio")); +} + +test "pio.comparison.i2c" { + @setEvalBranchQuota(17000); + try pio_comparison(@embedFile("comparison_tests/i2c.pio")); +} + +test "pio.comparison.manchester_encoding" { + @setEvalBranchQuota(11000); + try pio_comparison(@embedFile("comparison_tests/manchester_encoding.pio")); +} + +test "pio.comparison.nec_carrier_burst" { + @setEvalBranchQuota(6000); + try pio_comparison(@embedFile("comparison_tests/nec_carrier_burst.pio")); +} + +test "pio.comparison.nec_carrier_control" { + @setEvalBranchQuota(9000); + try pio_comparison(@embedFile("comparison_tests/nec_carrier_control.pio")); +} + +test "pio.comparison.nec_receive" { + @setEvalBranchQuota(11000); + try pio_comparison(@embedFile("comparison_tests/nec_receive.pio")); +} + +test "pio.comparison.pio_serialiser" { + @setEvalBranchQuota(3000); + try pio_comparison(@embedFile("comparison_tests/pio_serialiser.pio")); +} + +test "pio.comparison.pwm" { + @setEvalBranchQuota(4000); + try pio_comparison(@embedFile("comparison_tests/pwm.pio")); +} + +test "pio.comparison.quadrature_encoder" { + @setEvalBranchQuota(17000); + try pio_comparison(@embedFile("comparison_tests/quadrature_encoder.pio")); +} + +test "pio.comparison.resistor_dac" { + @setEvalBranchQuota(3000); + try pio_comparison(@embedFile("comparison_tests/resistor_dac.pio")); +} + +test "pio.comparison.spi" { + @setEvalBranchQuota(22000); + try pio_comparison(@embedFile("comparison_tests/spi.pio")); +} + +test "pio.comparison.squarewave" { + @setEvalBranchQuota(2000); + try pio_comparison(@embedFile("comparison_tests/squarewave.pio")); +} + +test "pio.comparison.squarewave_fast" { + @setEvalBranchQuota(2000); + try pio_comparison(@embedFile("comparison_tests/squarewave_fast.pio")); +} + +test "pio.comparison.squarewave_wrap" { + @setEvalBranchQuota(3000); + try pio_comparison(@embedFile("comparison_tests/squarewave_wrap.pio")); +} + +test "pio.comparison.st7789_lcd" { + @setEvalBranchQuota(5000); + try pio_comparison(@embedFile("comparison_tests/st7789_lcd.pio")); +} + +test "pio.comparison.uart_rx" { + @setEvalBranchQuota(10000); + try pio_comparison(@embedFile("comparison_tests/uart_rx.pio")); +} + +test "pio.comparison.uart_tx" { + @setEvalBranchQuota(6000); + try pio_comparison(@embedFile("comparison_tests/uart_tx.pio")); +} + +test "pio.comparison.ws2812" { + @setEvalBranchQuota(10000); + try pio_comparison(@embedFile("comparison_tests/ws2812.pio")); +} diff --git a/src/hal/pio/assembler/comparison_tests/README.adoc b/src/hal/pio/assembler/comparison_tests/README.adoc new file mode 100644 index 0000000..872e125 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/README.adoc @@ -0,0 +1,4 @@ += PIO example programs for testing + +These were all taken from https://github.com/raspberrypi/pico-examples[the official pico examples repo]. +The headers are generated using `pioasm`. diff --git a/src/hal/pio/assembler/comparison_tests/addition.pio b/src/hal/pio/assembler/comparison_tests/addition.pio new file mode 100644 index 0000000..8eddd0e --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/addition.pio @@ -0,0 +1,33 @@ +; +; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; + +.program addition + +; Pop two 32 bit integers from the TX FIFO, add them together, and push the +; result to the TX FIFO. Autopush/pull should be disabled as we're using +; explicit push and pull instructions. +; +; This program uses the two's complement identity x + y == ~(~x - y) + + pull + mov x, ~osr + pull + mov y, osr + jmp test ; this loop is equivalent to the following C code: +incr: ; while (y--) + jmp x-- test ; x--; +test: ; This has the effect of subtracting y from x, eventually. + jmp y-- incr + mov isr, ~x + push + +% c-sdk { +static inline void addition_program_init(PIO pio, uint sm, uint offset) { + pio_sm_config c = addition_program_get_default_config(offset); + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); +} +%} diff --git a/src/hal/pio/assembler/comparison_tests/addition.pio.h b/src/hal/pio/assembler/comparison_tests/addition.pio.h new file mode 100644 index 0000000..7621c58 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/addition.pio.h @@ -0,0 +1,52 @@ +// -------------------------------------------------- // +// This file is autogenerated by pioasm; do not edit! // +// -------------------------------------------------- // + +#pragma once + +#if !PICO_NO_HARDWARE +#include "hardware/pio.h" +#endif + +// -------- // +// addition // +// -------- // + +#define addition_wrap_target 0 +#define addition_wrap 8 + +static const uint16_t addition_program_instructions[] = { + // .wrap_target + 0x80a0, // 0: pull block + 0xa02f, // 1: mov x, !osr + 0x80a0, // 2: pull block + 0xa047, // 3: mov y, osr + 0x0006, // 4: jmp 6 + 0x0046, // 5: jmp x--, 6 + 0x0085, // 6: jmp y--, 5 + 0xa0c9, // 7: mov isr, !x + 0x8020, // 8: push block + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program addition_program = { + .instructions = addition_program_instructions, + .length = 9, + .origin = -1, +}; + +static inline pio_sm_config addition_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + addition_wrap_target, offset + addition_wrap); + return c; +} + +static inline void addition_program_init(PIO pio, uint sm, uint offset) { + pio_sm_config c = addition_program_get_default_config(offset); + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); +} + +#endif + diff --git a/src/hal/pio/assembler/comparison_tests/apa102.pio b/src/hal/pio/assembler/comparison_tests/apa102.pio new file mode 100644 index 0000000..5d76f08 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/apa102.pio @@ -0,0 +1,89 @@ +; +; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; + +.program apa102_mini +.side_set 1 + +; This is really just a TX-only SPI. CLK is side-set pin 0, DIN is OUT pin 0. +; Autopull enabled, threshold 32. +; +; Every word (32 bits) written to the FIFO will be shifted out in its entirety, MSB-first. + + out pins, 1 side 0 ; Stall here when no data (still asserts clock low) + nop side 1 + +% c-sdk { +#include "hardware/clocks.h" +static inline void apa102_mini_program_init(PIO pio, uint sm, uint offset, + uint baud, uint pin_clk, uint pin_din) { + pio_sm_set_pins_with_mask(pio, sm, 0, (1u << pin_clk) | (1u << pin_din)); + pio_sm_set_pindirs_with_mask(pio, sm, ~0u, (1u << pin_clk) | (1u << pin_din)); + pio_gpio_init(pio, pin_clk); + pio_gpio_init(pio, pin_din); + + pio_sm_config c = apa102_mini_program_get_default_config(offset); + sm_config_set_out_pins(&c, pin_din, 1); + sm_config_set_sideset_pins(&c, pin_clk); + // Shift to right, autopull with threshold 32 + sm_config_set_out_shift(&c, false, true, 32); + // Deeper FIFO as we're not doing any RX + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); + // We transmit 1 bit every 2 execution cycles + float div = (float)clock_get_hz(clk_sys) / (2 * baud); + sm_config_set_clkdiv(&c, div); + + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); +} +%} + +.program apa102_rgb555 + +; Alternative program to unpack two RGB555 pixels from a FIFO word and transmit. +; This makes it easier to DMA large buffers without processor involvement. + +; OSR: shift to right +; ISR: shift to right + +; To set brightness, set ISR to bit-reverse of 5-bit brightness, +; followed by 111. (00...00_b0b1b2b3b4_111) + +; DMA pixel format is 0RRRRRGGGGGBBBBB x2 (15 bpp, 2px per FIFO word) + +; APA102 command structure: +; increasing time ---->> +; | byte 3 | byte 2 | byte 1 | byte 0 | +; |7 0|7 0|7 0|7 0| +; ------------------------------------- +; Pixel |111bbbbb|BBBBBBBB|GGGGGGGG|RRRRRRRR| +; Start Frame |00000000|00000000|00000000|00000000| +; Stop Frame |11111111|11111111|11111111|11111111| + +.wrap_target +public pixel_out: + ; pixel_out formats an APA102 colour command in the ISR. + ; bit_run shifts 32 bits out of the ISR, with clock. + pull ifempty + set x, 2 +colour_loop: + in osr, 5 + out null, 5 + in null, 3 + jmp x-- colour_loop + in y, 8 + mov isr, ::isr ; reverse for msb-first wire order + out null, 1 +public bit_run: + ; in isr, n rotates ISR by n bits (right rotation only) + ; Use this to perform out shifts from ISR, via mov pins + set x, 31 +bit_out: + set pins, 0 + mov pins, isr [6] + set pins, 1 + in isr, 1 [6] + jmp x-- bit_out +.wrap diff --git a/src/hal/pio/assembler/comparison_tests/apa102.pio.h b/src/hal/pio/assembler/comparison_tests/apa102.pio.h new file mode 100644 index 0000000..fd5a520 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/apa102.pio.h @@ -0,0 +1,105 @@ +// -------------------------------------------------- // +// This file is autogenerated by pioasm; do not edit! // +// -------------------------------------------------- // + +#pragma once + +#if !PICO_NO_HARDWARE +#include "hardware/pio.h" +#endif + +// ----------- // +// apa102_mini // +// ----------- // + +#define apa102_mini_wrap_target 0 +#define apa102_mini_wrap 1 + +static const uint16_t apa102_mini_program_instructions[] = { + // .wrap_target + 0x6001, // 0: out pins, 1 side 0 + 0xb042, // 1: nop side 1 + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program apa102_mini_program = { + .instructions = apa102_mini_program_instructions, + .length = 2, + .origin = -1, +}; + +static inline pio_sm_config apa102_mini_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + apa102_mini_wrap_target, offset + apa102_mini_wrap); + sm_config_set_sideset(&c, 1, false, false); + return c; +} + +#include "hardware/clocks.h" +static inline void apa102_mini_program_init(PIO pio, uint sm, uint offset, + uint baud, uint pin_clk, uint pin_din) { + pio_sm_set_pins_with_mask(pio, sm, 0, (1u << pin_clk) | (1u << pin_din)); + pio_sm_set_pindirs_with_mask(pio, sm, ~0u, (1u << pin_clk) | (1u << pin_din)); + pio_gpio_init(pio, pin_clk); + pio_gpio_init(pio, pin_din); + pio_sm_config c = apa102_mini_program_get_default_config(offset); + sm_config_set_out_pins(&c, pin_din, 1); + sm_config_set_sideset_pins(&c, pin_clk); + // Shift to right, autopull with threshold 32 + sm_config_set_out_shift(&c, false, true, 32); + // Deeper FIFO as we're not doing any RX + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); + // We transmit 1 bit every 2 execution cycles + float div = (float)clock_get_hz(clk_sys) / (2 * baud); + sm_config_set_clkdiv(&c, div); + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); +} + +#endif + +// ------------- // +// apa102_rgb555 // +// ------------- // + +#define apa102_rgb555_wrap_target 0 +#define apa102_rgb555_wrap 14 + +#define apa102_rgb555_offset_pixel_out 0u +#define apa102_rgb555_offset_bit_run 9u + +static const uint16_t apa102_rgb555_program_instructions[] = { + // .wrap_target + 0x80e0, // 0: pull ifempty block + 0xe022, // 1: set x, 2 + 0x40e5, // 2: in osr, 5 + 0x6065, // 3: out null, 5 + 0x4063, // 4: in null, 3 + 0x0042, // 5: jmp x--, 2 + 0x4048, // 6: in y, 8 + 0xa0d6, // 7: mov isr, ::isr + 0x6061, // 8: out null, 1 + 0xe03f, // 9: set x, 31 + 0xe000, // 10: set pins, 0 + 0xa606, // 11: mov pins, isr [6] + 0xe001, // 12: set pins, 1 + 0x46c1, // 13: in isr, 1 [6] + 0x004a, // 14: jmp x--, 10 + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program apa102_rgb555_program = { + .instructions = apa102_rgb555_program_instructions, + .length = 15, + .origin = -1, +}; + +static inline pio_sm_config apa102_rgb555_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + apa102_rgb555_wrap_target, offset + apa102_rgb555_wrap); + return c; +} +#endif + diff --git a/src/hal/pio/assembler/comparison_tests/blink.pio b/src/hal/pio/assembler/comparison_tests/blink.pio new file mode 100644 index 0000000..ef30900 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/blink.pio @@ -0,0 +1,34 @@ +; +; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; + +; SET pin 0 should be mapped to your LED GPIO + +.program blink + pull block + out y, 32 +.wrap_target + mov x, y + set pins, 1 ; Turn LED on +lp1: + jmp x-- lp1 ; Delay for (x + 1) cycles, x is a 32 bit number + mov x, y + set pins, 0 ; Turn LED off +lp2: + jmp x-- lp2 ; Delay for the same number of cycles again +.wrap ; Blink forever! + + +% c-sdk { +// this is a raw helper function for use by the user which sets up the GPIO output, and configures the SM to output on a particular pin + +void blink_program_init(PIO pio, uint sm, uint offset, uint pin) { + pio_gpio_init(pio, pin); + pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true); + pio_sm_config c = blink_program_get_default_config(offset); + sm_config_set_set_pins(&c, pin, 1); + pio_sm_init(pio, sm, offset, &c); +} +%} diff --git a/src/hal/pio/assembler/comparison_tests/blink.pio.h b/src/hal/pio/assembler/comparison_tests/blink.pio.h new file mode 100644 index 0000000..e466a28 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/blink.pio.h @@ -0,0 +1,54 @@ +// -------------------------------------------------- // +// This file is autogenerated by pioasm; do not edit! // +// -------------------------------------------------- // + +#pragma once + +#if !PICO_NO_HARDWARE +#include "hardware/pio.h" +#endif + +// ----- // +// blink // +// ----- // + +#define blink_wrap_target 2 +#define blink_wrap 7 + +static const uint16_t blink_program_instructions[] = { + 0x80a0, // 0: pull block + 0x6040, // 1: out y, 32 + // .wrap_target + 0xa022, // 2: mov x, y + 0xe001, // 3: set pins, 1 + 0x0044, // 4: jmp x--, 4 + 0xa022, // 5: mov x, y + 0xe000, // 6: set pins, 0 + 0x0047, // 7: jmp x--, 7 + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program blink_program = { + .instructions = blink_program_instructions, + .length = 8, + .origin = -1, +}; + +static inline pio_sm_config blink_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + blink_wrap_target, offset + blink_wrap); + return c; +} + +// this is a raw helper function for use by the user which sets up the GPIO output, and configures the SM to output on a particular pin +void blink_program_init(PIO pio, uint sm, uint offset, uint pin) { + pio_gpio_init(pio, pin); + pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true); + pio_sm_config c = blink_program_get_default_config(offset); + sm_config_set_set_pins(&c, pin, 1); + pio_sm_init(pio, sm, offset, &c); +} + +#endif + diff --git a/src/hal/pio/assembler/comparison_tests/clocked_input.pio b/src/hal/pio/assembler/comparison_tests/clocked_input.pio new file mode 100644 index 0000000..51fa54c --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/clocked_input.pio @@ -0,0 +1,51 @@ +; +; Copyright (c) 2021 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; + +.program clocked_input + +; Sample bits using an external clock, and push groups of bits into the RX FIFO. +; - IN pin 0 is the data pin +; - IN pin 1 is the clock pin +; - Autopush is enabled, threshold 8 +; +; This program samples data with each rising clock edge (like mode 0 or mode 3 +; SPI). The data is actually sampled one system clock cycle after the rising +; edge is observed, so a clock ratio of at least input_clk < clk_sys / 6 is +; recommended for good sampling alignment. + + wait 0 pin 1 + wait 1 pin 1 + in pins, 1 + +% c-sdk { +static inline void clocked_input_program_init(PIO pio, uint sm, uint offset, uint pin) { + pio_sm_config c = clocked_input_program_get_default_config(offset); + + // Set the IN base pin to the provided `pin` parameter. This is the data + // pin, and the next-numbered GPIO is used as the clock pin. + sm_config_set_in_pins(&c, pin); + // Set the pin directions to input at the PIO + pio_sm_set_consecutive_pindirs(pio, sm, pin, 2, false); + // Connect these GPIOs to this PIO block + pio_gpio_init(pio, pin); + pio_gpio_init(pio, pin + 1); + + // Shifting to left matches the customary MSB-first ordering of SPI. + sm_config_set_in_shift( + &c, + false, // Shift-to-right = false (i.e. shift to left) + true, // Autopush enabled + 8 // Autopush threshold = 8 + ); + + // We only receive, so disable the TX FIFO to make the RX FIFO deeper. + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX); + + // Load our configuration, and start the program from the beginning + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); +} +%} diff --git a/src/hal/pio/assembler/comparison_tests/clocked_input.pio.h b/src/hal/pio/assembler/comparison_tests/clocked_input.pio.h new file mode 100644 index 0000000..277b939 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/clocked_input.pio.h @@ -0,0 +1,64 @@ +// -------------------------------------------------- // +// This file is autogenerated by pioasm; do not edit! // +// -------------------------------------------------- // + +#pragma once + +#if !PICO_NO_HARDWARE +#include "hardware/pio.h" +#endif + +// ------------- // +// clocked_input // +// ------------- // + +#define clocked_input_wrap_target 0 +#define clocked_input_wrap 2 + +static const uint16_t clocked_input_program_instructions[] = { + // .wrap_target + 0x2021, // 0: wait 0 pin, 1 + 0x20a1, // 1: wait 1 pin, 1 + 0x4001, // 2: in pins, 1 + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program clocked_input_program = { + .instructions = clocked_input_program_instructions, + .length = 3, + .origin = -1, +}; + +static inline pio_sm_config clocked_input_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + clocked_input_wrap_target, offset + clocked_input_wrap); + return c; +} + +static inline void clocked_input_program_init(PIO pio, uint sm, uint offset, uint pin) { + pio_sm_config c = clocked_input_program_get_default_config(offset); + // Set the IN base pin to the provided `pin` parameter. This is the data + // pin, and the next-numbered GPIO is used as the clock pin. + sm_config_set_in_pins(&c, pin); + // Set the pin directions to input at the PIO + pio_sm_set_consecutive_pindirs(pio, sm, pin, 2, false); + // Connect these GPIOs to this PIO block + pio_gpio_init(pio, pin); + pio_gpio_init(pio, pin + 1); + // Shifting to left matches the customary MSB-first ordering of SPI. + sm_config_set_in_shift( + &c, + false, // Shift-to-right = false (i.e. shift to left) + true, // Autopush enabled + 8 // Autopush threshold = 8 + ); + // We only receive, so disable the TX FIFO to make the RX FIFO deeper. + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX); + // Load our configuration, and start the program from the beginning + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); +} + +#endif + diff --git a/src/hal/pio/assembler/comparison_tests/differential_manchester.pio b/src/hal/pio/assembler/comparison_tests/differential_manchester.pio new file mode 100644 index 0000000..a9e825d --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/differential_manchester.pio @@ -0,0 +1,104 @@ +; +; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; + +.program differential_manchester_tx +.side_set 1 opt + +; Transmit one bit every 16 cycles. In each bit period: +; - A '0' is encoded as a transition at the start of the bit period +; - A '1' is encoded as a transition at the start *and* in the middle +; +; Side-set bit 0 must be mapped to the data output pin. +; Autopull must be enabled. + +public start: +initial_high: + out x, 1 ; Start of bit period: always assert transition + jmp !x high_0 side 1 [6] ; Test the data bit we just shifted out of OSR +high_1: + nop + jmp initial_high side 0 [6] ; For `1` bits, also transition in the middle +high_0: + jmp initial_low [7] ; Otherwise, the line is stable in the middle + +initial_low: + out x, 1 ; Always shift 1 bit from OSR to X so we can + jmp !x low_0 side 0 [6] ; branch on it. Autopull refills OSR for us. +low_1: + nop + jmp initial_low side 1 [6] ; If there are two transitions, return to +low_0: + jmp initial_high [7] ; the initial line state is flipped! + +% c-sdk { +static inline void differential_manchester_tx_program_init(PIO pio, uint sm, uint offset, uint pin, float div) { + pio_sm_set_pins_with_mask(pio, sm, 0, 1u << pin); + pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true); + pio_gpio_init(pio, pin); + + pio_sm_config c = differential_manchester_tx_program_get_default_config(offset); + sm_config_set_sideset_pins(&c, pin); + sm_config_set_out_shift(&c, true, true, 32); + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); + sm_config_set_clkdiv(&c, div); + pio_sm_init(pio, sm, offset + differential_manchester_tx_offset_start, &c); + + // Execute a blocking pull so that we maintain the initial line state until data is available + pio_sm_exec(pio, sm, pio_encode_pull(false, true)); + pio_sm_set_enabled(pio, sm, true); +} +%} +.program differential_manchester_rx + +; Assumes line is idle low +; One bit is 16 cycles. In each bit period: +; - A '0' is encoded as a transition at time 0 +; - A '1' is encoded as a transition at time 0 and a transition at time T/2 +; +; The IN mapping and the JMP pin select must both be mapped to the GPIO used for +; RX data. Autopush must be enabled. + +public start: +initial_high: ; Find rising edge at start of bit period + wait 1 pin, 0 [11] ; Delay to eye of second half-period (i.e 3/4 of way + jmp pin high_0 ; through bit) and branch on RX pin high/low. +high_1: + in x, 1 ; Second transition detected (a `1` data symbol) + jmp initial_high +high_0: + in y, 1 [1] ; Line still high, no centre transition (data is `0`) + ; Fall-through + +.wrap_target +initial_low: ; Find falling edge at start of bit period + wait 0 pin, 0 [11] ; Delay to eye of second half-period + jmp pin low_1 +low_0: + in y, 1 ; Line still low, no centre transition (data is `0`) + jmp initial_high +low_1: ; Second transition detected (data is `1`) + in x, 1 [1] +.wrap + +% c-sdk { +static inline void differential_manchester_rx_program_init(PIO pio, uint sm, uint offset, uint pin, float div) { + pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, false); + pio_gpio_init(pio, pin); + + pio_sm_config c = differential_manchester_rx_program_get_default_config(offset); + sm_config_set_in_pins(&c, pin); // for WAIT + sm_config_set_jmp_pin(&c, pin); // for JMP + sm_config_set_in_shift(&c, true, true, 32); + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX); + sm_config_set_clkdiv(&c, div); + pio_sm_init(pio, sm, offset, &c); + + // X and Y are set to 0 and 1, to conveniently emit these to ISR/FIFO. + pio_sm_exec(pio, sm, pio_encode_set(pio_x, 1)); + pio_sm_exec(pio, sm, pio_encode_set(pio_y, 0)); + pio_sm_set_enabled(pio, sm, true); +} +%} diff --git a/src/hal/pio/assembler/comparison_tests/differential_manchester.pio.h b/src/hal/pio/assembler/comparison_tests/differential_manchester.pio.h new file mode 100644 index 0000000..c8d76ca --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/differential_manchester.pio.h @@ -0,0 +1,120 @@ +// -------------------------------------------------- // +// This file is autogenerated by pioasm; do not edit! // +// -------------------------------------------------- // + +#pragma once + +#if !PICO_NO_HARDWARE +#include "hardware/pio.h" +#endif + +// -------------------------- // +// differential_manchester_tx // +// -------------------------- // + +#define differential_manchester_tx_wrap_target 0 +#define differential_manchester_tx_wrap 9 + +#define differential_manchester_tx_offset_start 0u + +static const uint16_t differential_manchester_tx_program_instructions[] = { + // .wrap_target + 0x6021, // 0: out x, 1 + 0x1e24, // 1: jmp !x, 4 side 1 [6] + 0xa042, // 2: nop + 0x1600, // 3: jmp 0 side 0 [6] + 0x0705, // 4: jmp 5 [7] + 0x6021, // 5: out x, 1 + 0x1629, // 6: jmp !x, 9 side 0 [6] + 0xa042, // 7: nop + 0x1e05, // 8: jmp 5 side 1 [6] + 0x0700, // 9: jmp 0 [7] + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program differential_manchester_tx_program = { + .instructions = differential_manchester_tx_program_instructions, + .length = 10, + .origin = -1, +}; + +static inline pio_sm_config differential_manchester_tx_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + differential_manchester_tx_wrap_target, offset + differential_manchester_tx_wrap); + sm_config_set_sideset(&c, 2, true, false); + return c; +} + +static inline void differential_manchester_tx_program_init(PIO pio, uint sm, uint offset, uint pin, float div) { + pio_sm_set_pins_with_mask(pio, sm, 0, 1u << pin); + pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true); + pio_gpio_init(pio, pin); + pio_sm_config c = differential_manchester_tx_program_get_default_config(offset); + sm_config_set_sideset_pins(&c, pin); + sm_config_set_out_shift(&c, true, true, 32); + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); + sm_config_set_clkdiv(&c, div); + pio_sm_init(pio, sm, offset + differential_manchester_tx_offset_start, &c); + // Execute a blocking pull so that we maintain the initial line state until data is available + pio_sm_exec(pio, sm, pio_encode_pull(false, true)); + pio_sm_set_enabled(pio, sm, true); +} + +#endif + +// -------------------------- // +// differential_manchester_rx // +// -------------------------- // + +#define differential_manchester_rx_wrap_target 5 +#define differential_manchester_rx_wrap 9 + +#define differential_manchester_rx_offset_start 0u + +static const uint16_t differential_manchester_rx_program_instructions[] = { + 0x2ba0, // 0: wait 1 pin, 0 [11] + 0x00c4, // 1: jmp pin, 4 + 0x4021, // 2: in x, 1 + 0x0000, // 3: jmp 0 + 0x4141, // 4: in y, 1 [1] + // .wrap_target + 0x2b20, // 5: wait 0 pin, 0 [11] + 0x00c9, // 6: jmp pin, 9 + 0x4041, // 7: in y, 1 + 0x0000, // 8: jmp 0 + 0x4121, // 9: in x, 1 [1] + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program differential_manchester_rx_program = { + .instructions = differential_manchester_rx_program_instructions, + .length = 10, + .origin = -1, +}; + +static inline pio_sm_config differential_manchester_rx_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + differential_manchester_rx_wrap_target, offset + differential_manchester_rx_wrap); + return c; +} + +static inline void differential_manchester_rx_program_init(PIO pio, uint sm, uint offset, uint pin, float div) { + pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, false); + pio_gpio_init(pio, pin); + pio_sm_config c = differential_manchester_rx_program_get_default_config(offset); + sm_config_set_in_pins(&c, pin); // for WAIT + sm_config_set_jmp_pin(&c, pin); // for JMP + sm_config_set_in_shift(&c, true, true, 32); + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX); + sm_config_set_clkdiv(&c, div); + pio_sm_init(pio, sm, offset, &c); + // X and Y are set to 0 and 1, to conveniently emit these to ISR/FIFO. + pio_sm_exec(pio, sm, pio_encode_set(pio_x, 1)); + pio_sm_exec(pio, sm, pio_encode_set(pio_y, 0)); + pio_sm_set_enabled(pio, sm, true); +} + +#endif + diff --git a/src/hal/pio/assembler/comparison_tests/hello.pio b/src/hal/pio/assembler/comparison_tests/hello.pio new file mode 100644 index 0000000..9eac4de --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/hello.pio @@ -0,0 +1,34 @@ +; +; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; + +.program hello + +; Repeatedly get one word of data from the TX FIFO, stalling when the FIFO is +; empty. Write the least significant bit to the OUT pin group. + +loop: + pull + out pins, 1 + jmp loop + +% c-sdk { +static inline void hello_program_init(PIO pio, uint sm, uint offset, uint pin) { + pio_sm_config c = hello_program_get_default_config(offset); + + // Map the state machine's OUT pin group to one pin, namely the `pin` + // parameter to this function. + sm_config_set_out_pins(&c, pin, 1); + // Set this pin's GPIO function (connect PIO to the pad) + pio_gpio_init(pio, pin); + // Set the pin direction to output at the PIO + pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true); + + // Load our configuration, and jump to the start of the program + pio_sm_init(pio, sm, offset, &c); + // Set the state machine running + pio_sm_set_enabled(pio, sm, true); +} +%} diff --git a/src/hal/pio/assembler/comparison_tests/hello.pio.h b/src/hal/pio/assembler/comparison_tests/hello.pio.h new file mode 100644 index 0000000..415d1cc --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/hello.pio.h @@ -0,0 +1,55 @@ +// -------------------------------------------------- // +// This file is autogenerated by pioasm; do not edit! // +// -------------------------------------------------- // + +#pragma once + +#if !PICO_NO_HARDWARE +#include "hardware/pio.h" +#endif + +// ----- // +// hello // +// ----- // + +#define hello_wrap_target 0 +#define hello_wrap 2 + +static const uint16_t hello_program_instructions[] = { + // .wrap_target + 0x80a0, // 0: pull block + 0x6001, // 1: out pins, 1 + 0x0000, // 2: jmp 0 + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program hello_program = { + .instructions = hello_program_instructions, + .length = 3, + .origin = -1, +}; + +static inline pio_sm_config hello_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + hello_wrap_target, offset + hello_wrap); + return c; +} + +static inline void hello_program_init(PIO pio, uint sm, uint offset, uint pin) { + pio_sm_config c = hello_program_get_default_config(offset); + // Map the state machine's OUT pin group to one pin, namely the `pin` + // parameter to this function. + sm_config_set_out_pins(&c, pin, 1); + // Set this pin's GPIO function (connect PIO to the pad) + pio_gpio_init(pio, pin); + // Set the pin direction to output at the PIO + pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true); + // Load our configuration, and jump to the start of the program + pio_sm_init(pio, sm, offset, &c); + // Set the state machine running + pio_sm_set_enabled(pio, sm, true); +} + +#endif + diff --git a/src/hal/pio/assembler/comparison_tests/hub75.pio b/src/hal/pio/assembler/comparison_tests/hub75.pio new file mode 100644 index 0000000..a6fb619 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/hub75.pio @@ -0,0 +1,128 @@ +; +; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; + +.program hub75_row + +; side-set pin 0 is LATCH +; side-set pin 1 is OEn +; OUT pins are row select A-E +; +; Each FIFO record consists of: +; - 5-bit row select (LSBs) +; - Pulse width - 1 (27 MSBs) +; +; Repeatedly select a row, pulse LATCH, and generate a pulse of a certain +; width on OEn. + +.side_set 2 + +.wrap_target + out pins, 5 [7] side 0x2 ; Deassert OEn, output row select + out x, 27 [7] side 0x3 ; Pulse LATCH, get OEn pulse width +pulse_loop: + jmp x-- pulse_loop side 0x0 ; Assert OEn for x+1 cycles +.wrap + +% c-sdk { +static inline void hub75_row_program_init(PIO pio, uint sm, uint offset, uint row_base_pin, uint n_row_pins, uint latch_base_pin) { + pio_sm_set_consecutive_pindirs(pio, sm, row_base_pin, n_row_pins, true); + pio_sm_set_consecutive_pindirs(pio, sm, latch_base_pin, 2, true); + for (uint i = row_base_pin; i < row_base_pin + n_row_pins; ++i) + pio_gpio_init(pio, i); + pio_gpio_init(pio, latch_base_pin); + pio_gpio_init(pio, latch_base_pin + 1); + + pio_sm_config c = hub75_row_program_get_default_config(offset); + sm_config_set_out_pins(&c, row_base_pin, n_row_pins); + sm_config_set_sideset_pins(&c, latch_base_pin); + sm_config_set_out_shift(&c, true, true, 32); + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); +} + +static inline void hub75_wait_tx_stall(PIO pio, uint sm) { + uint32_t txstall_mask = 1u << (PIO_FDEBUG_TXSTALL_LSB + sm); + pio->fdebug = txstall_mask; + while (!(pio->fdebug & txstall_mask)) + tight_loop_contents(); +} +%} + +.program hub75_data_rgb888 +.side_set 1 + +; Each FIFO record consists of a RGB888 pixel. (This is ok for e.g. an RGB565 +; source which has been gamma-corrected) +; +; Even pixels are sent on R0, G0, B0 and odd pixels on R1, G1, B1 (typically +; these are for different parts of the screen, NOT for adjacent pixels, so the +; frame buffer must be interleaved before passing to PIO.) +; +; Each pass through, we take bit n, n + 8 and n + 16 from each pixel, for n in +; {0...7}. Therefore the pixels need to be transmitted 8 times (ouch) to build +; up the full 8 bit value for each channel, and perform bit-planed PWM by +; varying pulse widths on the other state machine, in ascending powers of 2. +; This avoids a lot of bit shuffling on the processors, at the cost of DMA +; bandwidth (which we have loads of). + +; Might want to close your eyes before you read this +public entry_point: +.wrap_target +public shift0: + pull side 0 ; gets patched to `out null, n` if n nonzero (otherwise the PULL is required for fencing) + in osr, 1 side 0 ; shuffle shuffle shuffle + out null, 8 side 0 + in osr, 1 side 0 + out null, 8 side 0 + in osr, 1 side 0 + out null, 32 side 0 ; Discard remainder of OSR contents +public shift1: + pull side 0 ; gets patched to out null, n if n is nonzero (otherwise PULL required) + in osr, 1 side 1 ; Note this posedge clocks in the data from the previous iteration + out null, 8 side 1 + in osr, 1 side 1 + out null, 8 side 1 + in osr, 1 side 1 + out null, 32 side 1 + in null, 26 side 1 ; Note we are just doing this little manoeuvre here to get GPIOs in the order + mov pins, ::isr side 1 ; R0, G0, B0, R1, G1, B1. Can go 1 cycle faster if reversed +.wrap +; Note that because the clock edge for pixel n is in the middle of pixel n + +; 1, a dummy pixel at the end is required to clock the last piece of genuine +; data. (Also 1 pixel of garbage is clocked out at the start, but this is +; harmless) + +% c-sdk { +static inline void hub75_data_rgb888_program_init(PIO pio, uint sm, uint offset, uint rgb_base_pin, uint clock_pin) { + pio_sm_set_consecutive_pindirs(pio, sm, rgb_base_pin, 6, true); + pio_sm_set_consecutive_pindirs(pio, sm, clock_pin, 1, true); + for (uint i = rgb_base_pin; i < rgb_base_pin + 6; ++i) + pio_gpio_init(pio, i); + pio_gpio_init(pio, clock_pin); + + pio_sm_config c = hub75_data_rgb888_program_get_default_config(offset); + sm_config_set_out_pins(&c, rgb_base_pin, 6); + sm_config_set_sideset_pins(&c, clock_pin); + sm_config_set_out_shift(&c, true, true, 24); + // ISR shift to left. R0 ends up at bit 5. We push it up to MSB and then flip the register. + sm_config_set_in_shift(&c, false, false, 32); + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); + pio_sm_init(pio, sm, offset, &c); + pio_sm_exec(pio, sm, offset + hub75_data_rgb888_offset_entry_point); + pio_sm_set_enabled(pio, sm, true); +} + +// Patch a data program at `offset` to preshift pixels by `shamt` +static inline void hub75_data_rgb888_set_shift(PIO pio, uint sm, uint offset, uint shamt) { + uint16_t instr; + if (shamt == 0) + instr = pio_encode_pull(false, true); // blocking PULL + else + instr = pio_encode_out(pio_null, shamt); + pio->instr_mem[offset + hub75_data_rgb888_offset_shift0] = instr; + pio->instr_mem[offset + hub75_data_rgb888_offset_shift1] = instr; +} +%} diff --git a/src/hal/pio/assembler/comparison_tests/hub75.pio.h b/src/hal/pio/assembler/comparison_tests/hub75.pio.h new file mode 100644 index 0000000..4d6df69 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/hub75.pio.h @@ -0,0 +1,138 @@ +// -------------------------------------------------- // +// This file is autogenerated by pioasm; do not edit! // +// -------------------------------------------------- // + +#pragma once + +#if !PICO_NO_HARDWARE +#include "hardware/pio.h" +#endif + +// --------- // +// hub75_row // +// --------- // + +#define hub75_row_wrap_target 0 +#define hub75_row_wrap 2 + +static const uint16_t hub75_row_program_instructions[] = { + // .wrap_target + 0x7705, // 0: out pins, 5 side 2 [7] + 0x7f3b, // 1: out x, 27 side 3 [7] + 0x0042, // 2: jmp x--, 2 side 0 + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program hub75_row_program = { + .instructions = hub75_row_program_instructions, + .length = 3, + .origin = -1, +}; + +static inline pio_sm_config hub75_row_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + hub75_row_wrap_target, offset + hub75_row_wrap); + sm_config_set_sideset(&c, 2, false, false); + return c; +} + +static inline void hub75_row_program_init(PIO pio, uint sm, uint offset, uint row_base_pin, uint n_row_pins, uint latch_base_pin) { + pio_sm_set_consecutive_pindirs(pio, sm, row_base_pin, n_row_pins, true); + pio_sm_set_consecutive_pindirs(pio, sm, latch_base_pin, 2, true); + for (uint i = row_base_pin; i < row_base_pin + n_row_pins; ++i) + pio_gpio_init(pio, i); + pio_gpio_init(pio, latch_base_pin); + pio_gpio_init(pio, latch_base_pin + 1); + pio_sm_config c = hub75_row_program_get_default_config(offset); + sm_config_set_out_pins(&c, row_base_pin, n_row_pins); + sm_config_set_sideset_pins(&c, latch_base_pin); + sm_config_set_out_shift(&c, true, true, 32); + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); +} +static inline void hub75_wait_tx_stall(PIO pio, uint sm) { + uint32_t txstall_mask = 1u << (PIO_FDEBUG_TXSTALL_LSB + sm); + pio->fdebug = txstall_mask; + while (!(pio->fdebug & txstall_mask)) + tight_loop_contents(); +} + +#endif + +// ----------------- // +// hub75_data_rgb888 // +// ----------------- // + +#define hub75_data_rgb888_wrap_target 0 +#define hub75_data_rgb888_wrap 15 + +#define hub75_data_rgb888_offset_entry_point 0u +#define hub75_data_rgb888_offset_shift0 0u +#define hub75_data_rgb888_offset_shift1 7u + +static const uint16_t hub75_data_rgb888_program_instructions[] = { + // .wrap_target + 0x80a0, // 0: pull block side 0 + 0x40e1, // 1: in osr, 1 side 0 + 0x6068, // 2: out null, 8 side 0 + 0x40e1, // 3: in osr, 1 side 0 + 0x6068, // 4: out null, 8 side 0 + 0x40e1, // 5: in osr, 1 side 0 + 0x6060, // 6: out null, 32 side 0 + 0x80a0, // 7: pull block side 0 + 0x50e1, // 8: in osr, 1 side 1 + 0x7068, // 9: out null, 8 side 1 + 0x50e1, // 10: in osr, 1 side 1 + 0x7068, // 11: out null, 8 side 1 + 0x50e1, // 12: in osr, 1 side 1 + 0x7060, // 13: out null, 32 side 1 + 0x507a, // 14: in null, 26 side 1 + 0xb016, // 15: mov pins, ::isr side 1 + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program hub75_data_rgb888_program = { + .instructions = hub75_data_rgb888_program_instructions, + .length = 16, + .origin = -1, +}; + +static inline pio_sm_config hub75_data_rgb888_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + hub75_data_rgb888_wrap_target, offset + hub75_data_rgb888_wrap); + sm_config_set_sideset(&c, 1, false, false); + return c; +} + +static inline void hub75_data_rgb888_program_init(PIO pio, uint sm, uint offset, uint rgb_base_pin, uint clock_pin) { + pio_sm_set_consecutive_pindirs(pio, sm, rgb_base_pin, 6, true); + pio_sm_set_consecutive_pindirs(pio, sm, clock_pin, 1, true); + for (uint i = rgb_base_pin; i < rgb_base_pin + 6; ++i) + pio_gpio_init(pio, i); + pio_gpio_init(pio, clock_pin); + pio_sm_config c = hub75_data_rgb888_program_get_default_config(offset); + sm_config_set_out_pins(&c, rgb_base_pin, 6); + sm_config_set_sideset_pins(&c, clock_pin); + sm_config_set_out_shift(&c, true, true, 24); + // ISR shift to left. R0 ends up at bit 5. We push it up to MSB and then flip the register. + sm_config_set_in_shift(&c, false, false, 32); + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); + pio_sm_init(pio, sm, offset, &c); + pio_sm_exec(pio, sm, offset + hub75_data_rgb888_offset_entry_point); + pio_sm_set_enabled(pio, sm, true); +} +// Patch a data program at `offset` to preshift pixels by `shamt` +static inline void hub75_data_rgb888_set_shift(PIO pio, uint sm, uint offset, uint shamt) { + uint16_t instr; + if (shamt == 0) + instr = pio_encode_pull(false, true); // blocking PULL + else + instr = pio_encode_out(pio_null, shamt); + pio->instr_mem[offset + hub75_data_rgb888_offset_shift0] = instr; + pio->instr_mem[offset + hub75_data_rgb888_offset_shift1] = instr; +} + +#endif + diff --git a/src/hal/pio/assembler/comparison_tests/i2c.pio b/src/hal/pio/assembler/comparison_tests/i2c.pio new file mode 100644 index 0000000..65f3e78 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/i2c.pio @@ -0,0 +1,145 @@ +; +; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; + +.program i2c +.side_set 1 opt pindirs + +; TX Encoding: +; | 15:10 | 9 | 8:1 | 0 | +; | Instr | Final | Data | NAK | +; +; If Instr has a value n > 0, then this FIFO word has no +; data payload, and the next n + 1 words will be executed as instructions. +; Otherwise, shift out the 8 data bits, followed by the ACK bit. +; +; The Instr mechanism allows stop/start/repstart sequences to be programmed +; by the processor, and then carried out by the state machine at defined points +; in the datastream. +; +; The "Final" field should be set for the final byte in a transfer. +; This tells the state machine to ignore a NAK: if this field is not +; set, then any NAK will cause the state machine to halt and interrupt. +; +; Autopull should be enabled, with a threshold of 16. +; Autopush should be enabled, with a threshold of 8. +; The TX FIFO should be accessed with halfword writes, to ensure +; the data is immediately available in the OSR. +; +; Pin mapping: +; - Input pin 0 is SDA, 1 is SCL (if clock stretching used) +; - Jump pin is SDA +; - Side-set pin 0 is SCL +; - Set pin 0 is SDA +; - OUT pin 0 is SDA +; - SCL must be SDA + 1 (for wait mapping) +; +; The OE outputs should be inverted in the system IO controls! +; (It's possible for the inversion to be done in this program, +; but costs 2 instructions: 1 for inversion, and one to cope +; with the side effect of the MOV on TX shift counter.) + +do_nack: + jmp y-- entry_point ; Continue if NAK was expected + irq wait 0 rel ; Otherwise stop, ask for help + +do_byte: + set x, 7 ; Loop 8 times +bitloop: + out pindirs, 1 [7] ; Serialise write data (all-ones if reading) + nop side 1 [2] ; SCL rising edge + wait 1 pin, 1 [4] ; Allow clock to be stretched + in pins, 1 [7] ; Sample read data in middle of SCL pulse + jmp x-- bitloop side 0 [7] ; SCL falling edge + + ; Handle ACK pulse + out pindirs, 1 [7] ; On reads, we provide the ACK. + nop side 1 [7] ; SCL rising edge + wait 1 pin, 1 [7] ; Allow clock to be stretched + jmp pin do_nack side 0 [2] ; Test SDA for ACK/NAK, fall through if ACK + +public entry_point: +.wrap_target + out x, 6 ; Unpack Instr count + out y, 1 ; Unpack the NAK ignore bit + jmp !x do_byte ; Instr == 0, this is a data record. + out null, 32 ; Instr > 0, remainder of this OSR is invalid +do_exec: + out exec, 16 ; Execute one instruction per FIFO word + jmp x-- do_exec ; Repeat n + 1 times +.wrap + +% c-sdk { + +#include "hardware/clocks.h" +#include "hardware/gpio.h" + + +static inline void i2c_program_init(PIO pio, uint sm, uint offset, uint pin_sda, uint pin_scl) { + assert(pin_scl == pin_sda + 1); + pio_sm_config c = i2c_program_get_default_config(offset); + + // IO mapping + sm_config_set_out_pins(&c, pin_sda, 1); + sm_config_set_set_pins(&c, pin_sda, 1); + sm_config_set_in_pins(&c, pin_sda); + sm_config_set_sideset_pins(&c, pin_scl); + sm_config_set_jmp_pin(&c, pin_sda); + + sm_config_set_out_shift(&c, false, true, 16); + sm_config_set_in_shift(&c, false, true, 8); + + float div = (float)clock_get_hz(clk_sys) / (32 * 100000); + sm_config_set_clkdiv(&c, div); + + // Try to avoid glitching the bus while connecting the IOs. Get things set + // up so that pin is driven down when PIO asserts OE low, and pulled up + // otherwise. + gpio_pull_up(pin_scl); + gpio_pull_up(pin_sda); + uint32_t both_pins = (1u << pin_sda) | (1u << pin_scl); + pio_sm_set_pins_with_mask(pio, sm, both_pins, both_pins); + pio_sm_set_pindirs_with_mask(pio, sm, both_pins, both_pins); + pio_gpio_init(pio, pin_sda); + gpio_set_oeover(pin_sda, GPIO_OVERRIDE_INVERT); + pio_gpio_init(pio, pin_scl); + gpio_set_oeover(pin_scl, GPIO_OVERRIDE_INVERT); + pio_sm_set_pins_with_mask(pio, sm, 0, both_pins); + + // Clear IRQ flag before starting, and make sure flag doesn't actually + // assert a system-level interrupt (we're using it as a status flag) + pio_set_irq0_source_enabled(pio, pis_interrupt0 + sm, false); + pio_set_irq1_source_enabled(pio, pis_interrupt0 + sm, false); + pio_interrupt_clear(pio, sm); + + // Configure and start SM + pio_sm_init(pio, sm, offset + i2c_offset_entry_point, &c); + pio_sm_set_enabled(pio, sm, true); +} + +%} + + +.program set_scl_sda +.side_set 1 opt + +; Assemble a table of instructions which software can select from, and pass +; into the FIFO, to issue START/STOP/RSTART. This isn't intended to be run as +; a complete program. + + set pindirs, 0 side 0 [7] ; SCL = 0, SDA = 0 + set pindirs, 1 side 0 [7] ; SCL = 0, SDA = 1 + set pindirs, 0 side 1 [7] ; SCL = 1, SDA = 0 + set pindirs, 1 side 1 [7] ; SCL = 1, SDA = 1 + +% c-sdk { +// Define order of our instruction table +enum { + I2C_SC0_SD0 = 0, + I2C_SC0_SD1, + I2C_SC1_SD0, + I2C_SC1_SD1 +}; +%} diff --git a/src/hal/pio/assembler/comparison_tests/i2c.pio.h b/src/hal/pio/assembler/comparison_tests/i2c.pio.h new file mode 100644 index 0000000..5c47039 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/i2c.pio.h @@ -0,0 +1,136 @@ +// -------------------------------------------------- // +// This file is autogenerated by pioasm; do not edit! // +// -------------------------------------------------- // + +#pragma once + +#if !PICO_NO_HARDWARE +#include "hardware/pio.h" +#endif + +// --- // +// i2c // +// --- // + +#define i2c_wrap_target 12 +#define i2c_wrap 17 + +#define i2c_offset_entry_point 12u + +static const uint16_t i2c_program_instructions[] = { + 0x008c, // 0: jmp y--, 12 + 0xc030, // 1: irq wait 0 rel + 0xe027, // 2: set x, 7 + 0x6781, // 3: out pindirs, 1 [7] + 0xba42, // 4: nop side 1 [2] + 0x24a1, // 5: wait 1 pin, 1 [4] + 0x4701, // 6: in pins, 1 [7] + 0x1743, // 7: jmp x--, 3 side 0 [7] + 0x6781, // 8: out pindirs, 1 [7] + 0xbf42, // 9: nop side 1 [7] + 0x27a1, // 10: wait 1 pin, 1 [7] + 0x12c0, // 11: jmp pin, 0 side 0 [2] + // .wrap_target + 0x6026, // 12: out x, 6 + 0x6041, // 13: out y, 1 + 0x0022, // 14: jmp !x, 2 + 0x6060, // 15: out null, 32 + 0x60f0, // 16: out exec, 16 + 0x0050, // 17: jmp x--, 16 + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program i2c_program = { + .instructions = i2c_program_instructions, + .length = 18, + .origin = -1, +}; + +static inline pio_sm_config i2c_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + i2c_wrap_target, offset + i2c_wrap); + sm_config_set_sideset(&c, 2, true, true); + return c; +} + +#include "hardware/clocks.h" +#include "hardware/gpio.h" +static inline void i2c_program_init(PIO pio, uint sm, uint offset, uint pin_sda, uint pin_scl) { + assert(pin_scl == pin_sda + 1); + pio_sm_config c = i2c_program_get_default_config(offset); + // IO mapping + sm_config_set_out_pins(&c, pin_sda, 1); + sm_config_set_set_pins(&c, pin_sda, 1); + sm_config_set_in_pins(&c, pin_sda); + sm_config_set_sideset_pins(&c, pin_scl); + sm_config_set_jmp_pin(&c, pin_sda); + sm_config_set_out_shift(&c, false, true, 16); + sm_config_set_in_shift(&c, false, true, 8); + float div = (float)clock_get_hz(clk_sys) / (32 * 100000); + sm_config_set_clkdiv(&c, div); + // Try to avoid glitching the bus while connecting the IOs. Get things set + // up so that pin is driven down when PIO asserts OE low, and pulled up + // otherwise. + gpio_pull_up(pin_scl); + gpio_pull_up(pin_sda); + uint32_t both_pins = (1u << pin_sda) | (1u << pin_scl); + pio_sm_set_pins_with_mask(pio, sm, both_pins, both_pins); + pio_sm_set_pindirs_with_mask(pio, sm, both_pins, both_pins); + pio_gpio_init(pio, pin_sda); + gpio_set_oeover(pin_sda, GPIO_OVERRIDE_INVERT); + pio_gpio_init(pio, pin_scl); + gpio_set_oeover(pin_scl, GPIO_OVERRIDE_INVERT); + pio_sm_set_pins_with_mask(pio, sm, 0, both_pins); + // Clear IRQ flag before starting, and make sure flag doesn't actually + // assert a system-level interrupt (we're using it as a status flag) + pio_set_irq0_source_enabled(pio, pis_interrupt0 + sm, false); + pio_set_irq1_source_enabled(pio, pis_interrupt0 + sm, false); + pio_interrupt_clear(pio, sm); + // Configure and start SM + pio_sm_init(pio, sm, offset + i2c_offset_entry_point, &c); + pio_sm_set_enabled(pio, sm, true); +} + +#endif + +// ----------- // +// set_scl_sda // +// ----------- // + +#define set_scl_sda_wrap_target 0 +#define set_scl_sda_wrap 3 + +static const uint16_t set_scl_sda_program_instructions[] = { + // .wrap_target + 0xf780, // 0: set pindirs, 0 side 0 [7] + 0xf781, // 1: set pindirs, 1 side 0 [7] + 0xff80, // 2: set pindirs, 0 side 1 [7] + 0xff81, // 3: set pindirs, 1 side 1 [7] + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program set_scl_sda_program = { + .instructions = set_scl_sda_program_instructions, + .length = 4, + .origin = -1, +}; + +static inline pio_sm_config set_scl_sda_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + set_scl_sda_wrap_target, offset + set_scl_sda_wrap); + sm_config_set_sideset(&c, 2, true, false); + return c; +} + +// Define order of our instruction table +enum { + I2C_SC0_SD0 = 0, + I2C_SC0_SD1, + I2C_SC1_SD0, + I2C_SC1_SD1 +}; + +#endif + diff --git a/src/hal/pio/assembler/comparison_tests/manchester_encoding.pio b/src/hal/pio/assembler/comparison_tests/manchester_encoding.pio new file mode 100644 index 0000000..0117d2a --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/manchester_encoding.pio @@ -0,0 +1,94 @@ +; +; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; + +.program manchester_tx +.side_set 1 opt + +; Transmit one bit every 12 cycles. a '0' is encoded as a high-low sequence +; (each part lasting half a bit period, or 6 cycles) and a '1' is encoded as a +; low-high sequence. +; +; Side-set bit 0 must be mapped to the GPIO used for TX. +; Autopull must be enabled -- this program does not care about the threshold. +; The program starts at the public label 'start'. + +.wrap_target +do_1: + nop side 0 [5] ; Low for 6 cycles (5 delay, +1 for nop) + jmp get_bit side 1 [3] ; High for 4 cycles. 'get_bit' takes another 2 cycles +do_0: + nop side 1 [5] ; Output high for 6 cycles + nop side 0 [3] ; Output low for 4 cycles +public start: +get_bit: + out x, 1 ; Always shift out one bit from OSR to X, so we can + jmp !x do_0 ; branch on it. Autopull refills the OSR when empty. +.wrap + +% c-sdk { +static inline void manchester_tx_program_init(PIO pio, uint sm, uint offset, uint pin, float div) { + pio_sm_set_pins_with_mask(pio, sm, 0, 1u << pin); + pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true); + pio_gpio_init(pio, pin); + + pio_sm_config c = manchester_tx_program_get_default_config(offset); + sm_config_set_sideset_pins(&c, pin); + sm_config_set_out_shift(&c, true, true, 32); + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); + sm_config_set_clkdiv(&c, div); + pio_sm_init(pio, sm, offset + manchester_tx_offset_start, &c); + + pio_sm_set_enabled(pio, sm, true); +} +%} + +.program manchester_rx + +; Assumes line is idle low, first bit is 0 +; One bit is 12 cycles +; a '0' is encoded as 10 +; a '1' is encoded as 01 +; +; Both the IN base and the JMP pin mapping must be pointed at the GPIO used for RX. +; Autopush must be enabled. +; Before enabling the SM, it should be placed in a 'wait 1, pin` state, so that +; it will not start sampling until the initial line idle state ends. + +start_of_0: ; We are 0.25 bits into a 0 - signal is high + wait 0 pin 0 ; Wait for the 1->0 transition - at this point we are 0.5 into the bit + in y, 1 [8] ; Emit a 0, sleep 3/4 of a bit + jmp pin start_of_0 ; If signal is 1 again, it's another 0 bit, otherwise it's a 1 + +.wrap_target +start_of_1: ; We are 0.25 bits into a 1 - signal is 1 + wait 1 pin 0 ; Wait for the 0->1 transition - at this point we are 0.5 into the bit + in x, 1 [8] ; Emit a 1, sleep 3/4 of a bit + jmp pin start_of_0 ; If signal is 0 again, it's another 1 bit otherwise it's a 0 +.wrap + +% c-sdk { +static inline void manchester_rx_program_init(PIO pio, uint sm, uint offset, uint pin, float div) { + pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, false); + pio_gpio_init(pio, pin); + + pio_sm_config c = manchester_rx_program_get_default_config(offset); + sm_config_set_in_pins(&c, pin); // for WAIT + sm_config_set_jmp_pin(&c, pin); // for JMP + sm_config_set_in_shift(&c, true, true, 32); + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX); + sm_config_set_clkdiv(&c, div); + pio_sm_init(pio, sm, offset, &c); + + // X and Y are set to 0 and 1, to conveniently emit these to ISR/FIFO. + pio_sm_exec(pio, sm, pio_encode_set(pio_x, 1)); + pio_sm_exec(pio, sm, pio_encode_set(pio_y, 0)); + // Assume line is idle low, and first transmitted bit is 0. Put SM in a + // wait state before enabling. RX will begin once the first 0 symbol is + // detected. + pio_sm_exec(pio, sm, pio_encode_wait_pin(1, 0) | pio_encode_delay(2)); + pio_sm_set_enabled(pio, sm, true); +} +%} diff --git a/src/hal/pio/assembler/comparison_tests/manchester_encoding.pio.h b/src/hal/pio/assembler/comparison_tests/manchester_encoding.pio.h new file mode 100644 index 0000000..ee00886 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/manchester_encoding.pio.h @@ -0,0 +1,112 @@ +// -------------------------------------------------- // +// This file is autogenerated by pioasm; do not edit! // +// -------------------------------------------------- // + +#pragma once + +#if !PICO_NO_HARDWARE +#include "hardware/pio.h" +#endif + +// ------------- // +// manchester_tx // +// ------------- // + +#define manchester_tx_wrap_target 0 +#define manchester_tx_wrap 5 + +#define manchester_tx_offset_start 4u + +static const uint16_t manchester_tx_program_instructions[] = { + // .wrap_target + 0xb542, // 0: nop side 0 [5] + 0x1b04, // 1: jmp 4 side 1 [3] + 0xbd42, // 2: nop side 1 [5] + 0xb342, // 3: nop side 0 [3] + 0x6021, // 4: out x, 1 + 0x0022, // 5: jmp !x, 2 + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program manchester_tx_program = { + .instructions = manchester_tx_program_instructions, + .length = 6, + .origin = -1, +}; + +static inline pio_sm_config manchester_tx_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + manchester_tx_wrap_target, offset + manchester_tx_wrap); + sm_config_set_sideset(&c, 2, true, false); + return c; +} + +static inline void manchester_tx_program_init(PIO pio, uint sm, uint offset, uint pin, float div) { + pio_sm_set_pins_with_mask(pio, sm, 0, 1u << pin); + pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true); + pio_gpio_init(pio, pin); + pio_sm_config c = manchester_tx_program_get_default_config(offset); + sm_config_set_sideset_pins(&c, pin); + sm_config_set_out_shift(&c, true, true, 32); + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); + sm_config_set_clkdiv(&c, div); + pio_sm_init(pio, sm, offset + manchester_tx_offset_start, &c); + pio_sm_set_enabled(pio, sm, true); +} + +#endif + +// ------------- // +// manchester_rx // +// ------------- // + +#define manchester_rx_wrap_target 3 +#define manchester_rx_wrap 5 + +static const uint16_t manchester_rx_program_instructions[] = { + 0x2020, // 0: wait 0 pin, 0 + 0x4841, // 1: in y, 1 [8] + 0x00c0, // 2: jmp pin, 0 + // .wrap_target + 0x20a0, // 3: wait 1 pin, 0 + 0x4821, // 4: in x, 1 [8] + 0x00c0, // 5: jmp pin, 0 + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program manchester_rx_program = { + .instructions = manchester_rx_program_instructions, + .length = 6, + .origin = -1, +}; + +static inline pio_sm_config manchester_rx_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + manchester_rx_wrap_target, offset + manchester_rx_wrap); + return c; +} + +static inline void manchester_rx_program_init(PIO pio, uint sm, uint offset, uint pin, float div) { + pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, false); + pio_gpio_init(pio, pin); + pio_sm_config c = manchester_rx_program_get_default_config(offset); + sm_config_set_in_pins(&c, pin); // for WAIT + sm_config_set_jmp_pin(&c, pin); // for JMP + sm_config_set_in_shift(&c, true, true, 32); + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX); + sm_config_set_clkdiv(&c, div); + pio_sm_init(pio, sm, offset, &c); + // X and Y are set to 0 and 1, to conveniently emit these to ISR/FIFO. + pio_sm_exec(pio, sm, pio_encode_set(pio_x, 1)); + pio_sm_exec(pio, sm, pio_encode_set(pio_y, 0)); + // Assume line is idle low, and first transmitted bit is 0. Put SM in a + // wait state before enabling. RX will begin once the first 0 symbol is + // detected. + pio_sm_exec(pio, sm, pio_encode_wait_pin(1, 0) | pio_encode_delay(2)); + pio_sm_set_enabled(pio, sm, true); +} + +#endif + diff --git a/src/hal/pio/assembler/comparison_tests/nec_carrier_burst.pio b/src/hal/pio/assembler/comparison_tests/nec_carrier_burst.pio new file mode 100644 index 0000000..499e892 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/nec_carrier_burst.pio @@ -0,0 +1,61 @@ +; +; Copyright (c) 2021 mjcross +; +; SPDX-License-Identifier: BSD-3-Clause +; + + +.program nec_carrier_burst + +; Generate bursts of carrier. +; +; Repeatedly wait for an IRQ to be set then clear it and generate 21 cycles of +; carrier with 25% duty cycle +; +.define NUM_CYCLES 21 ; how many carrier cycles to generate +.define BURST_IRQ 7 ; which IRQ should trigger a carrier burst +.define public TICKS_PER_LOOP 4 ; the number of instructions in the loop (for timing) + +.wrap_target + set X, (NUM_CYCLES - 1) ; initialise the loop counter + wait 1 irq BURST_IRQ ; wait for the IRQ then clear it +cycle_loop: + set pins, 1 ; set the pin high (1 cycle) + set pins, 0 [1] ; set the pin low (2 cycles) + jmp X--, cycle_loop ; (1 more cycle) +.wrap + + +% c-sdk { +static inline void nec_carrier_burst_program_init(PIO pio, uint sm, uint offset, uint pin, float freq) { + // Create a new state machine configuration + // + pio_sm_config c = nec_carrier_burst_program_get_default_config (offset); + + // Map the SET pin group to one pin, namely the `pin` + // parameter to this function. + // + sm_config_set_set_pins (&c, pin, 1); + + // Set the GPIO function of the pin (connect the PIO to the pad) + // + pio_gpio_init (pio, pin); + + // Set the pin direction to output at the PIO + // + pio_sm_set_consecutive_pindirs (pio, sm, pin, 1, true); + + // Set the clock divider to generate the required frequency + // + float div = clock_get_hz (clk_sys) / (freq * nec_carrier_burst_TICKS_PER_LOOP); + sm_config_set_clkdiv (&c, div); + + // Apply the configuration to the state machine + // + pio_sm_init (pio, sm, offset, &c); + + // Set the state machine running + // + pio_sm_set_enabled (pio, sm, true); +} +%} diff --git a/src/hal/pio/assembler/comparison_tests/nec_carrier_burst.pio.h b/src/hal/pio/assembler/comparison_tests/nec_carrier_burst.pio.h new file mode 100644 index 0000000..5fa0014 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/nec_carrier_burst.pio.h @@ -0,0 +1,70 @@ +// -------------------------------------------------- // +// This file is autogenerated by pioasm; do not edit! // +// -------------------------------------------------- // + +#pragma once + +#if !PICO_NO_HARDWARE +#include "hardware/pio.h" +#endif + +// ----------------- // +// nec_carrier_burst // +// ----------------- // + +#define nec_carrier_burst_wrap_target 0 +#define nec_carrier_burst_wrap 4 + +#define nec_carrier_burst_TICKS_PER_LOOP 4 + +static const uint16_t nec_carrier_burst_program_instructions[] = { + // .wrap_target + 0xe034, // 0: set x, 20 + 0x20c7, // 1: wait 1 irq, 7 + 0xe001, // 2: set pins, 1 + 0xe100, // 3: set pins, 0 [1] + 0x0042, // 4: jmp x--, 2 + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program nec_carrier_burst_program = { + .instructions = nec_carrier_burst_program_instructions, + .length = 5, + .origin = -1, +}; + +static inline pio_sm_config nec_carrier_burst_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + nec_carrier_burst_wrap_target, offset + nec_carrier_burst_wrap); + return c; +} + +static inline void nec_carrier_burst_program_init(PIO pio, uint sm, uint offset, uint pin, float freq) { + // Create a new state machine configuration + // + pio_sm_config c = nec_carrier_burst_program_get_default_config (offset); + // Map the SET pin group to one pin, namely the `pin` + // parameter to this function. + // + sm_config_set_set_pins (&c, pin, 1); + // Set the GPIO function of the pin (connect the PIO to the pad) + // + pio_gpio_init (pio, pin); + // Set the pin direction to output at the PIO + // + pio_sm_set_consecutive_pindirs (pio, sm, pin, 1, true); + // Set the clock divider to generate the required frequency + // + float div = clock_get_hz (clk_sys) / (freq * nec_carrier_burst_TICKS_PER_LOOP); + sm_config_set_clkdiv (&c, div); + // Apply the configuration to the state machine + // + pio_sm_init (pio, sm, offset, &c); + // Set the state machine running + // + pio_sm_set_enabled (pio, sm, true); +} + +#endif + diff --git a/src/hal/pio/assembler/comparison_tests/nec_carrier_control.pio b/src/hal/pio/assembler/comparison_tests/nec_carrier_control.pio new file mode 100644 index 0000000..0733afe --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/nec_carrier_control.pio @@ -0,0 +1,79 @@ +; +; Copyright (c) 2021 mjcross +; +; SPDX-License-Identifier: BSD-3-Clause +; + + +.program nec_carrier_control + +; Transmit an encoded 32-bit frame in NEC IR format. +; +; Accepts 32-bit words from the transmit FIFO and sends them least-significant bit first +; using pulse position modulation. +; +; Carrier bursts are generated using the nec_carrier_burst program, which is expected to be +; running on a separate state machine. +; +; This program expects there to be 2 state machine ticks per 'normal' 562.5us +; burst period. +; +.define BURST_IRQ 7 ; the IRQ used to trigger a carrier burst +.define NUM_INITIAL_BURSTS 16 ; how many bursts to transmit for a 'sync burst' + +.wrap_target + pull ; fetch a data word from the transmit FIFO into the + ; output shift register, blocking if the FIFO is empty + + set X, (NUM_INITIAL_BURSTS - 1) ; send a sync burst (9ms) +long_burst: + irq BURST_IRQ + jmp X-- long_burst + + nop [15] ; send a 4.5ms space + irq BURST_IRQ [1] ; send a 562.5us burst to begin the first data bit + +data_bit: + out X, 1 ; shift the least-significant bit from the OSR + jmp !X burst ; send a short delay for a '0' bit + nop [3] ; send an additional delay for a '1' bit +burst: + irq BURST_IRQ ; send a 562.5us burst to end the data bit + +jmp !OSRE data_bit ; continue sending bits until the OSR is empty + +.wrap ; fetch another data word from the FIFO + + +% c-sdk { +static inline void nec_carrier_control_program_init (PIO pio, uint sm, uint offset, float tick_rate, int bits_per_frame) { + + // create a new state machine configuration + // + pio_sm_config c = nec_carrier_control_program_get_default_config(offset); + + // configure the output shift register + // + sm_config_set_out_shift (&c, + true, // shift right + false, // disable autopull + bits_per_frame); + + // join the FIFOs to make a single large transmit FIFO + // + sm_config_set_fifo_join (&c, PIO_FIFO_JOIN_TX); + + // configure the clock divider + // + float div = clock_get_hz (clk_sys) / tick_rate; + sm_config_set_clkdiv (&c, div); + + // apply the configuration to the state machine + // + pio_sm_init(pio, sm, offset, &c); + + // set the state machine running + // + pio_sm_set_enabled(pio, sm, true); +} +%} diff --git a/src/hal/pio/assembler/comparison_tests/nec_carrier_control.pio.h b/src/hal/pio/assembler/comparison_tests/nec_carrier_control.pio.h new file mode 100644 index 0000000..8c9a305 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/nec_carrier_control.pio.h @@ -0,0 +1,73 @@ +// -------------------------------------------------- // +// This file is autogenerated by pioasm; do not edit! // +// -------------------------------------------------- // + +#pragma once + +#if !PICO_NO_HARDWARE +#include "hardware/pio.h" +#endif + +// ------------------- // +// nec_carrier_control // +// ------------------- // + +#define nec_carrier_control_wrap_target 0 +#define nec_carrier_control_wrap 10 + +static const uint16_t nec_carrier_control_program_instructions[] = { + // .wrap_target + 0x80a0, // 0: pull block + 0xe02f, // 1: set x, 15 + 0xc007, // 2: irq nowait 7 + 0x0042, // 3: jmp x--, 2 + 0xaf42, // 4: nop [15] + 0xc107, // 5: irq nowait 7 [1] + 0x6021, // 6: out x, 1 + 0x0029, // 7: jmp !x, 9 + 0xa342, // 8: nop [3] + 0xc007, // 9: irq nowait 7 + 0x00e6, // 10: jmp !osre, 6 + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program nec_carrier_control_program = { + .instructions = nec_carrier_control_program_instructions, + .length = 11, + .origin = -1, +}; + +static inline pio_sm_config nec_carrier_control_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + nec_carrier_control_wrap_target, offset + nec_carrier_control_wrap); + return c; +} + +static inline void nec_carrier_control_program_init (PIO pio, uint sm, uint offset, float tick_rate, int bits_per_frame) { + // create a new state machine configuration + // + pio_sm_config c = nec_carrier_control_program_get_default_config(offset); + // configure the output shift register + // + sm_config_set_out_shift (&c, + true, // shift right + false, // disable autopull + bits_per_frame); + // join the FIFOs to make a single large transmit FIFO + // + sm_config_set_fifo_join (&c, PIO_FIFO_JOIN_TX); + // configure the clock divider + // + float div = clock_get_hz (clk_sys) / tick_rate; + sm_config_set_clkdiv (&c, div); + // apply the configuration to the state machine + // + pio_sm_init(pio, sm, offset, &c); + // set the state machine running + // + pio_sm_set_enabled(pio, sm, true); +} + +#endif + diff --git a/src/hal/pio/assembler/comparison_tests/nec_receive.pio b/src/hal/pio/assembler/comparison_tests/nec_receive.pio new file mode 100644 index 0000000..a2c5f5e --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/nec_receive.pio @@ -0,0 +1,96 @@ +; +; Copyright (c) 2021 mjcross +; +; SPDX-License-Identifier: BSD-3-Clause +; + + +.program nec_receive + +; Decode IR frames in NEC format and push 32-bit words to the input FIFO. +; +; The input pin should be connected to an IR detector with an 'active low' output. +; +; This program expects there to be 10 state machine clock ticks per 'normal' 562.5us burst period +; in order to permit timely detection of start of a burst. The initailisation function below sets +; the correct divisor to achive this relative to the system clock. +; +; Within the 'NEC' protocol frames consists of 32 bits sent least-siginificant bit first; so the +; Input Shift Register should be configured to shift right and autopush after 32 bits, as in the +; initialisation function below. +; +.define BURST_LOOP_COUNTER 30 ; the detection threshold for a 'frame sync' burst +.define BIT_SAMPLE_DELAY 15 ; how long to wait after the end of the burst before sampling + +.wrap_target + +next_burst: + set X, BURST_LOOP_COUNTER + wait 0 pin 0 ; wait for the next burst to start + +burst_loop: + jmp pin data_bit ; the burst ended before the counter expired + jmp X-- burst_loop ; wait for the burst to end + + ; the counter expired - this is a sync burst + mov ISR, NULL ; reset the Input Shift Register + wait 1 pin 0 ; wait for the sync burst to finish + jmp next_burst ; wait for the first data bit + +data_bit: + nop [ BIT_SAMPLE_DELAY - 1 ] ; wait for 1.5 burst periods before sampling the bit value + in PINS, 1 ; if the next burst has started then detect a '0' (short gap) + ; otherwise detect a '1' (long gap) + ; after 32 bits the ISR will autopush to the receive FIFO +.wrap + + +% c-sdk { +static inline void nec_receive_program_init (PIO pio, uint sm, uint offset, uint pin) { + + // Set the GPIO function of the pin (connect the PIO to the pad) + // + pio_gpio_init(pio, pin); + + // Set the pin direction to `input` at the PIO + // + pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, false); + + // Create a new state machine configuration + // + pio_sm_config c = nec_receive_program_get_default_config (offset); + + // configure the Input Shift Register + // + sm_config_set_in_shift (&c, + true, // shift right + true, // enable autopush + 32); // autopush after 32 bits + + // join the FIFOs to make a single large receive FIFO + // + sm_config_set_fifo_join (&c, PIO_FIFO_JOIN_RX); + + // Map the IN pin group to one pin, namely the `pin` + // parameter to this function. + // + sm_config_set_in_pins (&c, pin); + + // Map the JMP pin to the `pin` parameter of this function. + // + sm_config_set_jmp_pin (&c, pin); + + // Set the clock divider to 10 ticks per 562.5us burst period + // + float div = clock_get_hz (clk_sys) / (10.0 / 562.5e-6); + sm_config_set_clkdiv (&c, div); + + // Apply the configuration to the state machine + // + pio_sm_init (pio, sm, offset, &c); + + // Set the state machine running + // + pio_sm_set_enabled (pio, sm, true); +} +%} diff --git a/src/hal/pio/assembler/comparison_tests/nec_receive.pio.h b/src/hal/pio/assembler/comparison_tests/nec_receive.pio.h new file mode 100644 index 0000000..e9611b6 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/nec_receive.pio.h @@ -0,0 +1,84 @@ +// -------------------------------------------------- // +// This file is autogenerated by pioasm; do not edit! // +// -------------------------------------------------- // + +#pragma once + +#if !PICO_NO_HARDWARE +#include "hardware/pio.h" +#endif + +// ----------- // +// nec_receive // +// ----------- // + +#define nec_receive_wrap_target 0 +#define nec_receive_wrap 8 + +static const uint16_t nec_receive_program_instructions[] = { + // .wrap_target + 0xe03e, // 0: set x, 30 + 0x2020, // 1: wait 0 pin, 0 + 0x00c7, // 2: jmp pin, 7 + 0x0042, // 3: jmp x--, 2 + 0xa0c3, // 4: mov isr, null + 0x20a0, // 5: wait 1 pin, 0 + 0x0000, // 6: jmp 0 + 0xae42, // 7: nop [14] + 0x4001, // 8: in pins, 1 + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program nec_receive_program = { + .instructions = nec_receive_program_instructions, + .length = 9, + .origin = -1, +}; + +static inline pio_sm_config nec_receive_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + nec_receive_wrap_target, offset + nec_receive_wrap); + return c; +} + +static inline void nec_receive_program_init (PIO pio, uint sm, uint offset, uint pin) { + // Set the GPIO function of the pin (connect the PIO to the pad) + // + pio_gpio_init(pio, pin); + // Set the pin direction to `input` at the PIO + // + pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, false); + // Create a new state machine configuration + // + pio_sm_config c = nec_receive_program_get_default_config (offset); + // configure the Input Shift Register + // + sm_config_set_in_shift (&c, + true, // shift right + true, // enable autopush + 32); // autopush after 32 bits + // join the FIFOs to make a single large receive FIFO + // + sm_config_set_fifo_join (&c, PIO_FIFO_JOIN_RX); + // Map the IN pin group to one pin, namely the `pin` + // parameter to this function. + // + sm_config_set_in_pins (&c, pin); + // Map the JMP pin to the `pin` parameter of this function. + // + sm_config_set_jmp_pin (&c, pin); + // Set the clock divider to 10 ticks per 562.5us burst period + // + float div = clock_get_hz (clk_sys) / (10.0 / 562.5e-6); + sm_config_set_clkdiv (&c, div); + // Apply the configuration to the state machine + // + pio_sm_init (pio, sm, offset, &c); + // Set the state machine running + // + pio_sm_set_enabled (pio, sm, true); +} + +#endif + diff --git a/src/hal/pio/assembler/comparison_tests/pio_serialiser.pio b/src/hal/pio/assembler/comparison_tests/pio_serialiser.pio new file mode 100644 index 0000000..67a6866 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/pio_serialiser.pio @@ -0,0 +1,27 @@ +; +; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; + +.program pio_serialiser + +; Just serialise a stream of bits. Take 32 bits from each FIFO record. LSB-first. + +.wrap_target + out pins, 1 +.wrap + +% c-sdk { +static inline void pio_serialiser_program_init(PIO pio, uint sm, uint offset, uint data_pin, float clk_div) { + pio_gpio_init(pio, data_pin); + pio_sm_set_consecutive_pindirs(pio, sm, data_pin, 1, true); + pio_sm_config c = pio_serialiser_program_get_default_config(offset); + sm_config_set_out_pins(&c, data_pin, 1); + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); + sm_config_set_clkdiv(&c, clk_div); + sm_config_set_out_shift(&c, true, true, 32); + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); +} +%} diff --git a/src/hal/pio/assembler/comparison_tests/pio_serialiser.pio.h b/src/hal/pio/assembler/comparison_tests/pio_serialiser.pio.h new file mode 100644 index 0000000..0627585 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/pio_serialiser.pio.h @@ -0,0 +1,50 @@ +// -------------------------------------------------- // +// This file is autogenerated by pioasm; do not edit! // +// -------------------------------------------------- // + +#pragma once + +#if !PICO_NO_HARDWARE +#include "hardware/pio.h" +#endif + +// -------------- // +// pio_serialiser // +// -------------- // + +#define pio_serialiser_wrap_target 0 +#define pio_serialiser_wrap 0 + +static const uint16_t pio_serialiser_program_instructions[] = { + // .wrap_target + 0x6001, // 0: out pins, 1 + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program pio_serialiser_program = { + .instructions = pio_serialiser_program_instructions, + .length = 1, + .origin = -1, +}; + +static inline pio_sm_config pio_serialiser_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + pio_serialiser_wrap_target, offset + pio_serialiser_wrap); + return c; +} + +static inline void pio_serialiser_program_init(PIO pio, uint sm, uint offset, uint data_pin, float clk_div) { + pio_gpio_init(pio, data_pin); + pio_sm_set_consecutive_pindirs(pio, sm, data_pin, 1, true); + pio_sm_config c = pio_serialiser_program_get_default_config(offset); + sm_config_set_out_pins(&c, data_pin, 1); + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); + sm_config_set_clkdiv(&c, clk_div); + sm_config_set_out_shift(&c, true, true, 32); + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); +} + +#endif + diff --git a/src/hal/pio/assembler/comparison_tests/pwm.pio b/src/hal/pio/assembler/comparison_tests/pwm.pio new file mode 100644 index 0000000..d0f2bcb --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/pwm.pio @@ -0,0 +1,31 @@ +; +; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; + +; Side-set pin 0 is used for PWM output + +.program pwm +.side_set 1 opt + + pull noblock side 0 ; Pull from FIFO to OSR if available, else copy X to OSR. + mov x, osr ; Copy most-recently-pulled value back to scratch X + mov y, isr ; ISR contains PWM period. Y used as counter. +countloop: + jmp x!=y noset ; Set pin high if X == Y, keep the two paths length matched + jmp skip side 1 +noset: + nop ; Single dummy cycle to keep the two paths the same length +skip: + jmp y-- countloop ; Loop until Y hits 0, then pull a fresh PWM value from FIFO + +% c-sdk { +static inline void pwm_program_init(PIO pio, uint sm, uint offset, uint pin) { + pio_gpio_init(pio, pin); + pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true); + pio_sm_config c = pwm_program_get_default_config(offset); + sm_config_set_sideset_pins(&c, pin); + pio_sm_init(pio, sm, offset, &c); +} +%} diff --git a/src/hal/pio/assembler/comparison_tests/pwm.pio.h b/src/hal/pio/assembler/comparison_tests/pwm.pio.h new file mode 100644 index 0000000..7d738a0 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/pwm.pio.h @@ -0,0 +1,53 @@ +// -------------------------------------------------- // +// This file is autogenerated by pioasm; do not edit! // +// -------------------------------------------------- // + +#pragma once + +#if !PICO_NO_HARDWARE +#include "hardware/pio.h" +#endif + +// --- // +// pwm // +// --- // + +#define pwm_wrap_target 0 +#define pwm_wrap 6 + +static const uint16_t pwm_program_instructions[] = { + // .wrap_target + 0x9080, // 0: pull noblock side 0 + 0xa027, // 1: mov x, osr + 0xa046, // 2: mov y, isr + 0x00a5, // 3: jmp x != y, 5 + 0x1806, // 4: jmp 6 side 1 + 0xa042, // 5: nop + 0x0083, // 6: jmp y--, 3 + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program pwm_program = { + .instructions = pwm_program_instructions, + .length = 7, + .origin = -1, +}; + +static inline pio_sm_config pwm_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + pwm_wrap_target, offset + pwm_wrap); + sm_config_set_sideset(&c, 2, true, false); + return c; +} + +static inline void pwm_program_init(PIO pio, uint sm, uint offset, uint pin) { + pio_gpio_init(pio, pin); + pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true); + pio_sm_config c = pwm_program_get_default_config(offset); + sm_config_set_sideset_pins(&c, pin); + pio_sm_init(pio, sm, offset, &c); +} + +#endif + diff --git a/src/hal/pio/assembler/comparison_tests/quadrature_encoder.pio b/src/hal/pio/assembler/comparison_tests/quadrature_encoder.pio new file mode 100644 index 0000000..d245d4b --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/quadrature_encoder.pio @@ -0,0 +1,165 @@ +; +; Copyright (c) 2021 pmarques-dev @ github +; +; SPDX-License-Identifier: BSD-3-Clause +; + +.program quadrature_encoder + +; this code must be loaded into address 0, but at 29 instructions, it probably +; wouldn't be able to share space with other programs anyway +.origin 0 + + +; the code works by running a loop that continuously shifts the 2 phase pins into +; ISR and looks at the lower 4 bits to do a computed jump to an instruction that +; does the proper "do nothing" | "increment" | "decrement" action for that pin +; state change (or no change) + +; ISR holds the last state of the 2 pins during most of the code. The Y register +; keeps the current encoder count and is incremented / decremented according to +; the steps sampled + +; writing any non zero value to the TX FIFO makes the state machine push the +; current count to RX FIFO between 6 to 18 clocks afterwards. The worst case +; sampling loop takes 14 cycles, so this program is able to read step rates up +; to sysclk / 14 (e.g., sysclk 125MHz, max step rate = 8.9 Msteps/sec) + + +; 00 state + JMP update ; read 00 + JMP decrement ; read 01 + JMP increment ; read 10 + JMP update ; read 11 + +; 01 state + JMP increment ; read 00 + JMP update ; read 01 + JMP update ; read 10 + JMP decrement ; read 11 + +; 10 state + JMP decrement ; read 00 + JMP update ; read 01 + JMP update ; read 10 + JMP increment ; read 11 + +; to reduce code size, the last 2 states are implemented in place and become the +; target for the other jumps + +; 11 state + JMP update ; read 00 + JMP increment ; read 01 +decrement: + ; note: the target of this instruction must be the next address, so that + ; the effect of the instruction does not depend on the value of Y. The + ; same is true for the "JMP X--" below. Basically "JMP Y--, " + ; is just a pure "decrement Y" instruction, with no other side effects + JMP Y--, update ; read 10 + + ; this is where the main loop starts +.wrap_target +update: + ; we start by checking the TX FIFO to see if the main code is asking for + ; the current count after the PULL noblock, OSR will have either 0 if + ; there was nothing or the value that was there + SET X, 0 + PULL noblock + + ; since there are not many free registers, and PULL is done into OSR, we + ; have to do some juggling to avoid losing the state information and + ; still place the values where we need them + MOV X, OSR + MOV OSR, ISR + + ; the main code did not ask for the count, so just go to "sample_pins" + JMP !X, sample_pins + + ; if it did ask for the count, then we push it + MOV ISR, Y ; we trash ISR, but we already have a copy in OSR + PUSH + +sample_pins: + ; we shift into ISR the last state of the 2 input pins (now in OSR) and + ; the new state of the 2 pins, thus producing the 4 bit target for the + ; computed jump into the correct action for this state + MOV ISR, NULL + IN OSR, 2 + IN PINS, 2 + MOV PC, ISR + + ; the PIO does not have a increment instruction, so to do that we do a + ; negate, decrement, negate sequence +increment: + MOV X, !Y + JMP X--, increment_cont +increment_cont: + MOV Y, !X +.wrap ; the .wrap here avoids one jump instruction and saves a cycle too + + + +% c-sdk { + +#include "hardware/clocks.h" +#include "hardware/gpio.h" + +// max_step_rate is used to lower the clock of the state machine to save power +// if the application doesn't require a very high sampling rate. Passing zero +// will set the clock to the maximum, which gives a max step rate of around +// 8.9 Msteps/sec at 125MHz + +static inline void quadrature_encoder_program_init(PIO pio, uint sm, uint offset, uint pin, int max_step_rate) +{ + pio_sm_set_consecutive_pindirs(pio, sm, pin, 2, false); + gpio_pull_up(pin); + gpio_pull_up(pin + 1); + + pio_sm_config c = quadrature_encoder_program_get_default_config(offset); + sm_config_set_in_pins(&c, pin); // for WAIT, IN + sm_config_set_jmp_pin(&c, pin); // for JMP + // shift to left, autopull disabled + sm_config_set_in_shift(&c, false, false, 32); + // don't join FIFO's + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_NONE); + + // passing "0" as the sample frequency, + if (max_step_rate == 0) { + sm_config_set_clkdiv(&c, 1.0); + } else { + // one state machine loop takes at most 14 cycles + float div = (float)clock_get_hz(clk_sys) / (14 * max_step_rate); + sm_config_set_clkdiv(&c, div); + } + + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); +} + + +// When requesting the current count we may have to wait a few cycles (average +// ~11 sysclk cycles) for the state machine to reply. If we are reading multiple +// encoders, we may request them all in one go and then fetch them all, thus +// avoiding doing the wait multiple times. If we are reading just one encoder, +// we can use the "get_count" function to request and wait + +static inline void quadrature_encoder_request_count(PIO pio, uint sm) +{ + pio->txf[sm] = 1; +} + +static inline int32_t quadrature_encoder_fetch_count(PIO pio, uint sm) +{ + while (pio_sm_is_rx_fifo_empty(pio, sm)) + tight_loop_contents(); + return pio->rxf[sm]; +} + +static inline int32_t quadrature_encoder_get_count(PIO pio, uint sm) +{ + quadrature_encoder_request_count(pio, sm); + return quadrature_encoder_fetch_count(pio, sm); +} + +%} + diff --git a/src/hal/pio/assembler/comparison_tests/quadrature_encoder.pio.h b/src/hal/pio/assembler/comparison_tests/quadrature_encoder.pio.h new file mode 100644 index 0000000..4cc4bb3 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/quadrature_encoder.pio.h @@ -0,0 +1,116 @@ +// -------------------------------------------------- // +// This file is autogenerated by pioasm; do not edit! // +// -------------------------------------------------- // + +#pragma once + +#if !PICO_NO_HARDWARE +#include "hardware/pio.h" +#endif + +// ------------------ // +// quadrature_encoder // +// ------------------ // + +#define quadrature_encoder_wrap_target 15 +#define quadrature_encoder_wrap 28 + +static const uint16_t quadrature_encoder_program_instructions[] = { + 0x000f, // 0: jmp 15 + 0x000e, // 1: jmp 14 + 0x001a, // 2: jmp 26 + 0x000f, // 3: jmp 15 + 0x001a, // 4: jmp 26 + 0x000f, // 5: jmp 15 + 0x000f, // 6: jmp 15 + 0x000e, // 7: jmp 14 + 0x000e, // 8: jmp 14 + 0x000f, // 9: jmp 15 + 0x000f, // 10: jmp 15 + 0x001a, // 11: jmp 26 + 0x000f, // 12: jmp 15 + 0x001a, // 13: jmp 26 + 0x008f, // 14: jmp y--, 15 + // .wrap_target + 0xe020, // 15: set x, 0 + 0x8080, // 16: pull noblock + 0xa027, // 17: mov x, osr + 0xa0e6, // 18: mov osr, isr + 0x0036, // 19: jmp !x, 22 + 0xa0c2, // 20: mov isr, y + 0x8020, // 21: push block + 0xa0c3, // 22: mov isr, null + 0x40e2, // 23: in osr, 2 + 0x4002, // 24: in pins, 2 + 0xa0a6, // 25: mov pc, isr + 0xa02a, // 26: mov x, !y + 0x005c, // 27: jmp x--, 28 + 0xa049, // 28: mov y, !x + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program quadrature_encoder_program = { + .instructions = quadrature_encoder_program_instructions, + .length = 29, + .origin = 0, +}; + +static inline pio_sm_config quadrature_encoder_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + quadrature_encoder_wrap_target, offset + quadrature_encoder_wrap); + return c; +} + +#include "hardware/clocks.h" +#include "hardware/gpio.h" +// max_step_rate is used to lower the clock of the state machine to save power +// if the application doesn't require a very high sampling rate. Passing zero +// will set the clock to the maximum, which gives a max step rate of around +// 8.9 Msteps/sec at 125MHz +static inline void quadrature_encoder_program_init(PIO pio, uint sm, uint offset, uint pin, int max_step_rate) +{ + pio_sm_set_consecutive_pindirs(pio, sm, pin, 2, false); + gpio_pull_up(pin); + gpio_pull_up(pin + 1); + pio_sm_config c = quadrature_encoder_program_get_default_config(offset); + sm_config_set_in_pins(&c, pin); // for WAIT, IN + sm_config_set_jmp_pin(&c, pin); // for JMP + // shift to left, autopull disabled + sm_config_set_in_shift(&c, false, false, 32); + // don't join FIFO's + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_NONE); + // passing "0" as the sample frequency, + if (max_step_rate == 0) { + sm_config_set_clkdiv(&c, 1.0); + } else { + // one state machine loop takes at most 14 cycles + float div = (float)clock_get_hz(clk_sys) / (14 * max_step_rate); + sm_config_set_clkdiv(&c, div); + } + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); +} +// When requesting the current count we may have to wait a few cycles (average +// ~11 sysclk cycles) for the state machine to reply. If we are reading multiple +// encoders, we may request them all in one go and then fetch them all, thus +// avoiding doing the wait multiple times. If we are reading just one encoder, +// we can use the "get_count" function to request and wait +static inline void quadrature_encoder_request_count(PIO pio, uint sm) +{ + pio->txf[sm] = 1; +} +static inline int32_t quadrature_encoder_fetch_count(PIO pio, uint sm) +{ + while (pio_sm_is_rx_fifo_empty(pio, sm)) + tight_loop_contents(); + return pio->rxf[sm]; +} +static inline int32_t quadrature_encoder_get_count(PIO pio, uint sm) +{ + quadrature_encoder_request_count(pio, sm); + return quadrature_encoder_fetch_count(pio, sm); +} + +#endif + diff --git a/src/hal/pio/assembler/comparison_tests/resistor_dac.pio b/src/hal/pio/assembler/comparison_tests/resistor_dac.pio new file mode 100644 index 0000000..2dca1f1 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/resistor_dac.pio @@ -0,0 +1,38 @@ +; +; Copyright (c) 2021 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; + +.program resistor_dac_5bit + +; Drive one of the 5-bit resistor DACs on the VGA reference board. (this isn't +; a good way to do VGA -- just want a nice sawtooth for the ADC example!) + + out pins, 5 + + + +% c-sdk { +#include "hardware/clocks.h" +static inline void resistor_dac_5bit_program_init(PIO pio, uint sm, uint offset, + uint sample_rate_hz, uint pin_base) { + + pio_sm_set_pins_with_mask(pio, sm, 0, 0x1fu << pin_base); + pio_sm_set_pindirs_with_mask(pio, sm, ~0u, 0x1fu << pin_base); + for (int i = 0; i < 5; ++i) + pio_gpio_init(pio, pin_base + i); + + pio_sm_config c = resistor_dac_5bit_program_get_default_config(offset); + sm_config_set_out_pins(&c, pin_base, 5); + // Shift to right, autopull threshold 5 + sm_config_set_out_shift(&c, true, true, 5); + // Deeper FIFO as we're not doing any RX + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); + float div = (float)clock_get_hz(clk_sys) / sample_rate_hz; + sm_config_set_clkdiv(&c, div); + + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); +} +%} diff --git a/src/hal/pio/assembler/comparison_tests/resistor_dac.pio.h b/src/hal/pio/assembler/comparison_tests/resistor_dac.pio.h new file mode 100644 index 0000000..df80791 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/resistor_dac.pio.h @@ -0,0 +1,57 @@ +// -------------------------------------------------- // +// This file is autogenerated by pioasm; do not edit! // +// -------------------------------------------------- // + +#pragma once + +#if !PICO_NO_HARDWARE +#include "hardware/pio.h" +#endif + +// ----------------- // +// resistor_dac_5bit // +// ----------------- // + +#define resistor_dac_5bit_wrap_target 0 +#define resistor_dac_5bit_wrap 0 + +static const uint16_t resistor_dac_5bit_program_instructions[] = { + // .wrap_target + 0x6005, // 0: out pins, 5 + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program resistor_dac_5bit_program = { + .instructions = resistor_dac_5bit_program_instructions, + .length = 1, + .origin = -1, +}; + +static inline pio_sm_config resistor_dac_5bit_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + resistor_dac_5bit_wrap_target, offset + resistor_dac_5bit_wrap); + return c; +} + +#include "hardware/clocks.h" +static inline void resistor_dac_5bit_program_init(PIO pio, uint sm, uint offset, + uint sample_rate_hz, uint pin_base) { + pio_sm_set_pins_with_mask(pio, sm, 0, 0x1fu << pin_base); + pio_sm_set_pindirs_with_mask(pio, sm, ~0u, 0x1fu << pin_base); + for (int i = 0; i < 5; ++i) + pio_gpio_init(pio, pin_base + i); + pio_sm_config c = resistor_dac_5bit_program_get_default_config(offset); + sm_config_set_out_pins(&c, pin_base, 5); + // Shift to right, autopull threshold 5 + sm_config_set_out_shift(&c, true, true, 5); + // Deeper FIFO as we're not doing any RX + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); + float div = (float)clock_get_hz(clk_sys) / sample_rate_hz; + sm_config_set_clkdiv(&c, div); + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); +} + +#endif + diff --git a/src/hal/pio/assembler/comparison_tests/spi.pio b/src/hal/pio/assembler/comparison_tests/spi.pio new file mode 100644 index 0000000..eba785e --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/spi.pio @@ -0,0 +1,168 @@ +; +; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; + +; These programs implement full-duplex SPI, with a SCK period of 4 clock +; cycles. A different program is provided for each value of CPHA, and CPOL is +; achieved using the hardware GPIO inversion available in the IO controls. +; +; Transmit-only SPI can go twice as fast -- see the ST7789 example! + + +.program spi_cpha0 +.side_set 1 + +; Pin assignments: +; - SCK is side-set pin 0 +; - MOSI is OUT pin 0 +; - MISO is IN pin 0 +; +; Autopush and autopull must be enabled, and the serial frame size is set by +; configuring the push/pull threshold. Shift left/right is fine, but you must +; justify the data yourself. This is done most conveniently for frame sizes of +; 8 or 16 bits by using the narrow store replication and narrow load byte +; picking behaviour of RP2040's IO fabric. + +; Clock phase = 0: data is captured on the leading edge of each SCK pulse, and +; transitions on the trailing edge, or some time before the first leading edge. + + out pins, 1 side 0 [1] ; Stall here on empty (sideset proceeds even if + in pins, 1 side 1 [1] ; instruction stalls, so we stall with SCK low) + +.program spi_cpha1 +.side_set 1 + +; Clock phase = 1: data transitions on the leading edge of each SCK pulse, and +; is captured on the trailing edge. + + out x, 1 side 0 ; Stall here on empty (keep SCK deasserted) + mov pins, x side 1 [1] ; Output data, assert SCK (mov pins uses OUT mapping) + in pins, 1 side 0 ; Input data, deassert SCK + +% c-sdk { +#include "hardware/gpio.h" +static inline void pio_spi_init(PIO pio, uint sm, uint prog_offs, uint n_bits, + float clkdiv, bool cpha, bool cpol, uint pin_sck, uint pin_mosi, uint pin_miso) { + pio_sm_config c = cpha ? spi_cpha1_program_get_default_config(prog_offs) : spi_cpha0_program_get_default_config(prog_offs); + sm_config_set_out_pins(&c, pin_mosi, 1); + sm_config_set_in_pins(&c, pin_miso); + sm_config_set_sideset_pins(&c, pin_sck); + // Only support MSB-first in this example code (shift to left, auto push/pull, threshold=nbits) + sm_config_set_out_shift(&c, false, true, n_bits); + sm_config_set_in_shift(&c, false, true, n_bits); + sm_config_set_clkdiv(&c, clkdiv); + + // MOSI, SCK output are low, MISO is input + pio_sm_set_pins_with_mask(pio, sm, 0, (1u << pin_sck) | (1u << pin_mosi)); + pio_sm_set_pindirs_with_mask(pio, sm, (1u << pin_sck) | (1u << pin_mosi), (1u << pin_sck) | (1u << pin_mosi) | (1u << pin_miso)); + pio_gpio_init(pio, pin_mosi); + pio_gpio_init(pio, pin_miso); + pio_gpio_init(pio, pin_sck); + + // The pin muxes can be configured to invert the output (among other things + // and this is a cheesy way to get CPOL=1 + gpio_set_outover(pin_sck, cpol ? GPIO_OVERRIDE_INVERT : GPIO_OVERRIDE_NORMAL); + // SPI is synchronous, so bypass input synchroniser to reduce input delay. + hw_set_bits(&pio->input_sync_bypass, 1u << pin_miso); + + pio_sm_init(pio, sm, prog_offs, &c); + pio_sm_set_enabled(pio, sm, true); +} +%} + +; SPI with Chip Select +; ----------------------------------------------------------------------------- +; +; For your amusement, here are some SPI programs with an automatic chip select +; (asserted once data appears in TX FIFO, deasserts when FIFO bottoms out, has +; a nice front/back porch). +; +; The number of bits per FIFO entry is configured via the Y register +; and the autopush/pull threshold. From 2 to 32 bits. +; +; Pin assignments: +; - SCK is side-set bit 0 +; - CSn is side-set bit 1 +; - MOSI is OUT bit 0 (host-to-device) +; - MISO is IN bit 0 (device-to-host) +; +; This program only supports one chip select -- use GPIO if more are needed +; +; Provide a variation for each possibility of CPHA; for CPOL we can just +; invert SCK in the IO muxing controls (downstream from PIO) + + +; CPHA=0: data is captured on the leading edge of each SCK pulse (including +; the first pulse), and transitions on the trailing edge + +.program spi_cpha0_cs +.side_set 2 + +.wrap_target +bitloop: + out pins, 1 side 0x0 [1] + in pins, 1 side 0x1 + jmp x-- bitloop side 0x1 + + out pins, 1 side 0x0 + mov x, y side 0x0 ; Reload bit counter from Y + in pins, 1 side 0x1 + jmp !osre bitloop side 0x1 ; Fall-through if TXF empties + + nop side 0x0 [1] ; CSn back porch +public entry_point: ; Must set X,Y to n-2 before starting! + pull ifempty side 0x2 [1] ; Block with CSn high (minimum 2 cycles) +.wrap ; Note ifempty to avoid time-of-check race + +; CPHA=1: data transitions on the leading edge of each SCK pulse, and is +; captured on the trailing edge + +.program spi_cpha1_cs +.side_set 2 + +.wrap_target +bitloop: + out pins, 1 side 0x1 [1] + in pins, 1 side 0x0 + jmp x-- bitloop side 0x0 + + out pins, 1 side 0x1 + mov x, y side 0x1 + in pins, 1 side 0x0 + jmp !osre bitloop side 0x0 + +public entry_point: ; Must set X,Y to n-2 before starting! + pull ifempty side 0x2 [1] ; Block with CSn high (minimum 2 cycles) + nop side 0x0 [1]; CSn front porch +.wrap + +% c-sdk { +#include "hardware/gpio.h" +static inline void pio_spi_cs_init(PIO pio, uint sm, uint prog_offs, uint n_bits, float clkdiv, bool cpha, bool cpol, + uint pin_sck, uint pin_mosi, uint pin_miso) { + pio_sm_config c = cpha ? spi_cpha1_cs_program_get_default_config(prog_offs) : spi_cpha0_cs_program_get_default_config(prog_offs); + sm_config_set_out_pins(&c, pin_mosi, 1); + sm_config_set_in_pins(&c, pin_miso); + sm_config_set_sideset_pins(&c, pin_sck); + sm_config_set_out_shift(&c, false, true, n_bits); + sm_config_set_in_shift(&c, false, true, n_bits); + sm_config_set_clkdiv(&c, clkdiv); + + pio_sm_set_pins_with_mask(pio, sm, (2u << pin_sck), (3u << pin_sck) | (1u << pin_mosi)); + pio_sm_set_pindirs_with_mask(pio, sm, (3u << pin_sck) | (1u << pin_mosi), (3u << pin_sck) | (1u << pin_mosi) | (1u << pin_miso)); + pio_gpio_init(pio, pin_mosi); + pio_gpio_init(pio, pin_miso); + pio_gpio_init(pio, pin_sck); + pio_gpio_init(pio, pin_sck + 1); + gpio_set_outover(pin_sck, cpol ? GPIO_OVERRIDE_INVERT : GPIO_OVERRIDE_NORMAL); + hw_set_bits(&pio->input_sync_bypass, 1u << pin_miso); + + uint entry_point = prog_offs + (cpha ? spi_cpha1_cs_offset_entry_point : spi_cpha0_cs_offset_entry_point); + pio_sm_init(pio, sm, entry_point, &c); + pio_sm_exec(pio, sm, pio_encode_set(pio_x, n_bits - 2)); + pio_sm_exec(pio, sm, pio_encode_set(pio_y, n_bits - 2)); + pio_sm_set_enabled(pio, sm, true); +} +%} diff --git a/src/hal/pio/assembler/comparison_tests/spi.pio.h b/src/hal/pio/assembler/comparison_tests/spi.pio.h new file mode 100644 index 0000000..22aa805 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/spi.pio.h @@ -0,0 +1,198 @@ +// -------------------------------------------------- // +// This file is autogenerated by pioasm; do not edit! // +// -------------------------------------------------- // + +#pragma once + +#if !PICO_NO_HARDWARE +#include "hardware/pio.h" +#endif + +// --------- // +// spi_cpha0 // +// --------- // + +#define spi_cpha0_wrap_target 0 +#define spi_cpha0_wrap 1 + +static const uint16_t spi_cpha0_program_instructions[] = { + // .wrap_target + 0x6101, // 0: out pins, 1 side 0 [1] + 0x5101, // 1: in pins, 1 side 1 [1] + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program spi_cpha0_program = { + .instructions = spi_cpha0_program_instructions, + .length = 2, + .origin = -1, +}; + +static inline pio_sm_config spi_cpha0_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + spi_cpha0_wrap_target, offset + spi_cpha0_wrap); + sm_config_set_sideset(&c, 1, false, false); + return c; +} +#endif + +// --------- // +// spi_cpha1 // +// --------- // + +#define spi_cpha1_wrap_target 0 +#define spi_cpha1_wrap 2 + +static const uint16_t spi_cpha1_program_instructions[] = { + // .wrap_target + 0x6021, // 0: out x, 1 side 0 + 0xb101, // 1: mov pins, x side 1 [1] + 0x4001, // 2: in pins, 1 side 0 + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program spi_cpha1_program = { + .instructions = spi_cpha1_program_instructions, + .length = 3, + .origin = -1, +}; + +static inline pio_sm_config spi_cpha1_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + spi_cpha1_wrap_target, offset + spi_cpha1_wrap); + sm_config_set_sideset(&c, 1, false, false); + return c; +} + +#include "hardware/gpio.h" +static inline void pio_spi_init(PIO pio, uint sm, uint prog_offs, uint n_bits, + float clkdiv, bool cpha, bool cpol, uint pin_sck, uint pin_mosi, uint pin_miso) { + pio_sm_config c = cpha ? spi_cpha1_program_get_default_config(prog_offs) : spi_cpha0_program_get_default_config(prog_offs); + sm_config_set_out_pins(&c, pin_mosi, 1); + sm_config_set_in_pins(&c, pin_miso); + sm_config_set_sideset_pins(&c, pin_sck); + // Only support MSB-first in this example code (shift to left, auto push/pull, threshold=nbits) + sm_config_set_out_shift(&c, false, true, n_bits); + sm_config_set_in_shift(&c, false, true, n_bits); + sm_config_set_clkdiv(&c, clkdiv); + // MOSI, SCK output are low, MISO is input + pio_sm_set_pins_with_mask(pio, sm, 0, (1u << pin_sck) | (1u << pin_mosi)); + pio_sm_set_pindirs_with_mask(pio, sm, (1u << pin_sck) | (1u << pin_mosi), (1u << pin_sck) | (1u << pin_mosi) | (1u << pin_miso)); + pio_gpio_init(pio, pin_mosi); + pio_gpio_init(pio, pin_miso); + pio_gpio_init(pio, pin_sck); + // The pin muxes can be configured to invert the output (among other things + // and this is a cheesy way to get CPOL=1 + gpio_set_outover(pin_sck, cpol ? GPIO_OVERRIDE_INVERT : GPIO_OVERRIDE_NORMAL); + // SPI is synchronous, so bypass input synchroniser to reduce input delay. + hw_set_bits(&pio->input_sync_bypass, 1u << pin_miso); + pio_sm_init(pio, sm, prog_offs, &c); + pio_sm_set_enabled(pio, sm, true); +} + +#endif + +// ------------ // +// spi_cpha0_cs // +// ------------ // + +#define spi_cpha0_cs_wrap_target 0 +#define spi_cpha0_cs_wrap 8 + +#define spi_cpha0_cs_offset_entry_point 8u + +static const uint16_t spi_cpha0_cs_program_instructions[] = { + // .wrap_target + 0x6101, // 0: out pins, 1 side 0 [1] + 0x4801, // 1: in pins, 1 side 1 + 0x0840, // 2: jmp x--, 0 side 1 + 0x6001, // 3: out pins, 1 side 0 + 0xa022, // 4: mov x, y side 0 + 0x4801, // 5: in pins, 1 side 1 + 0x08e0, // 6: jmp !osre, 0 side 1 + 0xa142, // 7: nop side 0 [1] + 0x91e0, // 8: pull ifempty block side 2 [1] + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program spi_cpha0_cs_program = { + .instructions = spi_cpha0_cs_program_instructions, + .length = 9, + .origin = -1, +}; + +static inline pio_sm_config spi_cpha0_cs_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + spi_cpha0_cs_wrap_target, offset + spi_cpha0_cs_wrap); + sm_config_set_sideset(&c, 2, false, false); + return c; +} +#endif + +// ------------ // +// spi_cpha1_cs // +// ------------ // + +#define spi_cpha1_cs_wrap_target 0 +#define spi_cpha1_cs_wrap 8 + +#define spi_cpha1_cs_offset_entry_point 7u + +static const uint16_t spi_cpha1_cs_program_instructions[] = { + // .wrap_target + 0x6901, // 0: out pins, 1 side 1 [1] + 0x4001, // 1: in pins, 1 side 0 + 0x0040, // 2: jmp x--, 0 side 0 + 0x6801, // 3: out pins, 1 side 1 + 0xa822, // 4: mov x, y side 1 + 0x4001, // 5: in pins, 1 side 0 + 0x00e0, // 6: jmp !osre, 0 side 0 + 0x91e0, // 7: pull ifempty block side 2 [1] + 0xa142, // 8: nop side 0 [1] + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program spi_cpha1_cs_program = { + .instructions = spi_cpha1_cs_program_instructions, + .length = 9, + .origin = -1, +}; + +static inline pio_sm_config spi_cpha1_cs_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + spi_cpha1_cs_wrap_target, offset + spi_cpha1_cs_wrap); + sm_config_set_sideset(&c, 2, false, false); + return c; +} + +#include "hardware/gpio.h" +static inline void pio_spi_cs_init(PIO pio, uint sm, uint prog_offs, uint n_bits, float clkdiv, bool cpha, bool cpol, + uint pin_sck, uint pin_mosi, uint pin_miso) { + pio_sm_config c = cpha ? spi_cpha1_cs_program_get_default_config(prog_offs) : spi_cpha0_cs_program_get_default_config(prog_offs); + sm_config_set_out_pins(&c, pin_mosi, 1); + sm_config_set_in_pins(&c, pin_miso); + sm_config_set_sideset_pins(&c, pin_sck); + sm_config_set_out_shift(&c, false, true, n_bits); + sm_config_set_in_shift(&c, false, true, n_bits); + sm_config_set_clkdiv(&c, clkdiv); + pio_sm_set_pins_with_mask(pio, sm, (2u << pin_sck), (3u << pin_sck) | (1u << pin_mosi)); + pio_sm_set_pindirs_with_mask(pio, sm, (3u << pin_sck) | (1u << pin_mosi), (3u << pin_sck) | (1u << pin_mosi) | (1u << pin_miso)); + pio_gpio_init(pio, pin_mosi); + pio_gpio_init(pio, pin_miso); + pio_gpio_init(pio, pin_sck); + pio_gpio_init(pio, pin_sck + 1); + gpio_set_outover(pin_sck, cpol ? GPIO_OVERRIDE_INVERT : GPIO_OVERRIDE_NORMAL); + hw_set_bits(&pio->input_sync_bypass, 1u << pin_miso); + uint entry_point = prog_offs + (cpha ? spi_cpha1_cs_offset_entry_point : spi_cpha0_cs_offset_entry_point); + pio_sm_init(pio, sm, entry_point, &c); + pio_sm_exec(pio, sm, pio_encode_set(pio_x, n_bits - 2)); + pio_sm_exec(pio, sm, pio_encode_set(pio_y, n_bits - 2)); + pio_sm_set_enabled(pio, sm, true); +} + +#endif + diff --git a/src/hal/pio/assembler/comparison_tests/squarewave.pio b/src/hal/pio/assembler/comparison_tests/squarewave.pio new file mode 100644 index 0000000..405c899 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/squarewave.pio @@ -0,0 +1,13 @@ +; +; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; + +.program squarewave + set pindirs, 1 ; Set pin to output +again: + set pins, 1 [1] ; Drive pin high and then delay for one cycle + set pins, 0 ; Drive pin low + jmp again ; Set PC to label `again` + diff --git a/src/hal/pio/assembler/comparison_tests/squarewave.pio.h b/src/hal/pio/assembler/comparison_tests/squarewave.pio.h new file mode 100644 index 0000000..9ec7ea6 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/squarewave.pio.h @@ -0,0 +1,40 @@ +// -------------------------------------------------- // +// This file is autogenerated by pioasm; do not edit! // +// -------------------------------------------------- // + +#pragma once + +#if !PICO_NO_HARDWARE +#include "hardware/pio.h" +#endif + +// ---------- // +// squarewave // +// ---------- // + +#define squarewave_wrap_target 0 +#define squarewave_wrap 3 + +static const uint16_t squarewave_program_instructions[] = { + // .wrap_target + 0xe081, // 0: set pindirs, 1 + 0xe101, // 1: set pins, 1 [1] + 0xe000, // 2: set pins, 0 + 0x0001, // 3: jmp 1 + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program squarewave_program = { + .instructions = squarewave_program_instructions, + .length = 4, + .origin = -1, +}; + +static inline pio_sm_config squarewave_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + squarewave_wrap_target, offset + squarewave_wrap); + return c; +} +#endif + diff --git a/src/hal/pio/assembler/comparison_tests/squarewave_fast.pio b/src/hal/pio/assembler/comparison_tests/squarewave_fast.pio new file mode 100644 index 0000000..26162fa --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/squarewave_fast.pio @@ -0,0 +1,19 @@ +; +; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; + +; Note that if you modify squarewave.c to include this program, you'll also +; need to set the wrap registers yourself. This would be handled for you by +; squarewave_program_get_default_config(). + + +.program squarewave_fast +; Like squarewave_wrap, but remove the delay cycles so we can run twice as fast. + set pindirs, 1 ; Set pin to output +.wrap_target + set pins, 1 ; Drive pin high + set pins, 0 ; Drive pin low +.wrap + diff --git a/src/hal/pio/assembler/comparison_tests/squarewave_fast.pio.h b/src/hal/pio/assembler/comparison_tests/squarewave_fast.pio.h new file mode 100644 index 0000000..686209c --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/squarewave_fast.pio.h @@ -0,0 +1,39 @@ +// -------------------------------------------------- // +// This file is autogenerated by pioasm; do not edit! // +// -------------------------------------------------- // + +#pragma once + +#if !PICO_NO_HARDWARE +#include "hardware/pio.h" +#endif + +// --------------- // +// squarewave_fast // +// --------------- // + +#define squarewave_fast_wrap_target 1 +#define squarewave_fast_wrap 2 + +static const uint16_t squarewave_fast_program_instructions[] = { + 0xe081, // 0: set pindirs, 1 + // .wrap_target + 0xe001, // 1: set pins, 1 + 0xe000, // 2: set pins, 0 + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program squarewave_fast_program = { + .instructions = squarewave_fast_program_instructions, + .length = 3, + .origin = -1, +}; + +static inline pio_sm_config squarewave_fast_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + squarewave_fast_wrap_target, offset + squarewave_fast_wrap); + return c; +} +#endif + diff --git a/src/hal/pio/assembler/comparison_tests/squarewave_test.pio b/src/hal/pio/assembler/comparison_tests/squarewave_test.pio new file mode 100644 index 0000000..1b3e290 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/squarewave_test.pio @@ -0,0 +1,12 @@ +; +; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; + +.program squarewave +set pindirs, 1 ; Set pin to output +again: set pins, 1 [1] ; Drive pin high and then delay for one cycle + set pins, 0 ; Drive pin low + jmp again ; Set PC to label `again` + diff --git a/src/hal/pio/assembler/comparison_tests/squarewave_wrap.pio b/src/hal/pio/assembler/comparison_tests/squarewave_wrap.pio new file mode 100644 index 0000000..100f09c --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/squarewave_wrap.pio @@ -0,0 +1,19 @@ +; +; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; + +; Note that if you modify squarewave.c to include this program, you'll also +; need to set the wrap registers yourself. This would be handled for you by +; squarewave_program_get_default_config(). + +.program squarewave_wrap +; Like squarewave, but use the state machine's .wrap hardware instead of an +; explicit jmp. This is a free (0-cycle) unconditional jump. + + set pindirs, 1 ; Set pin to output +.wrap_target + set pins, 1 [1] ; Drive pin high and then delay for one cycle + set pins, 0 [1] ; Drive pin low and then delay for one cycle +.wrap diff --git a/src/hal/pio/assembler/comparison_tests/squarewave_wrap.pio.h b/src/hal/pio/assembler/comparison_tests/squarewave_wrap.pio.h new file mode 100644 index 0000000..ff90703 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/squarewave_wrap.pio.h @@ -0,0 +1,39 @@ +// -------------------------------------------------- // +// This file is autogenerated by pioasm; do not edit! // +// -------------------------------------------------- // + +#pragma once + +#if !PICO_NO_HARDWARE +#include "hardware/pio.h" +#endif + +// --------------- // +// squarewave_wrap // +// --------------- // + +#define squarewave_wrap_wrap_target 1 +#define squarewave_wrap_wrap 2 + +static const uint16_t squarewave_wrap_program_instructions[] = { + 0xe081, // 0: set pindirs, 1 + // .wrap_target + 0xe101, // 1: set pins, 1 [1] + 0xe100, // 2: set pins, 0 [1] + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program squarewave_wrap_program = { + .instructions = squarewave_wrap_program_instructions, + .length = 3, + .origin = -1, +}; + +static inline pio_sm_config squarewave_wrap_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + squarewave_wrap_wrap_target, offset + squarewave_wrap_wrap); + return c; +} +#endif + diff --git a/src/hal/pio/assembler/comparison_tests/st7789_lcd.pio b/src/hal/pio/assembler/comparison_tests/st7789_lcd.pio new file mode 100644 index 0000000..aa35c68 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/st7789_lcd.pio @@ -0,0 +1,57 @@ +; +; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; + +.program st7789_lcd +.side_set 1 + +; This is just a simple clocked serial TX. At 125 MHz system clock we can +; sustain up to 62.5 Mbps. +; Data on OUT pin 0 +; Clock on side-set pin 0 + +.wrap_target + out pins, 1 side 0 ; stall here if no data (clock low) + nop side 1 +.wrap + +% c-sdk { +// For optimal use of DMA bandwidth we would use an autopull threshold of 32, +// but we are using a threshold of 8 here (consume 1 byte from each FIFO entry +// and discard the remainder) to make things easier for software on the other side + +static inline void st7789_lcd_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clk_pin, float clk_div) { + pio_gpio_init(pio, data_pin); + pio_gpio_init(pio, clk_pin); + pio_sm_set_consecutive_pindirs(pio, sm, data_pin, 1, true); + pio_sm_set_consecutive_pindirs(pio, sm, clk_pin, 1, true); + pio_sm_config c = st7789_lcd_program_get_default_config(offset); + sm_config_set_sideset_pins(&c, clk_pin); + sm_config_set_out_pins(&c, data_pin, 1); + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); + sm_config_set_clkdiv(&c, clk_div); + sm_config_set_out_shift(&c, false, true, 8); + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); +} + +// Making use of the narrow store replication behaviour on RP2040 to get the +// data left-justified (as we are using shift-to-left to get MSB-first serial) + +static inline void st7789_lcd_put(PIO pio, uint sm, uint8_t x) { + while (pio_sm_is_tx_fifo_full(pio, sm)) + ; + *(volatile uint8_t*)&pio->txf[sm] = x; +} + +// SM is done when it stalls on an empty FIFO + +static inline void st7789_lcd_wait_idle(PIO pio, uint sm) { + uint32_t sm_stall_mask = 1u << (sm + PIO_FDEBUG_TXSTALL_LSB); + pio->fdebug = sm_stall_mask; + while (!(pio->fdebug & sm_stall_mask)) + ; +} +%} diff --git a/src/hal/pio/assembler/comparison_tests/st7789_lcd.pio.h b/src/hal/pio/assembler/comparison_tests/st7789_lcd.pio.h new file mode 100644 index 0000000..c77167e --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/st7789_lcd.pio.h @@ -0,0 +1,72 @@ +// -------------------------------------------------- // +// This file is autogenerated by pioasm; do not edit! // +// -------------------------------------------------- // + +#pragma once + +#if !PICO_NO_HARDWARE +#include "hardware/pio.h" +#endif + +// ---------- // +// st7789_lcd // +// ---------- // + +#define st7789_lcd_wrap_target 0 +#define st7789_lcd_wrap 1 + +static const uint16_t st7789_lcd_program_instructions[] = { + // .wrap_target + 0x6001, // 0: out pins, 1 side 0 + 0xb042, // 1: nop side 1 + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program st7789_lcd_program = { + .instructions = st7789_lcd_program_instructions, + .length = 2, + .origin = -1, +}; + +static inline pio_sm_config st7789_lcd_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + st7789_lcd_wrap_target, offset + st7789_lcd_wrap); + sm_config_set_sideset(&c, 1, false, false); + return c; +} + +// For optimal use of DMA bandwidth we would use an autopull threshold of 32, +// but we are using a threshold of 8 here (consume 1 byte from each FIFO entry +// and discard the remainder) to make things easier for software on the other side +static inline void st7789_lcd_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clk_pin, float clk_div) { + pio_gpio_init(pio, data_pin); + pio_gpio_init(pio, clk_pin); + pio_sm_set_consecutive_pindirs(pio, sm, data_pin, 1, true); + pio_sm_set_consecutive_pindirs(pio, sm, clk_pin, 1, true); + pio_sm_config c = st7789_lcd_program_get_default_config(offset); + sm_config_set_sideset_pins(&c, clk_pin); + sm_config_set_out_pins(&c, data_pin, 1); + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); + sm_config_set_clkdiv(&c, clk_div); + sm_config_set_out_shift(&c, false, true, 8); + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); +} +// Making use of the narrow store replication behaviour on RP2040 to get the +// data left-justified (as we are using shift-to-left to get MSB-first serial) +static inline void st7789_lcd_put(PIO pio, uint sm, uint8_t x) { + while (pio_sm_is_tx_fifo_full(pio, sm)) + ; + *(volatile uint8_t*)&pio->txf[sm] = x; +} +// SM is done when it stalls on an empty FIFO +static inline void st7789_lcd_wait_idle(PIO pio, uint sm) { + uint32_t sm_stall_mask = 1u << (sm + PIO_FDEBUG_TXSTALL_LSB); + pio->fdebug = sm_stall_mask; + while (!(pio->fdebug & sm_stall_mask)) + ; +} + +#endif + diff --git a/src/hal/pio/assembler/comparison_tests/uart_rx.pio b/src/hal/pio/assembler/comparison_tests/uart_rx.pio new file mode 100644 index 0000000..54a6577 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/uart_rx.pio @@ -0,0 +1,94 @@ +; +; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; + +.program uart_rx_mini + +; Minimum viable 8n1 UART receiver. Wait for the start bit, then sample 8 bits +; with the correct timing. +; IN pin 0 is mapped to the GPIO used as UART RX. +; Autopush must be enabled, with a threshold of 8. + + wait 0 pin 0 ; Wait for start bit + set x, 7 [10] ; Preload bit counter, delay until eye of first data bit +bitloop: ; Loop 8 times + in pins, 1 ; Sample data + jmp x-- bitloop [6] ; Each iteration is 8 cycles + +% c-sdk { +#include "hardware/clocks.h" +#include "hardware/gpio.h" + +static inline void uart_rx_mini_program_init(PIO pio, uint sm, uint offset, uint pin, uint baud) { + pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, false); + pio_gpio_init(pio, pin); + gpio_pull_up(pin); + + pio_sm_config c = uart_rx_mini_program_get_default_config(offset); + sm_config_set_in_pins(&c, pin); // for WAIT, IN + // Shift to right, autopush enabled + sm_config_set_in_shift(&c, true, true, 8); + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX); + // SM transmits 1 bit per 8 execution cycles. + float div = (float)clock_get_hz(clk_sys) / (8 * baud); + sm_config_set_clkdiv(&c, div); + + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); +} +%} + +.program uart_rx + +; Slightly more fleshed-out 8n1 UART receiver which handles framing errors and +; break conditions more gracefully. +; IN pin 0 and JMP pin are both mapped to the GPIO used as UART RX. + +start: + wait 0 pin 0 ; Stall until start bit is asserted + set x, 7 [10] ; Preload bit counter, then delay until halfway through +bitloop: ; the first data bit (12 cycles incl wait, set). + in pins, 1 ; Shift data bit into ISR + jmp x-- bitloop [6] ; Loop 8 times, each loop iteration is 8 cycles + jmp pin good_stop ; Check stop bit (should be high) + + irq 4 rel ; Either a framing error or a break. Set a sticky flag, + wait 1 pin 0 ; and wait for line to return to idle state. + jmp start ; Don't push data if we didn't see good framing. + +good_stop: ; No delay before returning to start; a little slack is + push ; important in case the TX clock is slightly too fast. + + +% c-sdk { +static inline void uart_rx_program_init(PIO pio, uint sm, uint offset, uint pin, uint baud) { + pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, false); + pio_gpio_init(pio, pin); + gpio_pull_up(pin); + + pio_sm_config c = uart_rx_program_get_default_config(offset); + sm_config_set_in_pins(&c, pin); // for WAIT, IN + sm_config_set_jmp_pin(&c, pin); // for JMP + // Shift to right, autopush disabled + sm_config_set_in_shift(&c, true, false, 32); + // Deeper FIFO as we're not doing any TX + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX); + // SM transmits 1 bit per 8 execution cycles. + float div = (float)clock_get_hz(clk_sys) / (8 * baud); + sm_config_set_clkdiv(&c, div); + + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); +} + +static inline char uart_rx_program_getc(PIO pio, uint sm) { + // 8-bit read from the uppermost byte of the FIFO, as data is left-justified + io_rw_8 *rxfifo_shift = (io_rw_8*)&pio->rxf[sm] + 3; + while (pio_sm_is_rx_fifo_empty(pio, sm)) + tight_loop_contents(); + return (char)*rxfifo_shift; +} + +%} diff --git a/src/hal/pio/assembler/comparison_tests/uart_rx.pio.h b/src/hal/pio/assembler/comparison_tests/uart_rx.pio.h new file mode 100644 index 0000000..b6b5da6 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/uart_rx.pio.h @@ -0,0 +1,120 @@ +// -------------------------------------------------- // +// This file is autogenerated by pioasm; do not edit! // +// -------------------------------------------------- // + +#pragma once + +#if !PICO_NO_HARDWARE +#include "hardware/pio.h" +#endif + +// ------------ // +// uart_rx_mini // +// ------------ // + +#define uart_rx_mini_wrap_target 0 +#define uart_rx_mini_wrap 3 + +static const uint16_t uart_rx_mini_program_instructions[] = { + // .wrap_target + 0x2020, // 0: wait 0 pin, 0 + 0xea27, // 1: set x, 7 [10] + 0x4001, // 2: in pins, 1 + 0x0642, // 3: jmp x--, 2 [6] + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program uart_rx_mini_program = { + .instructions = uart_rx_mini_program_instructions, + .length = 4, + .origin = -1, +}; + +static inline pio_sm_config uart_rx_mini_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + uart_rx_mini_wrap_target, offset + uart_rx_mini_wrap); + return c; +} + +#include "hardware/clocks.h" +#include "hardware/gpio.h" +static inline void uart_rx_mini_program_init(PIO pio, uint sm, uint offset, uint pin, uint baud) { + pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, false); + pio_gpio_init(pio, pin); + gpio_pull_up(pin); + pio_sm_config c = uart_rx_mini_program_get_default_config(offset); + sm_config_set_in_pins(&c, pin); // for WAIT, IN + // Shift to right, autopush enabled + sm_config_set_in_shift(&c, true, true, 8); + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX); + // SM transmits 1 bit per 8 execution cycles. + float div = (float)clock_get_hz(clk_sys) / (8 * baud); + sm_config_set_clkdiv(&c, div); + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); +} + +#endif + +// ------- // +// uart_rx // +// ------- // + +#define uart_rx_wrap_target 0 +#define uart_rx_wrap 8 + +static const uint16_t uart_rx_program_instructions[] = { + // .wrap_target + 0x2020, // 0: wait 0 pin, 0 + 0xea27, // 1: set x, 7 [10] + 0x4001, // 2: in pins, 1 + 0x0642, // 3: jmp x--, 2 [6] + 0x00c8, // 4: jmp pin, 8 + 0xc014, // 5: irq nowait 4 rel + 0x20a0, // 6: wait 1 pin, 0 + 0x0000, // 7: jmp 0 + 0x8020, // 8: push block + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program uart_rx_program = { + .instructions = uart_rx_program_instructions, + .length = 9, + .origin = -1, +}; + +static inline pio_sm_config uart_rx_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + uart_rx_wrap_target, offset + uart_rx_wrap); + return c; +} + +static inline void uart_rx_program_init(PIO pio, uint sm, uint offset, uint pin, uint baud) { + pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, false); + pio_gpio_init(pio, pin); + gpio_pull_up(pin); + pio_sm_config c = uart_rx_program_get_default_config(offset); + sm_config_set_in_pins(&c, pin); // for WAIT, IN + sm_config_set_jmp_pin(&c, pin); // for JMP + // Shift to right, autopush disabled + sm_config_set_in_shift(&c, true, false, 32); + // Deeper FIFO as we're not doing any TX + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX); + // SM transmits 1 bit per 8 execution cycles. + float div = (float)clock_get_hz(clk_sys) / (8 * baud); + sm_config_set_clkdiv(&c, div); + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); +} +static inline char uart_rx_program_getc(PIO pio, uint sm) { + // 8-bit read from the uppermost byte of the FIFO, as data is left-justified + io_rw_8 *rxfifo_shift = (io_rw_8*)&pio->rxf[sm] + 3; + while (pio_sm_is_rx_fifo_empty(pio, sm)) + tight_loop_contents(); + return (char)*rxfifo_shift; +} + +#endif + diff --git a/src/hal/pio/assembler/comparison_tests/uart_tx.pio b/src/hal/pio/assembler/comparison_tests/uart_tx.pio new file mode 100644 index 0000000..b1320f6 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/uart_tx.pio @@ -0,0 +1,61 @@ +; +; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; + +.program uart_tx +.side_set 1 opt + +; An 8n1 UART transmit program. +; OUT pin 0 and side-set pin 0 are both mapped to UART TX pin. + + pull side 1 [7] ; Assert stop bit, or stall with line in idle state + set x, 7 side 0 [7] ; Preload bit counter, assert start bit for 8 clocks +bitloop: ; This loop will run 8 times (8n1 UART) + out pins, 1 ; Shift 1 bit from OSR to the first OUT pin + jmp x-- bitloop [6] ; Each loop iteration is 8 cycles. + + +% c-sdk { +#include "hardware/clocks.h" + +static inline void uart_tx_program_init(PIO pio, uint sm, uint offset, uint pin_tx, uint baud) { + // Tell PIO to initially drive output-high on the selected pin, then map PIO + // onto that pin with the IO muxes. + pio_sm_set_pins_with_mask(pio, sm, 1u << pin_tx, 1u << pin_tx); + pio_sm_set_pindirs_with_mask(pio, sm, 1u << pin_tx, 1u << pin_tx); + pio_gpio_init(pio, pin_tx); + + pio_sm_config c = uart_tx_program_get_default_config(offset); + + // OUT shifts to right, no autopull + sm_config_set_out_shift(&c, true, false, 32); + + // We are mapping both OUT and side-set to the same pin, because sometimes + // we need to assert user data onto the pin (with OUT) and sometimes + // assert constant values (start/stop bit) + sm_config_set_out_pins(&c, pin_tx, 1); + sm_config_set_sideset_pins(&c, pin_tx); + + // We only need TX, so get an 8-deep FIFO! + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); + + // SM transmits 1 bit per 8 execution cycles. + float div = (float)clock_get_hz(clk_sys) / (8 * baud); + sm_config_set_clkdiv(&c, div); + + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); +} + +static inline void uart_tx_program_putc(PIO pio, uint sm, char c) { + pio_sm_put_blocking(pio, sm, (uint32_t)c); +} + +static inline void uart_tx_program_puts(PIO pio, uint sm, const char *s) { + while (*s) + uart_tx_program_putc(pio, sm, *s++); +} + +%} diff --git a/src/hal/pio/assembler/comparison_tests/uart_tx.pio.h b/src/hal/pio/assembler/comparison_tests/uart_tx.pio.h new file mode 100644 index 0000000..ff9b7d2 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/uart_tx.pio.h @@ -0,0 +1,73 @@ +// -------------------------------------------------- // +// This file is autogenerated by pioasm; do not edit! // +// -------------------------------------------------- // + +#pragma once + +#if !PICO_NO_HARDWARE +#include "hardware/pio.h" +#endif + +// ------- // +// uart_tx // +// ------- // + +#define uart_tx_wrap_target 0 +#define uart_tx_wrap 3 + +static const uint16_t uart_tx_program_instructions[] = { + // .wrap_target + 0x9fa0, // 0: pull block side 1 [7] + 0xf727, // 1: set x, 7 side 0 [7] + 0x6001, // 2: out pins, 1 + 0x0642, // 3: jmp x--, 2 [6] + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program uart_tx_program = { + .instructions = uart_tx_program_instructions, + .length = 4, + .origin = -1, +}; + +static inline pio_sm_config uart_tx_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + uart_tx_wrap_target, offset + uart_tx_wrap); + sm_config_set_sideset(&c, 2, true, false); + return c; +} + +#include "hardware/clocks.h" +static inline void uart_tx_program_init(PIO pio, uint sm, uint offset, uint pin_tx, uint baud) { + // Tell PIO to initially drive output-high on the selected pin, then map PIO + // onto that pin with the IO muxes. + pio_sm_set_pins_with_mask(pio, sm, 1u << pin_tx, 1u << pin_tx); + pio_sm_set_pindirs_with_mask(pio, sm, 1u << pin_tx, 1u << pin_tx); + pio_gpio_init(pio, pin_tx); + pio_sm_config c = uart_tx_program_get_default_config(offset); + // OUT shifts to right, no autopull + sm_config_set_out_shift(&c, true, false, 32); + // We are mapping both OUT and side-set to the same pin, because sometimes + // we need to assert user data onto the pin (with OUT) and sometimes + // assert constant values (start/stop bit) + sm_config_set_out_pins(&c, pin_tx, 1); + sm_config_set_sideset_pins(&c, pin_tx); + // We only need TX, so get an 8-deep FIFO! + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); + // SM transmits 1 bit per 8 execution cycles. + float div = (float)clock_get_hz(clk_sys) / (8 * baud); + sm_config_set_clkdiv(&c, div); + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); +} +static inline void uart_tx_program_putc(PIO pio, uint sm, char c) { + pio_sm_put_blocking(pio, sm, (uint32_t)c); +} +static inline void uart_tx_program_puts(PIO pio, uint sm, const char *s) { + while (*s) + uart_tx_program_putc(pio, sm, *s++); +} + +#endif + diff --git a/src/hal/pio/assembler/comparison_tests/ws2812.pio b/src/hal/pio/assembler/comparison_tests/ws2812.pio new file mode 100644 index 0000000..3c31fd6 --- /dev/null +++ b/src/hal/pio/assembler/comparison_tests/ws2812.pio @@ -0,0 +1,85 @@ +; +; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; + +.program ws2812 +.side_set 1 + +.define public T1 2 +.define public T2 5 +.define public T3 3 + +.lang_opt python sideset_init = pico.PIO.OUT_HIGH +.lang_opt python out_init = pico.PIO.OUT_HIGH +.lang_opt python out_shiftdir = 1 + +.wrap_target +bitloop: + out x, 1 side 0 [T3 - 1] ; Side-set still takes place when instruction stalls + jmp !x do_zero side 1 [T1 - 1] ; Branch on the bit we shifted out. Positive pulse +do_one: + jmp bitloop side 1 [T2 - 1] ; Continue driving high, for a long pulse +do_zero: + nop side 0 [T2 - 1] ; Or drive low, for a short pulse +.wrap + +% c-sdk { +#include "hardware/clocks.h" + +static inline void ws2812_program_init(PIO pio, uint sm, uint offset, uint pin, float freq, bool rgbw) { + + pio_gpio_init(pio, pin); + pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true); + + pio_sm_config c = ws2812_program_get_default_config(offset); + sm_config_set_sideset_pins(&c, pin); + sm_config_set_out_shift(&c, false, true, rgbw ? 32 : 24); + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); + + int cycles_per_bit = ws2812_T1 + ws2812_T2 + ws2812_T3; + float div = clock_get_hz(clk_sys) / (freq * cycles_per_bit); + sm_config_set_clkdiv(&c, div); + + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); +} +%} + +.program ws2812_parallel + +.define public T1 2 +.define public T2 5 +.define public T3 3 + +.wrap_target + out x, 32 + mov pins, !null [T1-1] + mov pins, x [T2-1] + mov pins, null [T3-2] +.wrap + +% c-sdk { +#include "hardware/clocks.h" + +static inline void ws2812_parallel_program_init(PIO pio, uint sm, uint offset, uint pin_base, uint pin_count, float freq) { + for(uint i=pin_base; i |int| @intCast(T, int), + .string => |str| outer: for (define_lists) |defines| { + for (defines) |define| { + if (std.mem.eql(u8, str, define.name)) { + if (define.value > std.math.maxInt(T)) { + diags.* = Diagnostics.init( + index, + "{s}'s value ({}) is too large to fit in {} bits", + .{ str, define.value, @bitSizeOf(T) }, + ); + + break :outer error.TooBig; + } + + break :outer @intCast(T, define.value); + } + } + } else { + diags.* = Diagnostics.init(index, "define '{s}' not found", .{ + str, + }); + + break :outer error.DefineNotFound; + }, + .expression => |expr_str| { + const expr = try Expression.tokenize(expr_str, index, diags); + const result = try expr.evaluate(define_lists, diags); + if (result < 0 or result > std.math.maxInt(T)) { + diags.* = Diagnostics.init( + index, + "value of {} does not fit in a u{}", + .{ + result, @bitSizeOf(T), + }, + ); + } + + return @intCast(T, result); + }, + }; + } + + fn evaluate( + self: *Self, + comptime T: type, + program: BoundedProgram, + value: Value, + index: u32, + diags: *?Diagnostics, + ) !T { + return evaluate_impl(T, &.{ + self.output.global_defines.slice(), + self.output.private_defines.slice(), + program.defines.slice(), + program.private_defines.slice(), + }, value, index, diags); + } + + fn evaluate_target( + self: *Self, + program: BoundedProgram, + target: []const u8, + index: u32, + diags: *?Diagnostics, + ) !u5 { + return for (program.labels.slice()) |label| { + if (std.mem.eql(u8, target, label.name)) + break label.index; + } else try self.evaluate(u5, program, try Value.from_string(target), index, diags); + } + + fn evaluate_global( + self: *Self, + comptime T: type, + value: Value, + index: u32, + diags: *?Diagnostics, + ) !T { + return evaluate_impl(T, &.{ + self.output.global_defines.slice(), + self.output.private_defines.slice(), + }, value, index, diags); + } + + fn encode_globals(self: *Self, diags: *?Diagnostics) !void { + assert(self.index == 0); + + // read defines until program is had + while (self.peek_token()) |token| switch (token.data) { + .define => |define| { + const result = DefineWithIndex{ + .name = define.name, + .value = try self.evaluate_global(i128, define.value, token.index, diags), + .index = define.index, + }; + + if (define.public) + try self.output.global_defines.append(result) + else + try self.output.private_defines.append(result); + + self.consume(1); + }, + .program => break, + else => return error.InvalidTokenInGlobalSpace, + }; + } + + fn encode_program_init(self: *Self, program: *BoundedProgram, diags: *?Diagnostics) !void { + while (self.peek_token()) |token| { + switch (token.data) { + .program, .label, .instruction, .word, .wrap_target => break, + .define => |define| { + const result = DefineWithIndex{ + .name = define.name, + .value = try self.evaluate(i128, program.*, define.value, token.index, diags), + .index = define.index, + }; + + if (define.public) + try program.defines.append(result) + else + try program.private_defines.append(result); + + self.consume(1); + }, + .origin => |value| { + program.origin = try self.evaluate(u5, program.*, value, token.index, diags); + self.consume(1); + }, + .side_set => |side_set| { + program.side_set = .{ + .count = try self.evaluate(u3, program.*, side_set.count, token.index, diags), + .optional = side_set.opt, + .pindirs = side_set.pindirs, + }; + self.consume(1); + }, + // ignore + .lang_opt => self.consume(1), + .wrap => unreachable, + } + } + } + + fn encode_instruction( + self: *Self, + program: *BoundedProgram, + token: Token.Instruction, + token_index: u32, + diags: *?Diagnostics, + ) !void { + // guaranteed to be an instruction variant + const payload: Instruction.Payload = switch (token.payload) { + .nop => .{ + .mov = .{ + .destination = .y, + .operation = .none, + .source = .y, + }, + }, + .jmp => |jmp| .{ + .jmp = .{ + .condition = jmp.condition, + .address = try self.evaluate_target(program.*, jmp.target, token_index, diags), + }, + }, + .wait => |wait| .{ + .wait = .{ + .polarity = wait.polarity, + .source = wait.source, + .index = try self.evaluate(u5, program.*, wait.num, token_index, diags), + }, + }, + .in => |in| .{ + .in = .{ + .source = in.source, + .bit_count = in.bit_count, + }, + }, + .out => |out| .{ + .out = .{ + .destination = out.destination, + .bit_count = out.bit_count, + }, + }, + .push => |push| .{ + .push = .{ + .if_full = @boolToInt(push.iffull), + .block = @boolToInt(push.block), + }, + }, + .pull => |pull| .{ + .pull = .{ + .if_empty = @boolToInt(pull.ifempty), + .block = @boolToInt(pull.block), + }, + }, + .mov => |mov| .{ + .mov = .{ + .destination = mov.destination, + .operation = mov.operation, + .source = mov.source, + }, + }, + .irq => |irq| blk: { + const irq_num = try self.evaluate(u5, program.*, irq.num, token_index, diags); + break :blk .{ + .irq = .{ + .clear = @boolToInt(irq.clear), + .wait = @boolToInt(irq.wait), + .index = if (irq.rel) + @as(u5, 0x10) | irq_num + else + irq_num, + }, + }; + }, + .set => |set| .{ + .set = .{ + .destination = set.destination, + .data = try self.evaluate(u5, program.*, set.value, token_index, diags), + }, + }, + }; + + const tag: Instruction.Tag = switch (token.payload) { + .nop => .mov, + .jmp => .jmp, + .wait => .wait, + .in => .in, + .out => .out, + .push => .push_pull, + .pull => .push_pull, + .mov => .mov, + .irq => .irq, + .set => .set, + }; + + if (program.side_set) |side_set| { + if (!side_set.optional and token.side_set == null) { + diags.* = Diagnostics.init(token_index, "'side' must be specified for this instruction because 'opt' was not specied in the .side_set directive", .{}); + return error.InvalidSideSet; + } + } else { + if (token.side_set != null) { + diags.* = Diagnostics.init(token_index, ".side_set directive must be specified for program to use side_set", .{}); + return error.InvalidSideSet; + } + } + + const side_set: ?u5 = if (token.side_set) |s| + try self.evaluate(u5, program.*, s, token_index, diags) + else + null; + + const delay: ?u5 = if (token.delay) |d| + try self.evaluate(u5, program.*, d, token_index, diags) + else + null; + + const delay_side_set = try calc_delay_side_set( + program.side_set, + side_set, + delay, + ); + + try program.instructions.append(Instruction{ + .tag = tag, + .payload = payload, + .delay_side_set = delay_side_set, + }); + } + + fn calc_delay_side_set( + program_settings: ?SideSet, + side_set_opt: ?u5, + delay_opt: ?u5, + ) !u5 { + // TODO: error for side_set/delay collision + const delay: u5 = if (delay_opt) |delay| delay else 0; + return if (program_settings) |settings| + if (settings.optional) + if (side_set_opt) |side_set| + 0x10 | (side_set << @as(u3, 4) - settings.count) | delay + else + delay + else + (side_set_opt.? << @as(u3, 5) - settings.count) | delay + else + delay; + } + + fn encode_instruction_body(self: *Self, program: *BoundedProgram, diags: *?Diagnostics) !void { + // first scan through body for labels + var instr_index: u5 = 0; + for (self.tokens[self.index..]) |token| { + switch (token.data) { + .label => |label| try program.labels.append(.{ + .name = label.name, + .public = label.public, + .index = instr_index, + }), + .instruction, .word => instr_index += 1, + .wrap_target => { + if (program.wrap_target != null) { + diags.* = Diagnostics.init(token.index, "wrap_target already set for this program", .{}); + return error.WrapTargetAlreadySet; + } + + program.wrap_target = instr_index; + }, + .wrap => { + if (program.wrap != null) { + diags.* = Diagnostics.init(token.index, "wrap already set for this program", .{}); + return error.WrapAlreadySet; + } + + program.wrap = instr_index - 1; + }, + .program => break, + else => unreachable, // invalid + } + } + + // encode instructions, labels will be populated + for (self.tokens[self.index..], self.index..) |token, i| { + switch (token.data) { + .instruction => |instr| try self.encode_instruction(program, instr, token.index, diags), + .word => |word| try program.instructions.append( + @bitCast(Instruction, try self.evaluate(u16, program.*, word, token.index, diags)), + ), + // already processed + .label, .wrap_target, .wrap => {}, + .program => { + self.index = @intCast(u32, i); + break; + }, + + else => unreachable, // invalid + } + } else if (self.tokens.len > 0) + self.index = @intCast(u32, self.tokens.len); + } + + fn encode_program(self: *Self, diags: *?Diagnostics) !?BoundedProgram { + const program_token = self.get_token() orelse return null; + if (program_token.data != .program) + return error.ExpectedProgramToken; + + var program = BoundedProgram{ + .name = program_token.data.program, + .defines = BoundedDefines.init(0) catch unreachable, + .private_defines = BoundedDefines.init(0) catch unreachable, + .instructions = BoundedInstructions.init(0) catch unreachable, + .labels = BoundedLabels.init(0) catch unreachable, + .side_set = null, + .origin = null, + .wrap_target = null, + .wrap = null, + }; + + try self.encode_program_init(&program, diags); + try self.encode_instruction_body(&program, diags); + + return program; + } + + fn encode_output(self: *Self, diags: *?Diagnostics) !Self.Output { + try self.encode_globals(diags); + + while (try self.encode_program(diags)) |program| + try self.output.programs.append(program); + + return self.output; + } + }; +} + +pub const Instruction = packed struct(u16) { + payload: Payload, + delay_side_set: u5, + tag: Tag, + + pub const Payload = packed union { + jmp: Jmp, + wait: Wait, + in: In, + out: Out, + push: Push, + pull: Pull, + mov: Mov, + irq: Irq, + set: Set, + }; + + pub const Tag = enum(u3) { + jmp, + wait, + in, + out, + push_pull, + mov, + irq, + set, + }; + + pub const Jmp = packed struct(u8) { + address: u5, + condition: Token.Instruction.Jmp.Condition, + }; + + pub const Wait = packed struct(u8) { + index: u5, + source: Token.Instruction.Wait.Source, + polarity: u1, + }; + + pub const In = packed struct(u8) { + bit_count: u5, + source: Token.Instruction.In.Source, + }; + + pub const Out = packed struct(u8) { + bit_count: u5, + destination: Token.Instruction.Out.Destination, + }; + + pub const Push = packed struct(u8) { + _reserved0: u5 = 0, + block: u1, + if_full: u1, + _reserved1: u1 = 0, + }; + + pub const Pull = packed struct(u8) { + _reserved0: u5 = 0, + block: u1, + if_empty: u1, + _reserved1: u1 = 1, + }; + + pub const Mov = packed struct(u8) { + source: Token.Instruction.Mov.Source, + operation: Token.Instruction.Mov.Operation, + destination: Token.Instruction.Mov.Destination, + }; + + pub const Irq = packed struct(u8) { + index: u5, + wait: u1, + clear: u1, + reserved: u1 = 0, + }; + + pub const Set = packed struct(u8) { + data: u5, + destination: Token.Instruction.Set.Destination, + }; +}; + +//============================================================================== +// Encoder Tests +//============================================================================== + +const expect = std.testing.expect; +const expectEqual = std.testing.expectEqual; +const expectEqualStrings = std.testing.expectEqualStrings; + +fn encode_bounded_output_impl(source: []const u8, diags: *?assembler.Diagnostics) !Encoder(.{}).Output { + const tokens = try tokenizer.tokenize(source, diags, .{}); + var encoder = Encoder(.{}).init(tokens.slice()); + return try encoder.encode_output(diags); +} + +fn encode_bounded_output(source: []const u8) !Encoder(.{}).Output { + var diags: ?assembler.Diagnostics = null; + return encode_bounded_output_impl(source, &diags) catch |err| if (diags) |d| blk: { + std.log.err("error at index {}: {s}", .{ d.index, d.message.slice() }); + break :blk err; + } else err; +} + +test "encode.define" { + const output = try encode_bounded_output(".define foo 5"); + + try expectEqual(@as(usize, 0), output.global_defines.len); + try expectEqual(@as(usize, 1), output.private_defines.len); + try expectEqual(@as(usize, 0), output.programs.len); + + try expectEqualStrings("foo", output.private_defines.get(0).name); + try expectEqual(@as(i128, 5), output.private_defines.get(0).value); +} + +test "encode.define.public" { + const output = try encode_bounded_output(".define PUBLIC foo 5"); + + try expectEqual(@as(usize, 1), output.global_defines.len); + try expectEqual(@as(usize, 0), output.private_defines.len); + try expectEqual(@as(usize, 0), output.programs.len); +} + +test "encode.program.empty" { + const output = try encode_bounded_output(".program arst"); + + try expectEqual(@as(usize, 0), output.global_defines.len); + try expectEqual(@as(usize, 0), output.private_defines.len); + try expectEqual(@as(usize, 1), output.programs.len); + + try expectEqualStrings("arst", output.programs.get(0).name); + try expectEqual(@as(usize, 0), output.programs.get(0).instructions.len); +} + +test "encode.program.define" { + const output = try encode_bounded_output( + \\.program arst + \\.define bruh 7 + ); + + try expectEqual(@as(usize, 0), output.global_defines.len); + try expectEqual(@as(usize, 0), output.private_defines.len); + try expectEqual(@as(usize, 1), output.programs.len); + + const program = output.programs.get(0); + try expectEqualStrings("arst", program.name); + try expectEqual(@as(usize, 0), program.instructions.len); + + const define = program.private_defines.get(0); + try expectEqualStrings("bruh", define.name); + try expectEqual(@as(i128, 7), define.value); +} + +test "encode.program.define.public" { + const output = try encode_bounded_output( + \\.program arst + \\.define public bruh 7 + ); + + try expectEqual(@as(usize, 0), output.global_defines.len); + try expectEqual(@as(usize, 0), output.private_defines.len); + try expectEqual(@as(usize, 1), output.programs.len); + + const program = output.programs.get(0); + try expectEqualStrings("arst", program.name); + try expectEqual(@as(usize, 0), program.instructions.len); + + const define = program.defines.get(0); + try expectEqualStrings("bruh", define.name); + try expectEqual(@as(i128, 7), define.value); +} + +test "encode.program.define.namespaced" { + const output = try encode_bounded_output( + \\.program arst + \\.define public bruh 7 + \\.program what + \\.define public hi 8 + ); + + try expectEqual(@as(usize, 0), output.global_defines.len); + try expectEqual(@as(usize, 0), output.private_defines.len); + try expectEqual(@as(usize, 2), output.programs.len); + + const program_arst = output.programs.get(0); + try expectEqualStrings("arst", program_arst.name); + try expectEqual(@as(usize, 0), program_arst.instructions.len); + + const define_bruh = program_arst.defines.get(0); + try expectEqualStrings("bruh", define_bruh.name); + try expectEqual(@as(i128, 7), define_bruh.value); + + const program_what = output.programs.get(1); + try expectEqualStrings("what", program_what.name); + try expectEqual(@as(usize, 0), program_what.instructions.len); + + const define_hi = program_what.defines.get(0); + try expectEqualStrings("hi", define_hi.name); + try expectEqual(@as(i128, 8), define_hi.value); +} + +test "encode.origin" { + const output = try encode_bounded_output( + \\.program arst + \\.origin 0 + ); + + try expectEqual(@as(usize, 0), output.global_defines.len); + try expectEqual(@as(usize, 0), output.private_defines.len); + try expectEqual(@as(usize, 1), output.programs.len); + + const program = output.programs.get(0); + try expectEqualStrings("arst", program.name); + try expectEqual(@as(usize, 0), program.instructions.len); + + try expectEqual(@as(?u5, 0), program.origin); +} + +test "encode.wrap_target" { + const output = try encode_bounded_output( + \\.program arst + \\nop + \\.wrap_target + \\nop + ); + + try expectEqual(@as(usize, 0), output.global_defines.len); + try expectEqual(@as(usize, 0), output.private_defines.len); + try expectEqual(@as(usize, 1), output.programs.len); + + const program = output.programs.get(0); + try expectEqualStrings("arst", program.name); + try expectEqual(@as(usize, 2), program.instructions.len); + + try expectEqual(@as(?u5, 1), program.wrap_target); +} + +test "encode.wrap" { + const output = try encode_bounded_output( + \\.program arst + \\nop + \\.wrap + \\nop + ); + + try expectEqual(@as(usize, 0), output.global_defines.len); + try expectEqual(@as(usize, 0), output.private_defines.len); + try expectEqual(@as(usize, 1), output.programs.len); + + const program = output.programs.get(0); + try expectEqualStrings("arst", program.name); + try expectEqual(@as(usize, 2), program.instructions.len); + + try expectEqual(@as(?u5, 0), program.wrap); +} + +test "encode.side_set" { + const output = try encode_bounded_output( + \\.program arst + \\.side_set 1 + ); + + try expectEqual(@as(usize, 0), output.global_defines.len); + try expectEqual(@as(usize, 0), output.private_defines.len); + try expectEqual(@as(usize, 1), output.programs.len); + + const program = output.programs.get(0); + try expectEqual(@as(?u5, 1), program.side_set.?.count); +} + +test "encode.side_set.opt" { + const output = try encode_bounded_output( + \\.program arst + \\.side_set 1 opt + ); + + try expectEqual(@as(usize, 0), output.global_defines.len); + try expectEqual(@as(usize, 0), output.private_defines.len); + try expectEqual(@as(usize, 1), output.programs.len); + + const program = output.programs.get(0); + try expectEqual(@as(?u5, 1), program.side_set.?.count); + try expect(program.side_set.?.optional); +} + +test "encode.side_set.pindirs" { + const output = try encode_bounded_output( + \\.program arst + \\.side_set 1 pindirs + ); + + try expectEqual(@as(usize, 0), output.global_defines.len); + try expectEqual(@as(usize, 0), output.private_defines.len); + try expectEqual(@as(usize, 1), output.programs.len); + + const program = output.programs.get(0); + try expectEqual(@as(?u5, 1), program.side_set.?.count); + try expect(program.side_set.?.pindirs); +} + +test "encode.label" { + const output = try encode_bounded_output( + \\.program arst + \\nop + \\my_label: + \\nop + ); + + try expectEqual(@as(usize, 0), output.global_defines.len); + try expectEqual(@as(usize, 0), output.private_defines.len); + try expectEqual(@as(usize, 1), output.programs.len); + + const program = output.programs.get(0); + try expectEqual(@as(usize, 1), program.labels.len); + + const label = program.labels.get(0); + try expectEqualStrings("my_label", label.name); + try expectEqual(@as(u32, 1), label.index); + try expectEqual(false, label.public); +} + +test "encode.label.public" { + const output = try encode_bounded_output( + \\.program arst + \\nop + \\nop + \\public my_label: + \\nop + ); + + try expectEqual(@as(usize, 0), output.global_defines.len); + try expectEqual(@as(usize, 0), output.private_defines.len); + try expectEqual(@as(usize, 1), output.programs.len); + + const program = output.programs.get(0); + try expectEqual(@as(usize, 1), program.labels.len); + + const label = program.labels.get(0); + try expectEqualStrings("my_label", label.name); + try expectEqual(@as(u32, 2), label.index); + try expectEqual(true, label.public); +} + +test "encode.side_set.bits" { + const output = try encode_bounded_output( + \\.program arst + \\.side_set 1 opt + \\nop side 1 + \\nop [1] + \\nop side 0 [1] + ); + + try expectEqual(@as(usize, 0), output.global_defines.len); + try expectEqual(@as(usize, 0), output.private_defines.len); + try expectEqual(@as(usize, 1), output.programs.len); + + const program = output.programs.get(0); + + const instr0 = program.instructions.get(0); + try expectEqual(@as(u5, 0x18), instr0.delay_side_set); + + const instr1 = program.instructions.get(1); + try expectEqual(@as(u5, 0x1), instr1.delay_side_set); + + const instr2 = program.instructions.get(2); + try expectEqual(@as(u5, 0x11), instr2.delay_side_set); +} + +test "encode.evaluate.global" { + const output = try encode_bounded_output( + \\.define NUM 5 + \\.define public FOO NUM + ); + + try expectEqual(@as(usize, 1), output.private_defines.len); + try expectEqual(@as(usize, 1), output.global_defines.len); + try expectEqualStrings("FOO", output.global_defines.get(0).name); + try expectEqual(@as(i128, 5), output.global_defines.get(0).value); +} + +test "encode.evaluate.addition" { + const output = try encode_bounded_output( + \\.define public FOO (1+5) + ); + + try expectEqual(@as(usize, 1), output.global_defines.len); + try expectEqualStrings("FOO", output.global_defines.get(0).name); + try expectEqual(@as(i128, 6), output.global_defines.get(0).value); +} + +test "encode.evaluate.subtraction" { + const output = try encode_bounded_output( + \\.define public FOO (5-1) + ); + + try expectEqual(@as(usize, 1), output.global_defines.len); + try expectEqualStrings("FOO", output.global_defines.get(0).name); + try expectEqual(@as(i128, 4), output.global_defines.get(0).value); +} + +test "encode.evaluate.multiplication" { + const output = try encode_bounded_output( + \\.define public FOO (5*2) + ); + + try expectEqual(@as(usize, 1), output.global_defines.len); + try expectEqualStrings("FOO", output.global_defines.get(0).name); + try expectEqual(@as(i128, 10), output.global_defines.get(0).value); +} + +test "encode.evaluate.division" { + const output = try encode_bounded_output( + \\.define public FOO (6/2) + ); + + try expectEqual(@as(usize, 1), output.global_defines.len); + try expectEqualStrings("FOO", output.global_defines.get(0).name); + try expectEqual(@as(i128, 3), output.global_defines.get(0).value); +} + +test "encode.evaluate.bit reversal" { + const output = try encode_bounded_output( + \\.define public FOO ::1 + ); + + try expectEqual(@as(usize, 1), output.global_defines.len); + try expectEqualStrings("FOO", output.global_defines.get(0).name); + try expectEqual(@as(i128, 0x80000000), output.global_defines.get(0).value); +} + +test "encode.jmp.label" { + const output = try encode_bounded_output( + \\.program arst + \\nop + \\my_label: + \\nop + \\nop + \\jmp my_label + ); + + try expectEqual(@as(usize, 0), output.global_defines.len); + try expectEqual(@as(usize, 0), output.private_defines.len); + try expectEqual(@as(usize, 1), output.programs.len); + + const program = output.programs.get(0); + try expectEqual(@as(usize, 1), program.labels.len); + + const label = program.labels.get(0); + try expectEqualStrings("my_label", label.name); + try expectEqual(@as(u32, 1), label.index); + try expectEqual(false, label.public); + + const instr = program.instructions.get(3); + try expectEqual(Instruction.Tag.jmp, instr.tag); + try expectEqual(@as(u5, 0), instr.delay_side_set); + try expectEqual(Token.Instruction.Jmp.Condition.always, instr.payload.jmp.condition); + try expectEqual(@as(u5, 1), instr.payload.jmp.address); +} + +//test "encode.error.duplicated program name" {} +//test "encode.error.duplicated define" {} +//test "encode.error.multiple side_set" {} +//test "encode.error.label with no instruction" {} +//test "encode.error.label with no instruction" {} + +// Test Plan +// ========= +// +// - .program name validation +// - .origin in program init and in program body +// - .side_set must be in the program init +// - .wrap_target must come before an instruction, defaults to start of a program +// - .wrap_target must only be used once in a program +// - .wrap must be placed after an instruction, defaults to end of a program +// - .wrap must only be used once in a program +// - +// diff --git a/src/hal/pio/assembler/tokenizer.zig b/src/hal/pio/assembler/tokenizer.zig new file mode 100644 index 0000000..cc360f5 --- /dev/null +++ b/src/hal/pio/assembler/tokenizer.zig @@ -0,0 +1,1947 @@ +const std = @import("std"); +const assert = std.debug.assert; + +const assembler = @import("../assembler.zig"); +const Diagnostics = assembler.Diagnostics; + +const Expression = @import("Expression.zig"); + +pub const Options = struct { + capacity: u32 = 256, +}; + +pub fn tokenize( + source: []const u8, + diags: *?assembler.Diagnostics, + comptime options: Options, +) !std.BoundedArray(Token, options.capacity) { + var tokens = std.BoundedArray(Token, options.capacity).init(0) catch unreachable; + var tokenizer = Tokenizer.init(source); + while (try tokenizer.next(diags)) |token| + try tokens.append(token); + + return tokens; +} + +pub const Value = union(enum) { + // integer, hex, binary + integer: u32, + // either a symbol or label + string: []const u8, + expression: []const u8, + + pub fn format( + value: Value, + comptime fmt: []const u8, + options: std.fmt.FormatOptions, + writer: anytype, + ) !void { + _ = fmt; + _ = options; + switch (value) { + .string => |str| try writer.print("\"{s}\"", .{str}), + .expression => |expr| try writer.print("{s}", .{expr}), + .integer => |int| try writer.print("{}", .{int}), + } + } + + pub fn from_string(str: []const u8) !Value { + return Value{ + .integer = std.fmt.parseInt(u32, str, 0) catch { + return Value{ + .string = str, + }; + }, + }; + } +}; + +// the characters we're interested in are: +// ';' -> line comment +// '/' -> '/' -> line comment +// '/' -> '*' -> block comment +// '%' -> -> -> -> '{' -> code block +// '.' -> directive +pub const Tokenizer = struct { + source: []const u8, + index: u32, + + pub fn format( + self: Tokenizer, + comptime fmt: []const u8, + options: std.fmt.FormatOptions, + writer: anytype, + ) !void { + _ = fmt; + _ = options; + + try writer.print( + \\parser: + \\ index: {} + \\ + \\ + , .{self.index}); + + var printed_cursor = false; + var line_it = std.mem.tokenize(u8, self.source, "\n\r"); + while (line_it.next()) |line| { + try writer.print("{s}\n", .{line}); + if (!printed_cursor and line_it.index > self.index) { + try writer.writeByteNTimes(' ', line.len - (line_it.index - self.index)); + try writer.writeAll("\x1b[30;42;1m^\x1b[0m\n"); + printed_cursor = true; + } + } + } + + fn init(source: []const u8) Tokenizer { + return Tokenizer{ + .source = source, + .index = 0, + }; + } + + fn consume(self: *Tokenizer, count: u32) void { + assert(self.index < self.source.len); + self.index += count; + } + + fn peek(self: Tokenizer) ?u8 { + return if (self.index < self.source.len) + self.source[self.index] + else + null; + } + + fn get(self: *Tokenizer) ?u8 { + return if (self.index < self.source.len) blk: { + defer self.index += 1; + break :blk self.source[self.index]; + } else null; + } + + fn skip_line(self: *Tokenizer) void { + while (self.get()) |c| + if (c == '\n') + return; + } + + fn skip_until_end_of_comment_block(self: *Tokenizer) void { + while (self.get()) |c| { + if (c == '*') { + if (self.peek()) |p| { + self.consume(1); + if (p == '/') { + return; + } + } + } + } + } + + fn skip_until_end_of_code_block(self: *Tokenizer) void { + // TODO: assert we have the code identifier and open curly bracket + while (self.get()) |c| { + if (c == '%') { + if (self.peek()) |p| { + self.consume(1); + if (p == '}') { + return; + } + } + } + } + } + + fn read_until_whitespace_or_end(self: *Tokenizer) ![]const u8 { + const start = self.index; + var end: ?u32 = null; + while (self.peek()) |p| { + switch (p) { + ' ', '\n', '\r', '\t', ',' => { + end = self.index; + break; + }, + else => self.consume(1), + } + } else end = self.index; + + return self.source[start .. end orelse return error.EndOfStream]; + } + + fn skip_whitespace(self: *Tokenizer) void { + while (self.peek()) |p| { + switch (p) { + ' ', '\t', '\r', '\n', ',' => self.consume(1), + else => return, + } + } + } + + /// returns array of args + fn get_args(self: *Tokenizer, comptime num: u32, diags: *?Diagnostics) TokenizeError![num]?[]const u8 { + var args: [num]?[]const u8 = undefined; + for (&args) |*arg| + arg.* = try self.get_arg(diags); + + return args; + } + + const PeekResult = struct { + str: []const u8, + start: u32, + }; + + fn peek_arg(self: *Tokenizer, diags: *?Diagnostics) TokenizeError!?PeekResult { + var tmp_index = self.index; + return self.peek_arg_impl(&tmp_index, diags); + } + + fn consume_peek(self: *Tokenizer, result: PeekResult) void { + assert(self.index <= result.start); + self.index = result.start + @intCast(u32, result.str.len); + } + + /// gets next arg without consuming the stream + fn peek_arg_impl( + self: *Tokenizer, + index: *u32, + diags: *?Diagnostics, + ) TokenizeError!?PeekResult { + + // skip whitespace + while (index.* < self.source.len) { + switch (self.source[index.*]) { + ' ', '\t', ',' => index.* += 1, + else => break, + } + } + + if (index.* == self.source.len) + return null; + + const start = index.*; + const end = end: { + break :end switch (self.source[start]) { + '(' => blk: { + var depth: u32 = 0; + break :blk while (index.* < self.source.len) : (index.* += 1) { + switch (self.source[index.*]) { + '(' => depth += 1, + ')' => { + depth -= 1; + + if (depth == 0) { + index.* += 1; + break index.*; + } + }, + else => {}, + } + } else { + diags.* = Diagnostics.init(start, "mismatched parenthesis", .{}); + return error.InvalidExpression; + }; + }, + '[' => while (index.* < self.source.len) : (index.* += 1) { + if (self.source[index.*] == ']') { + index.* += 1; + break index.*; + } + } else { + diags.* = Diagnostics.init(start, "mismatched parenthesis", .{}); + return error.InvalidExpression; + }, + else => while (index.* < self.source.len) { + switch (self.source[index.*]) { + // ; and / are to stop at comments + ' ', '\t', '\r', '\n', ',', ';', '/' => break index.*, + else => index.* += 1, + } + } else index.*, + }; + }; + + return if (start != end) + PeekResult{ + .str = self.source[start..end], + .start = start, + } + else + null; + } + + fn get_arg(self: *Tokenizer, diags: *?Diagnostics) TokenizeError!?[]const u8 { + return if (try self.peek_arg_impl(&self.index, diags)) |result| + result.str + else + null; + } + + const Identifier = struct { + index: u32, + str: []const u8, + }; + + fn get_identifier(self: *Tokenizer) TokenizeError!Identifier { + self.skip_whitespace(); + return Identifier{ + .index = self.index, + .str = try self.read_until_whitespace_or_end(), + }; + } + + const TokenizeError = error{ + EndOfStream, + NoValue, + NotAnExpression, + Overflow, + InvalidCharacter, + InvalidSource, + InvalidCondition, + MissingArg, + InvalidDestination, + InvalidOperation, + InvalidExpression, + TooBig, + }; + + fn get_program(self: *Tokenizer, index: u32, diags: *?Diagnostics) TokenizeError!Token { + const name = (try self.get_arg(diags)) orelse { + diags.* = Diagnostics.init(index, "missing program name", .{}); + return error.MissingArg; + }; + return Token{ + .index = index, + .data = .{ .program = name }, + }; + } + + fn assert_is_lower(str: []const u8) void { + for (str) |c| + assert(std.ascii.isLower(c)); + } + + fn eql_lower(comptime lhs: []const u8, rhs: []const u8) bool { + assert_is_lower(lhs); + if (lhs.len != rhs.len) + return false; + + var buf: [lhs.len]u8 = undefined; + for (&buf, rhs) |*b, r| + b.* = std.ascii.toLower(r); + + return std.mem.eql(u8, &buf, lhs); + } + + fn get_define(self: *Tokenizer, index: u32, diags: *?Diagnostics) TokenizeError!Token { + const maybe_public = try self.get_identifier(); + var is_public = eql_lower("public", maybe_public.str); + + const name = if (is_public) + try self.get_identifier() + else + maybe_public; + + return Token{ + .index = index, + .data = .{ + .define = .{ + .name = name.str, + .value = Value{ + .expression = (try self.get_arg(diags)) orelse { + diags.* = Diagnostics.init(index, "failed to get expression", .{}); + return error.InvalidExpression; + }, + }, + .public = is_public, + .index = name.index, + }, + }, + }; + } + + fn get_expression(self: *Tokenizer) TokenizeError!Value { + const start = self.index; + var count: u32 = 1; + + if (self.get()) |c| + if (c != '(') + return error.NotAnExpression; + + while (self.get()) |c| { + switch (c) { + '(' => count += 1, + ')' => { + count -= 1; + }, + else => {}, + } + + if (count == 0) { + return Value{ + .expression = self.source[start..self.index], + }; + } + } else { + return error.NotAnExpression; + } + } + + fn get_value(self: *Tokenizer) TokenizeError!Value { + self.skip_whitespace(); + + if (self.peek()) |p| + if (p == '(') + return try self.get_expression() + else { + const identifier = try self.get_identifier(); + return try Value.from_string(identifier.str); + } + else + return error.NoValue; + } + + fn get_origin(self: *Tokenizer, index: u32, diags: *?Diagnostics) TokenizeError!Token { + _ = diags; + return Token{ + .index = index, + .data = .{ + .origin = try self.get_value(), + }, + }; + } + + fn get_side_set(self: *Tokenizer, index: u32, diags: *?Diagnostics) TokenizeError!Token { + const args = try self.get_args(3, diags); + const count = try Value.from_string(args[0] orelse { + diags.* = Diagnostics.init(index, "missing count", .{}); + return error.MissingArg; + }); + var opt = false; + var pindirs = false; + + if (args[1]) |arg| { + if (std.mem.eql(u8, "opt", arg)) + opt = true + else if (std.mem.eql(u8, "pindirs", arg)) + pindirs = true; + } + + if (args[2]) |arg| { + if (std.mem.eql(u8, "pindirs", arg)) + pindirs = true; + } + + return Token{ + .index = index, + .data = .{ + .side_set = .{ + .count = count, + .opt = opt, + .pindirs = pindirs, + }, + }, + }; + } + + fn get_wrap_target(_: *Tokenizer, index: u32, _: *?Diagnostics) TokenizeError!Token { + return Token{ + .index = index, + .data = .{ .wrap_target = {} }, + }; + } + + fn get_wrap(_: *Tokenizer, index: u32, _: *?Diagnostics) TokenizeError!Token { + return Token{ + .index = index, + .data = .{ .wrap = {} }, + }; + } + + fn get_lang_opt(self: *Tokenizer, index: u32, diags: *?Diagnostics) TokenizeError!Token { + _ = diags; + return Token{ + .index = index, + .data = .{ + .lang_opt = .{ + .lang = (try self.get_identifier()).str, + .name = (try self.get_identifier()).str, + .option = (try self.get_identifier()).str, + }, + }, + }; + } + + fn get_word(self: *Tokenizer, index: u32, diags: *?Diagnostics) TokenizeError!Token { + _ = diags; + return Token{ + .index = index, + .data = .{ .word = try self.get_value() }, + }; + } + + const directives = std.ComptimeStringMap(*const fn (*Tokenizer, u32, *?Diagnostics) TokenizeError!Token, .{ + .{ "program", get_program }, + .{ "define", get_define }, + .{ "origin", get_origin }, + .{ "side_set", get_side_set }, + .{ "wrap_target", get_wrap_target }, + .{ "wrap", get_wrap }, + .{ "lang_opt", get_lang_opt }, + .{ "word", get_word }, + }); + + fn get_directive(self: *Tokenizer, diags: *?Diagnostics) !Token { + const index = self.index; + const identifier = try self.read_until_whitespace_or_end(); + return if (directives.get(identifier)) |handler| ret: { + const ret = try handler(self, index, diags); + self.skip_line(); + break :ret ret; + } else error.InvalidDirective; + } + + fn get_nop(_: *Tokenizer, _: *?Diagnostics) TokenizeError!Token.Instruction.Payload { + return Token.Instruction.Payload{ + .nop = {}, + }; + } + + fn target_from_string(str: []const u8) TokenizeError!Token.Instruction.Jmp.Target { + const value = Value.from_string(str); + return Token.Instruction.Payload{ + .jmp = .{ + .condition = .always, + .target = switch (value) { + .string => |label| Token.Instruction.Jmp.Target{ + .label = label, + }, + else => Token.Instruction.Jmp.Target{ + .value = value, + }, + }, + }, + }; + } + + fn get_jmp(self: *Tokenizer, diags: *?Diagnostics) TokenizeError!Token.Instruction.Payload { + const Condition = Token.Instruction.Jmp.Condition; + const conditions = std.ComptimeStringMap(Condition, .{ + .{ "!x", .x_is_zero }, + .{ "x--", .x_dec }, + .{ "!y", .y_is_zero }, + .{ "y--", .y_dec }, + .{ "x!=y", .x_is_not_y }, + .{ "pin", .pin }, + .{ "!osre", .osre_not_empty }, + }); + + const maybe_cond = (try self.get_arg(diags)) orelse return error.MissingArg; + const maybe_cond_lower = try lowercase_bounded(256, maybe_cond); + const cond: Condition = conditions.get(maybe_cond_lower.slice()) orelse .always; + const target_str = if (cond == .always) + maybe_cond + else + (try self.get_arg(diags)) orelse return error.MissingArg; + + return Token.Instruction.Payload{ + .jmp = .{ .condition = cond, .target = target_str }, + }; + } + + fn get_wait(self: *Tokenizer, diags: *?Diagnostics) TokenizeError!Token.Instruction.Payload { + const polarity = try std.fmt.parseInt(u1, (try self.get_arg(diags)) orelse return error.MissingArg, 0); + const source_str = (try self.get_arg(diags)) orelse return error.MissingArg; + const pin = try Value.from_string((try self.get_arg(diags)) orelse return error.MissingArg); + + var buf: [8]u8 = undefined; + for (source_str, 0..) |c, i| + buf[i] = std.ascii.toLower(c); + + const source_lower = buf[0..source_str.len]; + const source: Token.Instruction.Wait.Source = + if (std.mem.eql(u8, "gpio", source_lower)) + .gpio + else if (std.mem.eql(u8, "pin", source_lower)) + .pin + else if (std.mem.eql(u8, "irq", source_lower)) + .irq + else + return error.InvalidSource; + + const rel: bool = if (source == .irq) + if (try self.peek_arg(diags)) |rel_result| blk: { + const is_rel = std.mem.eql(u8, "rel", rel_result.str); + if (is_rel) + self.consume_peek(rel_result); + + break :blk is_rel; + } else false + else + false; + + return Token.Instruction.Payload{ + .wait = .{ + .polarity = polarity, + .source = source, + .num = pin, + .rel = rel, + }, + }; + } + + /// get the lowercase of a string, returns an error if it's too big + fn lowercase_bounded(comptime max_size: usize, str: []const u8) TokenizeError!std.BoundedArray(u8, max_size) { + if (str.len > max_size) + return error.TooBig; + + var ret = std.BoundedArray(u8, max_size).init(0) catch unreachable; + for (str) |c| + try ret.append(std.ascii.toLower(c)); + + return ret; + } + + // TODO: I need to take a break. There is no rush to finish this. The thing + // I need to keep in mind with `get_args()` is that I must only consume the + // args that are used. side set and delay may be on the same line + + fn get_in(self: *Tokenizer, diags: *?Diagnostics) TokenizeError!Token.Instruction.Payload { + const source_str = (try self.get_arg(diags)) orelse return error.MissingArg; + const bit_count_str = (try self.get_arg(diags)) orelse return error.MissingArg; + + const source_lower = try lowercase_bounded(256, source_str); + const bit_count_tmp = try std.fmt.parseInt(u6, bit_count_str, 0); + const bit_count = if (bit_count_tmp == 32) + @as(u5, 0) + else + @intCast(u5, bit_count_tmp); + + return Token.Instruction.Payload{ + .in = .{ + .source = std.meta.stringToEnum(Token.Instruction.In.Source, source_lower.slice()) orelse return error.InvalidSource, + .bit_count = bit_count, + }, + }; + } + + fn get_out(self: *Tokenizer, diags: *?Diagnostics) TokenizeError!Token.Instruction.Payload { + const dest_src = (try self.get_arg(diags)) orelse return error.MissingArg; + const bit_count_str = (try self.get_arg(diags)) orelse return error.MissingArg; + + const dest_lower = try lowercase_bounded(256, dest_src); + const bit_count_tmp = try std.fmt.parseInt(u6, bit_count_str, 0); + const bit_count = if (bit_count_tmp == 32) + @as(u5, 0) + else + @intCast(u5, bit_count_tmp); + + return Token.Instruction.Payload{ + .out = .{ + .destination = std.meta.stringToEnum(Token.Instruction.Out.Destination, dest_lower.slice()) orelse return error.InvalidDestination, + .bit_count = bit_count, + }, + }; + } + + fn block_from_peek(self: *Tokenizer, result: PeekResult) TokenizeError!bool { + const block_lower = try lowercase_bounded(256, result.str); + const is_block = std.mem.eql(u8, "block", block_lower.slice()); + const is_noblock = std.mem.eql(u8, "noblock", block_lower.slice()); + + if (is_block or is_noblock) + self.consume_peek(result); + + return if (is_block) + true + else if (is_noblock) + false + else + true; + } + + fn get_push(self: *Tokenizer, diags: *?Diagnostics) TokenizeError!Token.Instruction.Payload { + return if (try self.peek_arg(diags)) |first_result| ret: { + const lower = try lowercase_bounded(256, first_result.str); + const iffull = std.mem.eql(u8, "iffull", lower.slice()); + + const block: bool = if (iffull) blk: { + self.consume_peek(first_result); + break :blk if (try self.peek_arg(diags)) |block_result| + try self.block_from_peek(block_result) + else + true; + } else try self.block_from_peek(first_result); + + break :ret Token.Instruction.Payload{ + .push = .{ + .iffull = iffull, + .block = block, + }, + }; + } else Token.Instruction.Payload{ + .push = .{ + .iffull = false, + .block = true, + }, + }; + } + + fn get_pull(self: *Tokenizer, diags: *?Diagnostics) TokenizeError!Token.Instruction.Payload { + return if (try self.peek_arg(diags)) |first_result| ret: { + const lower = try lowercase_bounded(256, first_result.str); + const ifempty = std.mem.eql(u8, "ifempty", lower.slice()); + + const block: bool = if (ifempty) blk: { + self.consume_peek(first_result); + break :blk if (try self.peek_arg(diags)) |block_result| + try self.block_from_peek(block_result) + else + true; + } else try self.block_from_peek(first_result); + + break :ret Token.Instruction.Payload{ + .pull = .{ + .ifempty = ifempty, + .block = block, + }, + }; + } else Token.Instruction.Payload{ + .pull = .{ + .ifempty = false, + .block = true, + }, + }; + } + + fn get_mov(self: *Tokenizer, diags: *?Diagnostics) TokenizeError!Token.Instruction.Payload { + const dest_str = (try self.get_arg(diags)) orelse return error.MissingArg; + const dest_lower = try lowercase_bounded(256, dest_str); + const destination = std.meta.stringToEnum(Token.Instruction.Mov.Destination, dest_lower.slice()) orelse return error.InvalidDestination; + + const second = try self.get_arg(diags) orelse return error.MissingArg; + const op_prefixed: ?[]const u8 = if (std.mem.startsWith(u8, second, "!")) + "!" + else if (std.mem.startsWith(u8, second, "~")) + "~" + else if (std.mem.startsWith(u8, second, "::")) + "::" + else + null; + + const source_str = if (op_prefixed) |op_str| + if (second.len == op_str.len) + (try self.get_arg(diags)) orelse return error.MissingArg + else + second[op_str.len..] + else + second; + + const source_lower = try lowercase_bounded(256, source_str); + const source = std.meta.stringToEnum(Token.Instruction.Mov.Source, source_lower.slice()) orelse return error.InvalidSource; + const operation: Token.Instruction.Mov.Operation = if (op_prefixed) |op_str| + if (std.mem.eql(u8, "!", op_str)) + .invert + else if (std.mem.eql(u8, "~", op_str)) + .invert + else if (std.mem.eql(u8, "::", op_str)) + .bit_reverse + else + return error.InvalidOperation + else + .none; + + return Token.Instruction.Payload{ + .mov = .{ + .destination = destination, + .source = source, + .operation = operation, + }, + }; + } + + fn get_irq(self: *Tokenizer, diags: *?Diagnostics) TokenizeError!Token.Instruction.Payload { + const first = (try self.get_arg(diags)) orelse return error.MissingArg; + + var clear = false; + var wait = false; + var has_mode = false; + const first_lower = try lowercase_bounded(256, first); + if (std.mem.eql(u8, "set", first_lower.slice())) { + has_mode = true; + // do nothing + } else if (std.mem.eql(u8, "nowait", first_lower.slice())) { + has_mode = true; + // do nothing + } else if (std.mem.eql(u8, "wait", first_lower.slice())) { + has_mode = true; + wait = true; + } else if (std.mem.eql(u8, "clear", first_lower.slice())) { + has_mode = true; + clear = true; + } + + const num = Value{ + .expression = if (has_mode) + (try self.get_arg(diags)) orelse { + diags.* = Diagnostics.init(self.index, "irq (mode) (rel): failed to get num argument", .{}); + return error.MissingArg; + } + else + first, + }; + + const rel: bool = if (try self.peek_arg(diags)) |result| blk: { + const rel_lower = try lowercase_bounded(256, result.str); + const is_rel = std.mem.eql(u8, "rel", rel_lower.slice()); + if (is_rel) + self.consume_peek(result); + + break :blk is_rel; + } else false; + + return Token.Instruction.Payload{ + .irq = .{ + .clear = clear, + .wait = wait, + .num = num, + .rel = rel, + }, + }; + } + + fn get_set(self: *Tokenizer, diags: *?Diagnostics) TokenizeError!Token.Instruction.Payload { + const dest_str = (try self.get_arg(diags)) orelse { + diags.* = Diagnostics.init(0, "missing destination", .{}); + return error.MissingArg; + }; + const value = try self.get_value(); + + const dest_lower = try lowercase_bounded(256, dest_str); + + return Token.Instruction.Payload{ + .set = .{ + .destination = std.meta.stringToEnum(Token.Instruction.Set.Destination, dest_lower.slice()) orelse return error.InvalidDestination, + .value = value, + }, + }; + } + + const instructions = std.ComptimeStringMap(*const fn (*Tokenizer, *?Diagnostics) TokenizeError!Token.Instruction.Payload, .{ + .{ "nop", get_nop }, + .{ "jmp", get_jmp }, + .{ "wait", get_wait }, + .{ "in", get_in }, + .{ "out", get_out }, + .{ "push", get_push }, + .{ "pull", get_pull }, + .{ "mov", get_mov }, + .{ "irq", get_irq }, + .{ "set", get_set }, + }); + + fn get_instruction(self: *Tokenizer, name: Identifier, diags: *?Diagnostics) !Token { + const name_lower = try lowercase_bounded(256, name.str); + const payload = if (instructions.get(name_lower.slice())) |handler| + try handler(self, diags) + else { + diags.* = Diagnostics.init(name.index, "invalid instruction", .{}); + return error.InvalidInstruction; + }; + + var side_set: ?Value = null; + var delay: ?Value = null; + + if (try self.peek_arg(diags)) |result| { + if (eql_lower("side", result.str)) { + self.consume_peek(result); + + const side_set_str = (try self.get_arg(diags)) orelse return error.MissingArg; + side_set = Value{ .expression = side_set_str }; + } else if (std.mem.startsWith(u8, result.str, "[") and std.mem.endsWith(u8, result.str, "]")) { + self.consume_peek(result); + delay = Value{ .expression = result.str[1 .. result.str.len - 1] }; + } + } + + if (try self.peek_arg(diags)) |result| { + if (eql_lower("side", result.str)) { + self.consume_peek(result); + + const side_set_str = (try self.get_arg(diags)) orelse return error.MissingArg; + assert(side_set == null); + side_set = Value{ .expression = side_set_str }; + } else if (std.mem.startsWith(u8, result.str, "[") and std.mem.endsWith(u8, result.str, "]")) { + self.consume_peek(result); + assert(delay == null); + delay = Value{ + .expression = result.str[1 .. result.str.len - 1], + }; + } + } + + self.skip_line(); + return Token{ + .index = name.index, + .data = .{ + .instruction = .{ + .payload = payload, + .side_set = side_set, + .delay = delay, + }, + }, + }; + } + + fn next(self: *Tokenizer, diags: *?assembler.Diagnostics) !?Token { + while (self.peek()) |p| { + switch (p) { + ' ', '\t', '\n', '\r', ',' => self.consume(1), + ';' => self.skip_line(), + '/' => { + self.consume(1); + if (self.peek()) |p2| { + self.consume(1); + switch (p2) { + '/' => self.skip_line(), + '*' => self.skip_until_end_of_comment_block(), + else => unreachable, + } + } else return null; + }, + '%' => { + self.consume(1); + self.skip_until_end_of_code_block(); + }, + '.' => { + self.consume(1); + return try self.get_directive(diags); + }, + 'a'...'z', 'A'...'Z', '0'...'9', '_' => { + const first = try self.get_identifier(); + + // definitely a label + return if (eql_lower("public", first.str)) + Token{ + .index = first.index, + .data = .{ + .label = .{ + .public = true, + .name = blk: { + const tmp = (try self.get_identifier()).str; + break :blk tmp[0 .. tmp.len - 1]; + }, + }, + }, + } + else if (std.mem.endsWith(u8, first.str, ":")) + Token{ + .index = first.index, + .data = .{ + .label = .{ + .name = first.str[0 .. first.str.len - 1], + }, + }, + } + else + try self.get_instruction(first, diags); + }, + else => return error.Unhandled, + } + } + + return null; + } +}; + +pub const Token = struct { + index: u32, + data: union(enum) { + program: []const u8, + define: Token.Define, + origin: Value, + side_set: SideSet, + wrap_target: void, + wrap: void, + lang_opt: LangOpt, + word: Value, + label: Label, + instruction: Instruction, + }, + + pub const Tag = std.meta.Tag(std.meta.FieldType(Token, .data)); + + pub const Label = struct { + name: []const u8, + public: bool = false, + }; + + // TODO: use Value instead of numbers + pub const Instruction = struct { + payload: Payload, + side_set: ?Value = null, + // TODO: delay can look like [T1-1], so we could consider the square + // brackets to be an expression + delay: ?Value = null, + + pub const Payload = union(enum) { + nop: void, + jmp: Jmp, + wait: Wait, + in: In, + out: Out, + push: Push, + pull: Pull, + mov: Mov, + irq: Irq, + set: Set, + }; + + pub const Jmp = struct { + condition: Condition, + target: []const u8, + + pub const Condition = enum(u3) { + always = 0b000, + x_is_zero = 0b001, // !X + x_dec = 0b010, // X-- + y_is_zero = 0b011, // !Y + y_dec = 0b100, // Y-- + x_is_not_y = 0b101, //X!=Y + pin = 0b110, // PIN + osre_not_empty = 0b111, // !OSRE + }; + }; + + pub const Wait = struct { + polarity: u1, + source: Source, + num: Value, + rel: bool, + + pub const Source = enum(u2) { + gpio = 0b00, + pin = 0b01, + irq = 0b10, + }; + }; + + pub const In = struct { + source: Source, + bit_count: u5, + + pub const Source = enum(u3) { + pins = 0b00, + x = 0b001, + y = 0b010, + null = 0b011, + isr = 0b110, + osr = 0b111, + }; + }; + + pub const Out = struct { + destination: Destination, + bit_count: u5, + + pub const Destination = enum(u3) { + pins = 0b000, + x = 0b001, + y = 0b010, + null = 0b011, + pindirs = 0b100, + pc = 0b101, + isr = 0b110, + exec = 0b111, + }; + }; + + pub const Push = struct { + block: bool, + iffull: bool, + }; + + pub const Pull = struct { + block: bool, + ifempty: bool, + }; + + pub const Mov = struct { + destination: Destination, + operation: Operation, + source: Source, + + pub const Destination = enum(u3) { + pins = 0b000, + x = 0b001, + y = 0b010, + exec = 0b100, + pc = 0b101, + isr = 0b110, + osr = 0b111, + }; + + pub const Operation = enum(u2) { + none = 0b00, + invert = 0b01, + bit_reverse = 0b10, + }; + + pub const Source = enum(u3) { + pins = 0b00, + x = 0b001, + y = 0b010, + null = 0b011, + status = 0b101, + isr = 0b110, + osr = 0b111, + }; + }; + + pub const Irq = struct { + clear: bool, + wait: bool, + num: Value, + rel: bool, + }; + + pub const Set = struct { + destination: Destination, + value: Value, + + pub const Destination = enum(u3) { + pins = 0b000, + x = 0b001, + y = 0b010, + pindirs = 0b100, + }; + }; + }; + + pub const Define = struct { + name: []const u8, + value: Value, + public: bool = false, + index: u32, + }; + + pub const SideSet = struct { + count: Value, + opt: bool = false, + pindirs: bool = false, + }; + + pub const LangOpt = struct { + lang: []const u8, + name: []const u8, + option: []const u8, + }; +}; + +//============================================================================== +// Tokenization Tests +//============================================================================== + +const expect = std.testing.expect; +const expectEqual = std.testing.expectEqual; +const expectEqualStrings = std.testing.expectEqualStrings; + +const DirectiveTag = @typeInfo(Token.Directive).Union.tag_type.?; +const PayloadTag = @typeInfo(Token.Instruction.Payload).Union.tag_type.?; + +fn expect_program(expected: []const u8, actual: Token) !void { + try expectEqual(Token.Tag.program, actual.data); + try expectEqualStrings(expected, actual.data.program); +} + +fn expect_value(expected: Value, actual: Value) !void { + switch (expected) { + .integer => |int| try expectEqual(int, actual.integer), + .string => |str| try expectEqualStrings(str, actual.string), + .expression => |expr| try expectEqualStrings(expr, actual.expression), + } +} + +fn expect_opt_value(expected: ?Value, actual: ?Value) !void { + if (expected != null) + switch (expected.?) { + .integer => |int| try expectEqual(int, actual.?.integer), + .string => |str| try expectEqualStrings(str, actual.?.string), + .expression => |expr| try expectEqualStrings(expr, actual.?.expression), + }; +} + +fn expect_define(expected: Token.Define, actual: Token) !void { + try expectEqual(Token.Tag.define, actual.data); + + const define = actual.data.define; + try expectEqualStrings(expected.name, define.name); + try expect_value(expected.value, define.value); +} + +fn expect_origin(expected: Value, actual: Token) !void { + try expectEqual(Token.Tag.origin, actual.data); + try expect_value(expected, actual.data.origin); +} + +fn expect_side_set(expected: Token.SideSet, actual: Token) !void { + try expectEqual(Token.Tag.side_set, actual.data); + + const side_set = actual.data.side_set; + try expect_value(expected.count, side_set.count); + try expectEqual(expected.opt, side_set.opt); + try expectEqual(expected.pindirs, side_set.pindirs); +} + +fn expect_wrap_target(actual: Token) !void { + try expectEqual(Token.Tag.wrap_target, actual.data); +} + +fn expect_wrap(actual: Token) !void { + try expectEqual(Token.Tag.wrap, actual.data); +} + +fn expect_lang_opt(expected: Token.LangOpt, actual: Token) !void { + try expectEqual(Token.Tag.lang_opt, actual.data); + + const lang_opt = actual.data.lang_opt; + try expectEqualStrings(expected.lang, lang_opt.lang); + try expectEqualStrings(expected.name, lang_opt.name); + try expectEqualStrings(expected.option, lang_opt.option); +} + +fn expect_word(expected: Value, actual: Token) !void { + try expectEqual(Token.Tag.word, actual.data); + try expect_value(expected, actual.data.word); +} + +fn expect_label(expected: Token.Label, actual: Token) !void { + try expectEqual(Token.Tag.label, actual.data); + + const label = actual.data.label; + try expectEqual(expected.public, label.public); + try expectEqualStrings(expected.name, label.name); +} + +const ExpectedNopInstr = struct { + delay: ?Value = null, + side_set: ?Value = null, +}; + +fn expect_instr_nop(expected: ExpectedNopInstr, actual: Token) !void { + try expectEqual(Token.Tag.instruction, actual.data); + try expectEqual(PayloadTag.nop, actual.data.instruction.payload); + + const instr = actual.data.instruction; + try expect_opt_value(expected.delay, instr.delay); + try expect_opt_value(expected.side_set, instr.side_set); +} + +const ExpectedSetInstr = struct { + dest: Token.Instruction.Set.Destination, + value: Value, + delay: ?Value = null, + side_set: ?Value = null, +}; + +fn expect_instr_set(expected: ExpectedSetInstr, actual: Token) !void { + try expectEqual(Token.Tag.instruction, actual.data); + try expectEqual(PayloadTag.set, actual.data.instruction.payload); + + const instr = actual.data.instruction; + try expect_opt_value(expected.delay, instr.delay); + try expect_opt_value(expected.side_set, instr.side_set); + + const set = instr.payload.set; + try expectEqual(expected.dest, set.destination); + try expect_value(expected.value, set.value); +} + +const ExpectedJmpInstr = struct { + cond: Token.Instruction.Jmp.Condition = .always, + target: []const u8, + delay: ?Value = null, + side_set: ?Value = null, +}; + +fn expect_instr_jmp(expected: ExpectedJmpInstr, actual: Token) !void { + try expectEqual(Token.Tag.instruction, actual.data); + try expectEqual(PayloadTag.jmp, actual.data.instruction.payload); + + const instr = actual.data.instruction; + try expect_opt_value(expected.delay, instr.delay); + try expect_opt_value(expected.side_set, instr.side_set); + + const jmp = instr.payload.jmp; + try expectEqual(expected.cond, jmp.condition); + try expectEqualStrings(expected.target, jmp.target); +} + +const ExpectedWaitInstr = struct { + polarity: u1, + source: Token.Instruction.Wait.Source, + num: Value, + // only valid for irq source + rel: bool = false, + delay: ?Value = null, + side_set: ?Value = null, +}; + +fn expect_instr_wait(expected: ExpectedWaitInstr, actual: Token) !void { + try expectEqual(Token.Tag.instruction, actual.data); + try expectEqual(PayloadTag.wait, actual.data.instruction.payload); + + const instr = actual.data.instruction; + try expect_opt_value(expected.delay, instr.delay); + try expect_opt_value(expected.side_set, instr.side_set); + + const wait = instr.payload.wait; + try expectEqual(expected.polarity, wait.polarity); + try expectEqual(expected.source, wait.source); + try expect_value(expected.num, wait.num); +} + +const ExpectedInInstr = struct { + source: Token.Instruction.In.Source, + bit_count: u5, + delay: ?Value = null, + side_set: ?Value = null, +}; + +fn expect_instr_in(expected: ExpectedInInstr, actual: Token) !void { + try expectEqual(Token.Tag.instruction, actual.data); + try expectEqual(PayloadTag.in, actual.data.instruction.payload); + + const instr = actual.data.instruction; + try expect_opt_value(expected.delay, instr.delay); + try expect_opt_value(expected.side_set, instr.side_set); + + const in = instr.payload.in; + try expectEqual(expected.source, in.source); + try expectEqual(expected.bit_count, in.bit_count); +} + +const ExpectedOutInstr = struct { + destination: Token.Instruction.Out.Destination, + bit_count: u5, + delay: ?Value = null, + side_set: ?Value = null, +}; + +fn expect_instr_out(expected: ExpectedOutInstr, actual: Token) !void { + try expectEqual(Token.Tag.instruction, actual.data); + try expectEqual(PayloadTag.out, actual.data.instruction.payload); + + const instr = actual.data.instruction; + try expect_opt_value(expected.delay, instr.delay); + try expect_opt_value(expected.side_set, instr.side_set); + + const out = instr.payload.out; + try expectEqual(expected.destination, out.destination); + try expectEqual(expected.bit_count, out.bit_count); +} + +const ExpectedPushInstr = struct { + block: bool = true, + iffull: bool = false, + delay: ?Value = null, + side_set: ?Value = null, +}; + +fn expect_instr_push(expected: ExpectedPushInstr, actual: Token) !void { + try expectEqual(Token.Tag.instruction, actual.data); + try expectEqual(PayloadTag.push, actual.data.instruction.payload); + + const instr = actual.data.instruction; + try expect_opt_value(expected.delay, instr.delay); + try expect_opt_value(expected.side_set, instr.side_set); + + const push = instr.payload.push; + try expectEqual(expected.block, push.block); + try expectEqual(expected.iffull, push.iffull); +} + +const ExpectedPullInstr = struct { + block: bool = true, + ifempty: bool = false, + delay: ?Value = null, + side_set: ?Value = null, +}; + +fn expect_instr_pull(expected: ExpectedPullInstr, actual: Token) !void { + try expectEqual(Token.Tag.instruction, actual.data); + try expectEqual(PayloadTag.pull, actual.data.instruction.payload); + + const instr = actual.data.instruction; + try expect_opt_value(expected.delay, instr.delay); + try expect_opt_value(expected.side_set, instr.side_set); + + const pull = instr.payload.pull; + try expectEqual(expected.block, pull.block); + try expectEqual(expected.ifempty, pull.ifempty); +} + +const ExpectedMovInstr = struct { + source: Token.Instruction.Mov.Source, + destination: Token.Instruction.Mov.Destination, + operation: Token.Instruction.Mov.Operation = .none, + delay: ?Value = null, + side_set: ?Value = null, +}; + +fn expect_instr_mov(expected: ExpectedMovInstr, actual: Token) !void { + try expectEqual(Token.Tag.instruction, actual.data); + try expectEqual(PayloadTag.mov, actual.data.instruction.payload); + + const instr = actual.data.instruction; + try expect_opt_value(expected.delay, instr.delay); + try expect_opt_value(expected.side_set, instr.side_set); + + const mov = instr.payload.mov; + try expectEqual(expected.source, mov.source); + try expectEqual(expected.operation, mov.operation); + try expectEqual(expected.destination, mov.destination); +} + +const ExpectedIrqInstr = struct { + clear: bool, + wait: bool, + num: u5, + rel: bool = false, + delay: ?Value = null, + side_set: ?Value = null, +}; + +fn expect_instr_irq(expected: ExpectedIrqInstr, actual: Token) !void { + try expectEqual(Token.Tag.instruction, actual.data); + try expectEqual(PayloadTag.irq, actual.data.instruction.payload); + + const instr = actual.data.instruction; + try expect_opt_value(expected.delay, instr.delay); + try expect_opt_value(expected.side_set, instr.side_set); + + const irq = instr.payload.irq; + try expectEqual(expected.clear, irq.clear); + try expectEqual(expected.wait, irq.wait); + try expectEqual(expected.rel, irq.rel); +} + +fn bounded_tokenize(source: []const u8) !std.BoundedArray(Token, 256) { + var diags: ?assembler.Diagnostics = null; + return tokenize(source, &diags, .{}) catch |err| if (diags) |d| blk: { + std.log.err("error at index {}: {s}", .{ d.index, d.message.slice() }); + break :blk err; + } else err; +} + +test "tokenize.empty string" { + const tokens = try bounded_tokenize(""); + try expectEqual(@as(usize, 0), tokens.len); +} + +test "tokenize.whitespace" { + const tokens = try bounded_tokenize(" \t\r\n"); + try expectEqual(@as(usize, 0), tokens.len); +} + +test "tokenize.comma line comment" { + const tokens = try bounded_tokenize("; this is a line comment"); + + try expectEqual(@as(usize, 0), tokens.len); +} + +test "tokenize.slash line comment" { + const tokens = try bounded_tokenize("// this is a line comment"); + + try expectEqual(@as(usize, 0), tokens.len); +} + +test "tokenize.block comment" { + const tokens = try bounded_tokenize( + \\/* this is + \\ a block comment */ + ); + + try expectEqual(@as(usize, 0), tokens.len); +} + +test "tokenize.code block" { + const tokens = try bounded_tokenize( + \\% c-sdk { + \\ int foo; + \\%} + ); + + try expectEqual(@as(usize, 0), tokens.len); +} + +test "tokenize.directive.program" { + const tokens = try bounded_tokenize(".program arst"); + try expect_program("arst", tokens.get(0)); +} + +test "tokenize.directive.define" { + const tokens = try bounded_tokenize(".define symbol_name 1"); + + try expect_define(.{ + .name = "symbol_name", + .value = .{ .expression = "1" }, + .index = 8, + }, tokens.get(0)); +} + +test "tokenize.directive.define.public" { + const tokens = try bounded_tokenize(".define public symbol_name 0x1"); + + try expect_define(.{ + .name = "symbol_name", + .value = .{ .expression = "0x1" }, + .public = true, + .index = 15, + }, tokens.get(0)); +} + +test "tokenize.directive.define.with expression" { + const tokens = try bounded_tokenize( + \\.define symbol_name 0x1 + \\.define something (symbol_name * 2) + ); + + try expect_define(.{ + .name = "symbol_name", + .value = .{ .expression = "0x1" }, + .index = 8, + }, tokens.get(0)); + + try expect_define(.{ + .name = "something", + .value = .{ .expression = "(symbol_name * 2)" }, + .index = 32, + }, tokens.get(1)); +} + +test "tokenize.directive.origin" { + const tokens = try bounded_tokenize(".origin 0x10"); + try expect_origin(.{ .integer = 0x10 }, tokens.get(0)); +} + +test "tokenize.directive.side_set" { + const tokens = try bounded_tokenize(".side_set 1"); + try expect_side_set(.{ .count = .{ .integer = 1 } }, tokens.get(0)); +} + +test "tokenize.directive.side_set.opt" { + const tokens = try bounded_tokenize(".side_set 1 opt"); + try expect_side_set(.{ .count = .{ .integer = 1 }, .opt = true }, tokens.get(0)); +} + +test "tokenize.directive.side_set.pindirs" { + const tokens = try bounded_tokenize(".side_set 1 pindirs"); + try expect_side_set(.{ .count = .{ .integer = 1 }, .pindirs = true }, tokens.get(0)); +} + +test "tokenize.directive.wrap_target" { + const tokens = try bounded_tokenize(".wrap_target"); + try expect_wrap_target(tokens.get(0)); +} + +test "tokenize.directive.wrap" { + const tokens = try bounded_tokenize(".wrap"); + try expect_wrap(tokens.get(0)); +} + +test "tokenize.directive.lang_opt" { + const tokens = try bounded_tokenize(".lang_opt c flag foo"); + try expect_lang_opt(.{ .lang = "c", .name = "flag", .option = "foo" }, tokens.get(0)); +} + +test "tokenize.directive.word" { + const tokens = try bounded_tokenize(".word 0xaaaa"); + try expect_word(.{ .integer = 0xaaaa }, tokens.get(0)); +} + +test "tokenize.label" { + const tokens = try bounded_tokenize("my_label:"); + try expect_label(.{ .name = "my_label" }, tokens.get(0)); +} + +test "tokenize.label.public" { + const tokens = try bounded_tokenize("public my_label:"); + try expect_label(.{ .name = "my_label", .public = true }, tokens.get(0)); +} + +test "tokenize.instr.nop" { + const tokens = try bounded_tokenize("nop"); + try expect_instr_nop(.{}, tokens.get(0)); +} + +test "tokenize.instr.jmp.label" { + const tokens = try bounded_tokenize("jmp my_label"); + try expect_instr_jmp(.{ .target = "my_label" }, tokens.get(0)); +} + +test "tokenize.instr.jmp.value" { + const tokens = try bounded_tokenize("jmp 0x2"); + try expect_instr_jmp(.{ .target = "0x2" }, tokens.get(0)); +} + +test "tokenize.instr.jmp.conditions" { + const Condition = Token.Instruction.Jmp.Condition; + const cases = std.ComptimeStringMap(Condition, .{ + .{ "!x", .x_is_zero }, + .{ "x--", .x_dec }, + .{ "!y", .y_is_zero }, + .{ "y--", .y_dec }, + .{ "x!=y", .x_is_not_y }, + .{ "pin", .pin }, + .{ "!osre", .osre_not_empty }, + }); + + inline for (cases.kvs) |case| { + const op = case.key; + const cond = case.value; + const tokens = try bounded_tokenize(std.fmt.comptimePrint("jmp {s} my_label", .{op})); + + try expect_instr_jmp(.{ .cond = cond, .target = "my_label" }, tokens.get(0)); + } +} + +test "tokenize.instr.wait" { + inline for (.{ "gpio", "pin", "irq" }) |source| { + const tokens = try bounded_tokenize(std.fmt.comptimePrint("wait 0 {s} 1", .{source})); + try expect_instr_wait(.{ + .polarity = 0, + .source = @field(Token.Instruction.Wait.Source, source), + .num = .{ .integer = 1 }, + }, tokens.get(0)); + } +} + +test "tokenize.instr.wait.irq.rel" { + const tokens = try bounded_tokenize("wait 1 irq 1 rel"); + try expect_instr_wait(.{ + .polarity = 1, + .source = .irq, + .num = .{ .integer = 1 }, + .rel = true, + }, tokens.get(0)); +} + +test "tokenize.instr.in" { + inline for (.{ + "pins", + "x", + "y", + "null", + "isr", + "osr", + }, 1..) |source, bit_count| { + const tokens = try bounded_tokenize(std.fmt.comptimePrint("in {s}, {}", .{ + source, + bit_count, + })); + + try expect_instr_in(.{ + .source = @field(Token.Instruction.In.Source, source), + .bit_count = @intCast(u5, bit_count), + }, tokens.get(0)); + } +} + +test "tokenize.instr.out" { + inline for (.{ + "pins", + "x", + "y", + "null", + "pindirs", + "pc", + "isr", + "exec", + }, 1..) |destination, bit_count| { + const tokens = try bounded_tokenize(std.fmt.comptimePrint("out {s}, {}", .{ + destination, + bit_count, + })); + + try expect_instr_out(.{ + .destination = @field(Token.Instruction.Out.Destination, destination), + .bit_count = @intCast(u5, bit_count), + }, tokens.get(0)); + } +} + +test "tokenize.instr.push" { + const tokens = try bounded_tokenize("push"); + try expect_instr_push(.{}, tokens.get(0)); +} + +test "tokenize.instr.push.block" { + const tokens = try bounded_tokenize("push block"); + try expect_instr_push(.{ + .block = true, + }, tokens.get(0)); +} + +test "tokenize.instr.push.noblock" { + const tokens = try bounded_tokenize("push noblock"); + try expect_instr_push(.{ + .block = false, + }, tokens.get(0)); +} + +test "tokenize.instr.push.iffull" { + const tokens = try bounded_tokenize("push iffull noblock"); + try expect_instr_push(.{ + .block = false, + .iffull = true, + }, tokens.get(0)); +} + +test "tokenize.instr.pull" { + const tokens = try bounded_tokenize("pull"); + try expect_instr_pull(.{}, tokens.get(0)); +} + +test "tokenize.instr.pull.block" { + const tokens = try bounded_tokenize("pull block"); + try expect_instr_pull(.{ + .block = true, + }, tokens.get(0)); +} + +test "tokenize.instr.pull.noblock" { + const tokens = try bounded_tokenize("pull noblock"); + try expect_instr_pull(.{ + .block = false, + }, tokens.get(0)); +} + +test "tokenize.instr.pull.ifempty" { + const tokens = try bounded_tokenize("pull ifempty noblock"); + try expect_instr_pull(.{ + .block = false, + .ifempty = true, + }, tokens.get(0)); +} + +test "tokenize.instr.mov" { + inline for (.{ + "pins", + "x", + "y", + "null", + "status", + "isr", + "osr", + }) |source| { + const tokens = try bounded_tokenize(std.fmt.comptimePrint("mov x {s}", .{source})); + + try expect_instr_mov(.{ + .source = @field(Token.Instruction.Mov.Source, source), + .destination = .x, + }, tokens.get(0)); + } + + inline for (.{ + "pins", + "x", + "y", + "exec", + "pc", + "isr", + "osr", + }) |dest| { + const tokens = try bounded_tokenize(std.fmt.comptimePrint("mov {s} x", .{dest})); + + try expect_instr_mov(.{ + .source = .x, + .destination = @field(Token.Instruction.Mov.Destination, dest), + }, tokens.get(0)); + } + + const Operation = Token.Instruction.Mov.Operation; + const operations = std.ComptimeStringMap(Operation, .{ + .{ "!", .invert }, + .{ "~", .invert }, + .{ "::", .bit_reverse }, + }); + + inline for (.{ "", " " }) |space| { + inline for (operations.kvs) |kv| { + const str = kv.key; + const operation = kv.value; + const tokens = try bounded_tokenize(std.fmt.comptimePrint("mov x {s}{s}y", .{ + str, + space, + })); + + try expect_instr_mov(.{ + .destination = .x, + .operation = operation, + .source = .y, + }, tokens.get(0)); + } + } +} + +test "tokenize.instr.irq" { + const ClearWait = struct { + clear: bool, + wait: bool, + }; + + const modes = std.ComptimeStringMap(ClearWait, .{ + .{ "", .{ .clear = false, .wait = false } }, + .{ "set", .{ .clear = false, .wait = false } }, + .{ "nowait", .{ .clear = false, .wait = false } }, + .{ "wait", .{ .clear = false, .wait = true } }, + .{ "clear", .{ .clear = true, .wait = false } }, + }); + + inline for (modes.kvs, 0..) |kv, num| { + const tokens = try bounded_tokenize(std.fmt.comptimePrint("irq {s} {}", .{ + kv.key, + num, + })); + + try expect_instr_irq(.{ + .clear = kv.value.clear, + .wait = kv.value.wait, + .num = num, + }, tokens.get(0)); + } +} + +test "tokenize.instr.irq.rel" { + const tokens = try bounded_tokenize("irq set 2 rel"); + try expect_instr_irq(.{ + .clear = false, + .wait = false, + .num = 2, + .rel = true, + }, tokens.get(0)); +} + +test "tokenize.instr.set" { + inline for (.{ + "pins", + "x", + "y", + "pindirs", + }) |dest| { + const tokens = try bounded_tokenize(std.fmt.comptimePrint("set {s}, 2", .{dest})); + try expect_instr_set(.{ + .dest = @field(Token.Instruction.Set.Destination, dest), + .value = .{ .integer = 2 }, + }, tokens.get(0)); + } +} + +test "tokenize.instr.set.with expression including define" { + const tokens = try bounded_tokenize("set X, (NUM_CYCLES - 1) ; initialise the loop counter"); + try expect_instr_set(.{ + .dest = .x, + .value = .{ .expression = "(NUM_CYCLES - 1)" }, + }, tokens.get(0)); +} + +const instruction_examples = .{ + "nop", + "jmp arst", + "wait 0 gpio 1", + "in pins, 2", + "out pc, 1", + "push", + "pull", + "mov x y", + "irq 1", + "set pins 2", +}; + +test "tokenize.instr.label prefixed" { + inline for (instruction_examples) |instr| { + const tokens = try bounded_tokenize(std.fmt.comptimePrint("my_label: {s}", .{instr})); + try expectEqual(@as(usize, 2), tokens.len); + try expect_label(.{ .name = "my_label" }, tokens.get(0)); + } +} + +test "tokenize.instr.side_set" { + inline for (instruction_examples) |instr| { + const tokens = try bounded_tokenize(std.fmt.comptimePrint("{s} side 0", .{instr})); + const token = tokens.get(0); + try expect_value(.{ + .expression = "0", + }, token.data.instruction.side_set.?); + try expectEqual(@as(?Value, null), token.data.instruction.delay); + } +} + +test "tokenize.instr.delay" { + inline for (instruction_examples) |instr| { + const tokens = try bounded_tokenize(std.fmt.comptimePrint("{s} [1]", .{instr})); + const token = tokens.get(0); + try expectEqual(@as(?Value, null), token.data.instruction.side_set); + try expect_value(.{ + .expression = "1", + }, token.data.instruction.delay.?); + } +} + +test "tokenize.instr.delay.expression" { + inline for (instruction_examples) |instr| { + const tokens = try bounded_tokenize(std.fmt.comptimePrint("{s} [T-1]", .{instr})); + const token = tokens.get(0); + try expectEqual(@as(?Value, null), token.data.instruction.side_set); + try expect_value(.{ + .expression = "T-1", + }, token.data.instruction.delay.?); + } +} + +test "tokenize.instr.side_set.expression" { + inline for (instruction_examples) |instr| { + const tokens = try bounded_tokenize(std.fmt.comptimePrint("{s} side (N-1)", .{instr})); + const token = tokens.get(0); + try expect_value(.{ + .expression = "(N-1)", + }, token.data.instruction.side_set.?); + try expectEqual(@as(?Value, null), token.data.instruction.delay); + } +} + +test "tokenize.instr.side_set and delay" { + inline for (instruction_examples) |instr| { + const tokens = try bounded_tokenize(std.fmt.comptimePrint("{s} side 1 [2]", .{instr})); + const token = tokens.get(0); + try expect_value(.{ + .expression = "1", + }, token.data.instruction.side_set.?); + try expect_value(.{ + .expression = "2", + }, token.data.instruction.delay.?); + } +} + +test "tokenize.instr.side_set and delay reversed" { + inline for (instruction_examples) |instr| { + const tokens = try bounded_tokenize(std.fmt.comptimePrint("{s} [2] side 1", .{instr})); + const token = tokens.get(0); + try expect_value(.{ + .expression = "1", + }, token.data.instruction.side_set.?); + try expect_value(.{ + .expression = "2", + }, token.data.instruction.delay.?); + } +} + +test "tokenize.instr.comment with no whitespace" { + const tokens = try bounded_tokenize("nop side 0x0 [1]; CSn front porch"); + try expect_instr_nop(.{ + .side_set = .{ .expression = "0x0" }, + .delay = .{ .expression = "1" }, + }, tokens.get(0)); +} From 08779dfe02e3edab69126b6a96b1742049f6987a Mon Sep 17 00:00:00 2001 From: Vlad Panazan Date: Tue, 11 Apr 2023 07:43:12 +0300 Subject: [PATCH 42/74] Add SPI read function (#38) --- deps/microzig | 2 +- src/hal/pins.zig | 2 +- src/hal/spi.zig | 43 ++++++++++++++++++++++++++++++++++--------- 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/deps/microzig b/deps/microzig index dabc932..ceaa9dd 160000 --- a/deps/microzig +++ b/deps/microzig @@ -1 +1 @@ -Subproject commit dabc9325cdee394ff66e28c91803cb814954b157 +Subproject commit ceaa9ddcb080d0687ce2109f23db7db376ac911e diff --git a/src/hal/pins.zig b/src/hal/pins.zig index 7a204b8..3ff9246 100644 --- a/src/hal/pins.zig +++ b/src/hal/pins.zig @@ -520,7 +520,7 @@ pub const GlobalConfiguration = struct { if (@field(config, field.name)) |pin_config| { const gpio_num = @enumToInt(@field(Pin, field.name)); const pull = pin_config.pull orelse continue; - if (comptime pin_config.getDirection() != .in) + if (comptime pin_config.get_direction() != .in) @compileError("Only input pins can have pull up/down enabled"); gpio.set_pull(gpio_num, pull); diff --git a/src/hal/spi.zig b/src/hal/spi.zig index ea96f40..002ccc4 100644 --- a/src/hal/spi.zig +++ b/src/hal/spi.zig @@ -8,6 +8,7 @@ const gpio = @import("gpio.zig"); const clocks = @import("clocks.zig"); const resets = @import("resets.zig"); const time = @import("time.zig"); +const util = @import("util.zig"); const SpiRegs = microzig.chip.types.peripherals.SPI0; @@ -78,11 +79,11 @@ pub const SPI = enum { return spi; } - pub fn is_writable(spi: SPI) bool { + pub inline fn is_writable(spi: SPI) bool { return spi.get_regs().SSPSR.read().TNF == 1; } - pub fn is_readable(spi: SPI) bool { + pub inline fn is_readable(spi: SPI) bool { return spi.get_regs().SSPSR.read().RNE == 1; } pub fn transceive(spi: SPI, src: []const u8, dst: []u8) usize { @@ -106,7 +107,7 @@ pub const SPI = enum { return src.len; } - // Write len bytes directly from src to the SPI, and discard any data received back + /// Write len bytes directly from src to the SPI, and discard any data received back pub fn write(spi: SPI, src: []const u8) usize { const spi_regs = spi.get_regs(); // Write to TX FIFO whilst ignoring RX, then clean up afterward. When RX @@ -114,26 +115,50 @@ pub const SPI = enum { // push-on-full, but continues shifting. Safe if SSPIMSC_RORIM is not set. for (src) |s| { while (!spi.is_writable()) { - std.log.debug("SPI not writable!", .{}); + util.tight_loop_contents(); } spi_regs.SSPDR.write_raw(s); } // Drain RX FIFO, then wait for shifting to finish (which may be *after* // TX FIFO drains), then drain RX FIFO again while (spi.is_readable()) { - _ = spi_regs.SSPDR.raw; + _ = spi_regs.SSPDR.read(); } - while (spi.get_regs().SSPSR.read().BSY == 1) { - std.log.debug("SPI busy!", .{}); + while (spi_regs.SSPSR.read().BSY == 1) { + util.tight_loop_contents(); } while (spi.is_readable()) { - _ = spi_regs.SSPDR.raw; + _ = spi_regs.SSPDR.read(); } // Don't leave overrun flag set peripherals.SPI0.SSPICR.modify(.{ .RORIC = 1 }); return src.len; } + /// Read len bytes directly from the SPI to dst. + /// repeated_tx_data is output repeatedly on SO as data is read in from SI. + /// Generally this can be 0, but some devices require a specific value here, + /// e.g. SD cards expect 0xff + pub fn read(spi: SPI, repeated_tx_data: u8, dst: []u8) usize { + const spi_regs = spi.get_regs(); + const fifo_depth = 8; + var rx_remaining = dst.len; + var tx_remaining = dst.len; + + while (rx_remaining > 0 or tx_remaining > 0) { + if (tx_remaining > 0 and spi.is_writable() and rx_remaining < tx_remaining + fifo_depth) { + spi_regs.SSPDR.write_raw(repeated_tx_data); + tx_remaining -= 1; + } + if (rx_remaining > 0 and spi.is_readable()) { + const bytes = std.mem.asBytes(&spi_regs.SSPDR.read().DATA); + dst[dst.len - rx_remaining] = bytes[0]; + rx_remaining -= 1; + } + } + return dst.len; + } + fn set_baudrate(spi: SPI, baudrate: u32, freq_in: u32) u64 { const spi_regs = spi.get_regs(); // Find smallest prescale value which puts output frequency in range of @@ -143,9 +168,9 @@ pub const SPI = enum { if (freq_in < (prescale + 2) * 256 * baudrate) break; } std.debug.assert(prescale <= 254); //Freq too low + // Find largest post-divide which makes output <= baudrate. Post-divide is // an integer in the range 1 to 256 inclusive. - var postdiv: u64 = 256; while (postdiv > 1) : (postdiv -= 1) { if (freq_in / (prescale * (postdiv - 1)) > baudrate) break; From ed60b5f2e72c8dc267c151e4fa73e1d9effb5ff6 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Wed, 12 Apr 2023 23:50:03 -0700 Subject: [PATCH 43/74] Pio updates (#41) * program loading API * build examples in CI * build fixes --- .buildkite/pipeline.yml | 5 +- build.zig | 13 +- examples/squarewave.zig | 19 +- src/hal/pio.zig | 512 ++++++++++++++++++++++++-------------- src/hal/pio/assembler.zig | 4 +- 5 files changed, 353 insertions(+), 200 deletions(-) diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 50f730f..4e00ec2 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -1,2 +1,5 @@ steps: - - command: zig build test + - name: Build Examples + command: zig build + - name: Test + command: zig build test diff --git a/build.zig b/build.zig index 21a91ff..f9d3729 100644 --- a/build.zig +++ b/build.zig @@ -39,8 +39,8 @@ pub fn addPiPicoExecutable( // project requires multiple HALs, it accepts microzig as a param pub fn build(b: *Builder) !void { const optimize = b.standardOptimizeOption(.{}); - //var examples = Examples.init(b, optimize); - //examples.install(); + var examples = Examples.init(b, optimize); + examples.install(b); const pio_tests = b.addTest(.{ .root_source_file = .{ @@ -51,7 +51,7 @@ pub fn build(b: *Builder) !void { pio_tests.addIncludePath("src/hal/pio/assembler"); const test_step = b.step("test", "run unit tests"); - test_step.dependOn(&pio_tests.run().step); + test_step.dependOn(&b.addRunArtifact(pio_tests).step); } fn root() []const u8 { @@ -85,8 +85,9 @@ pub const Examples = struct { return ret; } - pub fn install(examples: *Examples) void { - inline for (@typeInfo(Examples).Struct.fields) |field| - @field(examples, field.name).install(); + pub fn install(examples: *Examples, b: *Builder) void { + inline for (@typeInfo(Examples).Struct.fields) |field| { + b.installArtifact(@field(examples, field.name).inner); + } } }; diff --git a/examples/squarewave.zig b/examples/squarewave.zig index b320681..7437000 100644 --- a/examples/squarewave.zig +++ b/examples/squarewave.zig @@ -13,11 +13,12 @@ const squarewave_program = (rp2040.pio.assemble( \\ set pins, 1 [1] ; Drive pin high and then delay for one cycle \\ set pins, 0 ; Drive pin low \\ jmp again ; Set PC to label `again` -) catch +, .{}) catch @panic("failed to assemble program")) .get_program_by_name("squarewave"); pub fn main() void { + gpio.reset(); // Pick one PIO instance arbitrarily. We're also arbitrarily picking state // machine 0 on this PIO instance (the state machines are numbered 0 to 3 // inclusive). @@ -35,19 +36,27 @@ pub fn main() void { // speed down uniformly to meet some precise frequency target, e.g. for a // UART baud rate. This register has 16 integer divisor bits and 8 // fractional divisor bits. - pio.set_clkdiv_int_frac(sm, 2, 0x80); + pio.sm_set_clkdiv(sm, .{ + .int = 2, + .frac = 0x80, + }); // There are five pin mapping groups (out, in, set, side-set, jmp pin) // which are used by different instructions or in different circumstances. // Here we're just using SET instructions. Configure state machine 0 SETs // to affect GPIO 0 only; then configure GPIO0 to be controlled by PIO0, // as opposed to e.g. the processors. - pio.set_out_pins(sm, 0, 1); - gpio.set_function(0, .pio0); + pio.gpio_init(0); + pio.sm_set_pin_mappings(sm, .{ + .out = .{ + .base = 0, + .count = 1, + }, + }); // Set the state machine running. The PIO CTRL register is global within a // PIO instance, so you can start/stop multiple state machines // simultaneously. We're using the register's hardware atomic set alias to // make one bit high without doing a read-modify-write on the register. - pio.set_enabled(sm, true); + pio.sm_set_enabled(sm, true); } diff --git a/src/hal/pio.zig b/src/hal/pio.zig index e37d713..22dc5a3 100644 --- a/src/hal/pio.zig +++ b/src/hal/pio.zig @@ -1,5 +1,6 @@ //! A PIO instance can load a single `Bytecode`, it has to be loaded into memory const std = @import("std"); +const assert = std.debug.assert; const microzig = @import("microzig"); const PIO = microzig.chip.types.peripherals.PIO0; @@ -8,26 +9,19 @@ const PIO1 = microzig.chip.peripherals.PIO1; const gpio = @import("gpio.zig"); const assembler = @import("pio/assembler.zig"); -pub const Bytecode = Bytecode; -pub const Program = assembler.Program; -pub const assemble = assembler.assemble; +const encoder = @import("pio/assembler/encoder.zig"); +// global state for keeping track of used things var used_instruction_space: [2]u32 = [_]u32{ 0, 0 }; var claimed_state_machines: [2]u4 = [_]u4{ 0, 0 }; -pub const Join = enum { - none, - rx, - tx, -}; - -pub const Status = enum { - rx_lessthan, - tx_lessthan, -}; +pub const Instruction = encoder.Instruction; +pub const Program = assembler.Program; +pub const assemble = assembler.assemble; -pub const Configuration = struct { - pin: u32, +pub const Fifo = enum { + tx, + rx, }; pub const StateMachine = enum(u2) { @@ -37,6 +31,97 @@ pub const StateMachine = enum(u2) { sm3, }; +pub const Irq = enum { + irq0, + irq1, + + pub const Regs = extern struct { + enable: @TypeOf(PIO0.IRQ0_INTE), + force: @TypeOf(PIO0.IRQ0_INTF), + status: @TypeOf(PIO0.IRQ0_INTS), + }; + + pub const Source = enum { + rx_not_empty, + tx_not_full, + // TODO: determine what this does, is it just a combination of the + // first two, or is it other things? + statemachine, + }; +}; + +pub const StateMachineRegs = extern struct { + clkdiv: @TypeOf(PIO0.SM0_CLKDIV), + execctrl: @TypeOf(PIO0.SM0_EXECCTRL), + shiftctrl: @TypeOf(PIO0.SM0_SHIFTCTRL), + addr: @TypeOf(PIO0.SM0_ADDR), + instr: @TypeOf(PIO0.SM0_INSTR), + pinctrl: @TypeOf(PIO0.SM0_PINCTRL), +}; + +pub const ClkDivOptions = struct { + int: u16, + frac: u8, + + pub fn from_float(div: f32) ClkDivOptions { + const fixed = @floatToInt(u24, div * 256); + return ClkDivOptions{ + .int = @truncate(u16, fixed >> 8), + .frac = @truncate(u8, fixed), + }; + } +}; + +pub const ExecOptions = struct { + wrap: u5, + wrap_target: u5, + side_pindir: bool, + side_set_optional: bool, +}; + +pub const ShiftOptions = struct { + autopush: bool = false, + autopull: bool = false, + in_shiftdir: Direction = .left, + out_shiftdir: Direction = .left, + push_threshold: u5 = 0, + pull_threshold: u5 = 0, + join_tx: bool = false, + join_rx: bool = false, + + pub const Direction = enum(u1) { + left, + right, + }; +}; + +pub fn PinMapping(comptime Count: type) type { + return struct { + base: u5 = 0, + count: Count = 0, + }; +} + +pub const PinMappingOptions = struct { + out: PinMapping(u6) = .{}, + set: PinMapping(u3) = .{}, + side_set: PinMapping(u3) = .{}, + in_base: u5 = 0, +}; + +pub const StateMachineInitOptions = struct { + clkdiv: ClkDivOptions, + exec: ExecOptions, + shift: ShiftOptions = .{}, + pin_mappings: PinMappingOptions = .{}, +}; + +pub const LoadAndStartProgramOptions = struct { + clkdiv: ClkDivOptions, + shift: ShiftOptions = .{}, + pin_mappings: PinMappingOptions = .{}, +}; + pub const Pio = enum(u1) { pio0 = 0, pio1 = 1, @@ -60,11 +145,6 @@ pub const Pio = enum(u1) { }); } - pub fn load(self: Pio, bytecode: Bytecode) !void { - _ = self; - _ = bytecode; - } - fn can_add_program_at_offset(self: Pio, program: Program, offset: u5) bool { if (program.origin) |origin| if (origin != offset) @@ -84,9 +164,10 @@ pub const Pio = enum(u1) { origin else error.NoSpace - else for (0..32 - program.isntruction.len) |i| { - if (self.can_add_program_at_offset(program, i)) - break i; + else for (0..(32 - program.instructions.len)) |i| { + const offset = @intCast(u5, i); + if (self.can_add_program_at_offset(program, offset)) + break offset; } else error.NoSpace; } @@ -103,12 +184,13 @@ pub const Pio = enum(u1) { } /// Public functions will need to lock independently, so only exposing this function for now - pub fn add_program(self: Pio, program: Program) !void { - // TODO: const lock = hw.Lock.claim() - // defer lock.unlock(); + pub fn add_program(self: Pio, program: Program) !u5 { + //const lock = hw.Lock.claim(); + //defer lock.unlock(); - const offset = try self.find_offset_for_program_unlocked(); - try self.add_program_at_offset(program, offset); + const offset = try self.find_offset_for_program(program); + try self.add_program_at_offset_unlocked(program, offset); + return offset; } pub fn claim_unused_state_machine(self: Pio) !StateMachine { @@ -125,15 +207,6 @@ pub const Pio = enum(u1) { } else error.NoSpace; } - pub const StateMachineRegs = extern struct { - clkdiv: @TypeOf(PIO0.SM0_CLKDIV), - execctrl: @TypeOf(PIO0.SM0_EXECCTRL), - shiftctrl: @TypeOf(PIO0.SM0_SHIFTCTRL), - addr: @TypeOf(PIO0.SM0_ADDR), - instr: @TypeOf(PIO0.SM0_INSTR), - pinctrl: @TypeOf(PIO0.SM0_PINCTRL), - }; - fn get_sm_regs(self: Pio, sm: StateMachine) *volatile StateMachineRegs { const pio_regs = self.get_regs(); return switch (sm) { @@ -144,71 +217,88 @@ pub const Pio = enum(u1) { }; } - pub fn join_fifo(self: Pio, sm: StateMachine, join: Join) void { - const tx: u1 = switch (join) { - .tx => 1, - .rx => 0, - .none => 0, - }; - const rx: u1 = switch (join) { - .tx => 0, - .rx => 1, - .none => 0, + fn get_irq_regs(self: Pio, irq: Irq) *volatile Irq.Regs { + const pio_regs = self.get_regs(); + return switch (irq) { + .irq0 => @ptrCast(*volatile Irq.Regs, &pio_regs.IRQ0_INTE), + .irq1 => @ptrCast(*volatile Irq.Regs, &pio_regs.IRQ1_INTE), }; - - const sm_regs = self.get_sm_regs(sm); - sm_regs.shiftctrl.modify(.{ - .FJOIN_TX = tx, - .FJOIN_RX = rx, - }); } - pub fn set_clkdiv_int_frac(self: Pio, sm: StateMachine, div_int: u16, div_frac: u8) void { - if (div_int == 0 and div_frac != 0) + pub inline fn sm_set_clkdiv(self: Pio, sm: StateMachine, options: ClkDivOptions) void { + if (options.int == 0 and options.frac != 0) @panic("invalid params"); const sm_regs = self.get_sm_regs(sm); sm_regs.clkdiv.write(.{ - .INT = div_int, - .FRAC = div_frac, + .INT = options.int, + .FRAC = options.frac, .reserved8 = 0, }); } - pub fn set_out_shift(self: Pio, sm: StateMachine, args: struct { - shift_right: bool, - autopull: bool, - pull_threshold: u5, - }) void { + pub inline fn sm_set_exec_options(self: Pio, sm: StateMachine, options: ExecOptions) void { const sm_regs = self.get_sm_regs(sm); - sm_regs.shiftctrl.modify(.{ - .OUT_SHIFTDIR = @boolToInt(args.shift_right), - .AUTOPULL = @boolToInt(args.autopull), - .PULL_THRESH = args.pull_threshold, + sm_regs.execctrl.modify(.{ + .WRAP_BOTTOM = options.wrap_target, + .WRAP_TOP = options.wrap, + .SIDE_PINDIR = @boolToInt(options.side_pindir), + .SIDE_EN = @boolToInt(options.side_set_optional), + + // TODO: plug in rest of the options + // STATUS_N + // STATUS_SEL + // OUT_STICKY + // INLINE_OUT_EN + // OUT_EN_SEL + // JMP_PIN + // EXEC_STALLED }); } - pub fn set_out_pins(self: Pio, sm: StateMachine, base: u5, count: u5) void { + pub inline fn sm_set_shift_options(self: Pio, sm: StateMachine, options: ShiftOptions) void { const sm_regs = self.get_sm_regs(sm); - sm_regs.pinctrl.modify(.{ - .OUT_BASE = base, - .OUT_COUNT = count, + sm_regs.shiftctrl.write(.{ + .AUTOPUSH = @boolToInt(options.autopush), + .AUTOPULL = @boolToInt(options.autopush), + + .IN_SHIFTDIR = @enumToInt(options.in_shiftdir), + .OUT_SHIFTDIR = @enumToInt(options.out_shiftdir), + + .PUSH_THRESH = options.push_threshold, + .PULL_THRESH = options.pull_threshold, + + .FJOIN_TX = @boolToInt(options.join_tx), + .FJOIN_RX = @boolToInt(options.join_rx), + + .reserved16 = 0, }); } - pub fn set_sideset_pins(self: Pio, sm: StateMachine, base: u5) void { + pub inline fn sm_set_pin_mappings(self: Pio, sm: StateMachine, options: PinMappingOptions) void { const sm_regs = self.get_sm_regs(sm); - sm_regs.pinctrl.modify(.{ .SIDESET_BASE = base }); + sm_regs.pinctrl.modify(.{ + .OUT_BASE = options.out.base, + .OUT_COUNT = options.out.count, + + .SET_BASE = options.set.base, + .SET_COUNT = options.set.count, + + .SIDESET_BASE = options.side_set.base, + .SIDESET_COUNT = options.side_set.count, + + .IN_BASE = options.in_base, + }); } - pub fn is_tx_fifo_full(self: Pio, sm: StateMachine) bool { + pub inline fn sm_is_tx_fifo_full(self: Pio, sm: StateMachine) bool { const regs = self.get_regs(); const txfull = regs.FSTAT.read().TXFULL; return (txfull & (@as(u4, 1) << @enumToInt(sm))) != 0; } - pub fn get_tx_fifo(self: Pio, sm: StateMachine) *volatile u32 { + pub inline fn sm_get_tx_fifo(self: Pio, sm: StateMachine) *volatile u32 { const regs = self.get_regs(); return switch (sm) { .sm0 => ®s.TXF0, @@ -218,33 +308,14 @@ pub const Pio = enum(u1) { }; } - pub fn blocking_write(self: Pio, sm: StateMachine, value: u32) void { - while (self.is_tx_fifo_full(sm)) {} + pub inline fn sm_blocking_write(self: Pio, sm: StateMachine, value: u32) void { + while (self.sm_is_tx_fifo_full(sm)) {} - const fifo_ptr = self.get_tx_fifo(sm); + const fifo_ptr = self.sm_get_tx_fifo(sm); fifo_ptr.* = value; } - pub fn encode_jmp() void {} - - //static inline uint _pio_encode_instr_and_args(enum pio_instr_bits instr_bits, uint arg1, uint arg2) { - // valid_params_if(PIO_INSTRUCTIONS, arg1 <= 0x7); - //#if PARAM_ASSERTIONS_ENABLED(PIO_INSTRUCTIONS) - // uint32_t major = _pio_major_instr_bits(instr_bits); - // if (major == pio_instr_bits_in || major == pio_instr_bits_out) { - // assert(arg2 && arg2 <= 32); - // } else { - // assert(arg2 <= 31); - // } - //#endif - // return instr_bits | (arg1 << 5u) | (arg2 & 0x1fu); - //} - // - //static inline uint pio_encode_jmp(uint addr) { - // return _pio_encode_instr_and_args(pio_instr_bits_jmp, 0, addr); - //} - - pub fn set_enabled(self: Pio, sm: StateMachine, enabled: bool) void { + pub inline fn sm_set_enabled(self: Pio, sm: StateMachine, enabled: bool) void { const regs = self.get_regs(); var value = regs.CTRL.read(); @@ -256,103 +327,172 @@ pub const Pio = enum(u1) { regs.CTRL.write(value); } - pub fn sm_init(self: Pio, sm: StateMachine, initial_pc: u5, config: StateMachineRegs) void { - // Halt the machine, set some sensible defaults - self.set_enabled(sm, false); + inline fn sm_clear_debug(self: Pio, sm: StateMachine) void { + const regs = self.get_regs(); + const mask: u4 = (@as(u4, 1) << @enumToInt(sm)); + + // write 1 to clear this register + regs.FDEBUG.modify(.{ + .RXSTALL = mask, + .RXUNDER = mask, + .TXOVER = mask, + .TXSTALL = mask, + }); + } + + /// changing the state of fifos will clear them + pub fn sm_clear_fifos(self: Pio, sm: StateMachine) void { + const sm_regs = self.get_sm_regs(sm); + var shiftctrl = sm_regs.shiftctrl.read(); + shiftctrl.FJOIN_TX ^= 1; + shiftctrl.FJOIN_RX ^= 1; + sm_regs.shiftctrl.write(shiftctrl); + } + + pub fn sm_fifo_level(self: Pio, sm: StateMachine, fifo: Fifo) u4 { + const num = @enumToInt(sm); + const offset: u5 = switch (fifo) { + .tx => 0, + .rx => 4, + }; + + const regs = self.get_regs(); + const levels = regs.FLEVEL.raw; - self.set_config(sm, config); - self.clear_fifos(sm); + return @truncate(u4, levels >> (@as(u5, 4) * num) + offset); + } - // Clear FIFO debug flags - //const uint32_t fdebug_sm_mask = - // (1u << PIO_FDEBUG_TXOVER_LSB) | - // (1u << PIO_FDEBUG_RXUNDER_LSB) | - // (1u << PIO_FDEBUG_TXSTALL_LSB) | - // (1u << PIO_FDEBUG_RXSTALL_LSB); - //pio->fdebug = fdebug_sm_mask << sm; + inline fn interrupt_bit_pos( + sm: StateMachine, + source: Irq.Source, + ) u5 { + return (@as(u5, 4) * @enumToInt(source)) + @enumToInt(sm); + } + + pub inline fn sm_clear_interrupt( + self: Pio, + sm: StateMachine, + irq: Irq, + source: Irq.Source, + ) void { + // TODO: why does the raw interrupt register no have irq1/0? + _ = irq; + const regs = self.get_regs(); + regs.INTR.raw &= ~(@as(u32, 1) << interrupt_bit_pos(sm, source)); + } + + // TODO: be able to disable an interrupt + pub inline fn sm_enable_interrupt( + self: Pio, + sm: StateMachine, + irq: Irq, + source: Irq.Source, + ) void { + const irq_regs = self.get_irq_regs(irq); + irq_regs.enable.raw |= @as(u32, 1) << interrupt_bit_pos(sm, source); + } + + pub inline fn sm_restart(self: Pio, sm: StateMachine) void { + const mask: u4 = (@as(u4, 1) << @enumToInt(sm)); + const regs = self.get_regs(); + regs.CTRL.modify(.{ + .SM_RESTART = mask, + }); + } + + pub inline fn sm_clkdiv_restart(self: Pio, sm: StateMachine) void { + const mask: u4 = (@as(u4, 1) << @enumToInt(sm)); + const regs = self.get_regs(); + regs.CTRL.modify(.{ + .CLKDIV_RESTART = mask, + }); + } + + pub fn sm_init( + self: Pio, + sm: StateMachine, + initial_pc: u5, + options: StateMachineInitOptions, + ) void { + // Halt the machine, set some sensible defaults + self.sm_set_enabled(sm, false); + self.sm_set_pin_mappings(sm, options.pin_mappings); + self.sm_set_clkdiv(sm, options.clkdiv); + self.sm_set_exec_options(sm, options.exec); + self.sm_set_shift_options(sm, options.shift); + + //self.set_config(sm, config); + self.sm_clear_fifos(sm); + self.sm_clear_debug(sm); // Finally, clear some internal SM state - self.restart(sm); - self.clkdiv_restart(sm); - self.exec(sm, encode_jmp(initial_pc)); + self.sm_restart(sm); + self.sm_clkdiv_restart(sm); + self.sm_exec(sm, Instruction{ + .tag = .jmp, + + .delay_side_set = 0, + .payload = .{ + .jmp = .{ + .address = initial_pc, + .condition = .always, + }, + }, + }); + } + + pub fn sm_exec(self: Pio, sm: StateMachine, instruction: Instruction) void { + const sm_regs = self.get_sm_regs(sm); + sm_regs.instr.raw = @bitCast(u16, instruction); } - // state machine configuration helpers: - // - // - set_out_pins - // - set_set_pins - // - set_in_pins - // - set_sideset_pins - // - set_sideset - // - calculate_clkdiv_from_float - // - set_clkdiv - // - set_wrap - // - set_jmp_pin - // - set_in_shift - // - set_out_shift - // - set_fifo_join - // - set_out_special - // - set_mov_status - // - // PIO: - // - // - can_add_program - // - add_program_at_offset - // - add_program - // - remove_program - // - clear_instruction_memory - // - sm_init - // - sm_set_enabled - // - sm_mask_enabled - // - sm_restart - // - restart_sm_mask - // - sm_clkdiv_restart - // - clkdiv_restart_sm_mask - // - enable_sm_mask_in_sync - // - set_irq0_source_enabled - // - set_irq1_source_enabled - // - set_irq0_source_mask_enabled - // - set_irq1_source_mask_enabled - // - set_irqn_source_enabled - // - set_irqn_source_mask_enabled - // - interrupt_get - // - interrupt_clear - // - sm_get_pc - // - sm_exec - // - sm_is_exec_stalled - // - sm_exec_wait_blocking - // - sm_set_wrap - // - sm_set_out_pins - // - sm_set_set_pins - // - sm_set_in_pins - // - sm_set_sideset_pins - // - sm_put - // - sm_get - // - sm_is_rx_fifo_full - // - sm_is_rx_fifo_empty - // - sm_is_rx_fifo_level - // - sm_is_tx_fifo_full - // - sm_is_tx_fifo_empty - // - sm_is_tx_fifo_level - // - sm_put_blocking - // - sm_get_blocking - // - sm_drain_tx_fifo - // - sm_set_clkdiv_int_frac - // - sm_set_clkdiv - // - sm_clear_fifos - // - sm_set_pins - // - sm_set_pins_with_mask - // - sm_set_pindirs_with_mask - // - sm_set_consecutive_pindirs - // - sm_claim - // - claim_sm_mask - // - sm_unclaim - // - claim_unused_sm - // - sm_is_claimed - // + pub fn sm_load_and_start_program( + self: Pio, + sm: StateMachine, + program: Program, + options: LoadAndStartProgramOptions, + ) !void { + const expected_side_set_pins = if (program.side_set) |side_set| + if (side_set.optional) + side_set.count - 1 + else + side_set.count + else + 0; + + assert(expected_side_set_pins == options.pin_mappings.side_set.count); + + // TODO: check program settings vs pin mapping + const offset = try self.add_program(program); + self.sm_init(sm, offset, .{ + .clkdiv = options.clkdiv, + .shift = options.shift, + .pin_mappings = options.pin_mappings, + .exec = .{ + .wrap = if (program.wrap) |wrap| + wrap + else + offset + @intCast(u5, program.instructions.len), + + .wrap_target = if (program.wrap_target) |wrap_target| + wrap_target + else + offset, + + .side_pindir = if (program.side_set) |side_set| + side_set.pindirs + else + false, + + .side_set_optional = if (program.side_set) |side_set| + side_set.optional + else + false, + }, + }); + } }; test "pio" { std.testing.refAllDecls(assembler); - //std.testing.refAllDecls(@import("pio/test.zig")); } diff --git a/src/hal/pio/assembler.zig b/src/hal/pio/assembler.zig index d3596fd..af4153a 100644 --- a/src/hal/pio/assembler.zig +++ b/src/hal/pio/assembler.zig @@ -22,7 +22,7 @@ pub const Program = struct { wrap: ?u5, pub fn get_mask(program: Program) u32 { - return (1 << program.instructions.len) - 1; + return (@as(u32, 1) << @intCast(u5, program.instructions.len)) - 1; } }; @@ -35,7 +35,7 @@ pub const Output = struct { comptime name: []const u8, ) Program { return for (output.programs) |program| { - if (std.mem.eql(u8, program.name, program)) + if (std.mem.eql(u8, name, program.name)) break program; } else @panic(std.fmt.comptimePrint("program '{s}' not found", .{name})); } From 344f60b864b925cf8510a17cb6591bfdbcd3cf86 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Thu, 13 Apr 2023 17:04:50 -0700 Subject: [PATCH 44/74] add comptime keyword where it's needed (#42) --- src/hal/pio/assembler/tokenizer.zig | 32 ++++++++++++++--------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/hal/pio/assembler/tokenizer.zig b/src/hal/pio/assembler/tokenizer.zig index cc360f5..62e4c0e 100644 --- a/src/hal/pio/assembler/tokenizer.zig +++ b/src/hal/pio/assembler/tokenizer.zig @@ -1601,7 +1601,7 @@ test "tokenize.instr.jmp.conditions" { inline for (cases.kvs) |case| { const op = case.key; const cond = case.value; - const tokens = try bounded_tokenize(std.fmt.comptimePrint("jmp {s} my_label", .{op})); + const tokens = try bounded_tokenize(comptime std.fmt.comptimePrint("jmp {s} my_label", .{op})); try expect_instr_jmp(.{ .cond = cond, .target = "my_label" }, tokens.get(0)); } @@ -1609,7 +1609,7 @@ test "tokenize.instr.jmp.conditions" { test "tokenize.instr.wait" { inline for (.{ "gpio", "pin", "irq" }) |source| { - const tokens = try bounded_tokenize(std.fmt.comptimePrint("wait 0 {s} 1", .{source})); + const tokens = try bounded_tokenize(comptime std.fmt.comptimePrint("wait 0 {s} 1", .{source})); try expect_instr_wait(.{ .polarity = 0, .source = @field(Token.Instruction.Wait.Source, source), @@ -1637,7 +1637,7 @@ test "tokenize.instr.in" { "isr", "osr", }, 1..) |source, bit_count| { - const tokens = try bounded_tokenize(std.fmt.comptimePrint("in {s}, {}", .{ + const tokens = try bounded_tokenize(comptime std.fmt.comptimePrint("in {s}, {}", .{ source, bit_count, })); @@ -1660,7 +1660,7 @@ test "tokenize.instr.out" { "isr", "exec", }, 1..) |destination, bit_count| { - const tokens = try bounded_tokenize(std.fmt.comptimePrint("out {s}, {}", .{ + const tokens = try bounded_tokenize(comptime std.fmt.comptimePrint("out {s}, {}", .{ destination, bit_count, })); @@ -1736,7 +1736,7 @@ test "tokenize.instr.mov" { "isr", "osr", }) |source| { - const tokens = try bounded_tokenize(std.fmt.comptimePrint("mov x {s}", .{source})); + const tokens = try bounded_tokenize(comptime std.fmt.comptimePrint("mov x {s}", .{source})); try expect_instr_mov(.{ .source = @field(Token.Instruction.Mov.Source, source), @@ -1753,7 +1753,7 @@ test "tokenize.instr.mov" { "isr", "osr", }) |dest| { - const tokens = try bounded_tokenize(std.fmt.comptimePrint("mov {s} x", .{dest})); + const tokens = try bounded_tokenize(comptime std.fmt.comptimePrint("mov {s} x", .{dest})); try expect_instr_mov(.{ .source = .x, @@ -1772,7 +1772,7 @@ test "tokenize.instr.mov" { inline for (operations.kvs) |kv| { const str = kv.key; const operation = kv.value; - const tokens = try bounded_tokenize(std.fmt.comptimePrint("mov x {s}{s}y", .{ + const tokens = try bounded_tokenize(comptime std.fmt.comptimePrint("mov x {s}{s}y", .{ str, space, })); @@ -1801,7 +1801,7 @@ test "tokenize.instr.irq" { }); inline for (modes.kvs, 0..) |kv, num| { - const tokens = try bounded_tokenize(std.fmt.comptimePrint("irq {s} {}", .{ + const tokens = try bounded_tokenize(comptime std.fmt.comptimePrint("irq {s} {}", .{ kv.key, num, })); @@ -1831,7 +1831,7 @@ test "tokenize.instr.set" { "y", "pindirs", }) |dest| { - const tokens = try bounded_tokenize(std.fmt.comptimePrint("set {s}, 2", .{dest})); + const tokens = try bounded_tokenize(comptime std.fmt.comptimePrint("set {s}, 2", .{dest})); try expect_instr_set(.{ .dest = @field(Token.Instruction.Set.Destination, dest), .value = .{ .integer = 2 }, @@ -1862,7 +1862,7 @@ const instruction_examples = .{ test "tokenize.instr.label prefixed" { inline for (instruction_examples) |instr| { - const tokens = try bounded_tokenize(std.fmt.comptimePrint("my_label: {s}", .{instr})); + const tokens = try bounded_tokenize(comptime std.fmt.comptimePrint("my_label: {s}", .{instr})); try expectEqual(@as(usize, 2), tokens.len); try expect_label(.{ .name = "my_label" }, tokens.get(0)); } @@ -1870,7 +1870,7 @@ test "tokenize.instr.label prefixed" { test "tokenize.instr.side_set" { inline for (instruction_examples) |instr| { - const tokens = try bounded_tokenize(std.fmt.comptimePrint("{s} side 0", .{instr})); + const tokens = try bounded_tokenize(comptime std.fmt.comptimePrint("{s} side 0", .{instr})); const token = tokens.get(0); try expect_value(.{ .expression = "0", @@ -1881,7 +1881,7 @@ test "tokenize.instr.side_set" { test "tokenize.instr.delay" { inline for (instruction_examples) |instr| { - const tokens = try bounded_tokenize(std.fmt.comptimePrint("{s} [1]", .{instr})); + const tokens = try bounded_tokenize(comptime std.fmt.comptimePrint("{s} [1]", .{instr})); const token = tokens.get(0); try expectEqual(@as(?Value, null), token.data.instruction.side_set); try expect_value(.{ @@ -1892,7 +1892,7 @@ test "tokenize.instr.delay" { test "tokenize.instr.delay.expression" { inline for (instruction_examples) |instr| { - const tokens = try bounded_tokenize(std.fmt.comptimePrint("{s} [T-1]", .{instr})); + const tokens = try bounded_tokenize(comptime std.fmt.comptimePrint("{s} [T-1]", .{instr})); const token = tokens.get(0); try expectEqual(@as(?Value, null), token.data.instruction.side_set); try expect_value(.{ @@ -1903,7 +1903,7 @@ test "tokenize.instr.delay.expression" { test "tokenize.instr.side_set.expression" { inline for (instruction_examples) |instr| { - const tokens = try bounded_tokenize(std.fmt.comptimePrint("{s} side (N-1)", .{instr})); + const tokens = try bounded_tokenize(comptime std.fmt.comptimePrint("{s} side (N-1)", .{instr})); const token = tokens.get(0); try expect_value(.{ .expression = "(N-1)", @@ -1914,7 +1914,7 @@ test "tokenize.instr.side_set.expression" { test "tokenize.instr.side_set and delay" { inline for (instruction_examples) |instr| { - const tokens = try bounded_tokenize(std.fmt.comptimePrint("{s} side 1 [2]", .{instr})); + const tokens = try bounded_tokenize(comptime std.fmt.comptimePrint("{s} side 1 [2]", .{instr})); const token = tokens.get(0); try expect_value(.{ .expression = "1", @@ -1927,7 +1927,7 @@ test "tokenize.instr.side_set and delay" { test "tokenize.instr.side_set and delay reversed" { inline for (instruction_examples) |instr| { - const tokens = try bounded_tokenize(std.fmt.comptimePrint("{s} [2] side 1", .{instr})); + const tokens = try bounded_tokenize(comptime std.fmt.comptimePrint("{s} [2] side 1", .{instr})); const token = tokens.get(0); try expect_value(.{ .expression = "1", From fa78bbfc4ab51ab46dbc9ad3ebd95cd0ea64a1d2 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Thu, 13 Apr 2023 22:24:28 -0700 Subject: [PATCH 45/74] update microzig (#43) Co-authored-by: mattnite --- deps/microzig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/microzig b/deps/microzig index ceaa9dd..ae6e619 160000 --- a/deps/microzig +++ b/deps/microzig @@ -1 +1 @@ -Subproject commit ceaa9ddcb080d0687ce2109f23db7db376ac911e +Subproject commit ae6e619197f5db4be18a4b8cf7bf4d1bde9e7763 From 975e5e446c298f98c26573dad1198c1f6186e1a0 Mon Sep 17 00:00:00 2001 From: David Sugar Date: Sun, 23 Apr 2023 17:11:05 +0200 Subject: [PATCH 46/74] Random number generator (#46) --- build.zig | 1 + examples/random.zig | 69 +++++++++++++++++++++++++++++++++++ src/hal.zig | 1 + src/hal/random.zig | 87 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 158 insertions(+) create mode 100644 examples/random.zig create mode 100644 src/hal/random.zig diff --git a/build.zig b/build.zig index f9d3729..c54780c 100644 --- a/build.zig +++ b/build.zig @@ -69,6 +69,7 @@ pub const Examples = struct { squarewave: *microzig.EmbeddedExecutable, //uart_pins: microzig.EmbeddedExecutable, flash_program: *microzig.EmbeddedExecutable, + random: *microzig.EmbeddedExecutable, pub fn init(b: *Builder, optimize: std.builtin.OptimizeMode) Examples { var ret: Examples = undefined; diff --git a/examples/random.zig b/examples/random.zig new file mode 100644 index 0000000..dbf00d5 --- /dev/null +++ b/examples/random.zig @@ -0,0 +1,69 @@ +//! Example that generates a 4 byte random number every second and outputs the result over UART + +const std = @import("std"); +const microzig = @import("microzig"); + +const rp2040 = microzig.hal; +const flash = rp2040.flash; +const time = rp2040.time; +const gpio = rp2040.gpio; +const clocks = rp2040.clocks; +const rand = rp2040.rand; + +const led = 25; +const uart_id = 0; +const baud_rate = 115200; +const uart_tx_pin = 0; +const uart_rx_pin = 1; + +pub fn panic(message: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { + std.log.err("panic: {s}", .{message}); + @breakpoint(); + while (true) {} +} + +pub const std_options = struct { + pub const log_level = .debug; + pub const logFn = rp2040.uart.log; +}; + +pub fn main() !void { + gpio.reset(); + gpio.init(led); + gpio.set_direction(led, .out); + gpio.put(led, 1); + + const uart = rp2040.uart.UART.init(uart_id, .{ + .baud_rate = baud_rate, + .tx_pin = uart_tx_pin, + .rx_pin = uart_rx_pin, + .clock_config = rp2040.clock_config, + }); + + var ascon = rand.Ascon.init(); + var rng = ascon.random(); + + rp2040.uart.init_logger(uart); + + var buffer: [8]u8 = undefined; + var dist: [256]usize = .{0} ** 256; + var counter: usize = 0; + + while (true) { + rng.bytes(buffer[0..]); + counter += 8; + for (buffer) |byte| { + dist[@intCast(usize, byte)] += 1; + } + std.log.info("Generate random number: {any}", .{buffer}); + + if (counter % 256 == 0) { + var i: usize = 0; + std.log.info("Distribution:", .{}); + while (i < 256) : (i += 1) { + std.log.info("{} -> {}, {d:2}%", .{ i, dist[i], @intToFloat(f32, dist[i]) / @intToFloat(f32, counter) }); + } + } + time.sleep_ms(1000); + } +} diff --git a/src/hal.zig b/src/hal.zig index 5813cf9..1350d07 100644 --- a/src/hal.zig +++ b/src/hal.zig @@ -16,6 +16,7 @@ pub const irq = @import("hal/irq.zig"); pub const rom = @import("hal/rom.zig"); pub const flash = @import("hal/flash.zig"); pub const pio = @import("hal/pio.zig"); +pub const rand = @import("hal/random.zig"); pub const clock_config = clocks.GlobalConfiguration.init(.{ .ref = .{ .source = .src_xosc }, diff --git a/src/hal/random.zig b/src/hal/random.zig new file mode 100644 index 0000000..3a292a6 --- /dev/null +++ b/src/hal/random.zig @@ -0,0 +1,87 @@ +//! Random number generator (RNG) using the Ascon CSPRNG + +const std = @import("std"); +const assert = std.debug.assert; +const Random = std.rand.Random; + +const microzig = @import("microzig"); +const peripherals = microzig.chip.peripherals; + +/// Wrapper around the Ascon CSPRNG with automatic reseed using the ROSC +/// +/// ## Usage +/// +/// ```zig +/// var ascon = Ascon.init(); +/// var rng = ascon.random(); +/// ``` +/// +/// _WARNING_: This might not meet the requirements of randomness +/// for security systems because the ROSC as entropy source can be +/// compromised. However, it promises at least equal distribution. +pub const Ascon = struct { + state: std.rand.Ascon, + counter: usize = 0, + + const reseed_threshold = 4096; + const secret_seed_length = std.rand.Ascon.secret_seed_length; + + pub fn init() @This() { + // Ensure that the system clocks run from the XOSC and/or PLLs + const ref_src = peripherals.CLOCKS.CLK_REF_CTRL.read().SRC.value; + const sys_clk_src = peripherals.CLOCKS.CLK_SYS_CTRL.read().SRC.value; + const aux_src = peripherals.CLOCKS.CLK_SYS_CTRL.read().AUXSRC.value; + assert((ref_src != .rosc_clksrc_ph and sys_clk_src == .clk_ref) or + (sys_clk_src == .clksrc_clk_sys_aux and aux_src != .rosc_clksrc)); + + // Get `secret_seed_length` random bytes from the ROSC ... + var b: [secret_seed_length]u8 = undefined; + rosc(&b); + + return @This(){ .state = std.rand.Ascon.init(b) }; + } + + /// Returns a `std.rand.Random` structure backed by the current RNG + pub fn random(self: *@This()) Random { + return Random.init(self, fill); + } + + /// Fills the buffer with random bytes + pub fn fill(self: *@This(), buf: []u8) void { + // Reseed every `secret_seed_length` bytes + if (self.counter > reseed_threshold) { + var b: [secret_seed_length]u8 = undefined; + rosc(&b); + self.state.addEntropy(&b); + self.counter = 0; + } + self.state.fill(buf); + self.counter += buf.len; + } + + /// Fill the buffer with up to buffer.len random bytes + /// + /// rand uses the RANDOMBIT register of the ROSC as its source, i. e., + /// the system clocks _MUST_ run from the XOSC and/or PLLs. + /// + /// _WARNING_: This function does not meet the requirements of randomness + /// for security systems because it can be compromised, but it may be useful + /// in less critical applications. + fn rosc(buffer: []u8) void { + const rosc_state = peripherals.ROSC.CTRL.read().ENABLE.value; + // Enable the ROSC so it generates random bits for us + peripherals.ROSC.CTRL.modify(.{ .ENABLE = .{ .value = .ENABLE } }); + defer peripherals.ROSC.CTRL.modify(.{ .ENABLE = .{ .value = rosc_state } }); + + var i: usize = 0; + while (i < buffer.len) : (i += 1) { + // We poll RANDOMBIT eight times per cycle to build a random byte + var r: u8 = @intCast(u8, peripherals.ROSC.RANDOMBIT.read().RANDOMBIT); + var j: usize = 0; + while (j < 7) : (j += 1) { + r = (r << 1) | @intCast(u8, peripherals.ROSC.RANDOMBIT.read().RANDOMBIT); + } + buffer[i] = r; + } + } +}; From b0b01570c1ac1fb3d606dd782ce6021bda565e1f Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Sun, 23 Apr 2023 11:55:47 -0700 Subject: [PATCH 47/74] update microzig (#47) --- deps/microzig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/microzig b/deps/microzig index ae6e619..dd491cc 160000 --- a/deps/microzig +++ b/deps/microzig @@ -1 +1 @@ -Subproject commit ae6e619197f5db4be18a4b8cf7bf4d1bde9e7763 +Subproject commit dd491cc84fe034cb07f5b6cc6aa486d97e0ef7ab From 812fb44180d6d2ba141f0e7889e0c1e2345b52c2 Mon Sep 17 00:00:00 2001 From: David Sugar Date: Mon, 24 Apr 2023 16:45:24 +0200 Subject: [PATCH 48/74] USB Device (#40) --- build.zig | 4 +- examples/scripts/hid_test.py | 29 ++ examples/scripts/usb_device_loopback.py | 48 ++ examples/usb_device.zig | 173 +++++++ examples/usb_hid.zig | 188 +++++++ src/hal.zig | 6 + src/hal/rom.zig | 6 +- src/hal/usb.zig | 647 ++++++++++++++++++++++++ 8 files changed, 1097 insertions(+), 4 deletions(-) create mode 100755 examples/scripts/hid_test.py create mode 100755 examples/scripts/usb_device_loopback.py create mode 100644 examples/usb_device.zig create mode 100644 examples/usb_hid.zig create mode 100644 src/hal/usb.zig diff --git a/build.zig b/build.zig index c54780c..1ee7e17 100644 --- a/build.zig +++ b/build.zig @@ -44,7 +44,7 @@ pub fn build(b: *Builder) !void { const pio_tests = b.addTest(.{ .root_source_file = .{ - .path = "src/hal/pio.zig", + .path = "src/hal.zig", }, .optimize = optimize, }); @@ -69,6 +69,8 @@ pub const Examples = struct { squarewave: *microzig.EmbeddedExecutable, //uart_pins: microzig.EmbeddedExecutable, flash_program: *microzig.EmbeddedExecutable, + usb_device: *microzig.EmbeddedExecutable, + usb_hid: *microzig.EmbeddedExecutable, random: *microzig.EmbeddedExecutable, pub fn init(b: *Builder, optimize: std.builtin.OptimizeMode) Examples { diff --git a/examples/scripts/hid_test.py b/examples/scripts/hid_test.py new file mode 100755 index 0000000..ccc2dd0 --- /dev/null +++ b/examples/scripts/hid_test.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 + +# Install python3 HID package https://pypi.org/project/hid/ +import hid + +# default is TinyUSB (0xcafe), Adafruit (0x239a), RaspberryPi (0x2e8a), Espressif (0x303a) VID +USB_VID = (0xcafe, 0x239a, 0x2e8a, 0x303a) + +print("VID list: " + ", ".join('%02x' % v for v in USB_VID)) + +for vid in USB_VID: + for dict in hid.enumerate(vid): + print(dict) + dev = hid.Device(dict['vendor_id'], dict['product_id']) + if dev: + while True: + inp = input("Send text to HID Device : ").encode('utf-8') + dev.write(inp) + + x = 0 + l = len(inp) + r = b"" + while (x < l): + str_in = dev.read(64) + r += str_in + x += 64 + + print("Received from HID Device:\n", r) + print("hex:\n", r.hex()) diff --git a/examples/scripts/usb_device_loopback.py b/examples/scripts/usb_device_loopback.py new file mode 100755 index 0000000..82bf478 --- /dev/null +++ b/examples/scripts/usb_device_loopback.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 + +# +# Copyright (c) 2020 Raspberry Pi (Trading) Ltd. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# sudo pip3 install pyusb + +import usb.core +import usb.util + +# find our device +dev = usb.core.find(idVendor=0x0000, idProduct=0x0001) + +# was it found? +if dev is None: + raise ValueError('Device not found') + +# get an endpoint instance +cfg = dev.get_active_configuration() +intf = cfg[(0, 0)] + +outep = usb.util.find_descriptor( + intf, + # match the first OUT endpoint + custom_match= \ + lambda e: \ + usb.util.endpoint_direction(e.bEndpointAddress) == \ + usb.util.ENDPOINT_OUT) + +inep = usb.util.find_descriptor( + intf, + # match the first IN endpoint + custom_match= \ + lambda e: \ + usb.util.endpoint_direction(e.bEndpointAddress) == \ + usb.util.ENDPOINT_IN) + +assert inep is not None +assert outep is not None + +test_string = "Hello World!" +outep.write(test_string) +from_device = inep.read(len(test_string)) + +print("Device Says: {}".format(''.join([chr(x) for x in from_device]))) diff --git a/examples/usb_device.zig b/examples/usb_device.zig new file mode 100644 index 0000000..c86d5e1 --- /dev/null +++ b/examples/usb_device.zig @@ -0,0 +1,173 @@ +const std = @import("std"); +const microzig = @import("microzig"); + +const rp2040 = microzig.hal; +const flash = rp2040.flash; +const time = rp2040.time; +const gpio = rp2040.gpio; +const clocks = rp2040.clocks; +const usb = rp2040.usb; + +const led = 25; +const uart_id = 0; +const baud_rate = 115200; +const uart_tx_pin = 0; +const uart_rx_pin = 1; + +// First we define two callbacks that will be used by the endpoints we define next... +fn ep1_in_callback(dc: *usb.DeviceConfiguration, data: []const u8) void { + _ = data; + // The host has collected the data we repeated onto + // EP1! Set up to receive more data on EP1. + usb.Usb.callbacks.usb_start_rx( + dc.endpoints[2], // EP1_OUT_CFG, + 64, + ); +} + +fn ep1_out_callback(dc: *usb.DeviceConfiguration, data: []const u8) void { + // We've gotten data from the host on our custom + // EP1! Set up EP1 to repeat it. + usb.Usb.callbacks.usb_start_tx( + dc.endpoints[3], // EP1_IN_CFG, + data, + ); +} + +// The endpoints EP0_IN and EP0_OUT are already defined but you can +// add your own endpoints to... +pub var EP1_OUT_CFG: usb.EndpointConfiguration = .{ + .descriptor = &usb.EndpointDescriptor{ + .length = @intCast(u8, @sizeOf(usb.EndpointDescriptor)), + .descriptor_type = usb.DescType.Endpoint, + .endpoint_address = usb.Dir.Out.endpoint(1), + .attributes = @enumToInt(usb.TransferType.Bulk), + .max_packet_size = 64, + .interval = 0, + }, + .endpoint_control_index = 2, + .buffer_control_index = 3, + .data_buffer_index = 2, + .next_pid_1 = false, + // The callback will be executed if we got an interrupt on EP1_OUT + .callback = ep1_out_callback, +}; + +pub var EP1_IN_CFG: usb.EndpointConfiguration = .{ + .descriptor = &usb.EndpointDescriptor{ + .length = @intCast(u8, @sizeOf(usb.EndpointDescriptor)), + .descriptor_type = usb.DescType.Endpoint, + .endpoint_address = usb.Dir.In.endpoint(1), + .attributes = @enumToInt(usb.TransferType.Bulk), + .max_packet_size = 64, + .interval = 0, + }, + .endpoint_control_index = 1, + .buffer_control_index = 2, + .data_buffer_index = 3, + .next_pid_1 = false, + // The callback will be executed if we got an interrupt on EP1_IN + .callback = ep1_in_callback, +}; + +// This is our device configuration +pub var DEVICE_CONFIGURATION: usb.DeviceConfiguration = .{ + .device_descriptor = &.{ + .length = @intCast(u8, @sizeOf(usb.DeviceDescriptor)), + .descriptor_type = usb.DescType.Device, + .bcd_usb = 0x0110, + .device_class = 0, + .device_subclass = 0, + .device_protocol = 0, + .max_packet_size0 = 64, + .vendor = 0, + .product = 1, + .bcd_device = 0, + .manufacturer_s = 1, + .product_s = 2, + .serial_s = 0, + .num_configurations = 1, + }, + .interface_descriptor = &.{ + .length = @intCast(u8, @sizeOf(usb.InterfaceDescriptor)), + .descriptor_type = usb.DescType.Interface, + .interface_number = 0, + .alternate_setting = 0, + // We have two endpoints (EP0 IN/OUT don't count) + .num_endpoints = 2, + .interface_class = 0xff, + .interface_subclass = 0, + .interface_protocol = 0, + .interface_s = 0, + }, + .config_descriptor = &.{ + .length = @intCast(u8, @sizeOf(usb.ConfigurationDescriptor)), + .descriptor_type = usb.DescType.Config, + .total_length = @intCast(u8, @sizeOf(usb.ConfigurationDescriptor) + @sizeOf(usb.InterfaceDescriptor) + @sizeOf(usb.EndpointDescriptor) + @sizeOf(usb.EndpointDescriptor)), + .num_interfaces = 1, + .configuration_value = 1, + .configuration_s = 0, + .attributes = 0xc0, + .max_power = 0x32, + }, + .lang_descriptor = "\x04\x03\x09\x04", // length || string descriptor (0x03) || Engl (0x0409) + .descriptor_strings = &.{ + // ugly unicode :| + "R\x00a\x00s\x00p\x00b\x00e\x00r\x00r\x00y\x00 \x00P\x00i\x00", + "P\x00i\x00c\x00o\x00 \x00T\x00e\x00s\x00t\x00 \x00D\x00e\x00v\x00i\x00c\x00e\x00", + }, + // Here we pass all endpoints to the config + // Dont forget to pass EP0_[IN|OUT] in the order seen below! + .endpoints = .{ + &usb.EP0_OUT_CFG, + &usb.EP0_IN_CFG, + &EP1_OUT_CFG, + &EP1_IN_CFG, + }, +}; + +pub fn panic(message: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { + std.log.err("panic: {s}", .{message}); + @breakpoint(); + while (true) {} +} + +pub const std_options = struct { + pub const log_level = .debug; + pub const logFn = rp2040.uart.log; +}; + +pub fn main() !void { + gpio.reset(); + gpio.init(led); + gpio.set_direction(led, .out); + gpio.put(led, 1); + + const uart = rp2040.uart.UART.init(uart_id, .{ + .baud_rate = baud_rate, + .tx_pin = uart_tx_pin, + .rx_pin = uart_rx_pin, + .clock_config = rp2040.clock_config, + }); + + rp2040.uart.init_logger(uart); + + // First we initialize the USB clock + rp2040.usb.Usb.init_clk(); + // Then initialize the USB device using the configuration defined above + rp2040.usb.Usb.init_device(&DEVICE_CONFIGURATION) catch unreachable; + var old: u64 = time.get_time_since_boot().us_since_boot; + var new: u64 = 0; + while (true) { + // You can now poll for USB events + rp2040.usb.Usb.task( + false, // debug output over UART [Y/n] + ) catch unreachable; + + new = time.get_time_since_boot().us_since_boot; + if (new - old > 500000) { + old = new; + gpio.toggle(led); + } + } +} diff --git a/examples/usb_hid.zig b/examples/usb_hid.zig new file mode 100644 index 0000000..633add7 --- /dev/null +++ b/examples/usb_hid.zig @@ -0,0 +1,188 @@ +const std = @import("std"); +const microzig = @import("microzig"); + +const rp2040 = microzig.hal; +const flash = rp2040.flash; +const time = rp2040.time; +const gpio = rp2040.gpio; +const clocks = rp2040.clocks; +const usb = rp2040.usb; + +const led = 25; +const uart_id = 0; +const baud_rate = 115200; +const uart_tx_pin = 0; +const uart_rx_pin = 1; + +// First we define two callbacks that will be used by the endpoints we define next... +fn ep1_in_callback(dc: *usb.DeviceConfiguration, data: []const u8) void { + _ = data; + // The host has collected the data we repeated onto + // EP1! Set up to receive more data on EP1. + usb.Usb.callbacks.usb_start_rx( + dc.endpoints[2], // EP1_OUT_CFG, + 64, + ); +} + +fn ep1_out_callback(dc: *usb.DeviceConfiguration, data: []const u8) void { + // We've gotten data from the host on our custom + // EP1! Set up EP1 to repeat it. + usb.Usb.callbacks.usb_start_tx( + dc.endpoints[3], // EP1_IN_CFG, + data, + ); +} + +// The endpoints EP0_IN and EP0_OUT are already defined but you can +// add your own endpoints to... +pub var EP1_OUT_CFG: usb.EndpointConfiguration = .{ + .descriptor = &usb.EndpointDescriptor{ + .length = @intCast(u8, @sizeOf(usb.EndpointDescriptor)), + .descriptor_type = usb.DescType.Endpoint, + .endpoint_address = usb.Dir.Out.endpoint(1), + .attributes = @enumToInt(usb.TransferType.Interrupt), + .max_packet_size = 64, + .interval = 0, + }, + .endpoint_control_index = 2, + .buffer_control_index = 3, + .data_buffer_index = 2, + .next_pid_1 = false, + // The callback will be executed if we got an interrupt on EP1_OUT + .callback = ep1_out_callback, +}; + +pub var EP1_IN_CFG: usb.EndpointConfiguration = .{ + .descriptor = &usb.EndpointDescriptor{ + .length = @intCast(u8, @sizeOf(usb.EndpointDescriptor)), + .descriptor_type = usb.DescType.Endpoint, + .endpoint_address = usb.Dir.In.endpoint(1), + .attributes = @enumToInt(usb.TransferType.Interrupt), + .max_packet_size = 64, + .interval = 0, + }, + .endpoint_control_index = 1, + .buffer_control_index = 2, + .data_buffer_index = 3, + .next_pid_1 = false, + // The callback will be executed if we got an interrupt on EP1_IN + .callback = ep1_in_callback, +}; + +// This is our device configuration +pub var DEVICE_CONFIGURATION: usb.DeviceConfiguration = .{ + .device_descriptor = &.{ + .length = @intCast(u8, @sizeOf(usb.DeviceDescriptor)), + .descriptor_type = usb.DescType.Device, + .bcd_usb = 0x0200, + .device_class = 0, + .device_subclass = 0, + .device_protocol = 0, + .max_packet_size0 = 64, + .vendor = 0xCafe, + .product = 1, + .bcd_device = 0x0100, + // Those are indices to the descriptor strings + // Make sure to provide enough string descriptors! + .manufacturer_s = 1, + .product_s = 2, + .serial_s = 3, + .num_configurations = 1, + }, + .interface_descriptor = &.{ + .length = @intCast(u8, @sizeOf(usb.InterfaceDescriptor)), + .descriptor_type = usb.DescType.Interface, + .interface_number = 0, + .alternate_setting = 0, + // We have two endpoints (EP0 IN/OUT don't count) + .num_endpoints = 2, + .interface_class = 3, + .interface_subclass = 0, + .interface_protocol = 0, + .interface_s = 0, + }, + .config_descriptor = &.{ + .length = @intCast(u8, @sizeOf(usb.ConfigurationDescriptor)), + .descriptor_type = usb.DescType.Config, + .total_length = @intCast(u8, @sizeOf(usb.ConfigurationDescriptor) + @sizeOf(usb.InterfaceDescriptor) + @sizeOf(usb.EndpointDescriptor) + @sizeOf(usb.EndpointDescriptor)), + .num_interfaces = 1, + .configuration_value = 1, + .configuration_s = 0, + .attributes = 0xc0, + .max_power = 0x32, + }, + .lang_descriptor = "\x04\x03\x09\x04", // length || string descriptor (0x03) || Engl (0x0409) + .descriptor_strings = &.{ + // ugly unicode :| + //"R\x00a\x00s\x00p\x00b\x00e\x00r\x00r\x00y\x00 \x00P\x00i\x00", + &usb.utf8ToUtf16Le("Raspberry Pi"), + //"P\x00i\x00c\x00o\x00 \x00T\x00e\x00s\x00t\x00 \x00D\x00e\x00v\x00i\x00c\x00e\x00", + &usb.utf8ToUtf16Le("Pico Test Device"), + //"c\x00a\x00f\x00e\x00b\x00a\x00b\x00e\x00", + &usb.utf8ToUtf16Le("cafebabe"), + }, + .hid = .{ + .hid_descriptor = &.{ + .bcd_hid = 0x0111, + .country_code = 0, + .num_descriptors = 1, + .report_length = 34, + }, + .report_descriptor = &usb.hid.ReportDescriptorFidoU2f, + }, + // Here we pass all endpoints to the config + // Dont forget to pass EP0_[IN|OUT] in the order seen below! + .endpoints = .{ + &usb.EP0_OUT_CFG, + &usb.EP0_IN_CFG, + &EP1_OUT_CFG, + &EP1_IN_CFG, + }, +}; + +pub fn panic(message: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { + std.log.err("panic: {s}", .{message}); + @breakpoint(); + while (true) {} +} + +pub const std_options = struct { + pub const log_level = .debug; + pub const logFn = rp2040.uart.log; +}; + +pub fn main() !void { + gpio.reset(); + gpio.init(led); + gpio.set_direction(led, .out); + gpio.put(led, 1); + + const uart = rp2040.uart.UART.init(uart_id, .{ + .baud_rate = baud_rate, + .tx_pin = uart_tx_pin, + .rx_pin = uart_rx_pin, + .clock_config = rp2040.clock_config, + }); + + rp2040.uart.init_logger(uart); + + // First we initialize the USB clock + rp2040.usb.Usb.init_clk(); + // Then initialize the USB device using the configuration defined above + rp2040.usb.Usb.init_device(&DEVICE_CONFIGURATION) catch unreachable; + var old: u64 = time.get_time_since_boot().us_since_boot; + var new: u64 = 0; + while (true) { + // You can now poll for USB events + rp2040.usb.Usb.task( + true, // debug output over UART [Y/n] + ) catch unreachable; + + new = time.get_time_since_boot().us_since_boot; + if (new - old > 500000) { + old = new; + gpio.toggle(led); + } + } +} diff --git a/src/hal.zig b/src/hal.zig index 1350d07..c9ac986 100644 --- a/src/hal.zig +++ b/src/hal.zig @@ -16,6 +16,7 @@ pub const irq = @import("hal/irq.zig"); pub const rom = @import("hal/rom.zig"); pub const flash = @import("hal/flash.zig"); pub const pio = @import("hal/pio.zig"); +pub const usb = @import("hal/usb.zig"); pub const rand = @import("hal/random.zig"); pub const clock_config = clocks.GlobalConfiguration.init(.{ @@ -37,3 +38,8 @@ pub fn init() void { pub fn get_cpu_id() u32 { return SIO.CPUID.*; } + +test "hal tests" { + _ = pio; + _ = usb; +} diff --git a/src/hal/rom.zig b/src/hal/rom.zig index 128c085..b76eb80 100644 --- a/src/hal/rom.zig +++ b/src/hal/rom.zig @@ -47,9 +47,9 @@ pub const signatures = struct { /// Signature of memset4: Sets n bytes start at ptr to the value c and returns ptr; must be word (32-bit) aligned! const memset4 = fn (ptr: [*]u32, c: u8, n: u32) [*]u32; /// Signature of memcpy: Copies n bytes starting at src to dest and returns dest. The results are undefined if the regions overlap. - const memcpy = fn (dest: [*]u8, src: [*]u8, n: u32) [*]u8; + const memcpy = fn (dest: [*]u8, src: [*]const u8, n: u32) [*]u8; /// Signature of memcpy44: Copies n bytes starting at src to dest and returns dest; must be word (32-bit) aligned! - const memcpy44 = fn (dest: [*]u32, src: [*]u32, n: u32) [*]u8; + const memcpy44 = fn (dest: [*]u32, src: [*]const u32, n: u32) [*]u8; /// Signature of connect_internal_flash: Restore all QSPI pad controls to their default state, and connect the SSI to the QSPI pads const connect_internal_flash = fn () void; /// Signature of flash_exit_xip: First set up the SSI for serial-mode operations, then issue the fixed XIP exit sequence described in @@ -189,7 +189,7 @@ 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: []u8) []u8 { +pub fn memcpy(dest: []u8, src: []const u8) []u8 { const S = struct { var f: ?*signatures.memcpy = null; }; diff --git a/src/hal/usb.zig b/src/hal/usb.zig new file mode 100644 index 0000000..48538a4 --- /dev/null +++ b/src/hal/usb.zig @@ -0,0 +1,647 @@ +//! USB device implementation +//! +//! Inspired by cbiffle's Rust [implementation](https://github.com/cbiffle/rp2040-usb-device-in-one-file/blob/main/src/main.rs) + +const std = @import("std"); + +const microzig = @import("microzig"); +const peripherals = microzig.chip.peripherals; + +/// Human Interface Device (HID) +pub const usb = microzig.core.usb; +pub const hid = usb.hid; + +const rom = @import("rom.zig"); +const resets = @import("resets.zig"); + +pub const EP0_OUT_IDX = 0; +pub const EP0_IN_IDX = 1; + +// +++++++++++++++++++++++++++++++++++++++++++++++++ +// User Interface +// +++++++++++++++++++++++++++++++++++++++++++++++++ + +/// The rp2040 usb device impl +/// +/// We create a concrete implementaion by passing a handful +/// of system specific functions to Usb(). Those functions +/// are used by the abstract USB impl of microzig. +pub const Usb = usb.Usb(F); + +pub const DeviceConfiguration = usb.DeviceConfiguration; +pub const DeviceDescriptor = usb.DeviceDescriptor; +pub const DescType = usb.DescType; +pub const InterfaceDescriptor = usb.InterfaceDescriptor; +pub const ConfigurationDescriptor = usb.ConfigurationDescriptor; +pub const EndpointDescriptor = usb.EndpointDescriptor; +pub const EndpointConfiguration = usb.EndpointConfiguration; +pub const Dir = usb.Dir; +pub const TransferType = usb.TransferType; + +pub const utf8ToUtf16Le = usb.utf8Toutf16Le; + +pub var EP0_OUT_CFG: usb.EndpointConfiguration = .{ + .descriptor = &usb.EndpointDescriptor{ + .length = @intCast(u8, @sizeOf(usb.EndpointDescriptor)), + .descriptor_type = usb.DescType.Endpoint, + .endpoint_address = usb.EP0_OUT_ADDR, + .attributes = @enumToInt(usb.TransferType.Control), + .max_packet_size = 64, + .interval = 0, + }, + .endpoint_control_index = null, + .buffer_control_index = 1, + .data_buffer_index = 0, + .next_pid_1 = false, +}; + +pub var EP0_IN_CFG: usb.EndpointConfiguration = .{ + .descriptor = &usb.EndpointDescriptor{ + .length = @intCast(u8, @sizeOf(usb.EndpointDescriptor)), + .descriptor_type = usb.DescType.Endpoint, + .endpoint_address = usb.EP0_IN_ADDR, + .attributes = @enumToInt(usb.TransferType.Control), + .max_packet_size = 64, + .interval = 0, + }, + .endpoint_control_index = null, + .buffer_control_index = 0, + .data_buffer_index = 0, + .next_pid_1 = false, +}; + +// +++++++++++++++++++++++++++++++++++++++++++++++++ +// Reference to endpoint buffers +// +++++++++++++++++++++++++++++++++++++++++++++++++ + +/// USB data buffers +pub const buffers = struct { + // Address 0x100-0xfff (3840 bytes) can be used for data buffers. + const USBDPRAM_BASE = 0x50100100; + // Data buffers are 64 bytes long as this is the max normal packet size + const BUFFER_SIZE = 64; + /// EP0 buffer 0 (shared between in and out) + const USB_EP0_BUFFER0 = USBDPRAM_BASE; + /// Optional EP0 buffer 1 + const USB_EP0_BUFFER1 = USBDPRAM_BASE + BUFFER_SIZE; + /// Data buffers + const USB_BUFFERS = USBDPRAM_BASE + (2 * BUFFER_SIZE); + + /// Mapping to the different data buffers in DPSRAM + pub var B: usb.Buffers = .{ + .ep0_buffer0 = @intToPtr([*]u8, USB_EP0_BUFFER0), + .ep0_buffer1 = @intToPtr([*]u8, USB_EP0_BUFFER1), + // We will initialize this comptime in a loop + .rest = .{ + @intToPtr([*]u8, USB_BUFFERS + (0 * BUFFER_SIZE)), + @intToPtr([*]u8, USB_BUFFERS + (1 * BUFFER_SIZE)), + @intToPtr([*]u8, USB_BUFFERS + (2 * BUFFER_SIZE)), + @intToPtr([*]u8, USB_BUFFERS + (3 * BUFFER_SIZE)), + @intToPtr([*]u8, USB_BUFFERS + (4 * BUFFER_SIZE)), + @intToPtr([*]u8, USB_BUFFERS + (5 * BUFFER_SIZE)), + @intToPtr([*]u8, USB_BUFFERS + (6 * BUFFER_SIZE)), + @intToPtr([*]u8, USB_BUFFERS + (7 * BUFFER_SIZE)), + @intToPtr([*]u8, USB_BUFFERS + (8 * BUFFER_SIZE)), + @intToPtr([*]u8, USB_BUFFERS + (9 * BUFFER_SIZE)), + @intToPtr([*]u8, USB_BUFFERS + (10 * BUFFER_SIZE)), + @intToPtr([*]u8, USB_BUFFERS + (11 * BUFFER_SIZE)), + @intToPtr([*]u8, USB_BUFFERS + (12 * BUFFER_SIZE)), + @intToPtr([*]u8, USB_BUFFERS + (13 * BUFFER_SIZE)), + @intToPtr([*]u8, USB_BUFFERS + (14 * BUFFER_SIZE)), + @intToPtr([*]u8, USB_BUFFERS + (15 * BUFFER_SIZE)), + }, + }; +}; + +// +++++++++++++++++++++++++++++++++++++++++++++++++ +// Code +// +++++++++++++++++++++++++++++++++++++++++++++++++ + +/// A set of functions required by the abstract USB impl to +/// create a concrete one. +pub const F = struct { + /// Initialize the USB clock to 48 MHz + /// + /// This requres that the system clock has been set up before hand + /// using the 12 MHz crystal. + pub fn usb_init_clk() void { + // Bring PLL_USB up to 48MHz. PLL_USB is clocked from refclk, which we've + // already moved over to the 12MHz XOSC. We just need to make it x4 that + // clock. + // + // PLL_USB out of reset + resets.reset(&.{.pll_usb}); + // Configure it: + // + // RFDIV = 1 + // FBDIV = 100 => FOUTVC0 = 1200 MHz + peripherals.PLL_USB.CS.modify(.{ .REFDIV = 1 }); + peripherals.PLL_USB.FBDIV_INT.modify(.{ .FBDIV_INT = 100 }); + peripherals.PLL_USB.PWR.modify(.{ .PD = 0, .VCOPD = 0 }); + // Wait for lock + while (peripherals.PLL_USB.CS.read().LOCK == 0) {} + // Set up post dividers to enable output + // + // POSTDIV1 = POSTDIV2 = 5 + // PLL_USB FOUT = 1200 MHz / 25 = 48 MHz + peripherals.PLL_USB.PRIM.modify(.{ .POSTDIV1 = 5, .POSTDIV2 = 5 }); + peripherals.PLL_USB.PWR.modify(.{ .POSTDIVPD = 0 }); + // Switch usbclk to be derived from PLLUSB + peripherals.CLOCKS.CLK_USB_CTRL.modify(.{ .AUXSRC = .{ .value = .clksrc_pll_usb } }); + + // We now have the stable 48MHz reference clock required for USB: + } + + pub fn usb_init_device(device_config: *usb.DeviceConfiguration) void { + // Bring USB out of reset + resets.reset(&.{.usbctrl}); + + // Clear the control portion of DPRAM. This may not be necessary -- the + // datasheet is ambiguous -- but the C examples do it, and so do we. + peripherals.USBCTRL_DPRAM.SETUP_PACKET_LOW.write_raw(0); + peripherals.USBCTRL_DPRAM.SETUP_PACKET_HIGH.write_raw(0); + + peripherals.USBCTRL_DPRAM.EP1_IN_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP1_OUT_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP2_IN_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP2_OUT_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP3_IN_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP3_OUT_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP4_IN_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP4_OUT_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP5_IN_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP5_OUT_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP6_IN_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP6_OUT_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP7_IN_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP7_OUT_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP8_IN_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP8_OUT_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP9_IN_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP9_OUT_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP10_IN_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP10_OUT_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP11_IN_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP11_OUT_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP12_IN_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP12_OUT_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP13_IN_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP13_OUT_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP14_IN_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP14_OUT_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP15_IN_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP15_OUT_CONTROL.write_raw(0); + + peripherals.USBCTRL_DPRAM.EP0_IN_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP0_OUT_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP1_IN_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP1_OUT_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP2_IN_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP2_OUT_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP3_IN_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP3_OUT_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP4_IN_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP4_OUT_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP5_IN_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP5_OUT_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP6_IN_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP6_OUT_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP7_IN_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP7_OUT_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP8_IN_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP8_OUT_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP9_IN_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP9_OUT_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP10_IN_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP10_OUT_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP11_IN_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP11_OUT_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP12_IN_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP12_OUT_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP13_IN_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP13_OUT_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP14_IN_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP14_OUT_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP15_IN_BUFFER_CONTROL.write_raw(0); + peripherals.USBCTRL_DPRAM.EP15_OUT_BUFFER_CONTROL.write_raw(0); + + // Mux the controller to the onboard USB PHY. I was surprised that there are + // alternatives to this, but, there are. + peripherals.USBCTRL_REGS.USB_MUXING.modify(.{ + .TO_PHY = 1, + // This bit is also set in the SDK example, without any discussion. It's + // undocumented (being named does not count as being documented). + .SOFTCON = 1, + }); + + // Force VBUS detect. Not all RP2040 boards wire up VBUS detect, which would + // let us detect being plugged into a host (the Pi Pico, to its credit, + // does). For maximum compatibility, we'll set the hardware to always + // pretend VBUS has been detected. + peripherals.USBCTRL_REGS.USB_PWR.modify(.{ + .VBUS_DETECT = 1, + .VBUS_DETECT_OVERRIDE_EN = 1, + }); + + // Enable controller in device mode. + peripherals.USBCTRL_REGS.MAIN_CTRL.modify(.{ + .CONTROLLER_EN = 1, + .HOST_NDEVICE = 0, + }); + + // Request to have an interrupt (which really just means setting a bit in + // the `buff_status` register) every time a buffer moves through EP0. + peripherals.USBCTRL_REGS.SIE_CTRL.modify(.{ + .EP0_INT_1BUF = 1, + }); + + // Enable interrupts (bits set in the `ints` register) for other conditions + // we use: + peripherals.USBCTRL_REGS.INTE.modify(.{ + // A buffer is done + .BUFF_STATUS = 1, + // The host has reset us + .BUS_RESET = 1, + // We've gotten a setup request on EP0 + .SETUP_REQ = 1, + }); + + // setup endpoints + for (device_config.endpoints) |ep| { + // EP0 doesn't have an endpoint control index; only process the other + // endpoints here. + if (ep.endpoint_control_index) |epci| { + // We need to compute the offset from the base of USB SRAM to the + // buffer we're choosing, because that's how the peripheral do. + const buf_base = @ptrToInt(buffers.B.get(ep.data_buffer_index)); + const dpram_base = @ptrToInt(peripherals.USBCTRL_DPRAM); + // The offset _should_ fit in a u16, but if we've gotten something + // wrong in the past few lines, a common symptom will be integer + // overflow producing a Very Large Number, + const dpram_offset = @intCast(u16, buf_base - dpram_base); + + // Configure the endpoint! + modify_endpoint_control(epci, .{ + .ENABLE = 1, + // Please set the corresponding bit in buff_status when a + // buffer is done, thx. + .INTERRUPT_PER_BUFF = 1, + // Select bulk vs control (or interrupt as soon as implemented). + .ENDPOINT_TYPE = .{ .raw = @intCast(u2, ep.descriptor.attributes) }, + // And, designate our buffer by its offset. + .BUFFER_ADDRESS = dpram_offset, + }); + } + } + + // Present full-speed device by enabling pullup on DP. This is the point + // where the host will notice our presence. + peripherals.USBCTRL_REGS.SIE_CTRL.modify(.{ .PULLUP_EN = 1 }); + } + + /// Configures a given endpoint to send data (device-to-host, IN) when the host + /// next asks for it. + /// + /// The contents of `buffer` will be _copied_ into USB SRAM, so you can + /// reuse `buffer` immediately after this returns. No need to wait for the + /// packet to be sent. + pub fn usb_start_tx( + ep: *usb.EndpointConfiguration, + buffer: []const u8, + ) void { + // It is technically possible to support longer buffers but this demo + // doesn't bother. + // TODO: assert!(buffer.len() <= 64); + // You should only be calling this on IN endpoints. + // TODO: assert!(UsbDir::of_endpoint_addr(ep.descriptor.endpoint_address) == UsbDir::In); + + // Copy the given data into the corresponding ep buffer + const epbuffer = buffers.B.get(ep.data_buffer_index); + _ = rom.memcpy(epbuffer[0..buffer.len], buffer); + + // Configure the IN: + const np: u1 = if (ep.next_pid_1) 1 else 0; + + // The AVAILABLE bit in the buffer control register should be set + // separately to the rest of the data in the buffer control register, + // so that the rest of the data in the buffer control register is + // accurate when the AVAILABLE bit is set. + + // Write the buffer information to the buffer control register + modify_buffer_control(ep.buffer_control_index, .{ + .PID_0 = np, // DATA0/1, depending + .FULL_0 = 1, // We have put data in + .LENGTH_0 = @intCast(u10, buffer.len), // There are this many bytes + }); + + // Nop for some clock cycles + // use volatile so the compiler doesn't optimize the nops away + asm volatile ( + \\ nop + \\ nop + \\ nop + ); + + // Set available bit + modify_buffer_control(ep.buffer_control_index, .{ + .AVAILABLE_0 = 1, // The data is for the computer to use now + }); + + ep.next_pid_1 = !ep.next_pid_1; + } + + pub fn usb_start_rx( + ep: *usb.EndpointConfiguration, + len: usize, + ) void { + // It is technically possible to support longer buffers but this demo + // doesn't bother. + // TODO: assert!(len <= 64); + // You should only be calling this on OUT endpoints. + // TODO: assert!(UsbDir::of_endpoint_addr(ep.descriptor.endpoint_address) == UsbDir::Out); + + // Check which DATA0/1 PID this endpoint is expecting next. + const np: u1 = if (ep.next_pid_1) 1 else 0; + // Configure the OUT: + modify_buffer_control(ep.buffer_control_index, .{ + .PID_0 = np, // DATA0/1 depending + .FULL_0 = 0, // Buffer is NOT full, we want the computer to fill it + .AVAILABLE_0 = 1, // It is, however, available to be filled + .LENGTH_0 = @intCast(u10, len), // Up tho this many bytes + }); + + // Flip the DATA0/1 PID for the next receive + ep.next_pid_1 = !ep.next_pid_1; + } + + /// Check which interrupt flags are set + pub fn get_interrupts() usb.InterruptStatus { + const ints = peripherals.USBCTRL_REGS.INTS.read(); + + return .{ + .BuffStatus = if (ints.BUFF_STATUS == 1) true else false, + .BusReset = if (ints.BUS_RESET == 1) true else false, + .DevConnDis = if (ints.DEV_CONN_DIS == 1) true else false, + .DevSuspend = if (ints.DEV_SUSPEND == 1) true else false, + .DevResumeFromHost = if (ints.DEV_RESUME_FROM_HOST == 1) true else false, + .SetupReq = if (ints.SETUP_REQ == 1) true else false, + }; + } + + /// Returns a received USB setup packet + /// + /// Side effect: The setup request status flag will be cleared + /// + /// One can assume that this function is only called if the + /// setup request falg is set. + pub fn get_setup_packet() usb.SetupPacket { + // Clear the status flag (write-one-to-clear) + peripherals.USBCTRL_REGS.SIE_STATUS.modify(.{ .SETUP_REC = 1 }); + + // This assumes that the setup packet is arriving on EP0, our + // control endpoint. Which it should be. We don't have any other + // Control endpoints. + + // Copy the setup packet out of its dedicated buffer at the base of + // USB SRAM. The PAC models this buffer as two 32-bit registers, + // which is, like, not _wrong_ but slightly awkward since it means + // we can't just treat it as bytes. Instead, copy it out to a byte + // array. + var setup_packet: [8]u8 = .{0} ** 8; + const spl: u32 = peripherals.USBCTRL_DPRAM.SETUP_PACKET_LOW.raw; + const sph: u32 = peripherals.USBCTRL_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)); + // Reinterpret as setup packet + return std.mem.bytesToValue(usb.SetupPacket, &setup_packet); + } + + /// Called on a bus reset interrupt + pub fn bus_reset() void { + // Acknowledge by writing the write-one-to-clear status bit. + peripherals.USBCTRL_REGS.SIE_STATUS.modify(.{ .BUS_RESET = 1 }); + peripherals.USBCTRL_REGS.ADDR_ENDP.modify(.{ .ADDRESS = 0 }); + } + + pub fn set_address(addr: u7) void { + peripherals.USBCTRL_REGS.ADDR_ENDP.modify(.{ .ADDRESS = addr }); + } + + pub fn get_EPBIter(dc: *const usb.DeviceConfiguration) usb.EPBIter { + return .{ + .bufbits = peripherals.USBCTRL_REGS.BUFF_STATUS.raw, + .device_config = dc, + .next = next, + }; + } +}; + +// +++++++++++++++++++++++++++++++++++++++++++++++++ +// Utility functions +// +++++++++++++++++++++++++++++++++++++++++++++++++ + +/// Check if the corresponding buffer is available +pub fn buffer_available( + ep: *usb.EndpointConfiguration, +) bool { + const rbc = read_raw_buffer_control(ep.buffer_control_index); + // Bit 11 of the EPn_X_BUFFER_CONTROL register represents the AVAILABLE_0 flag + return ((rbc & 0x400) == 0); +} + +pub fn modify_buffer_control( + i: usize, + fields: anytype, +) void { + // haven't found a better way to handle this + switch (i) { + 0 => peripherals.USBCTRL_DPRAM.EP0_IN_BUFFER_CONTROL.modify(fields), + 1 => peripherals.USBCTRL_DPRAM.EP0_OUT_BUFFER_CONTROL.modify(fields), + 2 => peripherals.USBCTRL_DPRAM.EP1_IN_BUFFER_CONTROL.modify(fields), + 3 => peripherals.USBCTRL_DPRAM.EP1_OUT_BUFFER_CONTROL.modify(fields), + 4 => peripherals.USBCTRL_DPRAM.EP2_IN_BUFFER_CONTROL.modify(fields), + 5 => peripherals.USBCTRL_DPRAM.EP2_OUT_BUFFER_CONTROL.modify(fields), + 6 => peripherals.USBCTRL_DPRAM.EP3_IN_BUFFER_CONTROL.modify(fields), + 7 => peripherals.USBCTRL_DPRAM.EP3_OUT_BUFFER_CONTROL.modify(fields), + 8 => peripherals.USBCTRL_DPRAM.EP4_IN_BUFFER_CONTROL.modify(fields), + 9 => peripherals.USBCTRL_DPRAM.EP4_OUT_BUFFER_CONTROL.modify(fields), + 10 => peripherals.USBCTRL_DPRAM.EP5_IN_BUFFER_CONTROL.modify(fields), + 11 => peripherals.USBCTRL_DPRAM.EP5_OUT_BUFFER_CONTROL.modify(fields), + 12 => peripherals.USBCTRL_DPRAM.EP6_IN_BUFFER_CONTROL.modify(fields), + 13 => peripherals.USBCTRL_DPRAM.EP6_OUT_BUFFER_CONTROL.modify(fields), + 14 => peripherals.USBCTRL_DPRAM.EP7_IN_BUFFER_CONTROL.modify(fields), + 15 => peripherals.USBCTRL_DPRAM.EP7_OUT_BUFFER_CONTROL.modify(fields), + 16 => peripherals.USBCTRL_DPRAM.EP8_IN_BUFFER_CONTROL.modify(fields), + 17 => peripherals.USBCTRL_DPRAM.EP8_OUT_BUFFER_CONTROL.modify(fields), + 18 => peripherals.USBCTRL_DPRAM.EP9_IN_BUFFER_CONTROL.modify(fields), + 19 => peripherals.USBCTRL_DPRAM.EP9_OUT_BUFFER_CONTROL.modify(fields), + 20 => peripherals.USBCTRL_DPRAM.EP10_IN_BUFFER_CONTROL.modify(fields), + 21 => peripherals.USBCTRL_DPRAM.EP10_OUT_BUFFER_CONTROL.modify(fields), + 22 => peripherals.USBCTRL_DPRAM.EP11_IN_BUFFER_CONTROL.modify(fields), + 23 => peripherals.USBCTRL_DPRAM.EP11_OUT_BUFFER_CONTROL.modify(fields), + 24 => peripherals.USBCTRL_DPRAM.EP12_IN_BUFFER_CONTROL.modify(fields), + 25 => peripherals.USBCTRL_DPRAM.EP12_OUT_BUFFER_CONTROL.modify(fields), + 26 => peripherals.USBCTRL_DPRAM.EP13_IN_BUFFER_CONTROL.modify(fields), + 27 => peripherals.USBCTRL_DPRAM.EP13_OUT_BUFFER_CONTROL.modify(fields), + 28 => peripherals.USBCTRL_DPRAM.EP14_IN_BUFFER_CONTROL.modify(fields), + 29 => peripherals.USBCTRL_DPRAM.EP14_OUT_BUFFER_CONTROL.modify(fields), + 30 => peripherals.USBCTRL_DPRAM.EP15_IN_BUFFER_CONTROL.modify(fields), + 31 => peripherals.USBCTRL_DPRAM.EP15_OUT_BUFFER_CONTROL.modify(fields), + else => {}, // TODO: We'll just ignore it for now + } +} + +pub fn read_raw_buffer_control( + i: usize, +) u32 { + // haven't found a better way to handle this + return switch (i) { + 0 => peripherals.USBCTRL_DPRAM.EP0_IN_BUFFER_CONTROL.raw, + 1 => peripherals.USBCTRL_DPRAM.EP0_OUT_BUFFER_CONTROL.raw, + 2 => peripherals.USBCTRL_DPRAM.EP1_IN_BUFFER_CONTROL.raw, + 3 => peripherals.USBCTRL_DPRAM.EP1_OUT_BUFFER_CONTROL.raw, + 4 => peripherals.USBCTRL_DPRAM.EP2_IN_BUFFER_CONTROL.raw, + 5 => peripherals.USBCTRL_DPRAM.EP2_OUT_BUFFER_CONTROL.raw, + 6 => peripherals.USBCTRL_DPRAM.EP3_IN_BUFFER_CONTROL.raw, + 7 => peripherals.USBCTRL_DPRAM.EP3_OUT_BUFFER_CONTROL.raw, + 8 => peripherals.USBCTRL_DPRAM.EP4_IN_BUFFER_CONTROL.raw, + 9 => peripherals.USBCTRL_DPRAM.EP4_OUT_BUFFER_CONTROL.raw, + 10 => peripherals.USBCTRL_DPRAM.EP5_IN_BUFFER_CONTROL.raw, + 11 => peripherals.USBCTRL_DPRAM.EP5_OUT_BUFFER_CONTROL.raw, + 12 => peripherals.USBCTRL_DPRAM.EP6_IN_BUFFER_CONTROL.raw, + 13 => peripherals.USBCTRL_DPRAM.EP6_OUT_BUFFER_CONTROL.raw, + 14 => peripherals.USBCTRL_DPRAM.EP7_IN_BUFFER_CONTROL.raw, + 15 => peripherals.USBCTRL_DPRAM.EP7_OUT_BUFFER_CONTROL.raw, + 16 => peripherals.USBCTRL_DPRAM.EP8_IN_BUFFER_CONTROL.raw, + 17 => peripherals.USBCTRL_DPRAM.EP8_OUT_BUFFER_CONTROL.raw, + 18 => peripherals.USBCTRL_DPRAM.EP9_IN_BUFFER_CONTROL.raw, + 19 => peripherals.USBCTRL_DPRAM.EP9_OUT_BUFFER_CONTROL.raw, + 20 => peripherals.USBCTRL_DPRAM.EP10_IN_BUFFER_CONTROL.raw, + 21 => peripherals.USBCTRL_DPRAM.EP10_OUT_BUFFER_CONTROL.raw, + 22 => peripherals.USBCTRL_DPRAM.EP11_IN_BUFFER_CONTROL.raw, + 23 => peripherals.USBCTRL_DPRAM.EP11_OUT_BUFFER_CONTROL.raw, + 24 => peripherals.USBCTRL_DPRAM.EP12_IN_BUFFER_CONTROL.raw, + 25 => peripherals.USBCTRL_DPRAM.EP12_OUT_BUFFER_CONTROL.raw, + 26 => peripherals.USBCTRL_DPRAM.EP13_IN_BUFFER_CONTROL.raw, + 27 => peripherals.USBCTRL_DPRAM.EP13_OUT_BUFFER_CONTROL.raw, + 28 => peripherals.USBCTRL_DPRAM.EP14_IN_BUFFER_CONTROL.raw, + 29 => peripherals.USBCTRL_DPRAM.EP14_OUT_BUFFER_CONTROL.raw, + 30 => peripherals.USBCTRL_DPRAM.EP15_IN_BUFFER_CONTROL.raw, + 31 => peripherals.USBCTRL_DPRAM.EP15_OUT_BUFFER_CONTROL.raw, + else => 0, // TODO: We'll just return 0 for now + }; +} + +pub fn modify_endpoint_control( + epci: usize, + fields: anytype, +) void { + // haven't found a better way to handle this + switch (epci) { + 1 => peripherals.USBCTRL_DPRAM.EP1_IN_CONTROL.modify(fields), + 2 => peripherals.USBCTRL_DPRAM.EP1_OUT_CONTROL.modify(fields), + 3 => peripherals.USBCTRL_DPRAM.EP2_IN_CONTROL.modify(fields), + 4 => peripherals.USBCTRL_DPRAM.EP2_OUT_CONTROL.modify(fields), + 5 => peripherals.USBCTRL_DPRAM.EP3_IN_CONTROL.modify(fields), + 6 => peripherals.USBCTRL_DPRAM.EP3_OUT_CONTROL.modify(fields), + 7 => peripherals.USBCTRL_DPRAM.EP4_IN_CONTROL.modify(fields), + 8 => peripherals.USBCTRL_DPRAM.EP4_OUT_CONTROL.modify(fields), + 9 => peripherals.USBCTRL_DPRAM.EP5_IN_CONTROL.modify(fields), + 10 => peripherals.USBCTRL_DPRAM.EP5_OUT_CONTROL.modify(fields), + 11 => peripherals.USBCTRL_DPRAM.EP6_IN_CONTROL.modify(fields), + 12 => peripherals.USBCTRL_DPRAM.EP6_OUT_CONTROL.modify(fields), + 13 => peripherals.USBCTRL_DPRAM.EP7_IN_CONTROL.modify(fields), + 14 => peripherals.USBCTRL_DPRAM.EP7_OUT_CONTROL.modify(fields), + 15 => peripherals.USBCTRL_DPRAM.EP8_IN_CONTROL.modify(fields), + 16 => peripherals.USBCTRL_DPRAM.EP8_OUT_CONTROL.modify(fields), + 17 => peripherals.USBCTRL_DPRAM.EP9_IN_CONTROL.modify(fields), + 18 => peripherals.USBCTRL_DPRAM.EP9_OUT_CONTROL.modify(fields), + 19 => peripherals.USBCTRL_DPRAM.EP10_IN_CONTROL.modify(fields), + 20 => peripherals.USBCTRL_DPRAM.EP10_OUT_CONTROL.modify(fields), + 21 => peripherals.USBCTRL_DPRAM.EP11_IN_CONTROL.modify(fields), + 22 => peripherals.USBCTRL_DPRAM.EP11_OUT_CONTROL.modify(fields), + 23 => peripherals.USBCTRL_DPRAM.EP12_IN_CONTROL.modify(fields), + 24 => peripherals.USBCTRL_DPRAM.EP12_OUT_CONTROL.modify(fields), + 25 => peripherals.USBCTRL_DPRAM.EP13_IN_CONTROL.modify(fields), + 26 => peripherals.USBCTRL_DPRAM.EP13_OUT_CONTROL.modify(fields), + 27 => peripherals.USBCTRL_DPRAM.EP14_IN_CONTROL.modify(fields), + 28 => peripherals.USBCTRL_DPRAM.EP14_OUT_CONTROL.modify(fields), + 29 => peripherals.USBCTRL_DPRAM.EP15_IN_CONTROL.modify(fields), + 30 => peripherals.USBCTRL_DPRAM.EP15_OUT_CONTROL.modify(fields), + else => {}, // TODO: We'll just ignore it for now + } +} + +// ----------------------------------------------------------- + +pub fn next(self: *usb.EPBIter) ?usb.EPB { + if (self.last_bit) |lb| { + // Acknowledge the last handled buffer + peripherals.USBCTRL_REGS.BUFF_STATUS.write_raw(lb); + self.last_bit = null; + } + // All input buffers handled? + if (self.bufbits == 0) return null; + + // Who's still outstanding? Find their bit index by counting how + // many LSBs are zero. + var lowbit_index: u5 = 0; + while ((self.bufbits >> lowbit_index) & 0x01 == 0) : (lowbit_index += 1) {} + // Remove their bit from our set. + const lowbit = @intCast(u32, 1) << lowbit_index; + self.last_bit = lowbit; + self.bufbits ^= lowbit; + + // Here we exploit knowledge of the ordering of buffer control + // registers in the peripheral. Each endpoint has a pair of + // registers, so we can determine the endpoint number by: + const epnum = @intCast(u8, lowbit_index >> 1); + // Of the pair, the IN endpoint comes first, followed by OUT, so + // we can get the direction by: + const dir = if (lowbit_index & 1 == 0) usb.Dir.In else usb.Dir.Out; + + const ep_addr = dir.endpoint(epnum); + // Process the buffer-done event. + + // Process the buffer-done event. + // + // Scan the device table to figure out which endpoint struct + // corresponds to this address. We could use a smarter + // method here, but in practice, the number of endpoints is + // small so a linear scan doesn't kill us. + var endpoint: ?*usb.EndpointConfiguration = null; + for (self.device_config.endpoints) |ep| { + if (ep.descriptor.endpoint_address == ep_addr) { + endpoint = ep; + break; + } + } + // Buffer event for unknown EP?! + // TODO: if (endpoint == null) return EPBError.UnknownEndpoint; + // Read the buffer control register to check status. + const bc = read_raw_buffer_control(endpoint.?.buffer_control_index); + + // We should only get here if we've been notified that + // the buffer is ours again. This is indicated by the hw + // _clearing_ the AVAILABLE bit. + // + // This ensures that we can return a shared reference to + // the databuffer contents without races. + // TODO: if ((bc & (1 << 10)) == 1) return EPBError.NotAvailable; + + // Cool. Checks out. + + // Get a pointer to the buffer in USB SRAM. This is the + // buffer _contents_. See the safety comments below. + const epbuffer = buffers.B.get(endpoint.?.data_buffer_index); + + // Get the actual length of the data, which may be less + // than the buffer size. + const len = @intCast(usize, bc & 0x3ff); + + // Copy the data from SRAM + return usb.EPB{ + .endpoint = endpoint.?, + .buffer = epbuffer[0..len], + }; +} From a2fccb3c73e3ac01ec1adcdc285943d1f1a651c6 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Tue, 25 Apr 2023 23:41:08 -0700 Subject: [PATCH 49/74] update microzig (#48) Co-authored-by: mattnite --- deps/microzig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/microzig b/deps/microzig index dd491cc..658648b 160000 --- a/deps/microzig +++ b/deps/microzig @@ -1 +1 @@ -Subproject commit dd491cc84fe034cb07f5b6cc6aa486d97e0ef7ab +Subproject commit 658648b86ba63762ac45665abe0a06ec279225b1 From bc4582cf4de165cf85ec8337a96dc9570129a629 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Wed, 26 Apr 2023 00:29:37 -0700 Subject: [PATCH 50/74] update microzig (#50) Co-authored-by: mattnite --- deps/microzig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/microzig b/deps/microzig index 658648b..b5edf6d 160000 --- a/deps/microzig +++ b/deps/microzig @@ -1 +1 @@ -Subproject commit 658648b86ba63762ac45665abe0a06ec279225b1 +Subproject commit b5edf6da6b540215f03689c3cc07d00478255f7d From c1c19d221e85845e3874d39e8bc7597f54f59237 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Wed, 26 Apr 2023 01:02:09 -0700 Subject: [PATCH 51/74] Gpio api (#51) * improve GPIO API * fix test, update microzig * first DMA functions, new abstraction for enumerating peripherals * rebase main * fix call to reset() --- examples/adc.zig | 18 +-- examples/blinky_core1.zig | 10 +- examples/flash_program.zig | 16 +-- examples/gpio_clk.zig | 9 +- examples/random.zig | 16 +-- examples/spi_master.zig | 3 +- examples/squarewave.zig | 103 +++++++++------ examples/uart.zig | 20 ++- examples/usb_device.zig | 18 ++- examples/usb_hid.zig | 18 ++- src/hal.zig | 34 +++-- src/hal/adc.zig | 5 +- src/hal/dma.zig | 131 ++++++++++++++++++ src/hal/gpio.zig | 198 ++++++++++++++++++---------- src/hal/hw.zig | 37 +++++- src/hal/pins.zig | 27 ++-- src/hal/pio.zig | 156 +++++++++++++--------- src/hal/pio/assembler.zig | 4 +- src/hal/pio/assembler/encoder.zig | 17 ++- src/hal/pio/assembler/tokenizer.zig | 8 +- src/hal/pll.zig | 2 +- src/hal/resets.zig | 150 ++++++++++++++++----- src/hal/spi.zig | 50 +++---- src/hal/uart.zig | 55 ++++---- src/hal/usb.zig | 4 +- 25 files changed, 717 insertions(+), 392 deletions(-) create mode 100644 src/hal/dma.zig diff --git a/examples/adc.zig b/examples/adc.zig index 5d8f0c3..b6d6bf4 100644 --- a/examples/adc.zig +++ b/examples/adc.zig @@ -3,26 +3,22 @@ const std = @import("std"); const microzig = @import("microzig"); const rp2040 = microzig.hal; +const gpio = rp2040.gpio; const adc = rp2040.adc; const time = rp2040.time; const temp_sensor: adc.Input = .temperature_sensor; -const uart_id = 0; +const uart = rp2040.uart.num(0); const baud_rate = 115200; -const uart_tx_pin = 0; -const uart_rx_pin = 1; +const uart_tx_pin = gpio.num(0); +const uart_rx_pin = gpio.num(1); pub const std_options = struct { pub const logFn = rp2040.uart.log; }; -pub fn init() void { - rp2040.clock_config.apply(); - rp2040.gpio.reset(); - adc.init(); - temp_sensor.init(); - - const uart = rp2040.uart.UART.init(uart_id, .{ +pub fn main() void { + uart.apply(.{ .baud_rate = baud_rate, .tx_pin = uart_tx_pin, .rx_pin = uart_rx_pin, @@ -30,9 +26,7 @@ pub fn init() void { }); rp2040.uart.init_logger(uart); -} -pub fn main() void { while (true) : (time.sleep_ms(1000)) { const sample = temp_sensor.read(); std.log.info("temp value: {}", .{sample}); diff --git a/examples/blinky_core1.zig b/examples/blinky_core1.zig index b3fdd04..64f0674 100644 --- a/examples/blinky_core1.zig +++ b/examples/blinky_core1.zig @@ -6,21 +6,19 @@ const gpio = rp2040.gpio; const time = rp2040.time; const multicore = rp2040.multicore; -const led = 25; +const led = gpio.num(25); fn core1() void { while (true) { - gpio.put(led, 1); + led.put(1); time.sleep_ms(250); - gpio.put(led, 0); + led.put(0); time.sleep_ms(250); } } pub fn main() !void { - gpio.init(led); - gpio.set_direction(led, .out); - + led.set_direction(.out); multicore.launch_core1(core1); while (true) { diff --git a/examples/flash_program.zig b/examples/flash_program.zig index 2fc5cc0..a2999c9 100644 --- a/examples/flash_program.zig +++ b/examples/flash_program.zig @@ -7,11 +7,11 @@ const time = rp2040.time; const gpio = rp2040.gpio; const clocks = rp2040.clocks; -const led = 25; -const uart_id = 0; +const led = gpio.num(25); +const uart = rp2040.uart.num(0); const baud_rate = 115200; -const uart_tx_pin = 0; -const uart_rx_pin = 1; +const uart_tx_pin = gpio.num(0); +const uart_rx_pin = gpio.num(1); const flash_target_offset: u32 = 256 * 1024; const flash_target_contents = @intToPtr([*]const u8, rp2040.flash.XIP_BASE + flash_target_offset); @@ -28,12 +28,10 @@ pub const std_options = struct { }; pub fn main() !void { - gpio.reset(); - gpio.init(led); - gpio.set_direction(led, .out); - gpio.put(led, 1); + led.set_direction(.out); + led.put(1); - const uart = rp2040.uart.UART.init(uart_id, .{ + uart.apply(.{ .baud_rate = baud_rate, .tx_pin = uart_tx_pin, .rx_pin = uart_rx_pin, diff --git a/examples/gpio_clk.zig b/examples/gpio_clk.zig index e66761c..dd28102 100644 --- a/examples/gpio_clk.zig +++ b/examples/gpio_clk.zig @@ -4,18 +4,13 @@ const rp2040 = microzig.hal; const gpio = rp2040.gpio; const clocks = rp2040.clocks; -const gpout0_pin = 21; +const gpout0_pin = gpio.num(21); const clock_config = clocks.GlobalConfiguration.init(.{ .sys = .{ .source = .src_xosc }, .gpout0 = .{ .source = .clk_sys }, }); -pub fn init() void { - clock_config.apply(); - gpio.reset(); -} - pub fn main() !void { - gpio.set_function(gpout0_pin, .gpck); + gpout0_pin.set_function(.gpck); while (true) {} } diff --git a/examples/random.zig b/examples/random.zig index dbf00d5..0645839 100644 --- a/examples/random.zig +++ b/examples/random.zig @@ -10,11 +10,11 @@ const gpio = rp2040.gpio; const clocks = rp2040.clocks; const rand = rp2040.rand; -const led = 25; -const uart_id = 0; +const led = gpio.num(25); +const uart = rp2040.uart.num(0); const baud_rate = 115200; -const uart_tx_pin = 0; -const uart_rx_pin = 1; +const uart_tx_pin = gpio.num(0); +const uart_rx_pin = gpio.num(1); pub fn panic(message: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { std.log.err("panic: {s}", .{message}); @@ -28,12 +28,10 @@ pub const std_options = struct { }; pub fn main() !void { - gpio.reset(); - gpio.init(led); - gpio.set_direction(led, .out); - gpio.put(led, 1); + led.set_direction(.out); + led.put(1); - const uart = rp2040.uart.UART.init(uart_id, .{ + uart.apply(.{ .baud_rate = baud_rate, .tx_pin = uart_tx_pin, .rx_pin = uart_rx_pin, diff --git a/examples/spi_master.zig b/examples/spi_master.zig index ba1c0c2..c160fee 100644 --- a/examples/spi_master.zig +++ b/examples/spi_master.zig @@ -8,11 +8,12 @@ const clocks = rp2040.clocks; const peripherals = microzig.chip.peripherals; const BUF_LEN = 0x100; +const spi = rp2040.spi.num(0); // Communicate with another RP2040 over spi // Slave implementation: https://github.com/raspberrypi/pico-examples/blob/master/spi/spi_master_slave/spi_slave/spi_slave.c pub fn main() !void { - const spi = rp2040.spi.SPI.init(0, .{ + spi.apply(.{ .clock_config = rp2040.clock_config, }); var out_buf: [BUF_LEN]u8 = .{ 0xAA, 0xBB, 0xCC, 0xDD } ** (BUF_LEN / 4); diff --git a/examples/squarewave.zig b/examples/squarewave.zig index 7437000..0564b62 100644 --- a/examples/squarewave.zig +++ b/examples/squarewave.zig @@ -6,57 +6,76 @@ const gpio = rp2040.gpio; const Pio = rp2040.pio.Pio; const StateMachine = rp2040.pio.StateMachine; -const squarewave_program = (rp2040.pio.assemble( +const squarewave_program = rp2040.pio.assemble( + \\; + \\; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + \\; + \\; SPDX-License-Identifier: BSD-3-Clause + \\; \\.program squarewave \\ set pindirs, 1 ; Set pin to output \\again: \\ set pins, 1 [1] ; Drive pin high and then delay for one cycle \\ set pins, 0 ; Drive pin low \\ jmp again ; Set PC to label `again` -, .{}) catch - @panic("failed to assemble program")) - .get_program_by_name("squarewave"); +, .{}).get_program_by_name("squarewave"); + +// Pick one PIO instance arbitrarily. We're also arbitrarily picking state +// machine 0 on this PIO instance (the state machines are numbered 0 to 3 +// inclusive). +const pio: Pio = .pio0; +const sm: StateMachine = .sm0; pub fn main() void { - gpio.reset(); - // Pick one PIO instance arbitrarily. We're also arbitrarily picking state - // machine 0 on this PIO instance (the state machines are numbered 0 to 3 - // inclusive). - const pio: Pio = .pio0; - const sm: StateMachine = .sm0; - - // Load the assembled program directly into the PIO's instruction memory. - // Each PIO instance has a 32-slot instruction memory, which all 4 state - // machines can see. The system has write-only access. - for (squarewave_program.instructions, 0..) |insn, i| - pio.get_instruction_memory()[i] = insn; - - // Configure state machine 0 to run at sysclk/2.5. The state machines can - // run as fast as one instruction per clock cycle, but we can scale their - // speed down uniformly to meet some precise frequency target, e.g. for a - // UART baud rate. This register has 16 integer divisor bits and 8 - // fractional divisor bits. - pio.sm_set_clkdiv(sm, .{ - .int = 2, - .frac = 0x80, - }); - - // There are five pin mapping groups (out, in, set, side-set, jmp pin) - // which are used by different instructions or in different circumstances. - // Here we're just using SET instructions. Configure state machine 0 SETs - // to affect GPIO 0 only; then configure GPIO0 to be controlled by PIO0, - // as opposed to e.g. the processors. - pio.gpio_init(0); - pio.sm_set_pin_mappings(sm, .{ - .out = .{ - .base = 0, - .count = 1, + pio.gpio_init(gpio.num(2)); + pio.sm_load_and_start_program(sm, squarewave_program, .{ + .clkdiv = rp2040.pio.ClkDivOptions.from_float(125), + .pin_mappings = .{ + .set = .{ + .base = 2, + .count = 1, + }, }, - }); + }) catch unreachable; - // Set the state machine running. The PIO CTRL register is global within a - // PIO instance, so you can start/stop multiple state machines - // simultaneously. We're using the register's hardware atomic set alias to - // make one bit high without doing a read-modify-write on the register. pio.sm_set_enabled(sm, true); + + while (true) {} + + //// Load the assembled program directly into the PIO's instruction memory. + //// Each PIO instance has a 32-slot instruction memory, which all 4 state + //// machines can see. The system has write-only access. + //for (squarewave_program.instructions, 0..) |insn, i| + // pio.get_instruction_memory()[i] = insn; + + //// Configure state machine 0 to run at sysclk/2.5. The state machines can + //// run as fast as one instruction per clock cycle, but we can scale their + //// speed down uniformly to meet some precise frequency target, e.g. for a + //// UART baud rate. This register has 16 integer divisor bits and 8 + //// fractional divisor bits. + //pio.sm_set_clkdiv(sm, .{ + // .int = 2, + // .frac = 0x80, + //}); + + //// There are five pin mapping groups (out, in, set, side-set, jmp pin) + //// which are used by different instructions or in different circumstances. + //// Here we're just using SET instructions. Configure state machine 0 SETs + //// to affect GPIO 0 only; then configure GPIO0 to be controlled by PIO0, + //// as opposed to e.g. the processors. + //pio.gpio_init(2); + //pio.sm_set_pin_mappings(sm, .{ + // .out = .{ + // .base = 2, + // .count = 1, + // }, + //}); + + //// Set the state machine running. The PIO CTRL register is global within a + //// PIO instance, so you can start/stop multiple state machines + //// simultaneously. We're using the register's hardware atomic set alias to + //// make one bit high without doing a read-modify-write on the register. + //pio.sm_set_enabled(sm, true); + + //while (true) {} } diff --git a/examples/uart.zig b/examples/uart.zig index 57cf1c4..6be3b38 100644 --- a/examples/uart.zig +++ b/examples/uart.zig @@ -6,11 +6,11 @@ const time = rp2040.time; const gpio = rp2040.gpio; const clocks = rp2040.clocks; -const led = 25; -const uart_id = 0; +const led = gpio.num(25); +const uart = rp2040.uart.num(0); const baud_rate = 115200; -const uart_tx_pin = 0; -const uart_rx_pin = 1; +const uart_tx_pin = gpio.num(0); +const uart_rx_pin = gpio.num(1); pub fn panic(message: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { std.log.err("panic: {s}", .{message}); @@ -24,12 +24,10 @@ pub const std_options = struct { }; pub fn main() !void { - gpio.reset(); - gpio.init(led); - gpio.set_direction(led, .out); - gpio.put(led, 1); + led.set_direction(.out); + led.put(1); - const uart = rp2040.uart.UART.init(uart_id, .{ + uart.apply(.{ .baud_rate = baud_rate, .tx_pin = uart_tx_pin, .rx_pin = uart_rx_pin, @@ -40,11 +38,11 @@ pub fn main() !void { var i: u32 = 0; while (true) : (i += 1) { - gpio.put(led, 1); + led.put(1); std.log.info("what {}", .{i}); time.sleep_ms(500); - gpio.put(led, 0); + led.put(0); time.sleep_ms(500); } } diff --git a/examples/usb_device.zig b/examples/usb_device.zig index c86d5e1..3395286 100644 --- a/examples/usb_device.zig +++ b/examples/usb_device.zig @@ -8,11 +8,11 @@ const gpio = rp2040.gpio; const clocks = rp2040.clocks; const usb = rp2040.usb; -const led = 25; -const uart_id = 0; +const led = gpio.num(25); +const uart = rp2040.uart.num(0); const baud_rate = 115200; -const uart_tx_pin = 0; -const uart_rx_pin = 1; +const uart_tx_pin = gpio.num(0); +const uart_rx_pin = gpio.num(1); // First we define two callbacks that will be used by the endpoints we define next... fn ep1_in_callback(dc: *usb.DeviceConfiguration, data: []const u8) void { @@ -138,12 +138,10 @@ pub const std_options = struct { }; pub fn main() !void { - gpio.reset(); - gpio.init(led); - gpio.set_direction(led, .out); - gpio.put(led, 1); + led.set_direction(.out); + led.put(1); - const uart = rp2040.uart.UART.init(uart_id, .{ + uart.apply(.{ .baud_rate = baud_rate, .tx_pin = uart_tx_pin, .rx_pin = uart_rx_pin, @@ -167,7 +165,7 @@ pub fn main() !void { new = time.get_time_since_boot().us_since_boot; if (new - old > 500000) { old = new; - gpio.toggle(led); + led.toggle(); } } } diff --git a/examples/usb_hid.zig b/examples/usb_hid.zig index 633add7..051ad74 100644 --- a/examples/usb_hid.zig +++ b/examples/usb_hid.zig @@ -8,11 +8,11 @@ const gpio = rp2040.gpio; const clocks = rp2040.clocks; const usb = rp2040.usb; -const led = 25; -const uart_id = 0; +const led = gpio.num(25); +const uart = rp2040.uart.num(0); const baud_rate = 115200; -const uart_tx_pin = 0; -const uart_rx_pin = 1; +const uart_tx_pin = gpio.num(0); +const uart_rx_pin = gpio.num(1); // First we define two callbacks that will be used by the endpoints we define next... fn ep1_in_callback(dc: *usb.DeviceConfiguration, data: []const u8) void { @@ -153,12 +153,10 @@ pub const std_options = struct { }; pub fn main() !void { - gpio.reset(); - gpio.init(led); - gpio.set_direction(led, .out); - gpio.put(led, 1); + led.set_direction(.out); + led.put(1); - const uart = rp2040.uart.UART.init(uart_id, .{ + uart.apply(.{ .baud_rate = baud_rate, .tx_pin = uart_tx_pin, .rx_pin = uart_rx_pin, @@ -182,7 +180,7 @@ pub fn main() !void { new = time.get_time_since_boot().us_since_boot; if (new - old > 500000) { old = new; - gpio.toggle(led); + led.toggle(); } } } diff --git a/src/hal.zig b/src/hal.zig index c9ac986..89e2b58 100644 --- a/src/hal.zig +++ b/src/hal.zig @@ -3,21 +3,22 @@ const microzig = @import("microzig"); const SIO = microzig.chip.peripherals.SIO; pub const adc = @import("hal/adc.zig"); -pub const pins = @import("hal/pins.zig"); -pub const gpio = @import("hal/gpio.zig"); pub const clocks = @import("hal/clocks.zig"); +pub const dma = @import("hal/dma.zig"); +pub const flash = @import("hal/flash.zig"); +pub const gpio = @import("hal/gpio.zig"); +pub const irq = @import("hal/irq.zig"); pub const multicore = @import("hal/multicore.zig"); -pub const time = @import("hal/time.zig"); -pub const uart = @import("hal/uart.zig"); +pub const pins = @import("hal/pins.zig"); +pub const pio = @import("hal/pio.zig"); pub const pwm = @import("hal/pwm.zig"); -pub const spi = @import("hal/spi.zig"); +pub const rand = @import("hal/random.zig"); pub const resets = @import("hal/resets.zig"); -pub const irq = @import("hal/irq.zig"); pub const rom = @import("hal/rom.zig"); -pub const flash = @import("hal/flash.zig"); -pub const pio = @import("hal/pio.zig"); +pub const spi = @import("hal/spi.zig"); +pub const time = @import("hal/time.zig"); +pub const uart = @import("hal/uart.zig"); pub const usb = @import("hal/usb.zig"); -pub const rand = @import("hal/random.zig"); pub const clock_config = clocks.GlobalConfiguration.init(.{ .ref = .{ .source = .src_xosc }, @@ -32,7 +33,22 @@ pub const clock_config = clocks.GlobalConfiguration.init(.{ }); pub fn init() void { + // Reset all peripherals to put system into a known state, - except + // for QSPI pads and the XIP IO bank, as this is fatal if running from + // flash - and the PLLs, as this is fatal if clock muxing has not been + // reset on this boot - and USB, syscfg, as this disturbs USB-to-SWD + // on core 1 + resets.reset_block(resets.masks.init); + + // Remove reset from peripherals which are clocked only by clk_sys and + // clk_ref. Other peripherals stay in reset until we've configured + // clocks. + resets.unreset_block_wait(resets.masks.clocked_by_sys_and_ref); + clock_config.apply(); + + // Peripheral clocks should now all be running + resets.unreset_block_wait(resets.masks.all); } pub fn get_cpu_id() u32 { diff --git a/src/hal/adc.zig b/src/hal/adc.zig index ba293b0..2f6b96b 100644 --- a/src/hal/adc.zig +++ b/src/hal/adc.zig @@ -43,9 +43,9 @@ pub const Input = enum(u3) { switch (input) { .temperature_sensor => set_temp_sensor_enabled(true), else => { - const gpio_num = @as(u32, @enumToInt(input)) + 26; + const pin = gpio.num(@as(u5, @enumToInt(input)) + 26); + pin.set_function(.null); - gpio.set_function(gpio_num, .null); // TODO: implement these, otherwise adc isn't going to work. //gpio.disablePulls(gpio_num); //gpio.setInputEnabled(gpio_num, false); @@ -105,7 +105,6 @@ pub const InputMask = InputMask: { /// Initialize ADC hardware pub fn init() void { - resets.reset(&.{.adc}); ADC.CS.write(.{ .EN = 1, .TS_EN = 0, diff --git a/src/hal/dma.zig b/src/hal/dma.zig new file mode 100644 index 0000000..248e333 --- /dev/null +++ b/src/hal/dma.zig @@ -0,0 +1,131 @@ +const std = @import("std"); +const assert = std.debug.assert; + +const microzig = @import("microzig"); +const chip = microzig.chip; +const DMA = chip.peripherals.DMA; + +const hw = @import("hw.zig"); + +var claimed_channels: u12 = 0; + +pub const Dreq = enum(u6) { + uart0_tx = 20, + uart1_tx = 21, + _, +}; + +pub fn num(n: u4) Channel { + assert(n < 12); + + return @intToEnum(Channel, n); +} + +pub fn claim_unused_channel() ?Channel {} + +pub const Channel = enum(u4) { + _, + + /// panics if the channel is already claimed + pub fn claim(channel: Channel) void { + _ = channel; + @panic("TODO"); + } + + pub fn unclaim(channel: Channel) void { + _ = channel; + @panic("TODO"); + } + + pub fn is_claimed(channel: Channel) bool { + _ = channel; + @panic("TODO"); + } + + const Regs = extern struct { + read_addr: u32, + write_addr: u32, + trans_count: u32, + ctrl_trig: @TypeOf(DMA.CH0_CTRL_TRIG), + + // alias 1 + al1_ctrl: u32, + al1_read_addr: u32, + al1_write_addr: u32, + al1_trans_count: u32, + + // alias 2 + al2_ctrl: u32, + al2_read_addr: u32, + al2_write_addr: u32, + al2_trans_count: u32, + + // alias 3 + al3_ctrl: u32, + al3_read_addr: u32, + al3_write_addr: u32, + al3_trans_count: u32, + }; + + fn get_regs(channel: Channel) *volatile Regs { + const regs = @ptrCast(*volatile [12]Regs, &DMA.CH0_READ_ADDR); + return ®s[@enumToInt(channel)]; + } + + pub const TransferConfig = struct { + transfer_size_bytes: u3, + enable: bool, + read_increment: bool, + write_increment: bool, + dreq: Dreq, + + // TODO: + // chain to + // ring + // byte swapping + }; + + pub fn trigger_transfer( + channel: Channel, + write_addr: u32, + read_addr: u32, + count: u32, + config: TransferConfig, + ) void { + const regs = channel.get_regs(); + regs.read_addr = read_addr; + regs.write_addr = write_addr; + regs.trans_count = count; + regs.ctrl_trig.modify(.{ + .EN = @boolToInt(config.enable), + .DATA_SIZE = .{ + .value = .SIZE_BYTE, + }, + .INCR_READ = @boolToInt(config.read_increment), + .INCR_WRITE = @boolToInt(config.write_increment), + .TREQ_SEL = .{ + .raw = @enumToInt(config.dreq), + }, + }); + } + + pub fn set_irq0_enabled(channel: Channel, enabled: bool) void { + if (enabled) { + const inte0_set = hw.set_alias_raw(&DMA.INTE0); + inte0_set.* = @as(u32, 1) << @enumToInt(channel); + } else { + const inte0_clear = hw.clear_alias_raw(&DMA.INTE0); + inte0_clear.* = @as(u32, 1) << @enumToInt(channel); + } + } + + pub fn acknowledge_irq0(channel: Channel) void { + const ints0_set = hw.set_alias_raw(&DMA.INTS0); + ints0_set.* = @as(u32, 1) << @enumToInt(channel); + } + + pub fn is_busy(channel: Channel) bool { + const regs = channel.get_regs(); + return regs.ctrl_trig.read().BUSY == 1; + } +}; diff --git a/src/hal/gpio.zig b/src/hal/gpio.zig index c0b6bae..02f421e 100644 --- a/src/hal/gpio.zig +++ b/src/hal/gpio.zig @@ -63,92 +63,147 @@ pub const Enabled = enum { enabled, }; -pub inline fn reset() void { - resets.reset(&.{ .io_bank0, .pads_bank0 }); -} +pub const PullUpDown = enum { + up, + down, +}; + +pub fn num(n: u5) Pin { + if (n > 29) + @panic("the RP2040 only has GPIO 0-29"); -/// Initialize a GPIO, set func to SIO -pub inline fn init(comptime gpio: u32) void { - const mask = 1 << gpio; - SIO.GPIO_OE_CLR.raw = mask; - SIO.GPIO_OUT_CLR.raw = mask; - set_function(gpio, .sio); + return @intToEnum(Pin, n); } -/// Reset GPIO back to null function (disables it) -pub inline fn deinit(comptime gpio: u32) void { - set_function(gpio, .null); +pub fn mask(m: u32) Mask { + _ = m; + @panic("TODO"); } -pub const PullUpDown = enum { - up, - down, +pub const Mask = enum(u30) { + _, }; -pub inline fn set_pull(comptime gpio: u32, mode: ?PullUpDown) void { - const gpio_name = comptime std.fmt.comptimePrint("GPIO{d}", .{gpio}); - const gpio_regs = &@field(PADS_BANK0, gpio_name); +pub const Pin = enum(u5) { + _, + + pub const Regs = struct { + status: @TypeOf(IO_BANK0.GPIO0_STATUS), + ctrl: microzig.mmio.Mmio(packed struct(u32) { + FUNCSEL: packed union { + raw: u5, + value: Function, + }, + reserved8: u3, + OUTOVER: packed union { + raw: u2, + value: Override, + }, + reserved12: u2, + OEOVER: packed union { + raw: u2, + value: Override, + }, + reserved16: u2, + INOVER: packed union { + raw: u2, + value: Override, + }, + reserved28: u10, + IRQOVER: packed union { + raw: u2, + value: Override, + }, + padding: u2, + }), + }; + + pub const PadsReg = @TypeOf(PADS_BANK0.GPIO0); + + fn get_regs(gpio: Pin) *volatile Regs { + const regs = @ptrCast(*volatile [30]Regs, &IO_BANK0.GPIO0_STATUS); + return ®s[@enumToInt(gpio)]; + } - if (mode == null) { - gpio_regs.modify(.{ .PUE = 0, .PDE = 0 }); - } else switch (mode.?) { - .up => gpio_regs.modify(.{ .PUE = 1, .PDE = 0 }), - .down => gpio_regs.modify(.{ .PUE = 0, .PDE = 1 }), + fn get_pads_reg(gpio: Pin) *volatile PadsReg { + const regs = @ptrCast(*volatile [30]PadsReg, &PADS_BANK0.GPIO0); + return ®s[@enumToInt(gpio)]; } -} -pub inline fn set_direction(comptime gpio: u32, direction: Direction) void { - const mask = 1 << gpio; - switch (direction) { - .in => SIO.GPIO_OE_CLR.raw = mask, - .out => SIO.GPIO_OE_SET.raw = mask, + pub fn mask(gpio: Pin) u32 { + return @as(u32, 1) << @enumToInt(gpio); } -} -/// Drive a single GPIO high/low -pub inline fn put(comptime gpio: u32, value: u1) void { - std.log.debug("GPIO{} put: {}", .{ gpio, value }); - const mask = 1 << gpio; - switch (value) { - 0 => SIO.GPIO_OUT_CLR.raw = mask, - 1 => SIO.GPIO_OUT_SET.raw = mask, + pub inline fn set_pull(gpio: Pin, mode: ?PullUpDown) void { + const pads_reg = gpio.get_pads_reg(); + + if (mode == null) { + pads_reg.modify(.{ .PUE = 0, .PDE = 0 }); + } else switch (mode.?) { + .up => pads_reg.modify(.{ .PUE = 1, .PDE = 0 }), + .down => pads_reg.modify(.{ .PUE = 0, .PDE = 1 }), + } } -} -pub inline fn toggle(comptime gpio: u32) void { - SIO.GPIO_OUT_XOR.raw = (1 << gpio); -} + pub inline fn set_direction(gpio: Pin, direction: Direction) void { + switch (direction) { + .in => SIO.GPIO_OE_CLR.raw = gpio.mask(), + .out => SIO.GPIO_OE_SET.raw = gpio.mask(), + } + } -pub inline fn read(comptime gpio: u32) u1 { - const mask = 1 << gpio; - return if ((SIO.GPIO_IN.raw & mask) != 0) - 1 - else - 0; -} + /// Drive a single GPIO high/low + pub inline fn put(gpio: Pin, value: u1) void { + switch (value) { + 0 => SIO.GPIO_OUT_CLR.raw = gpio.mask(), + 1 => SIO.GPIO_OUT_SET.raw = gpio.mask(), + } + } -pub inline fn set_function(comptime gpio: u32, function: Function) void { - const pad_bank_reg = comptime std.fmt.comptimePrint("GPIO{}", .{gpio}); - @field(PADS_BANK0, pad_bank_reg).modify(.{ - .IE = 1, - .OD = 0, - }); - - const io_bank_reg = comptime std.fmt.comptimePrint("GPIO{}_CTRL", .{gpio}); - @field(IO_BANK0, io_bank_reg).write(.{ - .FUNCSEL = .{ .raw = @enumToInt(function) }, - .OUTOVER = .{ .value = .NORMAL }, - .INOVER = .{ .value = .NORMAL }, - .IRQOVER = .{ .value = .NORMAL }, - .OEOVER = .{ .value = .NORMAL }, - - .reserved8 = 0, - .reserved12 = 0, - .reserved16 = 0, - .reserved28 = 0, - .padding = 0, - }); -} + pub inline fn toggle(gpio: Pin) void { + SIO.GPIO_OUT_XOR.raw = gpio.mask(); + } + + pub inline fn read(gpio: Pin) u1 { + return if ((SIO.GPIO_IN.raw & gpio.mask()) != 0) + 1 + else + 0; + } + + pub inline fn set_function(gpio: Pin, function: Function) void { + const pads_reg = gpio.get_pads_reg(); + pads_reg.modify(.{ + .IE = 1, + .OD = 0, + }); + + const regs = gpio.get_regs(); + regs.ctrl.modify(.{ + .FUNCSEL = .{ .value = function }, + .OUTOVER = .{ .value = .normal }, + .INOVER = .{ .value = .normal }, + .IRQOVER = .{ .value = .normal }, + .OEOVER = .{ .value = .normal }, + + .reserved8 = 0, + .reserved12 = 0, + .reserved16 = 0, + .reserved28 = 0, + .padding = 0, + }); + } + + //pub fn set_drive_strength(gpio: Gpio, drive: DriveStrength) void { + // _ = drive; + // const pads_reg = gpio.get_pads_reg(); + // pads_reg.modify(.{ + // .DRIVE = .{ + // .value = .@"12mA", + // }, + // }); + //} +}; // setting both uplls enables a "bus keep" function, a weak pull to whatever // is current high/low state of GPIO @@ -165,7 +220,6 @@ pub inline fn set_function(comptime gpio: u32, function: Function) void { //pub fn setInputEnabled(gpio: u32, enabled: Enabled) void {} //pub fn setinputHysteresisEnabled(gpio: u32, enabled: Enabled) void {} //pub fn setSlewRate(gpio: u32, slew_rate: SlewRate) void {} -//pub fn setDriveStrength(gpio: u32, drive: DriveStrength) void {} + //pub fn setIrqEnabled(gpio: u32, events: IrqEvents) void {} //pub fn acknowledgeIrq(gpio: u32, events: IrqEvents) void {} - diff --git a/src/hal/hw.zig b/src/hal/hw.zig index a44aff1..1017c8a 100644 --- a/src/hal/hw.zig +++ b/src/hal/hw.zig @@ -1,11 +1,44 @@ +const std = @import("std"); +const assert = std.debug.assert; + pub const Lock = struct { impl: u32, pub fn claim() Lock { - + @panic("TODO"); } pub fn unlock(lock: Lock) void { - + _ = lock; + @panic("TODO"); } }; + +const rw_bits = @as(u32, 0x0) << 12; +const xor_bits = @as(u32, 0x1) << 12; +const set_bits = @as(u32, 0x2) << 12; +const clear_bits = @as(u32, 0x3) << 12; + +pub fn clear_alias_raw(ptr: anytype) *u32 { + return @intToPtr(*u32, @ptrToInt(ptr) | clear_bits); +} + +pub fn set_alias_raw(ptr: anytype) *u32 { + return @intToPtr(*u32, @ptrToInt(ptr) | set_bits); +} + +pub fn xor_alias_raw(ptr: anytype) *u32 { + return @intToPtr(*u32, @ptrToInt(ptr) | xor_bits); +} + +pub fn clear_alias(ptr: anytype) @TypeOf(ptr) { + return @intToPtr(@TypeOf(ptr), @ptrToInt(ptr) | clear_bits); +} + +pub fn set_alias(ptr: anytype) @TypeOf(ptr) { + return @intToPtr(@TypeOf(ptr), @ptrToInt(ptr) | set_bits); +} + +pub fn xor_alias(ptr: anytype) @TypeOf(ptr) { + return @intToPtr(@TypeOf(ptr), @ptrToInt(ptr) | xor_bits); +} diff --git a/src/hal/pins.zig b/src/hal/pins.zig index 3ff9246..a882df5 100644 --- a/src/hal/pins.zig +++ b/src/hal/pins.zig @@ -315,24 +315,24 @@ const function_table = [@typeInfo(Function).Enum.fields.len][30]u1{ pub fn GPIO(comptime num: u5, comptime direction: gpio.Direction) type { return switch (direction) { .in => struct { - const gpio_num = num; + const pin = gpio.num(num); pub inline fn read(self: @This()) u1 { _ = self; - return gpio.read(gpio_num); + return pin.read(); } }, .out => struct { - const gpio_num = num; + const pin = gpio.num(num); pub inline fn put(self: @This(), value: u1) void { _ = self; - gpio.put(gpio_num, value); + pin.put(value); } pub inline fn toggle(self: @This()) void { _ = self; - gpio.toggle(gpio_num); + pin.toggle(); } }, }; @@ -473,7 +473,6 @@ pub const GlobalConfiguration = struct { // TODO: ensure only one instance of an input function exists const used_gpios = comptime input_gpios | output_gpios; - gpio.reset(); if (used_gpios != 0) { SIO.GPIO_OE_CLR.raw = used_gpios; @@ -482,7 +481,7 @@ pub const GlobalConfiguration = struct { inline for (@typeInfo(GlobalConfiguration).Struct.fields) |field| { if (@field(config, field.name)) |pin_config| { - const gpio_num = @enumToInt(@field(Pin, field.name)); + const pin = gpio.num(@enumToInt(@field(Pin, field.name))); const func = pin_config.function; // xip = 0, @@ -496,17 +495,17 @@ pub const GlobalConfiguration = struct { // @"null" = 0x1f, if (func == .SIO) { - gpio.set_function(gpio_num, .sio); + pin.set_function(.sio); } else if (comptime func.is_pwm()) { - gpio.set_function(gpio_num, .pwm); + pin.set_function(.pwm); } else if (comptime func.is_adc()) { - gpio.set_function(gpio_num, .null); + pin.set_function(.null); } else if (comptime func.isUartTx() or func.isUartRx()) { - gpio.set_function(gpio_num, .uart); + pin.set_function(.uart); } else { @compileError(std.fmt.comptimePrint("Unimplemented pin function. Please implement setting pin function {s} for GPIO {}", .{ @tagName(func), - gpio_num, + @enumToInt(pin), })); } } @@ -527,10 +526,6 @@ pub const GlobalConfiguration = struct { }; } - if (has_pwm) { - resets.reset(&.{.pwm}); - } - if (has_adc) { adc.init(); } diff --git a/src/hal/pio.zig b/src/hal/pio.zig index 22dc5a3..2eb1709 100644 --- a/src/hal/pio.zig +++ b/src/hal/pio.zig @@ -8,6 +8,8 @@ const PIO0 = microzig.chip.peripherals.PIO0; const PIO1 = microzig.chip.peripherals.PIO1; const gpio = @import("gpio.zig"); +const resets = @import("resets.zig"); +const hw = @import("hw.zig"); const assembler = @import("pio/assembler.zig"); const encoder = @import("pio/assembler/encoder.zig"); @@ -29,6 +31,19 @@ pub const StateMachine = enum(u2) { sm1, sm2, sm3, + + pub const Regs = extern struct { + clkdiv: @TypeOf(PIO0.SM0_CLKDIV), + execctrl: @TypeOf(PIO0.SM0_EXECCTRL), + shiftctrl: @TypeOf(PIO0.SM0_SHIFTCTRL), + addr: @TypeOf(PIO0.SM0_ADDR), + instr: @TypeOf(PIO0.SM0_INSTR), + pinctrl: @TypeOf(PIO0.SM0_PINCTRL), + }; + + comptime { + assert(@sizeOf([2]Regs) == (4 * 6 * 2)); + } }; pub const Irq = enum { @@ -41,6 +56,10 @@ pub const Irq = enum { status: @TypeOf(PIO0.IRQ0_INTS), }; + comptime { + assert(@sizeOf([2]Regs) == (3 * 4 * 2)); + } + pub const Source = enum { rx_not_empty, tx_not_full, @@ -50,18 +69,9 @@ pub const Irq = enum { }; }; -pub const StateMachineRegs = extern struct { - clkdiv: @TypeOf(PIO0.SM0_CLKDIV), - execctrl: @TypeOf(PIO0.SM0_EXECCTRL), - shiftctrl: @TypeOf(PIO0.SM0_SHIFTCTRL), - addr: @TypeOf(PIO0.SM0_ADDR), - instr: @TypeOf(PIO0.SM0_INSTR), - pinctrl: @TypeOf(PIO0.SM0_PINCTRL), -}; - pub const ClkDivOptions = struct { - int: u16, - frac: u8, + int: u16 = 1, + frac: u8 = 0, pub fn from_float(div: f32) ClkDivOptions { const fixed = @floatToInt(u24, div * 256); @@ -73,18 +83,20 @@ pub const ClkDivOptions = struct { }; pub const ExecOptions = struct { - wrap: u5, - wrap_target: u5, - side_pindir: bool, - side_set_optional: bool, + wrap: u5 = 31, + wrap_target: u5 = 0, + side_pindir: bool = false, + side_set_optional: bool = false, }; pub const ShiftOptions = struct { autopush: bool = false, autopull: bool = false, - in_shiftdir: Direction = .left, - out_shiftdir: Direction = .left, + in_shiftdir: Direction = .right, + out_shiftdir: Direction = .right, + /// 0 means full 32-bits push_threshold: u5 = 0, + /// 0 means full 32-bits pull_threshold: u5 = 0, join_tx: bool = false, join_rx: bool = false, @@ -104,16 +116,16 @@ pub fn PinMapping(comptime Count: type) type { pub const PinMappingOptions = struct { out: PinMapping(u6) = .{}, - set: PinMapping(u3) = .{}, + set: PinMapping(u3) = .{ .count = 5 }, side_set: PinMapping(u3) = .{}, in_base: u5 = 0, }; pub const StateMachineInitOptions = struct { - clkdiv: ClkDivOptions, - exec: ExecOptions, - shift: ShiftOptions = .{}, + clkdiv: ClkDivOptions = .{}, pin_mappings: PinMappingOptions = .{}, + exec: ExecOptions = .{}, + shift: ShiftOptions = .{}, }; pub const LoadAndStartProgramOptions = struct { @@ -126,6 +138,13 @@ pub const Pio = enum(u1) { pio0 = 0, pio1 = 1, + pub fn reset(self: Pio) void { + switch (self) { + .pio0 => resets.reset(&.{.pio0}), + .pio1 => resets.reset(&.{.pio1}), + } + } + fn get_regs(self: Pio) *volatile PIO { return switch (self) { .pio0 => PIO0, @@ -138,8 +157,8 @@ pub const Pio = enum(u1) { return @ptrCast(*volatile [32]u32, ®s.INSTR_MEM0); } - pub fn gpio_init(self: Pio, comptime pin: u5) void { - gpio.set_function(pin, switch (self) { + pub fn gpio_init(self: Pio, pin: gpio.Pin) void { + pin.set_function(switch (self) { .pio0 => .pio0, .pio1 => .pio1, }); @@ -207,25 +226,19 @@ pub const Pio = enum(u1) { } else error.NoSpace; } - fn get_sm_regs(self: Pio, sm: StateMachine) *volatile StateMachineRegs { + fn get_sm_regs(self: Pio, sm: StateMachine) *volatile StateMachine.Regs { const pio_regs = self.get_regs(); - return switch (sm) { - .sm0 => @ptrCast(*volatile StateMachineRegs, &pio_regs.SM0_CLKDIV), - .sm1 => @ptrCast(*volatile StateMachineRegs, &pio_regs.SM1_CLKDIV), - .sm2 => @ptrCast(*volatile StateMachineRegs, &pio_regs.SM2_CLKDIV), - .sm3 => @ptrCast(*volatile StateMachineRegs, &pio_regs.SM3_CLKDIV), - }; + const sm_regs = @ptrCast(*volatile [4]StateMachine.Regs, &pio_regs.SM0_CLKDIV); + return &sm_regs[@enumToInt(sm)]; } fn get_irq_regs(self: Pio, irq: Irq) *volatile Irq.Regs { const pio_regs = self.get_regs(); - return switch (irq) { - .irq0 => @ptrCast(*volatile Irq.Regs, &pio_regs.IRQ0_INTE), - .irq1 => @ptrCast(*volatile Irq.Regs, &pio_regs.IRQ1_INTE), - }; + const irq_regs = @ptrCast(*volatile [2]Irq.Regs, &pio_regs.IRQ0_INTE); + return &irq_regs[@enumToInt(irq)]; } - pub inline fn sm_set_clkdiv(self: Pio, sm: StateMachine, options: ClkDivOptions) void { + pub fn sm_set_clkdiv(self: Pio, sm: StateMachine, options: ClkDivOptions) void { if (options.int == 0 and options.frac != 0) @panic("invalid params"); @@ -238,7 +251,7 @@ pub const Pio = enum(u1) { }); } - pub inline fn sm_set_exec_options(self: Pio, sm: StateMachine, options: ExecOptions) void { + pub fn sm_set_exec_options(self: Pio, sm: StateMachine, options: ExecOptions) void { const sm_regs = self.get_sm_regs(sm); sm_regs.execctrl.modify(.{ .WRAP_BOTTOM = options.wrap_target, @@ -257,11 +270,11 @@ pub const Pio = enum(u1) { }); } - pub inline fn sm_set_shift_options(self: Pio, sm: StateMachine, options: ShiftOptions) void { + pub fn sm_set_shift_options(self: Pio, sm: StateMachine, options: ShiftOptions) void { const sm_regs = self.get_sm_regs(sm); sm_regs.shiftctrl.write(.{ .AUTOPUSH = @boolToInt(options.autopush), - .AUTOPULL = @boolToInt(options.autopush), + .AUTOPULL = @boolToInt(options.autopull), .IN_SHIFTDIR = @enumToInt(options.in_shiftdir), .OUT_SHIFTDIR = @enumToInt(options.out_shiftdir), @@ -276,7 +289,7 @@ pub const Pio = enum(u1) { }); } - pub inline fn sm_set_pin_mappings(self: Pio, sm: StateMachine, options: PinMappingOptions) void { + pub fn sm_set_pin_mappings(self: Pio, sm: StateMachine, options: PinMappingOptions) void { const sm_regs = self.get_sm_regs(sm); sm_regs.pinctrl.modify(.{ .OUT_BASE = options.out.base, @@ -292,30 +305,32 @@ pub const Pio = enum(u1) { }); } - pub inline fn sm_is_tx_fifo_full(self: Pio, sm: StateMachine) bool { + pub fn sm_is_tx_fifo_full(self: Pio, sm: StateMachine) bool { const regs = self.get_regs(); const txfull = regs.FSTAT.read().TXFULL; return (txfull & (@as(u4, 1) << @enumToInt(sm))) != 0; } - pub inline fn sm_get_tx_fifo(self: Pio, sm: StateMachine) *volatile u32 { + pub fn sm_get_tx_fifo(self: Pio, sm: StateMachine) *volatile u32 { const regs = self.get_regs(); - return switch (sm) { - .sm0 => ®s.TXF0, - .sm1 => ®s.TXF1, - .sm2 => ®s.TXF2, - .sm3 => ®s.TXF3, - }; + const fifos = @ptrCast(*volatile [4]u32, ®s.TXF0); + return &fifos[@enumToInt(sm)]; } - pub inline fn sm_blocking_write(self: Pio, sm: StateMachine, value: u32) void { - while (self.sm_is_tx_fifo_full(sm)) {} - + /// this function writes to the TX FIFO without checking that it's + /// writable, if it's not then the value is ignored + pub fn sm_write(self: Pio, sm: StateMachine, value: u32) void { const fifo_ptr = self.sm_get_tx_fifo(sm); fifo_ptr.* = value; } - pub inline fn sm_set_enabled(self: Pio, sm: StateMachine, enabled: bool) void { + pub fn sm_blocking_write(self: Pio, sm: StateMachine, value: u32) void { + while (self.sm_is_tx_fifo_full(sm)) {} + + self.sm_write(sm, value); + } + + pub fn sm_set_enabled(self: Pio, sm: StateMachine, enabled: bool) void { const regs = self.get_regs(); var value = regs.CTRL.read(); @@ -327,7 +342,7 @@ pub const Pio = enum(u1) { regs.CTRL.write(value); } - inline fn sm_clear_debug(self: Pio, sm: StateMachine) void { + fn sm_clear_debug(self: Pio, sm: StateMachine) void { const regs = self.get_regs(); const mask: u4 = (@as(u4, 1) << @enumToInt(sm)); @@ -343,10 +358,22 @@ pub const Pio = enum(u1) { /// changing the state of fifos will clear them pub fn sm_clear_fifos(self: Pio, sm: StateMachine) void { const sm_regs = self.get_sm_regs(sm); - var shiftctrl = sm_regs.shiftctrl.read(); - shiftctrl.FJOIN_TX ^= 1; - shiftctrl.FJOIN_RX ^= 1; - sm_regs.shiftctrl.write(shiftctrl); + const xor_shiftctrl = hw.xor_alias(&sm_regs.shiftctrl); + const mask = .{ + .FJOIN_TX = 1, + .FJOIN_RX = 1, + + .AUTOPUSH = 0, + .AUTOPULL = 0, + .IN_SHIFTDIR = 0, + .OUT_SHIFTDIR = 0, + .PUSH_THRESH = 0, + .PULL_THRESH = 0, + .reserved16 = 0, + }; + + xor_shiftctrl.write(mask); + xor_shiftctrl.write(mask); } pub fn sm_fifo_level(self: Pio, sm: StateMachine, fifo: Fifo) u4 { @@ -362,14 +389,14 @@ pub const Pio = enum(u1) { return @truncate(u4, levels >> (@as(u5, 4) * num) + offset); } - inline fn interrupt_bit_pos( + fn interrupt_bit_pos( sm: StateMachine, source: Irq.Source, ) u5 { return (@as(u5, 4) * @enumToInt(source)) + @enumToInt(sm); } - pub inline fn sm_clear_interrupt( + pub fn sm_clear_interrupt( self: Pio, sm: StateMachine, irq: Irq, @@ -378,11 +405,11 @@ pub const Pio = enum(u1) { // TODO: why does the raw interrupt register no have irq1/0? _ = irq; const regs = self.get_regs(); - regs.INTR.raw &= ~(@as(u32, 1) << interrupt_bit_pos(sm, source)); + regs.IRQ.raw |= @as(u32, 1) << interrupt_bit_pos(sm, source); } // TODO: be able to disable an interrupt - pub inline fn sm_enable_interrupt( + pub fn sm_enable_interrupt( self: Pio, sm: StateMachine, irq: Irq, @@ -392,7 +419,7 @@ pub const Pio = enum(u1) { irq_regs.enable.raw |= @as(u32, 1) << interrupt_bit_pos(sm, source); } - pub inline fn sm_restart(self: Pio, sm: StateMachine) void { + pub fn sm_restart(self: Pio, sm: StateMachine) void { const mask: u4 = (@as(u4, 1) << @enumToInt(sm)); const regs = self.get_regs(); regs.CTRL.modify(.{ @@ -400,7 +427,7 @@ pub const Pio = enum(u1) { }); } - pub inline fn sm_clkdiv_restart(self: Pio, sm: StateMachine) void { + pub fn sm_clkdiv_restart(self: Pio, sm: StateMachine) void { const mask: u4 = (@as(u4, 1) << @enumToInt(sm)); const regs = self.get_regs(); regs.CTRL.modify(.{ @@ -416,12 +443,11 @@ pub const Pio = enum(u1) { ) void { // Halt the machine, set some sensible defaults self.sm_set_enabled(sm, false); - self.sm_set_pin_mappings(sm, options.pin_mappings); self.sm_set_clkdiv(sm, options.clkdiv); self.sm_set_exec_options(sm, options.exec); self.sm_set_shift_options(sm, options.shift); + self.sm_set_pin_mappings(sm, options.pin_mappings); - //self.set_config(sm, config); self.sm_clear_fifos(sm); self.sm_clear_debug(sm); @@ -480,7 +506,7 @@ pub const Pio = enum(u1) { offset, .side_pindir = if (program.side_set) |side_set| - side_set.pindirs + side_set.pindir else false, diff --git a/src/hal/pio/assembler.zig b/src/hal/pio/assembler.zig index af4153a..3cde6ee 100644 --- a/src/hal/pio/assembler.zig +++ b/src/hal/pio/assembler.zig @@ -121,12 +121,12 @@ fn format_compile_error(comptime message: []const u8, comptime source: []const u }); } -pub fn assemble(comptime source: []const u8, comptime options: AssembleOptions) !Output { +pub fn assemble(comptime source: []const u8, comptime options: AssembleOptions) Output { var diags: ?Diagnostics = null; return assemble_impl(source, &diags, options) catch |err| if (diags) |d| @compileError(format_compile_error(d.message.slice(), source, d.index)) else - err; + @compileError(err); } test "tokenizer and encoder" { diff --git a/src/hal/pio/assembler/encoder.zig b/src/hal/pio/assembler/encoder.zig index a562575..e0bc74c 100644 --- a/src/hal/pio/assembler/encoder.zig +++ b/src/hal/pio/assembler/encoder.zig @@ -27,7 +27,7 @@ pub fn encode( pub const SideSet = struct { count: u3, optional: bool, - pindirs: bool, + pindir: bool, }; pub const Define = struct { @@ -76,15 +76,20 @@ pub fn Encoder(comptime options: Options) type { wrap: ?u5, pub fn to_exported_program(comptime bounded: BoundedProgram) assembler.Program { + comptime var program_name: [bounded.name.len]u8 = undefined; + std.mem.copy(u8, &program_name, bounded.name); return assembler.Program{ - .name = bounded.name, + .name = &program_name, .defines = blk: { var tmp = std.BoundedArray(assembler.Define, options.max_defines).init(0) catch unreachable; - for (bounded.defines.slice()) |define| + for (bounded.defines.slice()) |define| { + comptime var define_name: [define.name.len]u8 = undefined; + std.mem.copy(u8, &define_name, define.name); tmp.append(.{ - .name = define.name, + .name = &define_name, .value = @intCast(i64, define.value), }) catch unreachable; + } break :blk tmp.slice(); }, @@ -281,7 +286,7 @@ pub fn Encoder(comptime options: Options) type { program.side_set = .{ .count = try self.evaluate(u3, program.*, side_set.count, token.index, diags), .optional = side_set.opt, - .pindirs = side_set.pindirs, + .pindir = side_set.pindir, }; self.consume(1); }, @@ -823,7 +828,7 @@ test "encode.side_set.pindirs" { const program = output.programs.get(0); try expectEqual(@as(?u5, 1), program.side_set.?.count); - try expect(program.side_set.?.pindirs); + try expect(program.side_set.?.pindir); } test "encode.label" { diff --git a/src/hal/pio/assembler/tokenizer.zig b/src/hal/pio/assembler/tokenizer.zig index 62e4c0e..29c596d 100644 --- a/src/hal/pio/assembler/tokenizer.zig +++ b/src/hal/pio/assembler/tokenizer.zig @@ -439,7 +439,7 @@ pub const Tokenizer = struct { .side_set = .{ .count = count, .opt = opt, - .pindirs = pindirs, + .pindir = pindirs, }, }, }; @@ -1129,7 +1129,7 @@ pub const Token = struct { pub const SideSet = struct { count: Value, opt: bool = false, - pindirs: bool = false, + pindir: bool = false, }; pub const LangOpt = struct { @@ -1191,7 +1191,7 @@ fn expect_side_set(expected: Token.SideSet, actual: Token) !void { const side_set = actual.data.side_set; try expect_value(expected.count, side_set.count); try expectEqual(expected.opt, side_set.opt); - try expectEqual(expected.pindirs, side_set.pindirs); + try expectEqual(expected.pindir, side_set.pindir); } fn expect_wrap_target(actual: Token) !void { @@ -1538,7 +1538,7 @@ test "tokenize.directive.side_set.opt" { test "tokenize.directive.side_set.pindirs" { const tokens = try bounded_tokenize(".side_set 1 pindirs"); - try expect_side_set(.{ .count = .{ .integer = 1 }, .pindirs = true }, tokens.get(0)); + try expect_side_set(.{ .count = .{ .integer = 1 }, .pindir = true }, tokens.get(0)); } test "tokenize.directive.wrap_target" { diff --git a/src/hal/pll.zig b/src/hal/pll.zig index 62fd9ec..3757049 100644 --- a/src/hal/pll.zig +++ b/src/hal/pll.zig @@ -19,7 +19,7 @@ pub const Configuration = struct { } }; -pub const PLL = enum { +pub const PLL = enum(u1) { sys, usb, diff --git a/src/hal/resets.zig b/src/hal/resets.zig index 218e6b4..f25d550 100644 --- a/src/hal/resets.zig +++ b/src/hal/resets.zig @@ -3,42 +3,39 @@ const EnumField = std.builtin.Type.EnumField; const microzig = @import("microzig"); const RESETS = microzig.chip.peripherals.RESETS; -const Mask = @TypeOf(RESETS.RESET).underlying_type; - -pub const Module = enum { - adc, - busctrl, - dma, - i2c0, - i2c1, - io_bank0, - io_qspi, - jtag, - pads_bank0, - pads_qspi, - pio0, - pio1, - pll_sys, - pll_usb, - pwm, - rtc, - spi0, - spi1, - syscfg, - sysinfo, - tbman, - timer, - uart0, - uart1, - usbctrl, -}; -pub inline fn reset(comptime modules: []const Module) void { - comptime var mask = std.mem.zeroes(Mask); +const hw = @import("hw.zig"); - inline for (modules) |module| - @field(mask, @tagName(module)) = 1; +pub const Mask = packed struct(u32) { + adc: bool = false, + busctrl: bool = false, + dma: bool = false, + i2c0: bool = false, + i2c1: bool = false, + io_bank0: bool = false, + io_qspi: bool = false, + jtag: bool = false, + pads_bank0: bool = false, + pads_qspi: bool = false, + pio0: bool = false, + pio1: bool = false, + pll_sys: bool = false, + pll_usb: bool = false, + pwm: bool = false, + rtc: bool = false, + spi0: bool = false, + spi1: bool = false, + syscfg: bool = false, + sysinfo: bool = false, + tbman: bool = false, + timer: bool = false, + uart0: bool = false, + uart1: bool = false, + usbctrl: bool = false, + padding: u7 = 0, +}; +pub fn reset(mask: Mask) void { const raw_mask = @bitCast(u32, mask); RESETS.RESET.raw = raw_mask; @@ -46,3 +43,90 @@ pub inline fn reset(comptime modules: []const Module) void { while ((RESETS.RESET_DONE.raw & raw_mask) != raw_mask) {} } + +pub fn reset_block(mask: Mask) void { + hw.set_alias_raw(&RESETS.RESET).* = @bitCast(u32, mask); +} + +pub fn unreset_block(mask: Mask) void { + hw.clear_alias_raw(&RESETS.RESET).* = @bitCast(u32, mask); +} + +pub fn unreset_block_wait(mask: Mask) void { + const raw_mask = @bitCast(u32, mask); + hw.clear_alias_raw(&RESETS.RESET).* = raw_mask; + while (RESETS.RESET_DONE.raw & raw_mask != raw_mask) {} +} + +pub const masks = struct { + pub const init = Mask{ + .adc = true, + .busctrl = true, + .dma = true, + .i2c0 = true, + .i2c1 = true, + .io_bank0 = true, + .jtag = true, + .pads_bank0 = true, + .pio0 = true, + .pio1 = true, + .pwm = true, + .rtc = true, + .spi0 = true, + .spi1 = true, + .sysinfo = true, + .tbman = true, + .timer = true, + .uart0 = true, + .uart1 = true, + }; + + pub const all = Mask{ + .adc = true, + .busctrl = true, + .dma = true, + .i2c0 = true, + .i2c1 = true, + .io_bank0 = true, + .io_qspi = true, + .jtag = true, + .pads_bank0 = true, + .pads_qspi = true, + .pio0 = true, + .pio1 = true, + .pll_sys = true, + .pll_usb = true, + .pwm = true, + .rtc = true, + .spi0 = true, + .spi1 = true, + .syscfg = true, + .sysinfo = true, + .tbman = true, + .timer = true, + .uart0 = true, + .uart1 = true, + .usbctrl = true, + }; + + pub const clocked_by_sys_and_ref = Mask{ + .busctrl = true, + .dma = true, + .i2c0 = true, + .i2c1 = true, + .io_bank0 = true, + .io_qspi = true, + .jtag = true, + .pads_bank0 = true, + .pads_qspi = true, + .pio0 = true, + .pio1 = true, + .pll_sys = true, + .pll_usb = true, + .pwm = true, + .syscfg = true, + .sysinfo = true, + .tbman = true, + .timer = true, + }; +}; diff --git a/src/hal/spi.zig b/src/hal/spi.zig index 002ccc4..7170600 100644 --- a/src/hal/spi.zig +++ b/src/hal/spi.zig @@ -14,40 +14,28 @@ const SpiRegs = microzig.chip.types.peripherals.SPI0; pub const Config = struct { clock_config: clocks.GlobalConfiguration, - tx_pin: ?u32 = 19, - rx_pin: ?u32 = 16, - sck_pin: ?u32 = 18, - csn_pin: ?u32 = 17, + tx_pin: ?gpio.Pin = gpio.num(19), + rx_pin: ?gpio.Pin = gpio.num(16), + sck_pin: ?gpio.Pin = gpio.num(18), + csn_pin: ?gpio.Pin = gpio.num(17), baud_rate: u32 = 1000 * 1000, }; -pub const SPI = enum { - spi0, - spi1, +pub fn num(n: u1) SPI { + return @intToEnum(SPI, n); +} + +pub const SPI = enum(u1) { + _, fn get_regs(spi: SPI) *volatile SpiRegs { - return switch (spi) { - .spi0 => SPI0, - .spi1 => SPI1, + return switch (@enumToInt(spi)) { + 0 => SPI0, + 1 => SPI1, }; } - pub fn reset(spi: SPI) void { - switch (spi) { - .spi0 => resets.reset(&.{.spi0}), - .spi1 => resets.reset(&.{.spi1}), - } - } - - pub fn init(comptime id: u32, comptime config: Config) SPI { - const spi: SPI = switch (id) { - 0 => .spi0, - 1 => .spi1, - else => @compileError("there is only spi0 and spi1"), - }; - - spi.reset(); - + pub fn apply(spi: SPI, comptime config: Config) void { const peri_freq = config.clock_config.peri.?.output_freq; _ = spi.set_baudrate(config.baud_rate, peri_freq); @@ -71,12 +59,10 @@ pub const SPI = enum { .SSE = 1, }); - if (config.tx_pin) |pin| gpio.set_function(pin, .spi); - if (config.rx_pin) |pin| gpio.set_function(pin, .spi); - if (config.sck_pin) |pin| gpio.set_function(pin, .spi); - if (config.csn_pin) |pin| gpio.set_function(pin, .spi); - - return spi; + if (config.tx_pin) |pin| pin.set_function(.spi); + if (config.rx_pin) |pin| pin.set_function(.spi); + if (config.sck_pin) |pin| pin.set_function(.spi); + if (config.csn_pin) |pin| pin.set_function(.spi); } pub inline fn is_writable(spi: SPI) bool { diff --git a/src/hal/uart.zig b/src/hal/uart.zig index f4c72c5..6a08b85 100644 --- a/src/hal/uart.zig +++ b/src/hal/uart.zig @@ -8,6 +8,7 @@ const gpio = @import("gpio.zig"); const clocks = @import("clocks.zig"); const resets = @import("resets.zig"); const time = @import("time.zig"); +const dma = @import("dma.zig"); const assert = std.debug.assert; @@ -33,17 +34,20 @@ pub const Parity = enum { pub const Config = struct { clock_config: clocks.GlobalConfiguration, - tx_pin: ?u32 = null, - rx_pin: ?u32 = null, + tx_pin: ?gpio.Pin = null, + rx_pin: ?gpio.Pin = null, baud_rate: u32, word_bits: WordBits = .eight, stop_bits: StopBits = .one, parity: Parity = .none, }; -pub const UART = enum { - uart0, - uart1, +pub fn num(n: u1) UART { + return @intToEnum(UART, n); +} + +pub const UART = enum(u1) { + _, const WriteError = error{}; const ReadError = error{}; @@ -59,23 +63,15 @@ pub const UART = enum { } fn get_regs(uart: UART) *volatile UartRegs { - return switch (uart) { - .uart0 => UART0, - .uart1 => UART1, + return switch (@enumToInt(uart)) { + 0 => UART0, + 1 => UART1, }; } - pub fn init(comptime id: u32, comptime config: Config) UART { - const uart: UART = switch (id) { - 0 => .uart0, - 1 => .uart1, - else => @compileError("there is only uart0 and uart1"), - }; - + pub fn apply(uart: UART, comptime config: Config) void { assert(config.baud_rate > 0); - uart.reset(); - const uart_regs = uart.get_regs(); const peri_freq = config.clock_config.peri.?.output_freq; uart.set_baudrate(config.baud_rate, peri_freq); @@ -96,10 +92,8 @@ pub const UART = enum { }); // TODO comptime assertions - if (config.tx_pin) |tx_pin| gpio.set_function(tx_pin, .uart); - if (config.rx_pin) |rx_pin| gpio.set_function(rx_pin, .uart); - - return uart; + if (config.tx_pin) |tx_pin| tx_pin.set_function(.uart); + if (config.rx_pin) |rx_pin| rx_pin.set_function(.uart); } pub fn is_readable(uart: UART) bool { @@ -122,6 +116,18 @@ pub const UART = enum { return payload.len; } + pub fn tx_fifo(uart: UART) *volatile u32 { + const regs = uart.get_regs(); + return @ptrCast(*volatile u32, ®s.UARTDR); + } + + pub fn dreq_tx(uart: UART) dma.Dreq { + return switch (@enumToInt(uart)) { + 0 => .uart0_tx, + 1 => .uart1_tx, + }; + } + pub fn read(uart: UART, buffer: []u8) ReadError!usize { const uart_regs = uart.get_regs(); for (buffer) |*byte| { @@ -141,13 +147,6 @@ pub const UART = enum { return uart_regs.UARTDR.read().DATA; } - pub fn reset(uart: UART) void { - switch (uart) { - .uart0 => resets.reset(&.{.uart0}), - .uart1 => resets.reset(&.{.uart1}), - } - } - pub fn set_format( uart: UART, word_bits: WordBits, diff --git a/src/hal/usb.zig b/src/hal/usb.zig index 48538a4..e2147f5 100644 --- a/src/hal/usb.zig +++ b/src/hal/usb.zig @@ -130,7 +130,7 @@ pub const F = struct { // clock. // // PLL_USB out of reset - resets.reset(&.{.pll_usb}); + resets.reset(.{ .pll_usb = true }); // Configure it: // // RFDIV = 1 @@ -154,7 +154,7 @@ pub const F = struct { pub fn usb_init_device(device_config: *usb.DeviceConfiguration) void { // Bring USB out of reset - resets.reset(&.{.usbctrl}); + resets.reset(.{ .usbctrl = true }); // Clear the control portion of DPRAM. This may not be necessary -- the // datasheet is ambiguous -- but the C examples do it, and so do we. From f343617ca44ff2e750de273497663798b8a4afaa Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Wed, 3 May 2023 21:40:42 -0700 Subject: [PATCH 52/74] update microzig (#52) Co-authored-by: mattnite --- deps/microzig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/microzig b/deps/microzig index b5edf6d..4e62e99 160000 --- a/deps/microzig +++ b/deps/microzig @@ -1 +1 @@ -Subproject commit b5edf6da6b540215f03689c3cc07d00478255f7d +Subproject commit 4e62e99e3cf8ad2b8805bc6138c53995bd9745be From c74f6f06348773594e6311cdff0411298cfce578 Mon Sep 17 00:00:00 2001 From: joelpaulkoch <64319336+joelpaulkoch@users.noreply.github.com> Date: Mon, 15 May 2023 04:48:21 +0200 Subject: [PATCH 53/74] Fix: call renamed is_uart functions (#55) --- src/hal/pins.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hal/pins.zig b/src/hal/pins.zig index a882df5..1746409 100644 --- a/src/hal/pins.zig +++ b/src/hal/pins.zig @@ -500,7 +500,7 @@ pub const GlobalConfiguration = struct { pin.set_function(.pwm); } else if (comptime func.is_adc()) { pin.set_function(.null); - } else if (comptime func.isUartTx() or func.isUartRx()) { + } else if (comptime func.is_uart_tx() or func.is_uart_rx()) { pin.set_function(.uart); } else { @compileError(std.fmt.comptimePrint("Unimplemented pin function. Please implement setting pin function {s} for GPIO {}", .{ From 81142fdfc0acc47a801866e99d14df15a0440f19 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Mon, 15 May 2023 21:47:43 -0700 Subject: [PATCH 54/74] update microzig (#56) Co-authored-by: mattnite --- deps/microzig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/microzig b/deps/microzig index 4e62e99..9588941 160000 --- a/deps/microzig +++ b/deps/microzig @@ -1 +1 @@ -Subproject commit 4e62e99e3cf8ad2b8805bc6138c53995bd9745be +Subproject commit 95889419155b7ffb1b11055549540096eaa2a6c5 From ed12908afc6c54973b4d7fe8d0725c1e0eba57a2 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Mon, 15 May 2023 22:37:10 -0700 Subject: [PATCH 55/74] turn on PIO comparison tests (#58) --- src/hal/pio/assembler.zig | 2 +- src/hal/pio/assembler/comparison_tests.zig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hal/pio/assembler.zig b/src/hal/pio/assembler.zig index 3cde6ee..1c38816 100644 --- a/src/hal/pio/assembler.zig +++ b/src/hal/pio/assembler.zig @@ -136,5 +136,5 @@ test "tokenizer and encoder" { } test "comparison" { - //std.testing.refAllDecls(@import("assembler/comparison_tests.zig")); + std.testing.refAllDecls(@import("assembler/comparison_tests.zig")); } diff --git a/src/hal/pio/assembler/comparison_tests.zig b/src/hal/pio/assembler/comparison_tests.zig index 4a39465..5a98c93 100644 --- a/src/hal/pio/assembler/comparison_tests.zig +++ b/src/hal/pio/assembler/comparison_tests.zig @@ -31,7 +31,7 @@ const c = @cImport({ }); fn pio_comparison(comptime source: []const u8) !void { - const output = comptime assembler.assemble(source, .{}) catch unreachable; + const output = comptime assembler.assemble(source, .{}); try std.testing.expect(output.programs.len > 0); inline for (output.programs) |program| { From d05e8779b8d3d722540cb21af0a81a3826d46efb Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Mon, 15 May 2023 22:37:20 -0700 Subject: [PATCH 56/74] workaround for compiler bug where volatile is not propagated over a field access (#57) --- src/hal/resets.zig | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/hal/resets.zig b/src/hal/resets.zig index f25d550..a35ad79 100644 --- a/src/hal/resets.zig +++ b/src/hal/resets.zig @@ -44,18 +44,23 @@ pub fn reset(mask: Mask) void { while ((RESETS.RESET_DONE.raw & raw_mask) != raw_mask) {} } -pub fn reset_block(mask: Mask) void { +pub inline fn reset_block(mask: Mask) void { hw.set_alias_raw(&RESETS.RESET).* = @bitCast(u32, mask); } -pub fn unreset_block(mask: Mask) void { +pub inline fn unreset_block(mask: Mask) void { hw.clear_alias_raw(&RESETS.RESET).* = @bitCast(u32, mask); } pub fn unreset_block_wait(mask: Mask) void { const raw_mask = @bitCast(u32, mask); hw.clear_alias_raw(&RESETS.RESET).* = raw_mask; - while (RESETS.RESET_DONE.raw & raw_mask != raw_mask) {} + + // have to bitcast after a read() instead of `RESETS.RESET_DONE.raw` due to + // some optimization bug. While loops will not be optimzed away if the + // condition has side effects like dereferencing a volatile pointer. + // It seems that volatile is not propagating correctly. + while (@bitCast(u32, RESETS.RESET_DONE.read()) & raw_mask != raw_mask) {} } pub const masks = struct { From a2ccaff13fb971524bb9d4f54ec204413d6f2956 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Mon, 15 May 2023 22:50:34 -0700 Subject: [PATCH 57/74] improve GPIO API (#59) --- src/hal/adc.zig | 5 ++- src/hal/clocks.zig | 1 - src/hal/gpio.zig | 79 ++++++++++++++++++++++++++-------------------- src/hal/hw.zig | 16 ++++++---- src/hal/pins.zig | 2 +- src/hal/spi.zig | 6 ++-- src/hal/util.zig | 18 ----------- 7 files changed, 60 insertions(+), 67 deletions(-) delete mode 100644 src/hal/util.zig diff --git a/src/hal/adc.zig b/src/hal/adc.zig index 2f6b96b..a77b102 100644 --- a/src/hal/adc.zig +++ b/src/hal/adc.zig @@ -5,9 +5,8 @@ const assert = std.debug.assert; const microzig = @import("microzig"); const ADC = microzig.chip.peripherals.ADC; -const rp2040 = microzig.hal; -const gpio = rp2040.gpio; -const resets = rp2040.resets; +const gpio = @import("gpio.zig"); +const resets = @import("resets.zig"); pub const temperature_sensor = struct { pub inline fn init() void { diff --git a/src/hal/clocks.zig b/src/hal/clocks.zig index 4a49809..b13ebd3 100644 --- a/src/hal/clocks.zig +++ b/src/hal/clocks.zig @@ -1,7 +1,6 @@ const std = @import("std"); const pll = @import("pll.zig"); -const util = @import("util.zig"); const assert = std.debug.assert; // TODO: remove diff --git a/src/hal/gpio.zig b/src/hal/gpio.zig index 02f421e..53d3b0b 100644 --- a/src/hal/gpio.zig +++ b/src/hal/gpio.zig @@ -63,7 +63,7 @@ pub const Enabled = enum { enabled, }; -pub const PullUpDown = enum { +pub const Pull = enum { up, down, }; @@ -76,12 +76,45 @@ pub fn num(n: u5) Pin { } pub fn mask(m: u32) Mask { - _ = m; - @panic("TODO"); + return @intToEnum(Mask, m); } pub const Mask = enum(u30) { _, + + pub fn set_function(self: Mask, function: Function) void { + const raw_mask = @enumToInt(self); + for (0..@bitSizeOf(Mask)) |i| { + const bit = @intCast(u5, i); + if (0 != raw_mask & (@as(u32, 1) << bit)) + num(bit).set_function(function); + } + } + + pub fn set_direction(self: Mask, direction: Direction) void { + const raw_mask = @enumToInt(self); + switch (direction) { + .out => SIO.GPIO_OE_SET.raw = raw_mask, + .in => SIO.GPIO_OE_CLR.raw = raw_mask, + } + } + + pub fn set_pull(self: Mask, pull: ?Pull) void { + const raw_mask = @enumToInt(self); + for (0..@bitSizeOf(Mask)) |i| { + const bit = @intCast(u5, i); + if (0 != raw_mask & (@as(u32, 1) << bit)) + num(bit).set_pull(pull); + } + } + + pub fn put(self: Mask, value: u32) void { + SIO.GPIO_OUT_XOR.raw = (SIO.GPIO_OUT.raw ^ value) & @enumToInt(self); + } + + pub fn read(self: Mask) u32 { + return SIO.GPIO_IN.raw & @enumToInt(self); + } }; pub const Pin = enum(u5) { @@ -134,12 +167,12 @@ pub const Pin = enum(u5) { return @as(u32, 1) << @enumToInt(gpio); } - pub inline fn set_pull(gpio: Pin, mode: ?PullUpDown) void { + pub inline fn set_pull(gpio: Pin, pull: ?Pull) void { const pads_reg = gpio.get_pads_reg(); - if (mode == null) { + if (pull == null) { pads_reg.modify(.{ .PUE = 0, .PDE = 0 }); - } else switch (mode.?) { + } else switch (pull.?) { .up => pads_reg.modify(.{ .PUE = 1, .PDE = 0 }), .down => pads_reg.modify(.{ .PUE = 0, .PDE = 1 }), } @@ -171,6 +204,11 @@ pub const Pin = enum(u5) { 0; } + pub inline fn set_input_enabled(pin: Pin, enabled: bool) void { + const pads_reg = pin.get_pads_reg(); + pads_reg.modify(.{ .IE = @boolToInt(enabled) }); + } + pub inline fn set_function(gpio: Pin, function: Function) void { const pads_reg = gpio.get_pads_reg(); pads_reg.modify(.{ @@ -193,33 +231,4 @@ pub const Pin = enum(u5) { .padding = 0, }); } - - //pub fn set_drive_strength(gpio: Gpio, drive: DriveStrength) void { - // _ = drive; - // const pads_reg = gpio.get_pads_reg(); - // pads_reg.modify(.{ - // .DRIVE = .{ - // .value = .@"12mA", - // }, - // }); - //} }; - -// setting both uplls enables a "bus keep" function, a weak pull to whatever -// is current high/low state of GPIO -//pub fn setPulls(gpio: u32, up: bool, down: bool) void {} -// -//pub fn pullUp(gpio: u32) void {} -// -//pub fn pullDown(gpio: u32) void {} -//pub fn disablePulls(gpio: u32) void {} -//pub fn setIrqOver(gpio: u32, value: u32) void {} -//pub fn setOutOver(gpio: u32, value: u32) void {} -//pub fn setInOver(gpio: u32, value: u32) void {} -//pub fn setOeOver(gpio: u32, value: u32) void {} -//pub fn setInputEnabled(gpio: u32, enabled: Enabled) void {} -//pub fn setinputHysteresisEnabled(gpio: u32, enabled: Enabled) void {} -//pub fn setSlewRate(gpio: u32, slew_rate: SlewRate) void {} - -//pub fn setIrqEnabled(gpio: u32, events: IrqEvents) void {} -//pub fn acknowledgeIrq(gpio: u32, events: IrqEvents) void {} diff --git a/src/hal/hw.zig b/src/hal/hw.zig index 1017c8a..89aee45 100644 --- a/src/hal/hw.zig +++ b/src/hal/hw.zig @@ -19,16 +19,16 @@ const xor_bits = @as(u32, 0x1) << 12; const set_bits = @as(u32, 0x2) << 12; const clear_bits = @as(u32, 0x3) << 12; -pub fn clear_alias_raw(ptr: anytype) *u32 { - return @intToPtr(*u32, @ptrToInt(ptr) | clear_bits); +pub fn clear_alias_raw(ptr: anytype) *volatile u32 { + return @intToPtr(*volatile u32, @ptrToInt(ptr) | clear_bits); } -pub fn set_alias_raw(ptr: anytype) *u32 { - return @intToPtr(*u32, @ptrToInt(ptr) | set_bits); +pub fn set_alias_raw(ptr: anytype) *volatile u32 { + return @intToPtr(*volatile u32, @ptrToInt(ptr) | set_bits); } -pub fn xor_alias_raw(ptr: anytype) *u32 { - return @intToPtr(*u32, @ptrToInt(ptr) | xor_bits); +pub fn xor_alias_raw(ptr: anytype) *volatile u32 { + return @intToPtr(*volatile u32, @ptrToInt(ptr) | xor_bits); } pub fn clear_alias(ptr: anytype) @TypeOf(ptr) { @@ -42,3 +42,7 @@ pub fn set_alias(ptr: anytype) @TypeOf(ptr) { pub fn xor_alias(ptr: anytype) @TypeOf(ptr) { return @intToPtr(@TypeOf(ptr), @ptrToInt(ptr) | xor_bits); } + +pub inline fn tight_loop_contents() void { + asm volatile ("" ::: "memory"); +} diff --git a/src/hal/pins.zig b/src/hal/pins.zig index 1746409..f232092 100644 --- a/src/hal/pins.zig +++ b/src/hal/pins.zig @@ -48,7 +48,7 @@ pub const Pin = enum { function: Function = .SIO, direction: ?gpio.Direction = null, drive_strength: ?gpio.DriveStrength = null, - pull: ?gpio.PullUpDown = null, + pull: ?gpio.Pull = null, slew_rate: ?gpio.SlewRate = null, // input/output enable // schmitt trigger diff --git a/src/hal/spi.zig b/src/hal/spi.zig index 7170600..ee02131 100644 --- a/src/hal/spi.zig +++ b/src/hal/spi.zig @@ -8,7 +8,7 @@ const gpio = @import("gpio.zig"); const clocks = @import("clocks.zig"); const resets = @import("resets.zig"); const time = @import("time.zig"); -const util = @import("util.zig"); +const hw = @import("hw.zig"); const SpiRegs = microzig.chip.types.peripherals.SPI0; @@ -101,7 +101,7 @@ pub const SPI = enum(u1) { // push-on-full, but continues shifting. Safe if SSPIMSC_RORIM is not set. for (src) |s| { while (!spi.is_writable()) { - util.tight_loop_contents(); + hw.tight_loop_contents(); } spi_regs.SSPDR.write_raw(s); } @@ -111,7 +111,7 @@ pub const SPI = enum(u1) { _ = spi_regs.SSPDR.read(); } while (spi_regs.SSPSR.read().BSY == 1) { - util.tight_loop_contents(); + hw.tight_loop_contents(); } while (spi.is_readable()) { _ = spi_regs.SSPDR.read(); diff --git a/src/hal/util.zig b/src/hal/util.zig deleted file mode 100644 index 4f0d71c..0000000 --- a/src/hal/util.zig +++ /dev/null @@ -1,18 +0,0 @@ -pub fn xor_alias(ptr: anytype) @TypeOf(ptr) { - const xor_addr = @ptrToInt(ptr) | (1 << 12); - return @ptrCast(@TypeOf(ptr), xor_addr); -} - -pub fn set_alias(ptr: anytype) @TypeOf(ptr) { - const set_addr = @ptrToInt(ptr) | (2 << 12); - return @ptrCast(@TypeOf(ptr), set_addr); -} - -pub fn clear_alias(ptr: anytype) @TypeOf(ptr) { - const clear_addr = @ptrToInt(ptr) | (3 << 12); - return @ptrCast(@TypeOf(ptr), clear_addr); -} - -pub inline fn tight_loop_contents() void { - asm volatile ("" ::: "memory"); -} From 886234b88284bd90c951b930c98f28681140435b Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Mon, 15 May 2023 23:12:22 -0700 Subject: [PATCH 58/74] improve timer API (#60) --- examples/usb_device.zig | 4 ++-- examples/usb_hid.zig | 4 ++-- src/hal/time.zig | 35 +++++++++++++++++------------------ src/hal/uart.zig | 4 ++-- 4 files changed, 23 insertions(+), 24 deletions(-) diff --git a/examples/usb_device.zig b/examples/usb_device.zig index 3395286..252db52 100644 --- a/examples/usb_device.zig +++ b/examples/usb_device.zig @@ -154,7 +154,7 @@ pub fn main() !void { rp2040.usb.Usb.init_clk(); // Then initialize the USB device using the configuration defined above rp2040.usb.Usb.init_device(&DEVICE_CONFIGURATION) catch unreachable; - var old: u64 = time.get_time_since_boot().us_since_boot; + var old: u64 = time.get_time_since_boot().to_us(); var new: u64 = 0; while (true) { // You can now poll for USB events @@ -162,7 +162,7 @@ pub fn main() !void { false, // debug output over UART [Y/n] ) catch unreachable; - new = time.get_time_since_boot().us_since_boot; + new = time.get_time_since_boot().to_us(); if (new - old > 500000) { old = new; led.toggle(); diff --git a/examples/usb_hid.zig b/examples/usb_hid.zig index 051ad74..a19a3e0 100644 --- a/examples/usb_hid.zig +++ b/examples/usb_hid.zig @@ -169,7 +169,7 @@ pub fn main() !void { rp2040.usb.Usb.init_clk(); // Then initialize the USB device using the configuration defined above rp2040.usb.Usb.init_device(&DEVICE_CONFIGURATION) catch unreachable; - var old: u64 = time.get_time_since_boot().us_since_boot; + var old: u64 = time.get_time_since_boot().to_us(); var new: u64 = 0; while (true) { // You can now poll for USB events @@ -177,7 +177,7 @@ pub fn main() !void { true, // debug output over UART [Y/n] ) catch unreachable; - new = time.get_time_since_boot().us_since_boot; + new = time.get_time_since_boot().to_us(); if (new - old > 500000) { old = new; led.toggle(); diff --git a/src/hal/time.zig b/src/hal/time.zig index 3b568bf..d7f815b 100644 --- a/src/hal/time.zig +++ b/src/hal/time.zig @@ -1,8 +1,19 @@ const microzig = @import("microzig"); const TIMER = microzig.chip.peripherals.TIMER; -pub const Absolute = struct { - us_since_boot: u64, +/// Using an enum to make it a distinct type, the underlying number is +/// time since boot in microseconds. +pub const Absolute = enum(u64) { + _, + + pub fn reached(time: Absolute) bool { + const now = get_time_since_boot(); + return now.to_us() >= time.to_us(); + } + + pub fn to_us(time: Absolute) u64 { + return @enumToInt(time); + } }; pub fn get_time_since_boot() Absolute { @@ -12,23 +23,14 @@ pub fn get_time_since_boot() Absolute { var low_word = TIMER.TIMERAWL; const next_high_word = TIMER.TIMERAWH; if (next_high_word == high_word) - break Absolute{ - .us_since_boot = @intCast(u64, high_word) << 32 | low_word, - }; + break @intToEnum(Absolute, @intCast(u64, high_word) << 32 | low_word); high_word = next_high_word; } else unreachable; } pub fn make_timeout_us(timeout_us: u64) Absolute { - return Absolute{ - .us_since_boot = get_time_since_boot().us_since_boot + timeout_us, - }; -} - -pub fn reached(time: Absolute) bool { - const now = get_time_since_boot(); - return now.us_since_boot >= time.us_since_boot; + return @intToEnum(Absolute, get_time_since_boot().to_us() + timeout_us); } pub fn sleep_ms(time_ms: u32) void { @@ -36,9 +38,6 @@ pub fn sleep_ms(time_ms: u32) void { } pub fn sleep_us(time_us: u64) void { - const end_time = Absolute{ - .us_since_boot = time_us + get_time_since_boot().us_since_boot, - }; - - while (!reached(end_time)) {} + const end_time = make_timeout_us(time_us); + while (!end_time.reached()) {} } diff --git a/src/hal/uart.zig b/src/hal/uart.zig index 6a08b85..b7a9b11 100644 --- a/src/hal/uart.zig +++ b/src/hal/uart.zig @@ -219,8 +219,8 @@ pub fn log( if (uart_logger) |uart| { const current_time = time.get_time_since_boot(); - const seconds = current_time.us_since_boot / std.time.us_per_s; - const microseconds = current_time.us_since_boot % std.time.us_per_s; + const seconds = current_time.to_us() / std.time.us_per_s; + const microseconds = current_time.to_us() % std.time.us_per_s; uart.print(prefix ++ format ++ "\r\n", .{ seconds, microseconds } ++ args) catch {}; } From abff6d1f4bec6804bd42b7dabaed3f6fae3f196d Mon Sep 17 00:00:00 2001 From: Vlad Panazan Date: Thu, 18 May 2023 00:39:54 +0300 Subject: [PATCH 59/74] add ws2812 pio example (#54) --- build.zig | 1 + examples/ws2812.zig | 94 +++++++++++++++++++++++++++++++++++++++++++++ src/hal/pio.zig | 4 +- 3 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 examples/ws2812.zig diff --git a/build.zig b/build.zig index 1ee7e17..4afab69 100644 --- a/build.zig +++ b/build.zig @@ -71,6 +71,7 @@ pub const Examples = struct { flash_program: *microzig.EmbeddedExecutable, usb_device: *microzig.EmbeddedExecutable, usb_hid: *microzig.EmbeddedExecutable, + ws2812: *microzig.EmbeddedExecutable, random: *microzig.EmbeddedExecutable, pub fn init(b: *Builder, optimize: std.builtin.OptimizeMode) Examples { diff --git a/examples/ws2812.zig b/examples/ws2812.zig new file mode 100644 index 0000000..e51d973 --- /dev/null +++ b/examples/ws2812.zig @@ -0,0 +1,94 @@ +const std = @import("std"); +const microzig = @import("microzig"); +const rp2040 = microzig.hal; +const gpio = rp2040.gpio; +const Pio = rp2040.pio.Pio; +const StateMachine = rp2040.pio.StateMachine; + +const ws2812_program = blk: { + @setEvalBranchQuota(5000); + break :blk rp2040.pio.assemble( + \\; + \\; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + \\; + \\; SPDX-License-Identifier: BSD-3-Clause + \\; + \\.program ws2812 + \\.side_set 1 + \\ + \\.define public T1 2 + \\.define public T2 5 + \\.define public T3 3 + \\ + \\.wrap_target + \\bitloop: + \\ out x, 1 side 0 [T3 - 1] ; Side-set still takes place when instruction stalls + \\ jmp !x do_zero side 1 [T1 - 1] ; Branch on the bit we shifted out. Positive pulse + \\do_one: + \\ jmp bitloop side 1 [T2 - 1] ; Continue driving high, for a long pulse + \\do_zero: + \\ nop side 0 [T2 - 1] ; Or drive low, for a short pulse + \\.wrap + , .{}).get_program_by_name("ws2812"); +}; + +const pio: Pio = .pio0; +const sm: StateMachine = .sm0; +const led_pin = gpio.num(23); + +pub fn main() void { + pio.gpio_init(led_pin); + sm_set_consecutive_pindirs(pio, sm, @enumToInt(led_pin), 1, true); + + const cycles_per_bit: comptime_int = ws2812_program.defines[0].value + //T1 + ws2812_program.defines[1].value + //T2 + ws2812_program.defines[2].value; //T3 + const div = @intToFloat(f32, rp2040.clock_config.sys.?.output_freq) / + (800_000 * cycles_per_bit); + + pio.sm_load_and_start_program(sm, ws2812_program, .{ + .clkdiv = rp2040.pio.ClkDivOptions.from_float(div), + .pin_mappings = .{ + .side_set = .{ + .base = @enumToInt(led_pin), + .count = 1, + }, + }, + .shift = .{ + .out_shiftdir = .left, + .autopull = true, + .pull_threshold = 24, + .join_tx = true, + }, + }) catch unreachable; + pio.sm_set_enabled(sm, true); + + while (true) { + pio.sm_blocking_write(sm, 0x00ff00 << 8); //red + rp2040.time.sleep_ms(1000); + pio.sm_blocking_write(sm, 0xff0000 << 8); //green + rp2040.time.sleep_ms(1000); + pio.sm_blocking_write(sm, 0x0000ff << 8); //blue + rp2040.time.sleep_ms(1000); + } +} + +fn sm_set_consecutive_pindirs(_pio: Pio, _sm: StateMachine, pin: u5, count: u3, is_out: bool) void { + const sm_regs = _pio.get_sm_regs(_sm); + const pinctrl_saved = sm_regs.pinctrl.raw; + sm_regs.pinctrl.modify(.{ + .SET_BASE = pin, + .SET_COUNT = count, + }); + _pio.sm_exec(_sm, rp2040.pio.Instruction{ + .tag = .set, + .delay_side_set = 0, + .payload = .{ + .set = .{ + .data = @boolToInt(is_out), + .destination = .pindirs, + }, + }, + }); + sm_regs.pinctrl.raw = pinctrl_saved; +} diff --git a/src/hal/pio.zig b/src/hal/pio.zig index 2eb1709..2943a3f 100644 --- a/src/hal/pio.zig +++ b/src/hal/pio.zig @@ -226,7 +226,7 @@ pub const Pio = enum(u1) { } else error.NoSpace; } - fn get_sm_regs(self: Pio, sm: StateMachine) *volatile StateMachine.Regs { + pub fn get_sm_regs(self: Pio, sm: StateMachine) *volatile StateMachine.Regs { const pio_regs = self.get_regs(); const sm_regs = @ptrCast(*volatile [4]StateMachine.Regs, &pio_regs.SM0_CLKDIV); return &sm_regs[@enumToInt(sm)]; @@ -480,7 +480,7 @@ pub const Pio = enum(u1) { ) !void { const expected_side_set_pins = if (program.side_set) |side_set| if (side_set.optional) - side_set.count - 1 + side_set.count + 1 else side_set.count else From d1e35696d430c10fa3b2346d3137a81c122dc90b Mon Sep 17 00:00:00 2001 From: Hubert Jasudowicz Date: Thu, 18 May 2023 09:24:18 +0200 Subject: [PATCH 60/74] examples: Set LED GPIO function (#61) Set the pin function to SIO instead of null (default). --- examples/blinky_core1.zig | 1 + examples/flash_program.zig | 1 + examples/random.zig | 1 + examples/uart.zig | 1 + examples/usb_device.zig | 1 + examples/usb_hid.zig | 1 + 6 files changed, 6 insertions(+) diff --git a/examples/blinky_core1.zig b/examples/blinky_core1.zig index 64f0674..0615729 100644 --- a/examples/blinky_core1.zig +++ b/examples/blinky_core1.zig @@ -18,6 +18,7 @@ fn core1() void { } pub fn main() !void { + led.set_function(.sio); led.set_direction(.out); multicore.launch_core1(core1); diff --git a/examples/flash_program.zig b/examples/flash_program.zig index a2999c9..4bae769 100644 --- a/examples/flash_program.zig +++ b/examples/flash_program.zig @@ -28,6 +28,7 @@ pub const std_options = struct { }; pub fn main() !void { + led.set_function(.sio); led.set_direction(.out); led.put(1); diff --git a/examples/random.zig b/examples/random.zig index 0645839..151482e 100644 --- a/examples/random.zig +++ b/examples/random.zig @@ -28,6 +28,7 @@ pub const std_options = struct { }; pub fn main() !void { + led.set_function(.sio); led.set_direction(.out); led.put(1); diff --git a/examples/uart.zig b/examples/uart.zig index 6be3b38..914b9ae 100644 --- a/examples/uart.zig +++ b/examples/uart.zig @@ -24,6 +24,7 @@ pub const std_options = struct { }; pub fn main() !void { + led.set_function(.sio); led.set_direction(.out); led.put(1); diff --git a/examples/usb_device.zig b/examples/usb_device.zig index 252db52..27d961d 100644 --- a/examples/usb_device.zig +++ b/examples/usb_device.zig @@ -138,6 +138,7 @@ pub const std_options = struct { }; pub fn main() !void { + led.set_function(.sio); led.set_direction(.out); led.put(1); diff --git a/examples/usb_hid.zig b/examples/usb_hid.zig index a19a3e0..34b9a12 100644 --- a/examples/usb_hid.zig +++ b/examples/usb_hid.zig @@ -153,6 +153,7 @@ pub const std_options = struct { }; pub fn main() !void { + led.set_function(.sio); led.set_direction(.out); led.put(1); From 7b7caa9eb40ca87db79958aeadd2e40155c1ab95 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Thu, 18 May 2023 20:51:23 -0700 Subject: [PATCH 61/74] improve ADC API (#62) --- examples/adc.zig | 12 +- src/hal/adc.zig | 386 +++++++++++++++++++++++++++++++---------------- 2 files changed, 262 insertions(+), 136 deletions(-) diff --git a/examples/adc.zig b/examples/adc.zig index b6d6bf4..ff180dd 100644 --- a/examples/adc.zig +++ b/examples/adc.zig @@ -7,7 +7,6 @@ const gpio = rp2040.gpio; const adc = rp2040.adc; const time = rp2040.time; -const temp_sensor: adc.Input = .temperature_sensor; const uart = rp2040.uart.num(0); const baud_rate = 115200; const uart_tx_pin = gpio.num(0); @@ -18,6 +17,10 @@ pub const std_options = struct { }; pub fn main() void { + adc.apply(.{ + .temp_sensor_enabled = true, + }); + uart.apply(.{ .baud_rate = baud_rate, .tx_pin = uart_tx_pin, @@ -26,9 +29,12 @@ pub fn main() void { }); rp2040.uart.init_logger(uart); - while (true) : (time.sleep_ms(1000)) { - const sample = temp_sensor.read(); + const sample = adc.convert_one_shot_blocking(.temp_sensor) catch { + std.log.err("conversion failed!", .{}); + continue; + }; + std.log.info("temp value: {}", .{sample}); } } diff --git a/src/hal/adc.zig b/src/hal/adc.zig index a77b102..592273b 100644 --- a/src/hal/adc.zig +++ b/src/hal/adc.zig @@ -7,196 +7,316 @@ const microzig = @import("microzig"); const ADC = microzig.chip.peripherals.ADC; const gpio = @import("gpio.zig"); const resets = @import("resets.zig"); +const clocks = @import("clocks.zig"); -pub const temperature_sensor = struct { - pub inline fn init() void { - set_temp_sensor_enabled(true); - } - - pub inline fn deinit() void { - set_temp_sensor_enabled(false); - } - - pub inline fn read_raw() u16 { - return Input.read(.temperature_sensor); - } - - // One-shot conversion returning the temperature in Celcius - pub inline fn read(comptime T: type, comptime Vref: T) T { - // TODO: consider fixed-point - const raw = @intToFloat(T, read_raw()); - const voltage: T = Vref * raw / 0x0fff; - return (27.0 - ((voltage - 0.706) / 0.001721)); - } +pub const Error = error{ + /// ADC conversion failed, one such reason is that the controller failed to + /// converge on a result. + Conversion, }; -pub const Input = enum(u3) { - ain0, - ain1, - ain2, - ain3, - temperature_sensor, - - /// Setup the GPIO pin as an ADC input - pub fn init(comptime input: Input) void { - switch (input) { - .temperature_sensor => set_temp_sensor_enabled(true), - else => { - const pin = gpio.num(@as(u5, @enumToInt(input)) + 26); - pin.set_function(.null); - - // TODO: implement these, otherwise adc isn't going to work. - //gpio.disablePulls(gpio_num); - //gpio.setInputEnabled(gpio_num, false); - }, - } - } - - /// Disables temp sensor, otherwise it does nothing if the input is - /// one of the others. - pub inline fn deinit(input: Input) void { - switch (input) { - .temperature_sensor => set_temp_sensor_enabled(true), - else => {}, - } - } - - /// Single-shot, blocking conversion - pub fn read(input: Input) u12 { - // TODO: not sure if setting these during the same write is - // correct - ADC.CS.modify(.{ - .AINSEL = @enumToInt(input), - .START_ONCE = 1, - }); - - // wait for the - while (ADC.CS.read().READY == 0) {} - - return ADC.RESULT.read().RESULT; - } -}; +/// temp_sensor is not valid because you can refer to it by name. +pub fn input(n: u2) Input { + return @intToEnum(Input, n); +} -pub const InputMask = InputMask: { - const enum_fields = @typeInfo(Input).Enum.fields; - var fields: [enum_fields.len]std.builtin.Type.StructField = undefined; - - const default_value: u1 = 0; - for (enum_fields, &fields) |enum_field, *field| - field = std.builtin.Type.StructField{ - .name = enum_field.name, - .field_type = u1, - .default_value = &default_value, - .is_comptime = false, - .alignment = 1, - }; +/// Enable the ADC controller. +pub fn set_enabled(enabled: bool) void { + ADC.CS.modify(.{ .EN = @boolToInt(enabled) }); +} - break :InputMask @Type(.{ - .Struct = .{ - .layout = .Packed, - .fields = &fields, - .backing_integer = std.meta.Int(.Unsigned, enum_fields.len), - .decls = &.{}, - .is_tuple = false, - }, - }); +const Config = struct { + /// Note that this frequency is the sample frequency of the controller, not + /// each input. So for 4 inputs in round-robin mode you'd see 1/4 sample + /// rate for a given put vs what is set here. + sample_frequency: ?u32 = null, + round_robin: ?InputMask = null, + fifo: ?fifo.Config = null, + temp_sensor_enabled: bool = false, }; -/// Initialize ADC hardware -pub fn init() void { +/// Applies configuration to ADC, leaves it in an enabled state by setting +/// CS.EN = 1. The global clock configuration is not needed to configure the +/// sample rate because the ADC hardware block requires a 48MHz clock. +pub fn apply(config: Config) void { ADC.CS.write(.{ - .EN = 1, - .TS_EN = 0, + .EN = 0, + .TS_EN = @boolToInt(config.temp_sensor_enabled), .START_ONCE = 0, .START_MANY = 0, .READY = 0, + .ERR = 0, .ERR_STICKY = 0, .AINSEL = 0, - .RROBIN = 0, + .RROBIN = if (config.round_robin) |rr| + @bitCast(u5, rr) + else + 0, .reserved8 = 0, .reserved12 = 0, .reserved16 = 0, .padding = 0, }); - while (ADC.CS.read().READY == 0) {} -} -/// Enable/disable ADC interrupt -pub inline fn irq_set_enabled(enable: bool) void { - // TODO: check if this works - ADC.INTE.write(.{ .FIFO = if (enable) @as(u1, 1) else @as(u1, 0) }); + if (config.sample_frequency) |sample_frequency| { + const cycles = (48_000_000 * 256) / @as(u64, sample_frequency); + ADC.DIV.write(.{ + .FRAC = @truncate(u8, cycles), + .INT = @intCast(u16, (cycles >> 8) - 1), + + .padding = 0, + }); + } + + if (config.fifo) |fifo_config| + fifo.apply(fifo_config); + + set_enabled(true); } /// Select analog input for next conversion. -pub inline fn select_input(input: Input) void { - ADC.CS.modify(.{ .AINSEL = @enumToInt(input) }); +pub fn select_input(in: Input) void { + ADC.CS.modify(.{ .AINSEL = @enumToInt(in) }); } /// Get the currently selected analog input. 0..3 are GPIO 26..29 respectively, /// 4 is the temperature sensor. -pub inline fn get_selected_input() Input { - // TODO: ensure that the field shouldn't have other values - return @intToEnum(Input, ADC.CS.read().AINSEL); +pub fn get_selected_input() Input { + const cs = ADC.SC.read(); + return @intToEnum(Input, cs.AINSEL); } +pub const Input = enum(u3) { + /// The temperature sensor must be enabled using + /// `set_temp_sensor_enabled()` in order to use it + temp_sensor = 5, + _, + + /// Get the corresponding GPIO pin for an ADC input. Panics if you give it + /// temp_sensor. + pub fn get_gpio_pin(in: Input) gpio.Pin { + return switch (in) { + else => gpio.num(@as(u5, @enumToInt(in)) + 26), + .temp_sensor => @panic("temp_sensor doesn't have a pin"), + }; + } + + /// Prepares an ADC input's corresponding GPIO pin to be used as an analog + /// input. + pub fn configure_gpio_pin(in: Input) void { + switch (in) { + else => { + const pin = in.get_gpio_pin(); + pin.set_function(.null); + pin.set_pull(null); + pin.set_input_enabled(false); + }, + .temp_sensor => {}, + } + } +}; + /// Set to true to power on the temperature sensor. -pub inline fn set_temp_sensor_enabled(enable: bool) void { - ADC.CS.modify(.{ .TS_EN = if (enable) @as(u1, 1) else @as(u1, 0) }); +pub fn set_temp_sensor_enabled(enable: bool) void { + ADC.CS.modify(.{ .TS_EN = @boolToInt(enable) }); +} + +/// T must be floating point. +pub fn temp_sensor_result_to_celcius(comptime T: type, comptime vref: T, result: u12) T { + // TODO: consider fixed-point + const raw = @intToFloat(T, result); + const voltage: T = vref * raw / 0x0fff; + return (27.0 - ((voltage - 0.706) / 0.001721)); } +/// For selecting which inputs are to be used in round-robin mode +pub const InputMask = packed struct(u5) { + ain0: bool = false, + ain1: bool = false, + ain2: bool = false, + ain3: bool = false, + temp_sensor: bool = false, +}; + /// Sets which of the inputs are to be run in round-robin mode. Setting all to /// 0 will disable round-robin mode but `disableRoundRobin()` is provided so /// the user may be explicit. -pub inline fn set_round_robin(comptime enabled_inputs: InputMask) void { +pub fn round_robin_set(enabled_inputs: InputMask) void { ADC.CS.modify(.{ .RROBIN = @bitCast(u5, enabled_inputs) }); } /// Disable round-robin sample mode. -pub inline fn disable_round_robin() void { +pub fn round_robin_disable() void { ADC.CS.modify(.{ .RROBIN = 0 }); } -/// Enable free-running sample mode. -pub inline fn run(enable: bool) void { - ADC.CS.modify(.{ .START_MANY = if (enable) @as(u1, 1) else @as(u1, 0) }); +pub const Mode = enum { + one_shot, + free_running, +}; + +/// Start the ADC controller. There are three "modes" that the controller +/// operates in: +/// +/// - one shot: the input is selected and then conversion is started. The +/// controller stops once the conversion is complete. +/// +/// - free running single input: the input is selected and then the conversion +/// is started. Once a conversion is complete the controller begins another +/// on the same input. +/// +/// - free running round-robin: a mask of which inputs to sample is set using +/// `round_robin_set()`. Once conversion is completed for one input, a +/// conversion is started for the next set input in the mask. +pub fn start(mode: Mode) void { + switch (mode) { + .one_shot => ADC.CS.modify(.{ + .START_ONCE = 1, + }), + .free_running => ADC.CS.modify(.{ + .START_MANY = 1, + }), + } +} + +/// Check whether the ADC controller has a conversion result +pub fn is_ready() bool { + const cs = ADC.CS.read(); + return cs.READY != 0; } -pub inline fn set_clk_div() void { - @compileError("todo"); +/// Single-shot, blocking conversion +pub fn convert_one_shot_blocking(in: Input) Error!u12 { + select_input(in); + start(.one_shot); + + while (!is_ready()) {} + + return read_result(); } -/// The fifo is 4 samples long, if a conversion is completed and the FIFO is -/// full, the result is dropped. +/// Read conversion result from ADC controller, this function assumes that the +/// controller has a result ready. +pub fn read_result() Error!u12 { + const cs = ADC.CS.read(); + return if (cs.ERR == 1) + error.Conversion + else blk: { + const conversion = ADC.RESULT.read(); + break :blk conversion.RESULT; + }; +} + +/// The ADC FIFO can store up to four conversion results. It must be enabled in +/// order to use DREQ or IRQ driven streaming. pub const fifo = struct { - pub inline fn setup() void { - @compileError("todo"); - // There are a number of considerations wrt DMA and error detection + // TODO: what happens when DMA and IRQ are enabled? + pub const Config = struct { + /// Assert DMA requests when the fifo contains data + dreq_enabled: bool = false, + /// Assert Interrupt when fifo contains data + irq_enabled: bool = false, + /// DREQ/IRQ asserted when level >= threshold + thresh: u4 = 0, + /// Shift the conversion so it's 8-bit, good for DMAing to a byte + /// buffer + shift: bool = false, + }; + + /// Apply ADC FIFO configuration and enable it + pub fn apply(config: fifo.Config) void { + ADC.FCS.write(.{ + .DREQ_EN = @boolToInt(config.dreq_enabled), + .THRESH = config.thresh, + .SHIFT = @boolToInt(config.shift), + + .EN = 1, + .EMPTY = 0, + .FULL = 0, + .LEVEL = 0, + + // As far as it is known, there is zero cost to being able to + // report errors in the FIFO, so let's. + .ERR = 1, + + // Writing 1 to these will clear them if they're already set + .UNDER = 1, + .OVER = 1, + + .reserved8 = 0, + .reserved16 = 0, + .reserved24 = 0, + .padding = 0, + }); + + irq_set_enabled(config.irq_enabled); + } + + // TODO: do we need to acknowledge an ADC interrupt? + + /// Enable/disable ADC interrupt. + pub fn irq_set_enabled(enable: bool) void { + // TODO: check if this works + ADC.INTE.write(.{ + .FIFO = @boolToInt(enable), + .padding = 0, + }); + } + + /// Check if the ADC FIFO is full. + pub fn is_full() bool { + const fsc = ADC.FSC.read(); + return fsc.FULL != 0; + } + + /// Check if the ADC FIFO is empty. + pub fn is_empty() bool { + const fsc = ADC.FSC.read(); + return fsc.EMPTY != 0; + } + + /// Get the number of conversion in the ADC FIFO. + pub fn get_level() u4 { + const fsc = ADC.FSC.read(); + return fsc.LEVEL; } - /// Return true if FIFO is empty. - pub inline fn is_empty() bool { - @compileError("todo"); + /// Check if the ADC FIFO has overflowed. When overflow happens, the new + /// conversion is discarded. This flag is sticky, to clear it call + /// `clear_overflowed()`. + pub fn has_overflowed() bool { + const fsc = ADC.FSC.read(); + return fsc.OVER != 0; } - /// Read how many samples are in the FIFO. - pub inline fn get_level() u8 { - @compileError("todo"); + /// Clear the overflow status flag if it is set. + pub fn clear_overflowed() void { + ADC.FSC.modify(.{ .OVER = 1 }); } - /// Pop latest result from FIFO. - pub inline fn get() u16 { - @compileError("todo"); + /// Check if the ADC FIFO has underflowed. This means that the FIFO + /// register was read while the FIFO was empty. This flag is sticky, to + /// clear it call `clear_underflowed()`. + pub fn has_underflowed() bool { + const fsc = ADC.FSC.read(); + return fsc.UNDER != 0; } - /// Block until result is available in FIFO, then pop it. - pub inline fn get_blocking() u16 { - @compileError("todo"); + /// Clear the underflow status flag if it is set. + pub fn clear_underflowed() void { + ADC.FSC.modify(.{ .UNDER = 1 }); } - /// Wait for conversion to complete then discard results in FIFO. - pub inline fn drain() void { - @compileError("todo"); + /// Pop conversion from ADC FIFO. This function assumes that the FIFO is + /// not empty. + pub fn pop() Error!u12 { + assert(!is_empty()); + const result = ADC.FIFO.read(); + return if (result.ERR == 1) + error.Conversion + else + result.VAL; } }; From 316e241a88fa3c131e22ea421123794eb67604a7 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Tue, 30 May 2023 22:31:44 -0700 Subject: [PATCH 62/74] DMA API, and time API improvements from SYCL 2023 workshop (#63) --- src/hal/dma.zig | 56 +++++++++++++++++++++++++++--------------------- src/hal/time.zig | 52 ++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 80 insertions(+), 28 deletions(-) diff --git a/src/hal/dma.zig b/src/hal/dma.zig index 248e333..ded0a8c 100644 --- a/src/hal/dma.zig +++ b/src/hal/dma.zig @@ -7,7 +7,8 @@ const DMA = chip.peripherals.DMA; const hw = @import("hw.zig"); -var claimed_channels: u12 = 0; +const num_channels = 12; +var claimed_channels = std.PackedIntArray(bool, num_channels).initAllTo(false); pub const Dreq = enum(u6) { uart0_tx = 20, @@ -15,31 +16,38 @@ pub const Dreq = enum(u6) { _, }; -pub fn num(n: u4) Channel { - assert(n < 12); +pub fn channel(n: u4) Channel { + assert(n < num_channels); return @intToEnum(Channel, n); } -pub fn claim_unused_channel() ?Channel {} +pub fn claim_unused_channel() ?Channel { + for (0..num_channels) |i| { + if (claimed_channels.get(i)) { + claimed_channels.set(i, true); + return channel(i); + } + } + + return null; +} pub const Channel = enum(u4) { _, /// panics if the channel is already claimed - pub fn claim(channel: Channel) void { - _ = channel; - @panic("TODO"); + pub fn claim(chan: Channel) void { + if (chan.is_claimed()) + @panic("channel is already claimed!"); } - pub fn unclaim(channel: Channel) void { - _ = channel; - @panic("TODO"); + pub fn unclaim(chan: Channel) void { + claimed_channels.set(@enumToInt(chan), false); } - pub fn is_claimed(channel: Channel) bool { - _ = channel; - @panic("TODO"); + pub fn is_claimed(chan: Channel) bool { + return claimed_channels.get(@enumToInt(chan)); } const Regs = extern struct { @@ -67,9 +75,9 @@ pub const Channel = enum(u4) { al3_trans_count: u32, }; - fn get_regs(channel: Channel) *volatile Regs { + fn get_regs(chan: Channel) *volatile Regs { const regs = @ptrCast(*volatile [12]Regs, &DMA.CH0_READ_ADDR); - return ®s[@enumToInt(channel)]; + return ®s[@enumToInt(chan)]; } pub const TransferConfig = struct { @@ -86,13 +94,13 @@ pub const Channel = enum(u4) { }; pub fn trigger_transfer( - channel: Channel, + chan: Channel, write_addr: u32, read_addr: u32, count: u32, config: TransferConfig, ) void { - const regs = channel.get_regs(); + const regs = chan.get_regs(); regs.read_addr = read_addr; regs.write_addr = write_addr; regs.trans_count = count; @@ -109,23 +117,23 @@ pub const Channel = enum(u4) { }); } - pub fn set_irq0_enabled(channel: Channel, enabled: bool) void { + pub fn set_irq0_enabled(chan: Channel, enabled: bool) void { if (enabled) { const inte0_set = hw.set_alias_raw(&DMA.INTE0); - inte0_set.* = @as(u32, 1) << @enumToInt(channel); + inte0_set.* = @as(u32, 1) << @enumToInt(chan); } else { const inte0_clear = hw.clear_alias_raw(&DMA.INTE0); - inte0_clear.* = @as(u32, 1) << @enumToInt(channel); + inte0_clear.* = @as(u32, 1) << @enumToInt(chan); } } - pub fn acknowledge_irq0(channel: Channel) void { + pub fn acknowledge_irq0(chan: Channel) void { const ints0_set = hw.set_alias_raw(&DMA.INTS0); - ints0_set.* = @as(u32, 1) << @enumToInt(channel); + ints0_set.* = @as(u32, 1) << @enumToInt(chan); } - pub fn is_busy(channel: Channel) bool { - const regs = channel.get_regs(); + pub fn is_busy(chan: Channel) bool { + const regs = chan.get_regs(); return regs.ctrl_trig.read().BUSY == 1; } }; diff --git a/src/hal/time.zig b/src/hal/time.zig index d7f815b..e6cace5 100644 --- a/src/hal/time.zig +++ b/src/hal/time.zig @@ -6,14 +6,58 @@ const TIMER = microzig.chip.peripherals.TIMER; pub const Absolute = enum(u64) { _, - pub fn reached(time: Absolute) bool { - const now = get_time_since_boot(); - return now.to_us() >= time.to_us(); + pub fn from_us(us: u64) Absolute { + return @intToEnum(Absolute, us); } pub fn to_us(time: Absolute) u64 { return @enumToInt(time); } + + pub fn is_reached_by(deadline: Absolute, point: Absolute) bool { + return deadline.to_us() <= point.to_us(); + } + + pub fn is_reached(time: Absolute) bool { + const now = get_time_since_boot(); + return time.is_reached_by(now); + } + + pub fn diff(future: Absolute, past: Absolute) Duration { + return Duration.from_us(future.to_us() - past.to_us()); + } + + pub fn add_duration(time: Absolute, dur: Duration) Absolute { + return Absolute.from_us(time.to_us() + dur.to_us()); + } +}; + +pub const Duration = enum(u64) { + _, + + pub fn from_us(us: u64) Duration { + return @intToEnum(Duration, us); + } + + pub fn from_ms(ms: u64) Duration { + return from_us(1000 * ms); + } + + pub fn to_us(duration: Duration) u64 { + return @enumToInt(duration); + } + + pub fn less_than(self: Duration, other: Duration) bool { + return self.to_us() < other.to_us(); + } + + pub fn minus(self: Duration, other: Duration) Duration { + return from_us(self.to_us() - other.to_us()); + } + + pub fn plus(self: Duration, other: Duration) Duration { + return from_us(self.to_us() + other.to_us()); + } }; pub fn get_time_since_boot() Absolute { @@ -39,5 +83,5 @@ pub fn sleep_ms(time_ms: u32) void { pub fn sleep_us(time_us: u64) void { const end_time = make_timeout_us(time_us); - while (!end_time.reached()) {} + while (!end_time.is_reached()) {} } From 371d4efde433a9dc87b9f6bc9c31ad491474f658 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Quei=C3=9Fner?= Date: Sun, 25 Jun 2023 20:15:00 +0200 Subject: [PATCH 63/74] =?UTF-8?q?Runs=20zig=20fmt,=20implements=20a=20good?= =?UTF-8?q?=20bunch=20of=20I=C2=B2C=20functions=20(#65)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Felix "xq" Queißner --- deps/microzig | 2 +- examples/flash_program.zig | 2 +- examples/random.zig | 2 +- examples/usb_device.zig | 4 +- examples/usb_hid.zig | 4 +- examples/ws2812.zig | 8 +- src/chips/RP2040.zig | 80 +++--- src/hal.zig | 1 + src/hal/adc.zig | 22 +- src/hal/clocks.zig | 4 +- src/hal/dma.zig | 22 +- src/hal/flash.zig | 4 +- src/hal/gpio.zig | 22 +- src/hal/hw.zig | 12 +- src/hal/i2c.zig | 413 ++++++++++++++++++++++++++++++ src/hal/multicore.zig | 10 +- src/hal/pins.zig | 12 +- src/hal/pio.zig | 50 ++-- src/hal/pio/assembler/encoder.zig | 12 +- src/hal/pwm.zig | 10 +- src/hal/rom.zig | 6 +- src/hal/spi.zig | 4 +- src/hal/time.zig | 12 +- src/hal/uart.zig | 6 +- src/hal/usb.zig | 44 ++-- 25 files changed, 591 insertions(+), 177 deletions(-) create mode 100644 src/hal/i2c.zig diff --git a/deps/microzig b/deps/microzig index 9588941..a49fad9 160000 --- a/deps/microzig +++ b/deps/microzig @@ -1 +1 @@ -Subproject commit 95889419155b7ffb1b11055549540096eaa2a6c5 +Subproject commit a49fad973077dffd5fa0b392720295ad033f076e diff --git a/examples/flash_program.zig b/examples/flash_program.zig index 4bae769..d38d0ae 100644 --- a/examples/flash_program.zig +++ b/examples/flash_program.zig @@ -14,7 +14,7 @@ const uart_tx_pin = gpio.num(0); const uart_rx_pin = gpio.num(1); const flash_target_offset: u32 = 256 * 1024; -const flash_target_contents = @intToPtr([*]const u8, rp2040.flash.XIP_BASE + flash_target_offset); +const flash_target_contents = @ptrFromInt([*]const u8, rp2040.flash.XIP_BASE + flash_target_offset); pub fn panic(message: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { std.log.err("panic: {s}", .{message}); diff --git a/examples/random.zig b/examples/random.zig index 151482e..40d2f68 100644 --- a/examples/random.zig +++ b/examples/random.zig @@ -60,7 +60,7 @@ pub fn main() !void { var i: usize = 0; std.log.info("Distribution:", .{}); while (i < 256) : (i += 1) { - std.log.info("{} -> {}, {d:2}%", .{ i, dist[i], @intToFloat(f32, dist[i]) / @intToFloat(f32, counter) }); + std.log.info("{} -> {}, {d:2}%", .{ i, dist[i], @floatFromInt(f32, dist[i]) / @floatFromInt(f32, counter) }); } } time.sleep_ms(1000); diff --git a/examples/usb_device.zig b/examples/usb_device.zig index 27d961d..d2b243d 100644 --- a/examples/usb_device.zig +++ b/examples/usb_device.zig @@ -41,7 +41,7 @@ pub var EP1_OUT_CFG: usb.EndpointConfiguration = .{ .length = @intCast(u8, @sizeOf(usb.EndpointDescriptor)), .descriptor_type = usb.DescType.Endpoint, .endpoint_address = usb.Dir.Out.endpoint(1), - .attributes = @enumToInt(usb.TransferType.Bulk), + .attributes = @intFromEnum(usb.TransferType.Bulk), .max_packet_size = 64, .interval = 0, }, @@ -58,7 +58,7 @@ pub var EP1_IN_CFG: usb.EndpointConfiguration = .{ .length = @intCast(u8, @sizeOf(usb.EndpointDescriptor)), .descriptor_type = usb.DescType.Endpoint, .endpoint_address = usb.Dir.In.endpoint(1), - .attributes = @enumToInt(usb.TransferType.Bulk), + .attributes = @intFromEnum(usb.TransferType.Bulk), .max_packet_size = 64, .interval = 0, }, diff --git a/examples/usb_hid.zig b/examples/usb_hid.zig index 34b9a12..2eced2b 100644 --- a/examples/usb_hid.zig +++ b/examples/usb_hid.zig @@ -41,7 +41,7 @@ pub var EP1_OUT_CFG: usb.EndpointConfiguration = .{ .length = @intCast(u8, @sizeOf(usb.EndpointDescriptor)), .descriptor_type = usb.DescType.Endpoint, .endpoint_address = usb.Dir.Out.endpoint(1), - .attributes = @enumToInt(usb.TransferType.Interrupt), + .attributes = @intFromEnum(usb.TransferType.Interrupt), .max_packet_size = 64, .interval = 0, }, @@ -58,7 +58,7 @@ pub var EP1_IN_CFG: usb.EndpointConfiguration = .{ .length = @intCast(u8, @sizeOf(usb.EndpointDescriptor)), .descriptor_type = usb.DescType.Endpoint, .endpoint_address = usb.Dir.In.endpoint(1), - .attributes = @enumToInt(usb.TransferType.Interrupt), + .attributes = @intFromEnum(usb.TransferType.Interrupt), .max_packet_size = 64, .interval = 0, }, diff --git a/examples/ws2812.zig b/examples/ws2812.zig index e51d973..f61204b 100644 --- a/examples/ws2812.zig +++ b/examples/ws2812.zig @@ -38,19 +38,19 @@ const led_pin = gpio.num(23); pub fn main() void { pio.gpio_init(led_pin); - sm_set_consecutive_pindirs(pio, sm, @enumToInt(led_pin), 1, true); + sm_set_consecutive_pindirs(pio, sm, @intFromEnum(led_pin), 1, true); const cycles_per_bit: comptime_int = ws2812_program.defines[0].value + //T1 ws2812_program.defines[1].value + //T2 ws2812_program.defines[2].value; //T3 - const div = @intToFloat(f32, rp2040.clock_config.sys.?.output_freq) / + const div = @floatFromInt(f32, rp2040.clock_config.sys.?.output_freq) / (800_000 * cycles_per_bit); pio.sm_load_and_start_program(sm, ws2812_program, .{ .clkdiv = rp2040.pio.ClkDivOptions.from_float(div), .pin_mappings = .{ .side_set = .{ - .base = @enumToInt(led_pin), + .base = @intFromEnum(led_pin), .count = 1, }, }, @@ -85,7 +85,7 @@ fn sm_set_consecutive_pindirs(_pio: Pio, _sm: StateMachine, pin: u5, count: u3, .delay_side_set = 0, .payload = .{ .set = .{ - .data = @boolToInt(is_out), + .data = @intFromBool(is_out), .destination = .pindirs, }, }, diff --git a/src/chips/RP2040.zig b/src/chips/RP2040.zig index 62af336..74f6134 100644 --- a/src/chips/RP2040.zig +++ b/src/chips/RP2040.zig @@ -65,9 +65,9 @@ pub const devices = struct { pub const peripherals = struct { /// System Control Space - pub const MPU = @intToPtr(*volatile types.peripherals.SCS, 0xd90); + pub const MPU = @ptrFromInt(*volatile types.peripherals.SCS, 0xd90); /// QSPI flash execute-in-place block - pub const XIP_CTRL = @intToPtr(*volatile types.peripherals.XIP_CTRL, 0x14000000); + pub const XIP_CTRL = @ptrFromInt(*volatile types.peripherals.XIP_CTRL, 0x14000000); /// DW_apb_ssi has the following features: /// * APB interface – Allows for easy integration into a DesignWare Synthesizable Components for AMBA 2 implementation. /// * APB3 and APB4 protocol support. @@ -94,27 +94,27 @@ pub const devices = struct { /// - Interrupt polarity – active high interrupt lines. /// - Serial clock polarity – low serial-clock polarity directly after reset. /// - Serial clock phase – capture on first edge of serial-clock directly after reset. - pub const XIP_SSI = @intToPtr(*volatile types.peripherals.XIP_SSI, 0x18000000); - pub const SYSINFO = @intToPtr(*volatile types.peripherals.SYSINFO, 0x40000000); + pub const XIP_SSI = @ptrFromInt(*volatile types.peripherals.XIP_SSI, 0x18000000); + pub const SYSINFO = @ptrFromInt(*volatile types.peripherals.SYSINFO, 0x40000000); /// Register block for various chip control signals - pub const SYSCFG = @intToPtr(*volatile types.peripherals.SYSCFG, 0x40004000); - pub const CLOCKS = @intToPtr(*volatile types.peripherals.CLOCKS, 0x40008000); - pub const RESETS = @intToPtr(*volatile types.peripherals.RESETS, 0x4000c000); - pub const PSM = @intToPtr(*volatile types.peripherals.PSM, 0x40010000); - pub const IO_BANK0 = @intToPtr(*volatile types.peripherals.IO_BANK0, 0x40014000); - pub const IO_QSPI = @intToPtr(*volatile types.peripherals.IO_QSPI, 0x40018000); - pub const PADS_BANK0 = @intToPtr(*volatile types.peripherals.PADS_BANK0, 0x4001c000); - pub const PADS_QSPI = @intToPtr(*volatile types.peripherals.PADS_QSPI, 0x40020000); + pub const SYSCFG = @ptrFromInt(*volatile types.peripherals.SYSCFG, 0x40004000); + pub const CLOCKS = @ptrFromInt(*volatile types.peripherals.CLOCKS, 0x40008000); + pub const RESETS = @ptrFromInt(*volatile types.peripherals.RESETS, 0x4000c000); + pub const PSM = @ptrFromInt(*volatile types.peripherals.PSM, 0x40010000); + pub const IO_BANK0 = @ptrFromInt(*volatile types.peripherals.IO_BANK0, 0x40014000); + pub const IO_QSPI = @ptrFromInt(*volatile types.peripherals.IO_QSPI, 0x40018000); + pub const PADS_BANK0 = @ptrFromInt(*volatile types.peripherals.PADS_BANK0, 0x4001c000); + pub const PADS_QSPI = @ptrFromInt(*volatile types.peripherals.PADS_QSPI, 0x40020000); /// Controls the crystal oscillator - pub const XOSC = @intToPtr(*volatile types.peripherals.XOSC, 0x40024000); - pub const PLL_SYS = @intToPtr(*volatile types.peripherals.PLL_SYS, 0x40028000); - pub const PLL_USB = @intToPtr(*volatile types.peripherals.PLL_SYS, 0x4002c000); + pub const XOSC = @ptrFromInt(*volatile types.peripherals.XOSC, 0x40024000); + pub const PLL_SYS = @ptrFromInt(*volatile types.peripherals.PLL_SYS, 0x40028000); + pub const PLL_USB = @ptrFromInt(*volatile types.peripherals.PLL_SYS, 0x4002c000); /// Register block for busfabric control signals and performance counters - pub const BUSCTRL = @intToPtr(*volatile types.peripherals.BUSCTRL, 0x40030000); - pub const UART0 = @intToPtr(*volatile types.peripherals.UART0, 0x40034000); - pub const UART1 = @intToPtr(*volatile types.peripherals.UART0, 0x40038000); - pub const SPI0 = @intToPtr(*volatile types.peripherals.SPI0, 0x4003c000); - pub const SPI1 = @intToPtr(*volatile types.peripherals.SPI0, 0x40040000); + pub const BUSCTRL = @ptrFromInt(*volatile types.peripherals.BUSCTRL, 0x40030000); + pub const UART0 = @ptrFromInt(*volatile types.peripherals.UART0, 0x40034000); + pub const UART1 = @ptrFromInt(*volatile types.peripherals.UART0, 0x40038000); + pub const SPI0 = @ptrFromInt(*volatile types.peripherals.SPI0, 0x4003c000); + pub const SPI1 = @ptrFromInt(*volatile types.peripherals.SPI0, 0x40040000); /// DW_apb_i2c address block /// List of configuration constants for the Synopsys I2C hardware (you may see references to these in I2C register header; these are *fixed* values, set at hardware design time): /// IC_ULTRA_FAST_MODE ................ 0x0 @@ -185,7 +185,7 @@ pub const devices = struct { /// IC_STOP_DET_IF_MASTER_ACTIVE ...... 0x0 /// IC_DEFAULT_UFM_SPKLEN ............. 0x1 /// IC_TX_BUFFER_DEPTH ................ 16 - pub const I2C0 = @intToPtr(*volatile types.peripherals.I2C0, 0x40044000); + pub const I2C0 = @ptrFromInt(*volatile types.peripherals.I2C0, 0x40044000); /// DW_apb_i2c address block /// List of configuration constants for the Synopsys I2C hardware (you may see references to these in I2C register header; these are *fixed* values, set at hardware design time): /// IC_ULTRA_FAST_MODE ................ 0x0 @@ -256,11 +256,11 @@ pub const devices = struct { /// IC_STOP_DET_IF_MASTER_ACTIVE ...... 0x0 /// IC_DEFAULT_UFM_SPKLEN ............. 0x1 /// IC_TX_BUFFER_DEPTH ................ 16 - pub const I2C1 = @intToPtr(*volatile types.peripherals.I2C0, 0x40048000); + pub const I2C1 = @ptrFromInt(*volatile types.peripherals.I2C0, 0x40048000); /// Control and data interface to SAR ADC - pub const ADC = @intToPtr(*volatile types.peripherals.ADC, 0x4004c000); + pub const ADC = @ptrFromInt(*volatile types.peripherals.ADC, 0x4004c000); /// Simple PWM - pub const PWM = @intToPtr(*volatile types.peripherals.PWM, 0x40050000); + pub const PWM = @ptrFromInt(*volatile types.peripherals.PWM, 0x40050000); /// Controls time and alarms /// time is a 64 bit value indicating the time in usec since power-on /// timeh is the top 32 bits of time & timel is the bottom 32 bits @@ -271,35 +271,35 @@ pub const devices = struct { /// An alarm can be cancelled before it has finished by clearing the alarm_enable /// When an alarm fires, the corresponding alarm_irq is set and alarm_running is cleared /// To clear the interrupt write a 1 to the corresponding alarm_irq - pub const TIMER = @intToPtr(*volatile types.peripherals.TIMER, 0x40054000); - pub const WATCHDOG = @intToPtr(*volatile types.peripherals.WATCHDOG, 0x40058000); + pub const TIMER = @ptrFromInt(*volatile types.peripherals.TIMER, 0x40054000); + pub const WATCHDOG = @ptrFromInt(*volatile types.peripherals.WATCHDOG, 0x40058000); /// Register block to control RTC - pub const RTC = @intToPtr(*volatile types.peripherals.RTC, 0x4005c000); - pub const ROSC = @intToPtr(*volatile types.peripherals.ROSC, 0x40060000); + pub const RTC = @ptrFromInt(*volatile types.peripherals.RTC, 0x4005c000); + pub const ROSC = @ptrFromInt(*volatile types.peripherals.ROSC, 0x40060000); /// control and status for on-chip voltage regulator and chip level reset subsystem - pub const VREG_AND_CHIP_RESET = @intToPtr(*volatile types.peripherals.VREG_AND_CHIP_RESET, 0x40064000); + pub const VREG_AND_CHIP_RESET = @ptrFromInt(*volatile types.peripherals.VREG_AND_CHIP_RESET, 0x40064000); /// Testbench manager. Allows the programmer to know what platform their software is running on. - pub const TBMAN = @intToPtr(*volatile types.peripherals.TBMAN, 0x4006c000); + pub const TBMAN = @ptrFromInt(*volatile types.peripherals.TBMAN, 0x4006c000); /// DMA with separate read and write masters - pub const DMA = @intToPtr(*volatile types.peripherals.DMA, 0x50000000); + pub const DMA = @ptrFromInt(*volatile types.peripherals.DMA, 0x50000000); /// DPRAM layout for USB device. - pub const USBCTRL_DPRAM = @intToPtr(*volatile types.peripherals.USBCTRL_DPRAM, 0x50100000); + pub const USBCTRL_DPRAM = @ptrFromInt(*volatile types.peripherals.USBCTRL_DPRAM, 0x50100000); /// USB FS/LS controller device registers - pub const USBCTRL_REGS = @intToPtr(*volatile types.peripherals.USBCTRL_REGS, 0x50110000); + pub const USBCTRL_REGS = @ptrFromInt(*volatile types.peripherals.USBCTRL_REGS, 0x50110000); /// Programmable IO block - pub const PIO0 = @intToPtr(*volatile types.peripherals.PIO0, 0x50200000); + pub const PIO0 = @ptrFromInt(*volatile types.peripherals.PIO0, 0x50200000); /// Programmable IO block - pub const PIO1 = @intToPtr(*volatile types.peripherals.PIO0, 0x50300000); + pub const PIO1 = @ptrFromInt(*volatile types.peripherals.PIO0, 0x50300000); /// Single-cycle IO block /// Provides core-local and inter-core hardware for the two processors, with single-cycle access. - pub const SIO = @intToPtr(*volatile types.peripherals.SIO, 0xd0000000); - pub const PPB = @intToPtr(*volatile types.peripherals.PPB, 0xe0000000); + pub const SIO = @ptrFromInt(*volatile types.peripherals.SIO, 0xd0000000); + pub const PPB = @ptrFromInt(*volatile types.peripherals.PPB, 0xe0000000); /// System Tick Timer - pub const SysTick = @intToPtr(*volatile types.peripherals.SysTick, 0xe000e010); + pub const SysTick = @ptrFromInt(*volatile types.peripherals.SysTick, 0xe000e010); /// System Control Space - pub const NVIC = @intToPtr(*volatile types.peripherals.NVIC, 0xe000e100); + pub const NVIC = @ptrFromInt(*volatile types.peripherals.NVIC, 0xe000e100); /// System Control Space - pub const SCB = @intToPtr(*volatile types.peripherals.SCB, 0xe000ed00); + pub const SCB = @ptrFromInt(*volatile types.peripherals.SCB, 0xe000ed00); }; }; }; diff --git a/src/hal.zig b/src/hal.zig index 89e2b58..78ebcf2 100644 --- a/src/hal.zig +++ b/src/hal.zig @@ -16,6 +16,7 @@ pub const rand = @import("hal/random.zig"); pub const resets = @import("hal/resets.zig"); pub const rom = @import("hal/rom.zig"); pub const spi = @import("hal/spi.zig"); +pub const i2c = @import("hal/i2c.zig"); pub const time = @import("hal/time.zig"); pub const uart = @import("hal/uart.zig"); pub const usb = @import("hal/usb.zig"); diff --git a/src/hal/adc.zig b/src/hal/adc.zig index 592273b..973db63 100644 --- a/src/hal/adc.zig +++ b/src/hal/adc.zig @@ -17,12 +17,12 @@ pub const Error = error{ /// temp_sensor is not valid because you can refer to it by name. pub fn input(n: u2) Input { - return @intToEnum(Input, n); + return @enumFromInt(Input, n); } /// Enable the ADC controller. pub fn set_enabled(enabled: bool) void { - ADC.CS.modify(.{ .EN = @boolToInt(enabled) }); + ADC.CS.modify(.{ .EN = @intFromBool(enabled) }); } const Config = struct { @@ -41,7 +41,7 @@ const Config = struct { pub fn apply(config: Config) void { ADC.CS.write(.{ .EN = 0, - .TS_EN = @boolToInt(config.temp_sensor_enabled), + .TS_EN = @intFromBool(config.temp_sensor_enabled), .START_ONCE = 0, .START_MANY = 0, .READY = 0, @@ -78,14 +78,14 @@ pub fn apply(config: Config) void { /// Select analog input for next conversion. pub fn select_input(in: Input) void { - ADC.CS.modify(.{ .AINSEL = @enumToInt(in) }); + ADC.CS.modify(.{ .AINSEL = @intFromEnum(in) }); } /// Get the currently selected analog input. 0..3 are GPIO 26..29 respectively, /// 4 is the temperature sensor. pub fn get_selected_input() Input { const cs = ADC.SC.read(); - return @intToEnum(Input, cs.AINSEL); + return @enumFromInt(Input, cs.AINSEL); } pub const Input = enum(u3) { @@ -98,7 +98,7 @@ pub const Input = enum(u3) { /// temp_sensor. pub fn get_gpio_pin(in: Input) gpio.Pin { return switch (in) { - else => gpio.num(@as(u5, @enumToInt(in)) + 26), + else => gpio.num(@as(u5, @intFromEnum(in)) + 26), .temp_sensor => @panic("temp_sensor doesn't have a pin"), }; } @@ -120,13 +120,13 @@ pub const Input = enum(u3) { /// Set to true to power on the temperature sensor. pub fn set_temp_sensor_enabled(enable: bool) void { - ADC.CS.modify(.{ .TS_EN = @boolToInt(enable) }); + ADC.CS.modify(.{ .TS_EN = @intFromBool(enable) }); } /// T must be floating point. pub fn temp_sensor_result_to_celcius(comptime T: type, comptime vref: T, result: u12) T { // TODO: consider fixed-point - const raw = @intToFloat(T, result); + const raw = @floatFromInt(T, result); const voltage: T = vref * raw / 0x0fff; return (27.0 - ((voltage - 0.706) / 0.001721)); } @@ -228,9 +228,9 @@ pub const fifo = struct { /// Apply ADC FIFO configuration and enable it pub fn apply(config: fifo.Config) void { ADC.FCS.write(.{ - .DREQ_EN = @boolToInt(config.dreq_enabled), + .DREQ_EN = @intFromBool(config.dreq_enabled), .THRESH = config.thresh, - .SHIFT = @boolToInt(config.shift), + .SHIFT = @intFromBool(config.shift), .EN = 1, .EMPTY = 0, @@ -260,7 +260,7 @@ pub const fifo = struct { pub fn irq_set_enabled(enable: bool) void { // TODO: check if this works ADC.INTE.write(.{ - .FIFO = @boolToInt(enable), + .FIFO = @intFromBool(enable), .padding = 0, }); } diff --git a/src/hal/clocks.zig b/src/hal/clocks.zig index b13ebd3..cb5350f 100644 --- a/src/hal/clocks.zig +++ b/src/hal/clocks.zig @@ -86,7 +86,7 @@ pub const Generator = enum(u32) { const generators = @ptrCast(*volatile [@typeInfo(Generator).Enum.fields.len]GeneratorRegs, CLOCKS); fn get_regs(generator: Generator) *volatile GeneratorRegs { - return &generators[@enumToInt(generator)]; + return &generators[@intFromEnum(generator)]; } pub fn has_glitchless_mux(generator: Generator) bool { @@ -666,7 +666,7 @@ pub fn count_frequency_khz(source: Source, comptime clock_config: GlobalConfigur CLOCKS.FC0_INTERVAL.raw = 10; CLOCKS.FC0_MIN_KHZ.raw = 0; CLOCKS.FC0_MAX_KHZ.raw = std.math.maxInt(u32); - CLOCKS.FC0_SRC.raw = @enumToInt(source); + CLOCKS.FC0_SRC.raw = @intFromEnum(source); while (CLOCKS.FC0_STATUS.read().DONE != 1) {} diff --git a/src/hal/dma.zig b/src/hal/dma.zig index ded0a8c..35b285a 100644 --- a/src/hal/dma.zig +++ b/src/hal/dma.zig @@ -19,7 +19,7 @@ pub const Dreq = enum(u6) { pub fn channel(n: u4) Channel { assert(n < num_channels); - return @intToEnum(Channel, n); + return @enumFromInt(Channel, n); } pub fn claim_unused_channel() ?Channel { @@ -43,11 +43,11 @@ pub const Channel = enum(u4) { } pub fn unclaim(chan: Channel) void { - claimed_channels.set(@enumToInt(chan), false); + claimed_channels.set(@intFromEnum(chan), false); } pub fn is_claimed(chan: Channel) bool { - return claimed_channels.get(@enumToInt(chan)); + return claimed_channels.get(@intFromEnum(chan)); } const Regs = extern struct { @@ -77,7 +77,7 @@ pub const Channel = enum(u4) { fn get_regs(chan: Channel) *volatile Regs { const regs = @ptrCast(*volatile [12]Regs, &DMA.CH0_READ_ADDR); - return ®s[@enumToInt(chan)]; + return ®s[@intFromEnum(chan)]; } pub const TransferConfig = struct { @@ -105,14 +105,14 @@ pub const Channel = enum(u4) { regs.write_addr = write_addr; regs.trans_count = count; regs.ctrl_trig.modify(.{ - .EN = @boolToInt(config.enable), + .EN = @intFromBool(config.enable), .DATA_SIZE = .{ .value = .SIZE_BYTE, }, - .INCR_READ = @boolToInt(config.read_increment), - .INCR_WRITE = @boolToInt(config.write_increment), + .INCR_READ = @intFromBool(config.read_increment), + .INCR_WRITE = @intFromBool(config.write_increment), .TREQ_SEL = .{ - .raw = @enumToInt(config.dreq), + .raw = @intFromEnum(config.dreq), }, }); } @@ -120,16 +120,16 @@ pub const Channel = enum(u4) { pub fn set_irq0_enabled(chan: Channel, enabled: bool) void { if (enabled) { const inte0_set = hw.set_alias_raw(&DMA.INTE0); - inte0_set.* = @as(u32, 1) << @enumToInt(chan); + inte0_set.* = @as(u32, 1) << @intFromEnum(chan); } else { const inte0_clear = hw.clear_alias_raw(&DMA.INTE0); - inte0_clear.* = @as(u32, 1) << @enumToInt(chan); + inte0_clear.* = @as(u32, 1) << @intFromEnum(chan); } } pub fn acknowledge_irq0(chan: Channel) void { const ints0_set = hw.set_alias_raw(&DMA.INTS0); - ints0_set.* = @as(u32, 1) << @enumToInt(chan); + ints0_set.* = @as(u32, 1) << @intFromEnum(chan); } pub fn is_busy(chan: Channel) bool { diff --git a/src/hal/flash.zig b/src/hal/flash.zig index a7404b1..cb86c72 100644 --- a/src/hal/flash.zig +++ b/src/hal/flash.zig @@ -23,7 +23,7 @@ pub const boot2 = struct { /// Copy the 2nd stage bootloader into memory pub fn flash_init() linksection(".time_critical") void { if (copyout_valid) return; - const bootloader = @intToPtr([*]u32, XIP_BASE); + const bootloader = @ptrFromInt([*]u32, XIP_BASE); var i: usize = 0; while (i < BOOT2_SIZE_BYTES) : (i += 1) { copyout[i] = bootloader[i]; @@ -55,7 +55,7 @@ pub fn range_erase(offset: u32, count: u32) linksection(".time_critical") void { rom.connect_internal_flash()(); rom.flash_exit_xip()(); - rom.flash_range_erase()(offset, count, BLOCK_SIZE, @enumToInt(Command.block_erase)); + rom.flash_range_erase()(offset, count, BLOCK_SIZE, @intFromEnum(Command.block_erase)); rom.flash_flush_cache()(); boot2.flash_enable_xip(); diff --git a/src/hal/gpio.zig b/src/hal/gpio.zig index 53d3b0b..3b9e5ae 100644 --- a/src/hal/gpio.zig +++ b/src/hal/gpio.zig @@ -72,18 +72,18 @@ pub fn num(n: u5) Pin { if (n > 29) @panic("the RP2040 only has GPIO 0-29"); - return @intToEnum(Pin, n); + return @enumFromInt(Pin, n); } pub fn mask(m: u32) Mask { - return @intToEnum(Mask, m); + return @enumFromInt(Mask, m); } pub const Mask = enum(u30) { _, pub fn set_function(self: Mask, function: Function) void { - const raw_mask = @enumToInt(self); + const raw_mask = @intFromEnum(self); for (0..@bitSizeOf(Mask)) |i| { const bit = @intCast(u5, i); if (0 != raw_mask & (@as(u32, 1) << bit)) @@ -92,7 +92,7 @@ pub const Mask = enum(u30) { } pub fn set_direction(self: Mask, direction: Direction) void { - const raw_mask = @enumToInt(self); + const raw_mask = @intFromEnum(self); switch (direction) { .out => SIO.GPIO_OE_SET.raw = raw_mask, .in => SIO.GPIO_OE_CLR.raw = raw_mask, @@ -100,7 +100,7 @@ pub const Mask = enum(u30) { } pub fn set_pull(self: Mask, pull: ?Pull) void { - const raw_mask = @enumToInt(self); + const raw_mask = @intFromEnum(self); for (0..@bitSizeOf(Mask)) |i| { const bit = @intCast(u5, i); if (0 != raw_mask & (@as(u32, 1) << bit)) @@ -109,11 +109,11 @@ pub const Mask = enum(u30) { } pub fn put(self: Mask, value: u32) void { - SIO.GPIO_OUT_XOR.raw = (SIO.GPIO_OUT.raw ^ value) & @enumToInt(self); + SIO.GPIO_OUT_XOR.raw = (SIO.GPIO_OUT.raw ^ value) & @intFromEnum(self); } pub fn read(self: Mask) u32 { - return SIO.GPIO_IN.raw & @enumToInt(self); + return SIO.GPIO_IN.raw & @intFromEnum(self); } }; @@ -155,16 +155,16 @@ pub const Pin = enum(u5) { fn get_regs(gpio: Pin) *volatile Regs { const regs = @ptrCast(*volatile [30]Regs, &IO_BANK0.GPIO0_STATUS); - return ®s[@enumToInt(gpio)]; + return ®s[@intFromEnum(gpio)]; } fn get_pads_reg(gpio: Pin) *volatile PadsReg { const regs = @ptrCast(*volatile [30]PadsReg, &PADS_BANK0.GPIO0); - return ®s[@enumToInt(gpio)]; + return ®s[@intFromEnum(gpio)]; } pub fn mask(gpio: Pin) u32 { - return @as(u32, 1) << @enumToInt(gpio); + return @as(u32, 1) << @intFromEnum(gpio); } pub inline fn set_pull(gpio: Pin, pull: ?Pull) void { @@ -206,7 +206,7 @@ pub const Pin = enum(u5) { pub inline fn set_input_enabled(pin: Pin, enabled: bool) void { const pads_reg = pin.get_pads_reg(); - pads_reg.modify(.{ .IE = @boolToInt(enabled) }); + pads_reg.modify(.{ .IE = @intFromBool(enabled) }); } pub inline fn set_function(gpio: Pin, function: Function) void { diff --git a/src/hal/hw.zig b/src/hal/hw.zig index 89aee45..28a1981 100644 --- a/src/hal/hw.zig +++ b/src/hal/hw.zig @@ -20,27 +20,27 @@ const set_bits = @as(u32, 0x2) << 12; const clear_bits = @as(u32, 0x3) << 12; pub fn clear_alias_raw(ptr: anytype) *volatile u32 { - return @intToPtr(*volatile u32, @ptrToInt(ptr) | clear_bits); + return @ptrFromInt(*volatile u32, @intFromPtr(ptr) | clear_bits); } pub fn set_alias_raw(ptr: anytype) *volatile u32 { - return @intToPtr(*volatile u32, @ptrToInt(ptr) | set_bits); + return @ptrFromInt(*volatile u32, @intFromPtr(ptr) | set_bits); } pub fn xor_alias_raw(ptr: anytype) *volatile u32 { - return @intToPtr(*volatile u32, @ptrToInt(ptr) | xor_bits); + return @ptrFromInt(*volatile u32, @intFromPtr(ptr) | xor_bits); } pub fn clear_alias(ptr: anytype) @TypeOf(ptr) { - return @intToPtr(@TypeOf(ptr), @ptrToInt(ptr) | clear_bits); + return @ptrFromInt(@TypeOf(ptr), @intFromPtr(ptr) | clear_bits); } pub fn set_alias(ptr: anytype) @TypeOf(ptr) { - return @intToPtr(@TypeOf(ptr), @ptrToInt(ptr) | set_bits); + return @ptrFromInt(@TypeOf(ptr), @intFromPtr(ptr) | set_bits); } pub fn xor_alias(ptr: anytype) @TypeOf(ptr) { - return @intToPtr(@TypeOf(ptr), @ptrToInt(ptr) | xor_bits); + return @ptrFromInt(@TypeOf(ptr), @intFromPtr(ptr) | xor_bits); } pub inline fn tight_loop_contents() void { diff --git a/src/hal/i2c.zig b/src/hal/i2c.zig new file mode 100644 index 0000000..cc7467e --- /dev/null +++ b/src/hal/i2c.zig @@ -0,0 +1,413 @@ +const std = @import("std"); +const microzig = @import("microzig"); +const peripherals = microzig.chip.peripherals; +const I2C0 = peripherals.I2C0; +const I2C1 = peripherals.I2C1; + +const gpio = @import("gpio.zig"); +const clocks = @import("clocks.zig"); +const resets = @import("resets.zig"); +const time = @import("time.zig"); +const hw = @import("hw.zig"); + +const I2cRegs = microzig.chip.types.peripherals.I2C0; + +pub const Config = struct { + clock_config: clocks.GlobalConfiguration, + sda_pin: ?gpio.Pin = gpio.num(20), // both pins only have I²C as alternate function + scl_pin: ?gpio.Pin = gpio.num(21), // both pins only have I²C as alternate function + baud_rate: u32 = 100_000, +}; + +pub fn num(n: u1) I2C { + return @enumFromInt(I2C, n); +} + +pub const Address = enum(u7) { + _, + + pub fn new(addr: u7) Address { + var a = @enumFromInt(Address, addr); + std.debug.assert(!a.is_reserved()); + return a; + } + + pub fn is_reserved(addr: Address) bool { + return ((@intFromEnum(addr) & 0x78) == 0) or ((@intFromEnum(addr) & 0x78) == 0x78); + } + + pub fn format(addr: Address, fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { + _ = fmt; + _ = options; + try writer.print("I2C(0x{X:0>2}", .{@intFromEnum(addr)}); + } +}; + +pub const I2C = enum(u1) { + _, + + fn get_regs(i2c: I2C) *volatile I2cRegs { + return switch (@intFromEnum(i2c)) { + 0 => I2C0, + 1 => I2C1, + }; + } + + fn disable(i2c: I2C) void { + i2c.get_regs().IC_ENABLE.write(.{ + .ENABLE = .{ .value = .DISABLED }, + .ABORT = .{ .value = .DISABLE }, + .TX_CMD_BLOCK = .{ .value = .NOT_BLOCKED }, + .padding = 0, + }); + } + + fn enable(i2c: I2C) void { + i2c.get_regs().IC_ENABLE.write(.{ + .ENABLE = .{ .value = .ENABLED }, + .ABORT = .{ .value = .DISABLE }, + .TX_CMD_BLOCK = .{ .value = .NOT_BLOCKED }, + .padding = 0, + }); + } + + /// Initialise the I2C HW block. + pub fn apply(i2c: I2C, comptime config: Config) u32 { + const peri_freq = (comptime config.clock_config.get_frequency(.clk_sys)) orelse @compileError("clk_sys must be set for I²C"); + + const regs = i2c.get_regs(); + + i2c.disable(); + + regs.IC_ENABLE.write(.{ + .ENABLE = .{ .value = .DISABLED }, + .ABORT = .{ .value = .DISABLE }, + .TX_CMD_BLOCK = .{ .value = .NOT_BLOCKED }, + .padding = 0, + }); + + // Configure as a fast-mode master with RepStart support, 7-bit addresses + regs.IC_CON.write(.{ + .MASTER_MODE = .{ .value = .ENABLED }, + .SPEED = .{ .value = .FAST }, + .IC_RESTART_EN = .{ .value = .ENABLED }, + .IC_SLAVE_DISABLE = .{ .value = .SLAVE_DISABLED }, + .TX_EMPTY_CTRL = .{ .value = .ENABLED }, + + .IC_10BITADDR_SLAVE = .{ .raw = 0 }, + .IC_10BITADDR_MASTER = .{ .raw = 0 }, + .STOP_DET_IFADDRESSED = .{ .raw = 0 }, + .RX_FIFO_FULL_HLD_CTRL = .{ .raw = 0 }, + .STOP_DET_IF_MASTER_ACTIVE = 0, + .padding = 0, + }); + + // Set FIFO watermarks to 1 to make things simpler. This is encoded by a register value of 0. + regs.IC_RX_TL.write(.{ .RX_TL = 0, .padding = 0 }); + regs.IC_TX_TL.write(.{ .TX_TL = 0, .padding = 0 }); + + // Always enable the DREQ signalling -- harmless if DMA isn't listening + regs.IC_DMA_CR.write(.{ + .RDMAE = .{ .value = .ENABLED }, + .TDMAE = .{ .value = .ENABLED }, + .padding = 0, + }); + + if (config.sda_pin) |pin| { + pin.set_function(.i2c); + pin.set_pull(.up); + // TODO: Set slew rate + } + if (config.scl_pin) |pin| { + pin.set_function(.i2c); + pin.set_pull(.up); + // TODO: Set slew rate + } + + // Re-sets regs.enable upon returning: + return i2c.set_baudrate(config.baud_rate, peri_freq); + } + + /// Set I2C baudrate. + pub fn set_baudrate(i2c: I2C, baud_rate: u32, freq_in: u32) u32 { + std.debug.assert(baud_rate != 0); + // I2C is synchronous design that runs from clk_sys + + const regs = i2c.get_regs(); + + // TODO there are some subtleties to I2C timing which we are completely ignoring here + const period: u32 = (freq_in + baud_rate / 2) / baud_rate; + const lcnt: u32 = period * 3 / 5; // oof this one hurts + const hcnt: u32 = period - lcnt; + + // Check for out-of-range divisors: + std.debug.assert(hcnt <= std.math.maxInt(u16)); + std.debug.assert(lcnt <= std.math.maxInt(u16)); + std.debug.assert(hcnt >= 8); + std.debug.assert(lcnt >= 8); + + // Per I2C-bus specification a device in standard or fast mode must + // internally provide a hold time of at least 300ns for the SDA signal to + // bridge the undefined region of the falling edge of SCL. A smaller hold + // time of 120ns is used for fast mode plus. + const sda_tx_hold_count: u32 = if (baud_rate < 1_000_000) + // sda_tx_hold_count = freq_in [cycles/s] * 300ns * (1s / 1e9ns) + // Reduce 300/1e9 to 3/1e7 to avoid numbers that don't fit in uint. + // Add 1 to avoid division truncation. + ((freq_in * 3) / 10000000) + 1 + else + // sda_tx_hold_count = freq_in [cycles/s] * 120ns * (1s / 1e9ns) + // Reduce 120/1e9 to 3/25e6 to avoid numbers that don't fit in uint. + // Add 1 to avoid division truncation. + ((freq_in * 3) / 25000000) + 1; + + std.debug.assert(sda_tx_hold_count <= lcnt - 2); + + i2c.disable(); + + // Always use "fast" mode (<= 400 kHz, works fine for standard mode too) + regs.IC_CON.modify(.{ .SPEED = .{ .value = .FAST } }); + regs.IC_FS_SCL_HCNT.write(.{ .IC_FS_SCL_HCNT = @intCast(u16, hcnt), .padding = 0 }); + regs.IC_FS_SCL_LCNT.write(.{ .IC_FS_SCL_LCNT = @intCast(u16, lcnt), .padding = 0 }); + regs.IC_FS_SPKLEN.write(.{ .IC_FS_SPKLEN = if (lcnt < 16) 1 else @intCast(u8, lcnt / 16), .padding = 0 }); + regs.IC_SDA_HOLD.modify(.{ .IC_SDA_TX_HOLD = @intCast(u16, sda_tx_hold_count) }); + + i2c.enable(); + + return freq_in / period; + } + + // /// Set I2C port to slave mode. + // pub fn set_slave_mode(i2c: I2C, slave: bool, addr: u8) void { + // // + // } + + pub const WriteBlockingUntilError = error{ DeviceNotPresent, NoAcknowledge, Timeout }; + + /// Attempt to write specified number of bytes to address, blocking until the specified absolute time is reached. + pub fn write_blocking_until(i2c: I2C, addr: Address, src: []const u8, until: time.Absolute) WriteBlockingUntilError!usize { + const Timeout = struct { + limit: time.Absolute, + inline fn perform(tc: @This()) !void { + if (tc.limit.is_reached()) + return error.Timeout; + } + }; + return i2c.write_blocking_internal(addr, src, Timeout{ .limit = until }); + } + + pub const ReadBlockingUntilError = error{ DeviceNotPresent, NoAcknowledge, Timeout }; + + /// Attempt to read specified number of bytes from address, blocking until the specified absolute time is reached. + pub fn read_blocking_until(i2c: I2C, addr: Address, dst: []u8, until: time.Absolute) ReadBlockingUntilError!usize { + const Timeout = struct { + limit: time.Absolute, + inline fn perform(tc: @This()) !void { + if (tc.limit.is_reached()) + return error.Timeout; + } + }; + return i2c.read_blocking_internal(addr, dst, Timeout{ .limit = until }); + } + + pub const WriteTimeoutUsError = error{ DeviceNotPresent, NoAcknowledge, Timeout }; + + /// Attempt to write specified number of bytes to address, with timeout. + pub fn write_timeout_us(i2c: I2C, addr: Address, src: []const u8, timeout: time.Duration) WriteTimeoutUsError!usize { + return i2c.write_blocking_until(addr, src, time.get_time_since_boot().add_duration(timeout)); + } + + pub const ReadTimeoutUsError = error{ DeviceNotPresent, NoAcknowledge, Timeout }; + + /// Attempt to read specified number of bytes from address, with timeout. + pub fn read_timeout_us(i2c: I2C, addr: Address, dst: []u8, timeout: time.Duration) ReadTimeoutUsError!usize { + return i2c.read_blocking_until(addr, dst, time.get_time_since_boot().add_duration(timeout)); + } + + /// Attempt to write specified number of bytes to address, blocking. + pub const WriteBlockingError = error{ DeviceNotPresent, NoAcknowledge, Unexpected }; + pub fn write_blocking(i2c: I2C, addr: Address, src: []const u8) WriteBlockingError!usize { + const Timeout = struct { + inline fn perform(tc: @This()) !void { + _ = tc; + } + }; + return try i2c.write_blocking_internal(addr, src, Timeout{}); + } + + /// Attempt to read specified number of bytes from address, blocking. + pub const ReadBlockingError = error{ DeviceNotPresent, NoAcknowledge, Unexpected }; + pub fn read_blocking(i2c: I2C, addr: Address, dst: []u8) ReadBlockingError!usize { + const Timeout = struct { + inline fn perform(tc: @This()) !void { + _ = tc; + } + }; + try i2c.read_blocking_internal(addr, dst, Timeout{}); + } + + /// Determine non-blocking write space available. + pub inline fn get_write_available(i2c: I2C) u5 { + return i2c.get_regs().IC_TXFLR.read().TXFLR; + } + + /// Determine number of bytes received. + pub inline fn get_read_available(i2c: I2C) u5 { + return i2c.get_regs().IC_RXFLR.read().RXFLR; + } + + // /// Write direct to TX FIFO. + // pub fn write_raw_blocking(i2c: I2C, src: []const u8) void { + // // + // } + + // /// Read direct from RX FIFO. + // pub fn read_raw_blocking(i2c: I2C, dst: []u8) void { + // // + // } + + // /// Pop a byte from I2C Rx FIFO. + // pub fn read_byte_raw(i2c: I2C) u8 { + // // + // } + + // /// Push a byte into I2C Tx FIFO. + // pub fn write_byte_raw(i2c: I2C, value: u8) void { + // // + // } + + // /// Return the DREQ to use for pacing transfers to/from a particular I2C instance. + // pub fn get_dreq(i2c: I2C, is_tx: bool) u32 { + // // + // } + + fn set_address(i2c: I2C, addr: Address) void { + i2c.disable(); + i2c.get_regs().IC_TAR.write(.{ + .IC_TAR = @intFromEnum(addr), + .GC_OR_START = .{ .value = .GENERAL_CALL }, + .SPECIAL = .{ .value = .DISABLED }, + .padding = 0, + }); + i2c.enable(); + } + + fn write_blocking_internal(i2c: I2C, addr: Address, src: []const u8, timeout_check: anytype) !usize { + std.debug.assert(!addr.is_reserved()); + // Synopsys hw accepts start/stop flags alongside data items in the same + // FIFO word, so no 0 byte transfers. + std.debug.assert(src.len > 0); + + const regs = i2c.get_regs(); + + i2c.set_address(addr); + + { + // If the transaction was aborted or if it completed + // successfully wait until the STOP condition has occured. + defer blk: { + + // TODO Could there be an abort while waiting for the STOP + // condition here? If so, additional code would be needed here + // to take care of the abort. + while (regs.IC_RAW_INTR_STAT.read().STOP_DET.value == .INACTIVE) { + timeout_check.perform() catch break :blk; + hw.tight_loop_contents(); + } + + // If there was a timeout, don't attempt to do anything else. + _ = regs.IC_CLR_STOP_DET.read(); + } + + for (src, 0..) |byte, i| { + const first = (i == 0); + const last = (i == (src.len - 1)); + + regs.IC_DATA_CMD.write(.{ + .RESTART = .{ .raw = @intFromBool(first) }, // TODO: Implement non-restarting variant + .STOP = .{ .raw = @intFromBool(last) }, // TODO: Implement non-restarting variant + .CMD = .{ .value = .WRITE }, + .DAT = byte, + + .FIRST_DATA_BYTE = .{ .value = .INACTIVE }, + .padding = 0, + }); + + // Wait until the transmission of the address/data from the internal + // shift register has completed. For this to function correctly, the + // TX_EMPTY_CTRL flag in IC_CON must be set. The TX_EMPTY_CTRL flag + // was set in i2c_init. + while (regs.IC_RAW_INTR_STAT.read().TX_EMPTY.value == .INACTIVE) { + try timeout_check.perform(); + hw.tight_loop_contents(); + } + + const abort_reason = regs.IC_TX_ABRT_SOURCE.read(); + if (@bitCast(u32, abort_reason) != 0) { + // Note clearing the abort flag also clears the reason, and + // this instance of flag is clear-on-read! Note also the + // IC_CLR_TX_ABRT register always reads as 0. + _ = regs.IC_CLR_TX_ABRT.read(); + + if (abort_reason.ABRT_7B_ADDR_NOACK.value == .ACTIVE) { + // No reported errors - seems to happen if there is nothing connected to the bus. + // Address byte not acknowledged + return error.DeviceNotPresent; + } + if (abort_reason.ABRT_TXDATA_NOACK.value == .ABRT_TXDATA_NOACK_GENERATED) { + // TODO: How to handle this, also possible to do "return i;" here to signal not everything was transferred + return error.NoAcknowledge; + } + + std.log.debug("unexpected i2c abort while writing to {}: {}", .{ addr, abort_reason }); + return error.Unexpected; + } + } + } + + return src.len; + } + + fn read_blocking_internal(i2c: I2C, addr: Address, dst: []u8, timeout_check: anytype) !usize { + std.debug.assert(!addr.is_reserved()); + + const regs = i2c.get_regs(); + + i2c.set_address(addr); + + for (dst, 0..) |*byte, i| { + const first = (i == 0); + const last = (i == dst.len - 1); + while (i2c.get_write_available(i2c) == 0) { + hw.tight_loop_contents(); + } + + regs.IC_DATA_CMD.write(.{ + .RESTART = .{ .raw = @intFromBool(first) }, // TODO: Implement non-restarting variant + .STOP = .{ .raw = @intFromBool(last) }, // TODO: Implement non-restarting variant + .CMD = .{ .value = .READ }, + + .DAT = 0, + .FIRST_DATA_BYTE = .{ .value = 0 }, + .padding = 0, + }); + + while (i2c.get_read_available() == 0) { + const abort_reason = regs.IC_TX_ABRT_SOURCE.read(); + const abort = (regs.IC_CLR_TX_ABRT.read().CLR_TX_ABRT != 0); + if (abort) { + if (abort_reason.ABRT_7B_ADDR_NOACK.value == .ACTIVE) + return error.DeviceNotPresent; + std.log.debug("unexpected i2c abort while reading from {}: {}", .{ addr, abort_reason }); + return error.Unexpected; + } + + try timeout_check.perform(); + } + + byte.* = regs.IC_DATA_CMD.read().DAT; + } + + return dst.len; + } +}; diff --git a/src/hal/multicore.zig b/src/hal/multicore.zig index e3199d9..bc2b4de 100644 --- a/src/hal/multicore.zig +++ b/src/hal/multicore.zig @@ -70,7 +70,7 @@ pub fn launch_core1_with_stack(entrypoint: *const fn () void, stack: []u32) void fn wrapper(_: u32, _: u32, _: u32, _: u32, entry: u32, stack_base: [*]u32) callconv(.C) void { // TODO: protect stack using MPU _ = stack_base; - @intToPtr(*const fn () void, entry)(); + @ptrFromInt(*const fn () void, entry)(); } }.wrapper; @@ -79,12 +79,12 @@ pub fn launch_core1_with_stack(entrypoint: *const fn () void, stack: []u32) void while (PSM.FRCE_OFF.read().proc1 != 1) microzig.cpu.nop(); PSM.FRCE_OFF.modify(.{ .proc1 = 0 }); - stack[stack.len - 2] = @ptrToInt(entrypoint); - stack[stack.len - 1] = @ptrToInt(stack.ptr); + stack[stack.len - 2] = @intFromPtr(entrypoint); + stack[stack.len - 1] = @intFromPtr(stack.ptr); // calculate top of the stack const stack_ptr: u32 = - @ptrToInt(stack.ptr) + + @intFromPtr(stack.ptr) + (stack.len - 2) * @sizeOf(u32); // pop the two elements we "pushed" above // after reseting core1 is waiting for this specific sequence @@ -94,7 +94,7 @@ pub fn launch_core1_with_stack(entrypoint: *const fn () void, stack: []u32) void 1, SCB.VTOR.raw, stack_ptr, - @ptrToInt(wrapper), + @intFromPtr(wrapper), }; var seq: usize = 0; diff --git a/src/hal/pins.zig b/src/hal/pins.zig index f232092..5de0810 100644 --- a/src/hal/pins.zig +++ b/src/hal/pins.zig @@ -355,7 +355,7 @@ pub fn Pins(comptime config: GlobalConfiguration) type { if (pin_config.function == .SIO) { pin_field.name = pin_config.name orelse field.name; - pin_field.type = GPIO(@enumToInt(@field(Pin, field.name)), pin_config.direction orelse .in); + pin_field.type = GPIO(@intFromEnum(@field(Pin, field.name)), pin_config.direction orelse .in); } else if (pin_config.function.is_pwm()) { pin_field.name = pin_config.name orelse @tagName(pin_config.function); pin_field.type = pwm.Pwm(pin_config.function.pwm_slice(), pin_config.function.pwm_channel()); @@ -450,8 +450,8 @@ pub const GlobalConfiguration = struct { comptime { inline for (@typeInfo(GlobalConfiguration).Struct.fields) |field| if (@field(config, field.name)) |pin_config| { - const gpio_num = @enumToInt(@field(Pin, field.name)); - if (0 == function_table[@enumToInt(pin_config.function)][gpio_num]) + const gpio_num = @intFromEnum(@field(Pin, field.name)); + if (0 == function_table[@intFromEnum(pin_config.function)][gpio_num]) @compileError(comptimePrint("{s} cannot be configured for {}", .{ field.name, pin_config.function })); if (pin_config.function == .SIO) { @@ -481,7 +481,7 @@ pub const GlobalConfiguration = struct { inline for (@typeInfo(GlobalConfiguration).Struct.fields) |field| { if (@field(config, field.name)) |pin_config| { - const pin = gpio.num(@enumToInt(@field(Pin, field.name))); + const pin = gpio.num(@intFromEnum(@field(Pin, field.name))); const func = pin_config.function; // xip = 0, @@ -505,7 +505,7 @@ pub const GlobalConfiguration = struct { } else { @compileError(std.fmt.comptimePrint("Unimplemented pin function. Please implement setting pin function {s} for GPIO {}", .{ @tagName(func), - @enumToInt(pin), + @intFromEnum(pin), })); } } @@ -517,7 +517,7 @@ pub const GlobalConfiguration = struct { if (input_gpios != 0) { inline for (@typeInfo(GlobalConfiguration).Struct.fields) |field| if (@field(config, field.name)) |pin_config| { - const gpio_num = @enumToInt(@field(Pin, field.name)); + const gpio_num = @intFromEnum(@field(Pin, field.name)); const pull = pin_config.pull orelse continue; if (comptime pin_config.get_direction() != .in) @compileError("Only input pins can have pull up/down enabled"); diff --git a/src/hal/pio.zig b/src/hal/pio.zig index 2943a3f..6b7ca1f 100644 --- a/src/hal/pio.zig +++ b/src/hal/pio.zig @@ -74,7 +74,7 @@ pub const ClkDivOptions = struct { frac: u8 = 0, pub fn from_float(div: f32) ClkDivOptions { - const fixed = @floatToInt(u24, div * 256); + const fixed = @intFromFloat(u24, div * 256); return ClkDivOptions{ .int = @truncate(u16, fixed >> 8), .frac = @truncate(u8, fixed), @@ -169,7 +169,7 @@ pub const Pio = enum(u1) { if (origin != offset) return false; - const used_mask = used_instruction_space[@enumToInt(self)]; + const used_mask = used_instruction_space[@intFromEnum(self)]; const program_mask = program.get_mask(); // We can add the program if the masks don't overlap, if there is @@ -199,7 +199,7 @@ pub const Pio = enum(u1) { instruction_memory[i] = insn; const program_mask = program.get_mask(); - used_instruction_space[@enumToInt(self)] |= program_mask << offset; + used_instruction_space[@intFromEnum(self)] |= program_mask << offset; } /// Public functions will need to lock independently, so only exposing this function for now @@ -216,12 +216,12 @@ pub const Pio = enum(u1) { // TODO: const lock = hw.Lock.claim() // defer lock.unlock(); - const claimed_mask = claimed_state_machines[@enumToInt(self)]; + const claimed_mask = claimed_state_machines[@intFromEnum(self)]; return for (0..4) |i| { const sm_mask = (@as(u4, 1) << @intCast(u2, i)); if (0 == (claimed_mask & sm_mask)) { - claimed_state_machines[@enumToInt(self)] |= sm_mask; - break @intToEnum(StateMachine, i); + claimed_state_machines[@intFromEnum(self)] |= sm_mask; + break @enumFromInt(StateMachine, i); } } else error.NoSpace; } @@ -229,13 +229,13 @@ pub const Pio = enum(u1) { pub fn get_sm_regs(self: Pio, sm: StateMachine) *volatile StateMachine.Regs { const pio_regs = self.get_regs(); const sm_regs = @ptrCast(*volatile [4]StateMachine.Regs, &pio_regs.SM0_CLKDIV); - return &sm_regs[@enumToInt(sm)]; + return &sm_regs[@intFromEnum(sm)]; } fn get_irq_regs(self: Pio, irq: Irq) *volatile Irq.Regs { const pio_regs = self.get_regs(); const irq_regs = @ptrCast(*volatile [2]Irq.Regs, &pio_regs.IRQ0_INTE); - return &irq_regs[@enumToInt(irq)]; + return &irq_regs[@intFromEnum(irq)]; } pub fn sm_set_clkdiv(self: Pio, sm: StateMachine, options: ClkDivOptions) void { @@ -256,8 +256,8 @@ pub const Pio = enum(u1) { sm_regs.execctrl.modify(.{ .WRAP_BOTTOM = options.wrap_target, .WRAP_TOP = options.wrap, - .SIDE_PINDIR = @boolToInt(options.side_pindir), - .SIDE_EN = @boolToInt(options.side_set_optional), + .SIDE_PINDIR = @intFromBool(options.side_pindir), + .SIDE_EN = @intFromBool(options.side_set_optional), // TODO: plug in rest of the options // STATUS_N @@ -273,17 +273,17 @@ pub const Pio = enum(u1) { pub fn sm_set_shift_options(self: Pio, sm: StateMachine, options: ShiftOptions) void { const sm_regs = self.get_sm_regs(sm); sm_regs.shiftctrl.write(.{ - .AUTOPUSH = @boolToInt(options.autopush), - .AUTOPULL = @boolToInt(options.autopull), + .AUTOPUSH = @intFromBool(options.autopush), + .AUTOPULL = @intFromBool(options.autopull), - .IN_SHIFTDIR = @enumToInt(options.in_shiftdir), - .OUT_SHIFTDIR = @enumToInt(options.out_shiftdir), + .IN_SHIFTDIR = @intFromEnum(options.in_shiftdir), + .OUT_SHIFTDIR = @intFromEnum(options.out_shiftdir), .PUSH_THRESH = options.push_threshold, .PULL_THRESH = options.pull_threshold, - .FJOIN_TX = @boolToInt(options.join_tx), - .FJOIN_RX = @boolToInt(options.join_rx), + .FJOIN_TX = @intFromBool(options.join_tx), + .FJOIN_RX = @intFromBool(options.join_rx), .reserved16 = 0, }); @@ -308,13 +308,13 @@ pub const Pio = enum(u1) { pub fn sm_is_tx_fifo_full(self: Pio, sm: StateMachine) bool { const regs = self.get_regs(); const txfull = regs.FSTAT.read().TXFULL; - return (txfull & (@as(u4, 1) << @enumToInt(sm))) != 0; + return (txfull & (@as(u4, 1) << @intFromEnum(sm))) != 0; } pub fn sm_get_tx_fifo(self: Pio, sm: StateMachine) *volatile u32 { const regs = self.get_regs(); const fifos = @ptrCast(*volatile [4]u32, ®s.TXF0); - return &fifos[@enumToInt(sm)]; + return &fifos[@intFromEnum(sm)]; } /// this function writes to the TX FIFO without checking that it's @@ -335,16 +335,16 @@ pub const Pio = enum(u1) { var value = regs.CTRL.read(); if (enabled) - value.SM_ENABLE |= @as(u4, 1) << @enumToInt(sm) + value.SM_ENABLE |= @as(u4, 1) << @intFromEnum(sm) else - value.SM_ENABLE &= ~(@as(u4, 1) << @enumToInt(sm)); + value.SM_ENABLE &= ~(@as(u4, 1) << @intFromEnum(sm)); regs.CTRL.write(value); } fn sm_clear_debug(self: Pio, sm: StateMachine) void { const regs = self.get_regs(); - const mask: u4 = (@as(u4, 1) << @enumToInt(sm)); + const mask: u4 = (@as(u4, 1) << @intFromEnum(sm)); // write 1 to clear this register regs.FDEBUG.modify(.{ @@ -377,7 +377,7 @@ pub const Pio = enum(u1) { } pub fn sm_fifo_level(self: Pio, sm: StateMachine, fifo: Fifo) u4 { - const num = @enumToInt(sm); + const num = @intFromEnum(sm); const offset: u5 = switch (fifo) { .tx => 0, .rx => 4, @@ -393,7 +393,7 @@ pub const Pio = enum(u1) { sm: StateMachine, source: Irq.Source, ) u5 { - return (@as(u5, 4) * @enumToInt(source)) + @enumToInt(sm); + return (@as(u5, 4) * @intFromEnum(source)) + @intFromEnum(sm); } pub fn sm_clear_interrupt( @@ -420,7 +420,7 @@ pub const Pio = enum(u1) { } pub fn sm_restart(self: Pio, sm: StateMachine) void { - const mask: u4 = (@as(u4, 1) << @enumToInt(sm)); + const mask: u4 = (@as(u4, 1) << @intFromEnum(sm)); const regs = self.get_regs(); regs.CTRL.modify(.{ .SM_RESTART = mask, @@ -428,7 +428,7 @@ pub const Pio = enum(u1) { } pub fn sm_clkdiv_restart(self: Pio, sm: StateMachine) void { - const mask: u4 = (@as(u4, 1) << @enumToInt(sm)); + const mask: u4 = (@as(u4, 1) << @intFromEnum(sm)); const regs = self.get_regs(); regs.CTRL.modify(.{ .CLKDIV_RESTART = mask, diff --git a/src/hal/pio/assembler/encoder.zig b/src/hal/pio/assembler/encoder.zig index e0bc74c..502b374 100644 --- a/src/hal/pio/assembler/encoder.zig +++ b/src/hal/pio/assembler/encoder.zig @@ -340,14 +340,14 @@ pub fn Encoder(comptime options: Options) type { }, .push => |push| .{ .push = .{ - .if_full = @boolToInt(push.iffull), - .block = @boolToInt(push.block), + .if_full = @intFromBool(push.iffull), + .block = @intFromBool(push.block), }, }, .pull => |pull| .{ .pull = .{ - .if_empty = @boolToInt(pull.ifempty), - .block = @boolToInt(pull.block), + .if_empty = @intFromBool(pull.ifempty), + .block = @intFromBool(pull.block), }, }, .mov => |mov| .{ @@ -361,8 +361,8 @@ pub fn Encoder(comptime options: Options) type { const irq_num = try self.evaluate(u5, program.*, irq.num, token_index, diags); break :blk .{ .irq = .{ - .clear = @boolToInt(irq.clear), - .wait = @boolToInt(irq.wait), + .clear = @intFromBool(irq.clear), + .wait = @intFromBool(irq.wait), .index = if (irq.rel) @as(u5, 0x10) | irq_num else diff --git a/src/hal/pwm.zig b/src/hal/pwm.zig index 7277b11..6e5fe1d 100644 --- a/src/hal/pwm.zig +++ b/src/hal/pwm.zig @@ -10,7 +10,7 @@ fn get_regs(comptime slice: u32) *volatile Regs { @import("std").debug.assert(slice < 8); const PwmType = microzig.chip.types.peripherals.PWM; const reg_diff = comptime @offsetOf(PwmType, "CH1_CSR") - @offsetOf(PwmType, "CH0_CSR"); - return @intToPtr(*volatile Regs, @ptrToInt(PWM) + reg_diff * slice); + return @ptrFromInt(*volatile Regs, @intFromPtr(PWM) + reg_diff * slice); } pub fn Pwm(comptime slice_num: u32, comptime chan: Channel) type { @@ -74,7 +74,7 @@ const Regs = extern struct { pub inline fn set_slice_phase_correct(comptime slice: u32, phase_correct: bool) void { log.debug("PWM{} set phase correct: {}", .{ slice, phase_correct }); get_regs(slice).csr.modify(.{ - .PH_CORRECT = @boolToInt(phase_correct), + .PH_CORRECT = @intFromBool(phase_correct), }); } @@ -89,7 +89,7 @@ pub inline fn set_slice_clk_div(comptime slice: u32, integer: u8, fraction: u4) pub inline fn set_slice_clk_div_mode(comptime slice: u32, mode: ClkDivMode) void { log.debug("PWM{} set clk div mode: {}", .{ slice, mode }); get_regs(slice).csr.modify(.{ - .DIVMODE = @enumToInt(mode), + .DIVMODE = @intFromEnum(mode), }); } @@ -100,10 +100,10 @@ pub inline fn set_channel_inversion( ) void { switch (channel) { .a => get_regs(slice).csr.modify(.{ - .A_INV = @boolToInt(invert), + .A_INV = @intFromBool(invert), }), .b => get_regs(slice).csr.modifi(.{ - .B_INV = @boolToInt(invert), + .B_INV = @intFromBool(invert), }), } } diff --git a/src/hal/rom.zig b/src/hal/rom.zig index b76eb80..7b25387 100644 --- a/src/hal/rom.zig +++ b/src/hal/rom.zig @@ -100,8 +100,8 @@ pub fn rom_table_code(c1: u8, c2: u8) u32 { /// /// The converted pointer pub inline fn rom_hword_as_ptr(rom_addr: u32) *anyopaque { - const ptr_to_ptr = @intToPtr(*u16, rom_addr); - return @intToPtr(*anyopaque, @intCast(usize, ptr_to_ptr.*)); + const ptr_to_ptr = @ptrFromInt(*u16, rom_addr); + return @ptrFromInt(*anyopaque, @intCast(usize, ptr_to_ptr.*)); } /// Lookup a bootrom function by code (inline) @@ -115,7 +115,7 @@ pub inline fn rom_hword_as_ptr(rom_addr: u32) *anyopaque { pub inline fn _rom_func_lookup(code: Code) *anyopaque { const rom_table_lookup = @ptrCast(*signatures.rom_table_lookup, rom_hword_as_ptr(0x18)); const func_table = @ptrCast(*u16, @alignCast(2, rom_hword_as_ptr(0x14))); - return rom_table_lookup(func_table, @enumToInt(code)); + return rom_table_lookup(func_table, @intFromEnum(code)); } /// Lookup a bootrom function by code diff --git a/src/hal/spi.zig b/src/hal/spi.zig index ee02131..251b61b 100644 --- a/src/hal/spi.zig +++ b/src/hal/spi.zig @@ -22,14 +22,14 @@ pub const Config = struct { }; pub fn num(n: u1) SPI { - return @intToEnum(SPI, n); + return @enumFromInt(SPI, n); } pub const SPI = enum(u1) { _, fn get_regs(spi: SPI) *volatile SpiRegs { - return switch (@enumToInt(spi)) { + return switch (@intFromEnum(spi)) { 0 => SPI0, 1 => SPI1, }; diff --git a/src/hal/time.zig b/src/hal/time.zig index e6cace5..95691cc 100644 --- a/src/hal/time.zig +++ b/src/hal/time.zig @@ -7,11 +7,11 @@ pub const Absolute = enum(u64) { _, pub fn from_us(us: u64) Absolute { - return @intToEnum(Absolute, us); + return @enumFromInt(Absolute, us); } pub fn to_us(time: Absolute) u64 { - return @enumToInt(time); + return @intFromEnum(time); } pub fn is_reached_by(deadline: Absolute, point: Absolute) bool { @@ -36,7 +36,7 @@ pub const Duration = enum(u64) { _, pub fn from_us(us: u64) Duration { - return @intToEnum(Duration, us); + return @enumFromInt(Duration, us); } pub fn from_ms(ms: u64) Duration { @@ -44,7 +44,7 @@ pub const Duration = enum(u64) { } pub fn to_us(duration: Duration) u64 { - return @enumToInt(duration); + return @intFromEnum(duration); } pub fn less_than(self: Duration, other: Duration) bool { @@ -67,14 +67,14 @@ pub fn get_time_since_boot() Absolute { var low_word = TIMER.TIMERAWL; const next_high_word = TIMER.TIMERAWH; if (next_high_word == high_word) - break @intToEnum(Absolute, @intCast(u64, high_word) << 32 | low_word); + break @enumFromInt(Absolute, @intCast(u64, high_word) << 32 | low_word); high_word = next_high_word; } else unreachable; } pub fn make_timeout_us(timeout_us: u64) Absolute { - return @intToEnum(Absolute, get_time_since_boot().to_us() + timeout_us); + return @enumFromInt(Absolute, get_time_since_boot().to_us() + timeout_us); } pub fn sleep_ms(time_ms: u32) void { diff --git a/src/hal/uart.zig b/src/hal/uart.zig index b7a9b11..678d979 100644 --- a/src/hal/uart.zig +++ b/src/hal/uart.zig @@ -43,7 +43,7 @@ pub const Config = struct { }; pub fn num(n: u1) UART { - return @intToEnum(UART, n); + return @enumFromInt(UART, n); } pub const UART = enum(u1) { @@ -63,7 +63,7 @@ pub const UART = enum(u1) { } fn get_regs(uart: UART) *volatile UartRegs { - return switch (@enumToInt(uart)) { + return switch (@intFromEnum(uart)) { 0 => UART0, 1 => UART1, }; @@ -122,7 +122,7 @@ pub const UART = enum(u1) { } pub fn dreq_tx(uart: UART) dma.Dreq { - return switch (@enumToInt(uart)) { + return switch (@intFromEnum(uart)) { 0 => .uart0_tx, 1 => .uart1_tx, }; diff --git a/src/hal/usb.zig b/src/hal/usb.zig index e2147f5..60a9f69 100644 --- a/src/hal/usb.zig +++ b/src/hal/usb.zig @@ -45,7 +45,7 @@ pub var EP0_OUT_CFG: usb.EndpointConfiguration = .{ .length = @intCast(u8, @sizeOf(usb.EndpointDescriptor)), .descriptor_type = usb.DescType.Endpoint, .endpoint_address = usb.EP0_OUT_ADDR, - .attributes = @enumToInt(usb.TransferType.Control), + .attributes = @intFromEnum(usb.TransferType.Control), .max_packet_size = 64, .interval = 0, }, @@ -60,7 +60,7 @@ pub var EP0_IN_CFG: usb.EndpointConfiguration = .{ .length = @intCast(u8, @sizeOf(usb.EndpointDescriptor)), .descriptor_type = usb.DescType.Endpoint, .endpoint_address = usb.EP0_IN_ADDR, - .attributes = @enumToInt(usb.TransferType.Control), + .attributes = @intFromEnum(usb.TransferType.Control), .max_packet_size = 64, .interval = 0, }, @@ -89,26 +89,26 @@ pub const buffers = struct { /// Mapping to the different data buffers in DPSRAM pub var B: usb.Buffers = .{ - .ep0_buffer0 = @intToPtr([*]u8, USB_EP0_BUFFER0), - .ep0_buffer1 = @intToPtr([*]u8, USB_EP0_BUFFER1), + .ep0_buffer0 = @ptrFromInt([*]u8, USB_EP0_BUFFER0), + .ep0_buffer1 = @ptrFromInt([*]u8, USB_EP0_BUFFER1), // We will initialize this comptime in a loop .rest = .{ - @intToPtr([*]u8, USB_BUFFERS + (0 * BUFFER_SIZE)), - @intToPtr([*]u8, USB_BUFFERS + (1 * BUFFER_SIZE)), - @intToPtr([*]u8, USB_BUFFERS + (2 * BUFFER_SIZE)), - @intToPtr([*]u8, USB_BUFFERS + (3 * BUFFER_SIZE)), - @intToPtr([*]u8, USB_BUFFERS + (4 * BUFFER_SIZE)), - @intToPtr([*]u8, USB_BUFFERS + (5 * BUFFER_SIZE)), - @intToPtr([*]u8, USB_BUFFERS + (6 * BUFFER_SIZE)), - @intToPtr([*]u8, USB_BUFFERS + (7 * BUFFER_SIZE)), - @intToPtr([*]u8, USB_BUFFERS + (8 * BUFFER_SIZE)), - @intToPtr([*]u8, USB_BUFFERS + (9 * BUFFER_SIZE)), - @intToPtr([*]u8, USB_BUFFERS + (10 * BUFFER_SIZE)), - @intToPtr([*]u8, USB_BUFFERS + (11 * BUFFER_SIZE)), - @intToPtr([*]u8, USB_BUFFERS + (12 * BUFFER_SIZE)), - @intToPtr([*]u8, USB_BUFFERS + (13 * BUFFER_SIZE)), - @intToPtr([*]u8, USB_BUFFERS + (14 * BUFFER_SIZE)), - @intToPtr([*]u8, USB_BUFFERS + (15 * BUFFER_SIZE)), + @ptrFromInt([*]u8, USB_BUFFERS + (0 * BUFFER_SIZE)), + @ptrFromInt([*]u8, USB_BUFFERS + (1 * BUFFER_SIZE)), + @ptrFromInt([*]u8, USB_BUFFERS + (2 * BUFFER_SIZE)), + @ptrFromInt([*]u8, USB_BUFFERS + (3 * BUFFER_SIZE)), + @ptrFromInt([*]u8, USB_BUFFERS + (4 * BUFFER_SIZE)), + @ptrFromInt([*]u8, USB_BUFFERS + (5 * BUFFER_SIZE)), + @ptrFromInt([*]u8, USB_BUFFERS + (6 * BUFFER_SIZE)), + @ptrFromInt([*]u8, USB_BUFFERS + (7 * BUFFER_SIZE)), + @ptrFromInt([*]u8, USB_BUFFERS + (8 * BUFFER_SIZE)), + @ptrFromInt([*]u8, USB_BUFFERS + (9 * BUFFER_SIZE)), + @ptrFromInt([*]u8, USB_BUFFERS + (10 * BUFFER_SIZE)), + @ptrFromInt([*]u8, USB_BUFFERS + (11 * BUFFER_SIZE)), + @ptrFromInt([*]u8, USB_BUFFERS + (12 * BUFFER_SIZE)), + @ptrFromInt([*]u8, USB_BUFFERS + (13 * BUFFER_SIZE)), + @ptrFromInt([*]u8, USB_BUFFERS + (14 * BUFFER_SIZE)), + @ptrFromInt([*]u8, USB_BUFFERS + (15 * BUFFER_SIZE)), }, }; }; @@ -273,8 +273,8 @@ pub const F = struct { if (ep.endpoint_control_index) |epci| { // We need to compute the offset from the base of USB SRAM to the // buffer we're choosing, because that's how the peripheral do. - const buf_base = @ptrToInt(buffers.B.get(ep.data_buffer_index)); - const dpram_base = @ptrToInt(peripherals.USBCTRL_DPRAM); + const buf_base = @intFromPtr(buffers.B.get(ep.data_buffer_index)); + const dpram_base = @intFromPtr(peripherals.USBCTRL_DPRAM); // The offset _should_ fit in a u16, but if we've gotten something // wrong in the past few lines, a common symptom will be integer // overflow producing a Very Large Number, From c197a153127442e0e9af1456bc33faa45c2768dd Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Tue, 27 Jun 2023 20:32:24 -0700 Subject: [PATCH 64/74] update microzig (#67) Co-authored-by: mattnite --- deps/microzig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/microzig b/deps/microzig index a49fad9..9392fe0 160000 --- a/deps/microzig +++ b/deps/microzig @@ -1 +1 @@ -Subproject commit a49fad973077dffd5fa0b392720295ad033f076e +Subproject commit 9392fe0f7bddde26155c181ab80b70097b49c791 From 2b5c6096b03017748b0b5762657e5f3b2aa66533 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Tue, 27 Jun 2023 21:10:35 -0700 Subject: [PATCH 65/74] builtin type inference fix (#68) --- examples/flash_program.zig | 2 +- examples/random.zig | 4 +- examples/squarewave.zig | 29 +++++----- examples/usb_device.zig | 12 ++--- examples/usb_hid.zig | 12 ++--- examples/ws2812.zig | 2 +- src/chips/RP2040.zig | 80 ++++++++++++++-------------- src/hal/adc.zig | 14 ++--- src/hal/clocks.zig | 4 +- src/hal/dma.zig | 4 +- src/hal/flash.zig | 2 +- src/hal/gpio.zig | 12 ++--- src/hal/hw.zig | 12 ++--- src/hal/i2c.zig | 14 ++--- src/hal/multicore.zig | 2 +- src/hal/pins.zig | 6 +-- src/hal/pio.zig | 26 ++++----- src/hal/pio/assembler.zig | 2 +- src/hal/pio/assembler/Expression.zig | 14 ++--- src/hal/pio/assembler/encoder.zig | 16 +++--- src/hal/pio/assembler/tokenizer.zig | 10 ++-- src/hal/pwm.zig | 2 +- src/hal/random.zig | 4 +- src/hal/resets.zig | 10 ++-- src/hal/rom.zig | 46 ++++++++-------- src/hal/spi.zig | 6 +-- src/hal/time.zig | 8 +-- src/hal/uart.zig | 8 +-- src/hal/usb.zig | 54 +++++++++---------- 29 files changed, 210 insertions(+), 207 deletions(-) diff --git a/examples/flash_program.zig b/examples/flash_program.zig index d38d0ae..48754e1 100644 --- a/examples/flash_program.zig +++ b/examples/flash_program.zig @@ -14,7 +14,7 @@ const uart_tx_pin = gpio.num(0); const uart_rx_pin = gpio.num(1); const flash_target_offset: u32 = 256 * 1024; -const flash_target_contents = @ptrFromInt([*]const u8, rp2040.flash.XIP_BASE + flash_target_offset); +const flash_target_contents = @as([*]const u8, @ptrFromInt(rp2040.flash.XIP_BASE + flash_target_offset)); pub fn panic(message: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { std.log.err("panic: {s}", .{message}); diff --git a/examples/random.zig b/examples/random.zig index 40d2f68..34d03d1 100644 --- a/examples/random.zig +++ b/examples/random.zig @@ -52,7 +52,7 @@ pub fn main() !void { rng.bytes(buffer[0..]); counter += 8; for (buffer) |byte| { - dist[@intCast(usize, byte)] += 1; + dist[@as(usize, @intCast(byte))] += 1; } std.log.info("Generate random number: {any}", .{buffer}); @@ -60,7 +60,7 @@ pub fn main() !void { var i: usize = 0; std.log.info("Distribution:", .{}); while (i < 256) : (i += 1) { - std.log.info("{} -> {}, {d:2}%", .{ i, dist[i], @floatFromInt(f32, dist[i]) / @floatFromInt(f32, counter) }); + std.log.info("{} -> {}, {d:2}%", .{ i, dist[i], @as(f32, @floatFromInt(dist[i])) / @as(f32, @floatFromInt(counter)) }); } } time.sleep_ms(1000); diff --git a/examples/squarewave.zig b/examples/squarewave.zig index 0564b62..0894d9a 100644 --- a/examples/squarewave.zig +++ b/examples/squarewave.zig @@ -6,19 +6,22 @@ const gpio = rp2040.gpio; const Pio = rp2040.pio.Pio; const StateMachine = rp2040.pio.StateMachine; -const squarewave_program = rp2040.pio.assemble( - \\; - \\; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. - \\; - \\; SPDX-License-Identifier: BSD-3-Clause - \\; - \\.program squarewave - \\ set pindirs, 1 ; Set pin to output - \\again: - \\ set pins, 1 [1] ; Drive pin high and then delay for one cycle - \\ set pins, 0 ; Drive pin low - \\ jmp again ; Set PC to label `again` -, .{}).get_program_by_name("squarewave"); +const squarewave_program = blk: { + @setEvalBranchQuota(2000); + break :blk rp2040.pio.assemble( + \\; + \\; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + \\; + \\; SPDX-License-Identifier: BSD-3-Clause + \\; + \\.program squarewave + \\ set pindirs, 1 ; Set pin to output + \\again: + \\ set pins, 1 [1] ; Drive pin high and then delay for one cycle + \\ set pins, 0 ; Drive pin low + \\ jmp again ; Set PC to label `again` + , .{}).get_program_by_name("squarewave"); +}; // Pick one PIO instance arbitrarily. We're also arbitrarily picking state // machine 0 on this PIO instance (the state machines are numbered 0 to 3 diff --git a/examples/usb_device.zig b/examples/usb_device.zig index d2b243d..8f2d74e 100644 --- a/examples/usb_device.zig +++ b/examples/usb_device.zig @@ -38,7 +38,7 @@ fn ep1_out_callback(dc: *usb.DeviceConfiguration, data: []const u8) void { // add your own endpoints to... pub var EP1_OUT_CFG: usb.EndpointConfiguration = .{ .descriptor = &usb.EndpointDescriptor{ - .length = @intCast(u8, @sizeOf(usb.EndpointDescriptor)), + .length = @as(u8, @intCast(@sizeOf(usb.EndpointDescriptor))), .descriptor_type = usb.DescType.Endpoint, .endpoint_address = usb.Dir.Out.endpoint(1), .attributes = @intFromEnum(usb.TransferType.Bulk), @@ -55,7 +55,7 @@ pub var EP1_OUT_CFG: usb.EndpointConfiguration = .{ pub var EP1_IN_CFG: usb.EndpointConfiguration = .{ .descriptor = &usb.EndpointDescriptor{ - .length = @intCast(u8, @sizeOf(usb.EndpointDescriptor)), + .length = @as(u8, @intCast(@sizeOf(usb.EndpointDescriptor))), .descriptor_type = usb.DescType.Endpoint, .endpoint_address = usb.Dir.In.endpoint(1), .attributes = @intFromEnum(usb.TransferType.Bulk), @@ -73,7 +73,7 @@ pub var EP1_IN_CFG: usb.EndpointConfiguration = .{ // This is our device configuration pub var DEVICE_CONFIGURATION: usb.DeviceConfiguration = .{ .device_descriptor = &.{ - .length = @intCast(u8, @sizeOf(usb.DeviceDescriptor)), + .length = @as(u8, @intCast(@sizeOf(usb.DeviceDescriptor))), .descriptor_type = usb.DescType.Device, .bcd_usb = 0x0110, .device_class = 0, @@ -89,7 +89,7 @@ pub var DEVICE_CONFIGURATION: usb.DeviceConfiguration = .{ .num_configurations = 1, }, .interface_descriptor = &.{ - .length = @intCast(u8, @sizeOf(usb.InterfaceDescriptor)), + .length = @as(u8, @intCast(@sizeOf(usb.InterfaceDescriptor))), .descriptor_type = usb.DescType.Interface, .interface_number = 0, .alternate_setting = 0, @@ -101,9 +101,9 @@ pub var DEVICE_CONFIGURATION: usb.DeviceConfiguration = .{ .interface_s = 0, }, .config_descriptor = &.{ - .length = @intCast(u8, @sizeOf(usb.ConfigurationDescriptor)), + .length = @as(u8, @intCast(@sizeOf(usb.ConfigurationDescriptor))), .descriptor_type = usb.DescType.Config, - .total_length = @intCast(u8, @sizeOf(usb.ConfigurationDescriptor) + @sizeOf(usb.InterfaceDescriptor) + @sizeOf(usb.EndpointDescriptor) + @sizeOf(usb.EndpointDescriptor)), + .total_length = @as(u8, @intCast(@sizeOf(usb.ConfigurationDescriptor) + @sizeOf(usb.InterfaceDescriptor) + @sizeOf(usb.EndpointDescriptor) + @sizeOf(usb.EndpointDescriptor))), .num_interfaces = 1, .configuration_value = 1, .configuration_s = 0, diff --git a/examples/usb_hid.zig b/examples/usb_hid.zig index 2eced2b..752111a 100644 --- a/examples/usb_hid.zig +++ b/examples/usb_hid.zig @@ -38,7 +38,7 @@ fn ep1_out_callback(dc: *usb.DeviceConfiguration, data: []const u8) void { // add your own endpoints to... pub var EP1_OUT_CFG: usb.EndpointConfiguration = .{ .descriptor = &usb.EndpointDescriptor{ - .length = @intCast(u8, @sizeOf(usb.EndpointDescriptor)), + .length = @as(u8, @intCast(@sizeOf(usb.EndpointDescriptor))), .descriptor_type = usb.DescType.Endpoint, .endpoint_address = usb.Dir.Out.endpoint(1), .attributes = @intFromEnum(usb.TransferType.Interrupt), @@ -55,7 +55,7 @@ pub var EP1_OUT_CFG: usb.EndpointConfiguration = .{ pub var EP1_IN_CFG: usb.EndpointConfiguration = .{ .descriptor = &usb.EndpointDescriptor{ - .length = @intCast(u8, @sizeOf(usb.EndpointDescriptor)), + .length = @as(u8, @intCast(@sizeOf(usb.EndpointDescriptor))), .descriptor_type = usb.DescType.Endpoint, .endpoint_address = usb.Dir.In.endpoint(1), .attributes = @intFromEnum(usb.TransferType.Interrupt), @@ -73,7 +73,7 @@ pub var EP1_IN_CFG: usb.EndpointConfiguration = .{ // This is our device configuration pub var DEVICE_CONFIGURATION: usb.DeviceConfiguration = .{ .device_descriptor = &.{ - .length = @intCast(u8, @sizeOf(usb.DeviceDescriptor)), + .length = @as(u8, @intCast(@sizeOf(usb.DeviceDescriptor))), .descriptor_type = usb.DescType.Device, .bcd_usb = 0x0200, .device_class = 0, @@ -91,7 +91,7 @@ pub var DEVICE_CONFIGURATION: usb.DeviceConfiguration = .{ .num_configurations = 1, }, .interface_descriptor = &.{ - .length = @intCast(u8, @sizeOf(usb.InterfaceDescriptor)), + .length = @as(u8, @intCast(@sizeOf(usb.InterfaceDescriptor))), .descriptor_type = usb.DescType.Interface, .interface_number = 0, .alternate_setting = 0, @@ -103,9 +103,9 @@ pub var DEVICE_CONFIGURATION: usb.DeviceConfiguration = .{ .interface_s = 0, }, .config_descriptor = &.{ - .length = @intCast(u8, @sizeOf(usb.ConfigurationDescriptor)), + .length = @as(u8, @intCast(@sizeOf(usb.ConfigurationDescriptor))), .descriptor_type = usb.DescType.Config, - .total_length = @intCast(u8, @sizeOf(usb.ConfigurationDescriptor) + @sizeOf(usb.InterfaceDescriptor) + @sizeOf(usb.EndpointDescriptor) + @sizeOf(usb.EndpointDescriptor)), + .total_length = @as(u8, @intCast(@sizeOf(usb.ConfigurationDescriptor) + @sizeOf(usb.InterfaceDescriptor) + @sizeOf(usb.EndpointDescriptor) + @sizeOf(usb.EndpointDescriptor))), .num_interfaces = 1, .configuration_value = 1, .configuration_s = 0, diff --git a/examples/ws2812.zig b/examples/ws2812.zig index f61204b..64fbac2 100644 --- a/examples/ws2812.zig +++ b/examples/ws2812.zig @@ -43,7 +43,7 @@ pub fn main() void { const cycles_per_bit: comptime_int = ws2812_program.defines[0].value + //T1 ws2812_program.defines[1].value + //T2 ws2812_program.defines[2].value; //T3 - const div = @floatFromInt(f32, rp2040.clock_config.sys.?.output_freq) / + const div = @as(f32, @floatFromInt(rp2040.clock_config.sys.?.output_freq)) / (800_000 * cycles_per_bit); pio.sm_load_and_start_program(sm, ws2812_program, .{ diff --git a/src/chips/RP2040.zig b/src/chips/RP2040.zig index 74f6134..a11f255 100644 --- a/src/chips/RP2040.zig +++ b/src/chips/RP2040.zig @@ -65,9 +65,9 @@ pub const devices = struct { pub const peripherals = struct { /// System Control Space - pub const MPU = @ptrFromInt(*volatile types.peripherals.SCS, 0xd90); + pub const MPU = @as(*volatile types.peripherals.SCS, @ptrFromInt(0xd90)); /// QSPI flash execute-in-place block - pub const XIP_CTRL = @ptrFromInt(*volatile types.peripherals.XIP_CTRL, 0x14000000); + pub const XIP_CTRL = @as(*volatile types.peripherals.XIP_CTRL, @ptrFromInt(0x14000000)); /// DW_apb_ssi has the following features: /// * APB interface – Allows for easy integration into a DesignWare Synthesizable Components for AMBA 2 implementation. /// * APB3 and APB4 protocol support. @@ -94,27 +94,27 @@ pub const devices = struct { /// - Interrupt polarity – active high interrupt lines. /// - Serial clock polarity – low serial-clock polarity directly after reset. /// - Serial clock phase – capture on first edge of serial-clock directly after reset. - pub const XIP_SSI = @ptrFromInt(*volatile types.peripherals.XIP_SSI, 0x18000000); - pub const SYSINFO = @ptrFromInt(*volatile types.peripherals.SYSINFO, 0x40000000); + pub const XIP_SSI = @as(*volatile types.peripherals.XIP_SSI, @ptrFromInt(0x18000000)); + pub const SYSINFO = @as(*volatile types.peripherals.SYSINFO, @ptrFromInt(0x40000000)); /// Register block for various chip control signals - pub const SYSCFG = @ptrFromInt(*volatile types.peripherals.SYSCFG, 0x40004000); - pub const CLOCKS = @ptrFromInt(*volatile types.peripherals.CLOCKS, 0x40008000); - pub const RESETS = @ptrFromInt(*volatile types.peripherals.RESETS, 0x4000c000); - pub const PSM = @ptrFromInt(*volatile types.peripherals.PSM, 0x40010000); - pub const IO_BANK0 = @ptrFromInt(*volatile types.peripherals.IO_BANK0, 0x40014000); - pub const IO_QSPI = @ptrFromInt(*volatile types.peripherals.IO_QSPI, 0x40018000); - pub const PADS_BANK0 = @ptrFromInt(*volatile types.peripherals.PADS_BANK0, 0x4001c000); - pub const PADS_QSPI = @ptrFromInt(*volatile types.peripherals.PADS_QSPI, 0x40020000); + pub const SYSCFG = @as(*volatile types.peripherals.SYSCFG, @ptrFromInt(0x40004000)); + pub const CLOCKS = @as(*volatile types.peripherals.CLOCKS, @ptrFromInt(0x40008000)); + pub const RESETS = @as(*volatile types.peripherals.RESETS, @ptrFromInt(0x4000c000)); + pub const PSM = @as(*volatile types.peripherals.PSM, @ptrFromInt(0x40010000)); + pub const IO_BANK0 = @as(*volatile types.peripherals.IO_BANK0, @ptrFromInt(0x40014000)); + pub const IO_QSPI = @as(*volatile types.peripherals.IO_QSPI, @ptrFromInt(0x40018000)); + pub const PADS_BANK0 = @as(*volatile types.peripherals.PADS_BANK0, @ptrFromInt(0x4001c000)); + pub const PADS_QSPI = @as(*volatile types.peripherals.PADS_QSPI, @ptrFromInt(0x40020000)); /// Controls the crystal oscillator - pub const XOSC = @ptrFromInt(*volatile types.peripherals.XOSC, 0x40024000); - pub const PLL_SYS = @ptrFromInt(*volatile types.peripherals.PLL_SYS, 0x40028000); - pub const PLL_USB = @ptrFromInt(*volatile types.peripherals.PLL_SYS, 0x4002c000); + pub const XOSC = @as(*volatile types.peripherals.XOSC, @ptrFromInt(0x40024000)); + pub const PLL_SYS = @as(*volatile types.peripherals.PLL_SYS, @ptrFromInt(0x40028000)); + pub const PLL_USB = @as(*volatile types.peripherals.PLL_SYS, @ptrFromInt(0x4002c000)); /// Register block for busfabric control signals and performance counters - pub const BUSCTRL = @ptrFromInt(*volatile types.peripherals.BUSCTRL, 0x40030000); - pub const UART0 = @ptrFromInt(*volatile types.peripherals.UART0, 0x40034000); - pub const UART1 = @ptrFromInt(*volatile types.peripherals.UART0, 0x40038000); - pub const SPI0 = @ptrFromInt(*volatile types.peripherals.SPI0, 0x4003c000); - pub const SPI1 = @ptrFromInt(*volatile types.peripherals.SPI0, 0x40040000); + pub const BUSCTRL = @as(*volatile types.peripherals.BUSCTRL, @ptrFromInt(0x40030000)); + pub const UART0 = @as(*volatile types.peripherals.UART0, @ptrFromInt(0x40034000)); + pub const UART1 = @as(*volatile types.peripherals.UART0, @ptrFromInt(0x40038000)); + pub const SPI0 = @as(*volatile types.peripherals.SPI0, @ptrFromInt(0x4003c000)); + pub const SPI1 = @as(*volatile types.peripherals.SPI0, @ptrFromInt(0x40040000)); /// DW_apb_i2c address block /// List of configuration constants for the Synopsys I2C hardware (you may see references to these in I2C register header; these are *fixed* values, set at hardware design time): /// IC_ULTRA_FAST_MODE ................ 0x0 @@ -185,7 +185,7 @@ pub const devices = struct { /// IC_STOP_DET_IF_MASTER_ACTIVE ...... 0x0 /// IC_DEFAULT_UFM_SPKLEN ............. 0x1 /// IC_TX_BUFFER_DEPTH ................ 16 - pub const I2C0 = @ptrFromInt(*volatile types.peripherals.I2C0, 0x40044000); + pub const I2C0 = @as(*volatile types.peripherals.I2C0, @ptrFromInt(0x40044000)); /// DW_apb_i2c address block /// List of configuration constants for the Synopsys I2C hardware (you may see references to these in I2C register header; these are *fixed* values, set at hardware design time): /// IC_ULTRA_FAST_MODE ................ 0x0 @@ -256,11 +256,11 @@ pub const devices = struct { /// IC_STOP_DET_IF_MASTER_ACTIVE ...... 0x0 /// IC_DEFAULT_UFM_SPKLEN ............. 0x1 /// IC_TX_BUFFER_DEPTH ................ 16 - pub const I2C1 = @ptrFromInt(*volatile types.peripherals.I2C0, 0x40048000); + pub const I2C1 = @as(*volatile types.peripherals.I2C0, @ptrFromInt(0x40048000)); /// Control and data interface to SAR ADC - pub const ADC = @ptrFromInt(*volatile types.peripherals.ADC, 0x4004c000); + pub const ADC = @as(*volatile types.peripherals.ADC, @ptrFromInt(0x4004c000)); /// Simple PWM - pub const PWM = @ptrFromInt(*volatile types.peripherals.PWM, 0x40050000); + pub const PWM = @as(*volatile types.peripherals.PWM, @ptrFromInt(0x40050000)); /// Controls time and alarms /// time is a 64 bit value indicating the time in usec since power-on /// timeh is the top 32 bits of time & timel is the bottom 32 bits @@ -271,35 +271,35 @@ pub const devices = struct { /// An alarm can be cancelled before it has finished by clearing the alarm_enable /// When an alarm fires, the corresponding alarm_irq is set and alarm_running is cleared /// To clear the interrupt write a 1 to the corresponding alarm_irq - pub const TIMER = @ptrFromInt(*volatile types.peripherals.TIMER, 0x40054000); - pub const WATCHDOG = @ptrFromInt(*volatile types.peripherals.WATCHDOG, 0x40058000); + pub const TIMER = @as(*volatile types.peripherals.TIMER, @ptrFromInt(0x40054000)); + pub const WATCHDOG = @as(*volatile types.peripherals.WATCHDOG, @ptrFromInt(0x40058000)); /// Register block to control RTC - pub const RTC = @ptrFromInt(*volatile types.peripherals.RTC, 0x4005c000); - pub const ROSC = @ptrFromInt(*volatile types.peripherals.ROSC, 0x40060000); + pub const RTC = @as(*volatile types.peripherals.RTC, @ptrFromInt(0x4005c000)); + pub const ROSC = @as(*volatile types.peripherals.ROSC, @ptrFromInt(0x40060000)); /// control and status for on-chip voltage regulator and chip level reset subsystem - pub const VREG_AND_CHIP_RESET = @ptrFromInt(*volatile types.peripherals.VREG_AND_CHIP_RESET, 0x40064000); + pub const VREG_AND_CHIP_RESET = @as(*volatile types.peripherals.VREG_AND_CHIP_RESET, @ptrFromInt(0x40064000)); /// Testbench manager. Allows the programmer to know what platform their software is running on. - pub const TBMAN = @ptrFromInt(*volatile types.peripherals.TBMAN, 0x4006c000); + pub const TBMAN = @as(*volatile types.peripherals.TBMAN, @ptrFromInt(0x4006c000)); /// DMA with separate read and write masters - pub const DMA = @ptrFromInt(*volatile types.peripherals.DMA, 0x50000000); + pub const DMA = @as(*volatile types.peripherals.DMA, @ptrFromInt(0x50000000)); /// DPRAM layout for USB device. - pub const USBCTRL_DPRAM = @ptrFromInt(*volatile types.peripherals.USBCTRL_DPRAM, 0x50100000); + pub const USBCTRL_DPRAM = @as(*volatile types.peripherals.USBCTRL_DPRAM, @ptrFromInt(0x50100000)); /// USB FS/LS controller device registers - pub const USBCTRL_REGS = @ptrFromInt(*volatile types.peripherals.USBCTRL_REGS, 0x50110000); + pub const USBCTRL_REGS = @as(*volatile types.peripherals.USBCTRL_REGS, @ptrFromInt(0x50110000)); /// Programmable IO block - pub const PIO0 = @ptrFromInt(*volatile types.peripherals.PIO0, 0x50200000); + pub const PIO0 = @as(*volatile types.peripherals.PIO0, @ptrFromInt(0x50200000)); /// Programmable IO block - pub const PIO1 = @ptrFromInt(*volatile types.peripherals.PIO0, 0x50300000); + pub const PIO1 = @as(*volatile types.peripherals.PIO0, @ptrFromInt(0x50300000)); /// Single-cycle IO block /// Provides core-local and inter-core hardware for the two processors, with single-cycle access. - pub const SIO = @ptrFromInt(*volatile types.peripherals.SIO, 0xd0000000); - pub const PPB = @ptrFromInt(*volatile types.peripherals.PPB, 0xe0000000); + pub const SIO = @as(*volatile types.peripherals.SIO, @ptrFromInt(0xd0000000)); + pub const PPB = @as(*volatile types.peripherals.PPB, @ptrFromInt(0xe0000000)); /// System Tick Timer - pub const SysTick = @ptrFromInt(*volatile types.peripherals.SysTick, 0xe000e010); + pub const SysTick = @as(*volatile types.peripherals.SysTick, @ptrFromInt(0xe000e010)); /// System Control Space - pub const NVIC = @ptrFromInt(*volatile types.peripherals.NVIC, 0xe000e100); + pub const NVIC = @as(*volatile types.peripherals.NVIC, @ptrFromInt(0xe000e100)); /// System Control Space - pub const SCB = @ptrFromInt(*volatile types.peripherals.SCB, 0xe000ed00); + pub const SCB = @as(*volatile types.peripherals.SCB, @ptrFromInt(0xe000ed00)); }; }; }; diff --git a/src/hal/adc.zig b/src/hal/adc.zig index 973db63..e025a63 100644 --- a/src/hal/adc.zig +++ b/src/hal/adc.zig @@ -17,7 +17,7 @@ pub const Error = error{ /// temp_sensor is not valid because you can refer to it by name. pub fn input(n: u2) Input { - return @enumFromInt(Input, n); + return @as(Input, @enumFromInt(n)); } /// Enable the ADC controller. @@ -50,7 +50,7 @@ pub fn apply(config: Config) void { .ERR_STICKY = 0, .AINSEL = 0, .RROBIN = if (config.round_robin) |rr| - @bitCast(u5, rr) + @as(u5, @bitCast(rr)) else 0, @@ -63,8 +63,8 @@ pub fn apply(config: Config) void { if (config.sample_frequency) |sample_frequency| { const cycles = (48_000_000 * 256) / @as(u64, sample_frequency); ADC.DIV.write(.{ - .FRAC = @truncate(u8, cycles), - .INT = @intCast(u16, (cycles >> 8) - 1), + .FRAC = @as(u8, @truncate(cycles)), + .INT = @as(u16, @intCast((cycles >> 8) - 1)), .padding = 0, }); @@ -85,7 +85,7 @@ pub fn select_input(in: Input) void { /// 4 is the temperature sensor. pub fn get_selected_input() Input { const cs = ADC.SC.read(); - return @enumFromInt(Input, cs.AINSEL); + return @as(Input, @enumFromInt(cs.AINSEL)); } pub const Input = enum(u3) { @@ -126,7 +126,7 @@ pub fn set_temp_sensor_enabled(enable: bool) void { /// T must be floating point. pub fn temp_sensor_result_to_celcius(comptime T: type, comptime vref: T, result: u12) T { // TODO: consider fixed-point - const raw = @floatFromInt(T, result); + const raw = @as(T, @floatFromInt(result)); const voltage: T = vref * raw / 0x0fff; return (27.0 - ((voltage - 0.706) / 0.001721)); } @@ -144,7 +144,7 @@ pub const InputMask = packed struct(u5) { /// 0 will disable round-robin mode but `disableRoundRobin()` is provided so /// the user may be explicit. pub fn round_robin_set(enabled_inputs: InputMask) void { - ADC.CS.modify(.{ .RROBIN = @bitCast(u5, enabled_inputs) }); + ADC.CS.modify(.{ .RROBIN = @as(u5, @bitCast(enabled_inputs)) }); } /// Disable round-robin sample mode. diff --git a/src/hal/clocks.zig b/src/hal/clocks.zig index cb5350f..9a027aa 100644 --- a/src/hal/clocks.zig +++ b/src/hal/clocks.zig @@ -83,7 +83,7 @@ pub const Generator = enum(u32) { assert(24 == @sizeOf([2]GeneratorRegs)); } - const generators = @ptrCast(*volatile [@typeInfo(Generator).Enum.fields.len]GeneratorRegs, CLOCKS); + const generators = @as(*volatile [@typeInfo(Generator).Enum.fields.len]GeneratorRegs, @ptrCast(CLOCKS)); fn get_regs(generator: Generator) *volatile GeneratorRegs { return &generators[@intFromEnum(generator)]; @@ -617,7 +617,7 @@ pub const Configuration = struct { // source frequency has to be faster because dividing will always reduce. assert(input.freq >= output_freq); - const div = @intCast(u32, (@intCast(u64, input.freq) << 8) / output_freq); + const div = @as(u32, @intCast((@as(u64, @intCast(input.freq)) << 8) / output_freq)); // check divisor if (div > generator.get_div()) diff --git a/src/hal/dma.zig b/src/hal/dma.zig index 35b285a..469966f 100644 --- a/src/hal/dma.zig +++ b/src/hal/dma.zig @@ -19,7 +19,7 @@ pub const Dreq = enum(u6) { pub fn channel(n: u4) Channel { assert(n < num_channels); - return @enumFromInt(Channel, n); + return @as(Channel, @enumFromInt(n)); } pub fn claim_unused_channel() ?Channel { @@ -76,7 +76,7 @@ pub const Channel = enum(u4) { }; fn get_regs(chan: Channel) *volatile Regs { - const regs = @ptrCast(*volatile [12]Regs, &DMA.CH0_READ_ADDR); + const regs = @as(*volatile [12]Regs, @ptrCast(&DMA.CH0_READ_ADDR)); return ®s[@intFromEnum(chan)]; } diff --git a/src/hal/flash.zig b/src/hal/flash.zig index cb86c72..7ce3206 100644 --- a/src/hal/flash.zig +++ b/src/hal/flash.zig @@ -23,7 +23,7 @@ pub const boot2 = struct { /// Copy the 2nd stage bootloader into memory pub fn flash_init() linksection(".time_critical") void { if (copyout_valid) return; - const bootloader = @ptrFromInt([*]u32, XIP_BASE); + const bootloader = @as([*]u32, @ptrFromInt(XIP_BASE)); var i: usize = 0; while (i < BOOT2_SIZE_BYTES) : (i += 1) { copyout[i] = bootloader[i]; diff --git a/src/hal/gpio.zig b/src/hal/gpio.zig index 3b9e5ae..dffe3d1 100644 --- a/src/hal/gpio.zig +++ b/src/hal/gpio.zig @@ -72,11 +72,11 @@ pub fn num(n: u5) Pin { if (n > 29) @panic("the RP2040 only has GPIO 0-29"); - return @enumFromInt(Pin, n); + return @as(Pin, @enumFromInt(n)); } pub fn mask(m: u32) Mask { - return @enumFromInt(Mask, m); + return @as(Mask, @enumFromInt(m)); } pub const Mask = enum(u30) { @@ -85,7 +85,7 @@ pub const Mask = enum(u30) { pub fn set_function(self: Mask, function: Function) void { const raw_mask = @intFromEnum(self); for (0..@bitSizeOf(Mask)) |i| { - const bit = @intCast(u5, i); + const bit = @as(u5, @intCast(i)); if (0 != raw_mask & (@as(u32, 1) << bit)) num(bit).set_function(function); } @@ -102,7 +102,7 @@ pub const Mask = enum(u30) { pub fn set_pull(self: Mask, pull: ?Pull) void { const raw_mask = @intFromEnum(self); for (0..@bitSizeOf(Mask)) |i| { - const bit = @intCast(u5, i); + const bit = @as(u5, @intCast(i)); if (0 != raw_mask & (@as(u32, 1) << bit)) num(bit).set_pull(pull); } @@ -154,12 +154,12 @@ pub const Pin = enum(u5) { pub const PadsReg = @TypeOf(PADS_BANK0.GPIO0); fn get_regs(gpio: Pin) *volatile Regs { - const regs = @ptrCast(*volatile [30]Regs, &IO_BANK0.GPIO0_STATUS); + const regs = @as(*volatile [30]Regs, @ptrCast(&IO_BANK0.GPIO0_STATUS)); return ®s[@intFromEnum(gpio)]; } fn get_pads_reg(gpio: Pin) *volatile PadsReg { - const regs = @ptrCast(*volatile [30]PadsReg, &PADS_BANK0.GPIO0); + const regs = @as(*volatile [30]PadsReg, @ptrCast(&PADS_BANK0.GPIO0)); return ®s[@intFromEnum(gpio)]; } diff --git a/src/hal/hw.zig b/src/hal/hw.zig index 28a1981..8227027 100644 --- a/src/hal/hw.zig +++ b/src/hal/hw.zig @@ -20,27 +20,27 @@ const set_bits = @as(u32, 0x2) << 12; const clear_bits = @as(u32, 0x3) << 12; pub fn clear_alias_raw(ptr: anytype) *volatile u32 { - return @ptrFromInt(*volatile u32, @intFromPtr(ptr) | clear_bits); + return @as(*volatile u32, @ptrFromInt(@intFromPtr(ptr) | clear_bits)); } pub fn set_alias_raw(ptr: anytype) *volatile u32 { - return @ptrFromInt(*volatile u32, @intFromPtr(ptr) | set_bits); + return @as(*volatile u32, @ptrFromInt(@intFromPtr(ptr) | set_bits)); } pub fn xor_alias_raw(ptr: anytype) *volatile u32 { - return @ptrFromInt(*volatile u32, @intFromPtr(ptr) | xor_bits); + return @as(*volatile u32, @ptrFromInt(@intFromPtr(ptr) | xor_bits)); } pub fn clear_alias(ptr: anytype) @TypeOf(ptr) { - return @ptrFromInt(@TypeOf(ptr), @intFromPtr(ptr) | clear_bits); + return @as(@TypeOf(ptr), @ptrFromInt(@intFromPtr(ptr) | clear_bits)); } pub fn set_alias(ptr: anytype) @TypeOf(ptr) { - return @ptrFromInt(@TypeOf(ptr), @intFromPtr(ptr) | set_bits); + return @as(@TypeOf(ptr), @ptrFromInt(@intFromPtr(ptr) | set_bits)); } pub fn xor_alias(ptr: anytype) @TypeOf(ptr) { - return @ptrFromInt(@TypeOf(ptr), @intFromPtr(ptr) | xor_bits); + return @as(@TypeOf(ptr), @ptrFromInt(@intFromPtr(ptr) | xor_bits)); } pub inline fn tight_loop_contents() void { diff --git a/src/hal/i2c.zig b/src/hal/i2c.zig index cc7467e..b000e35 100644 --- a/src/hal/i2c.zig +++ b/src/hal/i2c.zig @@ -20,14 +20,14 @@ pub const Config = struct { }; pub fn num(n: u1) I2C { - return @enumFromInt(I2C, n); + return @as(I2C, @enumFromInt(n)); } pub const Address = enum(u7) { _, pub fn new(addr: u7) Address { - var a = @enumFromInt(Address, addr); + var a = @as(Address, @enumFromInt(addr)); std.debug.assert(!a.is_reserved()); return a; } @@ -167,10 +167,10 @@ pub const I2C = enum(u1) { // Always use "fast" mode (<= 400 kHz, works fine for standard mode too) regs.IC_CON.modify(.{ .SPEED = .{ .value = .FAST } }); - regs.IC_FS_SCL_HCNT.write(.{ .IC_FS_SCL_HCNT = @intCast(u16, hcnt), .padding = 0 }); - regs.IC_FS_SCL_LCNT.write(.{ .IC_FS_SCL_LCNT = @intCast(u16, lcnt), .padding = 0 }); - regs.IC_FS_SPKLEN.write(.{ .IC_FS_SPKLEN = if (lcnt < 16) 1 else @intCast(u8, lcnt / 16), .padding = 0 }); - regs.IC_SDA_HOLD.modify(.{ .IC_SDA_TX_HOLD = @intCast(u16, sda_tx_hold_count) }); + regs.IC_FS_SCL_HCNT.write(.{ .IC_FS_SCL_HCNT = @as(u16, @intCast(hcnt)), .padding = 0 }); + regs.IC_FS_SCL_LCNT.write(.{ .IC_FS_SCL_LCNT = @as(u16, @intCast(lcnt)), .padding = 0 }); + regs.IC_FS_SPKLEN.write(.{ .IC_FS_SPKLEN = if (lcnt < 16) 1 else @as(u8, @intCast(lcnt / 16)), .padding = 0 }); + regs.IC_SDA_HOLD.modify(.{ .IC_SDA_TX_HOLD = @as(u16, @intCast(sda_tx_hold_count)) }); i2c.enable(); @@ -343,7 +343,7 @@ pub const I2C = enum(u1) { } const abort_reason = regs.IC_TX_ABRT_SOURCE.read(); - if (@bitCast(u32, abort_reason) != 0) { + if (@as(u32, @bitCast(abort_reason)) != 0) { // Note clearing the abort flag also clears the reason, and // this instance of flag is clear-on-read! Note also the // IC_CLR_TX_ABRT register always reads as 0. diff --git a/src/hal/multicore.zig b/src/hal/multicore.zig index bc2b4de..1ca3ebb 100644 --- a/src/hal/multicore.zig +++ b/src/hal/multicore.zig @@ -70,7 +70,7 @@ pub fn launch_core1_with_stack(entrypoint: *const fn () void, stack: []u32) void fn wrapper(_: u32, _: u32, _: u32, _: u32, entry: u32, stack_base: [*]u32) callconv(.C) void { // TODO: protect stack using MPU _ = stack_base; - @ptrFromInt(*const fn () void, entry)(); + @as(*const fn () void, @ptrFromInt(entry))(); } }.wrapper; diff --git a/src/hal/pins.zig b/src/hal/pins.zig index 5de0810..3ca3238 100644 --- a/src/hal/pins.zig +++ b/src/hal/pins.zig @@ -362,13 +362,13 @@ pub fn Pins(comptime config: GlobalConfiguration) type { } else if (pin_config.function.is_adc()) { pin_field.name = pin_config.name orelse @tagName(pin_config.function); pin_field.type = adc.Input; - pin_field.default_value = @ptrCast(?*const anyopaque, switch (pin_config.function) { + pin_field.default_value = @as(?*const anyopaque, @ptrCast(switch (pin_config.function) { .ADC0 => &adc.Input.ain0, .ADC1 => &adc.Input.ain1, .ADC2 => &adc.Input.ain2, .ADC3 => &adc.Input.ain3, else => unreachable, - }); + })); } else { continue; } @@ -536,7 +536,7 @@ pub const GlobalConfiguration = struct { var ret: Pins(config) = undefined; inline for (@typeInfo(Pins(config)).Struct.fields) |field| { if (field.default_value) |default_value| { - @field(ret, field.name) = @ptrCast(*const field.field_type, default_value).*; + @field(ret, field.name) = @as(*const field.field_type, @ptrCast(default_value)).*; } else { @field(ret, field.name) = .{}; } diff --git a/src/hal/pio.zig b/src/hal/pio.zig index 6b7ca1f..9472728 100644 --- a/src/hal/pio.zig +++ b/src/hal/pio.zig @@ -74,10 +74,10 @@ pub const ClkDivOptions = struct { frac: u8 = 0, pub fn from_float(div: f32) ClkDivOptions { - const fixed = @intFromFloat(u24, div * 256); + const fixed = @as(u24, @intFromFloat(div * 256)); return ClkDivOptions{ - .int = @truncate(u16, fixed >> 8), - .frac = @truncate(u8, fixed), + .int = @as(u16, @truncate(fixed >> 8)), + .frac = @as(u8, @truncate(fixed)), }; } }; @@ -154,7 +154,7 @@ pub const Pio = enum(u1) { pub fn get_instruction_memory(self: Pio) *volatile [32]u32 { const regs = self.get_regs(); - return @ptrCast(*volatile [32]u32, ®s.INSTR_MEM0); + return @as(*volatile [32]u32, @ptrCast(®s.INSTR_MEM0)); } pub fn gpio_init(self: Pio, pin: gpio.Pin) void { @@ -184,7 +184,7 @@ pub const Pio = enum(u1) { else error.NoSpace else for (0..(32 - program.instructions.len)) |i| { - const offset = @intCast(u5, i); + const offset = @as(u5, @intCast(i)); if (self.can_add_program_at_offset(program, offset)) break offset; } else error.NoSpace; @@ -218,23 +218,23 @@ pub const Pio = enum(u1) { const claimed_mask = claimed_state_machines[@intFromEnum(self)]; return for (0..4) |i| { - const sm_mask = (@as(u4, 1) << @intCast(u2, i)); + const sm_mask = (@as(u4, 1) << @as(u2, @intCast(i))); if (0 == (claimed_mask & sm_mask)) { claimed_state_machines[@intFromEnum(self)] |= sm_mask; - break @enumFromInt(StateMachine, i); + break @as(StateMachine, @enumFromInt(i)); } } else error.NoSpace; } pub fn get_sm_regs(self: Pio, sm: StateMachine) *volatile StateMachine.Regs { const pio_regs = self.get_regs(); - const sm_regs = @ptrCast(*volatile [4]StateMachine.Regs, &pio_regs.SM0_CLKDIV); + const sm_regs = @as(*volatile [4]StateMachine.Regs, @ptrCast(&pio_regs.SM0_CLKDIV)); return &sm_regs[@intFromEnum(sm)]; } fn get_irq_regs(self: Pio, irq: Irq) *volatile Irq.Regs { const pio_regs = self.get_regs(); - const irq_regs = @ptrCast(*volatile [2]Irq.Regs, &pio_regs.IRQ0_INTE); + const irq_regs = @as(*volatile [2]Irq.Regs, @ptrCast(&pio_regs.IRQ0_INTE)); return &irq_regs[@intFromEnum(irq)]; } @@ -313,7 +313,7 @@ pub const Pio = enum(u1) { pub fn sm_get_tx_fifo(self: Pio, sm: StateMachine) *volatile u32 { const regs = self.get_regs(); - const fifos = @ptrCast(*volatile [4]u32, ®s.TXF0); + const fifos = @as(*volatile [4]u32, @ptrCast(®s.TXF0)); return &fifos[@intFromEnum(sm)]; } @@ -386,7 +386,7 @@ pub const Pio = enum(u1) { const regs = self.get_regs(); const levels = regs.FLEVEL.raw; - return @truncate(u4, levels >> (@as(u5, 4) * num) + offset); + return @as(u4, @truncate(levels >> (@as(u5, 4) * num) + offset)); } fn interrupt_bit_pos( @@ -469,7 +469,7 @@ pub const Pio = enum(u1) { pub fn sm_exec(self: Pio, sm: StateMachine, instruction: Instruction) void { const sm_regs = self.get_sm_regs(sm); - sm_regs.instr.raw = @bitCast(u16, instruction); + sm_regs.instr.raw = @as(u16, @bitCast(instruction)); } pub fn sm_load_and_start_program( @@ -498,7 +498,7 @@ pub const Pio = enum(u1) { .wrap = if (program.wrap) |wrap| wrap else - offset + @intCast(u5, program.instructions.len), + offset + @as(u5, @intCast(program.instructions.len)), .wrap_target = if (program.wrap_target) |wrap_target| wrap_target diff --git a/src/hal/pio/assembler.zig b/src/hal/pio/assembler.zig index 1c38816..6c6be6f 100644 --- a/src/hal/pio/assembler.zig +++ b/src/hal/pio/assembler.zig @@ -22,7 +22,7 @@ pub const Program = struct { wrap: ?u5, pub fn get_mask(program: Program) u32 { - return (@as(u32, 1) << @intCast(u5, program.instructions.len)) - 1; + return (@as(u32, 1) << @as(u5, @intCast(program.instructions.len))) - 1; } }; diff --git a/src/hal/pio/assembler/Expression.zig b/src/hal/pio/assembler/Expression.zig index 794b5c3..789fb78 100644 --- a/src/hal/pio/assembler/Expression.zig +++ b/src/hal/pio/assembler/Expression.zig @@ -123,7 +123,7 @@ fn trim_outer_parenthesis(str: []const u8) TrimResult { return TrimResult{ .str = str[start..end], - .index = @intCast(u32, start), + .index = @as(u32, @intCast(start)), }; } @@ -142,9 +142,9 @@ fn recursive_tokenize( var parenthesis_found = false; var depth: u32 = 0; - var i = @intCast(i32, expr_str.len - 1); + var i = @as(i32, @intCast(expr_str.len - 1)); outer: while (i >= 0) : (i -= 1) { - const idx = @intCast(u32, i); + const idx = @as(u32, @intCast(i)); // TODO: how about if the expression is fully enveloped in parenthesis? switch (expr_str[idx]) { ')' => { @@ -176,7 +176,7 @@ fn recursive_tokenize( const is_negative = (i == 0) or is_negative: { var j = i - 1; while (j >= 0) : (j -= 1) { - const jdx = @intCast(u32, j); + const jdx = @as(u32, @intCast(j)); switch (expr_str[jdx]) { ' ', '\t' => continue, '+', '-', '*', '/' => continue :outer, @@ -229,7 +229,7 @@ fn recursive_tokenize( } else { // if we hit this path, then the full string has been scanned, and no operators const trimmed = std.mem.trim(u8, expr_str, " \t"); - const value_index = expr_index + @intCast(u32, std.mem.indexOf(u8, expr_str, trimmed).?); + const value_index = expr_index + @as(u32, @intCast(std.mem.indexOf(u8, expr_str, trimmed).?)); try ops.append(.{ .op = .value, .index = value_index, @@ -242,7 +242,7 @@ fn recursive_tokenize( } if (depth != 0) { - diags.* = Diagnostics.init(expr_index + @intCast(u32, i), "mismatched parenthesis", .{}); + diags.* = Diagnostics.init(expr_index + @as(u32, @intCast(i)), "mismatched parenthesis", .{}); return error.MismatchedParenthesis; } } @@ -349,7 +349,7 @@ fn recursive_evaluate( } break :blk .{ - .value = @bitCast(i128, @bitReverse(@bitCast(u128, values[0].num)) >> (128 - 32)), + .value = @as(i128, @bitCast(@bitReverse(@as(u128, @bitCast(values[0].num))) >> (128 - 32))), .index = values[0].index, .consumed = .{ .ops = 2, diff --git a/src/hal/pio/assembler/encoder.zig b/src/hal/pio/assembler/encoder.zig index 502b374..0d13c1b 100644 --- a/src/hal/pio/assembler/encoder.zig +++ b/src/hal/pio/assembler/encoder.zig @@ -87,13 +87,13 @@ pub fn Encoder(comptime options: Options) type { std.mem.copy(u8, &define_name, define.name); tmp.append(.{ .name = &define_name, - .value = @intCast(i64, define.value), + .value = @as(i64, @intCast(define.value)), }) catch unreachable; } break :blk tmp.slice(); }, - .instructions = @ptrCast([]const u16, bounded.instructions.slice()), + .instructions = @as([]const u16, @ptrCast(bounded.instructions.slice())), .origin = bounded.origin, .side_set = bounded.side_set, .wrap_target = bounded.wrap_target, @@ -152,7 +152,7 @@ pub fn Encoder(comptime options: Options) type { diags: *?Diagnostics, ) !T { return switch (value) { - .integer => |int| @intCast(T, int), + .integer => |int| @as(T, @intCast(int)), .string => |str| outer: for (define_lists) |defines| { for (defines) |define| { if (std.mem.eql(u8, str, define.name)) { @@ -166,7 +166,7 @@ pub fn Encoder(comptime options: Options) type { break :outer error.TooBig; } - break :outer @intCast(T, define.value); + break :outer @as(T, @intCast(define.value)); } } } else { @@ -189,7 +189,7 @@ pub fn Encoder(comptime options: Options) type { ); } - return @intCast(T, result); + return @as(T, @intCast(result)); }, }; } @@ -482,19 +482,19 @@ pub fn Encoder(comptime options: Options) type { switch (token.data) { .instruction => |instr| try self.encode_instruction(program, instr, token.index, diags), .word => |word| try program.instructions.append( - @bitCast(Instruction, try self.evaluate(u16, program.*, word, token.index, diags)), + @as(Instruction, @bitCast(try self.evaluate(u16, program.*, word, token.index, diags))), ), // already processed .label, .wrap_target, .wrap => {}, .program => { - self.index = @intCast(u32, i); + self.index = @as(u32, @intCast(i)); break; }, else => unreachable, // invalid } } else if (self.tokens.len > 0) - self.index = @intCast(u32, self.tokens.len); + self.index = @as(u32, @intCast(self.tokens.len)); } fn encode_program(self: *Self, diags: *?Diagnostics) !?BoundedProgram { diff --git a/src/hal/pio/assembler/tokenizer.zig b/src/hal/pio/assembler/tokenizer.zig index 29c596d..2aef428 100644 --- a/src/hal/pio/assembler/tokenizer.zig +++ b/src/hal/pio/assembler/tokenizer.zig @@ -199,7 +199,7 @@ pub const Tokenizer = struct { fn consume_peek(self: *Tokenizer, result: PeekResult) void { assert(self.index <= result.start); - self.index = result.start + @intCast(u32, result.str.len); + self.index = result.start + @as(u32, @intCast(result.str.len)); } /// gets next arg without consuming the stream @@ -616,7 +616,7 @@ pub const Tokenizer = struct { const bit_count = if (bit_count_tmp == 32) @as(u5, 0) else - @intCast(u5, bit_count_tmp); + @as(u5, @intCast(bit_count_tmp)); return Token.Instruction.Payload{ .in = .{ @@ -635,7 +635,7 @@ pub const Tokenizer = struct { const bit_count = if (bit_count_tmp == 32) @as(u5, 0) else - @intCast(u5, bit_count_tmp); + @as(u5, @intCast(bit_count_tmp)); return Token.Instruction.Payload{ .out = .{ @@ -1644,7 +1644,7 @@ test "tokenize.instr.in" { try expect_instr_in(.{ .source = @field(Token.Instruction.In.Source, source), - .bit_count = @intCast(u5, bit_count), + .bit_count = @as(u5, @intCast(bit_count)), }, tokens.get(0)); } } @@ -1667,7 +1667,7 @@ test "tokenize.instr.out" { try expect_instr_out(.{ .destination = @field(Token.Instruction.Out.Destination, destination), - .bit_count = @intCast(u5, bit_count), + .bit_count = @as(u5, @intCast(bit_count)), }, tokens.get(0)); } } diff --git a/src/hal/pwm.zig b/src/hal/pwm.zig index 6e5fe1d..82c3756 100644 --- a/src/hal/pwm.zig +++ b/src/hal/pwm.zig @@ -10,7 +10,7 @@ fn get_regs(comptime slice: u32) *volatile Regs { @import("std").debug.assert(slice < 8); const PwmType = microzig.chip.types.peripherals.PWM; const reg_diff = comptime @offsetOf(PwmType, "CH1_CSR") - @offsetOf(PwmType, "CH0_CSR"); - return @ptrFromInt(*volatile Regs, @intFromPtr(PWM) + reg_diff * slice); + return @as(*volatile Regs, @ptrFromInt(@intFromPtr(PWM) + reg_diff * slice)); } pub fn Pwm(comptime slice_num: u32, comptime chan: Channel) type { diff --git a/src/hal/random.zig b/src/hal/random.zig index 3a292a6..b7f102f 100644 --- a/src/hal/random.zig +++ b/src/hal/random.zig @@ -76,10 +76,10 @@ pub const Ascon = struct { var i: usize = 0; while (i < buffer.len) : (i += 1) { // We poll RANDOMBIT eight times per cycle to build a random byte - var r: u8 = @intCast(u8, peripherals.ROSC.RANDOMBIT.read().RANDOMBIT); + var r: u8 = @as(u8, @intCast(peripherals.ROSC.RANDOMBIT.read().RANDOMBIT)); var j: usize = 0; while (j < 7) : (j += 1) { - r = (r << 1) | @intCast(u8, peripherals.ROSC.RANDOMBIT.read().RANDOMBIT); + r = (r << 1) | @as(u8, @intCast(peripherals.ROSC.RANDOMBIT.read().RANDOMBIT)); } buffer[i] = r; } diff --git a/src/hal/resets.zig b/src/hal/resets.zig index a35ad79..3bffa6f 100644 --- a/src/hal/resets.zig +++ b/src/hal/resets.zig @@ -36,7 +36,7 @@ pub const Mask = packed struct(u32) { }; pub fn reset(mask: Mask) void { - const raw_mask = @bitCast(u32, mask); + const raw_mask = @as(u32, @bitCast(mask)); RESETS.RESET.raw = raw_mask; RESETS.RESET.raw = 0; @@ -45,22 +45,22 @@ pub fn reset(mask: Mask) void { } pub inline fn reset_block(mask: Mask) void { - hw.set_alias_raw(&RESETS.RESET).* = @bitCast(u32, mask); + hw.set_alias_raw(&RESETS.RESET).* = @as(u32, @bitCast(mask)); } pub inline fn unreset_block(mask: Mask) void { - hw.clear_alias_raw(&RESETS.RESET).* = @bitCast(u32, mask); + hw.clear_alias_raw(&RESETS.RESET).* = @as(u32, @bitCast(mask)); } pub fn unreset_block_wait(mask: Mask) void { - const raw_mask = @bitCast(u32, mask); + const raw_mask = @as(u32, @bitCast(mask)); hw.clear_alias_raw(&RESETS.RESET).* = raw_mask; // have to bitcast after a read() instead of `RESETS.RESET_DONE.raw` due to // some optimization bug. While loops will not be optimzed away if the // condition has side effects like dereferencing a volatile pointer. // It seems that volatile is not propagating correctly. - while (@bitCast(u32, RESETS.RESET_DONE.read()) & raw_mask != raw_mask) {} + while (@as(u32, @bitCast(RESETS.RESET_DONE.read())) & raw_mask != raw_mask) {} } pub const masks = struct { diff --git a/src/hal/rom.zig b/src/hal/rom.zig index 7b25387..a398074 100644 --- a/src/hal/rom.zig +++ b/src/hal/rom.zig @@ -88,7 +88,7 @@ pub const signatures = struct { /// /// A 32 bit address pointing into bootrom pub fn rom_table_code(c1: u8, c2: u8) u32 { - return @intCast(u32, c1) | (@intCast(u32, c2) << 8); + return @as(u32, @intCast(c1)) | (@as(u32, @intCast(c2)) << 8); } /// Convert a 16 bit pointer stored at the given rom address into a pointer @@ -100,8 +100,8 @@ pub fn rom_table_code(c1: u8, c2: u8) u32 { /// /// The converted pointer pub inline fn rom_hword_as_ptr(rom_addr: u32) *anyopaque { - const ptr_to_ptr = @ptrFromInt(*u16, rom_addr); - return @ptrFromInt(*anyopaque, @intCast(usize, ptr_to_ptr.*)); + const ptr_to_ptr = @as(*u16, @ptrFromInt(rom_addr)); + return @as(*anyopaque, @ptrFromInt(@as(usize, @intCast(ptr_to_ptr.*)))); } /// Lookup a bootrom function by code (inline) @@ -113,8 +113,8 @@ pub inline fn rom_hword_as_ptr(rom_addr: u32) *anyopaque { /// /// A anyopaque pointer to the function; must be cast by the caller pub inline fn _rom_func_lookup(code: Code) *anyopaque { - const rom_table_lookup = @ptrCast(*signatures.rom_table_lookup, rom_hword_as_ptr(0x18)); - const func_table = @ptrCast(*u16, @alignCast(2, rom_hword_as_ptr(0x14))); + const rom_table_lookup = @as(*signatures.rom_table_lookup, @ptrCast(rom_hword_as_ptr(0x18))); + const func_table = @as(*u16, @ptrCast(@alignCast(rom_hword_as_ptr(0x14)))); return rom_table_lookup(func_table, @intFromEnum(code)); } @@ -140,7 +140,7 @@ pub fn popcount32(value: u32) u32 { var f: ?*signatures.popcount32 = null; }; - if (S.f == null) S.f = @ptrCast(*signatures.popcount32, _rom_func_lookup(Code.popcount32)); + if (S.f == null) S.f = @as(*signatures.popcount32, @ptrCast(_rom_func_lookup(Code.popcount32))); return S.f.?(value); } @@ -150,7 +150,7 @@ pub fn reverse32(value: u32) u32 { var f: ?*signatures.reverse32 = null; }; - if (S.f == null) S.f = @ptrCast(*signatures.reverse32, _rom_func_lookup(Code.reverse32)); + if (S.f == null) S.f = @as(*signatures.reverse32, @ptrCast(_rom_func_lookup(Code.reverse32))); return S.f.?(value); } @@ -160,7 +160,7 @@ pub fn clz32(value: u32) u32 { var f: ?*signatures.clz32 = null; }; - if (S.f == null) S.f = @ptrCast(*signatures.clz32, _rom_func_lookup(Code.clz32)); + if (S.f == null) S.f = @as(*signatures.clz32, @ptrCast(_rom_func_lookup(Code.clz32))); return S.f.?(value); } @@ -170,7 +170,7 @@ pub fn ctz32(value: u32) u32 { var f: ?*signatures.ctz32 = null; }; - if (S.f == null) S.f = @ptrCast(*signatures.ctz32, _rom_func_lookup(Code.ctz32)); + if (S.f == null) S.f = @as(*signatures.ctz32, @ptrCast(_rom_func_lookup(Code.ctz32))); return S.f.?(value); } @@ -184,7 +184,7 @@ pub fn memset(dest: []u8, c: u8) []u8 { var f: ?*signatures.memset = null; }; - if (S.f == null) S.f = @ptrCast(*signatures.memset, _rom_func_lookup(Code.memset)); + if (S.f == null) S.f = @as(*signatures.memset, @ptrCast(_rom_func_lookup(Code.memset))); return S.f.?(dest.ptr, c, dest.len)[0..dest.len]; } @@ -196,7 +196,7 @@ pub fn memcpy(dest: []u8, src: []const u8) []u8 { const n = if (dest.len <= src.len) dest.len else src.len; - if (S.f == null) S.f = @ptrCast(*signatures.memcpy, _rom_func_lookup(Code.memcpy)); + if (S.f == null) S.f = @as(*signatures.memcpy, @ptrCast(_rom_func_lookup(Code.memcpy))); return S.f.?(dest.ptr, src.ptr, n)[0..n]; } @@ -206,9 +206,9 @@ pub fn memcpy(dest: []u8, src: []const u8) []u8 { /// Restore all QSPI pad controls to their default state, and connect the SSI to the QSPI pads pub inline fn connect_internal_flash() *signatures.connect_internal_flash { - return @ptrCast( + return @as( *signatures.connect_internal_flash, - _rom_func_lookup(Code.connect_internal_flash), + @ptrCast(_rom_func_lookup(Code.connect_internal_flash)), ); } @@ -218,9 +218,9 @@ pub inline fn connect_internal_flash() *signatures.connect_internal_flash { /// SSI to XIP mode (e.g. by a call to _flash_flush_cache). This function configures /// the SSI with a fixed SCK clock divisor of /6. pub inline fn flash_exit_xip() *signatures.flash_exit_xip { - return @ptrCast( + return @as( *signatures.flash_exit_xip, - _rom_func_lookup(Code.flash_exit_xip), + @ptrCast(_rom_func_lookup(Code.flash_exit_xip)), ); } @@ -230,9 +230,9 @@ pub inline fn flash_exit_xip() *signatures.flash_exit_xip { /// possible, for much higher erase speed. addr must be aligned to a 4096-byte sector, /// and count must be a multiple of 4096 bytes. pub inline fn flash_range_erase() *signatures.flash_range_erase { - return @ptrCast( + return @as( *signatures.flash_range_erase, - _rom_func_lookup(Code.flash_range_erase), + @ptrCast(_rom_func_lookup(Code.flash_range_erase)), ); } @@ -240,18 +240,18 @@ pub inline fn flash_range_erase() *signatures.flash_range_erase { /// start of flash) and count bytes in size. addr must be aligned to a 256-byte /// boundary, and the length of data must be a multiple of 256. pub inline fn flash_range_program() *signatures.flash_range_program { - return @ptrCast( + return @as( *signatures.flash_range_program, - _rom_func_lookup(Code.flash_range_program), + @ptrCast(_rom_func_lookup(Code.flash_range_program)), ); } /// Flush and enable the XIP cache. Also clears the IO forcing on QSPI CSn, so that /// the SSI can drive the flash chip select as normal. pub inline fn flash_flush_cache() *signatures.flash_flush_cache { - return @ptrCast( + return @as( *signatures.flash_flush_cache, - _rom_func_lookup(Code.flash_flush_cache), + @ptrCast(_rom_func_lookup(Code.flash_flush_cache)), ); } @@ -262,8 +262,8 @@ pub inline fn flash_flush_cache() *signatures.flash_flush_cache { /// visible to the debug host, without having to know exactly what kind of flash /// device is connected. pub inline fn flash_enter_cmd_xip() *signatures.flash_enter_cmd_xip { - return @ptrCast( + return @as( *signatures.flash_enter_cmd_xip, - _rom_func_lookup(Code.flash_enter_cmd_xip), + @ptrCast(_rom_func_lookup(Code.flash_enter_cmd_xip)), ); } diff --git a/src/hal/spi.zig b/src/hal/spi.zig index 251b61b..b9b8891 100644 --- a/src/hal/spi.zig +++ b/src/hal/spi.zig @@ -22,7 +22,7 @@ pub const Config = struct { }; pub fn num(n: u1) SPI { - return @enumFromInt(SPI, n); + return @as(SPI, @enumFromInt(n)); } pub const SPI = enum(u1) { @@ -161,8 +161,8 @@ pub const SPI = enum(u1) { while (postdiv > 1) : (postdiv -= 1) { if (freq_in / (prescale * (postdiv - 1)) > baudrate) break; } - spi_regs.SSPCPSR.modify(.{ .CPSDVSR = @intCast(u8, prescale) }); - spi_regs.SSPCR0.modify(.{ .SCR = @intCast(u8, postdiv - 1) }); + spi_regs.SSPCPSR.modify(.{ .CPSDVSR = @as(u8, @intCast(prescale)) }); + spi_regs.SSPCR0.modify(.{ .SCR = @as(u8, @intCast(postdiv - 1)) }); // Return the frequency we were able to achieve return freq_in / (prescale * postdiv); diff --git a/src/hal/time.zig b/src/hal/time.zig index 95691cc..6bf6932 100644 --- a/src/hal/time.zig +++ b/src/hal/time.zig @@ -7,7 +7,7 @@ pub const Absolute = enum(u64) { _, pub fn from_us(us: u64) Absolute { - return @enumFromInt(Absolute, us); + return @as(Absolute, @enumFromInt(us)); } pub fn to_us(time: Absolute) u64 { @@ -36,7 +36,7 @@ pub const Duration = enum(u64) { _, pub fn from_us(us: u64) Duration { - return @enumFromInt(Duration, us); + return @as(Duration, @enumFromInt(us)); } pub fn from_ms(ms: u64) Duration { @@ -67,14 +67,14 @@ pub fn get_time_since_boot() Absolute { var low_word = TIMER.TIMERAWL; const next_high_word = TIMER.TIMERAWH; if (next_high_word == high_word) - break @enumFromInt(Absolute, @intCast(u64, high_word) << 32 | low_word); + break @as(Absolute, @enumFromInt(@as(u64, @intCast(high_word)) << 32 | low_word)); high_word = next_high_word; } else unreachable; } pub fn make_timeout_us(timeout_us: u64) Absolute { - return @enumFromInt(Absolute, get_time_since_boot().to_us() + timeout_us); + return @as(Absolute, @enumFromInt(get_time_since_boot().to_us() + timeout_us)); } pub fn sleep_ms(time_ms: u32) void { diff --git a/src/hal/uart.zig b/src/hal/uart.zig index 678d979..5e4162c 100644 --- a/src/hal/uart.zig +++ b/src/hal/uart.zig @@ -43,7 +43,7 @@ pub const Config = struct { }; pub fn num(n: u1) UART { - return @enumFromInt(UART, n); + return @as(UART, @enumFromInt(n)); } pub const UART = enum(u1) { @@ -118,7 +118,7 @@ pub const UART = enum(u1) { pub fn tx_fifo(uart: UART) *volatile u32 { const regs = uart.get_regs(); - return @ptrCast(*volatile u32, ®s.UARTDR); + return @as(*volatile u32, @ptrCast(®s.UARTDR)); } pub fn dreq_tx(uart: UART) dma.Dreq { @@ -180,7 +180,7 @@ pub const UART = enum(u1) { assert(baud_rate > 0); const uart_regs = uart.get_regs(); const baud_rate_div = (8 * peri_freq / baud_rate); - var baud_ibrd = @intCast(u16, baud_rate_div >> 7); + var baud_ibrd = @as(u16, @intCast(baud_rate_div >> 7)); const baud_fbrd: u6 = if (baud_ibrd == 0) baud_fbrd: { baud_ibrd = 1; @@ -188,7 +188,7 @@ pub const UART = enum(u1) { } else if (baud_ibrd >= 65535) baud_fbrd: { baud_ibrd = 65535; break :baud_fbrd 0; - } else @intCast(u6, ((@truncate(u7, baud_rate_div)) + 1) / 2); + } else @as(u6, @intCast(((@as(u7, @truncate(baud_rate_div))) + 1) / 2)); uart_regs.UARTIBRD.write(.{ .BAUD_DIVINT = baud_ibrd, .padding = 0 }); uart_regs.UARTFBRD.write(.{ .BAUD_DIVFRAC = baud_fbrd, .padding = 0 }); diff --git a/src/hal/usb.zig b/src/hal/usb.zig index 60a9f69..3177047 100644 --- a/src/hal/usb.zig +++ b/src/hal/usb.zig @@ -42,7 +42,7 @@ pub const utf8ToUtf16Le = usb.utf8Toutf16Le; pub var EP0_OUT_CFG: usb.EndpointConfiguration = .{ .descriptor = &usb.EndpointDescriptor{ - .length = @intCast(u8, @sizeOf(usb.EndpointDescriptor)), + .length = @as(u8, @intCast(@sizeOf(usb.EndpointDescriptor))), .descriptor_type = usb.DescType.Endpoint, .endpoint_address = usb.EP0_OUT_ADDR, .attributes = @intFromEnum(usb.TransferType.Control), @@ -57,7 +57,7 @@ pub var EP0_OUT_CFG: usb.EndpointConfiguration = .{ pub var EP0_IN_CFG: usb.EndpointConfiguration = .{ .descriptor = &usb.EndpointDescriptor{ - .length = @intCast(u8, @sizeOf(usb.EndpointDescriptor)), + .length = @as(u8, @intCast(@sizeOf(usb.EndpointDescriptor))), .descriptor_type = usb.DescType.Endpoint, .endpoint_address = usb.EP0_IN_ADDR, .attributes = @intFromEnum(usb.TransferType.Control), @@ -89,26 +89,26 @@ pub const buffers = struct { /// Mapping to the different data buffers in DPSRAM pub var B: usb.Buffers = .{ - .ep0_buffer0 = @ptrFromInt([*]u8, USB_EP0_BUFFER0), - .ep0_buffer1 = @ptrFromInt([*]u8, USB_EP0_BUFFER1), + .ep0_buffer0 = @as([*]u8, @ptrFromInt(USB_EP0_BUFFER0)), + .ep0_buffer1 = @as([*]u8, @ptrFromInt(USB_EP0_BUFFER1)), // We will initialize this comptime in a loop .rest = .{ - @ptrFromInt([*]u8, USB_BUFFERS + (0 * BUFFER_SIZE)), - @ptrFromInt([*]u8, USB_BUFFERS + (1 * BUFFER_SIZE)), - @ptrFromInt([*]u8, USB_BUFFERS + (2 * BUFFER_SIZE)), - @ptrFromInt([*]u8, USB_BUFFERS + (3 * BUFFER_SIZE)), - @ptrFromInt([*]u8, USB_BUFFERS + (4 * BUFFER_SIZE)), - @ptrFromInt([*]u8, USB_BUFFERS + (5 * BUFFER_SIZE)), - @ptrFromInt([*]u8, USB_BUFFERS + (6 * BUFFER_SIZE)), - @ptrFromInt([*]u8, USB_BUFFERS + (7 * BUFFER_SIZE)), - @ptrFromInt([*]u8, USB_BUFFERS + (8 * BUFFER_SIZE)), - @ptrFromInt([*]u8, USB_BUFFERS + (9 * BUFFER_SIZE)), - @ptrFromInt([*]u8, USB_BUFFERS + (10 * BUFFER_SIZE)), - @ptrFromInt([*]u8, USB_BUFFERS + (11 * BUFFER_SIZE)), - @ptrFromInt([*]u8, USB_BUFFERS + (12 * BUFFER_SIZE)), - @ptrFromInt([*]u8, USB_BUFFERS + (13 * BUFFER_SIZE)), - @ptrFromInt([*]u8, USB_BUFFERS + (14 * BUFFER_SIZE)), - @ptrFromInt([*]u8, USB_BUFFERS + (15 * BUFFER_SIZE)), + @as([*]u8, @ptrFromInt(USB_BUFFERS + (0 * BUFFER_SIZE))), + @as([*]u8, @ptrFromInt(USB_BUFFERS + (1 * BUFFER_SIZE))), + @as([*]u8, @ptrFromInt(USB_BUFFERS + (2 * BUFFER_SIZE))), + @as([*]u8, @ptrFromInt(USB_BUFFERS + (3 * BUFFER_SIZE))), + @as([*]u8, @ptrFromInt(USB_BUFFERS + (4 * BUFFER_SIZE))), + @as([*]u8, @ptrFromInt(USB_BUFFERS + (5 * BUFFER_SIZE))), + @as([*]u8, @ptrFromInt(USB_BUFFERS + (6 * BUFFER_SIZE))), + @as([*]u8, @ptrFromInt(USB_BUFFERS + (7 * BUFFER_SIZE))), + @as([*]u8, @ptrFromInt(USB_BUFFERS + (8 * BUFFER_SIZE))), + @as([*]u8, @ptrFromInt(USB_BUFFERS + (9 * BUFFER_SIZE))), + @as([*]u8, @ptrFromInt(USB_BUFFERS + (10 * BUFFER_SIZE))), + @as([*]u8, @ptrFromInt(USB_BUFFERS + (11 * BUFFER_SIZE))), + @as([*]u8, @ptrFromInt(USB_BUFFERS + (12 * BUFFER_SIZE))), + @as([*]u8, @ptrFromInt(USB_BUFFERS + (13 * BUFFER_SIZE))), + @as([*]u8, @ptrFromInt(USB_BUFFERS + (14 * BUFFER_SIZE))), + @as([*]u8, @ptrFromInt(USB_BUFFERS + (15 * BUFFER_SIZE))), }, }; }; @@ -278,7 +278,7 @@ pub const F = struct { // The offset _should_ fit in a u16, but if we've gotten something // wrong in the past few lines, a common symptom will be integer // overflow producing a Very Large Number, - const dpram_offset = @intCast(u16, buf_base - dpram_base); + const dpram_offset = @as(u16, @intCast(buf_base - dpram_base)); // Configure the endpoint! modify_endpoint_control(epci, .{ @@ -287,7 +287,7 @@ pub const F = struct { // buffer is done, thx. .INTERRUPT_PER_BUFF = 1, // Select bulk vs control (or interrupt as soon as implemented). - .ENDPOINT_TYPE = .{ .raw = @intCast(u2, ep.descriptor.attributes) }, + .ENDPOINT_TYPE = .{ .raw = @as(u2, @intCast(ep.descriptor.attributes)) }, // And, designate our buffer by its offset. .BUFFER_ADDRESS = dpram_offset, }); @@ -331,7 +331,7 @@ pub const F = struct { modify_buffer_control(ep.buffer_control_index, .{ .PID_0 = np, // DATA0/1, depending .FULL_0 = 1, // We have put data in - .LENGTH_0 = @intCast(u10, buffer.len), // There are this many bytes + .LENGTH_0 = @as(u10, @intCast(buffer.len)), // There are this many bytes }); // Nop for some clock cycles @@ -367,7 +367,7 @@ pub const F = struct { .PID_0 = np, // DATA0/1 depending .FULL_0 = 0, // Buffer is NOT full, we want the computer to fill it .AVAILABLE_0 = 1, // It is, however, available to be filled - .LENGTH_0 = @intCast(u10, len), // Up tho this many bytes + .LENGTH_0 = @as(u10, @intCast(len)), // Up tho this many bytes }); // Flip the DATA0/1 PID for the next receive @@ -588,14 +588,14 @@ pub fn next(self: *usb.EPBIter) ?usb.EPB { var lowbit_index: u5 = 0; while ((self.bufbits >> lowbit_index) & 0x01 == 0) : (lowbit_index += 1) {} // Remove their bit from our set. - const lowbit = @intCast(u32, 1) << lowbit_index; + const lowbit = @as(u32, @intCast(1)) << lowbit_index; self.last_bit = lowbit; self.bufbits ^= lowbit; // Here we exploit knowledge of the ordering of buffer control // registers in the peripheral. Each endpoint has a pair of // registers, so we can determine the endpoint number by: - const epnum = @intCast(u8, lowbit_index >> 1); + const epnum = @as(u8, @intCast(lowbit_index >> 1)); // Of the pair, the IN endpoint comes first, followed by OUT, so // we can get the direction by: const dir = if (lowbit_index & 1 == 0) usb.Dir.In else usb.Dir.Out; @@ -637,7 +637,7 @@ pub fn next(self: *usb.EPBIter) ?usb.EPB { // Get the actual length of the data, which may be less // than the buffer size. - const len = @intCast(usize, bc & 0x3ff); + const len = @as(usize, @intCast(bc & 0x3ff)); // Copy the data from SRAM return usb.EPB{ From 360655dbe23b2fd2350ebf2221496eada8b890b6 Mon Sep 17 00:00:00 2001 From: Vlad Panazan Date: Thu, 29 Jun 2023 22:53:47 +0200 Subject: [PATCH 66/74] use zig package manager (#70) --- .gitmodules | 3 --- build.zig | 2 +- build.zig.zon | 11 +++++++++++ deps/microzig | 1 - src/boards.zig | 2 +- src/chips.zig | 2 +- 6 files changed, 14 insertions(+), 7 deletions(-) delete mode 100644 .gitmodules create mode 100644 build.zig.zon delete mode 160000 deps/microzig diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 32e895c..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "deps/microzig"] - path = deps/microzig - url = https://github.com/ZigEmbeddedGroup/microzig.git diff --git a/build.zig b/build.zig index 4afab69..c690810 100644 --- a/build.zig +++ b/build.zig @@ -4,7 +4,7 @@ const Pkg = std.build.Pkg; const comptimePrint = std.fmt.comptimePrint; const FileSource = std.build.FileSource; -pub const microzig = @import("deps/microzig/build.zig"); +const microzig = @import("microzig"); pub const chips = @import("src/chips.zig"); pub const boards = @import("src/boards.zig"); diff --git a/build.zig.zon b/build.zig.zon new file mode 100644 index 0000000..32cee66 --- /dev/null +++ b/build.zig.zon @@ -0,0 +1,11 @@ +.{ + .name = "rp2040", + .version = "0.0.0", + .dependencies = .{ + .microzig = .{ + .url = "https://github.com/ZigEmbeddedGroup/microzig/archive/9392fe0f7bddde26155c181ab80b70097b49c791.tar.gz", + .hash = "1220326148075cd017425e04356329c33c3e794d31a54bdafa46521fcfcc55b422a3", + }, + }, +} + diff --git a/deps/microzig b/deps/microzig deleted file mode 160000 index 9392fe0..0000000 --- a/deps/microzig +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9392fe0f7bddde26155c181ab80b70097b49c791 diff --git a/src/boards.zig b/src/boards.zig index ebbf0d8..d2af0ee 100644 --- a/src/boards.zig +++ b/src/boards.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const microzig = @import("../deps/microzig/build.zig"); +const microzig = @import("microzig"); const chips = @import("chips.zig"); fn root_dir() []const u8 { diff --git a/src/chips.zig b/src/chips.zig index 8363cea..48b20e0 100644 --- a/src/chips.zig +++ b/src/chips.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const microzig = @import("../deps/microzig/build.zig"); +const microzig = @import("microzig"); fn root_dir() []const u8 { return std.fs.path.dirname(@src().file) orelse "."; From 35e9757bdb9873ffd7a5d2c192842cf93b58c7e5 Mon Sep 17 00:00:00 2001 From: Vlad Panazan Date: Sat, 1 Jul 2023 15:22:51 +0200 Subject: [PATCH 67/74] fix i2c reading and add bus scan example (#71) --- build.zig | 1 + examples/i2c_bus_scan.zig | 44 +++++++++++++++++++++++++++++++++++++++ src/hal/i2c.zig | 13 +++++++----- 3 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 examples/i2c_bus_scan.zig diff --git a/build.zig b/build.zig index c690810..e75a109 100644 --- a/build.zig +++ b/build.zig @@ -63,6 +63,7 @@ pub const Examples = struct { blinky: *microzig.EmbeddedExecutable, blinky_core1: *microzig.EmbeddedExecutable, gpio_clk: *microzig.EmbeddedExecutable, + i2c_bus_scan: *microzig.EmbeddedExecutable, pwm: *microzig.EmbeddedExecutable, spi_master: *microzig.EmbeddedExecutable, uart: *microzig.EmbeddedExecutable, diff --git a/examples/i2c_bus_scan.zig b/examples/i2c_bus_scan.zig new file mode 100644 index 0000000..702bcef --- /dev/null +++ b/examples/i2c_bus_scan.zig @@ -0,0 +1,44 @@ +const std = @import("std"); +const microzig = @import("microzig"); + +const rp2040 = microzig.hal; +const i2c = rp2040.i2c; +const gpio = rp2040.gpio; +const peripherals = microzig.chip.peripherals; + +pub const std_options = struct { + pub const log_level = .info; + pub const logFn = rp2040.uart.log; +}; + +const uart = rp2040.uart.num(0); +const i2c0 = i2c.num(0); + +pub fn main() !void { + uart.apply(.{ + .baud_rate = 115200, + .tx_pin = gpio.num(0), + .rx_pin = gpio.num(1), + .clock_config = rp2040.clock_config, + }); + rp2040.uart.init_logger(uart); + + _ = i2c0.apply(.{ + .clock_config = rp2040.clock_config, + .scl_pin = gpio.num(4), + .sda_pin = gpio.num(5), + }); + + for (0..std.math.maxInt(u7)) |addr| { + const a: i2c.Address = @enumFromInt(addr); + + // Skip over any reserved addresses. + if (a.is_reserved()) continue; + + var rx_data: [1]u8 = undefined; + _ = i2c0.read_blocking(a, &rx_data) catch continue; + + std.log.info("I2C device found at address {X}.", .{addr}); + } +} + diff --git a/src/hal/i2c.zig b/src/hal/i2c.zig index b000e35..a6c1517 100644 --- a/src/hal/i2c.zig +++ b/src/hal/i2c.zig @@ -243,12 +243,13 @@ pub const I2C = enum(u1) { _ = tc; } }; - try i2c.read_blocking_internal(addr, dst, Timeout{}); + return i2c.read_blocking_internal(addr, dst, Timeout{}); } /// Determine non-blocking write space available. pub inline fn get_write_available(i2c: I2C) u5 { - return i2c.get_regs().IC_TXFLR.read().TXFLR; + const IC_TX_BUFFER_DEPTH = 16; + return IC_TX_BUFFER_DEPTH - i2c.get_regs().IC_TXFLR.read().TXFLR; } /// Determine number of bytes received. @@ -378,7 +379,7 @@ pub const I2C = enum(u1) { for (dst, 0..) |*byte, i| { const first = (i == 0); const last = (i == dst.len - 1); - while (i2c.get_write_available(i2c) == 0) { + while (i2c.get_write_available() == 0) { hw.tight_loop_contents(); } @@ -388,11 +389,11 @@ pub const I2C = enum(u1) { .CMD = .{ .value = .READ }, .DAT = 0, - .FIRST_DATA_BYTE = .{ .value = 0 }, + .FIRST_DATA_BYTE = .{ .raw = 0 }, .padding = 0, }); - while (i2c.get_read_available() == 0) { + while (true) { const abort_reason = regs.IC_TX_ABRT_SOURCE.read(); const abort = (regs.IC_CLR_TX_ABRT.read().CLR_TX_ABRT != 0); if (abort) { @@ -403,6 +404,8 @@ pub const I2C = enum(u1) { } try timeout_check.perform(); + + if (i2c.get_read_available() != 0) break; } byte.* = regs.IC_DATA_CMD.read().DAT; From d6b3be320f8f9dd0958a9ab460da991f57fd7722 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Quei=C3=9Fner?= Date: Mon, 24 Jul 2023 15:01:19 +0200 Subject: [PATCH 68/74] rp2040-flasher inital commit (#72) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Felix (xq) Queißner --- build.zig | 14 ++ build.zig.zon | 5 +- tools/rp2040-flash.zig | 331 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 349 insertions(+), 1 deletion(-) create mode 100644 tools/rp2040-flash.zig diff --git a/build.zig b/build.zig index e75a109..b9f2803 100644 --- a/build.zig +++ b/build.zig @@ -39,6 +39,10 @@ pub fn addPiPicoExecutable( // project requires multiple HALs, it accepts microzig as a param pub fn build(b: *Builder) !void { const optimize = b.standardOptimizeOption(.{}); + + const args_dep = b.dependency("args", .{}); + const args_mod = args_dep.module("args"); + var examples = Examples.init(b, optimize); examples.install(b); @@ -52,6 +56,16 @@ pub fn build(b: *Builder) !void { const test_step = b.step("test", "run unit tests"); test_step.dependOn(&b.addRunArtifact(pio_tests).step); + + const flash_tool = b.addExecutable(.{ + .name = "rp2040-flash", + .optimize = .Debug, + .target = .{}, + .root_source_file = .{ .path = "tools/rp2040-flash.zig" }, + }); + flash_tool.addModule("args", args_mod); + + b.installArtifact(flash_tool); } fn root() []const u8 { diff --git a/build.zig.zon b/build.zig.zon index 32cee66..d8db2db 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -6,6 +6,9 @@ .url = "https://github.com/ZigEmbeddedGroup/microzig/archive/9392fe0f7bddde26155c181ab80b70097b49c791.tar.gz", .hash = "1220326148075cd017425e04356329c33c3e794d31a54bdafa46521fcfcc55b422a3", }, + .args = .{ + .url = "https://github.com/MasterQ32/zig-args/archive/91d1e89fb89a4d01dec7c9aec95b0a324080ebcc.tar.gz", + .hash = "12203d04cafc97f952d74cdb077e74c0ab3414f9f6b5fbd159112c62bfa584a0dbed", + }, }, } - diff --git a/tools/rp2040-flash.zig b/tools/rp2040-flash.zig new file mode 100644 index 0000000..23b48ac --- /dev/null +++ b/tools/rp2040-flash.zig @@ -0,0 +1,331 @@ +const std = @import("std"); +const args_parser = @import("args"); +const builtin = @import("builtin"); + +const CliOptions = struct { + help: bool = false, + device: ?[]const u8 = null, + wait: bool = false, + + pub const shorthands = .{ + .h = "help", + .d = "device", + .w = "wait", + }; +}; + +const wait_device_ready_timeout = 60 * std.time.ns_per_s; // timeout until a device is found +const wait_device_avail_timeout = 60 * std.time.ns_per_s; // timeout until a device is found +const access_denied_limit = 20; // try that many times with AccessDenied before the user is informed + +fn print_usage(file: std.fs.File, exe: ?[]const u8) !void { + try file.writer().writeAll(exe orelse "rp2040-flash"); + try file.writer().writeAll( + \\ [-h] [-d ] + \\Flash your RP2040 devices easily via UF2 interface. + \\ + \\Options: + \\ -h, --help Shows this help text. + \\ -d, --device Uses as the UF2 device. Otherwise tries to auto-guess the correct device. + \\ -w, --wait Waits 60 seconds until a device appears. + \\ + ); +} + +pub fn main() !u8 { + const stderr = std.io.getStdErr(); + const stdout = std.io.getStdOut(); + const stdin = std.io.getStdIn(); + + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer _ = arena.deinit(); + + const allocator = arena.allocator(); + + var cli = args_parser.parseForCurrentProcess(CliOptions, allocator, .print) catch return 1; + defer cli.deinit(); + + if (cli.options.help) { + try print_usage(stdout, cli.executable_name); + return 0; + } + + if (cli.positionals.len != 1) { + try print_usage(stderr, cli.executable_name); + return 1; + } + + const uf2_file_path = cli.positionals[0]; + + var uf2_file = try std.fs.cwd().openFile(uf2_file_path, .{}); + defer uf2_file.close(); + + const uf2_stat = try uf2_file.stat(); + if ((uf2_stat.size % 512) != 0) { + std.log.warn("{s} does not have a size multiple of 512. might be corrupt!", .{uf2_file_path}); + } + + const file_valid = blk: { + try uf2_file.seekTo(0); + + var file_valid = true; + + while (file_valid) { + var block: [512]u8 = undefined; + const len = try uf2_file.read(&block); + if (len == 0) + break; + + // 0 4 First magic number, 0x0A324655 ("UF2\n") + // 4 4 Second magic number, 0x9E5D5157 + // 8 4 Flags + // 12 4 Address in flash where the data should be written + // 16 4 Number of bytes used in data (often 256) + // 20 4 Sequential block number; starts at 0 + // 24 4 Total number of blocks in file + // 28 4 File size or board family ID or zero + // 32 476 Data, padded with zeros + // 508 4 Final magic number, 0x0AB16F30 + + const first_magic_number = std.mem.readIntLittle(u32, block[0..][0..4]); + const second_magic_number = std.mem.readIntLittle(u32, block[4..][0..4]); + const final_magic_number = std.mem.readIntLittle(u32, block[508..][0..4]); + + file_valid = file_valid and (first_magic_number == 0x0A324655); + file_valid = file_valid and (second_magic_number == 0x9E5D5157); + file_valid = file_valid and (final_magic_number == 0x0AB16F30); + } + break :blk file_valid; + }; + + if (file_valid == false) { + std.log.warn("{s} does not seem to be a valid UF2 file. Do you really want to flash it?", .{uf2_file_path}); + while (true) { + try stderr.writer().writeAll("Flash? [jN]: "); + + var buffer: [64]u8 = undefined; + const selection_or_null = try stdin.reader().readUntilDelimiterOrEof(&buffer, '\n'); + + const selection_str = std.mem.trim(u8, selection_or_null orelse "", "\r\n\t "); + if (selection_str.len == 0) + return 1; + + if (std.ascii.eqlIgnoreCase(selection_str, "j")) + break; + + if (std.ascii.eqlIgnoreCase(selection_str, "n")) + return 1; + } + } + + try uf2_file.seekTo(0); + + const detect_timeout = std.time.nanoTimestamp() + wait_device_avail_timeout; + var first_run = true; + const device_path = if (cli.options.device) |devname| + try allocator.dupe(u8, devname) + else while (true) { + if (std.time.nanoTimestamp() >= detect_timeout) { + try stderr.writeAll("failed to detect any RP2040 devices :(\n"); + + return 1; + } + + const maybe_device = try autoDetectPico(allocator); + + if (maybe_device) |device| + break device; + + if (!cli.options.wait) { + try stderr.writeAll("failed to detect any RP2040 devices :(\n"); + return 1; + } + + if (first_run) { + try stderr.writeAll("failed to detect any RP2040 devices, waiting...\n"); + first_run = false; + } + + std.time.sleep(250 * std.time.ns_per_ms); + }; + + const connect_timeout = std.time.nanoTimestamp() + wait_device_ready_timeout; + + var first_attempt = true; + var access_denied_counter: u32 = 0; + var last_err: anyerror = error.Unknown; + var device_file: std.fs.File = blk: while (std.time.nanoTimestamp() < connect_timeout) { + var device = std.fs.cwd().openFile(device_path, .{ .mode = .write_only }) catch |err| { + last_err = err; + + switch (err) { + error.FileNotFound => {}, // just waiting for the device + error.AccessDenied => { + access_denied_counter += 1; + if (access_denied_counter >= access_denied_limit) { + try stderr.writer().print("Could not open {s}: Access denied. Do you have write-access to the device?\n", .{device_path}); + return 1; + } + }, + else => |e| return e, + } + + if (first_attempt) { + try stderr.writer().print("Waiting for {s}.", .{device_path}); + first_attempt = false; + } else { + try stderr.writeAll("."); + } + std.time.sleep(250 * std.time.ns_per_ms); + continue; + }; + try stderr.writeAll("\n"); + break :blk device; + } else { + try stderr.writer().print("\nfailed to connect to {s}: {s}\n", .{ device_path, @errorName(last_err) }); + return 1; + }; + defer device_file.close(); + + try stderr.writeAll("Flashing"); + + { + try uf2_file.seekTo(0); + + var block_num: u64 = 0; + while (true) { + try stderr.writeAll("."); + + var block: [512]u8 = undefined; + const rd_len = try uf2_file.read(&block); + if (rd_len == 0) + break; + if (rd_len != block.len) { + try stderr.writer().print("\nFailed to read block {}: Only {} bytes read!\n", .{ block_num, rd_len }); + return 1; + } + + const wr_len = try device_file.write(&block); + if (wr_len != block.len) { + try stderr.writer().print("\nFailed to write block {}: Only {} bytes written!\n", .{ block_num, wr_len }); + return 1; + } + + block_num += 1; + } + } + try stderr.writeAll("\nDone.\n"); + + return 0; +} + +fn autoDetectPico(allocator: std.mem.Allocator) !?[]const u8 { + switch (builtin.os.tag) { + .linux => { + const stdin = std.io.getStdIn(); + const stderr = std.io.getStdErr(); + + const Device = struct { + name: []const u8, + path: []const u8, + }; + + var picos = std.ArrayList(Device).init(allocator); + defer picos.deinit(); + + var base_dir = try std.fs.openIterableDirAbsolute("/sys/block/", .{}); + defer base_dir.close(); + + var iter = base_dir.iterate(); + + while (try iter.next()) |entry| { + var device_dir = try base_dir.dir.openDir(entry.name, .{}); + defer device_dir.close(); + + const H = struct { + fn isPicoDevice(dir: std.fs.Dir, allo: std.mem.Allocator) !?[]const u8 { + // "/sys/block/*/removable" => "1" + // "/sys/block/*/device/model" => "RP2" + // "/sys/block/*/device/vendor" => "RPI" + + var buffer: [64]u8 = undefined; + + const removable = std.mem.trim(u8, try dir.readFile("removable", &buffer), "\r\n\t "); + if (!std.mem.eql(u8, removable, "1")) + return null; + + const device_model = std.mem.trim(u8, try dir.readFile("device/model", &buffer), "\r\n\t "); + if (!std.mem.eql(u8, device_model, "RP2")) + return null; + + const device_vendor = std.mem.trim(u8, try dir.readFile("device/vendor", &buffer), "\r\n\t "); + if (!std.mem.eql(u8, device_vendor, "RPI")) + return null; + + const device_id = std.mem.trim(u8, try dir.readFile("dev", &buffer), "\r\n\t "); + + return try std.fs.path.join(allo, &.{ + "/dev/block", device_id, + }); + } + }; + + const maybe_device = H.isPicoDevice(device_dir, allocator) catch |err| { + if (err != error.FileNotFound and err != error.AccessDenied) { + std.log.err("failed to scan /sys/block/{s}: {s}", .{ entry.name, @errorName(err) }); + } + continue; + }; + + if (maybe_device) |device_path| { + try picos.append(Device{ + .name = try allocator.dupe(u8, entry.name), + .path = device_path, + }); + } + } + + if (picos.items.len == 0) { + return null; + } + + var default_selection: usize = 0; + + try stderr.writer().writeAll("Select your device:\n"); + for (picos.items, 1..) |pico_dev, index| { + try stderr.writer().print("#{d: <2} {s}\n", .{ index, pico_dev.name }); + + if (default_selection == 0) { + default_selection = index; + } + } + + const selection = while (true) { + try stderr.writer().print("Select port [{}]: ", .{default_selection}); + + var buffer: [64]u8 = undefined; + const selection_or_null = try stdin.reader().readUntilDelimiterOrEof(&buffer, '\n'); + + const selection_str = std.mem.trim(u8, selection_or_null orelse break default_selection, "\r\n\t "); + + if (selection_str.len == 0) + break default_selection; + + const selection = std.fmt.parseInt(usize, selection_str, 10) catch continue; + + if (selection < 1 or selection > picos.items.len) { + continue; + } + + break selection; + }; + + return picos.items[selection - 1].path; + }, + + else => { + std.log.warn("Device auto-detection not implemented for {s}", .{@tagName(builtin.os.tag)}); + return null; + }, + } +} From 1cef56ad9d5df63af9c45f54a4983b36b0796f7f Mon Sep 17 00:00:00 2001 From: David Sugar Date: Mon, 31 Jul 2023 16:20:02 +0200 Subject: [PATCH 69/74] Enable XIP using stage 2 bootloader (#73) * flash enable xip calls stage two bootloader using inline assembly * flash erase/program now works in all modes (Debug, ReleaseSmall, ReleaseSafe, ReleaseFast) * further docs added --- examples/flash_program.zig | 2 +- rp2040.ld | 2 +- src/hal/flash.zig | 69 +++++++++++++++++++++++++++----------- 3 files changed, 51 insertions(+), 22 deletions(-) diff --git a/examples/flash_program.zig b/examples/flash_program.zig index 48754e1..9fd13be 100644 --- a/examples/flash_program.zig +++ b/examples/flash_program.zig @@ -62,7 +62,7 @@ pub fn main() !void { // Note that a whole number of pages (256 bytes) must be written at a time std.log.info("Programming target region...", .{}); - flash.range_program(flash_target_offset, &data); + flash.range_program(flash_target_offset, data[0..]); std.log.info("Done. Read back target region:", .{}); std.log.info("data: {s}", .{flash_target_contents[0..flash.PAGE_SIZE]}); diff --git a/rp2040.ld b/rp2040.ld index cac0892..4517b36 100644 --- a/rp2040.ld +++ b/rp2040.ld @@ -43,7 +43,7 @@ SECTIONS .data : { microzig_data_start = .; - *(.time_critical*) + KEEP(*(.time_critical*)) *(.data*) microzig_data_end = .; } > ram0 AT> flash0 diff --git a/src/hal/flash.zig b/src/hal/flash.zig index 7ce3206..f10315e 100644 --- a/src/hal/flash.zig +++ b/src/hal/flash.zig @@ -1,3 +1,4 @@ +//! See [rp2040 docs](https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf), page 136. const rom = @import("rom.zig"); pub const Command = enum(u8) { @@ -12,33 +13,51 @@ pub const BLOCK_SIZE = 65536; /// Bus reads to a 16MB memory window start at this address pub const XIP_BASE = 0x10000000; +/// Flash code related to the second stage boot loader pub const boot2 = struct { - /// Size of the second stage bootloader in bytes - const BOOT2_SIZE_BYTES = 64; + /// Size of the second stage bootloader in words + const BOOT2_SIZE_WORDS = 64; /// Buffer for the second stage bootloader - var copyout: [BOOT2_SIZE_BYTES]u32 = undefined; + /// + /// The only job of the second stage bootloader is to configure the SSI and + /// the external flash for the best possible execute-in-place (XIP) performance. + /// Until the SSI is correctly configured for the attached flash device, it's not + /// possible to access flash via the XIP address window, i.e., we have to copy + /// the bootloader into sram before calling `rom.flash_exit_xip`. This is required + /// if we want to erase and/or write to flash. + /// + /// At the end we can then just make a subroutine call to copyout, to configure + /// the SSI and flash. The second stage bootloader will return to the calling function + /// if a return address is provided in `lr`. + var copyout: [BOOT2_SIZE_WORDS]u32 = undefined; var copyout_valid: bool = false; /// Copy the 2nd stage bootloader into memory - pub fn flash_init() linksection(".time_critical") void { + /// + /// This is required by `_range_erase` and `_range_program` so we can later setup + /// XIP via the second stage bootloader. + pub export fn flash_init() linksection(".time_critical") void { if (copyout_valid) return; const bootloader = @as([*]u32, @ptrFromInt(XIP_BASE)); var i: usize = 0; - while (i < BOOT2_SIZE_BYTES) : (i += 1) { + while (i < BOOT2_SIZE_WORDS) : (i += 1) { copyout[i] = bootloader[i]; } copyout_valid = true; } - pub fn flash_enable_xip() linksection(".time_critical") void { - // TODO: use the second stage bootloader instead of cmd_xip - //const bootloader: []u32 = copyout[1..]; - - //const f = @ptrCast(*fn () void, bootloader.ptr); - //f(); - - rom.flash_enter_cmd_xip()(); + /// Configure the SSI and the external flash for XIP by calling the second stage + /// bootloader that was copied out to `copyout`. + pub export fn flash_enable_xip() linksection(".time_critical") void { + // The bootloader is in thumb mode + asm volatile ( + \\adds r0, #1 + \\blx r0 + : + : [copyout] "{r0}" (@intFromPtr(©out)), + : "r0", "lr" + ); } }; @@ -46,12 +65,17 @@ pub const boot2 = struct { /// /// The offset must be aligned to a 4096-byte sector, and count must /// be a multiple of 4096 bytes! -pub fn range_erase(offset: u32, count: u32) linksection(".time_critical") void { +pub inline fn range_erase(offset: u32, count: u32) void { + // Do not inline `_range_erase`! + @call(.never_inline, _range_erase, .{ offset, count }); +} + +export fn _range_erase(offset: u32, count: u32) linksection(".time_critical") void { // TODO: add sanity checks, e.g., offset + count < flash size - boot2.flash_init(); + asm volatile ("" ::: "memory"); // memory barrier - // TODO: __compiler_memory_barrier + boot2.flash_init(); rom.connect_internal_flash()(); rom.flash_exit_xip()(); @@ -65,16 +89,21 @@ pub fn range_erase(offset: u32, count: u32) linksection(".time_critical") void { /// /// The offset must be aligned to a 256-byte boundary, and the length of data /// must be a multiple of 256! -pub fn range_program(offset: u32, data: []const u8) linksection(".time_critical") void { +pub inline fn range_program(offset: u32, data: []const u8) void { + // Do not inline `_range_program`! + @call(.never_inline, _range_program, .{ offset, data.ptr, data.len }); +} + +export fn _range_program(offset: u32, data: [*]const u8, len: usize) linksection(".time_critical") void { // TODO: add sanity checks, e.g., offset + count < flash size - boot2.flash_init(); + asm volatile ("" ::: "memory"); // memory barrier - // TODO: __compiler_memory_barrier + boot2.flash_init(); rom.connect_internal_flash()(); rom.flash_exit_xip()(); - rom.flash_range_program()(offset, data.ptr, data.len); + rom.flash_range_program()(offset, data, len); rom.flash_flush_cache()(); boot2.flash_enable_xip(); From 695d3dc0e440cd963125b2efb7e95e60dd8bf0f7 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Thu, 3 Aug 2023 21:24:21 -0700 Subject: [PATCH 70/74] SourceFile -> LazyFile (#75) --- .github/workflows/build.yml | 22 ++++++++++++++++++++++ build.zig | 6 +++--- build.zig.zon | 4 ++-- 3 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..2203973 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,22 @@ +name: Build +on: + push: + +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ + linux-latest, + windows-latest, + macos-latest, + ] + steps: + - uses: actions/checkout@v2 + - uses: goto-bus-stop/setup-zig@v1.3.0 + with: + version: master + + - name: Build and Unit Test + run: zig build test -Doptimize=ReleaseSmall diff --git a/build.zig b/build.zig index b9f2803..dacb224 100644 --- a/build.zig +++ b/build.zig @@ -2,7 +2,7 @@ const std = @import("std"); const Builder = std.build.Builder; const Pkg = std.build.Pkg; const comptimePrint = std.fmt.comptimePrint; -const FileSource = std.build.FileSource; +const LazyPath = std.build.LazyPath; const microzig = @import("microzig"); @@ -17,7 +17,7 @@ pub const BuildOptions = struct { pub const PicoExecutableOptions = struct { name: []const u8, - source_file: FileSource, + source_file: LazyPath, optimize: std.builtin.OptimizeMode = .Debug, }; @@ -52,7 +52,7 @@ pub fn build(b: *Builder) !void { }, .optimize = optimize, }); - pio_tests.addIncludePath("src/hal/pio/assembler"); + pio_tests.addIncludePath(.{ .path = "src/hal/pio/assembler" }); const test_step = b.step("test", "run unit tests"); test_step.dependOn(&b.addRunArtifact(pio_tests).step); diff --git a/build.zig.zon b/build.zig.zon index d8db2db..28bea9e 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -3,8 +3,8 @@ .version = "0.0.0", .dependencies = .{ .microzig = .{ - .url = "https://github.com/ZigEmbeddedGroup/microzig/archive/9392fe0f7bddde26155c181ab80b70097b49c791.tar.gz", - .hash = "1220326148075cd017425e04356329c33c3e794d31a54bdafa46521fcfcc55b422a3", + .url = "https://github.com/ZigEmbeddedGroup/microzig/archive/d4a48f65fac24dcfe789d217a9154086b6a011e5.tar.gz", + .hash = "1220fd3ad4f6a88f111791cb80de1fc388d0a51114ab376f2bf8351cd176747fa303", }, .args = .{ .url = "https://github.com/MasterQ32/zig-args/archive/91d1e89fb89a4d01dec7c9aec95b0a324080ebcc.tar.gz", From 1dbdd0f80ea076cffeced5e9ca6e4322c2e6bc3e Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Thu, 3 Aug 2023 21:47:42 -0700 Subject: [PATCH 71/74] Fix eval branch quota for PIO comparison tests (#76) --- .github/workflows/build.yml | 2 +- src/hal/pio/assembler/comparison_tests.zig | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2203973..6801af6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: os: [ - linux-latest, + ubuntu-latest, windows-latest, macos-latest, ] diff --git a/src/hal/pio/assembler/comparison_tests.zig b/src/hal/pio/assembler/comparison_tests.zig index 5a98c93..4bad38d 100644 --- a/src/hal/pio/assembler/comparison_tests.zig +++ b/src/hal/pio/assembler/comparison_tests.zig @@ -53,7 +53,7 @@ test "pio.comparison.addition" { } test "pio.comparison.apa102" { - @setEvalBranchQuota(10000); + @setEvalBranchQuota(11000); try pio_comparison(@embedFile("comparison_tests/apa102.pio")); } @@ -153,7 +153,7 @@ test "pio.comparison.st7789_lcd" { } test "pio.comparison.uart_rx" { - @setEvalBranchQuota(10000); + @setEvalBranchQuota(11000); try pio_comparison(@embedFile("comparison_tests/uart_rx.pio")); } @@ -163,6 +163,6 @@ test "pio.comparison.uart_tx" { } test "pio.comparison.ws2812" { - @setEvalBranchQuota(10000); + @setEvalBranchQuota(11000); try pio_comparison(@embedFile("comparison_tests/ws2812.pio")); } From 6f201f7f4c4d3223eb1e30658a97c6776c82926a Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Fri, 4 Aug 2023 00:59:05 -0700 Subject: [PATCH 72/74] stabilize on 0.11.0 (#77) --- .github/workflows/build.yml | 2 +- README.adoc | 2 +- build.zig.zon | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6801af6..50ac1a4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@v2 - uses: goto-bus-stop/setup-zig@v1.3.0 with: - version: master + version: 0.11.0 - name: Build and Unit Test run: zig build test -Doptimize=ReleaseSmall diff --git a/README.adoc b/README.adoc index fc0ca7f..38c63c6 100644 --- a/README.adoc +++ b/README.adoc @@ -4,4 +4,4 @@ HAL and register definitions for the RP2040. == What version of Zig to use -Right now we are following https://ziglang.org/download/[master], but once 0.11.0 is released, we will be switching to the latest stable version of Zig. +0.11.0 diff --git a/build.zig.zon b/build.zig.zon index 28bea9e..cfb4ad4 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -3,8 +3,8 @@ .version = "0.0.0", .dependencies = .{ .microzig = .{ - .url = "https://github.com/ZigEmbeddedGroup/microzig/archive/d4a48f65fac24dcfe789d217a9154086b6a011e5.tar.gz", - .hash = "1220fd3ad4f6a88f111791cb80de1fc388d0a51114ab376f2bf8351cd176747fa303", + .url = "https://github.com/ZigEmbeddedGroup/microzig/archive/0b3be0a4cc7e6d45714cb09961efc771e364723c.tar.gz", + .hash = "1220ada6d01db7b3d0aa8642df89b1af9ee71b681438249e9a7efb2275fc4cf32152", }, .args = .{ .url = "https://github.com/MasterQ32/zig-args/archive/91d1e89fb89a4d01dec7c9aec95b0a324080ebcc.tar.gz", From 2a0c0ff2814a716a163822211c2686d84801a97a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Quei=C3=9Fner?= Date: Tue, 12 Sep 2023 23:06:26 +0200 Subject: [PATCH 73/74] Implements proper support for different stage2 bootloaders (#80) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Felix "xq" Queißner --- README.adoc | 8 + build.zig | 153 ++- src/boards.zig | 64 +- src/boards/raspberry_pi_pico.zig | 39 +- src/boards/shared/bootrom.zig | 41 + src/boards/waveshare_rp2040_eth.zig | 5 + src/boards/waveshare_rp2040_matrix.zig | 5 + src/boards/waveshare_rp2040_plus_16m.zig | 5 + src/boards/waveshare_rp2040_plus_4m.zig | 5 + src/bootroms/at25sf128a.S | 278 ++++++ src/bootroms/generic_03h.S | 98 ++ src/bootroms/is25lp080.S | 256 +++++ src/bootroms/legacy.S | 26 + src/bootroms/shared/addressmap.h | 73 ++ src/bootroms/shared/asm_helper.S | 41 + src/bootroms/shared/exit_from_boot2.S | 28 + src/bootroms/shared/m0plus.h | 1149 ++++++++++++++++++++++ src/bootroms/shared/pads_qspi.h | 454 +++++++++ src/bootroms/shared/read_flash_sreg.S | 30 + src/bootroms/shared/regs.h | 11 + src/bootroms/shared/ssi.h | 809 +++++++++++++++ src/bootroms/shared/stage2.ld | 31 + src/bootroms/shared/wait_ssi_ready.S | 26 + src/bootroms/w25q080.S | 280 ++++++ src/bootroms/w25x10cl.S | 191 ++++ 25 files changed, 4041 insertions(+), 65 deletions(-) create mode 100644 src/boards/shared/bootrom.zig create mode 100644 src/boards/waveshare_rp2040_eth.zig create mode 100644 src/boards/waveshare_rp2040_matrix.zig create mode 100644 src/boards/waveshare_rp2040_plus_16m.zig create mode 100644 src/boards/waveshare_rp2040_plus_4m.zig create mode 100644 src/bootroms/at25sf128a.S create mode 100644 src/bootroms/generic_03h.S create mode 100644 src/bootroms/is25lp080.S create mode 100644 src/bootroms/legacy.S create mode 100644 src/bootroms/shared/addressmap.h create mode 100644 src/bootroms/shared/asm_helper.S create mode 100644 src/bootroms/shared/exit_from_boot2.S create mode 100644 src/bootroms/shared/m0plus.h create mode 100644 src/bootroms/shared/pads_qspi.h create mode 100644 src/bootroms/shared/read_flash_sreg.S create mode 100644 src/bootroms/shared/regs.h create mode 100644 src/bootroms/shared/ssi.h create mode 100644 src/bootroms/shared/stage2.ld create mode 100644 src/bootroms/shared/wait_ssi_ready.S create mode 100644 src/bootroms/w25q080.S create mode 100644 src/bootroms/w25x10cl.S diff --git a/README.adoc b/README.adoc index 38c63c6..c31cb3d 100644 --- a/README.adoc +++ b/README.adoc @@ -5,3 +5,11 @@ HAL and register definitions for the RP2040. == What version of Zig to use 0.11.0 + +== Supported devices == + +- Raspberry Pi Pico +- (*experimental*) Waveshare RP2040-Plus (4M Flash) +- (*experimental*) Waveshare RP2040-Plus (16M Flash) +- (*experimental*) Waveshare RP2040-ETH Mini +- (*experimental*) Waveshare RP2040-Matrix diff --git a/build.zig b/build.zig index dacb224..1d4dd3c 100644 --- a/build.zig +++ b/build.zig @@ -1,43 +1,121 @@ const std = @import("std"); -const Builder = std.build.Builder; -const Pkg = std.build.Pkg; +const Build = std.Build; const comptimePrint = std.fmt.comptimePrint; -const LazyPath = std.build.LazyPath; const microzig = @import("microzig"); pub const chips = @import("src/chips.zig"); pub const boards = @import("src/boards.zig"); -const linkerscript_path = root() ++ "rp2040.ld"; +const build_root = root(); -pub const BuildOptions = struct { - optimize: std.builtin.OptimizeMode, +const linkerscript_path = build_root ++ "/rp2040.ld"; + +pub const BootROM = union(enum) { + artifact: *std.build.CompileStep, // provide a custom startup code + blob: std.build.LazyPath, // just include a binary blob + + // Pre-shipped ones: + at25sf128a, + generic_03h, + is25lp080, + w25q080, + w25x10cl, + + // Use the old stage2 bootloader vendored with MicroZig till 2023-09-13 + legacy, }; pub const PicoExecutableOptions = struct { name: []const u8, - source_file: LazyPath, + source_file: std.Build.LazyPath, optimize: std.builtin.OptimizeMode = .Debug, + + board: boards.Board = boards.raspberry_pi_pico, + + bootrom: ?BootROM = null, }; -pub fn addPiPicoExecutable( - builder: *Builder, +pub const addPiPicoExecutable = addExecutable; // Deprecated, use addExecutable! + +pub const Stage2Bootloader = struct { + bin: std.Build.LazyPath, + elf: ?std.Build.LazyPath, +}; + +pub fn getBootrom(b: *Build, rom: BootROM) Stage2Bootloader { + const rom_exe = switch (rom) { + .artifact => |artifact| artifact, + .blob => |blob| return Stage2Bootloader{ + .bin = blob, + .elf = null, + }, + + else => blk: { + var target = chips.rp2040.cpu.target; + target.abi = .eabi; + + const rom_path = b.pathFromRoot(b.fmt("{s}/src/bootroms/{s}.S", .{ build_root, @tagName(rom) })); + + const rom_exe = b.addExecutable(.{ + .name = b.fmt("stage2-{s}", .{@tagName(rom)}), + .optimize = .ReleaseSmall, + .target = target, + .root_source_file = null, + }); + rom_exe.linkage = .static; + // rom_exe.pie = false; + // rom_exe.force_pic = false; + rom_exe.setLinkerScript(.{ .path = build_root ++ "/src/bootroms/shared/stage2.ld" }); + rom_exe.addAssemblyFile(.{ .path = rom_path }); + + break :blk rom_exe; + }, + }; + + const rom_objcopy = b.addObjCopy(rom_exe.getEmittedBin(), .{ + .basename = b.fmt("{s}.bin", .{@tagName(rom)}), + .format = .bin, + }); + + return Stage2Bootloader{ + .bin = rom_objcopy.getOutput(), + .elf = rom_exe.getEmittedBin(), + }; +} + +pub fn addExecutable( + b: *Build, opts: PicoExecutableOptions, ) *microzig.EmbeddedExecutable { - return microzig.addEmbeddedExecutable(builder, .{ + var exe = microzig.addEmbeddedExecutable(b, .{ .name = opts.name, .source_file = opts.source_file, - .backing = .{ .board = boards.raspberry_pi_pico }, + .backing = .{ .board = opts.board.inner }, .optimize = opts.optimize, .linkerscript_source_file = .{ .path = linkerscript_path }, }); + + const i: *std.Build.CompileStep = exe.inner; + + const bootrom_file = getBootrom(b, opts.bootrom orelse opts.board.bootrom); + + // HACK: Inject the file as a dependency to MicroZig.board + i.modules.get("microzig").?.dependencies.get("board").?.dependencies.put( + "bootloader", + b.createModule(.{ + .source_file = bootrom_file.bin, + }), + ) catch @panic("oom"); + bootrom_file.bin.addStepDependencies(&i.step); + + return exe; } // this build script is mostly for testing and verification of this // package. In an attempt to modularize -- designing for a case where a // project requires multiple HALs, it accepts microzig as a param -pub fn build(b: *Builder) !void { +pub fn build(b: *Build) !void { const optimize = b.standardOptimizeOption(.{}); const args_dep = b.dependency("args", .{}); @@ -57,15 +135,40 @@ pub fn build(b: *Builder) !void { const test_step = b.step("test", "run unit tests"); test_step.dependOn(&b.addRunArtifact(pio_tests).step); - const flash_tool = b.addExecutable(.{ - .name = "rp2040-flash", - .optimize = .Debug, - .target = .{}, - .root_source_file = .{ .path = "tools/rp2040-flash.zig" }, - }); - flash_tool.addModule("args", args_mod); + { + const flash_tool = b.addExecutable(.{ + .name = "rp2040-flash", + .optimize = .Debug, + .target = .{}, + .root_source_file = .{ .path = "tools/rp2040-flash.zig" }, + }); + flash_tool.addModule("args", args_mod); - b.installArtifact(flash_tool); + b.installArtifact(flash_tool); + } + + // Install all bootroms for debugging and CI + inline for (comptime std.enums.values(std.meta.Tag(BootROM))) |rom| { + if (rom == .artifact or rom == .blob) { + continue; + } + + if (rom == .is25lp080) { + // TODO: https://github.com/ZigEmbeddedGroup/raspberrypi-rp2040/issues/79 + // is25lp080.o:(text+0x16): has non-ABS relocation R_ARM_THM_CALL against symbol 'read_flash_sreg' + continue; + } + + const files = getBootrom(b, rom); + if (files.elf) |elf| { + b.getInstallStep().dependOn( + &b.addInstallFileWithDir(elf, .{ .custom = "stage2" }, b.fmt("{s}.elf", .{@tagName(rom)})).step, + ); + } + b.getInstallStep().dependOn( + &b.addInstallFileWithDir(files.bin, .{ .custom = "stage2" }, b.fmt("{s}.bin", .{@tagName(rom)})).step, + ); + } } fn root() []const u8 { @@ -89,12 +192,12 @@ pub const Examples = struct { ws2812: *microzig.EmbeddedExecutable, random: *microzig.EmbeddedExecutable, - pub fn init(b: *Builder, optimize: std.builtin.OptimizeMode) Examples { + pub fn init(b: *Build, optimize: std.builtin.OptimizeMode) Examples { var ret: Examples = undefined; inline for (@typeInfo(Examples).Struct.fields) |field| { const path = comptime root() ++ "examples/" ++ field.name ++ ".zig"; - @field(ret, field.name) = addPiPicoExecutable(b, .{ + @field(ret, field.name) = addExecutable(b, .{ .name = field.name, .source_file = .{ .path = path }, .optimize = optimize, @@ -104,9 +207,11 @@ pub const Examples = struct { return ret; } - pub fn install(examples: *Examples, b: *Builder) void { + pub fn install(examples: *Examples, b: *Build) void { inline for (@typeInfo(Examples).Struct.fields) |field| { - b.installArtifact(@field(examples, field.name).inner); + b.getInstallStep().dependOn( + &b.addInstallFileWithDir(@field(examples, field.name).inner.getEmittedBin(), .{ .custom = "firmware" }, field.name ++ ".elf").step, + ); } } }; diff --git a/src/boards.zig b/src/boards.zig index d2af0ee..8f68040 100644 --- a/src/boards.zig +++ b/src/boards.zig @@ -1,15 +1,69 @@ const std = @import("std"); const microzig = @import("microzig"); +const rp2040 = @import("../build.zig"); const chips = @import("chips.zig"); fn root_dir() []const u8 { return std.fs.path.dirname(@src().file) orelse "."; } -const board_path = std.fmt.comptimePrint("{s}/boards/raspberry_pi_pico.zig", .{root_dir()}); +fn board_path(comptime path: []const u8) std.Build.LazyPath { + return .{ + .path = std.fmt.comptimePrint("{s}/boards/{s}", .{ root_dir(), path }), + }; +} + +pub const Board = struct { + inner: microzig.Board, + bootrom: rp2040.BootROM, +}; + +// https://www.raspberrypi.com/products/raspberry-pi-pico/ +pub const raspberry_pi_pico = Board{ + .inner = .{ + .name = "Raspberry Pi Pico", + .source = board_path("raspberry_pi_pico.zig"), + .chip = chips.rp2040, + }, + .bootrom = .w25q080, +}; + +// https://www.waveshare.com/rp2040-plus.htm +pub const waveshare_rp2040_plus_4m = Board{ + .inner = .{ + .name = "Waveshare RP2040-Plus (4M Flash)", + .source = board_path("waveshare_rp2040_plus_4m.zig"), + .chip = chips.rp2040, + }, + .bootrom = .w25q080, +}; + +// https://www.waveshare.com/rp2040-plus.htm +pub const waveshare_rp2040_plus_16m = Board{ + .inner = .{ + .name = "Waveshare RP2040-Plus (16M Flash)", + .source = board_path("waveshare_rp2040_plus_16m.zig"), + .chip = chips.rp2040, + }, + .bootrom = .w25q080, +}; + +// https://www.waveshare.com/rp2040-eth.htm +pub const waveshare_rp2040_eth = Board{ + .inner = .{ + .name = "Waveshare RP2040-ETH Mini", + .source = board_path("waveshare_rp2040_eth.zig"), + .chip = chips.rp2040, + }, + .bootrom = .w25q080, +}; -pub const raspberry_pi_pico = microzig.Board{ - .name = "Raspberry Pi Pico", - .source = .{ .path = board_path }, - .chip = chips.rp2040, +// https://www.waveshare.com/rp2040-matrix.htm +pub const waveshare_rp2040_matrix = Board{ + .inner = .{ + .name = "Waveshare RP2040-Matrix", + .source = board_path("waveshare_rp2040_matrix.zig"), + .chip = chips.rp2040, + }, + .bootrom = .w25q080, }; diff --git a/src/boards/raspberry_pi_pico.zig b/src/boards/raspberry_pi_pico.zig index ca1a901..79d848c 100644 --- a/src/boards/raspberry_pi_pico.zig +++ b/src/boards/raspberry_pi_pico.zig @@ -1,38 +1,5 @@ pub const xosc_freq = 12_000_000; -// TODO: improve interface so that user can use a custom implementation and -// automatically checksum it. -pub export const _BOOT2: [256]u8 linksection(".boot2") = [_]u8{ - 0x00, 0xb5, 0x32, 0x4b, 0x21, 0x20, 0x58, 0x60, - 0x98, 0x68, 0x02, 0x21, 0x88, 0x43, 0x98, 0x60, - 0xd8, 0x60, 0x18, 0x61, 0x58, 0x61, 0x2e, 0x4b, - 0x00, 0x21, 0x99, 0x60, 0x02, 0x21, 0x59, 0x61, - 0x01, 0x21, 0xf0, 0x22, 0x99, 0x50, 0x2b, 0x49, - 0x19, 0x60, 0x01, 0x21, 0x99, 0x60, 0x35, 0x20, - 0x00, 0xf0, 0x44, 0xf8, 0x02, 0x22, 0x90, 0x42, - 0x14, 0xd0, 0x06, 0x21, 0x19, 0x66, 0x00, 0xf0, - 0x34, 0xf8, 0x19, 0x6e, 0x01, 0x21, 0x19, 0x66, - 0x00, 0x20, 0x18, 0x66, 0x1a, 0x66, 0x00, 0xf0, - 0x2c, 0xf8, 0x19, 0x6e, 0x19, 0x6e, 0x19, 0x6e, - 0x05, 0x20, 0x00, 0xf0, 0x2f, 0xf8, 0x01, 0x21, - 0x08, 0x42, 0xf9, 0xd1, 0x00, 0x21, 0x99, 0x60, - 0x1b, 0x49, 0x19, 0x60, 0x00, 0x21, 0x59, 0x60, - 0x1a, 0x49, 0x1b, 0x48, 0x01, 0x60, 0x01, 0x21, - 0x99, 0x60, 0xeb, 0x21, 0x19, 0x66, 0xa0, 0x21, - 0x19, 0x66, 0x00, 0xf0, 0x12, 0xf8, 0x00, 0x21, - 0x99, 0x60, 0x16, 0x49, 0x14, 0x48, 0x01, 0x60, - 0x01, 0x21, 0x99, 0x60, 0x01, 0xbc, 0x00, 0x28, - 0x00, 0xd0, 0x00, 0x47, 0x12, 0x48, 0x13, 0x49, - 0x08, 0x60, 0x03, 0xc8, 0x80, 0xf3, 0x08, 0x88, - 0x08, 0x47, 0x03, 0xb5, 0x99, 0x6a, 0x04, 0x20, - 0x01, 0x42, 0xfb, 0xd0, 0x01, 0x20, 0x01, 0x42, - 0xf8, 0xd1, 0x03, 0xbd, 0x02, 0xb5, 0x18, 0x66, - 0x18, 0x66, 0xff, 0xf7, 0xf2, 0xff, 0x18, 0x6e, - 0x18, 0x6e, 0x02, 0xbd, 0x00, 0x00, 0x02, 0x40, - 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x03, 0x5f, 0x00, 0x21, 0x22, 0x00, 0x00, - 0xf4, 0x00, 0x00, 0x18, 0x22, 0x20, 0x00, 0xa0, - 0x00, 0x01, 0x00, 0x10, 0x08, 0xed, 0x00, 0xe0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x74, 0xb2, 0x4e, 0x7a, -}; +comptime { + _ = @import("shared/bootrom.zig"); +} diff --git a/src/boards/shared/bootrom.zig b/src/boards/shared/bootrom.zig new file mode 100644 index 0000000..e6e32af --- /dev/null +++ b/src/boards/shared/bootrom.zig @@ -0,0 +1,41 @@ +const std = @import("std"); + +comptime { + _ = stage2_bootloader; +} + +export const stage2_bootloader: [256]u8 linksection(".boot2") = prepareBootSector( + @embedFile("bootloader"), +); + +/// Create a new +fn prepareBootSector(comptime stage2_rom: []const u8) [256]u8 { + @setEvalBranchQuota(10_000); + + var bootrom: [256]u8 = .{0xFF} ** 256; + @memcpy(bootrom[0..stage2_rom.len], stage2_rom); + + // 2.8.1.3.1. Checksum + // The last four bytes of the image loaded from flash (which we hope is a valid flash second stage) are a CRC32 checksum + // of the first 252 bytes. The parameters of the checksum are: + // • Polynomial: 0x04c11db7 + // • Input reflection: no + // • Output reflection: no + // • Initial value: 0xffffffff + // • Final XOR: 0x00000000 + // • Checksum value appears as little-endian integer at end of image + // The Bootrom makes 128 attempts of approximately 4ms each for a total of approximately 0.5 seconds before giving up + // and dropping into USB code to load and checksum the second stage with varying SPI parameters. If it sees a checksum + // pass it will immediately jump into the 252-byte payload which contains the flash second stage. + const Hash = std.hash.crc.Crc(u32, .{ + .polynomial = 0x04c11db7, + .initial = 0xffffffff, + .reflect_input = false, + .reflect_output = false, + .xor_output = 0x00000000, + }); + + std.mem.writeIntLittle(u32, bootrom[252..256], Hash.hash(bootrom[0..252])); + + return bootrom; +} diff --git a/src/boards/waveshare_rp2040_eth.zig b/src/boards/waveshare_rp2040_eth.zig new file mode 100644 index 0000000..79d848c --- /dev/null +++ b/src/boards/waveshare_rp2040_eth.zig @@ -0,0 +1,5 @@ +pub const xosc_freq = 12_000_000; + +comptime { + _ = @import("shared/bootrom.zig"); +} diff --git a/src/boards/waveshare_rp2040_matrix.zig b/src/boards/waveshare_rp2040_matrix.zig new file mode 100644 index 0000000..79d848c --- /dev/null +++ b/src/boards/waveshare_rp2040_matrix.zig @@ -0,0 +1,5 @@ +pub const xosc_freq = 12_000_000; + +comptime { + _ = @import("shared/bootrom.zig"); +} diff --git a/src/boards/waveshare_rp2040_plus_16m.zig b/src/boards/waveshare_rp2040_plus_16m.zig new file mode 100644 index 0000000..79d848c --- /dev/null +++ b/src/boards/waveshare_rp2040_plus_16m.zig @@ -0,0 +1,5 @@ +pub const xosc_freq = 12_000_000; + +comptime { + _ = @import("shared/bootrom.zig"); +} diff --git a/src/boards/waveshare_rp2040_plus_4m.zig b/src/boards/waveshare_rp2040_plus_4m.zig new file mode 100644 index 0000000..79d848c --- /dev/null +++ b/src/boards/waveshare_rp2040_plus_4m.zig @@ -0,0 +1,5 @@ +pub const xosc_freq = 12_000_000; + +comptime { + _ = @import("shared/bootrom.zig"); +} diff --git a/src/bootroms/at25sf128a.S b/src/bootroms/at25sf128a.S new file mode 100644 index 0000000..f8ecdc9 --- /dev/null +++ b/src/bootroms/at25sf128a.S @@ -0,0 +1,278 @@ +// ---------------------------------------------------------------------------- +// Second stage boot code +// Copyright (c) 2019-2021 Raspberry Pi (Trading) Ltd. +// SPDX-License-Identifier: BSD-3-Clause +// +// Device: Adesto AT25SF128A +// Based on W25Q080 code: main difference is the QE bit is being set +// via command 0x31 +// +// Description: Configures AT25SF128A to run in Quad I/O continuous read XIP mode +// +// Details: * Check status register 2 to determine if QSPI mode is enabled, +// and perform an SR2 programming cycle if necessary. +// * Use SSI to perform a dummy 0xEB read command, with the mode +// continuation bits set, so that the flash will not require +// 0xEB instruction prefix on subsequent reads. +// * Configure SSI to write address, mode bits, but no instruction. +// SSI + flash are now jointly in a state where continuous reads +// can take place. +// * Jump to exit pointer passed in via lr. Bootrom passes null, +// in which case this code uses a default 256 byte flash offset +// +// Building: * This code must be position-independent, and use stack only +// * The code will be padded to a size of 256 bytes, including a +// 4-byte checksum. Therefore code size cannot exceed 252 bytes. +// ---------------------------------------------------------------------------- + +#include "shared/asm_helper.S" +#include "shared/regs.h" + +// ---------------------------------------------------------------------------- +// Config section +// ---------------------------------------------------------------------------- +// It should be possible to support most flash devices by modifying this section + +// The serial flash interface will run at clk_sys/PICO_FLASH_SPI_CLKDIV. +// This must be a positive, even integer. +// The bootrom is very conservative with SPI frequency, but here we should be +// as aggressive as possible. + +#ifndef PICO_FLASH_SPI_CLKDIV +#define PICO_FLASH_SPI_CLKDIV 4 +#endif +#if PICO_FLASH_SPI_CLKDIV & 1 +#error PICO_FLASH_SPI_CLKDIV must be even +#endif + +// Define interface width: single/dual/quad IO +#define FRAME_FORMAT SSI_CTRLR0_SPI_FRF_VALUE_QUAD + +// For W25Q080 this is the "Read data fast quad IO" instruction: +#define CMD_READ 0xeb + +// "Mode bits" are 8 special bits sent immediately after +// the address bits in a "Read Data Fast Quad I/O" command sequence. +// On W25Q080, the four LSBs are don't care, and if MSBs == 0xa, the +// next read does not require the 0xeb instruction prefix. +#define MODE_CONTINUOUS_READ 0x20 + +// The number of address + mode bits, divided by 4 (always 4, not function of +// interface width). +#define ADDR_L 8 + +// How many clocks of Hi-Z following the mode bits. For W25Q080, 4 dummy cycles +// are required. +#define WAIT_CYCLES 4 + +// If defined, we will read status reg, compare to SREG_DATA, and overwrite +// with our value if the SR doesn't match. +// We do a two-byte write to SR1 (01h cmd) rather than a one-byte write to +// SR2 (31h cmd) as the latter command isn't supported by WX25Q080. +// This isn't great because it will remove block protections. +// A better solution is to use a volatile SR write if your device supports it. +#define PROGRAM_STATUS_REG + +#define CMD_WRITE_ENABLE 0x06 +#define CMD_READ_STATUS 0x05 +#define CMD_READ_STATUS2 0x35 +#define CMD_WRITE_STATUS 0x01 +#define CMD_WRITE_STATUS2 0x31 +#define SREG_DATA 0x02 // Enable quad-SPI mode + +// ---------------------------------------------------------------------------- +// Start of 2nd Stage Boot Code +// ---------------------------------------------------------------------------- + +pico_default_asm_setup + +.section .text + +// The exit point is passed in lr. If entered from bootrom, this will be the +// flash address immediately following this second stage (0x10000100). +// Otherwise it will be a return address -- second stage being called as a +// function by user code, after copying out of XIP region. r3 holds SSI base, +// r0...2 used as temporaries. Other GPRs not used. +regular_func _stage2_boot + push {lr} + + // Set pad configuration: + // - SCLK 8mA drive, no slew limiting + // - SDx disable input Schmitt to reduce delay + + ldr r3, =PADS_QSPI_BASE + movs r0, #(2 << PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_LSB | PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST_BITS) + str r0, [r3, #PADS_QSPI_GPIO_QSPI_SCLK_OFFSET] + ldr r0, [r3, #PADS_QSPI_GPIO_QSPI_SD0_OFFSET] + movs r1, #PADS_QSPI_GPIO_QSPI_SD0_SCHMITT_BITS + bics r0, r1 + str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD0_OFFSET] + str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD1_OFFSET] + str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD2_OFFSET] + str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD3_OFFSET] + + ldr r3, =XIP_SSI_BASE + + // Disable SSI to allow further config + movs r1, #0 + str r1, [r3, #SSI_SSIENR_OFFSET] + + // Set baud rate + movs r1, #PICO_FLASH_SPI_CLKDIV + str r1, [r3, #SSI_BAUDR_OFFSET] + + // Set 1-cycle sample delay. If PICO_FLASH_SPI_CLKDIV == 2 then this means, + // if the flash launches data on SCLK posedge, we capture it at the time that + // the next SCLK posedge is launched. This is shortly before that posedge + // arrives at the flash, so data hold time should be ok. For + // PICO_FLASH_SPI_CLKDIV > 2 this pretty much has no effect. + + movs r1, #1 + movs r2, #SSI_RX_SAMPLE_DLY_OFFSET // == 0xf0 so need 8 bits of offset significance + str r1, [r3, r2] + + +// On QSPI parts we usually need a 01h SR-write command to enable QSPI mode +// (i.e. turn WPn and HOLDn into IO2/IO3) +#ifdef PROGRAM_STATUS_REG +program_sregs: +#define CTRL0_SPI_TXRX \ + (7 << SSI_CTRLR0_DFS_32_LSB) | /* 8 bits per data frame */ \ + (SSI_CTRLR0_TMOD_VALUE_TX_AND_RX << SSI_CTRLR0_TMOD_LSB) + + ldr r1, =(CTRL0_SPI_TXRX) + str r1, [r3, #SSI_CTRLR0_OFFSET] + + // Enable SSI and select slave 0 + movs r1, #1 + str r1, [r3, #SSI_SSIENR_OFFSET] + + // Check whether SR needs updating + movs r0, #CMD_READ_STATUS2 + bl read_flash_sreg + movs r2, #SREG_DATA + cmp r0, r2 + beq skip_sreg_programming + + // Send write enable command + movs r1, #CMD_WRITE_ENABLE + str r1, [r3, #SSI_DR0_OFFSET] + + // Poll for completion and discard RX + bl wait_ssi_ready + ldr r1, [r3, #SSI_DR0_OFFSET] + + // Send status write command followed by data bytes + movs r1, #CMD_WRITE_STATUS2 + str r1, [r3, #SSI_DR0_OFFSET] + str r2, [r3, #SSI_DR0_OFFSET] + + bl wait_ssi_ready + ldr r1, [r3, #SSI_DR0_OFFSET] + ldr r1, [r3, #SSI_DR0_OFFSET] + ldr r1, [r3, #SSI_DR0_OFFSET] + + // Poll status register for write completion +1: + movs r0, #CMD_READ_STATUS + bl read_flash_sreg + movs r1, #1 + tst r0, r1 + bne 1b + +skip_sreg_programming: + + // Disable SSI again so that it can be reconfigured + movs r1, #0 + str r1, [r3, #SSI_SSIENR_OFFSET] +#endif + +// Currently the flash expects an 8 bit serial command prefix on every +// transfer, which is a waste of cycles. Perform a dummy Fast Read Quad I/O +// command, with mode bits set such that the flash will not expect a serial +// command prefix on *subsequent* transfers. We don't care about the results +// of the read, the important part is the mode bits. + +dummy_read: +#define CTRLR0_ENTER_XIP \ + (FRAME_FORMAT /* Quad I/O mode */ \ + << SSI_CTRLR0_SPI_FRF_LSB) | \ + (31 << SSI_CTRLR0_DFS_32_LSB) | /* 32 data bits */ \ + (SSI_CTRLR0_TMOD_VALUE_EEPROM_READ /* Send INST/ADDR, Receive Data */ \ + << SSI_CTRLR0_TMOD_LSB) + + ldr r1, =(CTRLR0_ENTER_XIP) + str r1, [r3, #SSI_CTRLR0_OFFSET] + + movs r1, #0x0 // NDF=0 (single 32b read) + str r1, [r3, #SSI_CTRLR1_OFFSET] + +#define SPI_CTRLR0_ENTER_XIP \ + (ADDR_L << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Address + mode bits */ \ + (WAIT_CYCLES << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z dummy clocks following address + mode */ \ + (SSI_SPI_CTRLR0_INST_L_VALUE_8B \ + << SSI_SPI_CTRLR0_INST_L_LSB) | /* 8-bit instruction */ \ + (SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C2A /* Send Command in serial mode then address in Quad I/O mode */ \ + << SSI_SPI_CTRLR0_TRANS_TYPE_LSB) + + ldr r1, =(SPI_CTRLR0_ENTER_XIP) + ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) // SPI_CTRL0 Register + str r1, [r0] + + movs r1, #1 // Re-enable SSI + str r1, [r3, #SSI_SSIENR_OFFSET] + + movs r1, #CMD_READ + str r1, [r3, #SSI_DR0_OFFSET] // Push SPI command into TX FIFO + movs r1, #MODE_CONTINUOUS_READ // 32-bit: 24 address bits (we don't care, so 0) and M[7:4]=1010 + str r1, [r3, #SSI_DR0_OFFSET] // Push Address into TX FIFO - this will trigger the transaction + + // Poll for completion + bl wait_ssi_ready + +// The flash is in a state where we can blast addresses in parallel, and get +// parallel data back. Now configure the SSI to translate XIP bus accesses +// into QSPI transfers of this form. + + movs r1, #0 + str r1, [r3, #SSI_SSIENR_OFFSET] // Disable SSI (and clear FIFO) to allow further config + +// Note that the INST_L field is used to select what XIP data gets pushed into +// the TX FIFO: +// INST_L_0_BITS {ADDR[23:0],XIP_CMD[7:0]} Load "mode bits" into XIP_CMD +// Anything else {XIP_CMD[7:0],ADDR[23:0]} Load SPI command into XIP_CMD +configure_ssi: +#define SPI_CTRLR0_XIP \ + (MODE_CONTINUOUS_READ /* Mode bits to keep flash in continuous read mode */ \ + << SSI_SPI_CTRLR0_XIP_CMD_LSB) | \ + (ADDR_L << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Total number of address + mode bits */ \ + (WAIT_CYCLES << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z dummy clocks following address + mode */ \ + (SSI_SPI_CTRLR0_INST_L_VALUE_NONE /* Do not send a command, instead send XIP_CMD as mode bits after address */ \ + << SSI_SPI_CTRLR0_INST_L_LSB) | \ + (SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_2C2A /* Send Address in Quad I/O mode (and Command but that is zero bits long) */ \ + << SSI_SPI_CTRLR0_TRANS_TYPE_LSB) + + ldr r1, =(SPI_CTRLR0_XIP) + ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) + str r1, [r0] + + movs r1, #1 + str r1, [r3, #SSI_SSIENR_OFFSET] // Re-enable SSI + +// Bus accesses to the XIP window will now be transparently serviced by the +// external flash on cache miss. We are ready to run code from flash. + +// Pull in standard exit routine +#include "shared/exit_from_boot2.S" + +// Common functions +#include "shared/wait_ssi_ready.S" +#ifdef PROGRAM_STATUS_REG +#include "shared/read_flash_sreg.S" +#endif + +.global literals +literals: +.ltorg + +.end diff --git a/src/bootroms/generic_03h.S b/src/bootroms/generic_03h.S new file mode 100644 index 0000000..1599c7b --- /dev/null +++ b/src/bootroms/generic_03h.S @@ -0,0 +1,98 @@ +// ---------------------------------------------------------------------------- +// Second stage boot code +// Copyright (c) 2019-2021 Raspberry Pi (Trading) Ltd. +// SPDX-License-Identifier: BSD-3-Clause +// +// Device: Anything which responds to 03h serial read command +// +// Details: * Configure SSI to translate each APB read into a 03h command +// * 8 command clocks, 24 address clocks and 32 data clocks +// * This enables you to boot from almost anything: you can pretty +// much solder a potato to your PCB, or a piece of cheese +// * The tradeoff is performance around 3x worse than QSPI XIP +// +// Building: * This code must be position-independent, and use stack only +// * The code will be padded to a size of 256 bytes, including a +// 4-byte checksum. Therefore code size cannot exceed 252 bytes. +// ---------------------------------------------------------------------------- + +#include "shared/asm_helper.S" +#include "shared/regs.h" + +pico_default_asm_setup + +// ---------------------------------------------------------------------------- +// Config section +// ---------------------------------------------------------------------------- +// It should be possible to support most flash devices by modifying this section + +// The serial flash interface will run at clk_sys/PICO_FLASH_SPI_CLKDIV. +// This must be a positive, even integer. +// The bootrom is very conservative with SPI frequency, but here we should be +// as aggressive as possible. +#ifndef PICO_FLASH_SPI_CLKDIV +#define PICO_FLASH_SPI_CLKDIV 4 +#endif + +#define CMD_READ 0x03 + +// Value is number of address bits divided by 4 +#define ADDR_L 6 + +#define CTRLR0_XIP \ + (SSI_CTRLR0_SPI_FRF_VALUE_STD << SSI_CTRLR0_SPI_FRF_LSB) | /* Standard 1-bit SPI serial frames */ \ + (31 << SSI_CTRLR0_DFS_32_LSB) | /* 32 clocks per data frame */ \ + (SSI_CTRLR0_TMOD_VALUE_EEPROM_READ << SSI_CTRLR0_TMOD_LSB) /* Send instr + addr, receive data */ + +#define SPI_CTRLR0_XIP \ + (CMD_READ << SSI_SPI_CTRLR0_XIP_CMD_LSB) | /* Value of instruction prefix */ \ + (ADDR_L << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Total number of address + mode bits */ \ + (2 << SSI_SPI_CTRLR0_INST_L_LSB) | /* 8 bit command prefix (field value is bits divided by 4) */ \ + (SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C1A << SSI_SPI_CTRLR0_TRANS_TYPE_LSB) /* command and address both in serial format */ + +// ---------------------------------------------------------------------------- +// Start of 2nd Stage Boot Code +// ---------------------------------------------------------------------------- + +.section .text + +regular_func _stage2_boot + push {lr} + + ldr r3, =XIP_SSI_BASE // Use as base address where possible + + // Disable SSI to allow further config + movs r1, #0 + str r1, [r3, #SSI_SSIENR_OFFSET] + + // Set baud rate + movs r1, #PICO_FLASH_SPI_CLKDIV + str r1, [r3, #SSI_BAUDR_OFFSET] + + ldr r1, =(CTRLR0_XIP) + str r1, [r3, #SSI_CTRLR0_OFFSET] + + ldr r1, =(SPI_CTRLR0_XIP) + ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) + str r1, [r0] + + // NDF=0 (single 32b read) + movs r1, #0x0 + str r1, [r3, #SSI_CTRLR1_OFFSET] + + // Re-enable SSI + movs r1, #1 + str r1, [r3, #SSI_SSIENR_OFFSET] + +// We are now in XIP mode. Any bus accesses to the XIP address window will be +// translated by the SSI into 03h read commands to the external flash (if cache is missed), +// and the data will be returned to the bus. + +// Pull in standard exit routine +#include "shared/exit_from_boot2.S" + +.global literals +literals: +.ltorg + +.end diff --git a/src/bootroms/is25lp080.S b/src/bootroms/is25lp080.S new file mode 100644 index 0000000..46f8c85 --- /dev/null +++ b/src/bootroms/is25lp080.S @@ -0,0 +1,256 @@ +// ---------------------------------------------------------------------------- +// Copyright (c) 2019-2021 Raspberry Pi (Trading) Ltd. +// SPDX-License-Identifier: BSD-3-Clause +// +// Device: ISSI IS25LP080D +// Based on W25Q080 code: main difference is the QE bit being in +// SR1 instead of SR2. +// +// Description: Configures IS25LP080D to run in Quad I/O continuous read XIP mode +// +// Details: * Check status register to determine if QSPI mode is enabled, +// and perform an SR programming cycle if necessary. +// * Use SSI to perform a dummy 0xEB read command, with the mode +// continuation bits set, so that the flash will not require +// 0xEB instruction prefix on subsequent reads. +// * Configure SSI to write address, mode bits, but no instruction. +// SSI + flash are now jointly in a state where continuous reads +// can take place. +// * Set VTOR = 0x10000100 (user vector table immediately after +// this boot2 image). +// * Read stack pointer (MSP) and reset vector from the flash +// vector table; set SP and jump, as though the processor had +// booted directly from flash. +// +// Building: * This code must be linked to run at 0x20027f00 +// * The code will be padded to a size of 256 bytes, including a +// 4-byte checksum. Therefore code size cannot exceed 252 bytes. +// ---------------------------------------------------------------------------- + +#include "shared/asm_helper.S" +#include "shared/regs.h" + +// ---------------------------------------------------------------------------- +// Config section +// ---------------------------------------------------------------------------- +// It should be possible to support most flash devices by modifying this section + +// The serial flash interface will run at clk_sys/PICO_FLASH_SPI_CLKDIV. +// This must be a positive, even integer. +// The bootrom is very conservative with SPI frequency, but here we should be +// as aggressive as possible. +#ifndef PICO_FLASH_SPI_CLKDIV +#define PICO_FLASH_SPI_CLKDIV 4 +#endif + + +// Define interface width: single/dual/quad IO +#define FRAME_FORMAT SSI_CTRLR0_SPI_FRF_VALUE_QUAD + +// For W25Q080 this is the "Read data fast quad IO" instruction: +#define CMD_READ 0xeb + +// "Mode bits" are 8 special bits sent immediately after +// the address bits in a "Read Data Fast Quad I/O" command sequence. +// On W25Q080, the four LSBs are don't care, and if MSBs == 0xa, the +// next read does not require the 0xeb instruction prefix. +#define MODE_CONTINUOUS_READ 0xa0 + +// The number of address + mode bits, divided by 4 (always 4, not function of +// interface width). +#define ADDR_L 8 + +// How many clocks of Hi-Z following the mode bits. For W25Q080, 4 dummy cycles +// are required. +#define WAIT_CYCLES 4 + +// If defined, we will read status reg, compare to SREG_DATA, and overwrite +// with our value if the SR doesn't match. +// This isn't great because it will remove block protections. +// A better solution is to use a volatile SR write if your device supports it. +#define PROGRAM_STATUS_REG + +#define CMD_WRITE_ENABLE 0x06 +#define CMD_READ_STATUS 0x05 +#define CMD_WRITE_STATUS 0x01 +#define SREG_DATA 0x40 // Enable quad-SPI mode + +// ---------------------------------------------------------------------------- +// Start of 2nd Stage Boot Code +// ---------------------------------------------------------------------------- + +pico_default_asm_setup + +.section text +regular_func _stage2_boot + push {lr} + + ldr r3, =XIP_SSI_BASE // Use as base address where possible + + // Disable SSI to allow further config + movs r1, #0 + str r1, [r3, #SSI_SSIENR_OFFSET] + + // Set baud rate + movs r1, #PICO_FLASH_SPI_CLKDIV + str r1, [r3, #SSI_BAUDR_OFFSET] + +// On QSPI parts we usually need a 01h SR-write command to enable QSPI mode +// (i.e. turn WPn and HOLDn into IO2/IO3) +#ifdef PROGRAM_STATUS_REG +program_sregs: +#define CTRL0_SPI_TXRX \ + (7 << SSI_CTRLR0_DFS_32_LSB) | /* 8 bits per data frame */ \ + (SSI_CTRLR0_TMOD_VALUE_TX_AND_RX << SSI_CTRLR0_TMOD_LSB) + + ldr r1, =(CTRL0_SPI_TXRX) + str r1, [r3, #SSI_CTRLR0_OFFSET] + + // Enable SSI and select slave 0 + movs r1, #1 + str r1, [r3, #SSI_SSIENR_OFFSET] + + // Check whether SR needs updating + ldr r0, =CMD_READ_STATUS + bl read_flash_sreg + ldr r2, =SREG_DATA + cmp r0, r2 + beq skip_sreg_programming + + // Send write enable command + movs r1, #CMD_WRITE_ENABLE + str r1, [r3, #SSI_DR0_OFFSET] + + // Poll for completion and discard RX + bl wait_ssi_ready + ldr r1, [r3, #SSI_DR0_OFFSET] + + // Send status write command followed by data bytes + movs r1, #CMD_WRITE_STATUS + str r1, [r3, #SSI_DR0_OFFSET] + movs r0, #0 + str r2, [r3, #SSI_DR0_OFFSET] + + bl wait_ssi_ready + ldr r1, [r3, #SSI_DR0_OFFSET] + ldr r1, [r3, #SSI_DR0_OFFSET] + + // Poll status register for write completion +1: + ldr r0, =CMD_READ_STATUS + bl read_flash_sreg + movs r1, #1 + tst r0, r1 + bne 1b + +skip_sreg_programming: + + // Send a 0xA3 high-performance-mode instruction +// ldr r1, =0xa3 +// str r1, [r3, #SSI_DR0_OFFSET] +// bl wait_ssi_ready + + // Disable SSI again so that it can be reconfigured + movs r1, #0 + str r1, [r3, #SSI_SSIENR_OFFSET] +#endif + + +// First we need to send the initial command to get us in to Fast Read Quad I/O +// mode. As this transaction requires a command, we can't send it in XIP mode. +// To enter Continuous Read mode as well we need to append 4'b0010 to the address +// bits and then add a further 4 don't care bits. We will construct this by +// specifying a 28-bit address, with the least significant bits being 4'b0010. +// This is just a dummy transaction so we'll perform a read from address zero +// and then discard what comes back. All we really care about is that at the +// end of the transaction, the flash device is in Continuous Read mode +// and from then on will only expect to receive addresses. +dummy_read: +#define CTRLR0_ENTER_XIP \ + (FRAME_FORMAT /* Quad I/O mode */ \ + << SSI_CTRLR0_SPI_FRF_LSB) | \ + (31 << SSI_CTRLR0_DFS_32_LSB) | /* 32 data bits */ \ + (SSI_CTRLR0_TMOD_VALUE_EEPROM_READ /* Send INST/ADDR, Receive Data */ \ + << SSI_CTRLR0_TMOD_LSB) + + ldr r1, =(CTRLR0_ENTER_XIP) + str r1, [r3, #SSI_CTRLR0_OFFSET] + + movs r1, #0x0 // NDF=0 (single 32b read) + str r1, [r3, #SSI_CTRLR1_OFFSET] + +#define SPI_CTRLR0_ENTER_XIP \ + (ADDR_L << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Address + mode bits */ \ + (WAIT_CYCLES << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z dummy clocks following address + mode */ \ + (SSI_SPI_CTRLR0_INST_L_VALUE_8B \ + << SSI_SPI_CTRLR0_INST_L_LSB) | /* 8-bit instruction */ \ + (SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C2A /* Send Command in serial mode then address in Quad I/O mode */ \ + << SSI_SPI_CTRLR0_TRANS_TYPE_LSB) + + ldr r1, =(SPI_CTRLR0_ENTER_XIP) + ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) // SPI_CTRL0 Register + str r1, [r0] + + movs r1, #1 // Re-enable SSI + str r1, [r3, #SSI_SSIENR_OFFSET] + + movs r1, #CMD_READ + str r1, [r3, #SSI_DR0_OFFSET] // Push SPI command into TX FIFO + movs r1, #MODE_CONTINUOUS_READ // 32-bit: 24 address bits (we don't care, so 0) and M[7:4]=1010 + str r1, [r3, #SSI_DR0_OFFSET] // Push Address into TX FIFO - this will trigger the transaction + + // Poll for completion + bl wait_ssi_ready + +// At this point CN# will be deasserted and the SPI clock will not be running. +// The Winbond WX25X10CL device will be in continuous read, dual I/O mode and +// only expecting address bits after the next CN# assertion. So long as we +// send 4'b0010 (and 4 more dummy HiZ bits) after every subsequent 24b address +// then the Winbond device will remain in continuous read mode. This is the +// ideal mode for Execute-In-Place. +// (If we want to exit continuous read mode then we will need to switch back +// to APM mode and generate a 28-bit address phase with the extra nibble set +// to 4'b0000). + + movs r1, #0 + str r1, [r3, #SSI_SSIENR_OFFSET] // Disable SSI (and clear FIFO) to allow further config + +// Note that the INST_L field is used to select what XIP data gets pushed into +// the TX FIFO: +// INST_L_0_BITS {ADDR[23:0],XIP_CMD[7:0]} Load "mode bits" into XIP_CMD +// Anything else {XIP_CMD[7:0],ADDR[23:0]} Load SPI command into XIP_CMD +configure_ssi: +#define SPI_CTRLR0_XIP \ + (MODE_CONTINUOUS_READ /* Mode bits to keep flash in continuous read mode */ \ + << SSI_SPI_CTRLR0_XIP_CMD_LSB) | \ + (ADDR_L << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Total number of address + mode bits */ \ + (WAIT_CYCLES << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z dummy clocks following address + mode */ \ + (SSI_SPI_CTRLR0_INST_L_VALUE_NONE /* Do not send a command, instead send XIP_CMD as mode bits after address */ \ + << SSI_SPI_CTRLR0_INST_L_LSB) | \ + (SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_2C2A /* Send Address in Quad I/O mode (and Command but that is zero bits long) */ \ + << SSI_SPI_CTRLR0_TRANS_TYPE_LSB) + + ldr r1, =(SPI_CTRLR0_XIP) + ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) + str r1, [r0] + + movs r1, #1 + str r1, [r3, #SSI_SSIENR_OFFSET] // Re-enable SSI + +// We are now in XIP mode, with all transactions using Dual I/O and only +// needing to send 24-bit addresses (plus mode bits) for each read transaction. + +// Pull in standard exit routine +#include "shared/exit_from_boot2.S" + +// Common functions +#include "shared/wait_ssi_ready.S" +#ifdef PROGRAM_STATUS_REG +#include "shared/read_flash_sreg.S" +#endif + +.global literals +literals: +.ltorg + +.end diff --git a/src/bootroms/legacy.S b/src/bootroms/legacy.S new file mode 100644 index 0000000..b2870c5 --- /dev/null +++ b/src/bootroms/legacy.S @@ -0,0 +1,26 @@ + +// This is the legacy blob we used to ship in +// src/boards/raspberry_pi_pico.zig +// Now it's generic over all boards we have. + +.text +.global _stage2_boot +_stage2_boot: +.byte 0x00, 0xb5, 0x32, 0x4b, 0x21, 0x20, 0x58, 0x60, 0x98, 0x68, 0x02, 0x21, 0x88, 0x43, 0x98, 0x60 +.byte 0xd8, 0x60, 0x18, 0x61, 0x58, 0x61, 0x2e, 0x4b, 0x00, 0x21, 0x99, 0x60, 0x02, 0x21, 0x59, 0x61 +.byte 0x01, 0x21, 0xf0, 0x22, 0x99, 0x50, 0x2b, 0x49, 0x19, 0x60, 0x01, 0x21, 0x99, 0x60, 0x35, 0x20 +.byte 0x00, 0xf0, 0x44, 0xf8, 0x02, 0x22, 0x90, 0x42, 0x14, 0xd0, 0x06, 0x21, 0x19, 0x66, 0x00, 0xf0 +.byte 0x34, 0xf8, 0x19, 0x6e, 0x01, 0x21, 0x19, 0x66, 0x00, 0x20, 0x18, 0x66, 0x1a, 0x66, 0x00, 0xf0 +.byte 0x2c, 0xf8, 0x19, 0x6e, 0x19, 0x6e, 0x19, 0x6e, 0x05, 0x20, 0x00, 0xf0, 0x2f, 0xf8, 0x01, 0x21 +.byte 0x08, 0x42, 0xf9, 0xd1, 0x00, 0x21, 0x99, 0x60, 0x1b, 0x49, 0x19, 0x60, 0x00, 0x21, 0x59, 0x60 +.byte 0x1a, 0x49, 0x1b, 0x48, 0x01, 0x60, 0x01, 0x21, 0x99, 0x60, 0xeb, 0x21, 0x19, 0x66, 0xa0, 0x21 +.byte 0x19, 0x66, 0x00, 0xf0, 0x12, 0xf8, 0x00, 0x21, 0x99, 0x60, 0x16, 0x49, 0x14, 0x48, 0x01, 0x60 +.byte 0x01, 0x21, 0x99, 0x60, 0x01, 0xbc, 0x00, 0x28, 0x00, 0xd0, 0x00, 0x47, 0x12, 0x48, 0x13, 0x49 +.byte 0x08, 0x60, 0x03, 0xc8, 0x80, 0xf3, 0x08, 0x88, 0x08, 0x47, 0x03, 0xb5, 0x99, 0x6a, 0x04, 0x20 +.byte 0x01, 0x42, 0xfb, 0xd0, 0x01, 0x20, 0x01, 0x42, 0xf8, 0xd1, 0x03, 0xbd, 0x02, 0xb5, 0x18, 0x66 +.byte 0x18, 0x66, 0xff, 0xf7, 0xf2, 0xff, 0x18, 0x6e, 0x18, 0x6e, 0x02, 0xbd, 0x00, 0x00, 0x02, 0x40 +.byte 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x5f, 0x00, 0x21, 0x22, 0x00, 0x00 +.byte 0xf4, 0x00, 0x00, 0x18, 0x22, 0x20, 0x00, 0xa0, 0x00, 0x01, 0x00, 0x10, 0x08, 0xed, 0x00, 0xe0 +.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0xb2, 0x4e, 0x7a + +// last four bytes are checksum, also computed by microzig when embedding the bootrom. diff --git a/src/bootroms/shared/addressmap.h b/src/bootroms/shared/addressmap.h new file mode 100644 index 0000000..e8c5b49 --- /dev/null +++ b/src/bootroms/shared/addressmap.h @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef _ADDRESSMAP_H_ +#define _ADDRESSMAP_H_ + + +// Register address offsets for atomic RMW aliases +#define REG_ALIAS_RW_BITS (0x0u << 12u) +#define REG_ALIAS_XOR_BITS (0x1u << 12u) +#define REG_ALIAS_SET_BITS (0x2u << 12u) +#define REG_ALIAS_CLR_BITS (0x3u << 12u) + +#define ROM_BASE _u(0x00000000) +#define XIP_BASE _u(0x10000000) +#define XIP_MAIN_BASE _u(0x10000000) +#define XIP_NOALLOC_BASE _u(0x11000000) +#define XIP_NOCACHE_BASE _u(0x12000000) +#define XIP_NOCACHE_NOALLOC_BASE _u(0x13000000) +#define XIP_CTRL_BASE _u(0x14000000) +#define XIP_SRAM_BASE _u(0x15000000) +#define XIP_SRAM_END _u(0x15004000) +#define XIP_SSI_BASE _u(0x18000000) +#define SRAM_BASE _u(0x20000000) +#define SRAM_STRIPED_BASE _u(0x20000000) +#define SRAM_STRIPED_END _u(0x20040000) +#define SRAM4_BASE _u(0x20040000) +#define SRAM5_BASE _u(0x20041000) +#define SRAM_END _u(0x20042000) +#define SRAM0_BASE _u(0x21000000) +#define SRAM1_BASE _u(0x21010000) +#define SRAM2_BASE _u(0x21020000) +#define SRAM3_BASE _u(0x21030000) +#define SYSINFO_BASE _u(0x40000000) +#define SYSCFG_BASE _u(0x40004000) +#define CLOCKS_BASE _u(0x40008000) +#define RESETS_BASE _u(0x4000c000) +#define PSM_BASE _u(0x40010000) +#define IO_BANK0_BASE _u(0x40014000) +#define IO_QSPI_BASE _u(0x40018000) +#define PADS_BANK0_BASE _u(0x4001c000) +#define PADS_QSPI_BASE _u(0x40020000) +#define XOSC_BASE _u(0x40024000) +#define PLL_SYS_BASE _u(0x40028000) +#define PLL_USB_BASE _u(0x4002c000) +#define BUSCTRL_BASE _u(0x40030000) +#define UART0_BASE _u(0x40034000) +#define UART1_BASE _u(0x40038000) +#define SPI0_BASE _u(0x4003c000) +#define SPI1_BASE _u(0x40040000) +#define I2C0_BASE _u(0x40044000) +#define I2C1_BASE _u(0x40048000) +#define ADC_BASE _u(0x4004c000) +#define PWM_BASE _u(0x40050000) +#define TIMER_BASE _u(0x40054000) +#define WATCHDOG_BASE _u(0x40058000) +#define RTC_BASE _u(0x4005c000) +#define ROSC_BASE _u(0x40060000) +#define VREG_AND_CHIP_RESET_BASE _u(0x40064000) +#define TBMAN_BASE _u(0x4006c000) +#define DMA_BASE _u(0x50000000) +#define USBCTRL_DPRAM_BASE _u(0x50100000) +#define USBCTRL_BASE _u(0x50100000) +#define USBCTRL_REGS_BASE _u(0x50110000) +#define PIO0_BASE _u(0x50200000) +#define PIO1_BASE _u(0x50300000) +#define XIP_AUX_BASE _u(0x50400000) +#define SIO_BASE _u(0xd0000000) +#define PPB_BASE _u(0xe0000000) + +#endif // _ADDRESSMAP_H_ diff --git a/src/bootroms/shared/asm_helper.S b/src/bootroms/shared/asm_helper.S new file mode 100644 index 0000000..8e2c37a --- /dev/null +++ b/src/bootroms/shared/asm_helper.S @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "regs.h" + +# note we don't do this by default in this file for backwards comaptibility with user code +# that may include this file, but not use unified syntax. Note that this macro does equivalent +# setup to the pico_default_asm macro for inline assembly in C code. +.macro pico_default_asm_setup +.syntax unified +.cpu cortex-m0plus +.thumb +.endm + +// do not put align in here as it is used mid function sometimes +.macro regular_func x +.global \x +.type \x,%function +.thumb_func +\x: +.endm + +.macro regular_func_with_section x +.section .text.\x +regular_func \x +.endm + +// do not put align in here as it is used mid function sometimes +.macro wrapper_func x +regular_func WRAPPER_FUNC_NAME(\x) +.endm + +.macro __pre_init func, priority_string +.section .preinit_array.\priority_string +.align 2 +.word \func +.endm + diff --git a/src/bootroms/shared/exit_from_boot2.S b/src/bootroms/shared/exit_from_boot2.S new file mode 100644 index 0000000..a1fd2bc --- /dev/null +++ b/src/bootroms/shared/exit_from_boot2.S @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _BOOT2_HELPER_EXIT_FROM_BOOT2 +#define _BOOT2_HELPER_EXIT_FROM_BOOT2 + +#include "regs.h" + +// If entered from the bootrom, lr (which we earlier pushed) will be 0, +// and we vector through the table at the start of the main flash image. +// Any regular function call will have a nonzero value for lr. +check_return: + pop {r0} + cmp r0, #0 + beq vector_into_flash + bx r0 +vector_into_flash: + ldr r0, =(XIP_BASE + 0x100) + ldr r1, =(PPB_BASE + M0PLUS_VTOR_OFFSET) + str r0, [r1] + ldmia r0, {r0, r1} + msr msp, r0 + bx r1 + +#endif diff --git a/src/bootroms/shared/m0plus.h b/src/bootroms/shared/m0plus.h new file mode 100644 index 0000000..cef5ab0 --- /dev/null +++ b/src/bootroms/shared/m0plus.h @@ -0,0 +1,1149 @@ +/** + * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +// ============================================================================= +// Register block : M0PLUS +// Version : 1 +// Bus type : ahbl +// Description : None +// ============================================================================= +#ifndef HARDWARE_REGS_M0PLUS_DEFINED +#define HARDWARE_REGS_M0PLUS_DEFINED +// ============================================================================= +// Register : M0PLUS_SYST_CSR +// Description : Use the SysTick Control and Status Register to enable the +// SysTick features. +#define M0PLUS_SYST_CSR_OFFSET _u(0x0000e010) +#define M0PLUS_SYST_CSR_BITS _u(0x00010007) +#define M0PLUS_SYST_CSR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_SYST_CSR_COUNTFLAG +// Description : Returns 1 if timer counted to 0 since last time this was read. +// Clears on read by application or debugger. +#define M0PLUS_SYST_CSR_COUNTFLAG_RESET _u(0x0) +#define M0PLUS_SYST_CSR_COUNTFLAG_BITS _u(0x00010000) +#define M0PLUS_SYST_CSR_COUNTFLAG_MSB _u(16) +#define M0PLUS_SYST_CSR_COUNTFLAG_LSB _u(16) +#define M0PLUS_SYST_CSR_COUNTFLAG_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_SYST_CSR_CLKSOURCE +// Description : SysTick clock source. Always reads as one if SYST_CALIB reports +// NOREF. +// Selects the SysTick timer clock source: +// 0 = External reference clock. +// 1 = Processor clock. +#define M0PLUS_SYST_CSR_CLKSOURCE_RESET _u(0x0) +#define M0PLUS_SYST_CSR_CLKSOURCE_BITS _u(0x00000004) +#define M0PLUS_SYST_CSR_CLKSOURCE_MSB _u(2) +#define M0PLUS_SYST_CSR_CLKSOURCE_LSB _u(2) +#define M0PLUS_SYST_CSR_CLKSOURCE_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_SYST_CSR_TICKINT +// Description : Enables SysTick exception request: +// 0 = Counting down to zero does not assert the SysTick exception +// request. +// 1 = Counting down to zero to asserts the SysTick exception +// request. +#define M0PLUS_SYST_CSR_TICKINT_RESET _u(0x0) +#define M0PLUS_SYST_CSR_TICKINT_BITS _u(0x00000002) +#define M0PLUS_SYST_CSR_TICKINT_MSB _u(1) +#define M0PLUS_SYST_CSR_TICKINT_LSB _u(1) +#define M0PLUS_SYST_CSR_TICKINT_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_SYST_CSR_ENABLE +// Description : Enable SysTick counter: +// 0 = Counter disabled. +// 1 = Counter enabled. +#define M0PLUS_SYST_CSR_ENABLE_RESET _u(0x0) +#define M0PLUS_SYST_CSR_ENABLE_BITS _u(0x00000001) +#define M0PLUS_SYST_CSR_ENABLE_MSB _u(0) +#define M0PLUS_SYST_CSR_ENABLE_LSB _u(0) +#define M0PLUS_SYST_CSR_ENABLE_ACCESS "RW" +// ============================================================================= +// Register : M0PLUS_SYST_RVR +// Description : Use the SysTick Reload Value Register to specify the start +// value to load into the current value register when the counter +// reaches 0. It can be any value between 0 and 0x00FFFFFF. A +// start value of 0 is possible, but has no effect because the +// SysTick interrupt and COUNTFLAG are activated when counting +// from 1 to 0. The reset value of this register is UNKNOWN. +// To generate a multi-shot timer with a period of N processor +// clock cycles, use a RELOAD value of N-1. For example, if the +// SysTick interrupt is required every 100 clock pulses, set +// RELOAD to 99. +#define M0PLUS_SYST_RVR_OFFSET _u(0x0000e014) +#define M0PLUS_SYST_RVR_BITS _u(0x00ffffff) +#define M0PLUS_SYST_RVR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_SYST_RVR_RELOAD +// Description : Value to load into the SysTick Current Value Register when the +// counter reaches 0. +#define M0PLUS_SYST_RVR_RELOAD_RESET _u(0x000000) +#define M0PLUS_SYST_RVR_RELOAD_BITS _u(0x00ffffff) +#define M0PLUS_SYST_RVR_RELOAD_MSB _u(23) +#define M0PLUS_SYST_RVR_RELOAD_LSB _u(0) +#define M0PLUS_SYST_RVR_RELOAD_ACCESS "RW" +// ============================================================================= +// Register : M0PLUS_SYST_CVR +// Description : Use the SysTick Current Value Register to find the current +// value in the register. The reset value of this register is +// UNKNOWN. +#define M0PLUS_SYST_CVR_OFFSET _u(0x0000e018) +#define M0PLUS_SYST_CVR_BITS _u(0x00ffffff) +#define M0PLUS_SYST_CVR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_SYST_CVR_CURRENT +// Description : Reads return the current value of the SysTick counter. This +// register is write-clear. Writing to it with any value clears +// the register to 0. Clearing this register also clears the +// COUNTFLAG bit of the SysTick Control and Status Register. +#define M0PLUS_SYST_CVR_CURRENT_RESET _u(0x000000) +#define M0PLUS_SYST_CVR_CURRENT_BITS _u(0x00ffffff) +#define M0PLUS_SYST_CVR_CURRENT_MSB _u(23) +#define M0PLUS_SYST_CVR_CURRENT_LSB _u(0) +#define M0PLUS_SYST_CVR_CURRENT_ACCESS "RW" +// ============================================================================= +// Register : M0PLUS_SYST_CALIB +// Description : Use the SysTick Calibration Value Register to enable software +// to scale to any required speed using divide and multiply. +#define M0PLUS_SYST_CALIB_OFFSET _u(0x0000e01c) +#define M0PLUS_SYST_CALIB_BITS _u(0xc0ffffff) +#define M0PLUS_SYST_CALIB_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_SYST_CALIB_NOREF +// Description : If reads as 1, the Reference clock is not provided - the +// CLKSOURCE bit of the SysTick Control and Status register will +// be forced to 1 and cannot be cleared to 0. +#define M0PLUS_SYST_CALIB_NOREF_RESET _u(0x0) +#define M0PLUS_SYST_CALIB_NOREF_BITS _u(0x80000000) +#define M0PLUS_SYST_CALIB_NOREF_MSB _u(31) +#define M0PLUS_SYST_CALIB_NOREF_LSB _u(31) +#define M0PLUS_SYST_CALIB_NOREF_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_SYST_CALIB_SKEW +// Description : If reads as 1, the calibration value for 10ms is inexact (due +// to clock frequency). +#define M0PLUS_SYST_CALIB_SKEW_RESET _u(0x0) +#define M0PLUS_SYST_CALIB_SKEW_BITS _u(0x40000000) +#define M0PLUS_SYST_CALIB_SKEW_MSB _u(30) +#define M0PLUS_SYST_CALIB_SKEW_LSB _u(30) +#define M0PLUS_SYST_CALIB_SKEW_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_SYST_CALIB_TENMS +// Description : An optional Reload value to be used for 10ms (100Hz) timing, +// subject to system clock skew errors. If the value reads as 0, +// the calibration value is not known. +#define M0PLUS_SYST_CALIB_TENMS_RESET _u(0x000000) +#define M0PLUS_SYST_CALIB_TENMS_BITS _u(0x00ffffff) +#define M0PLUS_SYST_CALIB_TENMS_MSB _u(23) +#define M0PLUS_SYST_CALIB_TENMS_LSB _u(0) +#define M0PLUS_SYST_CALIB_TENMS_ACCESS "RO" +// ============================================================================= +// Register : M0PLUS_NVIC_ISER +// Description : Use the Interrupt Set-Enable Register to enable interrupts and +// determine which interrupts are currently enabled. +// If a pending interrupt is enabled, the NVIC activates the +// interrupt based on its priority. If an interrupt is not +// enabled, asserting its interrupt signal changes the interrupt +// state to pending, but the NVIC never activates the interrupt, +// regardless of its priority. +#define M0PLUS_NVIC_ISER_OFFSET _u(0x0000e100) +#define M0PLUS_NVIC_ISER_BITS _u(0xffffffff) +#define M0PLUS_NVIC_ISER_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_ISER_SETENA +// Description : Interrupt set-enable bits. +// Write: +// 0 = No effect. +// 1 = Enable interrupt. +// Read: +// 0 = Interrupt disabled. +// 1 = Interrupt enabled. +#define M0PLUS_NVIC_ISER_SETENA_RESET _u(0x00000000) +#define M0PLUS_NVIC_ISER_SETENA_BITS _u(0xffffffff) +#define M0PLUS_NVIC_ISER_SETENA_MSB _u(31) +#define M0PLUS_NVIC_ISER_SETENA_LSB _u(0) +#define M0PLUS_NVIC_ISER_SETENA_ACCESS "RW" +// ============================================================================= +// Register : M0PLUS_NVIC_ICER +// Description : Use the Interrupt Clear-Enable Registers to disable interrupts +// and determine which interrupts are currently enabled. +#define M0PLUS_NVIC_ICER_OFFSET _u(0x0000e180) +#define M0PLUS_NVIC_ICER_BITS _u(0xffffffff) +#define M0PLUS_NVIC_ICER_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_ICER_CLRENA +// Description : Interrupt clear-enable bits. +// Write: +// 0 = No effect. +// 1 = Disable interrupt. +// Read: +// 0 = Interrupt disabled. +// 1 = Interrupt enabled. +#define M0PLUS_NVIC_ICER_CLRENA_RESET _u(0x00000000) +#define M0PLUS_NVIC_ICER_CLRENA_BITS _u(0xffffffff) +#define M0PLUS_NVIC_ICER_CLRENA_MSB _u(31) +#define M0PLUS_NVIC_ICER_CLRENA_LSB _u(0) +#define M0PLUS_NVIC_ICER_CLRENA_ACCESS "RW" +// ============================================================================= +// Register : M0PLUS_NVIC_ISPR +// Description : The NVIC_ISPR forces interrupts into the pending state, and +// shows which interrupts are pending. +#define M0PLUS_NVIC_ISPR_OFFSET _u(0x0000e200) +#define M0PLUS_NVIC_ISPR_BITS _u(0xffffffff) +#define M0PLUS_NVIC_ISPR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_ISPR_SETPEND +// Description : Interrupt set-pending bits. +// Write: +// 0 = No effect. +// 1 = Changes interrupt state to pending. +// Read: +// 0 = Interrupt is not pending. +// 1 = Interrupt is pending. +// Note: Writing 1 to the NVIC_ISPR bit corresponding to: +// An interrupt that is pending has no effect. +// A disabled interrupt sets the state of that interrupt to +// pending. +#define M0PLUS_NVIC_ISPR_SETPEND_RESET _u(0x00000000) +#define M0PLUS_NVIC_ISPR_SETPEND_BITS _u(0xffffffff) +#define M0PLUS_NVIC_ISPR_SETPEND_MSB _u(31) +#define M0PLUS_NVIC_ISPR_SETPEND_LSB _u(0) +#define M0PLUS_NVIC_ISPR_SETPEND_ACCESS "RW" +// ============================================================================= +// Register : M0PLUS_NVIC_ICPR +// Description : Use the Interrupt Clear-Pending Register to clear pending +// interrupts and determine which interrupts are currently +// pending. +#define M0PLUS_NVIC_ICPR_OFFSET _u(0x0000e280) +#define M0PLUS_NVIC_ICPR_BITS _u(0xffffffff) +#define M0PLUS_NVIC_ICPR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_ICPR_CLRPEND +// Description : Interrupt clear-pending bits. +// Write: +// 0 = No effect. +// 1 = Removes pending state and interrupt. +// Read: +// 0 = Interrupt is not pending. +// 1 = Interrupt is pending. +#define M0PLUS_NVIC_ICPR_CLRPEND_RESET _u(0x00000000) +#define M0PLUS_NVIC_ICPR_CLRPEND_BITS _u(0xffffffff) +#define M0PLUS_NVIC_ICPR_CLRPEND_MSB _u(31) +#define M0PLUS_NVIC_ICPR_CLRPEND_LSB _u(0) +#define M0PLUS_NVIC_ICPR_CLRPEND_ACCESS "RW" +// ============================================================================= +// Register : M0PLUS_NVIC_IPR0 +// Description : Use the Interrupt Priority Registers to assign a priority from +// 0 to 3 to each of the available interrupts. 0 is the highest +// priority, and 3 is the lowest. +// Note: Writing 1 to an NVIC_ICPR bit does not affect the active +// state of the corresponding interrupt. +// These registers are only word-accessible +#define M0PLUS_NVIC_IPR0_OFFSET _u(0x0000e400) +#define M0PLUS_NVIC_IPR0_BITS _u(0xc0c0c0c0) +#define M0PLUS_NVIC_IPR0_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR0_IP_3 +// Description : Priority of interrupt 3 +#define M0PLUS_NVIC_IPR0_IP_3_RESET _u(0x0) +#define M0PLUS_NVIC_IPR0_IP_3_BITS _u(0xc0000000) +#define M0PLUS_NVIC_IPR0_IP_3_MSB _u(31) +#define M0PLUS_NVIC_IPR0_IP_3_LSB _u(30) +#define M0PLUS_NVIC_IPR0_IP_3_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR0_IP_2 +// Description : Priority of interrupt 2 +#define M0PLUS_NVIC_IPR0_IP_2_RESET _u(0x0) +#define M0PLUS_NVIC_IPR0_IP_2_BITS _u(0x00c00000) +#define M0PLUS_NVIC_IPR0_IP_2_MSB _u(23) +#define M0PLUS_NVIC_IPR0_IP_2_LSB _u(22) +#define M0PLUS_NVIC_IPR0_IP_2_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR0_IP_1 +// Description : Priority of interrupt 1 +#define M0PLUS_NVIC_IPR0_IP_1_RESET _u(0x0) +#define M0PLUS_NVIC_IPR0_IP_1_BITS _u(0x0000c000) +#define M0PLUS_NVIC_IPR0_IP_1_MSB _u(15) +#define M0PLUS_NVIC_IPR0_IP_1_LSB _u(14) +#define M0PLUS_NVIC_IPR0_IP_1_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR0_IP_0 +// Description : Priority of interrupt 0 +#define M0PLUS_NVIC_IPR0_IP_0_RESET _u(0x0) +#define M0PLUS_NVIC_IPR0_IP_0_BITS _u(0x000000c0) +#define M0PLUS_NVIC_IPR0_IP_0_MSB _u(7) +#define M0PLUS_NVIC_IPR0_IP_0_LSB _u(6) +#define M0PLUS_NVIC_IPR0_IP_0_ACCESS "RW" +// ============================================================================= +// Register : M0PLUS_NVIC_IPR1 +// Description : Use the Interrupt Priority Registers to assign a priority from +// 0 to 3 to each of the available interrupts. 0 is the highest +// priority, and 3 is the lowest. +#define M0PLUS_NVIC_IPR1_OFFSET _u(0x0000e404) +#define M0PLUS_NVIC_IPR1_BITS _u(0xc0c0c0c0) +#define M0PLUS_NVIC_IPR1_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR1_IP_7 +// Description : Priority of interrupt 7 +#define M0PLUS_NVIC_IPR1_IP_7_RESET _u(0x0) +#define M0PLUS_NVIC_IPR1_IP_7_BITS _u(0xc0000000) +#define M0PLUS_NVIC_IPR1_IP_7_MSB _u(31) +#define M0PLUS_NVIC_IPR1_IP_7_LSB _u(30) +#define M0PLUS_NVIC_IPR1_IP_7_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR1_IP_6 +// Description : Priority of interrupt 6 +#define M0PLUS_NVIC_IPR1_IP_6_RESET _u(0x0) +#define M0PLUS_NVIC_IPR1_IP_6_BITS _u(0x00c00000) +#define M0PLUS_NVIC_IPR1_IP_6_MSB _u(23) +#define M0PLUS_NVIC_IPR1_IP_6_LSB _u(22) +#define M0PLUS_NVIC_IPR1_IP_6_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR1_IP_5 +// Description : Priority of interrupt 5 +#define M0PLUS_NVIC_IPR1_IP_5_RESET _u(0x0) +#define M0PLUS_NVIC_IPR1_IP_5_BITS _u(0x0000c000) +#define M0PLUS_NVIC_IPR1_IP_5_MSB _u(15) +#define M0PLUS_NVIC_IPR1_IP_5_LSB _u(14) +#define M0PLUS_NVIC_IPR1_IP_5_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR1_IP_4 +// Description : Priority of interrupt 4 +#define M0PLUS_NVIC_IPR1_IP_4_RESET _u(0x0) +#define M0PLUS_NVIC_IPR1_IP_4_BITS _u(0x000000c0) +#define M0PLUS_NVIC_IPR1_IP_4_MSB _u(7) +#define M0PLUS_NVIC_IPR1_IP_4_LSB _u(6) +#define M0PLUS_NVIC_IPR1_IP_4_ACCESS "RW" +// ============================================================================= +// Register : M0PLUS_NVIC_IPR2 +// Description : Use the Interrupt Priority Registers to assign a priority from +// 0 to 3 to each of the available interrupts. 0 is the highest +// priority, and 3 is the lowest. +#define M0PLUS_NVIC_IPR2_OFFSET _u(0x0000e408) +#define M0PLUS_NVIC_IPR2_BITS _u(0xc0c0c0c0) +#define M0PLUS_NVIC_IPR2_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR2_IP_11 +// Description : Priority of interrupt 11 +#define M0PLUS_NVIC_IPR2_IP_11_RESET _u(0x0) +#define M0PLUS_NVIC_IPR2_IP_11_BITS _u(0xc0000000) +#define M0PLUS_NVIC_IPR2_IP_11_MSB _u(31) +#define M0PLUS_NVIC_IPR2_IP_11_LSB _u(30) +#define M0PLUS_NVIC_IPR2_IP_11_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR2_IP_10 +// Description : Priority of interrupt 10 +#define M0PLUS_NVIC_IPR2_IP_10_RESET _u(0x0) +#define M0PLUS_NVIC_IPR2_IP_10_BITS _u(0x00c00000) +#define M0PLUS_NVIC_IPR2_IP_10_MSB _u(23) +#define M0PLUS_NVIC_IPR2_IP_10_LSB _u(22) +#define M0PLUS_NVIC_IPR2_IP_10_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR2_IP_9 +// Description : Priority of interrupt 9 +#define M0PLUS_NVIC_IPR2_IP_9_RESET _u(0x0) +#define M0PLUS_NVIC_IPR2_IP_9_BITS _u(0x0000c000) +#define M0PLUS_NVIC_IPR2_IP_9_MSB _u(15) +#define M0PLUS_NVIC_IPR2_IP_9_LSB _u(14) +#define M0PLUS_NVIC_IPR2_IP_9_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR2_IP_8 +// Description : Priority of interrupt 8 +#define M0PLUS_NVIC_IPR2_IP_8_RESET _u(0x0) +#define M0PLUS_NVIC_IPR2_IP_8_BITS _u(0x000000c0) +#define M0PLUS_NVIC_IPR2_IP_8_MSB _u(7) +#define M0PLUS_NVIC_IPR2_IP_8_LSB _u(6) +#define M0PLUS_NVIC_IPR2_IP_8_ACCESS "RW" +// ============================================================================= +// Register : M0PLUS_NVIC_IPR3 +// Description : Use the Interrupt Priority Registers to assign a priority from +// 0 to 3 to each of the available interrupts. 0 is the highest +// priority, and 3 is the lowest. +#define M0PLUS_NVIC_IPR3_OFFSET _u(0x0000e40c) +#define M0PLUS_NVIC_IPR3_BITS _u(0xc0c0c0c0) +#define M0PLUS_NVIC_IPR3_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR3_IP_15 +// Description : Priority of interrupt 15 +#define M0PLUS_NVIC_IPR3_IP_15_RESET _u(0x0) +#define M0PLUS_NVIC_IPR3_IP_15_BITS _u(0xc0000000) +#define M0PLUS_NVIC_IPR3_IP_15_MSB _u(31) +#define M0PLUS_NVIC_IPR3_IP_15_LSB _u(30) +#define M0PLUS_NVIC_IPR3_IP_15_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR3_IP_14 +// Description : Priority of interrupt 14 +#define M0PLUS_NVIC_IPR3_IP_14_RESET _u(0x0) +#define M0PLUS_NVIC_IPR3_IP_14_BITS _u(0x00c00000) +#define M0PLUS_NVIC_IPR3_IP_14_MSB _u(23) +#define M0PLUS_NVIC_IPR3_IP_14_LSB _u(22) +#define M0PLUS_NVIC_IPR3_IP_14_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR3_IP_13 +// Description : Priority of interrupt 13 +#define M0PLUS_NVIC_IPR3_IP_13_RESET _u(0x0) +#define M0PLUS_NVIC_IPR3_IP_13_BITS _u(0x0000c000) +#define M0PLUS_NVIC_IPR3_IP_13_MSB _u(15) +#define M0PLUS_NVIC_IPR3_IP_13_LSB _u(14) +#define M0PLUS_NVIC_IPR3_IP_13_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR3_IP_12 +// Description : Priority of interrupt 12 +#define M0PLUS_NVIC_IPR3_IP_12_RESET _u(0x0) +#define M0PLUS_NVIC_IPR3_IP_12_BITS _u(0x000000c0) +#define M0PLUS_NVIC_IPR3_IP_12_MSB _u(7) +#define M0PLUS_NVIC_IPR3_IP_12_LSB _u(6) +#define M0PLUS_NVIC_IPR3_IP_12_ACCESS "RW" +// ============================================================================= +// Register : M0PLUS_NVIC_IPR4 +// Description : Use the Interrupt Priority Registers to assign a priority from +// 0 to 3 to each of the available interrupts. 0 is the highest +// priority, and 3 is the lowest. +#define M0PLUS_NVIC_IPR4_OFFSET _u(0x0000e410) +#define M0PLUS_NVIC_IPR4_BITS _u(0xc0c0c0c0) +#define M0PLUS_NVIC_IPR4_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR4_IP_19 +// Description : Priority of interrupt 19 +#define M0PLUS_NVIC_IPR4_IP_19_RESET _u(0x0) +#define M0PLUS_NVIC_IPR4_IP_19_BITS _u(0xc0000000) +#define M0PLUS_NVIC_IPR4_IP_19_MSB _u(31) +#define M0PLUS_NVIC_IPR4_IP_19_LSB _u(30) +#define M0PLUS_NVIC_IPR4_IP_19_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR4_IP_18 +// Description : Priority of interrupt 18 +#define M0PLUS_NVIC_IPR4_IP_18_RESET _u(0x0) +#define M0PLUS_NVIC_IPR4_IP_18_BITS _u(0x00c00000) +#define M0PLUS_NVIC_IPR4_IP_18_MSB _u(23) +#define M0PLUS_NVIC_IPR4_IP_18_LSB _u(22) +#define M0PLUS_NVIC_IPR4_IP_18_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR4_IP_17 +// Description : Priority of interrupt 17 +#define M0PLUS_NVIC_IPR4_IP_17_RESET _u(0x0) +#define M0PLUS_NVIC_IPR4_IP_17_BITS _u(0x0000c000) +#define M0PLUS_NVIC_IPR4_IP_17_MSB _u(15) +#define M0PLUS_NVIC_IPR4_IP_17_LSB _u(14) +#define M0PLUS_NVIC_IPR4_IP_17_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR4_IP_16 +// Description : Priority of interrupt 16 +#define M0PLUS_NVIC_IPR4_IP_16_RESET _u(0x0) +#define M0PLUS_NVIC_IPR4_IP_16_BITS _u(0x000000c0) +#define M0PLUS_NVIC_IPR4_IP_16_MSB _u(7) +#define M0PLUS_NVIC_IPR4_IP_16_LSB _u(6) +#define M0PLUS_NVIC_IPR4_IP_16_ACCESS "RW" +// ============================================================================= +// Register : M0PLUS_NVIC_IPR5 +// Description : Use the Interrupt Priority Registers to assign a priority from +// 0 to 3 to each of the available interrupts. 0 is the highest +// priority, and 3 is the lowest. +#define M0PLUS_NVIC_IPR5_OFFSET _u(0x0000e414) +#define M0PLUS_NVIC_IPR5_BITS _u(0xc0c0c0c0) +#define M0PLUS_NVIC_IPR5_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR5_IP_23 +// Description : Priority of interrupt 23 +#define M0PLUS_NVIC_IPR5_IP_23_RESET _u(0x0) +#define M0PLUS_NVIC_IPR5_IP_23_BITS _u(0xc0000000) +#define M0PLUS_NVIC_IPR5_IP_23_MSB _u(31) +#define M0PLUS_NVIC_IPR5_IP_23_LSB _u(30) +#define M0PLUS_NVIC_IPR5_IP_23_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR5_IP_22 +// Description : Priority of interrupt 22 +#define M0PLUS_NVIC_IPR5_IP_22_RESET _u(0x0) +#define M0PLUS_NVIC_IPR5_IP_22_BITS _u(0x00c00000) +#define M0PLUS_NVIC_IPR5_IP_22_MSB _u(23) +#define M0PLUS_NVIC_IPR5_IP_22_LSB _u(22) +#define M0PLUS_NVIC_IPR5_IP_22_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR5_IP_21 +// Description : Priority of interrupt 21 +#define M0PLUS_NVIC_IPR5_IP_21_RESET _u(0x0) +#define M0PLUS_NVIC_IPR5_IP_21_BITS _u(0x0000c000) +#define M0PLUS_NVIC_IPR5_IP_21_MSB _u(15) +#define M0PLUS_NVIC_IPR5_IP_21_LSB _u(14) +#define M0PLUS_NVIC_IPR5_IP_21_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR5_IP_20 +// Description : Priority of interrupt 20 +#define M0PLUS_NVIC_IPR5_IP_20_RESET _u(0x0) +#define M0PLUS_NVIC_IPR5_IP_20_BITS _u(0x000000c0) +#define M0PLUS_NVIC_IPR5_IP_20_MSB _u(7) +#define M0PLUS_NVIC_IPR5_IP_20_LSB _u(6) +#define M0PLUS_NVIC_IPR5_IP_20_ACCESS "RW" +// ============================================================================= +// Register : M0PLUS_NVIC_IPR6 +// Description : Use the Interrupt Priority Registers to assign a priority from +// 0 to 3 to each of the available interrupts. 0 is the highest +// priority, and 3 is the lowest. +#define M0PLUS_NVIC_IPR6_OFFSET _u(0x0000e418) +#define M0PLUS_NVIC_IPR6_BITS _u(0xc0c0c0c0) +#define M0PLUS_NVIC_IPR6_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR6_IP_27 +// Description : Priority of interrupt 27 +#define M0PLUS_NVIC_IPR6_IP_27_RESET _u(0x0) +#define M0PLUS_NVIC_IPR6_IP_27_BITS _u(0xc0000000) +#define M0PLUS_NVIC_IPR6_IP_27_MSB _u(31) +#define M0PLUS_NVIC_IPR6_IP_27_LSB _u(30) +#define M0PLUS_NVIC_IPR6_IP_27_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR6_IP_26 +// Description : Priority of interrupt 26 +#define M0PLUS_NVIC_IPR6_IP_26_RESET _u(0x0) +#define M0PLUS_NVIC_IPR6_IP_26_BITS _u(0x00c00000) +#define M0PLUS_NVIC_IPR6_IP_26_MSB _u(23) +#define M0PLUS_NVIC_IPR6_IP_26_LSB _u(22) +#define M0PLUS_NVIC_IPR6_IP_26_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR6_IP_25 +// Description : Priority of interrupt 25 +#define M0PLUS_NVIC_IPR6_IP_25_RESET _u(0x0) +#define M0PLUS_NVIC_IPR6_IP_25_BITS _u(0x0000c000) +#define M0PLUS_NVIC_IPR6_IP_25_MSB _u(15) +#define M0PLUS_NVIC_IPR6_IP_25_LSB _u(14) +#define M0PLUS_NVIC_IPR6_IP_25_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR6_IP_24 +// Description : Priority of interrupt 24 +#define M0PLUS_NVIC_IPR6_IP_24_RESET _u(0x0) +#define M0PLUS_NVIC_IPR6_IP_24_BITS _u(0x000000c0) +#define M0PLUS_NVIC_IPR6_IP_24_MSB _u(7) +#define M0PLUS_NVIC_IPR6_IP_24_LSB _u(6) +#define M0PLUS_NVIC_IPR6_IP_24_ACCESS "RW" +// ============================================================================= +// Register : M0PLUS_NVIC_IPR7 +// Description : Use the Interrupt Priority Registers to assign a priority from +// 0 to 3 to each of the available interrupts. 0 is the highest +// priority, and 3 is the lowest. +#define M0PLUS_NVIC_IPR7_OFFSET _u(0x0000e41c) +#define M0PLUS_NVIC_IPR7_BITS _u(0xc0c0c0c0) +#define M0PLUS_NVIC_IPR7_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR7_IP_31 +// Description : Priority of interrupt 31 +#define M0PLUS_NVIC_IPR7_IP_31_RESET _u(0x0) +#define M0PLUS_NVIC_IPR7_IP_31_BITS _u(0xc0000000) +#define M0PLUS_NVIC_IPR7_IP_31_MSB _u(31) +#define M0PLUS_NVIC_IPR7_IP_31_LSB _u(30) +#define M0PLUS_NVIC_IPR7_IP_31_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR7_IP_30 +// Description : Priority of interrupt 30 +#define M0PLUS_NVIC_IPR7_IP_30_RESET _u(0x0) +#define M0PLUS_NVIC_IPR7_IP_30_BITS _u(0x00c00000) +#define M0PLUS_NVIC_IPR7_IP_30_MSB _u(23) +#define M0PLUS_NVIC_IPR7_IP_30_LSB _u(22) +#define M0PLUS_NVIC_IPR7_IP_30_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR7_IP_29 +// Description : Priority of interrupt 29 +#define M0PLUS_NVIC_IPR7_IP_29_RESET _u(0x0) +#define M0PLUS_NVIC_IPR7_IP_29_BITS _u(0x0000c000) +#define M0PLUS_NVIC_IPR7_IP_29_MSB _u(15) +#define M0PLUS_NVIC_IPR7_IP_29_LSB _u(14) +#define M0PLUS_NVIC_IPR7_IP_29_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_NVIC_IPR7_IP_28 +// Description : Priority of interrupt 28 +#define M0PLUS_NVIC_IPR7_IP_28_RESET _u(0x0) +#define M0PLUS_NVIC_IPR7_IP_28_BITS _u(0x000000c0) +#define M0PLUS_NVIC_IPR7_IP_28_MSB _u(7) +#define M0PLUS_NVIC_IPR7_IP_28_LSB _u(6) +#define M0PLUS_NVIC_IPR7_IP_28_ACCESS "RW" +// ============================================================================= +// Register : M0PLUS_CPUID +// Description : Read the CPU ID Base Register to determine: the ID number of +// the processor core, the version number of the processor core, +// the implementation details of the processor core. +#define M0PLUS_CPUID_OFFSET _u(0x0000ed00) +#define M0PLUS_CPUID_BITS _u(0xffffffff) +#define M0PLUS_CPUID_RESET _u(0x410cc601) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_CPUID_IMPLEMENTER +// Description : Implementor code: 0x41 = ARM +#define M0PLUS_CPUID_IMPLEMENTER_RESET _u(0x41) +#define M0PLUS_CPUID_IMPLEMENTER_BITS _u(0xff000000) +#define M0PLUS_CPUID_IMPLEMENTER_MSB _u(31) +#define M0PLUS_CPUID_IMPLEMENTER_LSB _u(24) +#define M0PLUS_CPUID_IMPLEMENTER_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_CPUID_VARIANT +// Description : Major revision number n in the rnpm revision status: +// 0x0 = Revision 0. +#define M0PLUS_CPUID_VARIANT_RESET _u(0x0) +#define M0PLUS_CPUID_VARIANT_BITS _u(0x00f00000) +#define M0PLUS_CPUID_VARIANT_MSB _u(23) +#define M0PLUS_CPUID_VARIANT_LSB _u(20) +#define M0PLUS_CPUID_VARIANT_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_CPUID_ARCHITECTURE +// Description : Constant that defines the architecture of the processor: +// 0xC = ARMv6-M architecture. +#define M0PLUS_CPUID_ARCHITECTURE_RESET _u(0xc) +#define M0PLUS_CPUID_ARCHITECTURE_BITS _u(0x000f0000) +#define M0PLUS_CPUID_ARCHITECTURE_MSB _u(19) +#define M0PLUS_CPUID_ARCHITECTURE_LSB _u(16) +#define M0PLUS_CPUID_ARCHITECTURE_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_CPUID_PARTNO +// Description : Number of processor within family: 0xC60 = Cortex-M0+ +#define M0PLUS_CPUID_PARTNO_RESET _u(0xc60) +#define M0PLUS_CPUID_PARTNO_BITS _u(0x0000fff0) +#define M0PLUS_CPUID_PARTNO_MSB _u(15) +#define M0PLUS_CPUID_PARTNO_LSB _u(4) +#define M0PLUS_CPUID_PARTNO_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_CPUID_REVISION +// Description : Minor revision number m in the rnpm revision status: +// 0x1 = Patch 1. +#define M0PLUS_CPUID_REVISION_RESET _u(0x1) +#define M0PLUS_CPUID_REVISION_BITS _u(0x0000000f) +#define M0PLUS_CPUID_REVISION_MSB _u(3) +#define M0PLUS_CPUID_REVISION_LSB _u(0) +#define M0PLUS_CPUID_REVISION_ACCESS "RO" +// ============================================================================= +// Register : M0PLUS_ICSR +// Description : Use the Interrupt Control State Register to set a pending +// Non-Maskable Interrupt (NMI), set or clear a pending PendSV, +// set or clear a pending SysTick, check for pending exceptions, +// check the vector number of the highest priority pended +// exception, check the vector number of the active exception. +#define M0PLUS_ICSR_OFFSET _u(0x0000ed04) +#define M0PLUS_ICSR_BITS _u(0x9edff1ff) +#define M0PLUS_ICSR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_ICSR_NMIPENDSET +// Description : Setting this bit will activate an NMI. Since NMI is the highest +// priority exception, it will activate as soon as it is +// registered. +// NMI set-pending bit. +// Write: +// 0 = No effect. +// 1 = Changes NMI exception state to pending. +// Read: +// 0 = NMI exception is not pending. +// 1 = NMI exception is pending. +// Because NMI is the highest-priority exception, normally the +// processor enters the NMI +// exception handler as soon as it detects a write of 1 to this +// bit. Entering the handler then clears +// this bit to 0. This means a read of this bit by the NMI +// exception handler returns 1 only if the +// NMI signal is reasserted while the processor is executing that +// handler. +#define M0PLUS_ICSR_NMIPENDSET_RESET _u(0x0) +#define M0PLUS_ICSR_NMIPENDSET_BITS _u(0x80000000) +#define M0PLUS_ICSR_NMIPENDSET_MSB _u(31) +#define M0PLUS_ICSR_NMIPENDSET_LSB _u(31) +#define M0PLUS_ICSR_NMIPENDSET_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_ICSR_PENDSVSET +// Description : PendSV set-pending bit. +// Write: +// 0 = No effect. +// 1 = Changes PendSV exception state to pending. +// Read: +// 0 = PendSV exception is not pending. +// 1 = PendSV exception is pending. +// Writing 1 to this bit is the only way to set the PendSV +// exception state to pending. +#define M0PLUS_ICSR_PENDSVSET_RESET _u(0x0) +#define M0PLUS_ICSR_PENDSVSET_BITS _u(0x10000000) +#define M0PLUS_ICSR_PENDSVSET_MSB _u(28) +#define M0PLUS_ICSR_PENDSVSET_LSB _u(28) +#define M0PLUS_ICSR_PENDSVSET_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_ICSR_PENDSVCLR +// Description : PendSV clear-pending bit. +// Write: +// 0 = No effect. +// 1 = Removes the pending state from the PendSV exception. +#define M0PLUS_ICSR_PENDSVCLR_RESET _u(0x0) +#define M0PLUS_ICSR_PENDSVCLR_BITS _u(0x08000000) +#define M0PLUS_ICSR_PENDSVCLR_MSB _u(27) +#define M0PLUS_ICSR_PENDSVCLR_LSB _u(27) +#define M0PLUS_ICSR_PENDSVCLR_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_ICSR_PENDSTSET +// Description : SysTick exception set-pending bit. +// Write: +// 0 = No effect. +// 1 = Changes SysTick exception state to pending. +// Read: +// 0 = SysTick exception is not pending. +// 1 = SysTick exception is pending. +#define M0PLUS_ICSR_PENDSTSET_RESET _u(0x0) +#define M0PLUS_ICSR_PENDSTSET_BITS _u(0x04000000) +#define M0PLUS_ICSR_PENDSTSET_MSB _u(26) +#define M0PLUS_ICSR_PENDSTSET_LSB _u(26) +#define M0PLUS_ICSR_PENDSTSET_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_ICSR_PENDSTCLR +// Description : SysTick exception clear-pending bit. +// Write: +// 0 = No effect. +// 1 = Removes the pending state from the SysTick exception. +// This bit is WO. On a register read its value is Unknown. +#define M0PLUS_ICSR_PENDSTCLR_RESET _u(0x0) +#define M0PLUS_ICSR_PENDSTCLR_BITS _u(0x02000000) +#define M0PLUS_ICSR_PENDSTCLR_MSB _u(25) +#define M0PLUS_ICSR_PENDSTCLR_LSB _u(25) +#define M0PLUS_ICSR_PENDSTCLR_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_ICSR_ISRPREEMPT +// Description : The system can only access this bit when the core is halted. It +// indicates that a pending interrupt is to be taken in the next +// running cycle. If C_MASKINTS is clear in the Debug Halting +// Control and Status Register, the interrupt is serviced. +#define M0PLUS_ICSR_ISRPREEMPT_RESET _u(0x0) +#define M0PLUS_ICSR_ISRPREEMPT_BITS _u(0x00800000) +#define M0PLUS_ICSR_ISRPREEMPT_MSB _u(23) +#define M0PLUS_ICSR_ISRPREEMPT_LSB _u(23) +#define M0PLUS_ICSR_ISRPREEMPT_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_ICSR_ISRPENDING +// Description : External interrupt pending flag +#define M0PLUS_ICSR_ISRPENDING_RESET _u(0x0) +#define M0PLUS_ICSR_ISRPENDING_BITS _u(0x00400000) +#define M0PLUS_ICSR_ISRPENDING_MSB _u(22) +#define M0PLUS_ICSR_ISRPENDING_LSB _u(22) +#define M0PLUS_ICSR_ISRPENDING_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_ICSR_VECTPENDING +// Description : Indicates the exception number for the highest priority pending +// exception: 0 = no pending exceptions. Non zero = The pending +// state includes the effect of memory-mapped enable and mask +// registers. It does not include the PRIMASK special-purpose +// register qualifier. +#define M0PLUS_ICSR_VECTPENDING_RESET _u(0x000) +#define M0PLUS_ICSR_VECTPENDING_BITS _u(0x001ff000) +#define M0PLUS_ICSR_VECTPENDING_MSB _u(20) +#define M0PLUS_ICSR_VECTPENDING_LSB _u(12) +#define M0PLUS_ICSR_VECTPENDING_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_ICSR_VECTACTIVE +// Description : Active exception number field. Reset clears the VECTACTIVE +// field. +#define M0PLUS_ICSR_VECTACTIVE_RESET _u(0x000) +#define M0PLUS_ICSR_VECTACTIVE_BITS _u(0x000001ff) +#define M0PLUS_ICSR_VECTACTIVE_MSB _u(8) +#define M0PLUS_ICSR_VECTACTIVE_LSB _u(0) +#define M0PLUS_ICSR_VECTACTIVE_ACCESS "RO" +// ============================================================================= +// Register : M0PLUS_VTOR +// Description : The VTOR holds the vector table offset address. +#define M0PLUS_VTOR_OFFSET _u(0x0000ed08) +#define M0PLUS_VTOR_BITS _u(0xffffff00) +#define M0PLUS_VTOR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_VTOR_TBLOFF +// Description : Bits [31:8] of the indicate the vector table offset address. +#define M0PLUS_VTOR_TBLOFF_RESET _u(0x000000) +#define M0PLUS_VTOR_TBLOFF_BITS _u(0xffffff00) +#define M0PLUS_VTOR_TBLOFF_MSB _u(31) +#define M0PLUS_VTOR_TBLOFF_LSB _u(8) +#define M0PLUS_VTOR_TBLOFF_ACCESS "RW" +// ============================================================================= +// Register : M0PLUS_AIRCR +// Description : Use the Application Interrupt and Reset Control Register to: +// determine data endianness, clear all active state information +// from debug halt mode, request a system reset. +#define M0PLUS_AIRCR_OFFSET _u(0x0000ed0c) +#define M0PLUS_AIRCR_BITS _u(0xffff8006) +#define M0PLUS_AIRCR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_AIRCR_VECTKEY +// Description : Register key: +// Reads as Unknown +// On writes, write 0x05FA to VECTKEY, otherwise the write is +// ignored. +#define M0PLUS_AIRCR_VECTKEY_RESET _u(0x0000) +#define M0PLUS_AIRCR_VECTKEY_BITS _u(0xffff0000) +#define M0PLUS_AIRCR_VECTKEY_MSB _u(31) +#define M0PLUS_AIRCR_VECTKEY_LSB _u(16) +#define M0PLUS_AIRCR_VECTKEY_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_AIRCR_ENDIANESS +// Description : Data endianness implemented: +// 0 = Little-endian. +#define M0PLUS_AIRCR_ENDIANESS_RESET _u(0x0) +#define M0PLUS_AIRCR_ENDIANESS_BITS _u(0x00008000) +#define M0PLUS_AIRCR_ENDIANESS_MSB _u(15) +#define M0PLUS_AIRCR_ENDIANESS_LSB _u(15) +#define M0PLUS_AIRCR_ENDIANESS_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_AIRCR_SYSRESETREQ +// Description : Writing 1 to this bit causes the SYSRESETREQ signal to the +// outer system to be asserted to request a reset. The intention +// is to force a large system reset of all major components except +// for debug. The C_HALT bit in the DHCSR is cleared as a result +// of the system reset requested. The debugger does not lose +// contact with the device. +#define M0PLUS_AIRCR_SYSRESETREQ_RESET _u(0x0) +#define M0PLUS_AIRCR_SYSRESETREQ_BITS _u(0x00000004) +#define M0PLUS_AIRCR_SYSRESETREQ_MSB _u(2) +#define M0PLUS_AIRCR_SYSRESETREQ_LSB _u(2) +#define M0PLUS_AIRCR_SYSRESETREQ_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_AIRCR_VECTCLRACTIVE +// Description : Clears all active state information for fixed and configurable +// exceptions. This bit: is self-clearing, can only be set by the +// DAP when the core is halted. When set: clears all active +// exception status of the processor, forces a return to Thread +// mode, forces an IPSR of 0. A debugger must re-initialize the +// stack. +#define M0PLUS_AIRCR_VECTCLRACTIVE_RESET _u(0x0) +#define M0PLUS_AIRCR_VECTCLRACTIVE_BITS _u(0x00000002) +#define M0PLUS_AIRCR_VECTCLRACTIVE_MSB _u(1) +#define M0PLUS_AIRCR_VECTCLRACTIVE_LSB _u(1) +#define M0PLUS_AIRCR_VECTCLRACTIVE_ACCESS "RW" +// ============================================================================= +// Register : M0PLUS_SCR +// Description : System Control Register. Use the System Control Register for +// power-management functions: signal to the system when the +// processor can enter a low power state, control how the +// processor enters and exits low power states. +#define M0PLUS_SCR_OFFSET _u(0x0000ed10) +#define M0PLUS_SCR_BITS _u(0x00000016) +#define M0PLUS_SCR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_SCR_SEVONPEND +// Description : Send Event on Pending bit: +// 0 = Only enabled interrupts or events can wakeup the processor, +// disabled interrupts are excluded. +// 1 = Enabled events and all interrupts, including disabled +// interrupts, can wakeup the processor. +// When an event or interrupt becomes pending, the event signal +// wakes up the processor from WFE. If the +// processor is not waiting for an event, the event is registered +// and affects the next WFE. +// The processor also wakes up on execution of an SEV instruction +// or an external event. +#define M0PLUS_SCR_SEVONPEND_RESET _u(0x0) +#define M0PLUS_SCR_SEVONPEND_BITS _u(0x00000010) +#define M0PLUS_SCR_SEVONPEND_MSB _u(4) +#define M0PLUS_SCR_SEVONPEND_LSB _u(4) +#define M0PLUS_SCR_SEVONPEND_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_SCR_SLEEPDEEP +// Description : Controls whether the processor uses sleep or deep sleep as its +// low power mode: +// 0 = Sleep. +// 1 = Deep sleep. +#define M0PLUS_SCR_SLEEPDEEP_RESET _u(0x0) +#define M0PLUS_SCR_SLEEPDEEP_BITS _u(0x00000004) +#define M0PLUS_SCR_SLEEPDEEP_MSB _u(2) +#define M0PLUS_SCR_SLEEPDEEP_LSB _u(2) +#define M0PLUS_SCR_SLEEPDEEP_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_SCR_SLEEPONEXIT +// Description : Indicates sleep-on-exit when returning from Handler mode to +// Thread mode: +// 0 = Do not sleep when returning to Thread mode. +// 1 = Enter sleep, or deep sleep, on return from an ISR to Thread +// mode. +// Setting this bit to 1 enables an interrupt driven application +// to avoid returning to an empty main application. +#define M0PLUS_SCR_SLEEPONEXIT_RESET _u(0x0) +#define M0PLUS_SCR_SLEEPONEXIT_BITS _u(0x00000002) +#define M0PLUS_SCR_SLEEPONEXIT_MSB _u(1) +#define M0PLUS_SCR_SLEEPONEXIT_LSB _u(1) +#define M0PLUS_SCR_SLEEPONEXIT_ACCESS "RW" +// ============================================================================= +// Register : M0PLUS_CCR +// Description : The Configuration and Control Register permanently enables +// stack alignment and causes unaligned accesses to result in a +// Hard Fault. +#define M0PLUS_CCR_OFFSET _u(0x0000ed14) +#define M0PLUS_CCR_BITS _u(0x00000208) +#define M0PLUS_CCR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_CCR_STKALIGN +// Description : Always reads as one, indicates 8-byte stack alignment on +// exception entry. On exception entry, the processor uses bit[9] +// of the stacked PSR to indicate the stack alignment. On return +// from the exception it uses this stacked bit to restore the +// correct stack alignment. +#define M0PLUS_CCR_STKALIGN_RESET _u(0x0) +#define M0PLUS_CCR_STKALIGN_BITS _u(0x00000200) +#define M0PLUS_CCR_STKALIGN_MSB _u(9) +#define M0PLUS_CCR_STKALIGN_LSB _u(9) +#define M0PLUS_CCR_STKALIGN_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_CCR_UNALIGN_TRP +// Description : Always reads as one, indicates that all unaligned accesses +// generate a HardFault. +#define M0PLUS_CCR_UNALIGN_TRP_RESET _u(0x0) +#define M0PLUS_CCR_UNALIGN_TRP_BITS _u(0x00000008) +#define M0PLUS_CCR_UNALIGN_TRP_MSB _u(3) +#define M0PLUS_CCR_UNALIGN_TRP_LSB _u(3) +#define M0PLUS_CCR_UNALIGN_TRP_ACCESS "RO" +// ============================================================================= +// Register : M0PLUS_SHPR2 +// Description : System handlers are a special class of exception handler that +// can have their priority set to any of the priority levels. Use +// the System Handler Priority Register 2 to set the priority of +// SVCall. +#define M0PLUS_SHPR2_OFFSET _u(0x0000ed1c) +#define M0PLUS_SHPR2_BITS _u(0xc0000000) +#define M0PLUS_SHPR2_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_SHPR2_PRI_11 +// Description : Priority of system handler 11, SVCall +#define M0PLUS_SHPR2_PRI_11_RESET _u(0x0) +#define M0PLUS_SHPR2_PRI_11_BITS _u(0xc0000000) +#define M0PLUS_SHPR2_PRI_11_MSB _u(31) +#define M0PLUS_SHPR2_PRI_11_LSB _u(30) +#define M0PLUS_SHPR2_PRI_11_ACCESS "RW" +// ============================================================================= +// Register : M0PLUS_SHPR3 +// Description : System handlers are a special class of exception handler that +// can have their priority set to any of the priority levels. Use +// the System Handler Priority Register 3 to set the priority of +// PendSV and SysTick. +#define M0PLUS_SHPR3_OFFSET _u(0x0000ed20) +#define M0PLUS_SHPR3_BITS _u(0xc0c00000) +#define M0PLUS_SHPR3_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_SHPR3_PRI_15 +// Description : Priority of system handler 15, SysTick +#define M0PLUS_SHPR3_PRI_15_RESET _u(0x0) +#define M0PLUS_SHPR3_PRI_15_BITS _u(0xc0000000) +#define M0PLUS_SHPR3_PRI_15_MSB _u(31) +#define M0PLUS_SHPR3_PRI_15_LSB _u(30) +#define M0PLUS_SHPR3_PRI_15_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_SHPR3_PRI_14 +// Description : Priority of system handler 14, PendSV +#define M0PLUS_SHPR3_PRI_14_RESET _u(0x0) +#define M0PLUS_SHPR3_PRI_14_BITS _u(0x00c00000) +#define M0PLUS_SHPR3_PRI_14_MSB _u(23) +#define M0PLUS_SHPR3_PRI_14_LSB _u(22) +#define M0PLUS_SHPR3_PRI_14_ACCESS "RW" +// ============================================================================= +// Register : M0PLUS_SHCSR +// Description : Use the System Handler Control and State Register to determine +// or clear the pending status of SVCall. +#define M0PLUS_SHCSR_OFFSET _u(0x0000ed24) +#define M0PLUS_SHCSR_BITS _u(0x00008000) +#define M0PLUS_SHCSR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_SHCSR_SVCALLPENDED +// Description : Reads as 1 if SVCall is Pending. Write 1 to set pending +// SVCall, write 0 to clear pending SVCall. +#define M0PLUS_SHCSR_SVCALLPENDED_RESET _u(0x0) +#define M0PLUS_SHCSR_SVCALLPENDED_BITS _u(0x00008000) +#define M0PLUS_SHCSR_SVCALLPENDED_MSB _u(15) +#define M0PLUS_SHCSR_SVCALLPENDED_LSB _u(15) +#define M0PLUS_SHCSR_SVCALLPENDED_ACCESS "RW" +// ============================================================================= +// Register : M0PLUS_MPU_TYPE +// Description : Read the MPU Type Register to determine if the processor +// implements an MPU, and how many regions the MPU supports. +#define M0PLUS_MPU_TYPE_OFFSET _u(0x0000ed90) +#define M0PLUS_MPU_TYPE_BITS _u(0x00ffff01) +#define M0PLUS_MPU_TYPE_RESET _u(0x00000800) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_MPU_TYPE_IREGION +// Description : Instruction region. Reads as zero as ARMv6-M only supports a +// unified MPU. +#define M0PLUS_MPU_TYPE_IREGION_RESET _u(0x00) +#define M0PLUS_MPU_TYPE_IREGION_BITS _u(0x00ff0000) +#define M0PLUS_MPU_TYPE_IREGION_MSB _u(23) +#define M0PLUS_MPU_TYPE_IREGION_LSB _u(16) +#define M0PLUS_MPU_TYPE_IREGION_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_MPU_TYPE_DREGION +// Description : Number of regions supported by the MPU. +#define M0PLUS_MPU_TYPE_DREGION_RESET _u(0x08) +#define M0PLUS_MPU_TYPE_DREGION_BITS _u(0x0000ff00) +#define M0PLUS_MPU_TYPE_DREGION_MSB _u(15) +#define M0PLUS_MPU_TYPE_DREGION_LSB _u(8) +#define M0PLUS_MPU_TYPE_DREGION_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_MPU_TYPE_SEPARATE +// Description : Indicates support for separate instruction and data address +// maps. Reads as 0 as ARMv6-M only supports a unified MPU. +#define M0PLUS_MPU_TYPE_SEPARATE_RESET _u(0x0) +#define M0PLUS_MPU_TYPE_SEPARATE_BITS _u(0x00000001) +#define M0PLUS_MPU_TYPE_SEPARATE_MSB _u(0) +#define M0PLUS_MPU_TYPE_SEPARATE_LSB _u(0) +#define M0PLUS_MPU_TYPE_SEPARATE_ACCESS "RO" +// ============================================================================= +// Register : M0PLUS_MPU_CTRL +// Description : Use the MPU Control Register to enable and disable the MPU, and +// to control whether the default memory map is enabled as a +// background region for privileged accesses, and whether the MPU +// is enabled for HardFaults and NMIs. +#define M0PLUS_MPU_CTRL_OFFSET _u(0x0000ed94) +#define M0PLUS_MPU_CTRL_BITS _u(0x00000007) +#define M0PLUS_MPU_CTRL_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_MPU_CTRL_PRIVDEFENA +// Description : Controls whether the default memory map is enabled as a +// background region for privileged accesses. This bit is ignored +// when ENABLE is clear. +// 0 = If the MPU is enabled, disables use of the default memory +// map. Any memory access to a location not +// covered by any enabled region causes a fault. +// 1 = If the MPU is enabled, enables use of the default memory +// map as a background region for privileged software accesses. +// When enabled, the background region acts as if it is region +// number -1. Any region that is defined and enabled has priority +// over this default map. +#define M0PLUS_MPU_CTRL_PRIVDEFENA_RESET _u(0x0) +#define M0PLUS_MPU_CTRL_PRIVDEFENA_BITS _u(0x00000004) +#define M0PLUS_MPU_CTRL_PRIVDEFENA_MSB _u(2) +#define M0PLUS_MPU_CTRL_PRIVDEFENA_LSB _u(2) +#define M0PLUS_MPU_CTRL_PRIVDEFENA_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_MPU_CTRL_HFNMIENA +// Description : Controls the use of the MPU for HardFaults and NMIs. Setting +// this bit when ENABLE is clear results in UNPREDICTABLE +// behaviour. +// When the MPU is enabled: +// 0 = MPU is disabled during HardFault and NMI handlers, +// regardless of the value of the ENABLE bit. +// 1 = the MPU is enabled during HardFault and NMI handlers. +#define M0PLUS_MPU_CTRL_HFNMIENA_RESET _u(0x0) +#define M0PLUS_MPU_CTRL_HFNMIENA_BITS _u(0x00000002) +#define M0PLUS_MPU_CTRL_HFNMIENA_MSB _u(1) +#define M0PLUS_MPU_CTRL_HFNMIENA_LSB _u(1) +#define M0PLUS_MPU_CTRL_HFNMIENA_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_MPU_CTRL_ENABLE +// Description : Enables the MPU. If the MPU is disabled, privileged and +// unprivileged accesses use the default memory map. +// 0 = MPU disabled. +// 1 = MPU enabled. +#define M0PLUS_MPU_CTRL_ENABLE_RESET _u(0x0) +#define M0PLUS_MPU_CTRL_ENABLE_BITS _u(0x00000001) +#define M0PLUS_MPU_CTRL_ENABLE_MSB _u(0) +#define M0PLUS_MPU_CTRL_ENABLE_LSB _u(0) +#define M0PLUS_MPU_CTRL_ENABLE_ACCESS "RW" +// ============================================================================= +// Register : M0PLUS_MPU_RNR +// Description : Use the MPU Region Number Register to select the region +// currently accessed by MPU_RBAR and MPU_RASR. +#define M0PLUS_MPU_RNR_OFFSET _u(0x0000ed98) +#define M0PLUS_MPU_RNR_BITS _u(0x0000000f) +#define M0PLUS_MPU_RNR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_MPU_RNR_REGION +// Description : Indicates the MPU region referenced by the MPU_RBAR and +// MPU_RASR registers. +// The MPU supports 8 memory regions, so the permitted values of +// this field are 0-7. +#define M0PLUS_MPU_RNR_REGION_RESET _u(0x0) +#define M0PLUS_MPU_RNR_REGION_BITS _u(0x0000000f) +#define M0PLUS_MPU_RNR_REGION_MSB _u(3) +#define M0PLUS_MPU_RNR_REGION_LSB _u(0) +#define M0PLUS_MPU_RNR_REGION_ACCESS "RW" +// ============================================================================= +// Register : M0PLUS_MPU_RBAR +// Description : Read the MPU Region Base Address Register to determine the base +// address of the region identified by MPU_RNR. Write to update +// the base address of said region or that of a specified region, +// with whose number MPU_RNR will also be updated. +#define M0PLUS_MPU_RBAR_OFFSET _u(0x0000ed9c) +#define M0PLUS_MPU_RBAR_BITS _u(0xffffff1f) +#define M0PLUS_MPU_RBAR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_MPU_RBAR_ADDR +// Description : Base address of the region. +#define M0PLUS_MPU_RBAR_ADDR_RESET _u(0x000000) +#define M0PLUS_MPU_RBAR_ADDR_BITS _u(0xffffff00) +#define M0PLUS_MPU_RBAR_ADDR_MSB _u(31) +#define M0PLUS_MPU_RBAR_ADDR_LSB _u(8) +#define M0PLUS_MPU_RBAR_ADDR_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_MPU_RBAR_VALID +// Description : On writes, indicates whether the write must update the base +// address of the region identified by the REGION field, updating +// the MPU_RNR to indicate this new region. +// Write: +// 0 = MPU_RNR not changed, and the processor: +// Updates the base address for the region specified in the +// MPU_RNR. +// Ignores the value of the REGION field. +// 1 = The processor: +// Updates the value of the MPU_RNR to the value of the REGION +// field. +// Updates the base address for the region specified in the REGION +// field. +// Always reads as zero. +#define M0PLUS_MPU_RBAR_VALID_RESET _u(0x0) +#define M0PLUS_MPU_RBAR_VALID_BITS _u(0x00000010) +#define M0PLUS_MPU_RBAR_VALID_MSB _u(4) +#define M0PLUS_MPU_RBAR_VALID_LSB _u(4) +#define M0PLUS_MPU_RBAR_VALID_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_MPU_RBAR_REGION +// Description : On writes, specifies the number of the region whose base +// address to update provided VALID is set written as 1. On reads, +// returns bits [3:0] of MPU_RNR. +#define M0PLUS_MPU_RBAR_REGION_RESET _u(0x0) +#define M0PLUS_MPU_RBAR_REGION_BITS _u(0x0000000f) +#define M0PLUS_MPU_RBAR_REGION_MSB _u(3) +#define M0PLUS_MPU_RBAR_REGION_LSB _u(0) +#define M0PLUS_MPU_RBAR_REGION_ACCESS "RW" +// ============================================================================= +// Register : M0PLUS_MPU_RASR +// Description : Use the MPU Region Attribute and Size Register to define the +// size, access behaviour and memory type of the region identified +// by MPU_RNR, and enable that region. +#define M0PLUS_MPU_RASR_OFFSET _u(0x0000eda0) +#define M0PLUS_MPU_RASR_BITS _u(0xffffff3f) +#define M0PLUS_MPU_RASR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : M0PLUS_MPU_RASR_ATTRS +// Description : The MPU Region Attribute field. Use to define the region +// attribute control. +// 28 = XN: Instruction access disable bit: +// 0 = Instruction fetches enabled. +// 1 = Instruction fetches disabled. +// 26:24 = AP: Access permission field +// 18 = S: Shareable bit +// 17 = C: Cacheable bit +// 16 = B: Bufferable bit +#define M0PLUS_MPU_RASR_ATTRS_RESET _u(0x0000) +#define M0PLUS_MPU_RASR_ATTRS_BITS _u(0xffff0000) +#define M0PLUS_MPU_RASR_ATTRS_MSB _u(31) +#define M0PLUS_MPU_RASR_ATTRS_LSB _u(16) +#define M0PLUS_MPU_RASR_ATTRS_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_MPU_RASR_SRD +// Description : Subregion Disable. For regions of 256 bytes or larger, each bit +// of this field controls whether one of the eight equal +// subregions is enabled. +#define M0PLUS_MPU_RASR_SRD_RESET _u(0x00) +#define M0PLUS_MPU_RASR_SRD_BITS _u(0x0000ff00) +#define M0PLUS_MPU_RASR_SRD_MSB _u(15) +#define M0PLUS_MPU_RASR_SRD_LSB _u(8) +#define M0PLUS_MPU_RASR_SRD_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_MPU_RASR_SIZE +// Description : Indicates the region size. Region size in bytes = 2^(SIZE+1). +// The minimum permitted value is 7 (b00111) = 256Bytes +#define M0PLUS_MPU_RASR_SIZE_RESET _u(0x00) +#define M0PLUS_MPU_RASR_SIZE_BITS _u(0x0000003e) +#define M0PLUS_MPU_RASR_SIZE_MSB _u(5) +#define M0PLUS_MPU_RASR_SIZE_LSB _u(1) +#define M0PLUS_MPU_RASR_SIZE_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : M0PLUS_MPU_RASR_ENABLE +// Description : Enables the region. +#define M0PLUS_MPU_RASR_ENABLE_RESET _u(0x0) +#define M0PLUS_MPU_RASR_ENABLE_BITS _u(0x00000001) +#define M0PLUS_MPU_RASR_ENABLE_MSB _u(0) +#define M0PLUS_MPU_RASR_ENABLE_LSB _u(0) +#define M0PLUS_MPU_RASR_ENABLE_ACCESS "RW" +// ============================================================================= +#endif // HARDWARE_REGS_M0PLUS_DEFINED diff --git a/src/bootroms/shared/pads_qspi.h b/src/bootroms/shared/pads_qspi.h new file mode 100644 index 0000000..b3a09e9 --- /dev/null +++ b/src/bootroms/shared/pads_qspi.h @@ -0,0 +1,454 @@ +/** + * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +// ============================================================================= +// Register block : PADS_QSPI +// Version : 1 +// Bus type : apb +// Description : None +// ============================================================================= +#ifndef HARDWARE_REGS_PADS_QSPI_DEFINED +#define HARDWARE_REGS_PADS_QSPI_DEFINED +// ============================================================================= +// Register : PADS_QSPI_VOLTAGE_SELECT +// Description : Voltage select. Per bank control +// 0x0 -> Set voltage to 3.3V (DVDD >= 2V5) +// 0x1 -> Set voltage to 1.8V (DVDD <= 1V8) +#define PADS_QSPI_VOLTAGE_SELECT_OFFSET _u(0x00000000) +#define PADS_QSPI_VOLTAGE_SELECT_BITS _u(0x00000001) +#define PADS_QSPI_VOLTAGE_SELECT_RESET _u(0x00000000) +#define PADS_QSPI_VOLTAGE_SELECT_MSB _u(0) +#define PADS_QSPI_VOLTAGE_SELECT_LSB _u(0) +#define PADS_QSPI_VOLTAGE_SELECT_ACCESS "RW" +#define PADS_QSPI_VOLTAGE_SELECT_VALUE_3V3 _u(0x0) +#define PADS_QSPI_VOLTAGE_SELECT_VALUE_1V8 _u(0x1) +// ============================================================================= +// Register : PADS_QSPI_GPIO_QSPI_SCLK +// Description : Pad control register +#define PADS_QSPI_GPIO_QSPI_SCLK_OFFSET _u(0x00000004) +#define PADS_QSPI_GPIO_QSPI_SCLK_BITS _u(0x000000ff) +#define PADS_QSPI_GPIO_QSPI_SCLK_RESET _u(0x00000056) +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SCLK_OD +// Description : Output disable. Has priority over output enable from +// peripherals +#define PADS_QSPI_GPIO_QSPI_SCLK_OD_RESET _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SCLK_OD_BITS _u(0x00000080) +#define PADS_QSPI_GPIO_QSPI_SCLK_OD_MSB _u(7) +#define PADS_QSPI_GPIO_QSPI_SCLK_OD_LSB _u(7) +#define PADS_QSPI_GPIO_QSPI_SCLK_OD_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SCLK_IE +// Description : Input enable +#define PADS_QSPI_GPIO_QSPI_SCLK_IE_RESET _u(0x1) +#define PADS_QSPI_GPIO_QSPI_SCLK_IE_BITS _u(0x00000040) +#define PADS_QSPI_GPIO_QSPI_SCLK_IE_MSB _u(6) +#define PADS_QSPI_GPIO_QSPI_SCLK_IE_LSB _u(6) +#define PADS_QSPI_GPIO_QSPI_SCLK_IE_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SCLK_DRIVE +// Description : Drive strength. +// 0x0 -> 2mA +// 0x1 -> 4mA +// 0x2 -> 8mA +// 0x3 -> 12mA +#define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_RESET _u(0x1) +#define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_BITS _u(0x00000030) +#define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_MSB _u(5) +#define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_LSB _u(4) +#define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_ACCESS "RW" +#define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_VALUE_2MA _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_VALUE_4MA _u(0x1) +#define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_VALUE_8MA _u(0x2) +#define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_VALUE_12MA _u(0x3) +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SCLK_PUE +// Description : Pull up enable +#define PADS_QSPI_GPIO_QSPI_SCLK_PUE_RESET _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SCLK_PUE_BITS _u(0x00000008) +#define PADS_QSPI_GPIO_QSPI_SCLK_PUE_MSB _u(3) +#define PADS_QSPI_GPIO_QSPI_SCLK_PUE_LSB _u(3) +#define PADS_QSPI_GPIO_QSPI_SCLK_PUE_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SCLK_PDE +// Description : Pull down enable +#define PADS_QSPI_GPIO_QSPI_SCLK_PDE_RESET _u(0x1) +#define PADS_QSPI_GPIO_QSPI_SCLK_PDE_BITS _u(0x00000004) +#define PADS_QSPI_GPIO_QSPI_SCLK_PDE_MSB _u(2) +#define PADS_QSPI_GPIO_QSPI_SCLK_PDE_LSB _u(2) +#define PADS_QSPI_GPIO_QSPI_SCLK_PDE_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SCLK_SCHMITT +// Description : Enable schmitt trigger +#define PADS_QSPI_GPIO_QSPI_SCLK_SCHMITT_RESET _u(0x1) +#define PADS_QSPI_GPIO_QSPI_SCLK_SCHMITT_BITS _u(0x00000002) +#define PADS_QSPI_GPIO_QSPI_SCLK_SCHMITT_MSB _u(1) +#define PADS_QSPI_GPIO_QSPI_SCLK_SCHMITT_LSB _u(1) +#define PADS_QSPI_GPIO_QSPI_SCLK_SCHMITT_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST +// Description : Slew rate control. 1 = Fast, 0 = Slow +#define PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST_RESET _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST_BITS _u(0x00000001) +#define PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST_MSB _u(0) +#define PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST_LSB _u(0) +#define PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST_ACCESS "RW" +// ============================================================================= +// Register : PADS_QSPI_GPIO_QSPI_SD0 +// Description : Pad control register +#define PADS_QSPI_GPIO_QSPI_SD0_OFFSET _u(0x00000008) +#define PADS_QSPI_GPIO_QSPI_SD0_BITS _u(0x000000ff) +#define PADS_QSPI_GPIO_QSPI_SD0_RESET _u(0x00000052) +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD0_OD +// Description : Output disable. Has priority over output enable from +// peripherals +#define PADS_QSPI_GPIO_QSPI_SD0_OD_RESET _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SD0_OD_BITS _u(0x00000080) +#define PADS_QSPI_GPIO_QSPI_SD0_OD_MSB _u(7) +#define PADS_QSPI_GPIO_QSPI_SD0_OD_LSB _u(7) +#define PADS_QSPI_GPIO_QSPI_SD0_OD_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD0_IE +// Description : Input enable +#define PADS_QSPI_GPIO_QSPI_SD0_IE_RESET _u(0x1) +#define PADS_QSPI_GPIO_QSPI_SD0_IE_BITS _u(0x00000040) +#define PADS_QSPI_GPIO_QSPI_SD0_IE_MSB _u(6) +#define PADS_QSPI_GPIO_QSPI_SD0_IE_LSB _u(6) +#define PADS_QSPI_GPIO_QSPI_SD0_IE_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD0_DRIVE +// Description : Drive strength. +// 0x0 -> 2mA +// 0x1 -> 4mA +// 0x2 -> 8mA +// 0x3 -> 12mA +#define PADS_QSPI_GPIO_QSPI_SD0_DRIVE_RESET _u(0x1) +#define PADS_QSPI_GPIO_QSPI_SD0_DRIVE_BITS _u(0x00000030) +#define PADS_QSPI_GPIO_QSPI_SD0_DRIVE_MSB _u(5) +#define PADS_QSPI_GPIO_QSPI_SD0_DRIVE_LSB _u(4) +#define PADS_QSPI_GPIO_QSPI_SD0_DRIVE_ACCESS "RW" +#define PADS_QSPI_GPIO_QSPI_SD0_DRIVE_VALUE_2MA _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SD0_DRIVE_VALUE_4MA _u(0x1) +#define PADS_QSPI_GPIO_QSPI_SD0_DRIVE_VALUE_8MA _u(0x2) +#define PADS_QSPI_GPIO_QSPI_SD0_DRIVE_VALUE_12MA _u(0x3) +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD0_PUE +// Description : Pull up enable +#define PADS_QSPI_GPIO_QSPI_SD0_PUE_RESET _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SD0_PUE_BITS _u(0x00000008) +#define PADS_QSPI_GPIO_QSPI_SD0_PUE_MSB _u(3) +#define PADS_QSPI_GPIO_QSPI_SD0_PUE_LSB _u(3) +#define PADS_QSPI_GPIO_QSPI_SD0_PUE_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD0_PDE +// Description : Pull down enable +#define PADS_QSPI_GPIO_QSPI_SD0_PDE_RESET _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SD0_PDE_BITS _u(0x00000004) +#define PADS_QSPI_GPIO_QSPI_SD0_PDE_MSB _u(2) +#define PADS_QSPI_GPIO_QSPI_SD0_PDE_LSB _u(2) +#define PADS_QSPI_GPIO_QSPI_SD0_PDE_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD0_SCHMITT +// Description : Enable schmitt trigger +#define PADS_QSPI_GPIO_QSPI_SD0_SCHMITT_RESET _u(0x1) +#define PADS_QSPI_GPIO_QSPI_SD0_SCHMITT_BITS _u(0x00000002) +#define PADS_QSPI_GPIO_QSPI_SD0_SCHMITT_MSB _u(1) +#define PADS_QSPI_GPIO_QSPI_SD0_SCHMITT_LSB _u(1) +#define PADS_QSPI_GPIO_QSPI_SD0_SCHMITT_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD0_SLEWFAST +// Description : Slew rate control. 1 = Fast, 0 = Slow +#define PADS_QSPI_GPIO_QSPI_SD0_SLEWFAST_RESET _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SD0_SLEWFAST_BITS _u(0x00000001) +#define PADS_QSPI_GPIO_QSPI_SD0_SLEWFAST_MSB _u(0) +#define PADS_QSPI_GPIO_QSPI_SD0_SLEWFAST_LSB _u(0) +#define PADS_QSPI_GPIO_QSPI_SD0_SLEWFAST_ACCESS "RW" +// ============================================================================= +// Register : PADS_QSPI_GPIO_QSPI_SD1 +// Description : Pad control register +#define PADS_QSPI_GPIO_QSPI_SD1_OFFSET _u(0x0000000c) +#define PADS_QSPI_GPIO_QSPI_SD1_BITS _u(0x000000ff) +#define PADS_QSPI_GPIO_QSPI_SD1_RESET _u(0x00000052) +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD1_OD +// Description : Output disable. Has priority over output enable from +// peripherals +#define PADS_QSPI_GPIO_QSPI_SD1_OD_RESET _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SD1_OD_BITS _u(0x00000080) +#define PADS_QSPI_GPIO_QSPI_SD1_OD_MSB _u(7) +#define PADS_QSPI_GPIO_QSPI_SD1_OD_LSB _u(7) +#define PADS_QSPI_GPIO_QSPI_SD1_OD_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD1_IE +// Description : Input enable +#define PADS_QSPI_GPIO_QSPI_SD1_IE_RESET _u(0x1) +#define PADS_QSPI_GPIO_QSPI_SD1_IE_BITS _u(0x00000040) +#define PADS_QSPI_GPIO_QSPI_SD1_IE_MSB _u(6) +#define PADS_QSPI_GPIO_QSPI_SD1_IE_LSB _u(6) +#define PADS_QSPI_GPIO_QSPI_SD1_IE_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD1_DRIVE +// Description : Drive strength. +// 0x0 -> 2mA +// 0x1 -> 4mA +// 0x2 -> 8mA +// 0x3 -> 12mA +#define PADS_QSPI_GPIO_QSPI_SD1_DRIVE_RESET _u(0x1) +#define PADS_QSPI_GPIO_QSPI_SD1_DRIVE_BITS _u(0x00000030) +#define PADS_QSPI_GPIO_QSPI_SD1_DRIVE_MSB _u(5) +#define PADS_QSPI_GPIO_QSPI_SD1_DRIVE_LSB _u(4) +#define PADS_QSPI_GPIO_QSPI_SD1_DRIVE_ACCESS "RW" +#define PADS_QSPI_GPIO_QSPI_SD1_DRIVE_VALUE_2MA _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SD1_DRIVE_VALUE_4MA _u(0x1) +#define PADS_QSPI_GPIO_QSPI_SD1_DRIVE_VALUE_8MA _u(0x2) +#define PADS_QSPI_GPIO_QSPI_SD1_DRIVE_VALUE_12MA _u(0x3) +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD1_PUE +// Description : Pull up enable +#define PADS_QSPI_GPIO_QSPI_SD1_PUE_RESET _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SD1_PUE_BITS _u(0x00000008) +#define PADS_QSPI_GPIO_QSPI_SD1_PUE_MSB _u(3) +#define PADS_QSPI_GPIO_QSPI_SD1_PUE_LSB _u(3) +#define PADS_QSPI_GPIO_QSPI_SD1_PUE_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD1_PDE +// Description : Pull down enable +#define PADS_QSPI_GPIO_QSPI_SD1_PDE_RESET _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SD1_PDE_BITS _u(0x00000004) +#define PADS_QSPI_GPIO_QSPI_SD1_PDE_MSB _u(2) +#define PADS_QSPI_GPIO_QSPI_SD1_PDE_LSB _u(2) +#define PADS_QSPI_GPIO_QSPI_SD1_PDE_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD1_SCHMITT +// Description : Enable schmitt trigger +#define PADS_QSPI_GPIO_QSPI_SD1_SCHMITT_RESET _u(0x1) +#define PADS_QSPI_GPIO_QSPI_SD1_SCHMITT_BITS _u(0x00000002) +#define PADS_QSPI_GPIO_QSPI_SD1_SCHMITT_MSB _u(1) +#define PADS_QSPI_GPIO_QSPI_SD1_SCHMITT_LSB _u(1) +#define PADS_QSPI_GPIO_QSPI_SD1_SCHMITT_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD1_SLEWFAST +// Description : Slew rate control. 1 = Fast, 0 = Slow +#define PADS_QSPI_GPIO_QSPI_SD1_SLEWFAST_RESET _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SD1_SLEWFAST_BITS _u(0x00000001) +#define PADS_QSPI_GPIO_QSPI_SD1_SLEWFAST_MSB _u(0) +#define PADS_QSPI_GPIO_QSPI_SD1_SLEWFAST_LSB _u(0) +#define PADS_QSPI_GPIO_QSPI_SD1_SLEWFAST_ACCESS "RW" +// ============================================================================= +// Register : PADS_QSPI_GPIO_QSPI_SD2 +// Description : Pad control register +#define PADS_QSPI_GPIO_QSPI_SD2_OFFSET _u(0x00000010) +#define PADS_QSPI_GPIO_QSPI_SD2_BITS _u(0x000000ff) +#define PADS_QSPI_GPIO_QSPI_SD2_RESET _u(0x00000052) +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD2_OD +// Description : Output disable. Has priority over output enable from +// peripherals +#define PADS_QSPI_GPIO_QSPI_SD2_OD_RESET _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SD2_OD_BITS _u(0x00000080) +#define PADS_QSPI_GPIO_QSPI_SD2_OD_MSB _u(7) +#define PADS_QSPI_GPIO_QSPI_SD2_OD_LSB _u(7) +#define PADS_QSPI_GPIO_QSPI_SD2_OD_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD2_IE +// Description : Input enable +#define PADS_QSPI_GPIO_QSPI_SD2_IE_RESET _u(0x1) +#define PADS_QSPI_GPIO_QSPI_SD2_IE_BITS _u(0x00000040) +#define PADS_QSPI_GPIO_QSPI_SD2_IE_MSB _u(6) +#define PADS_QSPI_GPIO_QSPI_SD2_IE_LSB _u(6) +#define PADS_QSPI_GPIO_QSPI_SD2_IE_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD2_DRIVE +// Description : Drive strength. +// 0x0 -> 2mA +// 0x1 -> 4mA +// 0x2 -> 8mA +// 0x3 -> 12mA +#define PADS_QSPI_GPIO_QSPI_SD2_DRIVE_RESET _u(0x1) +#define PADS_QSPI_GPIO_QSPI_SD2_DRIVE_BITS _u(0x00000030) +#define PADS_QSPI_GPIO_QSPI_SD2_DRIVE_MSB _u(5) +#define PADS_QSPI_GPIO_QSPI_SD2_DRIVE_LSB _u(4) +#define PADS_QSPI_GPIO_QSPI_SD2_DRIVE_ACCESS "RW" +#define PADS_QSPI_GPIO_QSPI_SD2_DRIVE_VALUE_2MA _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SD2_DRIVE_VALUE_4MA _u(0x1) +#define PADS_QSPI_GPIO_QSPI_SD2_DRIVE_VALUE_8MA _u(0x2) +#define PADS_QSPI_GPIO_QSPI_SD2_DRIVE_VALUE_12MA _u(0x3) +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD2_PUE +// Description : Pull up enable +#define PADS_QSPI_GPIO_QSPI_SD2_PUE_RESET _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SD2_PUE_BITS _u(0x00000008) +#define PADS_QSPI_GPIO_QSPI_SD2_PUE_MSB _u(3) +#define PADS_QSPI_GPIO_QSPI_SD2_PUE_LSB _u(3) +#define PADS_QSPI_GPIO_QSPI_SD2_PUE_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD2_PDE +// Description : Pull down enable +#define PADS_QSPI_GPIO_QSPI_SD2_PDE_RESET _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SD2_PDE_BITS _u(0x00000004) +#define PADS_QSPI_GPIO_QSPI_SD2_PDE_MSB _u(2) +#define PADS_QSPI_GPIO_QSPI_SD2_PDE_LSB _u(2) +#define PADS_QSPI_GPIO_QSPI_SD2_PDE_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD2_SCHMITT +// Description : Enable schmitt trigger +#define PADS_QSPI_GPIO_QSPI_SD2_SCHMITT_RESET _u(0x1) +#define PADS_QSPI_GPIO_QSPI_SD2_SCHMITT_BITS _u(0x00000002) +#define PADS_QSPI_GPIO_QSPI_SD2_SCHMITT_MSB _u(1) +#define PADS_QSPI_GPIO_QSPI_SD2_SCHMITT_LSB _u(1) +#define PADS_QSPI_GPIO_QSPI_SD2_SCHMITT_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD2_SLEWFAST +// Description : Slew rate control. 1 = Fast, 0 = Slow +#define PADS_QSPI_GPIO_QSPI_SD2_SLEWFAST_RESET _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SD2_SLEWFAST_BITS _u(0x00000001) +#define PADS_QSPI_GPIO_QSPI_SD2_SLEWFAST_MSB _u(0) +#define PADS_QSPI_GPIO_QSPI_SD2_SLEWFAST_LSB _u(0) +#define PADS_QSPI_GPIO_QSPI_SD2_SLEWFAST_ACCESS "RW" +// ============================================================================= +// Register : PADS_QSPI_GPIO_QSPI_SD3 +// Description : Pad control register +#define PADS_QSPI_GPIO_QSPI_SD3_OFFSET _u(0x00000014) +#define PADS_QSPI_GPIO_QSPI_SD3_BITS _u(0x000000ff) +#define PADS_QSPI_GPIO_QSPI_SD3_RESET _u(0x00000052) +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD3_OD +// Description : Output disable. Has priority over output enable from +// peripherals +#define PADS_QSPI_GPIO_QSPI_SD3_OD_RESET _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SD3_OD_BITS _u(0x00000080) +#define PADS_QSPI_GPIO_QSPI_SD3_OD_MSB _u(7) +#define PADS_QSPI_GPIO_QSPI_SD3_OD_LSB _u(7) +#define PADS_QSPI_GPIO_QSPI_SD3_OD_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD3_IE +// Description : Input enable +#define PADS_QSPI_GPIO_QSPI_SD3_IE_RESET _u(0x1) +#define PADS_QSPI_GPIO_QSPI_SD3_IE_BITS _u(0x00000040) +#define PADS_QSPI_GPIO_QSPI_SD3_IE_MSB _u(6) +#define PADS_QSPI_GPIO_QSPI_SD3_IE_LSB _u(6) +#define PADS_QSPI_GPIO_QSPI_SD3_IE_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD3_DRIVE +// Description : Drive strength. +// 0x0 -> 2mA +// 0x1 -> 4mA +// 0x2 -> 8mA +// 0x3 -> 12mA +#define PADS_QSPI_GPIO_QSPI_SD3_DRIVE_RESET _u(0x1) +#define PADS_QSPI_GPIO_QSPI_SD3_DRIVE_BITS _u(0x00000030) +#define PADS_QSPI_GPIO_QSPI_SD3_DRIVE_MSB _u(5) +#define PADS_QSPI_GPIO_QSPI_SD3_DRIVE_LSB _u(4) +#define PADS_QSPI_GPIO_QSPI_SD3_DRIVE_ACCESS "RW" +#define PADS_QSPI_GPIO_QSPI_SD3_DRIVE_VALUE_2MA _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SD3_DRIVE_VALUE_4MA _u(0x1) +#define PADS_QSPI_GPIO_QSPI_SD3_DRIVE_VALUE_8MA _u(0x2) +#define PADS_QSPI_GPIO_QSPI_SD3_DRIVE_VALUE_12MA _u(0x3) +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD3_PUE +// Description : Pull up enable +#define PADS_QSPI_GPIO_QSPI_SD3_PUE_RESET _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SD3_PUE_BITS _u(0x00000008) +#define PADS_QSPI_GPIO_QSPI_SD3_PUE_MSB _u(3) +#define PADS_QSPI_GPIO_QSPI_SD3_PUE_LSB _u(3) +#define PADS_QSPI_GPIO_QSPI_SD3_PUE_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD3_PDE +// Description : Pull down enable +#define PADS_QSPI_GPIO_QSPI_SD3_PDE_RESET _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SD3_PDE_BITS _u(0x00000004) +#define PADS_QSPI_GPIO_QSPI_SD3_PDE_MSB _u(2) +#define PADS_QSPI_GPIO_QSPI_SD3_PDE_LSB _u(2) +#define PADS_QSPI_GPIO_QSPI_SD3_PDE_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD3_SCHMITT +// Description : Enable schmitt trigger +#define PADS_QSPI_GPIO_QSPI_SD3_SCHMITT_RESET _u(0x1) +#define PADS_QSPI_GPIO_QSPI_SD3_SCHMITT_BITS _u(0x00000002) +#define PADS_QSPI_GPIO_QSPI_SD3_SCHMITT_MSB _u(1) +#define PADS_QSPI_GPIO_QSPI_SD3_SCHMITT_LSB _u(1) +#define PADS_QSPI_GPIO_QSPI_SD3_SCHMITT_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SD3_SLEWFAST +// Description : Slew rate control. 1 = Fast, 0 = Slow +#define PADS_QSPI_GPIO_QSPI_SD3_SLEWFAST_RESET _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SD3_SLEWFAST_BITS _u(0x00000001) +#define PADS_QSPI_GPIO_QSPI_SD3_SLEWFAST_MSB _u(0) +#define PADS_QSPI_GPIO_QSPI_SD3_SLEWFAST_LSB _u(0) +#define PADS_QSPI_GPIO_QSPI_SD3_SLEWFAST_ACCESS "RW" +// ============================================================================= +// Register : PADS_QSPI_GPIO_QSPI_SS +// Description : Pad control register +#define PADS_QSPI_GPIO_QSPI_SS_OFFSET _u(0x00000018) +#define PADS_QSPI_GPIO_QSPI_SS_BITS _u(0x000000ff) +#define PADS_QSPI_GPIO_QSPI_SS_RESET _u(0x0000005a) +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SS_OD +// Description : Output disable. Has priority over output enable from +// peripherals +#define PADS_QSPI_GPIO_QSPI_SS_OD_RESET _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SS_OD_BITS _u(0x00000080) +#define PADS_QSPI_GPIO_QSPI_SS_OD_MSB _u(7) +#define PADS_QSPI_GPIO_QSPI_SS_OD_LSB _u(7) +#define PADS_QSPI_GPIO_QSPI_SS_OD_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SS_IE +// Description : Input enable +#define PADS_QSPI_GPIO_QSPI_SS_IE_RESET _u(0x1) +#define PADS_QSPI_GPIO_QSPI_SS_IE_BITS _u(0x00000040) +#define PADS_QSPI_GPIO_QSPI_SS_IE_MSB _u(6) +#define PADS_QSPI_GPIO_QSPI_SS_IE_LSB _u(6) +#define PADS_QSPI_GPIO_QSPI_SS_IE_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SS_DRIVE +// Description : Drive strength. +// 0x0 -> 2mA +// 0x1 -> 4mA +// 0x2 -> 8mA +// 0x3 -> 12mA +#define PADS_QSPI_GPIO_QSPI_SS_DRIVE_RESET _u(0x1) +#define PADS_QSPI_GPIO_QSPI_SS_DRIVE_BITS _u(0x00000030) +#define PADS_QSPI_GPIO_QSPI_SS_DRIVE_MSB _u(5) +#define PADS_QSPI_GPIO_QSPI_SS_DRIVE_LSB _u(4) +#define PADS_QSPI_GPIO_QSPI_SS_DRIVE_ACCESS "RW" +#define PADS_QSPI_GPIO_QSPI_SS_DRIVE_VALUE_2MA _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SS_DRIVE_VALUE_4MA _u(0x1) +#define PADS_QSPI_GPIO_QSPI_SS_DRIVE_VALUE_8MA _u(0x2) +#define PADS_QSPI_GPIO_QSPI_SS_DRIVE_VALUE_12MA _u(0x3) +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SS_PUE +// Description : Pull up enable +#define PADS_QSPI_GPIO_QSPI_SS_PUE_RESET _u(0x1) +#define PADS_QSPI_GPIO_QSPI_SS_PUE_BITS _u(0x00000008) +#define PADS_QSPI_GPIO_QSPI_SS_PUE_MSB _u(3) +#define PADS_QSPI_GPIO_QSPI_SS_PUE_LSB _u(3) +#define PADS_QSPI_GPIO_QSPI_SS_PUE_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SS_PDE +// Description : Pull down enable +#define PADS_QSPI_GPIO_QSPI_SS_PDE_RESET _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SS_PDE_BITS _u(0x00000004) +#define PADS_QSPI_GPIO_QSPI_SS_PDE_MSB _u(2) +#define PADS_QSPI_GPIO_QSPI_SS_PDE_LSB _u(2) +#define PADS_QSPI_GPIO_QSPI_SS_PDE_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SS_SCHMITT +// Description : Enable schmitt trigger +#define PADS_QSPI_GPIO_QSPI_SS_SCHMITT_RESET _u(0x1) +#define PADS_QSPI_GPIO_QSPI_SS_SCHMITT_BITS _u(0x00000002) +#define PADS_QSPI_GPIO_QSPI_SS_SCHMITT_MSB _u(1) +#define PADS_QSPI_GPIO_QSPI_SS_SCHMITT_LSB _u(1) +#define PADS_QSPI_GPIO_QSPI_SS_SCHMITT_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : PADS_QSPI_GPIO_QSPI_SS_SLEWFAST +// Description : Slew rate control. 1 = Fast, 0 = Slow +#define PADS_QSPI_GPIO_QSPI_SS_SLEWFAST_RESET _u(0x0) +#define PADS_QSPI_GPIO_QSPI_SS_SLEWFAST_BITS _u(0x00000001) +#define PADS_QSPI_GPIO_QSPI_SS_SLEWFAST_MSB _u(0) +#define PADS_QSPI_GPIO_QSPI_SS_SLEWFAST_LSB _u(0) +#define PADS_QSPI_GPIO_QSPI_SS_SLEWFAST_ACCESS "RW" +// ============================================================================= +#endif // HARDWARE_REGS_PADS_QSPI_DEFINED diff --git a/src/bootroms/shared/read_flash_sreg.S b/src/bootroms/shared/read_flash_sreg.S new file mode 100644 index 0000000..1c68e49 --- /dev/null +++ b/src/bootroms/shared/read_flash_sreg.S @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _BOOT2_HELPER_READ_FLASH_SREG +#define _BOOT2_HELPER_READ_FLASH_SREG + +#include "wait_ssi_ready.S" + +// Pass status read cmd into r0. +// Returns status value in r0. +.global read_flash_sreg +.type read_flash_sreg,%function +.thumb_func +read_flash_sreg: + push {r1, lr} + str r0, [r3, #SSI_DR0_OFFSET] + // Dummy byte: + str r0, [r3, #SSI_DR0_OFFSET] + + bl wait_ssi_ready + // Discard first byte and combine the next two + ldr r0, [r3, #SSI_DR0_OFFSET] + ldr r0, [r3, #SSI_DR0_OFFSET] + + pop {r1, pc} + +#endif diff --git a/src/bootroms/shared/regs.h b/src/bootroms/shared/regs.h new file mode 100644 index 0000000..d2bafd8 --- /dev/null +++ b/src/bootroms/shared/regs.h @@ -0,0 +1,11 @@ +#ifndef RP2040_STAGE2_REGS_H +#define RP2040_STAGE2_REGS_H + +#define _u(x) x ## u + +#include "ssi.h" +#include "pads_qspi.h" +#include "addressmap.h" +#include "m0plus.h" + +#endif // RP2040_STAGE2_REGS_H \ No newline at end of file diff --git a/src/bootroms/shared/ssi.h b/src/bootroms/shared/ssi.h new file mode 100644 index 0000000..67fddc0 --- /dev/null +++ b/src/bootroms/shared/ssi.h @@ -0,0 +1,809 @@ +/** + * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +// ============================================================================= +// Register block : SSI +// Version : 1 +// Bus type : apb +// Description : DW_apb_ssi has the following features: +// * APB interface – Allows for easy integration into a +// DesignWare Synthesizable Components for AMBA 2 +// implementation. +// * APB3 and APB4 protocol support. +// * Scalable APB data bus width – Supports APB data bus widths +// of 8, 16, and 32 bits. +// * Serial-master or serial-slave operation – Enables serial +// communication with serial-master or serial-slave peripheral +// devices. +// * Programmable Dual/Quad/Octal SPI support in Master Mode. +// * Dual Data Rate (DDR) and Read Data Strobe (RDS) Support - +// Enables the DW_apb_ssi master to perform operations with the +// device in DDR and RDS modes when working in Dual/Quad/Octal +// mode of operation. +// * Data Mask Support - Enables the DW_apb_ssi to selectively +// update the bytes in the device. This feature is applicable +// only in enhanced SPI modes. +// * eXecute-In-Place (XIP) support - Enables the DW_apb_ssi +// master to behave as a memory mapped I/O and fetches the data +// from the device based on the APB read request. This feature +// is applicable only in enhanced SPI modes. +// * DMA Controller Interface – Enables the DW_apb_ssi to +// interface to a DMA controller over the bus using a +// handshaking interface for transfer requests. +// * Independent masking of interrupts – Master collision, +// transmit FIFO overflow, transmit FIFO empty, receive FIFO +// full, receive FIFO underflow, and receive FIFO overflow +// interrupts can all be masked independently. +// * Multi-master contention detection – Informs the processor +// of multiple serial-master accesses on the serial bus. +// * Bypass of meta-stability flip-flops for synchronous clocks +// – When the APB clock (pclk) and the DW_apb_ssi serial clock +// (ssi_clk) are synchronous, meta-stable flip-flops are not +// used when transferring control signals across these clock +// domains. +// * Programmable delay on the sample time of the received +// serial data bit (rxd); enables programmable control of +// routing delays resulting in higher serial data-bit rates. +// * Programmable features: +// - Serial interface operation – Choice of Motorola SPI, Texas +// Instruments Synchronous Serial Protocol or National +// Semiconductor Microwire. +// - Clock bit-rate – Dynamic control of the serial bit rate of +// the data transfer; used in only serial-master mode of +// operation. +// - Data Item size (4 to 32 bits) – Item size of each data +// transfer under the control of the programmer. +// * Configured features: +// - FIFO depth – 16 words deep. The FIFO width is fixed at 32 +// bits. +// - 1 slave select output. +// - Hardware slave-select – Dedicated hardware slave-select +// line. +// - Combined interrupt line - one combined interrupt line from +// the DW_apb_ssi to the interrupt controller. +// - Interrupt polarity – active high interrupt lines. +// - Serial clock polarity – low serial-clock polarity directly +// after reset. +// - Serial clock phase – capture on first edge of serial-clock +// directly after reset. +// ============================================================================= +#ifndef HARDWARE_REGS_SSI_DEFINED +#define HARDWARE_REGS_SSI_DEFINED +// ============================================================================= +// Register : SSI_CTRLR0 +// Description : Control register 0 +#define SSI_CTRLR0_OFFSET _u(0x00000000) +#define SSI_CTRLR0_BITS _u(0x017fffff) +#define SSI_CTRLR0_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : SSI_CTRLR0_SSTE +// Description : Slave select toggle enable +#define SSI_CTRLR0_SSTE_RESET _u(0x0) +#define SSI_CTRLR0_SSTE_BITS _u(0x01000000) +#define SSI_CTRLR0_SSTE_MSB _u(24) +#define SSI_CTRLR0_SSTE_LSB _u(24) +#define SSI_CTRLR0_SSTE_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : SSI_CTRLR0_SPI_FRF +// Description : SPI frame format +// 0x0 -> Standard 1-bit SPI frame format; 1 bit per SCK, +// full-duplex +// 0x1 -> Dual-SPI frame format; two bits per SCK, half-duplex +// 0x2 -> Quad-SPI frame format; four bits per SCK, half-duplex +#define SSI_CTRLR0_SPI_FRF_RESET _u(0x0) +#define SSI_CTRLR0_SPI_FRF_BITS _u(0x00600000) +#define SSI_CTRLR0_SPI_FRF_MSB _u(22) +#define SSI_CTRLR0_SPI_FRF_LSB _u(21) +#define SSI_CTRLR0_SPI_FRF_ACCESS "RW" +#define SSI_CTRLR0_SPI_FRF_VALUE_STD _u(0x0) +#define SSI_CTRLR0_SPI_FRF_VALUE_DUAL _u(0x1) +#define SSI_CTRLR0_SPI_FRF_VALUE_QUAD _u(0x2) +// ----------------------------------------------------------------------------- +// Field : SSI_CTRLR0_DFS_32 +// Description : Data frame size in 32b transfer mode +// Value of n -> n+1 clocks per frame. +#define SSI_CTRLR0_DFS_32_RESET _u(0x00) +#define SSI_CTRLR0_DFS_32_BITS _u(0x001f0000) +#define SSI_CTRLR0_DFS_32_MSB _u(20) +#define SSI_CTRLR0_DFS_32_LSB _u(16) +#define SSI_CTRLR0_DFS_32_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : SSI_CTRLR0_CFS +// Description : Control frame size +// Value of n -> n+1 clocks per frame. +#define SSI_CTRLR0_CFS_RESET _u(0x0) +#define SSI_CTRLR0_CFS_BITS _u(0x0000f000) +#define SSI_CTRLR0_CFS_MSB _u(15) +#define SSI_CTRLR0_CFS_LSB _u(12) +#define SSI_CTRLR0_CFS_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : SSI_CTRLR0_SRL +// Description : Shift register loop (test mode) +#define SSI_CTRLR0_SRL_RESET _u(0x0) +#define SSI_CTRLR0_SRL_BITS _u(0x00000800) +#define SSI_CTRLR0_SRL_MSB _u(11) +#define SSI_CTRLR0_SRL_LSB _u(11) +#define SSI_CTRLR0_SRL_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : SSI_CTRLR0_SLV_OE +// Description : Slave output enable +#define SSI_CTRLR0_SLV_OE_RESET _u(0x0) +#define SSI_CTRLR0_SLV_OE_BITS _u(0x00000400) +#define SSI_CTRLR0_SLV_OE_MSB _u(10) +#define SSI_CTRLR0_SLV_OE_LSB _u(10) +#define SSI_CTRLR0_SLV_OE_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : SSI_CTRLR0_TMOD +// Description : Transfer mode +// 0x0 -> Both transmit and receive +// 0x1 -> Transmit only (not for FRF == 0, standard SPI mode) +// 0x2 -> Receive only (not for FRF == 0, standard SPI mode) +// 0x3 -> EEPROM read mode (TX then RX; RX starts after control +// data TX'd) +#define SSI_CTRLR0_TMOD_RESET _u(0x0) +#define SSI_CTRLR0_TMOD_BITS _u(0x00000300) +#define SSI_CTRLR0_TMOD_MSB _u(9) +#define SSI_CTRLR0_TMOD_LSB _u(8) +#define SSI_CTRLR0_TMOD_ACCESS "RW" +#define SSI_CTRLR0_TMOD_VALUE_TX_AND_RX _u(0x0) +#define SSI_CTRLR0_TMOD_VALUE_TX_ONLY _u(0x1) +#define SSI_CTRLR0_TMOD_VALUE_RX_ONLY _u(0x2) +#define SSI_CTRLR0_TMOD_VALUE_EEPROM_READ _u(0x3) +// ----------------------------------------------------------------------------- +// Field : SSI_CTRLR0_SCPOL +// Description : Serial clock polarity +#define SSI_CTRLR0_SCPOL_RESET _u(0x0) +#define SSI_CTRLR0_SCPOL_BITS _u(0x00000080) +#define SSI_CTRLR0_SCPOL_MSB _u(7) +#define SSI_CTRLR0_SCPOL_LSB _u(7) +#define SSI_CTRLR0_SCPOL_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : SSI_CTRLR0_SCPH +// Description : Serial clock phase +#define SSI_CTRLR0_SCPH_RESET _u(0x0) +#define SSI_CTRLR0_SCPH_BITS _u(0x00000040) +#define SSI_CTRLR0_SCPH_MSB _u(6) +#define SSI_CTRLR0_SCPH_LSB _u(6) +#define SSI_CTRLR0_SCPH_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : SSI_CTRLR0_FRF +// Description : Frame format +#define SSI_CTRLR0_FRF_RESET _u(0x0) +#define SSI_CTRLR0_FRF_BITS _u(0x00000030) +#define SSI_CTRLR0_FRF_MSB _u(5) +#define SSI_CTRLR0_FRF_LSB _u(4) +#define SSI_CTRLR0_FRF_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : SSI_CTRLR0_DFS +// Description : Data frame size +#define SSI_CTRLR0_DFS_RESET _u(0x0) +#define SSI_CTRLR0_DFS_BITS _u(0x0000000f) +#define SSI_CTRLR0_DFS_MSB _u(3) +#define SSI_CTRLR0_DFS_LSB _u(0) +#define SSI_CTRLR0_DFS_ACCESS "RW" +// ============================================================================= +// Register : SSI_CTRLR1 +// Description : Master Control register 1 +#define SSI_CTRLR1_OFFSET _u(0x00000004) +#define SSI_CTRLR1_BITS _u(0x0000ffff) +#define SSI_CTRLR1_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : SSI_CTRLR1_NDF +// Description : Number of data frames +#define SSI_CTRLR1_NDF_RESET _u(0x0000) +#define SSI_CTRLR1_NDF_BITS _u(0x0000ffff) +#define SSI_CTRLR1_NDF_MSB _u(15) +#define SSI_CTRLR1_NDF_LSB _u(0) +#define SSI_CTRLR1_NDF_ACCESS "RW" +// ============================================================================= +// Register : SSI_SSIENR +// Description : SSI Enable +#define SSI_SSIENR_OFFSET _u(0x00000008) +#define SSI_SSIENR_BITS _u(0x00000001) +#define SSI_SSIENR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : SSI_SSIENR_SSI_EN +// Description : SSI enable +#define SSI_SSIENR_SSI_EN_RESET _u(0x0) +#define SSI_SSIENR_SSI_EN_BITS _u(0x00000001) +#define SSI_SSIENR_SSI_EN_MSB _u(0) +#define SSI_SSIENR_SSI_EN_LSB _u(0) +#define SSI_SSIENR_SSI_EN_ACCESS "RW" +// ============================================================================= +// Register : SSI_MWCR +// Description : Microwire Control +#define SSI_MWCR_OFFSET _u(0x0000000c) +#define SSI_MWCR_BITS _u(0x00000007) +#define SSI_MWCR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : SSI_MWCR_MHS +// Description : Microwire handshaking +#define SSI_MWCR_MHS_RESET _u(0x0) +#define SSI_MWCR_MHS_BITS _u(0x00000004) +#define SSI_MWCR_MHS_MSB _u(2) +#define SSI_MWCR_MHS_LSB _u(2) +#define SSI_MWCR_MHS_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : SSI_MWCR_MDD +// Description : Microwire control +#define SSI_MWCR_MDD_RESET _u(0x0) +#define SSI_MWCR_MDD_BITS _u(0x00000002) +#define SSI_MWCR_MDD_MSB _u(1) +#define SSI_MWCR_MDD_LSB _u(1) +#define SSI_MWCR_MDD_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : SSI_MWCR_MWMOD +// Description : Microwire transfer mode +#define SSI_MWCR_MWMOD_RESET _u(0x0) +#define SSI_MWCR_MWMOD_BITS _u(0x00000001) +#define SSI_MWCR_MWMOD_MSB _u(0) +#define SSI_MWCR_MWMOD_LSB _u(0) +#define SSI_MWCR_MWMOD_ACCESS "RW" +// ============================================================================= +// Register : SSI_SER +// Description : Slave enable +// For each bit: +// 0 -> slave not selected +// 1 -> slave selected +#define SSI_SER_OFFSET _u(0x00000010) +#define SSI_SER_BITS _u(0x00000001) +#define SSI_SER_RESET _u(0x00000000) +#define SSI_SER_MSB _u(0) +#define SSI_SER_LSB _u(0) +#define SSI_SER_ACCESS "RW" +// ============================================================================= +// Register : SSI_BAUDR +// Description : Baud rate +#define SSI_BAUDR_OFFSET _u(0x00000014) +#define SSI_BAUDR_BITS _u(0x0000ffff) +#define SSI_BAUDR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : SSI_BAUDR_SCKDV +// Description : SSI clock divider +#define SSI_BAUDR_SCKDV_RESET _u(0x0000) +#define SSI_BAUDR_SCKDV_BITS _u(0x0000ffff) +#define SSI_BAUDR_SCKDV_MSB _u(15) +#define SSI_BAUDR_SCKDV_LSB _u(0) +#define SSI_BAUDR_SCKDV_ACCESS "RW" +// ============================================================================= +// Register : SSI_TXFTLR +// Description : TX FIFO threshold level +#define SSI_TXFTLR_OFFSET _u(0x00000018) +#define SSI_TXFTLR_BITS _u(0x000000ff) +#define SSI_TXFTLR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : SSI_TXFTLR_TFT +// Description : Transmit FIFO threshold +#define SSI_TXFTLR_TFT_RESET _u(0x00) +#define SSI_TXFTLR_TFT_BITS _u(0x000000ff) +#define SSI_TXFTLR_TFT_MSB _u(7) +#define SSI_TXFTLR_TFT_LSB _u(0) +#define SSI_TXFTLR_TFT_ACCESS "RW" +// ============================================================================= +// Register : SSI_RXFTLR +// Description : RX FIFO threshold level +#define SSI_RXFTLR_OFFSET _u(0x0000001c) +#define SSI_RXFTLR_BITS _u(0x000000ff) +#define SSI_RXFTLR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : SSI_RXFTLR_RFT +// Description : Receive FIFO threshold +#define SSI_RXFTLR_RFT_RESET _u(0x00) +#define SSI_RXFTLR_RFT_BITS _u(0x000000ff) +#define SSI_RXFTLR_RFT_MSB _u(7) +#define SSI_RXFTLR_RFT_LSB _u(0) +#define SSI_RXFTLR_RFT_ACCESS "RW" +// ============================================================================= +// Register : SSI_TXFLR +// Description : TX FIFO level +#define SSI_TXFLR_OFFSET _u(0x00000020) +#define SSI_TXFLR_BITS _u(0x000000ff) +#define SSI_TXFLR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : SSI_TXFLR_TFTFL +// Description : Transmit FIFO level +#define SSI_TXFLR_TFTFL_RESET _u(0x00) +#define SSI_TXFLR_TFTFL_BITS _u(0x000000ff) +#define SSI_TXFLR_TFTFL_MSB _u(7) +#define SSI_TXFLR_TFTFL_LSB _u(0) +#define SSI_TXFLR_TFTFL_ACCESS "RO" +// ============================================================================= +// Register : SSI_RXFLR +// Description : RX FIFO level +#define SSI_RXFLR_OFFSET _u(0x00000024) +#define SSI_RXFLR_BITS _u(0x000000ff) +#define SSI_RXFLR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : SSI_RXFLR_RXTFL +// Description : Receive FIFO level +#define SSI_RXFLR_RXTFL_RESET _u(0x00) +#define SSI_RXFLR_RXTFL_BITS _u(0x000000ff) +#define SSI_RXFLR_RXTFL_MSB _u(7) +#define SSI_RXFLR_RXTFL_LSB _u(0) +#define SSI_RXFLR_RXTFL_ACCESS "RO" +// ============================================================================= +// Register : SSI_SR +// Description : Status register +#define SSI_SR_OFFSET _u(0x00000028) +#define SSI_SR_BITS _u(0x0000007f) +#define SSI_SR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : SSI_SR_DCOL +// Description : Data collision error +#define SSI_SR_DCOL_RESET _u(0x0) +#define SSI_SR_DCOL_BITS _u(0x00000040) +#define SSI_SR_DCOL_MSB _u(6) +#define SSI_SR_DCOL_LSB _u(6) +#define SSI_SR_DCOL_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : SSI_SR_TXE +// Description : Transmission error +#define SSI_SR_TXE_RESET _u(0x0) +#define SSI_SR_TXE_BITS _u(0x00000020) +#define SSI_SR_TXE_MSB _u(5) +#define SSI_SR_TXE_LSB _u(5) +#define SSI_SR_TXE_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : SSI_SR_RFF +// Description : Receive FIFO full +#define SSI_SR_RFF_RESET _u(0x0) +#define SSI_SR_RFF_BITS _u(0x00000010) +#define SSI_SR_RFF_MSB _u(4) +#define SSI_SR_RFF_LSB _u(4) +#define SSI_SR_RFF_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : SSI_SR_RFNE +// Description : Receive FIFO not empty +#define SSI_SR_RFNE_RESET _u(0x0) +#define SSI_SR_RFNE_BITS _u(0x00000008) +#define SSI_SR_RFNE_MSB _u(3) +#define SSI_SR_RFNE_LSB _u(3) +#define SSI_SR_RFNE_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : SSI_SR_TFE +// Description : Transmit FIFO empty +#define SSI_SR_TFE_RESET _u(0x0) +#define SSI_SR_TFE_BITS _u(0x00000004) +#define SSI_SR_TFE_MSB _u(2) +#define SSI_SR_TFE_LSB _u(2) +#define SSI_SR_TFE_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : SSI_SR_TFNF +// Description : Transmit FIFO not full +#define SSI_SR_TFNF_RESET _u(0x0) +#define SSI_SR_TFNF_BITS _u(0x00000002) +#define SSI_SR_TFNF_MSB _u(1) +#define SSI_SR_TFNF_LSB _u(1) +#define SSI_SR_TFNF_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : SSI_SR_BUSY +// Description : SSI busy flag +#define SSI_SR_BUSY_RESET _u(0x0) +#define SSI_SR_BUSY_BITS _u(0x00000001) +#define SSI_SR_BUSY_MSB _u(0) +#define SSI_SR_BUSY_LSB _u(0) +#define SSI_SR_BUSY_ACCESS "RO" +// ============================================================================= +// Register : SSI_IMR +// Description : Interrupt mask +#define SSI_IMR_OFFSET _u(0x0000002c) +#define SSI_IMR_BITS _u(0x0000003f) +#define SSI_IMR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : SSI_IMR_MSTIM +// Description : Multi-master contention interrupt mask +#define SSI_IMR_MSTIM_RESET _u(0x0) +#define SSI_IMR_MSTIM_BITS _u(0x00000020) +#define SSI_IMR_MSTIM_MSB _u(5) +#define SSI_IMR_MSTIM_LSB _u(5) +#define SSI_IMR_MSTIM_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : SSI_IMR_RXFIM +// Description : Receive FIFO full interrupt mask +#define SSI_IMR_RXFIM_RESET _u(0x0) +#define SSI_IMR_RXFIM_BITS _u(0x00000010) +#define SSI_IMR_RXFIM_MSB _u(4) +#define SSI_IMR_RXFIM_LSB _u(4) +#define SSI_IMR_RXFIM_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : SSI_IMR_RXOIM +// Description : Receive FIFO overflow interrupt mask +#define SSI_IMR_RXOIM_RESET _u(0x0) +#define SSI_IMR_RXOIM_BITS _u(0x00000008) +#define SSI_IMR_RXOIM_MSB _u(3) +#define SSI_IMR_RXOIM_LSB _u(3) +#define SSI_IMR_RXOIM_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : SSI_IMR_RXUIM +// Description : Receive FIFO underflow interrupt mask +#define SSI_IMR_RXUIM_RESET _u(0x0) +#define SSI_IMR_RXUIM_BITS _u(0x00000004) +#define SSI_IMR_RXUIM_MSB _u(2) +#define SSI_IMR_RXUIM_LSB _u(2) +#define SSI_IMR_RXUIM_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : SSI_IMR_TXOIM +// Description : Transmit FIFO overflow interrupt mask +#define SSI_IMR_TXOIM_RESET _u(0x0) +#define SSI_IMR_TXOIM_BITS _u(0x00000002) +#define SSI_IMR_TXOIM_MSB _u(1) +#define SSI_IMR_TXOIM_LSB _u(1) +#define SSI_IMR_TXOIM_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : SSI_IMR_TXEIM +// Description : Transmit FIFO empty interrupt mask +#define SSI_IMR_TXEIM_RESET _u(0x0) +#define SSI_IMR_TXEIM_BITS _u(0x00000001) +#define SSI_IMR_TXEIM_MSB _u(0) +#define SSI_IMR_TXEIM_LSB _u(0) +#define SSI_IMR_TXEIM_ACCESS "RW" +// ============================================================================= +// Register : SSI_ISR +// Description : Interrupt status +#define SSI_ISR_OFFSET _u(0x00000030) +#define SSI_ISR_BITS _u(0x0000003f) +#define SSI_ISR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : SSI_ISR_MSTIS +// Description : Multi-master contention interrupt status +#define SSI_ISR_MSTIS_RESET _u(0x0) +#define SSI_ISR_MSTIS_BITS _u(0x00000020) +#define SSI_ISR_MSTIS_MSB _u(5) +#define SSI_ISR_MSTIS_LSB _u(5) +#define SSI_ISR_MSTIS_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : SSI_ISR_RXFIS +// Description : Receive FIFO full interrupt status +#define SSI_ISR_RXFIS_RESET _u(0x0) +#define SSI_ISR_RXFIS_BITS _u(0x00000010) +#define SSI_ISR_RXFIS_MSB _u(4) +#define SSI_ISR_RXFIS_LSB _u(4) +#define SSI_ISR_RXFIS_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : SSI_ISR_RXOIS +// Description : Receive FIFO overflow interrupt status +#define SSI_ISR_RXOIS_RESET _u(0x0) +#define SSI_ISR_RXOIS_BITS _u(0x00000008) +#define SSI_ISR_RXOIS_MSB _u(3) +#define SSI_ISR_RXOIS_LSB _u(3) +#define SSI_ISR_RXOIS_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : SSI_ISR_RXUIS +// Description : Receive FIFO underflow interrupt status +#define SSI_ISR_RXUIS_RESET _u(0x0) +#define SSI_ISR_RXUIS_BITS _u(0x00000004) +#define SSI_ISR_RXUIS_MSB _u(2) +#define SSI_ISR_RXUIS_LSB _u(2) +#define SSI_ISR_RXUIS_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : SSI_ISR_TXOIS +// Description : Transmit FIFO overflow interrupt status +#define SSI_ISR_TXOIS_RESET _u(0x0) +#define SSI_ISR_TXOIS_BITS _u(0x00000002) +#define SSI_ISR_TXOIS_MSB _u(1) +#define SSI_ISR_TXOIS_LSB _u(1) +#define SSI_ISR_TXOIS_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : SSI_ISR_TXEIS +// Description : Transmit FIFO empty interrupt status +#define SSI_ISR_TXEIS_RESET _u(0x0) +#define SSI_ISR_TXEIS_BITS _u(0x00000001) +#define SSI_ISR_TXEIS_MSB _u(0) +#define SSI_ISR_TXEIS_LSB _u(0) +#define SSI_ISR_TXEIS_ACCESS "RO" +// ============================================================================= +// Register : SSI_RISR +// Description : Raw interrupt status +#define SSI_RISR_OFFSET _u(0x00000034) +#define SSI_RISR_BITS _u(0x0000003f) +#define SSI_RISR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : SSI_RISR_MSTIR +// Description : Multi-master contention raw interrupt status +#define SSI_RISR_MSTIR_RESET _u(0x0) +#define SSI_RISR_MSTIR_BITS _u(0x00000020) +#define SSI_RISR_MSTIR_MSB _u(5) +#define SSI_RISR_MSTIR_LSB _u(5) +#define SSI_RISR_MSTIR_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : SSI_RISR_RXFIR +// Description : Receive FIFO full raw interrupt status +#define SSI_RISR_RXFIR_RESET _u(0x0) +#define SSI_RISR_RXFIR_BITS _u(0x00000010) +#define SSI_RISR_RXFIR_MSB _u(4) +#define SSI_RISR_RXFIR_LSB _u(4) +#define SSI_RISR_RXFIR_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : SSI_RISR_RXOIR +// Description : Receive FIFO overflow raw interrupt status +#define SSI_RISR_RXOIR_RESET _u(0x0) +#define SSI_RISR_RXOIR_BITS _u(0x00000008) +#define SSI_RISR_RXOIR_MSB _u(3) +#define SSI_RISR_RXOIR_LSB _u(3) +#define SSI_RISR_RXOIR_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : SSI_RISR_RXUIR +// Description : Receive FIFO underflow raw interrupt status +#define SSI_RISR_RXUIR_RESET _u(0x0) +#define SSI_RISR_RXUIR_BITS _u(0x00000004) +#define SSI_RISR_RXUIR_MSB _u(2) +#define SSI_RISR_RXUIR_LSB _u(2) +#define SSI_RISR_RXUIR_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : SSI_RISR_TXOIR +// Description : Transmit FIFO overflow raw interrupt status +#define SSI_RISR_TXOIR_RESET _u(0x0) +#define SSI_RISR_TXOIR_BITS _u(0x00000002) +#define SSI_RISR_TXOIR_MSB _u(1) +#define SSI_RISR_TXOIR_LSB _u(1) +#define SSI_RISR_TXOIR_ACCESS "RO" +// ----------------------------------------------------------------------------- +// Field : SSI_RISR_TXEIR +// Description : Transmit FIFO empty raw interrupt status +#define SSI_RISR_TXEIR_RESET _u(0x0) +#define SSI_RISR_TXEIR_BITS _u(0x00000001) +#define SSI_RISR_TXEIR_MSB _u(0) +#define SSI_RISR_TXEIR_LSB _u(0) +#define SSI_RISR_TXEIR_ACCESS "RO" +// ============================================================================= +// Register : SSI_TXOICR +// Description : TX FIFO overflow interrupt clear +// Clear-on-read transmit FIFO overflow interrupt +#define SSI_TXOICR_OFFSET _u(0x00000038) +#define SSI_TXOICR_BITS _u(0x00000001) +#define SSI_TXOICR_RESET _u(0x00000000) +#define SSI_TXOICR_MSB _u(0) +#define SSI_TXOICR_LSB _u(0) +#define SSI_TXOICR_ACCESS "RO" +// ============================================================================= +// Register : SSI_RXOICR +// Description : RX FIFO overflow interrupt clear +// Clear-on-read receive FIFO overflow interrupt +#define SSI_RXOICR_OFFSET _u(0x0000003c) +#define SSI_RXOICR_BITS _u(0x00000001) +#define SSI_RXOICR_RESET _u(0x00000000) +#define SSI_RXOICR_MSB _u(0) +#define SSI_RXOICR_LSB _u(0) +#define SSI_RXOICR_ACCESS "RO" +// ============================================================================= +// Register : SSI_RXUICR +// Description : RX FIFO underflow interrupt clear +// Clear-on-read receive FIFO underflow interrupt +#define SSI_RXUICR_OFFSET _u(0x00000040) +#define SSI_RXUICR_BITS _u(0x00000001) +#define SSI_RXUICR_RESET _u(0x00000000) +#define SSI_RXUICR_MSB _u(0) +#define SSI_RXUICR_LSB _u(0) +#define SSI_RXUICR_ACCESS "RO" +// ============================================================================= +// Register : SSI_MSTICR +// Description : Multi-master interrupt clear +// Clear-on-read multi-master contention interrupt +#define SSI_MSTICR_OFFSET _u(0x00000044) +#define SSI_MSTICR_BITS _u(0x00000001) +#define SSI_MSTICR_RESET _u(0x00000000) +#define SSI_MSTICR_MSB _u(0) +#define SSI_MSTICR_LSB _u(0) +#define SSI_MSTICR_ACCESS "RO" +// ============================================================================= +// Register : SSI_ICR +// Description : Interrupt clear +// Clear-on-read all active interrupts +#define SSI_ICR_OFFSET _u(0x00000048) +#define SSI_ICR_BITS _u(0x00000001) +#define SSI_ICR_RESET _u(0x00000000) +#define SSI_ICR_MSB _u(0) +#define SSI_ICR_LSB _u(0) +#define SSI_ICR_ACCESS "RO" +// ============================================================================= +// Register : SSI_DMACR +// Description : DMA control +#define SSI_DMACR_OFFSET _u(0x0000004c) +#define SSI_DMACR_BITS _u(0x00000003) +#define SSI_DMACR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : SSI_DMACR_TDMAE +// Description : Transmit DMA enable +#define SSI_DMACR_TDMAE_RESET _u(0x0) +#define SSI_DMACR_TDMAE_BITS _u(0x00000002) +#define SSI_DMACR_TDMAE_MSB _u(1) +#define SSI_DMACR_TDMAE_LSB _u(1) +#define SSI_DMACR_TDMAE_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : SSI_DMACR_RDMAE +// Description : Receive DMA enable +#define SSI_DMACR_RDMAE_RESET _u(0x0) +#define SSI_DMACR_RDMAE_BITS _u(0x00000001) +#define SSI_DMACR_RDMAE_MSB _u(0) +#define SSI_DMACR_RDMAE_LSB _u(0) +#define SSI_DMACR_RDMAE_ACCESS "RW" +// ============================================================================= +// Register : SSI_DMATDLR +// Description : DMA TX data level +#define SSI_DMATDLR_OFFSET _u(0x00000050) +#define SSI_DMATDLR_BITS _u(0x000000ff) +#define SSI_DMATDLR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : SSI_DMATDLR_DMATDL +// Description : Transmit data watermark level +#define SSI_DMATDLR_DMATDL_RESET _u(0x00) +#define SSI_DMATDLR_DMATDL_BITS _u(0x000000ff) +#define SSI_DMATDLR_DMATDL_MSB _u(7) +#define SSI_DMATDLR_DMATDL_LSB _u(0) +#define SSI_DMATDLR_DMATDL_ACCESS "RW" +// ============================================================================= +// Register : SSI_DMARDLR +// Description : DMA RX data level +#define SSI_DMARDLR_OFFSET _u(0x00000054) +#define SSI_DMARDLR_BITS _u(0x000000ff) +#define SSI_DMARDLR_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : SSI_DMARDLR_DMARDL +// Description : Receive data watermark level (DMARDLR+1) +#define SSI_DMARDLR_DMARDL_RESET _u(0x00) +#define SSI_DMARDLR_DMARDL_BITS _u(0x000000ff) +#define SSI_DMARDLR_DMARDL_MSB _u(7) +#define SSI_DMARDLR_DMARDL_LSB _u(0) +#define SSI_DMARDLR_DMARDL_ACCESS "RW" +// ============================================================================= +// Register : SSI_IDR +// Description : Identification register +#define SSI_IDR_OFFSET _u(0x00000058) +#define SSI_IDR_BITS _u(0xffffffff) +#define SSI_IDR_RESET _u(0x51535049) +// ----------------------------------------------------------------------------- +// Field : SSI_IDR_IDCODE +// Description : Peripheral dentification code +#define SSI_IDR_IDCODE_RESET _u(0x51535049) +#define SSI_IDR_IDCODE_BITS _u(0xffffffff) +#define SSI_IDR_IDCODE_MSB _u(31) +#define SSI_IDR_IDCODE_LSB _u(0) +#define SSI_IDR_IDCODE_ACCESS "RO" +// ============================================================================= +// Register : SSI_SSI_VERSION_ID +// Description : Version ID +#define SSI_SSI_VERSION_ID_OFFSET _u(0x0000005c) +#define SSI_SSI_VERSION_ID_BITS _u(0xffffffff) +#define SSI_SSI_VERSION_ID_RESET _u(0x3430312a) +// ----------------------------------------------------------------------------- +// Field : SSI_SSI_VERSION_ID_SSI_COMP_VERSION +// Description : SNPS component version (format X.YY) +#define SSI_SSI_VERSION_ID_SSI_COMP_VERSION_RESET _u(0x3430312a) +#define SSI_SSI_VERSION_ID_SSI_COMP_VERSION_BITS _u(0xffffffff) +#define SSI_SSI_VERSION_ID_SSI_COMP_VERSION_MSB _u(31) +#define SSI_SSI_VERSION_ID_SSI_COMP_VERSION_LSB _u(0) +#define SSI_SSI_VERSION_ID_SSI_COMP_VERSION_ACCESS "RO" +// ============================================================================= +// Register : SSI_DR0 +// Description : Data Register 0 (of 36) +#define SSI_DR0_OFFSET _u(0x00000060) +#define SSI_DR0_BITS _u(0xffffffff) +#define SSI_DR0_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : SSI_DR0_DR +// Description : First data register of 36 +#define SSI_DR0_DR_RESET _u(0x00000000) +#define SSI_DR0_DR_BITS _u(0xffffffff) +#define SSI_DR0_DR_MSB _u(31) +#define SSI_DR0_DR_LSB _u(0) +#define SSI_DR0_DR_ACCESS "RW" +// ============================================================================= +// Register : SSI_RX_SAMPLE_DLY +// Description : RX sample delay +#define SSI_RX_SAMPLE_DLY_OFFSET _u(0x000000f0) +#define SSI_RX_SAMPLE_DLY_BITS _u(0x000000ff) +#define SSI_RX_SAMPLE_DLY_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : SSI_RX_SAMPLE_DLY_RSD +// Description : RXD sample delay (in SCLK cycles) +#define SSI_RX_SAMPLE_DLY_RSD_RESET _u(0x00) +#define SSI_RX_SAMPLE_DLY_RSD_BITS _u(0x000000ff) +#define SSI_RX_SAMPLE_DLY_RSD_MSB _u(7) +#define SSI_RX_SAMPLE_DLY_RSD_LSB _u(0) +#define SSI_RX_SAMPLE_DLY_RSD_ACCESS "RW" +// ============================================================================= +// Register : SSI_SPI_CTRLR0 +// Description : SPI control +#define SSI_SPI_CTRLR0_OFFSET _u(0x000000f4) +#define SSI_SPI_CTRLR0_BITS _u(0xff07fb3f) +#define SSI_SPI_CTRLR0_RESET _u(0x03000000) +// ----------------------------------------------------------------------------- +// Field : SSI_SPI_CTRLR0_XIP_CMD +// Description : SPI Command to send in XIP mode (INST_L = 8-bit) or to append +// to Address (INST_L = 0-bit) +#define SSI_SPI_CTRLR0_XIP_CMD_RESET _u(0x03) +#define SSI_SPI_CTRLR0_XIP_CMD_BITS _u(0xff000000) +#define SSI_SPI_CTRLR0_XIP_CMD_MSB _u(31) +#define SSI_SPI_CTRLR0_XIP_CMD_LSB _u(24) +#define SSI_SPI_CTRLR0_XIP_CMD_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : SSI_SPI_CTRLR0_SPI_RXDS_EN +// Description : Read data strobe enable +#define SSI_SPI_CTRLR0_SPI_RXDS_EN_RESET _u(0x0) +#define SSI_SPI_CTRLR0_SPI_RXDS_EN_BITS _u(0x00040000) +#define SSI_SPI_CTRLR0_SPI_RXDS_EN_MSB _u(18) +#define SSI_SPI_CTRLR0_SPI_RXDS_EN_LSB _u(18) +#define SSI_SPI_CTRLR0_SPI_RXDS_EN_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : SSI_SPI_CTRLR0_INST_DDR_EN +// Description : Instruction DDR transfer enable +#define SSI_SPI_CTRLR0_INST_DDR_EN_RESET _u(0x0) +#define SSI_SPI_CTRLR0_INST_DDR_EN_BITS _u(0x00020000) +#define SSI_SPI_CTRLR0_INST_DDR_EN_MSB _u(17) +#define SSI_SPI_CTRLR0_INST_DDR_EN_LSB _u(17) +#define SSI_SPI_CTRLR0_INST_DDR_EN_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : SSI_SPI_CTRLR0_SPI_DDR_EN +// Description : SPI DDR transfer enable +#define SSI_SPI_CTRLR0_SPI_DDR_EN_RESET _u(0x0) +#define SSI_SPI_CTRLR0_SPI_DDR_EN_BITS _u(0x00010000) +#define SSI_SPI_CTRLR0_SPI_DDR_EN_MSB _u(16) +#define SSI_SPI_CTRLR0_SPI_DDR_EN_LSB _u(16) +#define SSI_SPI_CTRLR0_SPI_DDR_EN_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : SSI_SPI_CTRLR0_WAIT_CYCLES +// Description : Wait cycles between control frame transmit and data reception +// (in SCLK cycles) +#define SSI_SPI_CTRLR0_WAIT_CYCLES_RESET _u(0x00) +#define SSI_SPI_CTRLR0_WAIT_CYCLES_BITS _u(0x0000f800) +#define SSI_SPI_CTRLR0_WAIT_CYCLES_MSB _u(15) +#define SSI_SPI_CTRLR0_WAIT_CYCLES_LSB _u(11) +#define SSI_SPI_CTRLR0_WAIT_CYCLES_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : SSI_SPI_CTRLR0_INST_L +// Description : Instruction length (0/4/8/16b) +// 0x0 -> No instruction +// 0x1 -> 4-bit instruction +// 0x2 -> 8-bit instruction +// 0x3 -> 16-bit instruction +#define SSI_SPI_CTRLR0_INST_L_RESET _u(0x0) +#define SSI_SPI_CTRLR0_INST_L_BITS _u(0x00000300) +#define SSI_SPI_CTRLR0_INST_L_MSB _u(9) +#define SSI_SPI_CTRLR0_INST_L_LSB _u(8) +#define SSI_SPI_CTRLR0_INST_L_ACCESS "RW" +#define SSI_SPI_CTRLR0_INST_L_VALUE_NONE _u(0x0) +#define SSI_SPI_CTRLR0_INST_L_VALUE_4B _u(0x1) +#define SSI_SPI_CTRLR0_INST_L_VALUE_8B _u(0x2) +#define SSI_SPI_CTRLR0_INST_L_VALUE_16B _u(0x3) +// ----------------------------------------------------------------------------- +// Field : SSI_SPI_CTRLR0_ADDR_L +// Description : Address length (0b-60b in 4b increments) +#define SSI_SPI_CTRLR0_ADDR_L_RESET _u(0x0) +#define SSI_SPI_CTRLR0_ADDR_L_BITS _u(0x0000003c) +#define SSI_SPI_CTRLR0_ADDR_L_MSB _u(5) +#define SSI_SPI_CTRLR0_ADDR_L_LSB _u(2) +#define SSI_SPI_CTRLR0_ADDR_L_ACCESS "RW" +// ----------------------------------------------------------------------------- +// Field : SSI_SPI_CTRLR0_TRANS_TYPE +// Description : Address and instruction transfer format +// 0x0 -> Command and address both in standard SPI frame format +// 0x1 -> Command in standard SPI format, address in format +// specified by FRF +// 0x2 -> Command and address both in format specified by FRF +// (e.g. Dual-SPI) +#define SSI_SPI_CTRLR0_TRANS_TYPE_RESET _u(0x0) +#define SSI_SPI_CTRLR0_TRANS_TYPE_BITS _u(0x00000003) +#define SSI_SPI_CTRLR0_TRANS_TYPE_MSB _u(1) +#define SSI_SPI_CTRLR0_TRANS_TYPE_LSB _u(0) +#define SSI_SPI_CTRLR0_TRANS_TYPE_ACCESS "RW" +#define SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C1A _u(0x0) +#define SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C2A _u(0x1) +#define SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_2C2A _u(0x2) +// ============================================================================= +// Register : SSI_TXD_DRIVE_EDGE +// Description : TX drive edge +#define SSI_TXD_DRIVE_EDGE_OFFSET _u(0x000000f8) +#define SSI_TXD_DRIVE_EDGE_BITS _u(0x000000ff) +#define SSI_TXD_DRIVE_EDGE_RESET _u(0x00000000) +// ----------------------------------------------------------------------------- +// Field : SSI_TXD_DRIVE_EDGE_TDE +// Description : TXD drive edge +#define SSI_TXD_DRIVE_EDGE_TDE_RESET _u(0x00) +#define SSI_TXD_DRIVE_EDGE_TDE_BITS _u(0x000000ff) +#define SSI_TXD_DRIVE_EDGE_TDE_MSB _u(7) +#define SSI_TXD_DRIVE_EDGE_TDE_LSB _u(0) +#define SSI_TXD_DRIVE_EDGE_TDE_ACCESS "RW" +// ============================================================================= +#endif // HARDWARE_REGS_SSI_DEFINED diff --git a/src/bootroms/shared/stage2.ld b/src/bootroms/shared/stage2.ld new file mode 100644 index 0000000..452281d --- /dev/null +++ b/src/bootroms/shared/stage2.ld @@ -0,0 +1,31 @@ +/* + * Target CPU: ARM Cortex-M0+ + * Target Chip: RP2040 + */ + +ENTRY(_stage2_boot); + +MEMORY +{ + flash0 (rx!w) : ORIGIN = 0x10000000, LENGTH = 0x00200000 + ram0 (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00040000 +} + +SECTIONS +{ + .text : { + KEEP (*(.text)) + *(.rodata*) + } > flash0 + + .ARM.exidx : { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } >flash0 + + + .data : + { + *(.data*) + *(.bss*) + } > ram0 /* AT> flash0 */ +} diff --git a/src/bootroms/shared/wait_ssi_ready.S b/src/bootroms/shared/wait_ssi_ready.S new file mode 100644 index 0000000..2e49b64 --- /dev/null +++ b/src/bootroms/shared/wait_ssi_ready.S @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _BOOT2_HELPER_WAIT_SSI_READY +#define _BOOT2_HELPER_WAIT_SSI_READY + +wait_ssi_ready: + push {r0, r1, lr} + + // Command is complete when there is nothing left to send + // (TX FIFO empty) and SSI is no longer busy (CSn deasserted) +1: + ldr r1, [r3, #SSI_SR_OFFSET] + movs r0, #SSI_SR_TFE_BITS + tst r1, r0 + beq 1b + movs r0, #SSI_SR_BUSY_BITS + tst r1, r0 + bne 1b + + pop {r0, r1, pc} + +#endif diff --git a/src/bootroms/w25q080.S b/src/bootroms/w25q080.S new file mode 100644 index 0000000..5663926 --- /dev/null +++ b/src/bootroms/w25q080.S @@ -0,0 +1,280 @@ +// ---------------------------------------------------------------------------- +// Second stage boot code +// Copyright (c) 2019-2021 Raspberry Pi (Trading) Ltd. +// SPDX-License-Identifier: BSD-3-Clause +// +// Device: Winbond W25Q080 +// Also supports W25Q16JV (which has some different SR instructions) +// Also supports AT25SF081 +// Also supports S25FL132K0 +// +// Description: Configures W25Q080 to run in Quad I/O continuous read XIP mode +// +// Details: * Check status register 2 to determine if QSPI mode is enabled, +// and perform an SR2 programming cycle if necessary. +// * Use SSI to perform a dummy 0xEB read command, with the mode +// continuation bits set, so that the flash will not require +// 0xEB instruction prefix on subsequent reads. +// * Configure SSI to write address, mode bits, but no instruction. +// SSI + flash are now jointly in a state where continuous reads +// can take place. +// * Jump to exit pointer passed in via lr. Bootrom passes null, +// in which case this code uses a default 256 byte flash offset +// +// Building: * This code must be position-independent, and use stack only +// * The code will be padded to a size of 256 bytes, including a +// 4-byte checksum. Therefore code size cannot exceed 252 bytes. +// ---------------------------------------------------------------------------- + +#include "shared/asm_helper.S" +#include "shared/regs.h" + +// ---------------------------------------------------------------------------- +// Config section +// ---------------------------------------------------------------------------- +// It should be possible to support most flash devices by modifying this section + +// The serial flash interface will run at clk_sys/PICO_FLASH_SPI_CLKDIV. +// This must be a positive, even integer. +// The bootrom is very conservative with SPI frequency, but here we should be +// as aggressive as possible. + +#ifndef PICO_FLASH_SPI_CLKDIV +#define PICO_FLASH_SPI_CLKDIV 4 +#endif +#if PICO_FLASH_SPI_CLKDIV & 1 +#error PICO_FLASH_SPI_CLKDIV must be even +#endif + +// Define interface width: single/dual/quad IO +#define FRAME_FORMAT SSI_CTRLR0_SPI_FRF_VALUE_QUAD + +// For W25Q080 this is the "Read data fast quad IO" instruction: +#define CMD_READ 0xeb + +// "Mode bits" are 8 special bits sent immediately after +// the address bits in a "Read Data Fast Quad I/O" command sequence. +// On W25Q080, the four LSBs are don't care, and if MSBs == 0xa, the +// next read does not require the 0xeb instruction prefix. +#define MODE_CONTINUOUS_READ 0xa0 + +// The number of address + mode bits, divided by 4 (always 4, not function of +// interface width). +#define ADDR_L 8 + +// How many clocks of Hi-Z following the mode bits. For W25Q080, 4 dummy cycles +// are required. +#define WAIT_CYCLES 4 + +// If defined, we will read status reg, compare to SREG_DATA, and overwrite +// with our value if the SR doesn't match. +// We do a two-byte write to SR1 (01h cmd) rather than a one-byte write to +// SR2 (31h cmd) as the latter command isn't supported by WX25Q080. +// This isn't great because it will remove block protections. +// A better solution is to use a volatile SR write if your device supports it. +#define PROGRAM_STATUS_REG + +#define CMD_WRITE_ENABLE 0x06 +#define CMD_READ_STATUS 0x05 +#define CMD_READ_STATUS2 0x35 +#define CMD_WRITE_STATUS 0x01 +#define SREG_DATA 0x02 // Enable quad-SPI mode + +// ---------------------------------------------------------------------------- +// Start of 2nd Stage Boot Code +// ---------------------------------------------------------------------------- + +pico_default_asm_setup + +.section .text + +// The exit point is passed in lr. If entered from bootrom, this will be the +// flash address immediately following this second stage (0x10000100). +// Otherwise it will be a return address -- second stage being called as a +// function by user code, after copying out of XIP region. r3 holds SSI base, +// r0...2 used as temporaries. Other GPRs not used. +regular_func _stage2_boot + push {lr} + + // Set pad configuration: + // - SCLK 8mA drive, no slew limiting + // - SDx disable input Schmitt to reduce delay + + ldr r3, =PADS_QSPI_BASE + movs r0, #(2 << PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_LSB | PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST_BITS) + str r0, [r3, #PADS_QSPI_GPIO_QSPI_SCLK_OFFSET] + ldr r0, [r3, #PADS_QSPI_GPIO_QSPI_SD0_OFFSET] + movs r1, #PADS_QSPI_GPIO_QSPI_SD0_SCHMITT_BITS + bics r0, r1 + str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD0_OFFSET] + str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD1_OFFSET] + str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD2_OFFSET] + str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD3_OFFSET] + + ldr r3, =XIP_SSI_BASE + + // Disable SSI to allow further config + movs r1, #0 + str r1, [r3, #SSI_SSIENR_OFFSET] + + // Set baud rate + movs r1, #PICO_FLASH_SPI_CLKDIV + str r1, [r3, #SSI_BAUDR_OFFSET] + + // Set 1-cycle sample delay. If PICO_FLASH_SPI_CLKDIV == 2 then this means, + // if the flash launches data on SCLK posedge, we capture it at the time that + // the next SCLK posedge is launched. This is shortly before that posedge + // arrives at the flash, so data hold time should be ok. For + // PICO_FLASH_SPI_CLKDIV > 2 this pretty much has no effect. + + movs r1, #1 + movs r2, #SSI_RX_SAMPLE_DLY_OFFSET // == 0xf0 so need 8 bits of offset significance + str r1, [r3, r2] + + +// On QSPI parts we usually need a 01h SR-write command to enable QSPI mode +// (i.e. turn WPn and HOLDn into IO2/IO3) +#ifdef PROGRAM_STATUS_REG +program_sregs: +#define CTRL0_SPI_TXRX \ + (7 << SSI_CTRLR0_DFS_32_LSB) | /* 8 bits per data frame */ \ + (SSI_CTRLR0_TMOD_VALUE_TX_AND_RX << SSI_CTRLR0_TMOD_LSB) + + ldr r1, =(CTRL0_SPI_TXRX) + str r1, [r3, #SSI_CTRLR0_OFFSET] + + // Enable SSI and select slave 0 + movs r1, #1 + str r1, [r3, #SSI_SSIENR_OFFSET] + + // Check whether SR needs updating + movs r0, #CMD_READ_STATUS2 + bl read_flash_sreg + movs r2, #SREG_DATA + cmp r0, r2 + beq skip_sreg_programming + + // Send write enable command + movs r1, #CMD_WRITE_ENABLE + str r1, [r3, #SSI_DR0_OFFSET] + + // Poll for completion and discard RX + bl wait_ssi_ready + ldr r1, [r3, #SSI_DR0_OFFSET] + + // Send status write command followed by data bytes + movs r1, #CMD_WRITE_STATUS + str r1, [r3, #SSI_DR0_OFFSET] + movs r0, #0 + str r0, [r3, #SSI_DR0_OFFSET] + str r2, [r3, #SSI_DR0_OFFSET] + + bl wait_ssi_ready + ldr r1, [r3, #SSI_DR0_OFFSET] + ldr r1, [r3, #SSI_DR0_OFFSET] + ldr r1, [r3, #SSI_DR0_OFFSET] + + // Poll status register for write completion +1: + movs r0, #CMD_READ_STATUS + bl read_flash_sreg + movs r1, #1 + tst r0, r1 + bne 1b + +skip_sreg_programming: + + // Disable SSI again so that it can be reconfigured + movs r1, #0 + str r1, [r3, #SSI_SSIENR_OFFSET] +#endif + +// Currently the flash expects an 8 bit serial command prefix on every +// transfer, which is a waste of cycles. Perform a dummy Fast Read Quad I/O +// command, with mode bits set such that the flash will not expect a serial +// command prefix on *subsequent* transfers. We don't care about the results +// of the read, the important part is the mode bits. + +dummy_read: +#define CTRLR0_ENTER_XIP \ + (FRAME_FORMAT /* Quad I/O mode */ \ + << SSI_CTRLR0_SPI_FRF_LSB) | \ + (31 << SSI_CTRLR0_DFS_32_LSB) | /* 32 data bits */ \ + (SSI_CTRLR0_TMOD_VALUE_EEPROM_READ /* Send INST/ADDR, Receive Data */ \ + << SSI_CTRLR0_TMOD_LSB) + + ldr r1, =(CTRLR0_ENTER_XIP) + str r1, [r3, #SSI_CTRLR0_OFFSET] + + movs r1, #0x0 // NDF=0 (single 32b read) + str r1, [r3, #SSI_CTRLR1_OFFSET] + +#define SPI_CTRLR0_ENTER_XIP \ + (ADDR_L << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Address + mode bits */ \ + (WAIT_CYCLES << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z dummy clocks following address + mode */ \ + (SSI_SPI_CTRLR0_INST_L_VALUE_8B \ + << SSI_SPI_CTRLR0_INST_L_LSB) | /* 8-bit instruction */ \ + (SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C2A /* Send Command in serial mode then address in Quad I/O mode */ \ + << SSI_SPI_CTRLR0_TRANS_TYPE_LSB) + + ldr r1, =(SPI_CTRLR0_ENTER_XIP) + ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) // SPI_CTRL0 Register + str r1, [r0] + + movs r1, #1 // Re-enable SSI + str r1, [r3, #SSI_SSIENR_OFFSET] + + movs r1, #CMD_READ + str r1, [r3, #SSI_DR0_OFFSET] // Push SPI command into TX FIFO + movs r1, #MODE_CONTINUOUS_READ // 32-bit: 24 address bits (we don't care, so 0) and M[7:4]=1010 + str r1, [r3, #SSI_DR0_OFFSET] // Push Address into TX FIFO - this will trigger the transaction + + // Poll for completion + bl wait_ssi_ready + +// The flash is in a state where we can blast addresses in parallel, and get +// parallel data back. Now configure the SSI to translate XIP bus accesses +// into QSPI transfers of this form. + + movs r1, #0 + str r1, [r3, #SSI_SSIENR_OFFSET] // Disable SSI (and clear FIFO) to allow further config + +// Note that the INST_L field is used to select what XIP data gets pushed into +// the TX FIFO: +// INST_L_0_BITS {ADDR[23:0],XIP_CMD[7:0]} Load "mode bits" into XIP_CMD +// Anything else {XIP_CMD[7:0],ADDR[23:0]} Load SPI command into XIP_CMD +configure_ssi: +#define SPI_CTRLR0_XIP \ + (MODE_CONTINUOUS_READ /* Mode bits to keep flash in continuous read mode */ \ + << SSI_SPI_CTRLR0_XIP_CMD_LSB) | \ + (ADDR_L << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Total number of address + mode bits */ \ + (WAIT_CYCLES << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z dummy clocks following address + mode */ \ + (SSI_SPI_CTRLR0_INST_L_VALUE_NONE /* Do not send a command, instead send XIP_CMD as mode bits after address */ \ + << SSI_SPI_CTRLR0_INST_L_LSB) | \ + (SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_2C2A /* Send Address in Quad I/O mode (and Command but that is zero bits long) */ \ + << SSI_SPI_CTRLR0_TRANS_TYPE_LSB) + + ldr r1, =(SPI_CTRLR0_XIP) + ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) + str r1, [r0] + + movs r1, #1 + str r1, [r3, #SSI_SSIENR_OFFSET] // Re-enable SSI + +// Bus accesses to the XIP window will now be transparently serviced by the +// external flash on cache miss. We are ready to run code from flash. + +// Pull in standard exit routine +#include "shared/exit_from_boot2.S" + +// Common functions +#include "shared/wait_ssi_ready.S" +#ifdef PROGRAM_STATUS_REG +#include "shared/read_flash_sreg.S" +#endif + +.global literals +literals: +.ltorg + +.end diff --git a/src/bootroms/w25x10cl.S b/src/bootroms/w25x10cl.S new file mode 100644 index 0000000..aab3f89 --- /dev/null +++ b/src/bootroms/w25x10cl.S @@ -0,0 +1,191 @@ +// ---------------------------------------------------------------------------- +// Second stage boot code +// Copyright (c) 2019-2021 Raspberry Pi (Trading) Ltd. +// SPDX-License-Identifier: BSD-3-Clause +// +// Device: Winbond W25X10CL +// +// Description: Configures W25X10CL to run in Dual I/O continuous read XIP mode +// +// Details: * Disable SSI +// * Configure SSI to generate 8b command + 28b address + 2 wait, +// with address and data using dual SPI mode +// * Enable SSI +// * Generate dummy read with command = 0xBB, top 24b of address +// of 0x000000 followed by M[7:0]=0010zzzz (with the HiZ being +// generated by 2 wait cycles). This leaves the W25X10CL in +// continuous read mode +// * Disable SSI +// * Configure SSI to generate 0b command + 28b address + 2 wait, +// with the extra 4 bits of address LSB being 0x2 to keep the +// W25X10CL in continuous read mode forever +// * Enable SSI +// * Set VTOR = 0x10000100 +// * Read MSP reset vector from 0x10000100 and write to MSP (this +// will also enable XIP mode in the SSI wrapper) +// * Read PC reset vector from 0x10000104 and jump to it +// +// Building: * This code must be linked to run at 0x20000000 +// * The code will be padded to a size of 256 bytes, including a +// 4-byte checksum. Therefore code size cannot exceed 252 bytes. +// ---------------------------------------------------------------------------- + +#include "shared/asm_helper.S" +#include "shared/regs.h" + +// The serial flash interface will run at clk_sys/PICO_FLASH_SPI_CLKDIV. +// This must be an even number. +#ifndef PICO_FLASH_SPI_CLKDIV +#define PICO_FLASH_SPI_CLKDIV 4 +#endif + +pico_default_asm_setup + +// ---------------------------------------------------------------------------- +// The "System Control Block" is a set of internal Cortex-M0+ control registers +// that are memory mapped and accessed like any other H/W register. They have +// fixed addresses in the address map of every Cortex-M0+ system. +// ---------------------------------------------------------------------------- + +.equ SCB_VTOR, 0xE000ED08 // RW Vector Table Offset Register + +// ---------------------------------------------------------------------------- +// Winbond W25X10CL Supported Commands +// Taken from "w25x10cl_reg_021714.pdf" +// ---------------------------------------------------------------------------- + +.equ W25X10CL_CMD_READ_DATA_FAST_DUAL_IO, 0xbb + +// ---------------------------------------------------------------------------- +// Winbond W25X10CL "Mode bits" are 8 special bits sent immediately after +// the address bits in a "Read Data Fast Dual I/O" command sequence. +// Of M[7:4], they say M[7:6] are reserved (set to zero), and bits M[3:0] +// are don't care (we HiZ). Only M[5:4] are used, and they must be set +// to M[5:4] = 2'b10 to enable continuous read mode. +// ---------------------------------------------------------------------------- + +.equ W25X10CL_MODE_CONTINUOUS_READ, 0x20 + +// ---------------------------------------------------------------------------- +// Start of 2nd Stage Boot Code +// ---------------------------------------------------------------------------- + +.org 0 + +.section .text + +// This code will get copied to 0x20000000 and then executed + +regular_func _stage2_boot + push {lr} + ldr r3, =XIP_SSI_BASE // Use as base address where possible + +// We are primarily interested in setting up Flash for DSPI XIP w/ continuous read + + movs r1, #0 + str r1, [r3, #SSI_SSIENR_OFFSET] // Disable SSI to allow further config + +// The Boot ROM sets a very conservative SPI clock frequency to be sure it can +// read the initial 256 bytes from any device. Here we can be more aggressive. + + movs r1, #PICO_FLASH_SPI_CLKDIV + str r1, [r3, #SSI_BAUDR_OFFSET] // Set SSI Clock + +// First we need to send the initial command to get us in to Fast Read Dual I/O +// mode. As this transaction requires a command, we can't send it in XIP mode. +// To enter Continuous Read mode as well we need to append 4'b0010 to the address +// bits and then add a further 4 don't care bits. We will construct this by +// specifying a 28-bit address, with the least significant bits being 4'b0010. +// This is just a dummy transaction so we'll perform a read from address zero +// and then discard what comes back. All we really care about is that at the +// end of the transaction, the Winbond W25X10CL device is in Continuous Read mode +// and from then on will only expect to receive addresses. + +#define CTRLR0_ENTER_XIP \ + (SSI_CTRLR0_SPI_FRF_VALUE_DUAL /* Dual I/O mode */ \ + << SSI_CTRLR0_SPI_FRF_LSB) | \ + (31 << SSI_CTRLR0_DFS_32_LSB) | /* 32 data bits */ \ + (SSI_CTRLR0_TMOD_VALUE_EEPROM_READ /* Send INST/ADDR, Receive Data */ \ + << SSI_CTRLR0_TMOD_LSB) + + ldr r1, =(CTRLR0_ENTER_XIP) + str r1, [r3, #SSI_CTRLR0_OFFSET] + + movs r1, #0x0 // NDF=0 (single 32b read) + str r1, [r3, #SSI_CTRLR1_OFFSET] + +#define SPI_CTRLR0_ENTER_XIP \ + (7 << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Send 28 bits (24 address + 4 mode) */ \ + (2 << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z the other 4 mode bits (2 cycles @ dual I/O = 4 bits) */ \ + (SSI_SPI_CTRLR0_INST_L_VALUE_8B \ + << SSI_SPI_CTRLR0_INST_L_LSB) | /* 8-bit instruction */ \ + (SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C2A /* Send Command in serial mode then address in Dual I/O mode */ \ + << SSI_SPI_CTRLR0_TRANS_TYPE_LSB) + + ldr r1, =(SPI_CTRLR0_ENTER_XIP) + ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) // SPI_CTRL0 Register + str r1, [r0] + + movs r1, #1 // Re-enable SSI + str r1, [r3, #SSI_SSIENR_OFFSET] + + movs r1, #W25X10CL_CMD_READ_DATA_FAST_DUAL_IO // 8b command = 0xBB + str r1, [r3, #SSI_DR0_OFFSET] // Push SPI command into TX FIFO + movs r1, #0x0000002 // 28-bit Address for dummy read = 0x000000 + 0x2 Mode bits to set M[5:4]=10 + str r1, [r3, #SSI_DR0_OFFSET] // Push Address into TX FIFO - this will trigger the transaction + +// Now we wait for the read transaction to complete by monitoring the SSI +// status register and checking for the "RX FIFO Not Empty" flag to assert. + + movs r1, #SSI_SR_RFNE_BITS +00: + ldr r0, [r3, #SSI_SR_OFFSET] // Read status register + tst r0, r1 // RFNE status flag set? + beq 00b // If not then wait + +// At this point CN# will be deasserted and the SPI clock will not be running. +// The Winbond WX25X10CL device will be in continuous read, dual I/O mode and +// only expecting address bits after the next CN# assertion. So long as we +// send 4'b0010 (and 4 more dummy HiZ bits) after every subsequent 24b address +// then the Winbond device will remain in continuous read mode. This is the +// ideal mode for Execute-In-Place. +// (If we want to exit continuous read mode then we will need to switch back +// to APM mode and generate a 28-bit address phase with the extra nibble set +// to 4'b0000). + + movs r1, #0 + str r1, [r3, #SSI_SSIENR_OFFSET] // Disable SSI (and clear FIFO) to allow further config + +// Note that the INST_L field is used to select what XIP data gets pushed into +// the TX FIFO: +// INST_L_0_BITS {ADDR[23:0],XIP_CMD[7:0]} Load "mode bits" into XIP_CMD +// Anything else {XIP_CMD[7:0],ADDR[23:0]} Load SPI command into XIP_CMD + +#define SPI_CTRLR0_XIP \ + (W25X10CL_MODE_CONTINUOUS_READ /* Mode bits to keep Winbond in continuous read mode */ \ + << SSI_SPI_CTRLR0_XIP_CMD_LSB) | \ + (7 << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Send 28 bits (24 address + 4 mode) */ \ + (2 << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z the other 4 mode bits (2 cycles @ dual I/O = 4 bits) */ \ + (SSI_SPI_CTRLR0_INST_L_VALUE_NONE /* Do not send a command, instead send XIP_CMD as mode bits after address */ \ + << SSI_SPI_CTRLR0_INST_L_LSB) | \ + (SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_2C2A /* Send Address in Dual I/O mode (and Command but that is zero bits long) */ \ + << SSI_SPI_CTRLR0_TRANS_TYPE_LSB) + + ldr r1, =(SPI_CTRLR0_XIP) + ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) + str r1, [r0] + + movs r1, #1 + str r1, [r3, #SSI_SSIENR_OFFSET] // Re-enable SSI + +// We are now in XIP mode, with all transactions using Dual I/O and only +// needing to send 24-bit addresses (plus mode bits) for each read transaction. + +// Pull in standard exit routine +#include "shared/exit_from_boot2.S" + +.global literals +literals: +.ltorg + +.end From d9cbc3654e2925dfdf2ccf4cd8179728dbc2d0bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Quei=C3=9Fner?= Date: Fri, 22 Sep 2023 09:02:51 +0200 Subject: [PATCH 74/74] Microzig Generation 2 Build Interface (#82) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Starts to rework build framework. * First building version. * Documents paths to supported devices. * Tiny fix for MicroZig. * Drops CI --------- Co-authored-by: Felix "xq" Queißner --- .buildkite/pipeline.yml | 5 - .github/workflows/build.yml | 22 - README.adoc | 12 +- build.zig | 382 +- build.zig.zon | 8 +- src/boards.zig | 69 - src/bootroms/w25q32jvssiq.S | 42 + src/chips.zig | 25 - src/chips/RP2040.zig | 18145 ---------------------------------- 9 files changed, 288 insertions(+), 18422 deletions(-) delete mode 100644 .buildkite/pipeline.yml delete mode 100644 .github/workflows/build.yml delete mode 100644 src/boards.zig create mode 100644 src/bootroms/w25q32jvssiq.S delete mode 100644 src/chips.zig delete mode 100644 src/chips/RP2040.zig diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml deleted file mode 100644 index 4e00ec2..0000000 --- a/.buildkite/pipeline.yml +++ /dev/null @@ -1,5 +0,0 @@ -steps: - - name: Build Examples - command: zig build - - name: Test - command: zig build test diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 50ac1a4..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Build -on: - push: - -jobs: - build: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ - ubuntu-latest, - windows-latest, - macos-latest, - ] - steps: - - uses: actions/checkout@v2 - - uses: goto-bus-stop/setup-zig@v1.3.0 - with: - version: 0.11.0 - - - name: Build and Unit Test - run: zig build test -Doptimize=ReleaseSmall diff --git a/README.adoc b/README.adoc index c31cb3d..8b6358d 100644 --- a/README.adoc +++ b/README.adoc @@ -8,8 +8,10 @@ HAL and register definitions for the RP2040. == Supported devices == -- Raspberry Pi Pico -- (*experimental*) Waveshare RP2040-Plus (4M Flash) -- (*experimental*) Waveshare RP2040-Plus (16M Flash) -- (*experimental*) Waveshare RP2040-ETH Mini -- (*experimental*) Waveshare RP2040-Matrix +- Raspberry Pi RP2040 (`chips.rp2040`) +- Raspberry Pi Pico (`boards.raspberry_pi.pico`) +- (*experimental*) Waveshare RP2040-Plus (4M Flash) (`boards.waveshare.rp2040_plus_4m`) +- (*experimental*) Waveshare RP2040-Plus (16M Flash) (`boards.waveshare.rp2040_plus_16m`) +- (*experimental*) Waveshare RP2040-ETH Mini (`boards.waveshare.rp2040_eth`) +- (*experimental*) Waveshare RP2040-Matrix (`boards.waveshare.rp2040_matrix`) + diff --git a/build.zig b/build.zig index 1d4dd3c..cb3c13f 100644 --- a/build.zig +++ b/build.zig @@ -1,15 +1,101 @@ const std = @import("std"); -const Build = std.Build; -const comptimePrint = std.fmt.comptimePrint; +const microzig = @import("root").dependencies.imports.microzig; // HACK: Please import MicroZig always under the name `microzig`. Otherwise the RP2040 module will fail to be properly imported. -const microzig = @import("microzig"); +fn root() []const u8 { + return comptime (std.fs.path.dirname(@src().file) orelse "."); +} +const build_root = root(); -pub const chips = @import("src/chips.zig"); -pub const boards = @import("src/boards.zig"); +//////////////////////////////////////// +// MicroZig Gen 2 Interface // +//////////////////////////////////////// -const build_root = root(); +pub fn build(b: *std.Build) !void { + // Dummy func to make package manager happy + _ = b; +} + +pub const chips = struct { + // Note: This chip has no flash support defined and requires additional configuration! + pub const rp2040 = .{ + .preferred_format = .{ .uf2 = .RP2040 }, + .chip = chip, + .hal = hal, + .board = null, + .linker_script = linker_script, + }; +}; + +pub const boards = struct { + pub const raspberry_pi = struct { + pub const pico = .{ + .preferred_format = .{ .uf2 = .RP2040 }, + .chip = chip, + .hal = hal, + .linker_script = linker_script, + .board = .{ + .name = "RaspberryPi Pico", + .source_file = .{ .cwd_relative = build_root ++ "/src/boards/raspberry_pi_pico.zig" }, + .url = "https://www.raspberrypi.com/products/raspberry-pi-pico/", + }, + .configure = rp2040_configure(.w25q080), + }; + }; -const linkerscript_path = build_root ++ "/rp2040.ld"; + pub const waveshare = struct { + pub const rp2040_plus_4m = .{ + .preferred_format = .{ .uf2 = .RP2040 }, + .chip = chip, + .hal = hal, + .linker_script = linker_script, + .board = .{ + .name = "Waveshare RP2040-Plus (4M Flash)", + .source_file = .{ .cwd_relative = build_root ++ "/src/boards/waveshare_rp2040_plus_4m.zig" }, + .url = "https://www.waveshare.com/rp2040-plus.htm", + }, + .configure = rp2040_configure(.w25q080), + }; + + pub const rp2040_plus_16m = .{ + .preferred_format = .{ .uf2 = .RP2040 }, + .chip = chip, + .hal = hal, + .linker_script = linker_script, + .board = .{ + .name = "Waveshare RP2040-Plus (16M Flash)", + .source_file = .{ .cwd_relative = build_root ++ "/src/boards/waveshare_rp2040_plus_16m.zig" }, + .url = "https://www.waveshare.com/rp2040-plus.htm", + }, + .configure = rp2040_configure(.w25q080), + }; + + pub const rp2040_eth = .{ + .preferred_format = .{ .uf2 = .RP2040 }, + .chip = chip, + .hal = hal, + .linker_script = linker_script, + .board = .{ + .name = "Waveshare RP2040-ETH Mini", + .source_file = .{ .cwd_relative = build_root ++ "/src/boards/waveshare_rp2040_eth.zig" }, + .url = "https://www.waveshare.com/rp2040-eth.htm", + }, + .configure = rp2040_configure(.w25q080), + }; + + pub const rp2040_matrix = .{ + .preferred_format = .{ .uf2 = .RP2040 }, + .chip = chip, + .hal = hal, + .linker_script = linker_script, + .board = .{ + .name = "Waveshare RP2040-Matrix", + .source_file = .{ .cwd_relative = build_root ++ "/src/boards/waveshare_rp2040_matrix.zig" }, + .url = "https://www.waveshare.com/rp2040-matrix.htm", + }, + .configure = rp2040_configure(.w25q080), + }; + }; +}; pub const BootROM = union(enum) { artifact: *std.build.CompileStep, // provide a custom startup code @@ -26,24 +112,54 @@ pub const BootROM = union(enum) { legacy, }; -pub const PicoExecutableOptions = struct { - name: []const u8, - source_file: std.Build.LazyPath, - optimize: std.builtin.OptimizeMode = .Debug, +const linker_script = .{ + .source_file = .{ .cwd_relative = build_root ++ "/rp2040.ld" }, +}; - board: boards.Board = boards.raspberry_pi_pico, +const hal = .{ + .source_file = .{ .cwd_relative = build_root ++ "/src/hal.zig" }, +}; - bootrom: ?BootROM = null, +const chip = .{ + .name = "RP2040", + .url = "https://www.raspberrypi.com/products/rp2040/", + .cpu = .cortex_m0plus, + .register_definition = .{ + .json = .{ .cwd_relative = build_root ++ "/src/chips/RP2040.json" }, + }, + .memory_regions = &.{ + .{ .kind = .flash, .offset = 0x10000100, .length = (2048 * 1024) - 256 }, + .{ .kind = .flash, .offset = 0x10000000, .length = 256 }, + .{ .kind = .ram, .offset = 0x20000000, .length = 256 * 1024 }, + }, }; -pub const addPiPicoExecutable = addExecutable; // Deprecated, use addExecutable! +/// Returns a configuration function that will add the provided `BootROM` to the firmware. +pub fn rp2040_configure(comptime bootrom: BootROM) *const fn (host_build: *std.Build, *microzig.Firmware) void { + const T = struct { + fn configure(host_build: *std.Build, fw: *microzig.Firmware) void { + const bootrom_file = getBootrom(host_build, bootrom); + + // HACK: Inject the file as a dependency to MicroZig.board + fw.modules.board.?.dependencies.put( + "bootloader", + host_build.createModule(.{ + .source_file = bootrom_file.bin, + }), + ) catch @panic("oom"); + bootrom_file.bin.addStepDependencies(&fw.artifact.step); + } + }; + + return T.configure; +} pub const Stage2Bootloader = struct { bin: std.Build.LazyPath, elf: ?std.Build.LazyPath, }; -pub fn getBootrom(b: *Build, rom: BootROM) Stage2Bootloader { +pub fn getBootrom(b: *std.Build, rom: BootROM) Stage2Bootloader { const rom_exe = switch (rom) { .artifact => |artifact| artifact, .blob => |blob| return Stage2Bootloader{ @@ -52,7 +168,7 @@ pub fn getBootrom(b: *Build, rom: BootROM) Stage2Bootloader { }, else => blk: { - var target = chips.rp2040.cpu.target; + var target = @as(microzig.CpuModel, chip.cpu).getDescriptor().target; target.abi = .eabi; const rom_path = b.pathFromRoot(b.fmt("{s}/src/bootroms/{s}.S", .{ build_root, @tagName(rom) })); @@ -84,134 +200,106 @@ pub fn getBootrom(b: *Build, rom: BootROM) Stage2Bootloader { }; } -pub fn addExecutable( - b: *Build, - opts: PicoExecutableOptions, -) *microzig.EmbeddedExecutable { - var exe = microzig.addEmbeddedExecutable(b, .{ - .name = opts.name, - .source_file = opts.source_file, - .backing = .{ .board = opts.board.inner }, - .optimize = opts.optimize, - .linkerscript_source_file = .{ .path = linkerscript_path }, - }); - - const i: *std.Build.CompileStep = exe.inner; - - const bootrom_file = getBootrom(b, opts.bootrom orelse opts.board.bootrom); - - // HACK: Inject the file as a dependency to MicroZig.board - i.modules.get("microzig").?.dependencies.get("board").?.dependencies.put( - "bootloader", - b.createModule(.{ - .source_file = bootrom_file.bin, - }), - ) catch @panic("oom"); - bootrom_file.bin.addStepDependencies(&i.step); - - return exe; -} - -// this build script is mostly for testing and verification of this -// package. In an attempt to modularize -- designing for a case where a -// project requires multiple HALs, it accepts microzig as a param -pub fn build(b: *Build) !void { - const optimize = b.standardOptimizeOption(.{}); - - const args_dep = b.dependency("args", .{}); - const args_mod = args_dep.module("args"); - - var examples = Examples.init(b, optimize); - examples.install(b); - - const pio_tests = b.addTest(.{ - .root_source_file = .{ - .path = "src/hal.zig", - }, - .optimize = optimize, - }); - pio_tests.addIncludePath(.{ .path = "src/hal/pio/assembler" }); - - const test_step = b.step("test", "run unit tests"); - test_step.dependOn(&b.addRunArtifact(pio_tests).step); - - { - const flash_tool = b.addExecutable(.{ - .name = "rp2040-flash", - .optimize = .Debug, - .target = .{}, - .root_source_file = .{ .path = "tools/rp2040-flash.zig" }, - }); - flash_tool.addModule("args", args_mod); - - b.installArtifact(flash_tool); - } - - // Install all bootroms for debugging and CI - inline for (comptime std.enums.values(std.meta.Tag(BootROM))) |rom| { - if (rom == .artifact or rom == .blob) { - continue; - } - - if (rom == .is25lp080) { - // TODO: https://github.com/ZigEmbeddedGroup/raspberrypi-rp2040/issues/79 - // is25lp080.o:(text+0x16): has non-ABS relocation R_ARM_THM_CALL against symbol 'read_flash_sreg' - continue; - } - - const files = getBootrom(b, rom); - if (files.elf) |elf| { - b.getInstallStep().dependOn( - &b.addInstallFileWithDir(elf, .{ .custom = "stage2" }, b.fmt("{s}.elf", .{@tagName(rom)})).step, - ); - } - b.getInstallStep().dependOn( - &b.addInstallFileWithDir(files.bin, .{ .custom = "stage2" }, b.fmt("{s}.bin", .{@tagName(rom)})).step, - ); - } -} - -fn root() []const u8 { - return comptime (std.fs.path.dirname(@src().file) orelse ".") ++ "/"; -} - -pub const Examples = struct { - adc: *microzig.EmbeddedExecutable, - blinky: *microzig.EmbeddedExecutable, - blinky_core1: *microzig.EmbeddedExecutable, - gpio_clk: *microzig.EmbeddedExecutable, - i2c_bus_scan: *microzig.EmbeddedExecutable, - pwm: *microzig.EmbeddedExecutable, - spi_master: *microzig.EmbeddedExecutable, - uart: *microzig.EmbeddedExecutable, - squarewave: *microzig.EmbeddedExecutable, - //uart_pins: microzig.EmbeddedExecutable, - flash_program: *microzig.EmbeddedExecutable, - usb_device: *microzig.EmbeddedExecutable, - usb_hid: *microzig.EmbeddedExecutable, - ws2812: *microzig.EmbeddedExecutable, - random: *microzig.EmbeddedExecutable, - - pub fn init(b: *Build, optimize: std.builtin.OptimizeMode) Examples { - var ret: Examples = undefined; - inline for (@typeInfo(Examples).Struct.fields) |field| { - const path = comptime root() ++ "examples/" ++ field.name ++ ".zig"; - - @field(ret, field.name) = addExecutable(b, .{ - .name = field.name, - .source_file = .{ .path = path }, - .optimize = optimize, - }); - } - - return ret; - } - - pub fn install(examples: *Examples, b: *Build) void { - inline for (@typeInfo(Examples).Struct.fields) |field| { - b.getInstallStep().dependOn( - &b.addInstallFileWithDir(@field(examples, field.name).inner.getEmittedBin(), .{ .custom = "firmware" }, field.name ++ ".elf").step, - ); - } - } -}; +///////////////////////////////////////// +// MicroZig Legacy Interface // +///////////////////////////////////////// + +// // this build script is mostly for testing and verification of this +// // package. In an attempt to modularize -- designing for a case where a +// // project requires multiple HALs, it accepts microzig as a param +// pub fn build(b: *Build) !void { +// const optimize = b.standardOptimizeOption(.{}); + +// const args_dep = b.dependency("args", .{}); +// const args_mod = args_dep.module("args"); + +// var examples = Examples.init(b, optimize); +// examples.install(b); + +// const pio_tests = b.addTest(.{ +// .root_source_file = .{ +// .path = "src/hal.zig", +// }, +// .optimize = optimize, +// }); +// pio_tests.addIncludePath(.{ .path = "src/hal/pio/assembler" }); + +// const test_step = b.step("test", "run unit tests"); +// test_step.dependOn(&b.addRunArtifact(pio_tests).step); + +// { +// const flash_tool = b.addExecutable(.{ +// .name = "rp2040-flash", +// .optimize = .Debug, +// .target = .{}, +// .root_source_file = .{ .path = "tools/rp2040-flash.zig" }, +// }); +// flash_tool.addModule("args", args_mod); + +// b.installArtifact(flash_tool); +// } + +// // Install all bootroms for debugging and CI +// inline for (comptime std.enums.values(std.meta.Tag(BootROM))) |rom| { +// if (rom == .artifact or rom == .blob) { +// continue; +// } + +// if (rom == .is25lp080) { +// // TODO: https://github.com/ZigEmbeddedGroup/raspberrypi-rp2040/issues/79 +// // is25lp080.o:(text+0x16): has non-ABS relocation R_ARM_THM_CALL against symbol 'read_flash_sreg' +// continue; +// } + +// const files = getBootrom(b, rom); +// if (files.elf) |elf| { +// b.getInstallStep().dependOn( +// &b.addInstallFileWithDir(elf, .{ .custom = "stage2" }, b.fmt("{s}.elf", .{@tagName(rom)})).step, +// ); +// } +// b.getInstallStep().dependOn( +// &b.addInstallFileWithDir(files.bin, .{ .custom = "stage2" }, b.fmt("{s}.bin", .{@tagName(rom)})).step, +// ); +// } +// } + +// pub const Examples = struct { +// adc: *microzig.EmbeddedExecutable, +// blinky: *microzig.EmbeddedExecutable, +// blinky_core1: *microzig.EmbeddedExecutable, +// gpio_clk: *microzig.EmbeddedExecutable, +// i2c_bus_scan: *microzig.EmbeddedExecutable, +// pwm: *microzig.EmbeddedExecutable, +// spi_master: *microzig.EmbeddedExecutable, +// uart: *microzig.EmbeddedExecutable, +// squarewave: *microzig.EmbeddedExecutable, +// //uart_pins: microzig.EmbeddedExecutable, +// flash_program: *microzig.EmbeddedExecutable, +// usb_device: *microzig.EmbeddedExecutable, +// usb_hid: *microzig.EmbeddedExecutable, +// ws2812: *microzig.EmbeddedExecutable, +// random: *microzig.EmbeddedExecutable, + +// pub fn init(b: *Build, optimize: std.builtin.OptimizeMode) Examples { +// var ret: Examples = undefined; +// inline for (@typeInfo(Examples).Struct.fields) |field| { +// const path = comptime root() ++ "examples/" ++ field.name ++ ".zig"; + +// @field(ret, field.name) = addExecutable(b, .{ +// .name = field.name, +// .source_file = .{ .path = path }, +// .optimize = optimize, +// }); +// } + +// return ret; +// } + +// pub fn install(examples: *Examples, b: *Build) void { +// inline for (@typeInfo(Examples).Struct.fields) |field| { +// b.getInstallStep().dependOn( +// &b.addInstallFileWithDir(@field(examples, field.name).inner.getEmittedBin(), .{ .custom = "firmware" }, field.name ++ ".elf").step, +// ); +// } +// } +// }; diff --git a/build.zig.zon b/build.zig.zon index cfb4ad4..9fb2765 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -2,10 +2,10 @@ .name = "rp2040", .version = "0.0.0", .dependencies = .{ - .microzig = .{ - .url = "https://github.com/ZigEmbeddedGroup/microzig/archive/0b3be0a4cc7e6d45714cb09961efc771e364723c.tar.gz", - .hash = "1220ada6d01db7b3d0aa8642df89b1af9ee71b681438249e9a7efb2275fc4cf32152", - }, + // .microzig = .{ + // .url = "https://github.com/ZigEmbeddedGroup/microzig/archive/0b3be0a4cc7e6d45714cb09961efc771e364723c.tar.gz", + // .hash = "1220ada6d01db7b3d0aa8642df89b1af9ee71b681438249e9a7efb2275fc4cf32152", + // }, .args = .{ .url = "https://github.com/MasterQ32/zig-args/archive/91d1e89fb89a4d01dec7c9aec95b0a324080ebcc.tar.gz", .hash = "12203d04cafc97f952d74cdb077e74c0ab3414f9f6b5fbd159112c62bfa584a0dbed", diff --git a/src/boards.zig b/src/boards.zig deleted file mode 100644 index 8f68040..0000000 --- a/src/boards.zig +++ /dev/null @@ -1,69 +0,0 @@ -const std = @import("std"); -const microzig = @import("microzig"); -const rp2040 = @import("../build.zig"); -const chips = @import("chips.zig"); - -fn root_dir() []const u8 { - return std.fs.path.dirname(@src().file) orelse "."; -} - -fn board_path(comptime path: []const u8) std.Build.LazyPath { - return .{ - .path = std.fmt.comptimePrint("{s}/boards/{s}", .{ root_dir(), path }), - }; -} - -pub const Board = struct { - inner: microzig.Board, - bootrom: rp2040.BootROM, -}; - -// https://www.raspberrypi.com/products/raspberry-pi-pico/ -pub const raspberry_pi_pico = Board{ - .inner = .{ - .name = "Raspberry Pi Pico", - .source = board_path("raspberry_pi_pico.zig"), - .chip = chips.rp2040, - }, - .bootrom = .w25q080, -}; - -// https://www.waveshare.com/rp2040-plus.htm -pub const waveshare_rp2040_plus_4m = Board{ - .inner = .{ - .name = "Waveshare RP2040-Plus (4M Flash)", - .source = board_path("waveshare_rp2040_plus_4m.zig"), - .chip = chips.rp2040, - }, - .bootrom = .w25q080, -}; - -// https://www.waveshare.com/rp2040-plus.htm -pub const waveshare_rp2040_plus_16m = Board{ - .inner = .{ - .name = "Waveshare RP2040-Plus (16M Flash)", - .source = board_path("waveshare_rp2040_plus_16m.zig"), - .chip = chips.rp2040, - }, - .bootrom = .w25q080, -}; - -// https://www.waveshare.com/rp2040-eth.htm -pub const waveshare_rp2040_eth = Board{ - .inner = .{ - .name = "Waveshare RP2040-ETH Mini", - .source = board_path("waveshare_rp2040_eth.zig"), - .chip = chips.rp2040, - }, - .bootrom = .w25q080, -}; - -// https://www.waveshare.com/rp2040-matrix.htm -pub const waveshare_rp2040_matrix = Board{ - .inner = .{ - .name = "Waveshare RP2040-Matrix", - .source = board_path("waveshare_rp2040_matrix.zig"), - .chip = chips.rp2040, - }, - .bootrom = .w25q080, -}; diff --git a/src/bootroms/w25q32jvssiq.S b/src/bootroms/w25q32jvssiq.S new file mode 100644 index 0000000..a122d72 --- /dev/null +++ b/src/bootroms/w25q32jvssiq.S @@ -0,0 +1,42 @@ + +// This blob was read from the original RP2040-ETH board +// and is assumed to be working with the W25Q32JVSSIQ flash. + +.text +.global _stage2_boot +_stage2_boot: + +// 00000000 00 b5 32 4b 21 20 58 60 98 68 02 21 88 43 98 60 |..2K! X`.h.!.C.`| +// 00000010 d8 60 18 61 58 61 2e 4b 00 21 99 60 02 21 59 61 |.`.aXa.K.!.`.!Ya| +// 00000020 01 21 f0 22 99 50 2b 49 19 60 01 21 99 60 35 20 |.!.".P+I.`.!.`5 | +// 00000030 00 f0 44 f8 02 22 90 42 14 d0 06 21 19 66 00 f0 |..D..".B...!.f..| +// 00000040 34 f8 19 6e 01 21 19 66 00 20 18 66 1a 66 00 f0 |4..n.!.f. .f.f..| +// 00000050 2c f8 19 6e 19 6e 19 6e 05 20 00 f0 2f f8 01 21 |,..n.n.n. ../..!| +// 00000060 08 42 f9 d1 00 21 99 60 1b 49 19 60 00 21 59 60 |.B...!.`.I.`.!Y`| +// 00000070 1a 49 1b 48 01 60 01 21 99 60 eb 21 19 66 a0 21 |.I.H.`.!.`.!.f.!| +// 00000080 19 66 00 f0 12 f8 00 21 99 60 16 49 14 48 01 60 |.f.....!.`.I.H.`| +// 00000090 01 21 99 60 01 bc 00 28 00 d0 00 47 12 48 13 49 |.!.`...(...G.H.I| +// 000000a0 08 60 03 c8 80 f3 08 88 08 47 03 b5 99 6a 04 20 |.`.......G...j. | +// 000000b0 01 42 fb d0 01 20 01 42 f8 d1 03 bd 02 b5 18 66 |.B... .B.......f| +// 000000c0 18 66 ff f7 f2 ff 18 6e 18 6e 02 bd 00 00 02 40 |.f.....n.n.....@| +// 000000d0 00 00 00 18 00 00 07 00 00 03 5f 00 21 22 00 00 |.........._.!"..| +// 000000e0 f4 00 00 18 22 20 00 a0 00 01 00 10 08 ed 00 e0 |...." ..........| +// 000000f0 00 00 00 00 00 00 00 00 00 00 00 00 74 b2 4e 7a |............t.Nz| + +.byte 0x00, 0xb5, 0x32, 0x4b, 0x21, 0x20, 0x58, 0x60, 0x98, 0x68, 0x02, 0x21, 0x88, 0x43, 0x98, 0x60 +.byte 0xd8, 0x60, 0x18, 0x61, 0x58, 0x61, 0x2e, 0x4b, 0x00, 0x21, 0x99, 0x60, 0x02, 0x21, 0x59, 0x61 +.byte 0x01, 0x21, 0xf0, 0x22, 0x99, 0x50, 0x2b, 0x49, 0x19, 0x60, 0x01, 0x21, 0x99, 0x60, 0x35, 0x20 +.byte 0x00, 0xf0, 0x44, 0xf8, 0x02, 0x22, 0x90, 0x42, 0x14, 0xd0, 0x06, 0x21, 0x19, 0x66, 0x00, 0xf0 +.byte 0x34, 0xf8, 0x19, 0x6e, 0x01, 0x21, 0x19, 0x66, 0x00, 0x20, 0x18, 0x66, 0x1a, 0x66, 0x00, 0xf0 +.byte 0x2c, 0xf8, 0x19, 0x6e, 0x19, 0x6e, 0x19, 0x6e, 0x05, 0x20, 0x00, 0xf0, 0x2f, 0xf8, 0x01, 0x21 +.byte 0x08, 0x42, 0xf9, 0xd1, 0x00, 0x21, 0x99, 0x60, 0x1b, 0x49, 0x19, 0x60, 0x00, 0x21, 0x59, 0x60 +.byte 0x1a, 0x49, 0x1b, 0x48, 0x01, 0x60, 0x01, 0x21, 0x99, 0x60, 0xeb, 0x21, 0x19, 0x66, 0xa0, 0x21 +.byte 0x19, 0x66, 0x00, 0xf0, 0x12, 0xf8, 0x00, 0x21, 0x99, 0x60, 0x16, 0x49, 0x14, 0x48, 0x01, 0x60 +.byte 0x01, 0x21, 0x99, 0x60, 0x01, 0xbc, 0x00, 0x28, 0x00, 0xd0, 0x00, 0x47, 0x12, 0x48, 0x13, 0x49 +.byte 0x08, 0x60, 0x03, 0xc8, 0x80, 0xf3, 0x08, 0x88, 0x08, 0x47, 0x03, 0xb5, 0x99, 0x6a, 0x04, 0x20 +.byte 0x01, 0x42, 0xfb, 0xd0, 0x01, 0x20, 0x01, 0x42, 0xf8, 0xd1, 0x03, 0xbd, 0x02, 0xb5, 0x18, 0x66 +.byte 0x18, 0x66, 0xff, 0xf7, 0xf2, 0xff, 0x18, 0x6e, 0x18, 0x6e, 0x02, 0xbd, 0x00, 0x00, 0x02, 0x40 +.byte 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x5f, 0x00, 0x21, 0x22, 0x00, 0x00 +.byte 0xf4, 0x00, 0x00, 0x18, 0x22, 0x20, 0x00, 0xa0, 0x00, 0x01, 0x00, 0x10, 0x08, 0xed, 0x00, 0xe0 +.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0xb2, 0x4e, 0x7a + diff --git a/src/chips.zig b/src/chips.zig deleted file mode 100644 index 48b20e0..0000000 --- a/src/chips.zig +++ /dev/null @@ -1,25 +0,0 @@ -const std = @import("std"); -const microzig = @import("microzig"); - -fn root_dir() []const u8 { - return std.fs.path.dirname(@src().file) orelse "."; -} - -const chip_path = std.fmt.comptimePrint("{s}/chips/RP2040.zig", .{root_dir()}); -const hal_path = std.fmt.comptimePrint("{s}/hal.zig", .{root_dir()}); -const json_register_schema_path = std.fmt.comptimePrint("{s}/chips/RP2040.json", .{root_dir()}); - -pub const rp2040 = microzig.Chip{ - .name = "RP2040", - .source = .{ .path = chip_path }, - .hal = .{ .path = hal_path }, - .cpu = microzig.cpus.cortex_m0plus, - .memory_regions = &.{ - .{ .kind = .flash, .offset = 0x10000100, .length = (2048 * 1024) - 256 }, - .{ .kind = .flash, .offset = 0x10000000, .length = 256 }, - .{ .kind = .ram, .offset = 0x20000000, .length = 256 * 1024 }, - }, - .json_register_schema = .{ - .path = json_register_schema_path, - }, -}; diff --git a/src/chips/RP2040.zig b/src/chips/RP2040.zig deleted file mode 100644 index a11f255..0000000 --- a/src/chips/RP2040.zig +++ /dev/null @@ -1,18145 +0,0 @@ -const micro = @import("microzig"); -const mmio = micro.mmio; - -pub const devices = struct { - pub const RP2040 = struct { - pub const properties = struct { - pub const @"cpu.nvic_prio_bits" = "2"; - pub const @"cpu.mpu" = "true"; - pub const @"cpu.fpu" = "false"; - pub const @"cpu.num_interrupts" = "26"; - pub const @"cpu.vtor" = "1"; - pub const @"cpu.revision" = "r0p1"; - pub const @"cpu.vendor_systick_config" = "false"; - pub const license = - \\ - \\ Copyright (c) 2020 Raspberry Pi (Trading) Ltd. \n - \\ \n - \\ SPDX-License-Identifier: BSD-3-Clause - \\ - ; - pub const @"cpu.name" = "CM0PLUS"; - pub const @"cpu.endian" = "little"; - }; - - pub const VectorTable = extern struct { - const Handler = micro.interrupt.Handler; - const unhandled = micro.interrupt.unhandled; - - initial_stack_pointer: u32, - Reset: Handler = unhandled, - NMI: Handler = unhandled, - HardFault: Handler = unhandled, - reserved2: [7]u32 = undefined, - SVCall: Handler = unhandled, - reserved10: [2]u32 = undefined, - PendSV: Handler = unhandled, - SysTick: Handler = unhandled, - TIMER_IRQ_0: Handler = unhandled, - TIMER_IRQ_1: Handler = unhandled, - TIMER_IRQ_2: Handler = unhandled, - TIMER_IRQ_3: Handler = unhandled, - PWM_IRQ_WRAP: Handler = unhandled, - USBCTRL_IRQ: Handler = unhandled, - XIP_IRQ: Handler = unhandled, - PIO0_IRQ_0: Handler = unhandled, - PIO0_IRQ_1: Handler = unhandled, - PIO1_IRQ_0: Handler = unhandled, - PIO1_IRQ_1: Handler = unhandled, - DMA_IRQ_0: Handler = unhandled, - DMA_IRQ_1: Handler = unhandled, - IO_IRQ_BANK0: Handler = unhandled, - IO_IRQ_QSPI: Handler = unhandled, - SIO_IRQ_PROC0: Handler = unhandled, - SIO_IRQ_PROC1: Handler = unhandled, - CLOCKS_IRQ: Handler = unhandled, - SPI0_IRQ: Handler = unhandled, - SPI1_IRQ: Handler = unhandled, - UART0_IRQ: Handler = unhandled, - UART1_IRQ: Handler = unhandled, - ADC_IRQ_FIFO: Handler = unhandled, - I2C0_IRQ: Handler = unhandled, - I2C1_IRQ: Handler = unhandled, - RTC_IRQ: Handler = unhandled, - }; - - pub const peripherals = struct { - /// System Control Space - pub const MPU = @as(*volatile types.peripherals.SCS, @ptrFromInt(0xd90)); - /// QSPI flash execute-in-place block - pub const XIP_CTRL = @as(*volatile types.peripherals.XIP_CTRL, @ptrFromInt(0x14000000)); - /// DW_apb_ssi has the following features: - /// * APB interface – Allows for easy integration into a DesignWare Synthesizable Components for AMBA 2 implementation. - /// * APB3 and APB4 protocol support. - /// * Scalable APB data bus width – Supports APB data bus widths of 8, 16, and 32 bits. - /// * Serial-master or serial-slave operation – Enables serial communication with serial-master or serial-slave peripheral devices. - /// * Programmable Dual/Quad/Octal SPI support in Master Mode. - /// * Dual Data Rate (DDR) and Read Data Strobe (RDS) Support - Enables the DW_apb_ssi master to perform operations with the device in DDR and RDS modes when working in Dual/Quad/Octal mode of operation. - /// * Data Mask Support - Enables the DW_apb_ssi to selectively update the bytes in the device. This feature is applicable only in enhanced SPI modes. - /// * eXecute-In-Place (XIP) support - Enables the DW_apb_ssi master to behave as a memory mapped I/O and fetches the data from the device based on the APB read request. This feature is applicable only in enhanced SPI modes. - /// * DMA Controller Interface – Enables the DW_apb_ssi to interface to a DMA controller over the bus using a handshaking interface for transfer requests. - /// * Independent masking of interrupts – Master collision, transmit FIFO overflow, transmit FIFO empty, receive FIFO full, receive FIFO underflow, and receive FIFO overflow interrupts can all be masked independently. - /// * Multi-master contention detection – Informs the processor of multiple serial-master accesses on the serial bus. - /// * Bypass of meta-stability flip-flops for synchronous clocks – When the APB clock (pclk) and the DW_apb_ssi serial clock (ssi_clk) are synchronous, meta-stable flip-flops are not used when transferring control signals across these clock domains. - /// * Programmable delay on the sample time of the received serial data bit (rxd); enables programmable control of routing delays resulting in higher serial data-bit rates. - /// * Programmable features: - /// - Serial interface operation – Choice of Motorola SPI, Texas Instruments Synchronous Serial Protocol or National Semiconductor Microwire. - /// - Clock bit-rate – Dynamic control of the serial bit rate of the data transfer; used in only serial-master mode of operation. - /// - Data Item size (4 to 32 bits) – Item size of each data transfer under the control of the programmer. - /// * Configured features: - /// - FIFO depth – 16 words deep. The FIFO width is fixed at 32 bits. - /// - 1 slave select output. - /// - Hardware slave-select – Dedicated hardware slave-select line. - /// - Combined interrupt line - one combined interrupt line from the DW_apb_ssi to the interrupt controller. - /// - Interrupt polarity – active high interrupt lines. - /// - Serial clock polarity – low serial-clock polarity directly after reset. - /// - Serial clock phase – capture on first edge of serial-clock directly after reset. - pub const XIP_SSI = @as(*volatile types.peripherals.XIP_SSI, @ptrFromInt(0x18000000)); - pub const SYSINFO = @as(*volatile types.peripherals.SYSINFO, @ptrFromInt(0x40000000)); - /// Register block for various chip control signals - pub const SYSCFG = @as(*volatile types.peripherals.SYSCFG, @ptrFromInt(0x40004000)); - pub const CLOCKS = @as(*volatile types.peripherals.CLOCKS, @ptrFromInt(0x40008000)); - pub const RESETS = @as(*volatile types.peripherals.RESETS, @ptrFromInt(0x4000c000)); - pub const PSM = @as(*volatile types.peripherals.PSM, @ptrFromInt(0x40010000)); - pub const IO_BANK0 = @as(*volatile types.peripherals.IO_BANK0, @ptrFromInt(0x40014000)); - pub const IO_QSPI = @as(*volatile types.peripherals.IO_QSPI, @ptrFromInt(0x40018000)); - pub const PADS_BANK0 = @as(*volatile types.peripherals.PADS_BANK0, @ptrFromInt(0x4001c000)); - pub const PADS_QSPI = @as(*volatile types.peripherals.PADS_QSPI, @ptrFromInt(0x40020000)); - /// Controls the crystal oscillator - pub const XOSC = @as(*volatile types.peripherals.XOSC, @ptrFromInt(0x40024000)); - pub const PLL_SYS = @as(*volatile types.peripherals.PLL_SYS, @ptrFromInt(0x40028000)); - pub const PLL_USB = @as(*volatile types.peripherals.PLL_SYS, @ptrFromInt(0x4002c000)); - /// Register block for busfabric control signals and performance counters - pub const BUSCTRL = @as(*volatile types.peripherals.BUSCTRL, @ptrFromInt(0x40030000)); - pub const UART0 = @as(*volatile types.peripherals.UART0, @ptrFromInt(0x40034000)); - pub const UART1 = @as(*volatile types.peripherals.UART0, @ptrFromInt(0x40038000)); - pub const SPI0 = @as(*volatile types.peripherals.SPI0, @ptrFromInt(0x4003c000)); - pub const SPI1 = @as(*volatile types.peripherals.SPI0, @ptrFromInt(0x40040000)); - /// DW_apb_i2c address block - /// List of configuration constants for the Synopsys I2C hardware (you may see references to these in I2C register header; these are *fixed* values, set at hardware design time): - /// IC_ULTRA_FAST_MODE ................ 0x0 - /// IC_UFM_TBUF_CNT_DEFAULT ........... 0x8 - /// IC_UFM_SCL_LOW_COUNT .............. 0x0008 - /// IC_UFM_SCL_HIGH_COUNT ............. 0x0006 - /// IC_TX_TL .......................... 0x0 - /// IC_TX_CMD_BLOCK ................... 0x1 - /// IC_HAS_DMA ........................ 0x1 - /// IC_HAS_ASYNC_FIFO ................. 0x0 - /// IC_SMBUS_ARP ...................... 0x0 - /// IC_FIRST_DATA_BYTE_STATUS ......... 0x1 - /// IC_INTR_IO ........................ 0x1 - /// IC_MASTER_MODE .................... 0x1 - /// IC_DEFAULT_ACK_GENERAL_CALL ....... 0x1 - /// IC_INTR_POL ....................... 0x1 - /// IC_OPTIONAL_SAR ................... 0x0 - /// IC_DEFAULT_TAR_SLAVE_ADDR ......... 0x055 - /// IC_DEFAULT_SLAVE_ADDR ............. 0x055 - /// IC_DEFAULT_HS_SPKLEN .............. 0x1 - /// IC_FS_SCL_HIGH_COUNT .............. 0x0006 - /// IC_HS_SCL_LOW_COUNT ............... 0x0008 - /// IC_DEVICE_ID_VALUE ................ 0x0 - /// IC_10BITADDR_MASTER ............... 0x0 - /// IC_CLK_FREQ_OPTIMIZATION .......... 0x0 - /// IC_DEFAULT_FS_SPKLEN .............. 0x7 - /// IC_ADD_ENCODED_PARAMS ............. 0x0 - /// IC_DEFAULT_SDA_HOLD ............... 0x000001 - /// IC_DEFAULT_SDA_SETUP .............. 0x64 - /// IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT . 0x0 - /// IC_CLOCK_PERIOD ................... 100 - /// IC_EMPTYFIFO_HOLD_MASTER_EN ....... 1 - /// IC_RESTART_EN ..................... 0x1 - /// IC_TX_CMD_BLOCK_DEFAULT ........... 0x0 - /// IC_BUS_CLEAR_FEATURE .............. 0x0 - /// IC_CAP_LOADING .................... 100 - /// IC_FS_SCL_LOW_COUNT ............... 0x000d - /// APB_DATA_WIDTH .................... 32 - /// IC_SDA_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff - /// IC_SLV_DATA_NACK_ONLY ............. 0x1 - /// IC_10BITADDR_SLAVE ................ 0x0 - /// IC_CLK_TYPE ....................... 0x0 - /// IC_SMBUS_UDID_MSB ................. 0x0 - /// IC_SMBUS_SUSPEND_ALERT ............ 0x0 - /// IC_HS_SCL_HIGH_COUNT .............. 0x0006 - /// IC_SLV_RESTART_DET_EN ............. 0x1 - /// IC_SMBUS .......................... 0x0 - /// IC_OPTIONAL_SAR_DEFAULT ........... 0x0 - /// IC_PERSISTANT_SLV_ADDR_DEFAULT .... 0x0 - /// IC_USE_COUNTS ..................... 0x0 - /// IC_RX_BUFFER_DEPTH ................ 16 - /// IC_SCL_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff - /// IC_RX_FULL_HLD_BUS_EN ............. 0x1 - /// IC_SLAVE_DISABLE .................. 0x1 - /// IC_RX_TL .......................... 0x0 - /// IC_DEVICE_ID ...................... 0x0 - /// IC_HC_COUNT_VALUES ................ 0x0 - /// I2C_DYNAMIC_TAR_UPDATE ............ 0 - /// IC_SMBUS_CLK_LOW_MEXT_DEFAULT ..... 0xffffffff - /// IC_SMBUS_CLK_LOW_SEXT_DEFAULT ..... 0xffffffff - /// IC_HS_MASTER_CODE ................. 0x1 - /// IC_SMBUS_RST_IDLE_CNT_DEFAULT ..... 0xffff - /// IC_SMBUS_UDID_LSB_DEFAULT ......... 0xffffffff - /// IC_SS_SCL_HIGH_COUNT .............. 0x0028 - /// IC_SS_SCL_LOW_COUNT ............... 0x002f - /// IC_MAX_SPEED_MODE ................. 0x2 - /// IC_STAT_FOR_CLK_STRETCH ........... 0x0 - /// IC_STOP_DET_IF_MASTER_ACTIVE ...... 0x0 - /// IC_DEFAULT_UFM_SPKLEN ............. 0x1 - /// IC_TX_BUFFER_DEPTH ................ 16 - pub const I2C0 = @as(*volatile types.peripherals.I2C0, @ptrFromInt(0x40044000)); - /// DW_apb_i2c address block - /// List of configuration constants for the Synopsys I2C hardware (you may see references to these in I2C register header; these are *fixed* values, set at hardware design time): - /// IC_ULTRA_FAST_MODE ................ 0x0 - /// IC_UFM_TBUF_CNT_DEFAULT ........... 0x8 - /// IC_UFM_SCL_LOW_COUNT .............. 0x0008 - /// IC_UFM_SCL_HIGH_COUNT ............. 0x0006 - /// IC_TX_TL .......................... 0x0 - /// IC_TX_CMD_BLOCK ................... 0x1 - /// IC_HAS_DMA ........................ 0x1 - /// IC_HAS_ASYNC_FIFO ................. 0x0 - /// IC_SMBUS_ARP ...................... 0x0 - /// IC_FIRST_DATA_BYTE_STATUS ......... 0x1 - /// IC_INTR_IO ........................ 0x1 - /// IC_MASTER_MODE .................... 0x1 - /// IC_DEFAULT_ACK_GENERAL_CALL ....... 0x1 - /// IC_INTR_POL ....................... 0x1 - /// IC_OPTIONAL_SAR ................... 0x0 - /// IC_DEFAULT_TAR_SLAVE_ADDR ......... 0x055 - /// IC_DEFAULT_SLAVE_ADDR ............. 0x055 - /// IC_DEFAULT_HS_SPKLEN .............. 0x1 - /// IC_FS_SCL_HIGH_COUNT .............. 0x0006 - /// IC_HS_SCL_LOW_COUNT ............... 0x0008 - /// IC_DEVICE_ID_VALUE ................ 0x0 - /// IC_10BITADDR_MASTER ............... 0x0 - /// IC_CLK_FREQ_OPTIMIZATION .......... 0x0 - /// IC_DEFAULT_FS_SPKLEN .............. 0x7 - /// IC_ADD_ENCODED_PARAMS ............. 0x0 - /// IC_DEFAULT_SDA_HOLD ............... 0x000001 - /// IC_DEFAULT_SDA_SETUP .............. 0x64 - /// IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT . 0x0 - /// IC_CLOCK_PERIOD ................... 100 - /// IC_EMPTYFIFO_HOLD_MASTER_EN ....... 1 - /// IC_RESTART_EN ..................... 0x1 - /// IC_TX_CMD_BLOCK_DEFAULT ........... 0x0 - /// IC_BUS_CLEAR_FEATURE .............. 0x0 - /// IC_CAP_LOADING .................... 100 - /// IC_FS_SCL_LOW_COUNT ............... 0x000d - /// APB_DATA_WIDTH .................... 32 - /// IC_SDA_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff - /// IC_SLV_DATA_NACK_ONLY ............. 0x1 - /// IC_10BITADDR_SLAVE ................ 0x0 - /// IC_CLK_TYPE ....................... 0x0 - /// IC_SMBUS_UDID_MSB ................. 0x0 - /// IC_SMBUS_SUSPEND_ALERT ............ 0x0 - /// IC_HS_SCL_HIGH_COUNT .............. 0x0006 - /// IC_SLV_RESTART_DET_EN ............. 0x1 - /// IC_SMBUS .......................... 0x0 - /// IC_OPTIONAL_SAR_DEFAULT ........... 0x0 - /// IC_PERSISTANT_SLV_ADDR_DEFAULT .... 0x0 - /// IC_USE_COUNTS ..................... 0x0 - /// IC_RX_BUFFER_DEPTH ................ 16 - /// IC_SCL_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff - /// IC_RX_FULL_HLD_BUS_EN ............. 0x1 - /// IC_SLAVE_DISABLE .................. 0x1 - /// IC_RX_TL .......................... 0x0 - /// IC_DEVICE_ID ...................... 0x0 - /// IC_HC_COUNT_VALUES ................ 0x0 - /// I2C_DYNAMIC_TAR_UPDATE ............ 0 - /// IC_SMBUS_CLK_LOW_MEXT_DEFAULT ..... 0xffffffff - /// IC_SMBUS_CLK_LOW_SEXT_DEFAULT ..... 0xffffffff - /// IC_HS_MASTER_CODE ................. 0x1 - /// IC_SMBUS_RST_IDLE_CNT_DEFAULT ..... 0xffff - /// IC_SMBUS_UDID_LSB_DEFAULT ......... 0xffffffff - /// IC_SS_SCL_HIGH_COUNT .............. 0x0028 - /// IC_SS_SCL_LOW_COUNT ............... 0x002f - /// IC_MAX_SPEED_MODE ................. 0x2 - /// IC_STAT_FOR_CLK_STRETCH ........... 0x0 - /// IC_STOP_DET_IF_MASTER_ACTIVE ...... 0x0 - /// IC_DEFAULT_UFM_SPKLEN ............. 0x1 - /// IC_TX_BUFFER_DEPTH ................ 16 - pub const I2C1 = @as(*volatile types.peripherals.I2C0, @ptrFromInt(0x40048000)); - /// Control and data interface to SAR ADC - pub const ADC = @as(*volatile types.peripherals.ADC, @ptrFromInt(0x4004c000)); - /// Simple PWM - pub const PWM = @as(*volatile types.peripherals.PWM, @ptrFromInt(0x40050000)); - /// Controls time and alarms - /// time is a 64 bit value indicating the time in usec since power-on - /// timeh is the top 32 bits of time & timel is the bottom 32 bits - /// to change time write to timelw before timehw - /// to read time read from timelr before timehr - /// An alarm is set by setting alarm_enable and writing to the corresponding alarm register - /// When an alarm is pending, the corresponding alarm_running signal will be high - /// An alarm can be cancelled before it has finished by clearing the alarm_enable - /// When an alarm fires, the corresponding alarm_irq is set and alarm_running is cleared - /// To clear the interrupt write a 1 to the corresponding alarm_irq - pub const TIMER = @as(*volatile types.peripherals.TIMER, @ptrFromInt(0x40054000)); - pub const WATCHDOG = @as(*volatile types.peripherals.WATCHDOG, @ptrFromInt(0x40058000)); - /// Register block to control RTC - pub const RTC = @as(*volatile types.peripherals.RTC, @ptrFromInt(0x4005c000)); - pub const ROSC = @as(*volatile types.peripherals.ROSC, @ptrFromInt(0x40060000)); - /// control and status for on-chip voltage regulator and chip level reset subsystem - pub const VREG_AND_CHIP_RESET = @as(*volatile types.peripherals.VREG_AND_CHIP_RESET, @ptrFromInt(0x40064000)); - /// Testbench manager. Allows the programmer to know what platform their software is running on. - pub const TBMAN = @as(*volatile types.peripherals.TBMAN, @ptrFromInt(0x4006c000)); - /// DMA with separate read and write masters - pub const DMA = @as(*volatile types.peripherals.DMA, @ptrFromInt(0x50000000)); - /// DPRAM layout for USB device. - pub const USBCTRL_DPRAM = @as(*volatile types.peripherals.USBCTRL_DPRAM, @ptrFromInt(0x50100000)); - /// USB FS/LS controller device registers - pub const USBCTRL_REGS = @as(*volatile types.peripherals.USBCTRL_REGS, @ptrFromInt(0x50110000)); - /// Programmable IO block - pub const PIO0 = @as(*volatile types.peripherals.PIO0, @ptrFromInt(0x50200000)); - /// Programmable IO block - pub const PIO1 = @as(*volatile types.peripherals.PIO0, @ptrFromInt(0x50300000)); - /// Single-cycle IO block - /// Provides core-local and inter-core hardware for the two processors, with single-cycle access. - pub const SIO = @as(*volatile types.peripherals.SIO, @ptrFromInt(0xd0000000)); - pub const PPB = @as(*volatile types.peripherals.PPB, @ptrFromInt(0xe0000000)); - /// System Tick Timer - pub const SysTick = @as(*volatile types.peripherals.SysTick, @ptrFromInt(0xe000e010)); - /// System Control Space - pub const NVIC = @as(*volatile types.peripherals.NVIC, @ptrFromInt(0xe000e100)); - /// System Control Space - pub const SCB = @as(*volatile types.peripherals.SCB, @ptrFromInt(0xe000ed00)); - }; - }; -}; - -pub const types = struct { - pub const peripherals = struct { - /// System Tick Timer - pub const SysTick = extern struct { - /// SysTick Control and Status Register - CTRL: mmio.Mmio(packed struct(u32) { - ENABLE: u1, - TICKINT: u1, - CLKSOURCE: u1, - reserved16: u13, - COUNTFLAG: u1, - padding: u15, - }), - /// SysTick Reload Value Register - LOAD: mmio.Mmio(packed struct(u32) { - RELOAD: u24, - padding: u8, - }), - /// SysTick Current Value Register - VAL: mmio.Mmio(packed struct(u32) { - CURRENT: u24, - padding: u8, - }), - /// SysTick Calibration Register - CALIB: mmio.Mmio(packed struct(u32) { - TENMS: u24, - reserved30: u6, - SKEW: u1, - NOREF: u1, - }), - }; - - /// System Control Block - pub const SCB = extern struct { - CPUID: mmio.Mmio(packed struct(u32) { - REVISION: u4, - PARTNO: u12, - ARCHITECTURE: u4, - VARIANT: u4, - IMPLEMENTER: u8, - }), - /// Interrupt Control and State Register - ICSR: mmio.Mmio(packed struct(u32) { - VECTACTIVE: u9, - reserved12: u3, - VECTPENDING: u9, - reserved22: u1, - ISRPENDING: u1, - ISRPREEMPT: u1, - reserved25: u1, - PENDSTCLR: u1, - PENDSTSET: u1, - PENDSVCLR: u1, - PENDSVSET: u1, - reserved31: u2, - NMIPENDSET: u1, - }), - /// Vector Table Offset Register - VTOR: mmio.Mmio(packed struct(u32) { - reserved8: u8, - TBLOFF: u24, - }), - /// Application Interrupt and Reset Control Register - AIRCR: mmio.Mmio(packed struct(u32) { - reserved1: u1, - VECTCLRACTIVE: u1, - SYSRESETREQ: u1, - reserved15: u12, - ENDIANESS: u1, - VECTKEY: u16, - }), - /// System Control Register - SCR: mmio.Mmio(packed struct(u32) { - reserved1: u1, - SLEEPONEXIT: u1, - SLEEPDEEP: u1, - reserved4: u1, - SEVONPEND: u1, - padding: u27, - }), - /// Configuration Control Register - CCR: mmio.Mmio(packed struct(u32) { - reserved3: u3, - UNALIGN_TRP: u1, - reserved9: u5, - STKALIGN: u1, - padding: u22, - }), - reserved28: [4]u8, - /// System Handlers Priority Registers. [0] is RESERVED - SHP: u32, - reserved36: [4]u8, - /// System Handler Control and State Register - SHCSR: mmio.Mmio(packed struct(u32) { - reserved15: u15, - SVCALLPENDED: u1, - padding: u16, - }), - }; - - /// Nested Vectored Interrupt Controller - pub const NVIC = extern struct { - /// Interrupt Set Enable Register - ISER: mmio.Mmio(packed struct(u32) { - TIMER_IRQ_0: u1, - TIMER_IRQ_1: u1, - TIMER_IRQ_2: u1, - TIMER_IRQ_3: u1, - PWM_IRQ_WRAP: u1, - USBCTRL_IRQ: u1, - XIP_IRQ: u1, - PIO0_IRQ_0: u1, - PIO0_IRQ_1: u1, - PIO1_IRQ_0: u1, - PIO1_IRQ_1: u1, - DMA_IRQ_0: u1, - DMA_IRQ_1: u1, - IO_IRQ_BANK0: u1, - IO_IRQ_QSPI: u1, - SIO_IRQ_PROC0: u1, - SIO_IRQ_PROC1: u1, - CLOCKS_IRQ: u1, - SPI0_IRQ: u1, - SPI1_IRQ: u1, - UART0_IRQ: u1, - UART1_IRQ: u1, - ADC_IRQ_FIFO: u1, - I2C0_IRQ: u1, - I2C1_IRQ: u1, - RTC_IRQ: u1, - padding: u6, - }), - reserved128: [124]u8, - /// Interrupt Clear Enable Register - ICER: mmio.Mmio(packed struct(u32) { - TIMER_IRQ_0: u1, - TIMER_IRQ_1: u1, - TIMER_IRQ_2: u1, - TIMER_IRQ_3: u1, - PWM_IRQ_WRAP: u1, - USBCTRL_IRQ: u1, - XIP_IRQ: u1, - PIO0_IRQ_0: u1, - PIO0_IRQ_1: u1, - PIO1_IRQ_0: u1, - PIO1_IRQ_1: u1, - DMA_IRQ_0: u1, - DMA_IRQ_1: u1, - IO_IRQ_BANK0: u1, - IO_IRQ_QSPI: u1, - SIO_IRQ_PROC0: u1, - SIO_IRQ_PROC1: u1, - CLOCKS_IRQ: u1, - SPI0_IRQ: u1, - SPI1_IRQ: u1, - UART0_IRQ: u1, - UART1_IRQ: u1, - ADC_IRQ_FIFO: u1, - I2C0_IRQ: u1, - I2C1_IRQ: u1, - RTC_IRQ: u1, - padding: u6, - }), - reserved256: [124]u8, - /// Interrupt Set Pending Register - ISPR: mmio.Mmio(packed struct(u32) { - TIMER_IRQ_0: u1, - TIMER_IRQ_1: u1, - TIMER_IRQ_2: u1, - TIMER_IRQ_3: u1, - PWM_IRQ_WRAP: u1, - USBCTRL_IRQ: u1, - XIP_IRQ: u1, - PIO0_IRQ_0: u1, - PIO0_IRQ_1: u1, - PIO1_IRQ_0: u1, - PIO1_IRQ_1: u1, - DMA_IRQ_0: u1, - DMA_IRQ_1: u1, - IO_IRQ_BANK0: u1, - IO_IRQ_QSPI: u1, - SIO_IRQ_PROC0: u1, - SIO_IRQ_PROC1: u1, - CLOCKS_IRQ: u1, - SPI0_IRQ: u1, - SPI1_IRQ: u1, - UART0_IRQ: u1, - UART1_IRQ: u1, - ADC_IRQ_FIFO: u1, - I2C0_IRQ: u1, - I2C1_IRQ: u1, - RTC_IRQ: u1, - padding: u6, - }), - reserved384: [124]u8, - /// Interrupt Clear Pending Register - ICPR: mmio.Mmio(packed struct(u32) { - TIMER_IRQ_0: u1, - TIMER_IRQ_1: u1, - TIMER_IRQ_2: u1, - TIMER_IRQ_3: u1, - PWM_IRQ_WRAP: u1, - USBCTRL_IRQ: u1, - XIP_IRQ: u1, - PIO0_IRQ_0: u1, - PIO0_IRQ_1: u1, - PIO1_IRQ_0: u1, - PIO1_IRQ_1: u1, - DMA_IRQ_0: u1, - DMA_IRQ_1: u1, - IO_IRQ_BANK0: u1, - IO_IRQ_QSPI: u1, - SIO_IRQ_PROC0: u1, - SIO_IRQ_PROC1: u1, - CLOCKS_IRQ: u1, - SPI0_IRQ: u1, - SPI1_IRQ: u1, - UART0_IRQ: u1, - UART1_IRQ: u1, - ADC_IRQ_FIFO: u1, - I2C0_IRQ: u1, - I2C1_IRQ: u1, - RTC_IRQ: u1, - padding: u6, - }), - reserved768: [380]u8, - /// Interrupt Priority Register - IPR0: mmio.Mmio(packed struct(u32) { - reserved6: u6, - TIMER_IRQ_0: u2, - reserved14: u6, - TIMER_IRQ_1: u2, - reserved22: u6, - TIMER_IRQ_2: u2, - reserved30: u6, - TIMER_IRQ_3: u2, - }), - /// Interrupt Priority Register - IPR1: mmio.Mmio(packed struct(u32) { - reserved6: u6, - PWM_IRQ_WRAP: u2, - reserved14: u6, - USBCTRL_IRQ: u2, - reserved22: u6, - XIP_IRQ: u2, - reserved30: u6, - PIO0_IRQ_0: u2, - }), - /// Interrupt Priority Register - IPR2: mmio.Mmio(packed struct(u32) { - reserved6: u6, - PIO0_IRQ_1: u2, - reserved14: u6, - PIO1_IRQ_0: u2, - reserved22: u6, - PIO1_IRQ_1: u2, - reserved30: u6, - DMA_IRQ_0: u2, - }), - /// Interrupt Priority Register - IPR3: mmio.Mmio(packed struct(u32) { - reserved6: u6, - DMA_IRQ_1: u2, - reserved14: u6, - IO_IRQ_BANK0: u2, - reserved22: u6, - IO_IRQ_QSPI: u2, - reserved30: u6, - SIO_IRQ_PROC0: u2, - }), - /// Interrupt Priority Register - IPR4: mmio.Mmio(packed struct(u32) { - reserved6: u6, - SIO_IRQ_PROC1: u2, - reserved14: u6, - CLOCKS_IRQ: u2, - reserved22: u6, - SPI0_IRQ: u2, - reserved30: u6, - SPI1_IRQ: u2, - }), - /// Interrupt Priority Register - IPR5: mmio.Mmio(packed struct(u32) { - reserved6: u6, - UART0_IRQ: u2, - reserved14: u6, - UART1_IRQ: u2, - reserved22: u6, - ADC_IRQ_FIFO: u2, - reserved30: u6, - I2C0_IRQ: u2, - }), - /// Interrupt Priority Register - IPR6: mmio.Mmio(packed struct(u32) { - reserved6: u6, - I2C1_IRQ: u2, - reserved14: u6, - RTC_IRQ: u2, - padding: u16, - }), - /// Interrupt Priority Register - IPR7: u32, - }; - - /// Memory Protection Unit - pub const MPU = extern struct { - /// MPU Type Register - TYPE: mmio.Mmio(packed struct(u32) { - SEPARATE: u1, - reserved8: u7, - DREGION: u8, - IREGION: u8, - padding: u8, - }), - /// MPU Control Register - CTRL: mmio.Mmio(packed struct(u32) { - ENABLE: u1, - HFNMIENA: u1, - PRIVDEFENA: u1, - padding: u29, - }), - /// MPU Region RNRber Register - RNR: mmio.Mmio(packed struct(u32) { - REGION: u8, - padding: u24, - }), - /// MPU Region Base Address Register - RBAR: mmio.Mmio(packed struct(u32) { - REGION: u4, - VALID: u1, - reserved8: u3, - ADDR: u24, - }), - /// MPU Region Attribute and Size Register - RASR: mmio.Mmio(packed struct(u32) { - ENABLE: u1, - SIZE: u5, - reserved8: u2, - SRD: u8, - B: u1, - C: u1, - S: u1, - TEX: u3, - reserved24: u2, - AP: u3, - reserved28: u1, - XN: u1, - padding: u3, - }), - }; - - /// QSPI flash execute-in-place block - pub const XIP_CTRL = extern struct { - /// Cache control - CTRL: mmio.Mmio(packed struct(u32) { - /// When 1, enable the cache. When the cache is disabled, all XIP accesses - /// will go straight to the flash, without querying the cache. When enabled, - /// cacheable XIP accesses will query the cache, and the flash will - /// not be accessed if the tag matches and the valid bit is set. - /// If the cache is enabled, cache-as-SRAM accesses have no effect on the - /// cache data RAM, and will produce a bus error response. - EN: u1, - /// When 1, writes to any alias other than 0x0 (caching, allocating) - /// will produce a bus fault. When 0, these writes are silently ignored. - /// In either case, writes to the 0x0 alias will deallocate on tag match, - /// as usual. - ERR_BADWRITE: u1, - reserved3: u1, - /// When 1, the cache memories are powered down. They retain state, - /// but can not be accessed. This reduces static power dissipation. - /// Writing 1 to this bit forces CTRL_EN to 0, i.e. the cache cannot - /// be enabled when powered down. - /// Cache-as-SRAM accesses will produce a bus error response when - /// the cache is powered down. - POWER_DOWN: u1, - padding: u28, - }), - /// Cache Flush control - FLUSH: mmio.Mmio(packed struct(u32) { - /// Write 1 to flush the cache. This clears the tag memory, but - /// the data memory retains its contents. (This means cache-as-SRAM - /// contents is not affected by flush or reset.) - /// Reading will hold the bus (stall the processor) until the flush - /// completes. Alternatively STAT can be polled until completion. - FLUSH: u1, - padding: u31, - }), - /// Cache Status - STAT: mmio.Mmio(packed struct(u32) { - /// Reads as 0 while a cache flush is in progress, and 1 otherwise. - /// The cache is flushed whenever the XIP block is reset, and also - /// when requested via the FLUSH register. - FLUSH_READY: u1, - /// When 1, indicates the XIP streaming FIFO is completely empty. - FIFO_EMPTY: u1, - /// When 1, indicates the XIP streaming FIFO is completely full. - /// The streaming FIFO is 2 entries deep, so the full and empty - /// flag allow its level to be ascertained. - FIFO_FULL: u1, - padding: u29, - }), - /// Cache Hit counter - /// A 32 bit saturating counter that increments upon each cache hit, - /// i.e. when an XIP access is serviced directly from cached data. - /// Write any value to clear. - CTR_HIT: u32, - /// Cache Access counter - /// A 32 bit saturating counter that increments upon each XIP access, - /// whether the cache is hit or not. This includes noncacheable accesses. - /// Write any value to clear. - CTR_ACC: u32, - /// FIFO stream address - STREAM_ADDR: mmio.Mmio(packed struct(u32) { - reserved2: u2, - /// The address of the next word to be streamed from flash to the streaming FIFO. - /// Increments automatically after each flash access. - /// Write the initial access address here before starting a streaming read. - STREAM_ADDR: u30, - }), - /// FIFO stream control - STREAM_CTR: mmio.Mmio(packed struct(u32) { - /// Write a nonzero value to start a streaming read. This will then - /// progress in the background, using flash idle cycles to transfer - /// a linear data block from flash to the streaming FIFO. - /// Decrements automatically (1 at a time) as the stream - /// progresses, and halts on reaching 0. - /// Write 0 to halt an in-progress stream, and discard any in-flight - /// read, so that a new stream can immediately be started (after - /// draining the FIFO and reinitialising STREAM_ADDR) - STREAM_CTR: u22, - padding: u10, - }), - /// FIFO stream data - /// Streamed data is buffered here, for retrieval by the system DMA. - /// This FIFO can also be accessed via the XIP_AUX slave, to avoid exposing - /// the DMA to bus stalls caused by other XIP traffic. - STREAM_FIFO: u32, - }; - - /// DW_apb_ssi has the following features: - /// * APB interface – Allows for easy integration into a DesignWare Synthesizable Components for AMBA 2 implementation. - /// * APB3 and APB4 protocol support. - /// * Scalable APB data bus width – Supports APB data bus widths of 8, 16, and 32 bits. - /// * Serial-master or serial-slave operation – Enables serial communication with serial-master or serial-slave peripheral devices. - /// * Programmable Dual/Quad/Octal SPI support in Master Mode. - /// * Dual Data Rate (DDR) and Read Data Strobe (RDS) Support - Enables the DW_apb_ssi master to perform operations with the device in DDR and RDS modes when working in Dual/Quad/Octal mode of operation. - /// * Data Mask Support - Enables the DW_apb_ssi to selectively update the bytes in the device. This feature is applicable only in enhanced SPI modes. - /// * eXecute-In-Place (XIP) support - Enables the DW_apb_ssi master to behave as a memory mapped I/O and fetches the data from the device based on the APB read request. This feature is applicable only in enhanced SPI modes. - /// * DMA Controller Interface – Enables the DW_apb_ssi to interface to a DMA controller over the bus using a handshaking interface for transfer requests. - /// * Independent masking of interrupts – Master collision, transmit FIFO overflow, transmit FIFO empty, receive FIFO full, receive FIFO underflow, and receive FIFO overflow interrupts can all be masked independently. - /// * Multi-master contention detection – Informs the processor of multiple serial-master accesses on the serial bus. - /// * Bypass of meta-stability flip-flops for synchronous clocks – When the APB clock (pclk) and the DW_apb_ssi serial clock (ssi_clk) are synchronous, meta-stable flip-flops are not used when transferring control signals across these clock domains. - /// * Programmable delay on the sample time of the received serial data bit (rxd); enables programmable control of routing delays resulting in higher serial data-bit rates. - /// * Programmable features: - /// - Serial interface operation – Choice of Motorola SPI, Texas Instruments Synchronous Serial Protocol or National Semiconductor Microwire. - /// - Clock bit-rate – Dynamic control of the serial bit rate of the data transfer; used in only serial-master mode of operation. - /// - Data Item size (4 to 32 bits) – Item size of each data transfer under the control of the programmer. - /// * Configured features: - /// - FIFO depth – 16 words deep. The FIFO width is fixed at 32 bits. - /// - 1 slave select output. - /// - Hardware slave-select – Dedicated hardware slave-select line. - /// - Combined interrupt line - one combined interrupt line from the DW_apb_ssi to the interrupt controller. - /// - Interrupt polarity – active high interrupt lines. - /// - Serial clock polarity – low serial-clock polarity directly after reset. - /// - Serial clock phase – capture on first edge of serial-clock directly after reset. - pub const XIP_SSI = extern struct { - /// Control register 0 - CTRLR0: mmio.Mmio(packed struct(u32) { - /// Data frame size - DFS: u4, - /// Frame format - FRF: u2, - /// Serial clock phase - SCPH: u1, - /// Serial clock polarity - SCPOL: u1, - /// Transfer mode - TMOD: packed union { - raw: u2, - value: enum(u2) { - /// Both transmit and receive - TX_AND_RX = 0x0, - /// Transmit only (not for FRF == 0, standard SPI mode) - TX_ONLY = 0x1, - /// Receive only (not for FRF == 0, standard SPI mode) - RX_ONLY = 0x2, - /// EEPROM read mode (TX then RX; RX starts after control data TX'd) - EEPROM_READ = 0x3, - }, - }, - /// Slave output enable - SLV_OE: u1, - /// Shift register loop (test mode) - SRL: u1, - /// Control frame size - /// Value of n -> n+1 clocks per frame. - CFS: u4, - /// Data frame size in 32b transfer mode - /// Value of n -> n+1 clocks per frame. - DFS_32: u5, - /// SPI frame format - SPI_FRF: packed union { - raw: u2, - value: enum(u2) { - /// Standard 1-bit SPI frame format; 1 bit per SCK, full-duplex - STD = 0x0, - /// Dual-SPI frame format; two bits per SCK, half-duplex - DUAL = 0x1, - /// Quad-SPI frame format; four bits per SCK, half-duplex - QUAD = 0x2, - _, - }, - }, - reserved24: u1, - /// Slave select toggle enable - SSTE: u1, - padding: u7, - }), - /// Master Control register 1 - CTRLR1: mmio.Mmio(packed struct(u32) { - /// Number of data frames - NDF: u16, - padding: u16, - }), - /// SSI Enable - SSIENR: mmio.Mmio(packed struct(u32) { - /// SSI enable - SSI_EN: u1, - padding: u31, - }), - /// Microwire Control - MWCR: mmio.Mmio(packed struct(u32) { - /// Microwire transfer mode - MWMOD: u1, - /// Microwire control - MDD: u1, - /// Microwire handshaking - MHS: u1, - padding: u29, - }), - /// Slave enable - SER: mmio.Mmio(packed struct(u32) { - /// For each bit: - /// 0 -> slave not selected - /// 1 -> slave selected - SER: u1, - padding: u31, - }), - /// Baud rate - BAUDR: mmio.Mmio(packed struct(u32) { - /// SSI clock divider - SCKDV: u16, - padding: u16, - }), - /// TX FIFO threshold level - TXFTLR: mmio.Mmio(packed struct(u32) { - /// Transmit FIFO threshold - TFT: u8, - padding: u24, - }), - /// RX FIFO threshold level - RXFTLR: mmio.Mmio(packed struct(u32) { - /// Receive FIFO threshold - RFT: u8, - padding: u24, - }), - /// TX FIFO level - TXFLR: mmio.Mmio(packed struct(u32) { - /// Transmit FIFO level - TFTFL: u8, - padding: u24, - }), - /// RX FIFO level - RXFLR: mmio.Mmio(packed struct(u32) { - /// Receive FIFO level - RXTFL: u8, - padding: u24, - }), - /// Status register - SR: mmio.Mmio(packed struct(u32) { - /// SSI busy flag - BUSY: u1, - /// Transmit FIFO not full - TFNF: u1, - /// Transmit FIFO empty - TFE: u1, - /// Receive FIFO not empty - RFNE: u1, - /// Receive FIFO full - RFF: u1, - /// Transmission error - TXE: u1, - /// Data collision error - DCOL: u1, - padding: u25, - }), - /// Interrupt mask - IMR: mmio.Mmio(packed struct(u32) { - /// Transmit FIFO empty interrupt mask - TXEIM: u1, - /// Transmit FIFO overflow interrupt mask - TXOIM: u1, - /// Receive FIFO underflow interrupt mask - RXUIM: u1, - /// Receive FIFO overflow interrupt mask - RXOIM: u1, - /// Receive FIFO full interrupt mask - RXFIM: u1, - /// Multi-master contention interrupt mask - MSTIM: u1, - padding: u26, - }), - /// Interrupt status - ISR: mmio.Mmio(packed struct(u32) { - /// Transmit FIFO empty interrupt status - TXEIS: u1, - /// Transmit FIFO overflow interrupt status - TXOIS: u1, - /// Receive FIFO underflow interrupt status - RXUIS: u1, - /// Receive FIFO overflow interrupt status - RXOIS: u1, - /// Receive FIFO full interrupt status - RXFIS: u1, - /// Multi-master contention interrupt status - MSTIS: u1, - padding: u26, - }), - /// Raw interrupt status - RISR: mmio.Mmio(packed struct(u32) { - /// Transmit FIFO empty raw interrupt status - TXEIR: u1, - /// Transmit FIFO overflow raw interrupt status - TXOIR: u1, - /// Receive FIFO underflow raw interrupt status - RXUIR: u1, - /// Receive FIFO overflow raw interrupt status - RXOIR: u1, - /// Receive FIFO full raw interrupt status - RXFIR: u1, - /// Multi-master contention raw interrupt status - MSTIR: u1, - padding: u26, - }), - /// TX FIFO overflow interrupt clear - TXOICR: mmio.Mmio(packed struct(u32) { - /// Clear-on-read transmit FIFO overflow interrupt - TXOICR: u1, - padding: u31, - }), - /// RX FIFO overflow interrupt clear - RXOICR: mmio.Mmio(packed struct(u32) { - /// Clear-on-read receive FIFO overflow interrupt - RXOICR: u1, - padding: u31, - }), - /// RX FIFO underflow interrupt clear - RXUICR: mmio.Mmio(packed struct(u32) { - /// Clear-on-read receive FIFO underflow interrupt - RXUICR: u1, - padding: u31, - }), - /// Multi-master interrupt clear - MSTICR: mmio.Mmio(packed struct(u32) { - /// Clear-on-read multi-master contention interrupt - MSTICR: u1, - padding: u31, - }), - /// Interrupt clear - ICR: mmio.Mmio(packed struct(u32) { - /// Clear-on-read all active interrupts - ICR: u1, - padding: u31, - }), - /// DMA control - DMACR: mmio.Mmio(packed struct(u32) { - /// Receive DMA enable - RDMAE: u1, - /// Transmit DMA enable - TDMAE: u1, - padding: u30, - }), - /// DMA TX data level - DMATDLR: mmio.Mmio(packed struct(u32) { - /// Transmit data watermark level - DMATDL: u8, - padding: u24, - }), - /// DMA RX data level - DMARDLR: mmio.Mmio(packed struct(u32) { - /// Receive data watermark level (DMARDLR+1) - DMARDL: u8, - padding: u24, - }), - /// Identification register - IDR: mmio.Mmio(packed struct(u32) { - /// Peripheral dentification code - IDCODE: u32, - }), - /// Version ID - SSI_VERSION_ID: mmio.Mmio(packed struct(u32) { - /// SNPS component version (format X.YY) - SSI_COMP_VERSION: u32, - }), - /// Data Register 0 (of 36) - DR0: mmio.Mmio(packed struct(u32) { - /// First data register of 36 - DR: u32, - }), - reserved240: [140]u8, - /// RX sample delay - RX_SAMPLE_DLY: mmio.Mmio(packed struct(u32) { - /// RXD sample delay (in SCLK cycles) - RSD: u8, - padding: u24, - }), - /// SPI control - SPI_CTRLR0: mmio.Mmio(packed struct(u32) { - /// Address and instruction transfer format - TRANS_TYPE: packed union { - raw: u2, - value: enum(u2) { - /// Command and address both in standard SPI frame format - @"1C1A" = 0x0, - /// Command in standard SPI format, address in format specified by FRF - @"1C2A" = 0x1, - /// Command and address both in format specified by FRF (e.g. Dual-SPI) - @"2C2A" = 0x2, - _, - }, - }, - /// Address length (0b-60b in 4b increments) - ADDR_L: u4, - reserved8: u2, - /// Instruction length (0/4/8/16b) - INST_L: packed union { - raw: u2, - value: enum(u2) { - /// No instruction - NONE = 0x0, - /// 4-bit instruction - @"4B" = 0x1, - /// 8-bit instruction - @"8B" = 0x2, - /// 16-bit instruction - @"16B" = 0x3, - }, - }, - reserved11: u1, - /// Wait cycles between control frame transmit and data reception (in SCLK cycles) - WAIT_CYCLES: u5, - /// SPI DDR transfer enable - SPI_DDR_EN: u1, - /// Instruction DDR transfer enable - INST_DDR_EN: u1, - /// Read data strobe enable - SPI_RXDS_EN: u1, - reserved24: u5, - /// SPI Command to send in XIP mode (INST_L = 8-bit) or to append to Address (INST_L = 0-bit) - XIP_CMD: u8, - }), - /// TX drive edge - TXD_DRIVE_EDGE: mmio.Mmio(packed struct(u32) { - /// TXD drive edge - TDE: u8, - padding: u24, - }), - }; - - pub const SYSINFO = extern struct { - /// JEDEC JEP-106 compliant chip identifier. - CHIP_ID: mmio.Mmio(packed struct(u32) { - MANUFACTURER: u12, - PART: u16, - REVISION: u4, - }), - /// Platform register. Allows software to know what environment it is running in. - PLATFORM: mmio.Mmio(packed struct(u32) { - FPGA: u1, - ASIC: u1, - padding: u30, - }), - reserved64: [56]u8, - /// Git hash of the chip source. Used to identify chip version. - GITREF_RP2040: u32, - }; - - /// Register block for various chip control signals - pub const SYSCFG = extern struct { - /// Processor core 0 NMI source mask - /// Set a bit high to enable NMI from that IRQ - PROC0_NMI_MASK: u32, - /// Processor core 1 NMI source mask - /// Set a bit high to enable NMI from that IRQ - PROC1_NMI_MASK: u32, - /// Configuration for processors - PROC_CONFIG: mmio.Mmio(packed struct(u32) { - /// Indication that proc0 has halted - PROC0_HALTED: u1, - /// Indication that proc1 has halted - PROC1_HALTED: u1, - reserved24: u22, - /// Configure proc0 DAP instance ID. - /// Recommend that this is NOT changed until you require debug access in multi-chip environment - /// WARNING: do not set to 15 as this is reserved for RescueDP - PROC0_DAP_INSTID: u4, - /// Configure proc1 DAP instance ID. - /// Recommend that this is NOT changed until you require debug access in multi-chip environment - /// WARNING: do not set to 15 as this is reserved for RescueDP - PROC1_DAP_INSTID: u4, - }), - /// For each bit, if 1, bypass the input synchronizer between that GPIO - /// and the GPIO input register in the SIO. The input synchronizers should - /// generally be unbypassed, to avoid injecting metastabilities into processors. - /// If you're feeling brave, you can bypass to save two cycles of input - /// latency. This register applies to GPIO 0...29. - PROC_IN_SYNC_BYPASS: mmio.Mmio(packed struct(u32) { - PROC_IN_SYNC_BYPASS: u30, - padding: u2, - }), - /// For each bit, if 1, bypass the input synchronizer between that GPIO - /// and the GPIO input register in the SIO. The input synchronizers should - /// generally be unbypassed, to avoid injecting metastabilities into processors. - /// If you're feeling brave, you can bypass to save two cycles of input - /// latency. This register applies to GPIO 30...35 (the QSPI IOs). - PROC_IN_SYNC_BYPASS_HI: mmio.Mmio(packed struct(u32) { - PROC_IN_SYNC_BYPASS_HI: u6, - padding: u26, - }), - /// Directly control the SWD debug port of either processor - DBGFORCE: mmio.Mmio(packed struct(u32) { - /// Observe the value of processor 0 SWDIO output. - PROC0_SWDO: u1, - /// Directly drive processor 0 SWDIO input, if PROC0_ATTACH is set - PROC0_SWDI: u1, - /// Directly drive processor 0 SWCLK, if PROC0_ATTACH is set - PROC0_SWCLK: u1, - /// Attach processor 0 debug port to syscfg controls, and disconnect it from external SWD pads. - PROC0_ATTACH: u1, - /// Observe the value of processor 1 SWDIO output. - PROC1_SWDO: u1, - /// Directly drive processor 1 SWDIO input, if PROC1_ATTACH is set - PROC1_SWDI: u1, - /// Directly drive processor 1 SWCLK, if PROC1_ATTACH is set - PROC1_SWCLK: u1, - /// Attach processor 1 debug port to syscfg controls, and disconnect it from external SWD pads. - PROC1_ATTACH: u1, - padding: u24, - }), - /// Control power downs to memories. Set high to power down memories. - /// Use with extreme caution - MEMPOWERDOWN: mmio.Mmio(packed struct(u32) { - SRAM0: u1, - SRAM1: u1, - SRAM2: u1, - SRAM3: u1, - SRAM4: u1, - SRAM5: u1, - USB: u1, - ROM: u1, - padding: u24, - }), - }; - - pub const CLOCKS = extern struct { - /// Clock control, can be changed on-the-fly (except for auxsrc) - CLK_GPOUT0_CTRL: mmio.Mmio(packed struct(u32) { - reserved5: u5, - /// Selects the auxiliary clock source, will glitch when switching - AUXSRC: packed union { - raw: u4, - value: enum(u4) { - clksrc_pll_sys = 0x0, - clksrc_gpin0 = 0x1, - clksrc_gpin1 = 0x2, - clksrc_pll_usb = 0x3, - rosc_clksrc = 0x4, - xosc_clksrc = 0x5, - clk_sys = 0x6, - clk_usb = 0x7, - clk_adc = 0x8, - clk_rtc = 0x9, - clk_ref = 0xa, - _, - }, - }, - reserved10: u1, - /// Asynchronously kills the clock generator - KILL: u1, - /// Starts and stops the clock generator cleanly - ENABLE: u1, - /// Enables duty cycle correction for odd divisors - DC50: u1, - reserved16: u3, - /// This delays the enable signal by up to 3 cycles of the input clock - /// This must be set before the clock is enabled to have any effect - PHASE: u2, - reserved20: u2, - /// An edge on this signal shifts the phase of the output by 1 cycle of the input clock - /// This can be done at any time - NUDGE: u1, - padding: u11, - }), - /// Clock divisor, can be changed on-the-fly - CLK_GPOUT0_DIV: mmio.Mmio(packed struct(u32) { - /// Fractional component of the divisor - FRAC: u8, - /// Integer component of the divisor, 0 -> divide by 2^16 - INT: u24, - }), - /// Indicates which SRC is currently selected by the glitchless mux (one-hot). - /// This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. - CLK_GPOUT0_SELECTED: u32, - /// Clock control, can be changed on-the-fly (except for auxsrc) - CLK_GPOUT1_CTRL: mmio.Mmio(packed struct(u32) { - reserved5: u5, - /// Selects the auxiliary clock source, will glitch when switching - AUXSRC: packed union { - raw: u4, - value: enum(u4) { - clksrc_pll_sys = 0x0, - clksrc_gpin0 = 0x1, - clksrc_gpin1 = 0x2, - clksrc_pll_usb = 0x3, - rosc_clksrc = 0x4, - xosc_clksrc = 0x5, - clk_sys = 0x6, - clk_usb = 0x7, - clk_adc = 0x8, - clk_rtc = 0x9, - clk_ref = 0xa, - _, - }, - }, - reserved10: u1, - /// Asynchronously kills the clock generator - KILL: u1, - /// Starts and stops the clock generator cleanly - ENABLE: u1, - /// Enables duty cycle correction for odd divisors - DC50: u1, - reserved16: u3, - /// This delays the enable signal by up to 3 cycles of the input clock - /// This must be set before the clock is enabled to have any effect - PHASE: u2, - reserved20: u2, - /// An edge on this signal shifts the phase of the output by 1 cycle of the input clock - /// This can be done at any time - NUDGE: u1, - padding: u11, - }), - /// Clock divisor, can be changed on-the-fly - CLK_GPOUT1_DIV: mmio.Mmio(packed struct(u32) { - /// Fractional component of the divisor - FRAC: u8, - /// Integer component of the divisor, 0 -> divide by 2^16 - INT: u24, - }), - /// Indicates which SRC is currently selected by the glitchless mux (one-hot). - /// This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. - CLK_GPOUT1_SELECTED: u32, - /// Clock control, can be changed on-the-fly (except for auxsrc) - CLK_GPOUT2_CTRL: mmio.Mmio(packed struct(u32) { - reserved5: u5, - /// Selects the auxiliary clock source, will glitch when switching - AUXSRC: packed union { - raw: u4, - value: enum(u4) { - clksrc_pll_sys = 0x0, - clksrc_gpin0 = 0x1, - clksrc_gpin1 = 0x2, - clksrc_pll_usb = 0x3, - rosc_clksrc_ph = 0x4, - xosc_clksrc = 0x5, - clk_sys = 0x6, - clk_usb = 0x7, - clk_adc = 0x8, - clk_rtc = 0x9, - clk_ref = 0xa, - _, - }, - }, - reserved10: u1, - /// Asynchronously kills the clock generator - KILL: u1, - /// Starts and stops the clock generator cleanly - ENABLE: u1, - /// Enables duty cycle correction for odd divisors - DC50: u1, - reserved16: u3, - /// This delays the enable signal by up to 3 cycles of the input clock - /// This must be set before the clock is enabled to have any effect - PHASE: u2, - reserved20: u2, - /// An edge on this signal shifts the phase of the output by 1 cycle of the input clock - /// This can be done at any time - NUDGE: u1, - padding: u11, - }), - /// Clock divisor, can be changed on-the-fly - CLK_GPOUT2_DIV: mmio.Mmio(packed struct(u32) { - /// Fractional component of the divisor - FRAC: u8, - /// Integer component of the divisor, 0 -> divide by 2^16 - INT: u24, - }), - /// Indicates which SRC is currently selected by the glitchless mux (one-hot). - /// This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. - CLK_GPOUT2_SELECTED: u32, - /// Clock control, can be changed on-the-fly (except for auxsrc) - CLK_GPOUT3_CTRL: mmio.Mmio(packed struct(u32) { - reserved5: u5, - /// Selects the auxiliary clock source, will glitch when switching - AUXSRC: packed union { - raw: u4, - value: enum(u4) { - clksrc_pll_sys = 0x0, - clksrc_gpin0 = 0x1, - clksrc_gpin1 = 0x2, - clksrc_pll_usb = 0x3, - rosc_clksrc_ph = 0x4, - xosc_clksrc = 0x5, - clk_sys = 0x6, - clk_usb = 0x7, - clk_adc = 0x8, - clk_rtc = 0x9, - clk_ref = 0xa, - _, - }, - }, - reserved10: u1, - /// Asynchronously kills the clock generator - KILL: u1, - /// Starts and stops the clock generator cleanly - ENABLE: u1, - /// Enables duty cycle correction for odd divisors - DC50: u1, - reserved16: u3, - /// This delays the enable signal by up to 3 cycles of the input clock - /// This must be set before the clock is enabled to have any effect - PHASE: u2, - reserved20: u2, - /// An edge on this signal shifts the phase of the output by 1 cycle of the input clock - /// This can be done at any time - NUDGE: u1, - padding: u11, - }), - /// Clock divisor, can be changed on-the-fly - CLK_GPOUT3_DIV: mmio.Mmio(packed struct(u32) { - /// Fractional component of the divisor - FRAC: u8, - /// Integer component of the divisor, 0 -> divide by 2^16 - INT: u24, - }), - /// Indicates which SRC is currently selected by the glitchless mux (one-hot). - /// This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. - CLK_GPOUT3_SELECTED: u32, - /// Clock control, can be changed on-the-fly (except for auxsrc) - CLK_REF_CTRL: mmio.Mmio(packed struct(u32) { - /// Selects the clock source glitchlessly, can be changed on-the-fly - SRC: packed union { - raw: u2, - value: enum(u2) { - rosc_clksrc_ph = 0x0, - clksrc_clk_ref_aux = 0x1, - xosc_clksrc = 0x2, - _, - }, - }, - reserved5: u3, - /// Selects the auxiliary clock source, will glitch when switching - AUXSRC: packed union { - raw: u2, - value: enum(u2) { - clksrc_pll_usb = 0x0, - clksrc_gpin0 = 0x1, - clksrc_gpin1 = 0x2, - _, - }, - }, - padding: u25, - }), - /// Clock divisor, can be changed on-the-fly - CLK_REF_DIV: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// Integer component of the divisor, 0 -> divide by 2^16 - INT: u2, - padding: u22, - }), - /// Indicates which SRC is currently selected by the glitchless mux (one-hot). - /// The glitchless multiplexer does not switch instantaneously (to avoid glitches), so software should poll this register to wait for the switch to complete. This register contains one decoded bit for each of the clock sources enumerated in the CTRL SRC field. At most one of these bits will be set at any time, indicating that clock is currently present at the output of the glitchless mux. Whilst switching is in progress, this register may briefly show all-0s. - CLK_REF_SELECTED: u32, - /// Clock control, can be changed on-the-fly (except for auxsrc) - CLK_SYS_CTRL: mmio.Mmio(packed struct(u32) { - /// Selects the clock source glitchlessly, can be changed on-the-fly - SRC: packed union { - raw: u1, - value: enum(u1) { - clk_ref = 0x0, - clksrc_clk_sys_aux = 0x1, - }, - }, - reserved5: u4, - /// Selects the auxiliary clock source, will glitch when switching - AUXSRC: packed union { - raw: u3, - value: enum(u3) { - clksrc_pll_sys = 0x0, - clksrc_pll_usb = 0x1, - rosc_clksrc = 0x2, - xosc_clksrc = 0x3, - clksrc_gpin0 = 0x4, - clksrc_gpin1 = 0x5, - _, - }, - }, - padding: u24, - }), - /// Clock divisor, can be changed on-the-fly - CLK_SYS_DIV: mmio.Mmio(packed struct(u32) { - /// Fractional component of the divisor - FRAC: u8, - /// Integer component of the divisor, 0 -> divide by 2^16 - INT: u24, - }), - /// Indicates which SRC is currently selected by the glitchless mux (one-hot). - /// The glitchless multiplexer does not switch instantaneously (to avoid glitches), so software should poll this register to wait for the switch to complete. This register contains one decoded bit for each of the clock sources enumerated in the CTRL SRC field. At most one of these bits will be set at any time, indicating that clock is currently present at the output of the glitchless mux. Whilst switching is in progress, this register may briefly show all-0s. - CLK_SYS_SELECTED: u32, - /// Clock control, can be changed on-the-fly (except for auxsrc) - CLK_PERI_CTRL: mmio.Mmio(packed struct(u32) { - reserved5: u5, - /// Selects the auxiliary clock source, will glitch when switching - AUXSRC: packed union { - raw: u3, - value: enum(u3) { - clk_sys = 0x0, - clksrc_pll_sys = 0x1, - clksrc_pll_usb = 0x2, - rosc_clksrc_ph = 0x3, - xosc_clksrc = 0x4, - clksrc_gpin0 = 0x5, - clksrc_gpin1 = 0x6, - _, - }, - }, - reserved10: u2, - /// Asynchronously kills the clock generator - KILL: u1, - /// Starts and stops the clock generator cleanly - ENABLE: u1, - padding: u20, - }), - reserved80: [4]u8, - /// Indicates which SRC is currently selected by the glitchless mux (one-hot). - /// This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. - CLK_PERI_SELECTED: u32, - /// Clock control, can be changed on-the-fly (except for auxsrc) - CLK_USB_CTRL: mmio.Mmio(packed struct(u32) { - reserved5: u5, - /// Selects the auxiliary clock source, will glitch when switching - AUXSRC: packed union { - raw: u3, - value: enum(u3) { - clksrc_pll_usb = 0x0, - clksrc_pll_sys = 0x1, - rosc_clksrc_ph = 0x2, - xosc_clksrc = 0x3, - clksrc_gpin0 = 0x4, - clksrc_gpin1 = 0x5, - _, - }, - }, - reserved10: u2, - /// Asynchronously kills the clock generator - KILL: u1, - /// Starts and stops the clock generator cleanly - ENABLE: u1, - reserved16: u4, - /// This delays the enable signal by up to 3 cycles of the input clock - /// This must be set before the clock is enabled to have any effect - PHASE: u2, - reserved20: u2, - /// An edge on this signal shifts the phase of the output by 1 cycle of the input clock - /// This can be done at any time - NUDGE: u1, - padding: u11, - }), - /// Clock divisor, can be changed on-the-fly - CLK_USB_DIV: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// Integer component of the divisor, 0 -> divide by 2^16 - INT: u2, - padding: u22, - }), - /// Indicates which SRC is currently selected by the glitchless mux (one-hot). - /// This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. - CLK_USB_SELECTED: u32, - /// Clock control, can be changed on-the-fly (except for auxsrc) - CLK_ADC_CTRL: mmio.Mmio(packed struct(u32) { - reserved5: u5, - /// Selects the auxiliary clock source, will glitch when switching - AUXSRC: packed union { - raw: u3, - value: enum(u3) { - clksrc_pll_usb = 0x0, - clksrc_pll_sys = 0x1, - rosc_clksrc_ph = 0x2, - xosc_clksrc = 0x3, - clksrc_gpin0 = 0x4, - clksrc_gpin1 = 0x5, - _, - }, - }, - reserved10: u2, - /// Asynchronously kills the clock generator - KILL: u1, - /// Starts and stops the clock generator cleanly - ENABLE: u1, - reserved16: u4, - /// This delays the enable signal by up to 3 cycles of the input clock - /// This must be set before the clock is enabled to have any effect - PHASE: u2, - reserved20: u2, - /// An edge on this signal shifts the phase of the output by 1 cycle of the input clock - /// This can be done at any time - NUDGE: u1, - padding: u11, - }), - /// Clock divisor, can be changed on-the-fly - CLK_ADC_DIV: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// Integer component of the divisor, 0 -> divide by 2^16 - INT: u2, - padding: u22, - }), - /// Indicates which SRC is currently selected by the glitchless mux (one-hot). - /// This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. - CLK_ADC_SELECTED: u32, - /// Clock control, can be changed on-the-fly (except for auxsrc) - CLK_RTC_CTRL: mmio.Mmio(packed struct(u32) { - reserved5: u5, - /// Selects the auxiliary clock source, will glitch when switching - AUXSRC: packed union { - raw: u3, - value: enum(u3) { - clksrc_pll_usb = 0x0, - clksrc_pll_sys = 0x1, - rosc_clksrc_ph = 0x2, - xosc_clksrc = 0x3, - clksrc_gpin0 = 0x4, - clksrc_gpin1 = 0x5, - _, - }, - }, - reserved10: u2, - /// Asynchronously kills the clock generator - KILL: u1, - /// Starts and stops the clock generator cleanly - ENABLE: u1, - reserved16: u4, - /// This delays the enable signal by up to 3 cycles of the input clock - /// This must be set before the clock is enabled to have any effect - PHASE: u2, - reserved20: u2, - /// An edge on this signal shifts the phase of the output by 1 cycle of the input clock - /// This can be done at any time - NUDGE: u1, - padding: u11, - }), - /// Clock divisor, can be changed on-the-fly - CLK_RTC_DIV: mmio.Mmio(packed struct(u32) { - /// Fractional component of the divisor - FRAC: u8, - /// Integer component of the divisor, 0 -> divide by 2^16 - INT: u24, - }), - /// Indicates which SRC is currently selected by the glitchless mux (one-hot). - /// This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. - CLK_RTC_SELECTED: u32, - CLK_SYS_RESUS_CTRL: mmio.Mmio(packed struct(u32) { - /// This is expressed as a number of clk_ref cycles - /// and must be >= 2x clk_ref_freq/min_clk_tst_freq - TIMEOUT: u8, - /// Enable resus - ENABLE: u1, - reserved12: u3, - /// Force a resus, for test purposes only - FRCE: u1, - reserved16: u3, - /// For clearing the resus after the fault that triggered it has been corrected - CLEAR: u1, - padding: u15, - }), - CLK_SYS_RESUS_STATUS: mmio.Mmio(packed struct(u32) { - /// Clock has been resuscitated, correct the error then send ctrl_clear=1 - RESUSSED: u1, - padding: u31, - }), - /// Reference clock frequency in kHz - FC0_REF_KHZ: mmio.Mmio(packed struct(u32) { - FC0_REF_KHZ: u20, - padding: u12, - }), - /// Minimum pass frequency in kHz. This is optional. Set to 0 if you are not using the pass/fail flags - FC0_MIN_KHZ: mmio.Mmio(packed struct(u32) { - FC0_MIN_KHZ: u25, - padding: u7, - }), - /// Maximum pass frequency in kHz. This is optional. Set to 0x1ffffff if you are not using the pass/fail flags - FC0_MAX_KHZ: mmio.Mmio(packed struct(u32) { - FC0_MAX_KHZ: u25, - padding: u7, - }), - /// Delays the start of frequency counting to allow the mux to settle - /// Delay is measured in multiples of the reference clock period - FC0_DELAY: mmio.Mmio(packed struct(u32) { - FC0_DELAY: u3, - padding: u29, - }), - /// The test interval is 0.98us * 2**interval, but let's call it 1us * 2**interval - /// The default gives a test interval of 250us - FC0_INTERVAL: mmio.Mmio(packed struct(u32) { - FC0_INTERVAL: u4, - padding: u28, - }), - /// Clock sent to frequency counter, set to 0 when not required - /// Writing to this register initiates the frequency count - FC0_SRC: mmio.Mmio(packed struct(u32) { - FC0_SRC: packed union { - raw: u8, - value: enum(u8) { - NULL = 0x0, - pll_sys_clksrc_primary = 0x1, - pll_usb_clksrc_primary = 0x2, - rosc_clksrc = 0x3, - rosc_clksrc_ph = 0x4, - xosc_clksrc = 0x5, - clksrc_gpin0 = 0x6, - clksrc_gpin1 = 0x7, - clk_ref = 0x8, - clk_sys = 0x9, - clk_peri = 0xa, - clk_usb = 0xb, - clk_adc = 0xc, - clk_rtc = 0xd, - _, - }, - }, - padding: u24, - }), - /// Frequency counter status - FC0_STATUS: mmio.Mmio(packed struct(u32) { - /// Test passed - PASS: u1, - reserved4: u3, - /// Test complete - DONE: u1, - reserved8: u3, - /// Test running - RUNNING: u1, - reserved12: u3, - /// Waiting for test clock to start - WAITING: u1, - reserved16: u3, - /// Test failed - FAIL: u1, - reserved20: u3, - /// Test clock slower than expected, only valid when status_done=1 - SLOW: u1, - reserved24: u3, - /// Test clock faster than expected, only valid when status_done=1 - FAST: u1, - reserved28: u3, - /// Test clock stopped during test - DIED: u1, - padding: u3, - }), - /// Result of frequency measurement, only valid when status_done=1 - FC0_RESULT: mmio.Mmio(packed struct(u32) { - FRAC: u5, - KHZ: u25, - padding: u2, - }), - /// enable clock in wake mode - WAKE_EN0: mmio.Mmio(packed struct(u32) { - clk_sys_clocks: u1, - clk_adc_adc: u1, - clk_sys_adc: u1, - clk_sys_busctrl: u1, - clk_sys_busfabric: u1, - clk_sys_dma: u1, - clk_sys_i2c0: u1, - clk_sys_i2c1: u1, - clk_sys_io: u1, - clk_sys_jtag: u1, - clk_sys_vreg_and_chip_reset: u1, - clk_sys_pads: u1, - clk_sys_pio0: u1, - clk_sys_pio1: u1, - clk_sys_pll_sys: u1, - clk_sys_pll_usb: u1, - clk_sys_psm: u1, - clk_sys_pwm: u1, - clk_sys_resets: u1, - clk_sys_rom: u1, - clk_sys_rosc: u1, - clk_rtc_rtc: u1, - clk_sys_rtc: u1, - clk_sys_sio: u1, - clk_peri_spi0: u1, - clk_sys_spi0: u1, - clk_peri_spi1: u1, - clk_sys_spi1: u1, - clk_sys_sram0: u1, - clk_sys_sram1: u1, - clk_sys_sram2: u1, - clk_sys_sram3: u1, - }), - /// enable clock in wake mode - WAKE_EN1: mmio.Mmio(packed struct(u32) { - clk_sys_sram4: u1, - clk_sys_sram5: u1, - clk_sys_syscfg: u1, - clk_sys_sysinfo: u1, - clk_sys_tbman: u1, - clk_sys_timer: u1, - clk_peri_uart0: u1, - clk_sys_uart0: u1, - clk_peri_uart1: u1, - clk_sys_uart1: u1, - clk_sys_usbctrl: u1, - clk_usb_usbctrl: u1, - clk_sys_watchdog: u1, - clk_sys_xip: u1, - clk_sys_xosc: u1, - padding: u17, - }), - /// enable clock in sleep mode - SLEEP_EN0: mmio.Mmio(packed struct(u32) { - clk_sys_clocks: u1, - clk_adc_adc: u1, - clk_sys_adc: u1, - clk_sys_busctrl: u1, - clk_sys_busfabric: u1, - clk_sys_dma: u1, - clk_sys_i2c0: u1, - clk_sys_i2c1: u1, - clk_sys_io: u1, - clk_sys_jtag: u1, - clk_sys_vreg_and_chip_reset: u1, - clk_sys_pads: u1, - clk_sys_pio0: u1, - clk_sys_pio1: u1, - clk_sys_pll_sys: u1, - clk_sys_pll_usb: u1, - clk_sys_psm: u1, - clk_sys_pwm: u1, - clk_sys_resets: u1, - clk_sys_rom: u1, - clk_sys_rosc: u1, - clk_rtc_rtc: u1, - clk_sys_rtc: u1, - clk_sys_sio: u1, - clk_peri_spi0: u1, - clk_sys_spi0: u1, - clk_peri_spi1: u1, - clk_sys_spi1: u1, - clk_sys_sram0: u1, - clk_sys_sram1: u1, - clk_sys_sram2: u1, - clk_sys_sram3: u1, - }), - /// enable clock in sleep mode - SLEEP_EN1: mmio.Mmio(packed struct(u32) { - clk_sys_sram4: u1, - clk_sys_sram5: u1, - clk_sys_syscfg: u1, - clk_sys_sysinfo: u1, - clk_sys_tbman: u1, - clk_sys_timer: u1, - clk_peri_uart0: u1, - clk_sys_uart0: u1, - clk_peri_uart1: u1, - clk_sys_uart1: u1, - clk_sys_usbctrl: u1, - clk_usb_usbctrl: u1, - clk_sys_watchdog: u1, - clk_sys_xip: u1, - clk_sys_xosc: u1, - padding: u17, - }), - /// indicates the state of the clock enable - ENABLED0: mmio.Mmio(packed struct(u32) { - clk_sys_clocks: u1, - clk_adc_adc: u1, - clk_sys_adc: u1, - clk_sys_busctrl: u1, - clk_sys_busfabric: u1, - clk_sys_dma: u1, - clk_sys_i2c0: u1, - clk_sys_i2c1: u1, - clk_sys_io: u1, - clk_sys_jtag: u1, - clk_sys_vreg_and_chip_reset: u1, - clk_sys_pads: u1, - clk_sys_pio0: u1, - clk_sys_pio1: u1, - clk_sys_pll_sys: u1, - clk_sys_pll_usb: u1, - clk_sys_psm: u1, - clk_sys_pwm: u1, - clk_sys_resets: u1, - clk_sys_rom: u1, - clk_sys_rosc: u1, - clk_rtc_rtc: u1, - clk_sys_rtc: u1, - clk_sys_sio: u1, - clk_peri_spi0: u1, - clk_sys_spi0: u1, - clk_peri_spi1: u1, - clk_sys_spi1: u1, - clk_sys_sram0: u1, - clk_sys_sram1: u1, - clk_sys_sram2: u1, - clk_sys_sram3: u1, - }), - /// indicates the state of the clock enable - ENABLED1: mmio.Mmio(packed struct(u32) { - clk_sys_sram4: u1, - clk_sys_sram5: u1, - clk_sys_syscfg: u1, - clk_sys_sysinfo: u1, - clk_sys_tbman: u1, - clk_sys_timer: u1, - clk_peri_uart0: u1, - clk_sys_uart0: u1, - clk_peri_uart1: u1, - clk_sys_uart1: u1, - clk_sys_usbctrl: u1, - clk_usb_usbctrl: u1, - clk_sys_watchdog: u1, - clk_sys_xip: u1, - clk_sys_xosc: u1, - padding: u17, - }), - /// Raw Interrupts - INTR: mmio.Mmio(packed struct(u32) { - CLK_SYS_RESUS: u1, - padding: u31, - }), - /// Interrupt Enable - INTE: mmio.Mmio(packed struct(u32) { - CLK_SYS_RESUS: u1, - padding: u31, - }), - /// Interrupt Force - INTF: mmio.Mmio(packed struct(u32) { - CLK_SYS_RESUS: u1, - padding: u31, - }), - /// Interrupt status after masking & forcing - INTS: mmio.Mmio(packed struct(u32) { - CLK_SYS_RESUS: u1, - padding: u31, - }), - }; - - pub const RESETS = extern struct { - /// Reset control. If a bit is set it means the peripheral is in reset. 0 means the peripheral's reset is deasserted. - RESET: mmio.Mmio(packed struct(u32) { - adc: u1, - busctrl: u1, - dma: u1, - i2c0: u1, - i2c1: u1, - io_bank0: u1, - io_qspi: u1, - jtag: u1, - pads_bank0: u1, - pads_qspi: u1, - pio0: u1, - pio1: u1, - pll_sys: u1, - pll_usb: u1, - pwm: u1, - rtc: u1, - spi0: u1, - spi1: u1, - syscfg: u1, - sysinfo: u1, - tbman: u1, - timer: u1, - uart0: u1, - uart1: u1, - usbctrl: u1, - padding: u7, - }), - /// Watchdog select. If a bit is set then the watchdog will reset this peripheral when the watchdog fires. - WDSEL: mmio.Mmio(packed struct(u32) { - adc: u1, - busctrl: u1, - dma: u1, - i2c0: u1, - i2c1: u1, - io_bank0: u1, - io_qspi: u1, - jtag: u1, - pads_bank0: u1, - pads_qspi: u1, - pio0: u1, - pio1: u1, - pll_sys: u1, - pll_usb: u1, - pwm: u1, - rtc: u1, - spi0: u1, - spi1: u1, - syscfg: u1, - sysinfo: u1, - tbman: u1, - timer: u1, - uart0: u1, - uart1: u1, - usbctrl: u1, - padding: u7, - }), - /// Reset done. If a bit is set then a reset done signal has been returned by the peripheral. This indicates that the peripheral's registers are ready to be accessed. - RESET_DONE: mmio.Mmio(packed struct(u32) { - adc: u1, - busctrl: u1, - dma: u1, - i2c0: u1, - i2c1: u1, - io_bank0: u1, - io_qspi: u1, - jtag: u1, - pads_bank0: u1, - pads_qspi: u1, - pio0: u1, - pio1: u1, - pll_sys: u1, - pll_usb: u1, - pwm: u1, - rtc: u1, - spi0: u1, - spi1: u1, - syscfg: u1, - sysinfo: u1, - tbman: u1, - timer: u1, - uart0: u1, - uart1: u1, - usbctrl: u1, - padding: u7, - }), - }; - - pub const PSM = extern struct { - /// Force block out of reset (i.e. power it on) - FRCE_ON: mmio.Mmio(packed struct(u32) { - rosc: u1, - xosc: u1, - clocks: u1, - resets: u1, - busfabric: u1, - rom: u1, - sram0: u1, - sram1: u1, - sram2: u1, - sram3: u1, - sram4: u1, - sram5: u1, - xip: u1, - vreg_and_chip_reset: u1, - sio: u1, - proc0: u1, - proc1: u1, - padding: u15, - }), - /// Force into reset (i.e. power it off) - FRCE_OFF: mmio.Mmio(packed struct(u32) { - rosc: u1, - xosc: u1, - clocks: u1, - resets: u1, - busfabric: u1, - rom: u1, - sram0: u1, - sram1: u1, - sram2: u1, - sram3: u1, - sram4: u1, - sram5: u1, - xip: u1, - vreg_and_chip_reset: u1, - sio: u1, - proc0: u1, - proc1: u1, - padding: u15, - }), - /// Set to 1 if this peripheral should be reset when the watchdog fires. - WDSEL: mmio.Mmio(packed struct(u32) { - rosc: u1, - xosc: u1, - clocks: u1, - resets: u1, - busfabric: u1, - rom: u1, - sram0: u1, - sram1: u1, - sram2: u1, - sram3: u1, - sram4: u1, - sram5: u1, - xip: u1, - vreg_and_chip_reset: u1, - sio: u1, - proc0: u1, - proc1: u1, - padding: u15, - }), - /// Indicates the peripheral's registers are ready to access. - DONE: mmio.Mmio(packed struct(u32) { - rosc: u1, - xosc: u1, - clocks: u1, - resets: u1, - busfabric: u1, - rom: u1, - sram0: u1, - sram1: u1, - sram2: u1, - sram3: u1, - sram4: u1, - sram5: u1, - xip: u1, - vreg_and_chip_reset: u1, - sio: u1, - proc0: u1, - proc1: u1, - padding: u15, - }), - }; - - pub const IO_BANK0 = extern struct { - /// GPIO status - GPIO0_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO0_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - jtag_tck = 0x0, - spi0_rx = 0x1, - uart0_tx = 0x2, - i2c0_sda = 0x3, - pwm_a_0 = 0x4, - sio_0 = 0x5, - pio0_0 = 0x6, - pio1_0 = 0x7, - usb_muxing_overcurr_detect = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO1_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO1_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - jtag_tms = 0x0, - spi0_ss_n = 0x1, - uart0_rx = 0x2, - i2c0_scl = 0x3, - pwm_b_0 = 0x4, - sio_1 = 0x5, - pio0_1 = 0x6, - pio1_1 = 0x7, - usb_muxing_vbus_detect = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO2_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO2_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - jtag_tdi = 0x0, - spi0_sclk = 0x1, - uart0_cts = 0x2, - i2c1_sda = 0x3, - pwm_a_1 = 0x4, - sio_2 = 0x5, - pio0_2 = 0x6, - pio1_2 = 0x7, - usb_muxing_vbus_en = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO3_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO3_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - jtag_tdo = 0x0, - spi0_tx = 0x1, - uart0_rts = 0x2, - i2c1_scl = 0x3, - pwm_b_1 = 0x4, - sio_3 = 0x5, - pio0_3 = 0x6, - pio1_3 = 0x7, - usb_muxing_overcurr_detect = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO4_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO4_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - spi0_rx = 0x1, - uart1_tx = 0x2, - i2c0_sda = 0x3, - pwm_a_2 = 0x4, - sio_4 = 0x5, - pio0_4 = 0x6, - pio1_4 = 0x7, - usb_muxing_vbus_detect = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO5_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO5_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - spi0_ss_n = 0x1, - uart1_rx = 0x2, - i2c0_scl = 0x3, - pwm_b_2 = 0x4, - sio_5 = 0x5, - pio0_5 = 0x6, - pio1_5 = 0x7, - usb_muxing_vbus_en = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO6_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO6_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - spi0_sclk = 0x1, - uart1_cts = 0x2, - i2c1_sda = 0x3, - pwm_a_3 = 0x4, - sio_6 = 0x5, - pio0_6 = 0x6, - pio1_6 = 0x7, - usb_muxing_extphy_softcon = 0x8, - usb_muxing_overcurr_detect = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO7_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO7_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - spi0_tx = 0x1, - uart1_rts = 0x2, - i2c1_scl = 0x3, - pwm_b_3 = 0x4, - sio_7 = 0x5, - pio0_7 = 0x6, - pio1_7 = 0x7, - usb_muxing_extphy_oe_n = 0x8, - usb_muxing_vbus_detect = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO8_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO8_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - spi1_rx = 0x1, - uart1_tx = 0x2, - i2c0_sda = 0x3, - pwm_a_4 = 0x4, - sio_8 = 0x5, - pio0_8 = 0x6, - pio1_8 = 0x7, - usb_muxing_extphy_rcv = 0x8, - usb_muxing_vbus_en = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO9_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO9_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - spi1_ss_n = 0x1, - uart1_rx = 0x2, - i2c0_scl = 0x3, - pwm_b_4 = 0x4, - sio_9 = 0x5, - pio0_9 = 0x6, - pio1_9 = 0x7, - usb_muxing_extphy_vp = 0x8, - usb_muxing_overcurr_detect = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO10_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO10_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - spi1_sclk = 0x1, - uart1_cts = 0x2, - i2c1_sda = 0x3, - pwm_a_5 = 0x4, - sio_10 = 0x5, - pio0_10 = 0x6, - pio1_10 = 0x7, - usb_muxing_extphy_vm = 0x8, - usb_muxing_vbus_detect = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO11_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO11_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - spi1_tx = 0x1, - uart1_rts = 0x2, - i2c1_scl = 0x3, - pwm_b_5 = 0x4, - sio_11 = 0x5, - pio0_11 = 0x6, - pio1_11 = 0x7, - usb_muxing_extphy_suspnd = 0x8, - usb_muxing_vbus_en = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO12_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO12_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - spi1_rx = 0x1, - uart0_tx = 0x2, - i2c0_sda = 0x3, - pwm_a_6 = 0x4, - sio_12 = 0x5, - pio0_12 = 0x6, - pio1_12 = 0x7, - usb_muxing_extphy_speed = 0x8, - usb_muxing_overcurr_detect = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO13_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO13_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - spi1_ss_n = 0x1, - uart0_rx = 0x2, - i2c0_scl = 0x3, - pwm_b_6 = 0x4, - sio_13 = 0x5, - pio0_13 = 0x6, - pio1_13 = 0x7, - usb_muxing_extphy_vpo = 0x8, - usb_muxing_vbus_detect = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO14_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO14_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - spi1_sclk = 0x1, - uart0_cts = 0x2, - i2c1_sda = 0x3, - pwm_a_7 = 0x4, - sio_14 = 0x5, - pio0_14 = 0x6, - pio1_14 = 0x7, - usb_muxing_extphy_vmo = 0x8, - usb_muxing_vbus_en = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO15_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO15_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - spi1_tx = 0x1, - uart0_rts = 0x2, - i2c1_scl = 0x3, - pwm_b_7 = 0x4, - sio_15 = 0x5, - pio0_15 = 0x6, - pio1_15 = 0x7, - usb_muxing_digital_dp = 0x8, - usb_muxing_overcurr_detect = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO16_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO16_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - spi0_rx = 0x1, - uart0_tx = 0x2, - i2c0_sda = 0x3, - pwm_a_0 = 0x4, - sio_16 = 0x5, - pio0_16 = 0x6, - pio1_16 = 0x7, - usb_muxing_digital_dm = 0x8, - usb_muxing_vbus_detect = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO17_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO17_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - spi0_ss_n = 0x1, - uart0_rx = 0x2, - i2c0_scl = 0x3, - pwm_b_0 = 0x4, - sio_17 = 0x5, - pio0_17 = 0x6, - pio1_17 = 0x7, - usb_muxing_vbus_en = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO18_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO18_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - spi0_sclk = 0x1, - uart0_cts = 0x2, - i2c1_sda = 0x3, - pwm_a_1 = 0x4, - sio_18 = 0x5, - pio0_18 = 0x6, - pio1_18 = 0x7, - usb_muxing_overcurr_detect = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO19_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO19_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - spi0_tx = 0x1, - uart0_rts = 0x2, - i2c1_scl = 0x3, - pwm_b_1 = 0x4, - sio_19 = 0x5, - pio0_19 = 0x6, - pio1_19 = 0x7, - usb_muxing_vbus_detect = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO20_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO20_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - spi0_rx = 0x1, - uart1_tx = 0x2, - i2c0_sda = 0x3, - pwm_a_2 = 0x4, - sio_20 = 0x5, - pio0_20 = 0x6, - pio1_20 = 0x7, - clocks_gpin_0 = 0x8, - usb_muxing_vbus_en = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO21_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO21_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - spi0_ss_n = 0x1, - uart1_rx = 0x2, - i2c0_scl = 0x3, - pwm_b_2 = 0x4, - sio_21 = 0x5, - pio0_21 = 0x6, - pio1_21 = 0x7, - clocks_gpout_0 = 0x8, - usb_muxing_overcurr_detect = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO22_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO22_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - spi0_sclk = 0x1, - uart1_cts = 0x2, - i2c1_sda = 0x3, - pwm_a_3 = 0x4, - sio_22 = 0x5, - pio0_22 = 0x6, - pio1_22 = 0x7, - clocks_gpin_1 = 0x8, - usb_muxing_vbus_detect = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO23_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO23_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - spi0_tx = 0x1, - uart1_rts = 0x2, - i2c1_scl = 0x3, - pwm_b_3 = 0x4, - sio_23 = 0x5, - pio0_23 = 0x6, - pio1_23 = 0x7, - clocks_gpout_1 = 0x8, - usb_muxing_vbus_en = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO24_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO24_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - spi1_rx = 0x1, - uart1_tx = 0x2, - i2c0_sda = 0x3, - pwm_a_4 = 0x4, - sio_24 = 0x5, - pio0_24 = 0x6, - pio1_24 = 0x7, - clocks_gpout_2 = 0x8, - usb_muxing_overcurr_detect = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO25_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO25_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - spi1_ss_n = 0x1, - uart1_rx = 0x2, - i2c0_scl = 0x3, - pwm_b_4 = 0x4, - sio_25 = 0x5, - pio0_25 = 0x6, - pio1_25 = 0x7, - clocks_gpout_3 = 0x8, - usb_muxing_vbus_detect = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO26_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO26_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - spi1_sclk = 0x1, - uart1_cts = 0x2, - i2c1_sda = 0x3, - pwm_a_5 = 0x4, - sio_26 = 0x5, - pio0_26 = 0x6, - pio1_26 = 0x7, - usb_muxing_vbus_en = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO27_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO27_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - spi1_tx = 0x1, - uart1_rts = 0x2, - i2c1_scl = 0x3, - pwm_b_5 = 0x4, - sio_27 = 0x5, - pio0_27 = 0x6, - pio1_27 = 0x7, - usb_muxing_overcurr_detect = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO28_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO28_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - spi1_rx = 0x1, - uart0_tx = 0x2, - i2c0_sda = 0x3, - pwm_a_6 = 0x4, - sio_28 = 0x5, - pio0_28 = 0x6, - pio1_28 = 0x7, - usb_muxing_vbus_detect = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO29_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO29_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - spi1_ss_n = 0x1, - uart0_rx = 0x2, - i2c0_scl = 0x3, - pwm_b_6 = 0x4, - sio_29 = 0x5, - pio0_29 = 0x6, - pio1_29 = 0x7, - usb_muxing_vbus_en = 0x9, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// Raw Interrupts - INTR0: mmio.Mmio(packed struct(u32) { - GPIO0_LEVEL_LOW: u1, - GPIO0_LEVEL_HIGH: u1, - GPIO0_EDGE_LOW: u1, - GPIO0_EDGE_HIGH: u1, - GPIO1_LEVEL_LOW: u1, - GPIO1_LEVEL_HIGH: u1, - GPIO1_EDGE_LOW: u1, - GPIO1_EDGE_HIGH: u1, - GPIO2_LEVEL_LOW: u1, - GPIO2_LEVEL_HIGH: u1, - GPIO2_EDGE_LOW: u1, - GPIO2_EDGE_HIGH: u1, - GPIO3_LEVEL_LOW: u1, - GPIO3_LEVEL_HIGH: u1, - GPIO3_EDGE_LOW: u1, - GPIO3_EDGE_HIGH: u1, - GPIO4_LEVEL_LOW: u1, - GPIO4_LEVEL_HIGH: u1, - GPIO4_EDGE_LOW: u1, - GPIO4_EDGE_HIGH: u1, - GPIO5_LEVEL_LOW: u1, - GPIO5_LEVEL_HIGH: u1, - GPIO5_EDGE_LOW: u1, - GPIO5_EDGE_HIGH: u1, - GPIO6_LEVEL_LOW: u1, - GPIO6_LEVEL_HIGH: u1, - GPIO6_EDGE_LOW: u1, - GPIO6_EDGE_HIGH: u1, - GPIO7_LEVEL_LOW: u1, - GPIO7_LEVEL_HIGH: u1, - GPIO7_EDGE_LOW: u1, - GPIO7_EDGE_HIGH: u1, - }), - /// Raw Interrupts - INTR1: mmio.Mmio(packed struct(u32) { - GPIO8_LEVEL_LOW: u1, - GPIO8_LEVEL_HIGH: u1, - GPIO8_EDGE_LOW: u1, - GPIO8_EDGE_HIGH: u1, - GPIO9_LEVEL_LOW: u1, - GPIO9_LEVEL_HIGH: u1, - GPIO9_EDGE_LOW: u1, - GPIO9_EDGE_HIGH: u1, - GPIO10_LEVEL_LOW: u1, - GPIO10_LEVEL_HIGH: u1, - GPIO10_EDGE_LOW: u1, - GPIO10_EDGE_HIGH: u1, - GPIO11_LEVEL_LOW: u1, - GPIO11_LEVEL_HIGH: u1, - GPIO11_EDGE_LOW: u1, - GPIO11_EDGE_HIGH: u1, - GPIO12_LEVEL_LOW: u1, - GPIO12_LEVEL_HIGH: u1, - GPIO12_EDGE_LOW: u1, - GPIO12_EDGE_HIGH: u1, - GPIO13_LEVEL_LOW: u1, - GPIO13_LEVEL_HIGH: u1, - GPIO13_EDGE_LOW: u1, - GPIO13_EDGE_HIGH: u1, - GPIO14_LEVEL_LOW: u1, - GPIO14_LEVEL_HIGH: u1, - GPIO14_EDGE_LOW: u1, - GPIO14_EDGE_HIGH: u1, - GPIO15_LEVEL_LOW: u1, - GPIO15_LEVEL_HIGH: u1, - GPIO15_EDGE_LOW: u1, - GPIO15_EDGE_HIGH: u1, - }), - /// Raw Interrupts - INTR2: mmio.Mmio(packed struct(u32) { - GPIO16_LEVEL_LOW: u1, - GPIO16_LEVEL_HIGH: u1, - GPIO16_EDGE_LOW: u1, - GPIO16_EDGE_HIGH: u1, - GPIO17_LEVEL_LOW: u1, - GPIO17_LEVEL_HIGH: u1, - GPIO17_EDGE_LOW: u1, - GPIO17_EDGE_HIGH: u1, - GPIO18_LEVEL_LOW: u1, - GPIO18_LEVEL_HIGH: u1, - GPIO18_EDGE_LOW: u1, - GPIO18_EDGE_HIGH: u1, - GPIO19_LEVEL_LOW: u1, - GPIO19_LEVEL_HIGH: u1, - GPIO19_EDGE_LOW: u1, - GPIO19_EDGE_HIGH: u1, - GPIO20_LEVEL_LOW: u1, - GPIO20_LEVEL_HIGH: u1, - GPIO20_EDGE_LOW: u1, - GPIO20_EDGE_HIGH: u1, - GPIO21_LEVEL_LOW: u1, - GPIO21_LEVEL_HIGH: u1, - GPIO21_EDGE_LOW: u1, - GPIO21_EDGE_HIGH: u1, - GPIO22_LEVEL_LOW: u1, - GPIO22_LEVEL_HIGH: u1, - GPIO22_EDGE_LOW: u1, - GPIO22_EDGE_HIGH: u1, - GPIO23_LEVEL_LOW: u1, - GPIO23_LEVEL_HIGH: u1, - GPIO23_EDGE_LOW: u1, - GPIO23_EDGE_HIGH: u1, - }), - /// Raw Interrupts - INTR3: mmio.Mmio(packed struct(u32) { - GPIO24_LEVEL_LOW: u1, - GPIO24_LEVEL_HIGH: u1, - GPIO24_EDGE_LOW: u1, - GPIO24_EDGE_HIGH: u1, - GPIO25_LEVEL_LOW: u1, - GPIO25_LEVEL_HIGH: u1, - GPIO25_EDGE_LOW: u1, - GPIO25_EDGE_HIGH: u1, - GPIO26_LEVEL_LOW: u1, - GPIO26_LEVEL_HIGH: u1, - GPIO26_EDGE_LOW: u1, - GPIO26_EDGE_HIGH: u1, - GPIO27_LEVEL_LOW: u1, - GPIO27_LEVEL_HIGH: u1, - GPIO27_EDGE_LOW: u1, - GPIO27_EDGE_HIGH: u1, - GPIO28_LEVEL_LOW: u1, - GPIO28_LEVEL_HIGH: u1, - GPIO28_EDGE_LOW: u1, - GPIO28_EDGE_HIGH: u1, - GPIO29_LEVEL_LOW: u1, - GPIO29_LEVEL_HIGH: u1, - GPIO29_EDGE_LOW: u1, - GPIO29_EDGE_HIGH: u1, - padding: u8, - }), - /// Interrupt Enable for proc0 - PROC0_INTE0: mmio.Mmio(packed struct(u32) { - GPIO0_LEVEL_LOW: u1, - GPIO0_LEVEL_HIGH: u1, - GPIO0_EDGE_LOW: u1, - GPIO0_EDGE_HIGH: u1, - GPIO1_LEVEL_LOW: u1, - GPIO1_LEVEL_HIGH: u1, - GPIO1_EDGE_LOW: u1, - GPIO1_EDGE_HIGH: u1, - GPIO2_LEVEL_LOW: u1, - GPIO2_LEVEL_HIGH: u1, - GPIO2_EDGE_LOW: u1, - GPIO2_EDGE_HIGH: u1, - GPIO3_LEVEL_LOW: u1, - GPIO3_LEVEL_HIGH: u1, - GPIO3_EDGE_LOW: u1, - GPIO3_EDGE_HIGH: u1, - GPIO4_LEVEL_LOW: u1, - GPIO4_LEVEL_HIGH: u1, - GPIO4_EDGE_LOW: u1, - GPIO4_EDGE_HIGH: u1, - GPIO5_LEVEL_LOW: u1, - GPIO5_LEVEL_HIGH: u1, - GPIO5_EDGE_LOW: u1, - GPIO5_EDGE_HIGH: u1, - GPIO6_LEVEL_LOW: u1, - GPIO6_LEVEL_HIGH: u1, - GPIO6_EDGE_LOW: u1, - GPIO6_EDGE_HIGH: u1, - GPIO7_LEVEL_LOW: u1, - GPIO7_LEVEL_HIGH: u1, - GPIO7_EDGE_LOW: u1, - GPIO7_EDGE_HIGH: u1, - }), - /// Interrupt Enable for proc0 - PROC0_INTE1: mmio.Mmio(packed struct(u32) { - GPIO8_LEVEL_LOW: u1, - GPIO8_LEVEL_HIGH: u1, - GPIO8_EDGE_LOW: u1, - GPIO8_EDGE_HIGH: u1, - GPIO9_LEVEL_LOW: u1, - GPIO9_LEVEL_HIGH: u1, - GPIO9_EDGE_LOW: u1, - GPIO9_EDGE_HIGH: u1, - GPIO10_LEVEL_LOW: u1, - GPIO10_LEVEL_HIGH: u1, - GPIO10_EDGE_LOW: u1, - GPIO10_EDGE_HIGH: u1, - GPIO11_LEVEL_LOW: u1, - GPIO11_LEVEL_HIGH: u1, - GPIO11_EDGE_LOW: u1, - GPIO11_EDGE_HIGH: u1, - GPIO12_LEVEL_LOW: u1, - GPIO12_LEVEL_HIGH: u1, - GPIO12_EDGE_LOW: u1, - GPIO12_EDGE_HIGH: u1, - GPIO13_LEVEL_LOW: u1, - GPIO13_LEVEL_HIGH: u1, - GPIO13_EDGE_LOW: u1, - GPIO13_EDGE_HIGH: u1, - GPIO14_LEVEL_LOW: u1, - GPIO14_LEVEL_HIGH: u1, - GPIO14_EDGE_LOW: u1, - GPIO14_EDGE_HIGH: u1, - GPIO15_LEVEL_LOW: u1, - GPIO15_LEVEL_HIGH: u1, - GPIO15_EDGE_LOW: u1, - GPIO15_EDGE_HIGH: u1, - }), - /// Interrupt Enable for proc0 - PROC0_INTE2: mmio.Mmio(packed struct(u32) { - GPIO16_LEVEL_LOW: u1, - GPIO16_LEVEL_HIGH: u1, - GPIO16_EDGE_LOW: u1, - GPIO16_EDGE_HIGH: u1, - GPIO17_LEVEL_LOW: u1, - GPIO17_LEVEL_HIGH: u1, - GPIO17_EDGE_LOW: u1, - GPIO17_EDGE_HIGH: u1, - GPIO18_LEVEL_LOW: u1, - GPIO18_LEVEL_HIGH: u1, - GPIO18_EDGE_LOW: u1, - GPIO18_EDGE_HIGH: u1, - GPIO19_LEVEL_LOW: u1, - GPIO19_LEVEL_HIGH: u1, - GPIO19_EDGE_LOW: u1, - GPIO19_EDGE_HIGH: u1, - GPIO20_LEVEL_LOW: u1, - GPIO20_LEVEL_HIGH: u1, - GPIO20_EDGE_LOW: u1, - GPIO20_EDGE_HIGH: u1, - GPIO21_LEVEL_LOW: u1, - GPIO21_LEVEL_HIGH: u1, - GPIO21_EDGE_LOW: u1, - GPIO21_EDGE_HIGH: u1, - GPIO22_LEVEL_LOW: u1, - GPIO22_LEVEL_HIGH: u1, - GPIO22_EDGE_LOW: u1, - GPIO22_EDGE_HIGH: u1, - GPIO23_LEVEL_LOW: u1, - GPIO23_LEVEL_HIGH: u1, - GPIO23_EDGE_LOW: u1, - GPIO23_EDGE_HIGH: u1, - }), - /// Interrupt Enable for proc0 - PROC0_INTE3: mmio.Mmio(packed struct(u32) { - GPIO24_LEVEL_LOW: u1, - GPIO24_LEVEL_HIGH: u1, - GPIO24_EDGE_LOW: u1, - GPIO24_EDGE_HIGH: u1, - GPIO25_LEVEL_LOW: u1, - GPIO25_LEVEL_HIGH: u1, - GPIO25_EDGE_LOW: u1, - GPIO25_EDGE_HIGH: u1, - GPIO26_LEVEL_LOW: u1, - GPIO26_LEVEL_HIGH: u1, - GPIO26_EDGE_LOW: u1, - GPIO26_EDGE_HIGH: u1, - GPIO27_LEVEL_LOW: u1, - GPIO27_LEVEL_HIGH: u1, - GPIO27_EDGE_LOW: u1, - GPIO27_EDGE_HIGH: u1, - GPIO28_LEVEL_LOW: u1, - GPIO28_LEVEL_HIGH: u1, - GPIO28_EDGE_LOW: u1, - GPIO28_EDGE_HIGH: u1, - GPIO29_LEVEL_LOW: u1, - GPIO29_LEVEL_HIGH: u1, - GPIO29_EDGE_LOW: u1, - GPIO29_EDGE_HIGH: u1, - padding: u8, - }), - /// Interrupt Force for proc0 - PROC0_INTF0: mmio.Mmio(packed struct(u32) { - GPIO0_LEVEL_LOW: u1, - GPIO0_LEVEL_HIGH: u1, - GPIO0_EDGE_LOW: u1, - GPIO0_EDGE_HIGH: u1, - GPIO1_LEVEL_LOW: u1, - GPIO1_LEVEL_HIGH: u1, - GPIO1_EDGE_LOW: u1, - GPIO1_EDGE_HIGH: u1, - GPIO2_LEVEL_LOW: u1, - GPIO2_LEVEL_HIGH: u1, - GPIO2_EDGE_LOW: u1, - GPIO2_EDGE_HIGH: u1, - GPIO3_LEVEL_LOW: u1, - GPIO3_LEVEL_HIGH: u1, - GPIO3_EDGE_LOW: u1, - GPIO3_EDGE_HIGH: u1, - GPIO4_LEVEL_LOW: u1, - GPIO4_LEVEL_HIGH: u1, - GPIO4_EDGE_LOW: u1, - GPIO4_EDGE_HIGH: u1, - GPIO5_LEVEL_LOW: u1, - GPIO5_LEVEL_HIGH: u1, - GPIO5_EDGE_LOW: u1, - GPIO5_EDGE_HIGH: u1, - GPIO6_LEVEL_LOW: u1, - GPIO6_LEVEL_HIGH: u1, - GPIO6_EDGE_LOW: u1, - GPIO6_EDGE_HIGH: u1, - GPIO7_LEVEL_LOW: u1, - GPIO7_LEVEL_HIGH: u1, - GPIO7_EDGE_LOW: u1, - GPIO7_EDGE_HIGH: u1, - }), - /// Interrupt Force for proc0 - PROC0_INTF1: mmio.Mmio(packed struct(u32) { - GPIO8_LEVEL_LOW: u1, - GPIO8_LEVEL_HIGH: u1, - GPIO8_EDGE_LOW: u1, - GPIO8_EDGE_HIGH: u1, - GPIO9_LEVEL_LOW: u1, - GPIO9_LEVEL_HIGH: u1, - GPIO9_EDGE_LOW: u1, - GPIO9_EDGE_HIGH: u1, - GPIO10_LEVEL_LOW: u1, - GPIO10_LEVEL_HIGH: u1, - GPIO10_EDGE_LOW: u1, - GPIO10_EDGE_HIGH: u1, - GPIO11_LEVEL_LOW: u1, - GPIO11_LEVEL_HIGH: u1, - GPIO11_EDGE_LOW: u1, - GPIO11_EDGE_HIGH: u1, - GPIO12_LEVEL_LOW: u1, - GPIO12_LEVEL_HIGH: u1, - GPIO12_EDGE_LOW: u1, - GPIO12_EDGE_HIGH: u1, - GPIO13_LEVEL_LOW: u1, - GPIO13_LEVEL_HIGH: u1, - GPIO13_EDGE_LOW: u1, - GPIO13_EDGE_HIGH: u1, - GPIO14_LEVEL_LOW: u1, - GPIO14_LEVEL_HIGH: u1, - GPIO14_EDGE_LOW: u1, - GPIO14_EDGE_HIGH: u1, - GPIO15_LEVEL_LOW: u1, - GPIO15_LEVEL_HIGH: u1, - GPIO15_EDGE_LOW: u1, - GPIO15_EDGE_HIGH: u1, - }), - /// Interrupt Force for proc0 - PROC0_INTF2: mmio.Mmio(packed struct(u32) { - GPIO16_LEVEL_LOW: u1, - GPIO16_LEVEL_HIGH: u1, - GPIO16_EDGE_LOW: u1, - GPIO16_EDGE_HIGH: u1, - GPIO17_LEVEL_LOW: u1, - GPIO17_LEVEL_HIGH: u1, - GPIO17_EDGE_LOW: u1, - GPIO17_EDGE_HIGH: u1, - GPIO18_LEVEL_LOW: u1, - GPIO18_LEVEL_HIGH: u1, - GPIO18_EDGE_LOW: u1, - GPIO18_EDGE_HIGH: u1, - GPIO19_LEVEL_LOW: u1, - GPIO19_LEVEL_HIGH: u1, - GPIO19_EDGE_LOW: u1, - GPIO19_EDGE_HIGH: u1, - GPIO20_LEVEL_LOW: u1, - GPIO20_LEVEL_HIGH: u1, - GPIO20_EDGE_LOW: u1, - GPIO20_EDGE_HIGH: u1, - GPIO21_LEVEL_LOW: u1, - GPIO21_LEVEL_HIGH: u1, - GPIO21_EDGE_LOW: u1, - GPIO21_EDGE_HIGH: u1, - GPIO22_LEVEL_LOW: u1, - GPIO22_LEVEL_HIGH: u1, - GPIO22_EDGE_LOW: u1, - GPIO22_EDGE_HIGH: u1, - GPIO23_LEVEL_LOW: u1, - GPIO23_LEVEL_HIGH: u1, - GPIO23_EDGE_LOW: u1, - GPIO23_EDGE_HIGH: u1, - }), - /// Interrupt Force for proc0 - PROC0_INTF3: mmio.Mmio(packed struct(u32) { - GPIO24_LEVEL_LOW: u1, - GPIO24_LEVEL_HIGH: u1, - GPIO24_EDGE_LOW: u1, - GPIO24_EDGE_HIGH: u1, - GPIO25_LEVEL_LOW: u1, - GPIO25_LEVEL_HIGH: u1, - GPIO25_EDGE_LOW: u1, - GPIO25_EDGE_HIGH: u1, - GPIO26_LEVEL_LOW: u1, - GPIO26_LEVEL_HIGH: u1, - GPIO26_EDGE_LOW: u1, - GPIO26_EDGE_HIGH: u1, - GPIO27_LEVEL_LOW: u1, - GPIO27_LEVEL_HIGH: u1, - GPIO27_EDGE_LOW: u1, - GPIO27_EDGE_HIGH: u1, - GPIO28_LEVEL_LOW: u1, - GPIO28_LEVEL_HIGH: u1, - GPIO28_EDGE_LOW: u1, - GPIO28_EDGE_HIGH: u1, - GPIO29_LEVEL_LOW: u1, - GPIO29_LEVEL_HIGH: u1, - GPIO29_EDGE_LOW: u1, - GPIO29_EDGE_HIGH: u1, - padding: u8, - }), - /// Interrupt status after masking & forcing for proc0 - PROC0_INTS0: mmio.Mmio(packed struct(u32) { - GPIO0_LEVEL_LOW: u1, - GPIO0_LEVEL_HIGH: u1, - GPIO0_EDGE_LOW: u1, - GPIO0_EDGE_HIGH: u1, - GPIO1_LEVEL_LOW: u1, - GPIO1_LEVEL_HIGH: u1, - GPIO1_EDGE_LOW: u1, - GPIO1_EDGE_HIGH: u1, - GPIO2_LEVEL_LOW: u1, - GPIO2_LEVEL_HIGH: u1, - GPIO2_EDGE_LOW: u1, - GPIO2_EDGE_HIGH: u1, - GPIO3_LEVEL_LOW: u1, - GPIO3_LEVEL_HIGH: u1, - GPIO3_EDGE_LOW: u1, - GPIO3_EDGE_HIGH: u1, - GPIO4_LEVEL_LOW: u1, - GPIO4_LEVEL_HIGH: u1, - GPIO4_EDGE_LOW: u1, - GPIO4_EDGE_HIGH: u1, - GPIO5_LEVEL_LOW: u1, - GPIO5_LEVEL_HIGH: u1, - GPIO5_EDGE_LOW: u1, - GPIO5_EDGE_HIGH: u1, - GPIO6_LEVEL_LOW: u1, - GPIO6_LEVEL_HIGH: u1, - GPIO6_EDGE_LOW: u1, - GPIO6_EDGE_HIGH: u1, - GPIO7_LEVEL_LOW: u1, - GPIO7_LEVEL_HIGH: u1, - GPIO7_EDGE_LOW: u1, - GPIO7_EDGE_HIGH: u1, - }), - /// Interrupt status after masking & forcing for proc0 - PROC0_INTS1: mmio.Mmio(packed struct(u32) { - GPIO8_LEVEL_LOW: u1, - GPIO8_LEVEL_HIGH: u1, - GPIO8_EDGE_LOW: u1, - GPIO8_EDGE_HIGH: u1, - GPIO9_LEVEL_LOW: u1, - GPIO9_LEVEL_HIGH: u1, - GPIO9_EDGE_LOW: u1, - GPIO9_EDGE_HIGH: u1, - GPIO10_LEVEL_LOW: u1, - GPIO10_LEVEL_HIGH: u1, - GPIO10_EDGE_LOW: u1, - GPIO10_EDGE_HIGH: u1, - GPIO11_LEVEL_LOW: u1, - GPIO11_LEVEL_HIGH: u1, - GPIO11_EDGE_LOW: u1, - GPIO11_EDGE_HIGH: u1, - GPIO12_LEVEL_LOW: u1, - GPIO12_LEVEL_HIGH: u1, - GPIO12_EDGE_LOW: u1, - GPIO12_EDGE_HIGH: u1, - GPIO13_LEVEL_LOW: u1, - GPIO13_LEVEL_HIGH: u1, - GPIO13_EDGE_LOW: u1, - GPIO13_EDGE_HIGH: u1, - GPIO14_LEVEL_LOW: u1, - GPIO14_LEVEL_HIGH: u1, - GPIO14_EDGE_LOW: u1, - GPIO14_EDGE_HIGH: u1, - GPIO15_LEVEL_LOW: u1, - GPIO15_LEVEL_HIGH: u1, - GPIO15_EDGE_LOW: u1, - GPIO15_EDGE_HIGH: u1, - }), - /// Interrupt status after masking & forcing for proc0 - PROC0_INTS2: mmio.Mmio(packed struct(u32) { - GPIO16_LEVEL_LOW: u1, - GPIO16_LEVEL_HIGH: u1, - GPIO16_EDGE_LOW: u1, - GPIO16_EDGE_HIGH: u1, - GPIO17_LEVEL_LOW: u1, - GPIO17_LEVEL_HIGH: u1, - GPIO17_EDGE_LOW: u1, - GPIO17_EDGE_HIGH: u1, - GPIO18_LEVEL_LOW: u1, - GPIO18_LEVEL_HIGH: u1, - GPIO18_EDGE_LOW: u1, - GPIO18_EDGE_HIGH: u1, - GPIO19_LEVEL_LOW: u1, - GPIO19_LEVEL_HIGH: u1, - GPIO19_EDGE_LOW: u1, - GPIO19_EDGE_HIGH: u1, - GPIO20_LEVEL_LOW: u1, - GPIO20_LEVEL_HIGH: u1, - GPIO20_EDGE_LOW: u1, - GPIO20_EDGE_HIGH: u1, - GPIO21_LEVEL_LOW: u1, - GPIO21_LEVEL_HIGH: u1, - GPIO21_EDGE_LOW: u1, - GPIO21_EDGE_HIGH: u1, - GPIO22_LEVEL_LOW: u1, - GPIO22_LEVEL_HIGH: u1, - GPIO22_EDGE_LOW: u1, - GPIO22_EDGE_HIGH: u1, - GPIO23_LEVEL_LOW: u1, - GPIO23_LEVEL_HIGH: u1, - GPIO23_EDGE_LOW: u1, - GPIO23_EDGE_HIGH: u1, - }), - /// Interrupt status after masking & forcing for proc0 - PROC0_INTS3: mmio.Mmio(packed struct(u32) { - GPIO24_LEVEL_LOW: u1, - GPIO24_LEVEL_HIGH: u1, - GPIO24_EDGE_LOW: u1, - GPIO24_EDGE_HIGH: u1, - GPIO25_LEVEL_LOW: u1, - GPIO25_LEVEL_HIGH: u1, - GPIO25_EDGE_LOW: u1, - GPIO25_EDGE_HIGH: u1, - GPIO26_LEVEL_LOW: u1, - GPIO26_LEVEL_HIGH: u1, - GPIO26_EDGE_LOW: u1, - GPIO26_EDGE_HIGH: u1, - GPIO27_LEVEL_LOW: u1, - GPIO27_LEVEL_HIGH: u1, - GPIO27_EDGE_LOW: u1, - GPIO27_EDGE_HIGH: u1, - GPIO28_LEVEL_LOW: u1, - GPIO28_LEVEL_HIGH: u1, - GPIO28_EDGE_LOW: u1, - GPIO28_EDGE_HIGH: u1, - GPIO29_LEVEL_LOW: u1, - GPIO29_LEVEL_HIGH: u1, - GPIO29_EDGE_LOW: u1, - GPIO29_EDGE_HIGH: u1, - padding: u8, - }), - /// Interrupt Enable for proc1 - PROC1_INTE0: mmio.Mmio(packed struct(u32) { - GPIO0_LEVEL_LOW: u1, - GPIO0_LEVEL_HIGH: u1, - GPIO0_EDGE_LOW: u1, - GPIO0_EDGE_HIGH: u1, - GPIO1_LEVEL_LOW: u1, - GPIO1_LEVEL_HIGH: u1, - GPIO1_EDGE_LOW: u1, - GPIO1_EDGE_HIGH: u1, - GPIO2_LEVEL_LOW: u1, - GPIO2_LEVEL_HIGH: u1, - GPIO2_EDGE_LOW: u1, - GPIO2_EDGE_HIGH: u1, - GPIO3_LEVEL_LOW: u1, - GPIO3_LEVEL_HIGH: u1, - GPIO3_EDGE_LOW: u1, - GPIO3_EDGE_HIGH: u1, - GPIO4_LEVEL_LOW: u1, - GPIO4_LEVEL_HIGH: u1, - GPIO4_EDGE_LOW: u1, - GPIO4_EDGE_HIGH: u1, - GPIO5_LEVEL_LOW: u1, - GPIO5_LEVEL_HIGH: u1, - GPIO5_EDGE_LOW: u1, - GPIO5_EDGE_HIGH: u1, - GPIO6_LEVEL_LOW: u1, - GPIO6_LEVEL_HIGH: u1, - GPIO6_EDGE_LOW: u1, - GPIO6_EDGE_HIGH: u1, - GPIO7_LEVEL_LOW: u1, - GPIO7_LEVEL_HIGH: u1, - GPIO7_EDGE_LOW: u1, - GPIO7_EDGE_HIGH: u1, - }), - /// Interrupt Enable for proc1 - PROC1_INTE1: mmio.Mmio(packed struct(u32) { - GPIO8_LEVEL_LOW: u1, - GPIO8_LEVEL_HIGH: u1, - GPIO8_EDGE_LOW: u1, - GPIO8_EDGE_HIGH: u1, - GPIO9_LEVEL_LOW: u1, - GPIO9_LEVEL_HIGH: u1, - GPIO9_EDGE_LOW: u1, - GPIO9_EDGE_HIGH: u1, - GPIO10_LEVEL_LOW: u1, - GPIO10_LEVEL_HIGH: u1, - GPIO10_EDGE_LOW: u1, - GPIO10_EDGE_HIGH: u1, - GPIO11_LEVEL_LOW: u1, - GPIO11_LEVEL_HIGH: u1, - GPIO11_EDGE_LOW: u1, - GPIO11_EDGE_HIGH: u1, - GPIO12_LEVEL_LOW: u1, - GPIO12_LEVEL_HIGH: u1, - GPIO12_EDGE_LOW: u1, - GPIO12_EDGE_HIGH: u1, - GPIO13_LEVEL_LOW: u1, - GPIO13_LEVEL_HIGH: u1, - GPIO13_EDGE_LOW: u1, - GPIO13_EDGE_HIGH: u1, - GPIO14_LEVEL_LOW: u1, - GPIO14_LEVEL_HIGH: u1, - GPIO14_EDGE_LOW: u1, - GPIO14_EDGE_HIGH: u1, - GPIO15_LEVEL_LOW: u1, - GPIO15_LEVEL_HIGH: u1, - GPIO15_EDGE_LOW: u1, - GPIO15_EDGE_HIGH: u1, - }), - /// Interrupt Enable for proc1 - PROC1_INTE2: mmio.Mmio(packed struct(u32) { - GPIO16_LEVEL_LOW: u1, - GPIO16_LEVEL_HIGH: u1, - GPIO16_EDGE_LOW: u1, - GPIO16_EDGE_HIGH: u1, - GPIO17_LEVEL_LOW: u1, - GPIO17_LEVEL_HIGH: u1, - GPIO17_EDGE_LOW: u1, - GPIO17_EDGE_HIGH: u1, - GPIO18_LEVEL_LOW: u1, - GPIO18_LEVEL_HIGH: u1, - GPIO18_EDGE_LOW: u1, - GPIO18_EDGE_HIGH: u1, - GPIO19_LEVEL_LOW: u1, - GPIO19_LEVEL_HIGH: u1, - GPIO19_EDGE_LOW: u1, - GPIO19_EDGE_HIGH: u1, - GPIO20_LEVEL_LOW: u1, - GPIO20_LEVEL_HIGH: u1, - GPIO20_EDGE_LOW: u1, - GPIO20_EDGE_HIGH: u1, - GPIO21_LEVEL_LOW: u1, - GPIO21_LEVEL_HIGH: u1, - GPIO21_EDGE_LOW: u1, - GPIO21_EDGE_HIGH: u1, - GPIO22_LEVEL_LOW: u1, - GPIO22_LEVEL_HIGH: u1, - GPIO22_EDGE_LOW: u1, - GPIO22_EDGE_HIGH: u1, - GPIO23_LEVEL_LOW: u1, - GPIO23_LEVEL_HIGH: u1, - GPIO23_EDGE_LOW: u1, - GPIO23_EDGE_HIGH: u1, - }), - /// Interrupt Enable for proc1 - PROC1_INTE3: mmio.Mmio(packed struct(u32) { - GPIO24_LEVEL_LOW: u1, - GPIO24_LEVEL_HIGH: u1, - GPIO24_EDGE_LOW: u1, - GPIO24_EDGE_HIGH: u1, - GPIO25_LEVEL_LOW: u1, - GPIO25_LEVEL_HIGH: u1, - GPIO25_EDGE_LOW: u1, - GPIO25_EDGE_HIGH: u1, - GPIO26_LEVEL_LOW: u1, - GPIO26_LEVEL_HIGH: u1, - GPIO26_EDGE_LOW: u1, - GPIO26_EDGE_HIGH: u1, - GPIO27_LEVEL_LOW: u1, - GPIO27_LEVEL_HIGH: u1, - GPIO27_EDGE_LOW: u1, - GPIO27_EDGE_HIGH: u1, - GPIO28_LEVEL_LOW: u1, - GPIO28_LEVEL_HIGH: u1, - GPIO28_EDGE_LOW: u1, - GPIO28_EDGE_HIGH: u1, - GPIO29_LEVEL_LOW: u1, - GPIO29_LEVEL_HIGH: u1, - GPIO29_EDGE_LOW: u1, - GPIO29_EDGE_HIGH: u1, - padding: u8, - }), - /// Interrupt Force for proc1 - PROC1_INTF0: mmio.Mmio(packed struct(u32) { - GPIO0_LEVEL_LOW: u1, - GPIO0_LEVEL_HIGH: u1, - GPIO0_EDGE_LOW: u1, - GPIO0_EDGE_HIGH: u1, - GPIO1_LEVEL_LOW: u1, - GPIO1_LEVEL_HIGH: u1, - GPIO1_EDGE_LOW: u1, - GPIO1_EDGE_HIGH: u1, - GPIO2_LEVEL_LOW: u1, - GPIO2_LEVEL_HIGH: u1, - GPIO2_EDGE_LOW: u1, - GPIO2_EDGE_HIGH: u1, - GPIO3_LEVEL_LOW: u1, - GPIO3_LEVEL_HIGH: u1, - GPIO3_EDGE_LOW: u1, - GPIO3_EDGE_HIGH: u1, - GPIO4_LEVEL_LOW: u1, - GPIO4_LEVEL_HIGH: u1, - GPIO4_EDGE_LOW: u1, - GPIO4_EDGE_HIGH: u1, - GPIO5_LEVEL_LOW: u1, - GPIO5_LEVEL_HIGH: u1, - GPIO5_EDGE_LOW: u1, - GPIO5_EDGE_HIGH: u1, - GPIO6_LEVEL_LOW: u1, - GPIO6_LEVEL_HIGH: u1, - GPIO6_EDGE_LOW: u1, - GPIO6_EDGE_HIGH: u1, - GPIO7_LEVEL_LOW: u1, - GPIO7_LEVEL_HIGH: u1, - GPIO7_EDGE_LOW: u1, - GPIO7_EDGE_HIGH: u1, - }), - /// Interrupt Force for proc1 - PROC1_INTF1: mmio.Mmio(packed struct(u32) { - GPIO8_LEVEL_LOW: u1, - GPIO8_LEVEL_HIGH: u1, - GPIO8_EDGE_LOW: u1, - GPIO8_EDGE_HIGH: u1, - GPIO9_LEVEL_LOW: u1, - GPIO9_LEVEL_HIGH: u1, - GPIO9_EDGE_LOW: u1, - GPIO9_EDGE_HIGH: u1, - GPIO10_LEVEL_LOW: u1, - GPIO10_LEVEL_HIGH: u1, - GPIO10_EDGE_LOW: u1, - GPIO10_EDGE_HIGH: u1, - GPIO11_LEVEL_LOW: u1, - GPIO11_LEVEL_HIGH: u1, - GPIO11_EDGE_LOW: u1, - GPIO11_EDGE_HIGH: u1, - GPIO12_LEVEL_LOW: u1, - GPIO12_LEVEL_HIGH: u1, - GPIO12_EDGE_LOW: u1, - GPIO12_EDGE_HIGH: u1, - GPIO13_LEVEL_LOW: u1, - GPIO13_LEVEL_HIGH: u1, - GPIO13_EDGE_LOW: u1, - GPIO13_EDGE_HIGH: u1, - GPIO14_LEVEL_LOW: u1, - GPIO14_LEVEL_HIGH: u1, - GPIO14_EDGE_LOW: u1, - GPIO14_EDGE_HIGH: u1, - GPIO15_LEVEL_LOW: u1, - GPIO15_LEVEL_HIGH: u1, - GPIO15_EDGE_LOW: u1, - GPIO15_EDGE_HIGH: u1, - }), - /// Interrupt Force for proc1 - PROC1_INTF2: mmio.Mmio(packed struct(u32) { - GPIO16_LEVEL_LOW: u1, - GPIO16_LEVEL_HIGH: u1, - GPIO16_EDGE_LOW: u1, - GPIO16_EDGE_HIGH: u1, - GPIO17_LEVEL_LOW: u1, - GPIO17_LEVEL_HIGH: u1, - GPIO17_EDGE_LOW: u1, - GPIO17_EDGE_HIGH: u1, - GPIO18_LEVEL_LOW: u1, - GPIO18_LEVEL_HIGH: u1, - GPIO18_EDGE_LOW: u1, - GPIO18_EDGE_HIGH: u1, - GPIO19_LEVEL_LOW: u1, - GPIO19_LEVEL_HIGH: u1, - GPIO19_EDGE_LOW: u1, - GPIO19_EDGE_HIGH: u1, - GPIO20_LEVEL_LOW: u1, - GPIO20_LEVEL_HIGH: u1, - GPIO20_EDGE_LOW: u1, - GPIO20_EDGE_HIGH: u1, - GPIO21_LEVEL_LOW: u1, - GPIO21_LEVEL_HIGH: u1, - GPIO21_EDGE_LOW: u1, - GPIO21_EDGE_HIGH: u1, - GPIO22_LEVEL_LOW: u1, - GPIO22_LEVEL_HIGH: u1, - GPIO22_EDGE_LOW: u1, - GPIO22_EDGE_HIGH: u1, - GPIO23_LEVEL_LOW: u1, - GPIO23_LEVEL_HIGH: u1, - GPIO23_EDGE_LOW: u1, - GPIO23_EDGE_HIGH: u1, - }), - /// Interrupt Force for proc1 - PROC1_INTF3: mmio.Mmio(packed struct(u32) { - GPIO24_LEVEL_LOW: u1, - GPIO24_LEVEL_HIGH: u1, - GPIO24_EDGE_LOW: u1, - GPIO24_EDGE_HIGH: u1, - GPIO25_LEVEL_LOW: u1, - GPIO25_LEVEL_HIGH: u1, - GPIO25_EDGE_LOW: u1, - GPIO25_EDGE_HIGH: u1, - GPIO26_LEVEL_LOW: u1, - GPIO26_LEVEL_HIGH: u1, - GPIO26_EDGE_LOW: u1, - GPIO26_EDGE_HIGH: u1, - GPIO27_LEVEL_LOW: u1, - GPIO27_LEVEL_HIGH: u1, - GPIO27_EDGE_LOW: u1, - GPIO27_EDGE_HIGH: u1, - GPIO28_LEVEL_LOW: u1, - GPIO28_LEVEL_HIGH: u1, - GPIO28_EDGE_LOW: u1, - GPIO28_EDGE_HIGH: u1, - GPIO29_LEVEL_LOW: u1, - GPIO29_LEVEL_HIGH: u1, - GPIO29_EDGE_LOW: u1, - GPIO29_EDGE_HIGH: u1, - padding: u8, - }), - /// Interrupt status after masking & forcing for proc1 - PROC1_INTS0: mmio.Mmio(packed struct(u32) { - GPIO0_LEVEL_LOW: u1, - GPIO0_LEVEL_HIGH: u1, - GPIO0_EDGE_LOW: u1, - GPIO0_EDGE_HIGH: u1, - GPIO1_LEVEL_LOW: u1, - GPIO1_LEVEL_HIGH: u1, - GPIO1_EDGE_LOW: u1, - GPIO1_EDGE_HIGH: u1, - GPIO2_LEVEL_LOW: u1, - GPIO2_LEVEL_HIGH: u1, - GPIO2_EDGE_LOW: u1, - GPIO2_EDGE_HIGH: u1, - GPIO3_LEVEL_LOW: u1, - GPIO3_LEVEL_HIGH: u1, - GPIO3_EDGE_LOW: u1, - GPIO3_EDGE_HIGH: u1, - GPIO4_LEVEL_LOW: u1, - GPIO4_LEVEL_HIGH: u1, - GPIO4_EDGE_LOW: u1, - GPIO4_EDGE_HIGH: u1, - GPIO5_LEVEL_LOW: u1, - GPIO5_LEVEL_HIGH: u1, - GPIO5_EDGE_LOW: u1, - GPIO5_EDGE_HIGH: u1, - GPIO6_LEVEL_LOW: u1, - GPIO6_LEVEL_HIGH: u1, - GPIO6_EDGE_LOW: u1, - GPIO6_EDGE_HIGH: u1, - GPIO7_LEVEL_LOW: u1, - GPIO7_LEVEL_HIGH: u1, - GPIO7_EDGE_LOW: u1, - GPIO7_EDGE_HIGH: u1, - }), - /// Interrupt status after masking & forcing for proc1 - PROC1_INTS1: mmio.Mmio(packed struct(u32) { - GPIO8_LEVEL_LOW: u1, - GPIO8_LEVEL_HIGH: u1, - GPIO8_EDGE_LOW: u1, - GPIO8_EDGE_HIGH: u1, - GPIO9_LEVEL_LOW: u1, - GPIO9_LEVEL_HIGH: u1, - GPIO9_EDGE_LOW: u1, - GPIO9_EDGE_HIGH: u1, - GPIO10_LEVEL_LOW: u1, - GPIO10_LEVEL_HIGH: u1, - GPIO10_EDGE_LOW: u1, - GPIO10_EDGE_HIGH: u1, - GPIO11_LEVEL_LOW: u1, - GPIO11_LEVEL_HIGH: u1, - GPIO11_EDGE_LOW: u1, - GPIO11_EDGE_HIGH: u1, - GPIO12_LEVEL_LOW: u1, - GPIO12_LEVEL_HIGH: u1, - GPIO12_EDGE_LOW: u1, - GPIO12_EDGE_HIGH: u1, - GPIO13_LEVEL_LOW: u1, - GPIO13_LEVEL_HIGH: u1, - GPIO13_EDGE_LOW: u1, - GPIO13_EDGE_HIGH: u1, - GPIO14_LEVEL_LOW: u1, - GPIO14_LEVEL_HIGH: u1, - GPIO14_EDGE_LOW: u1, - GPIO14_EDGE_HIGH: u1, - GPIO15_LEVEL_LOW: u1, - GPIO15_LEVEL_HIGH: u1, - GPIO15_EDGE_LOW: u1, - GPIO15_EDGE_HIGH: u1, - }), - /// Interrupt status after masking & forcing for proc1 - PROC1_INTS2: mmio.Mmio(packed struct(u32) { - GPIO16_LEVEL_LOW: u1, - GPIO16_LEVEL_HIGH: u1, - GPIO16_EDGE_LOW: u1, - GPIO16_EDGE_HIGH: u1, - GPIO17_LEVEL_LOW: u1, - GPIO17_LEVEL_HIGH: u1, - GPIO17_EDGE_LOW: u1, - GPIO17_EDGE_HIGH: u1, - GPIO18_LEVEL_LOW: u1, - GPIO18_LEVEL_HIGH: u1, - GPIO18_EDGE_LOW: u1, - GPIO18_EDGE_HIGH: u1, - GPIO19_LEVEL_LOW: u1, - GPIO19_LEVEL_HIGH: u1, - GPIO19_EDGE_LOW: u1, - GPIO19_EDGE_HIGH: u1, - GPIO20_LEVEL_LOW: u1, - GPIO20_LEVEL_HIGH: u1, - GPIO20_EDGE_LOW: u1, - GPIO20_EDGE_HIGH: u1, - GPIO21_LEVEL_LOW: u1, - GPIO21_LEVEL_HIGH: u1, - GPIO21_EDGE_LOW: u1, - GPIO21_EDGE_HIGH: u1, - GPIO22_LEVEL_LOW: u1, - GPIO22_LEVEL_HIGH: u1, - GPIO22_EDGE_LOW: u1, - GPIO22_EDGE_HIGH: u1, - GPIO23_LEVEL_LOW: u1, - GPIO23_LEVEL_HIGH: u1, - GPIO23_EDGE_LOW: u1, - GPIO23_EDGE_HIGH: u1, - }), - /// Interrupt status after masking & forcing for proc1 - PROC1_INTS3: mmio.Mmio(packed struct(u32) { - GPIO24_LEVEL_LOW: u1, - GPIO24_LEVEL_HIGH: u1, - GPIO24_EDGE_LOW: u1, - GPIO24_EDGE_HIGH: u1, - GPIO25_LEVEL_LOW: u1, - GPIO25_LEVEL_HIGH: u1, - GPIO25_EDGE_LOW: u1, - GPIO25_EDGE_HIGH: u1, - GPIO26_LEVEL_LOW: u1, - GPIO26_LEVEL_HIGH: u1, - GPIO26_EDGE_LOW: u1, - GPIO26_EDGE_HIGH: u1, - GPIO27_LEVEL_LOW: u1, - GPIO27_LEVEL_HIGH: u1, - GPIO27_EDGE_LOW: u1, - GPIO27_EDGE_HIGH: u1, - GPIO28_LEVEL_LOW: u1, - GPIO28_LEVEL_HIGH: u1, - GPIO28_EDGE_LOW: u1, - GPIO28_EDGE_HIGH: u1, - GPIO29_LEVEL_LOW: u1, - GPIO29_LEVEL_HIGH: u1, - GPIO29_EDGE_LOW: u1, - GPIO29_EDGE_HIGH: u1, - padding: u8, - }), - /// Interrupt Enable for dormant_wake - DORMANT_WAKE_INTE0: mmio.Mmio(packed struct(u32) { - GPIO0_LEVEL_LOW: u1, - GPIO0_LEVEL_HIGH: u1, - GPIO0_EDGE_LOW: u1, - GPIO0_EDGE_HIGH: u1, - GPIO1_LEVEL_LOW: u1, - GPIO1_LEVEL_HIGH: u1, - GPIO1_EDGE_LOW: u1, - GPIO1_EDGE_HIGH: u1, - GPIO2_LEVEL_LOW: u1, - GPIO2_LEVEL_HIGH: u1, - GPIO2_EDGE_LOW: u1, - GPIO2_EDGE_HIGH: u1, - GPIO3_LEVEL_LOW: u1, - GPIO3_LEVEL_HIGH: u1, - GPIO3_EDGE_LOW: u1, - GPIO3_EDGE_HIGH: u1, - GPIO4_LEVEL_LOW: u1, - GPIO4_LEVEL_HIGH: u1, - GPIO4_EDGE_LOW: u1, - GPIO4_EDGE_HIGH: u1, - GPIO5_LEVEL_LOW: u1, - GPIO5_LEVEL_HIGH: u1, - GPIO5_EDGE_LOW: u1, - GPIO5_EDGE_HIGH: u1, - GPIO6_LEVEL_LOW: u1, - GPIO6_LEVEL_HIGH: u1, - GPIO6_EDGE_LOW: u1, - GPIO6_EDGE_HIGH: u1, - GPIO7_LEVEL_LOW: u1, - GPIO7_LEVEL_HIGH: u1, - GPIO7_EDGE_LOW: u1, - GPIO7_EDGE_HIGH: u1, - }), - /// Interrupt Enable for dormant_wake - DORMANT_WAKE_INTE1: mmio.Mmio(packed struct(u32) { - GPIO8_LEVEL_LOW: u1, - GPIO8_LEVEL_HIGH: u1, - GPIO8_EDGE_LOW: u1, - GPIO8_EDGE_HIGH: u1, - GPIO9_LEVEL_LOW: u1, - GPIO9_LEVEL_HIGH: u1, - GPIO9_EDGE_LOW: u1, - GPIO9_EDGE_HIGH: u1, - GPIO10_LEVEL_LOW: u1, - GPIO10_LEVEL_HIGH: u1, - GPIO10_EDGE_LOW: u1, - GPIO10_EDGE_HIGH: u1, - GPIO11_LEVEL_LOW: u1, - GPIO11_LEVEL_HIGH: u1, - GPIO11_EDGE_LOW: u1, - GPIO11_EDGE_HIGH: u1, - GPIO12_LEVEL_LOW: u1, - GPIO12_LEVEL_HIGH: u1, - GPIO12_EDGE_LOW: u1, - GPIO12_EDGE_HIGH: u1, - GPIO13_LEVEL_LOW: u1, - GPIO13_LEVEL_HIGH: u1, - GPIO13_EDGE_LOW: u1, - GPIO13_EDGE_HIGH: u1, - GPIO14_LEVEL_LOW: u1, - GPIO14_LEVEL_HIGH: u1, - GPIO14_EDGE_LOW: u1, - GPIO14_EDGE_HIGH: u1, - GPIO15_LEVEL_LOW: u1, - GPIO15_LEVEL_HIGH: u1, - GPIO15_EDGE_LOW: u1, - GPIO15_EDGE_HIGH: u1, - }), - /// Interrupt Enable for dormant_wake - DORMANT_WAKE_INTE2: mmio.Mmio(packed struct(u32) { - GPIO16_LEVEL_LOW: u1, - GPIO16_LEVEL_HIGH: u1, - GPIO16_EDGE_LOW: u1, - GPIO16_EDGE_HIGH: u1, - GPIO17_LEVEL_LOW: u1, - GPIO17_LEVEL_HIGH: u1, - GPIO17_EDGE_LOW: u1, - GPIO17_EDGE_HIGH: u1, - GPIO18_LEVEL_LOW: u1, - GPIO18_LEVEL_HIGH: u1, - GPIO18_EDGE_LOW: u1, - GPIO18_EDGE_HIGH: u1, - GPIO19_LEVEL_LOW: u1, - GPIO19_LEVEL_HIGH: u1, - GPIO19_EDGE_LOW: u1, - GPIO19_EDGE_HIGH: u1, - GPIO20_LEVEL_LOW: u1, - GPIO20_LEVEL_HIGH: u1, - GPIO20_EDGE_LOW: u1, - GPIO20_EDGE_HIGH: u1, - GPIO21_LEVEL_LOW: u1, - GPIO21_LEVEL_HIGH: u1, - GPIO21_EDGE_LOW: u1, - GPIO21_EDGE_HIGH: u1, - GPIO22_LEVEL_LOW: u1, - GPIO22_LEVEL_HIGH: u1, - GPIO22_EDGE_LOW: u1, - GPIO22_EDGE_HIGH: u1, - GPIO23_LEVEL_LOW: u1, - GPIO23_LEVEL_HIGH: u1, - GPIO23_EDGE_LOW: u1, - GPIO23_EDGE_HIGH: u1, - }), - /// Interrupt Enable for dormant_wake - DORMANT_WAKE_INTE3: mmio.Mmio(packed struct(u32) { - GPIO24_LEVEL_LOW: u1, - GPIO24_LEVEL_HIGH: u1, - GPIO24_EDGE_LOW: u1, - GPIO24_EDGE_HIGH: u1, - GPIO25_LEVEL_LOW: u1, - GPIO25_LEVEL_HIGH: u1, - GPIO25_EDGE_LOW: u1, - GPIO25_EDGE_HIGH: u1, - GPIO26_LEVEL_LOW: u1, - GPIO26_LEVEL_HIGH: u1, - GPIO26_EDGE_LOW: u1, - GPIO26_EDGE_HIGH: u1, - GPIO27_LEVEL_LOW: u1, - GPIO27_LEVEL_HIGH: u1, - GPIO27_EDGE_LOW: u1, - GPIO27_EDGE_HIGH: u1, - GPIO28_LEVEL_LOW: u1, - GPIO28_LEVEL_HIGH: u1, - GPIO28_EDGE_LOW: u1, - GPIO28_EDGE_HIGH: u1, - GPIO29_LEVEL_LOW: u1, - GPIO29_LEVEL_HIGH: u1, - GPIO29_EDGE_LOW: u1, - GPIO29_EDGE_HIGH: u1, - padding: u8, - }), - /// Interrupt Force for dormant_wake - DORMANT_WAKE_INTF0: mmio.Mmio(packed struct(u32) { - GPIO0_LEVEL_LOW: u1, - GPIO0_LEVEL_HIGH: u1, - GPIO0_EDGE_LOW: u1, - GPIO0_EDGE_HIGH: u1, - GPIO1_LEVEL_LOW: u1, - GPIO1_LEVEL_HIGH: u1, - GPIO1_EDGE_LOW: u1, - GPIO1_EDGE_HIGH: u1, - GPIO2_LEVEL_LOW: u1, - GPIO2_LEVEL_HIGH: u1, - GPIO2_EDGE_LOW: u1, - GPIO2_EDGE_HIGH: u1, - GPIO3_LEVEL_LOW: u1, - GPIO3_LEVEL_HIGH: u1, - GPIO3_EDGE_LOW: u1, - GPIO3_EDGE_HIGH: u1, - GPIO4_LEVEL_LOW: u1, - GPIO4_LEVEL_HIGH: u1, - GPIO4_EDGE_LOW: u1, - GPIO4_EDGE_HIGH: u1, - GPIO5_LEVEL_LOW: u1, - GPIO5_LEVEL_HIGH: u1, - GPIO5_EDGE_LOW: u1, - GPIO5_EDGE_HIGH: u1, - GPIO6_LEVEL_LOW: u1, - GPIO6_LEVEL_HIGH: u1, - GPIO6_EDGE_LOW: u1, - GPIO6_EDGE_HIGH: u1, - GPIO7_LEVEL_LOW: u1, - GPIO7_LEVEL_HIGH: u1, - GPIO7_EDGE_LOW: u1, - GPIO7_EDGE_HIGH: u1, - }), - /// Interrupt Force for dormant_wake - DORMANT_WAKE_INTF1: mmio.Mmio(packed struct(u32) { - GPIO8_LEVEL_LOW: u1, - GPIO8_LEVEL_HIGH: u1, - GPIO8_EDGE_LOW: u1, - GPIO8_EDGE_HIGH: u1, - GPIO9_LEVEL_LOW: u1, - GPIO9_LEVEL_HIGH: u1, - GPIO9_EDGE_LOW: u1, - GPIO9_EDGE_HIGH: u1, - GPIO10_LEVEL_LOW: u1, - GPIO10_LEVEL_HIGH: u1, - GPIO10_EDGE_LOW: u1, - GPIO10_EDGE_HIGH: u1, - GPIO11_LEVEL_LOW: u1, - GPIO11_LEVEL_HIGH: u1, - GPIO11_EDGE_LOW: u1, - GPIO11_EDGE_HIGH: u1, - GPIO12_LEVEL_LOW: u1, - GPIO12_LEVEL_HIGH: u1, - GPIO12_EDGE_LOW: u1, - GPIO12_EDGE_HIGH: u1, - GPIO13_LEVEL_LOW: u1, - GPIO13_LEVEL_HIGH: u1, - GPIO13_EDGE_LOW: u1, - GPIO13_EDGE_HIGH: u1, - GPIO14_LEVEL_LOW: u1, - GPIO14_LEVEL_HIGH: u1, - GPIO14_EDGE_LOW: u1, - GPIO14_EDGE_HIGH: u1, - GPIO15_LEVEL_LOW: u1, - GPIO15_LEVEL_HIGH: u1, - GPIO15_EDGE_LOW: u1, - GPIO15_EDGE_HIGH: u1, - }), - /// Interrupt Force for dormant_wake - DORMANT_WAKE_INTF2: mmio.Mmio(packed struct(u32) { - GPIO16_LEVEL_LOW: u1, - GPIO16_LEVEL_HIGH: u1, - GPIO16_EDGE_LOW: u1, - GPIO16_EDGE_HIGH: u1, - GPIO17_LEVEL_LOW: u1, - GPIO17_LEVEL_HIGH: u1, - GPIO17_EDGE_LOW: u1, - GPIO17_EDGE_HIGH: u1, - GPIO18_LEVEL_LOW: u1, - GPIO18_LEVEL_HIGH: u1, - GPIO18_EDGE_LOW: u1, - GPIO18_EDGE_HIGH: u1, - GPIO19_LEVEL_LOW: u1, - GPIO19_LEVEL_HIGH: u1, - GPIO19_EDGE_LOW: u1, - GPIO19_EDGE_HIGH: u1, - GPIO20_LEVEL_LOW: u1, - GPIO20_LEVEL_HIGH: u1, - GPIO20_EDGE_LOW: u1, - GPIO20_EDGE_HIGH: u1, - GPIO21_LEVEL_LOW: u1, - GPIO21_LEVEL_HIGH: u1, - GPIO21_EDGE_LOW: u1, - GPIO21_EDGE_HIGH: u1, - GPIO22_LEVEL_LOW: u1, - GPIO22_LEVEL_HIGH: u1, - GPIO22_EDGE_LOW: u1, - GPIO22_EDGE_HIGH: u1, - GPIO23_LEVEL_LOW: u1, - GPIO23_LEVEL_HIGH: u1, - GPIO23_EDGE_LOW: u1, - GPIO23_EDGE_HIGH: u1, - }), - /// Interrupt Force for dormant_wake - DORMANT_WAKE_INTF3: mmio.Mmio(packed struct(u32) { - GPIO24_LEVEL_LOW: u1, - GPIO24_LEVEL_HIGH: u1, - GPIO24_EDGE_LOW: u1, - GPIO24_EDGE_HIGH: u1, - GPIO25_LEVEL_LOW: u1, - GPIO25_LEVEL_HIGH: u1, - GPIO25_EDGE_LOW: u1, - GPIO25_EDGE_HIGH: u1, - GPIO26_LEVEL_LOW: u1, - GPIO26_LEVEL_HIGH: u1, - GPIO26_EDGE_LOW: u1, - GPIO26_EDGE_HIGH: u1, - GPIO27_LEVEL_LOW: u1, - GPIO27_LEVEL_HIGH: u1, - GPIO27_EDGE_LOW: u1, - GPIO27_EDGE_HIGH: u1, - GPIO28_LEVEL_LOW: u1, - GPIO28_LEVEL_HIGH: u1, - GPIO28_EDGE_LOW: u1, - GPIO28_EDGE_HIGH: u1, - GPIO29_LEVEL_LOW: u1, - GPIO29_LEVEL_HIGH: u1, - GPIO29_EDGE_LOW: u1, - GPIO29_EDGE_HIGH: u1, - padding: u8, - }), - /// Interrupt status after masking & forcing for dormant_wake - DORMANT_WAKE_INTS0: mmio.Mmio(packed struct(u32) { - GPIO0_LEVEL_LOW: u1, - GPIO0_LEVEL_HIGH: u1, - GPIO0_EDGE_LOW: u1, - GPIO0_EDGE_HIGH: u1, - GPIO1_LEVEL_LOW: u1, - GPIO1_LEVEL_HIGH: u1, - GPIO1_EDGE_LOW: u1, - GPIO1_EDGE_HIGH: u1, - GPIO2_LEVEL_LOW: u1, - GPIO2_LEVEL_HIGH: u1, - GPIO2_EDGE_LOW: u1, - GPIO2_EDGE_HIGH: u1, - GPIO3_LEVEL_LOW: u1, - GPIO3_LEVEL_HIGH: u1, - GPIO3_EDGE_LOW: u1, - GPIO3_EDGE_HIGH: u1, - GPIO4_LEVEL_LOW: u1, - GPIO4_LEVEL_HIGH: u1, - GPIO4_EDGE_LOW: u1, - GPIO4_EDGE_HIGH: u1, - GPIO5_LEVEL_LOW: u1, - GPIO5_LEVEL_HIGH: u1, - GPIO5_EDGE_LOW: u1, - GPIO5_EDGE_HIGH: u1, - GPIO6_LEVEL_LOW: u1, - GPIO6_LEVEL_HIGH: u1, - GPIO6_EDGE_LOW: u1, - GPIO6_EDGE_HIGH: u1, - GPIO7_LEVEL_LOW: u1, - GPIO7_LEVEL_HIGH: u1, - GPIO7_EDGE_LOW: u1, - GPIO7_EDGE_HIGH: u1, - }), - /// Interrupt status after masking & forcing for dormant_wake - DORMANT_WAKE_INTS1: mmio.Mmio(packed struct(u32) { - GPIO8_LEVEL_LOW: u1, - GPIO8_LEVEL_HIGH: u1, - GPIO8_EDGE_LOW: u1, - GPIO8_EDGE_HIGH: u1, - GPIO9_LEVEL_LOW: u1, - GPIO9_LEVEL_HIGH: u1, - GPIO9_EDGE_LOW: u1, - GPIO9_EDGE_HIGH: u1, - GPIO10_LEVEL_LOW: u1, - GPIO10_LEVEL_HIGH: u1, - GPIO10_EDGE_LOW: u1, - GPIO10_EDGE_HIGH: u1, - GPIO11_LEVEL_LOW: u1, - GPIO11_LEVEL_HIGH: u1, - GPIO11_EDGE_LOW: u1, - GPIO11_EDGE_HIGH: u1, - GPIO12_LEVEL_LOW: u1, - GPIO12_LEVEL_HIGH: u1, - GPIO12_EDGE_LOW: u1, - GPIO12_EDGE_HIGH: u1, - GPIO13_LEVEL_LOW: u1, - GPIO13_LEVEL_HIGH: u1, - GPIO13_EDGE_LOW: u1, - GPIO13_EDGE_HIGH: u1, - GPIO14_LEVEL_LOW: u1, - GPIO14_LEVEL_HIGH: u1, - GPIO14_EDGE_LOW: u1, - GPIO14_EDGE_HIGH: u1, - GPIO15_LEVEL_LOW: u1, - GPIO15_LEVEL_HIGH: u1, - GPIO15_EDGE_LOW: u1, - GPIO15_EDGE_HIGH: u1, - }), - /// Interrupt status after masking & forcing for dormant_wake - DORMANT_WAKE_INTS2: mmio.Mmio(packed struct(u32) { - GPIO16_LEVEL_LOW: u1, - GPIO16_LEVEL_HIGH: u1, - GPIO16_EDGE_LOW: u1, - GPIO16_EDGE_HIGH: u1, - GPIO17_LEVEL_LOW: u1, - GPIO17_LEVEL_HIGH: u1, - GPIO17_EDGE_LOW: u1, - GPIO17_EDGE_HIGH: u1, - GPIO18_LEVEL_LOW: u1, - GPIO18_LEVEL_HIGH: u1, - GPIO18_EDGE_LOW: u1, - GPIO18_EDGE_HIGH: u1, - GPIO19_LEVEL_LOW: u1, - GPIO19_LEVEL_HIGH: u1, - GPIO19_EDGE_LOW: u1, - GPIO19_EDGE_HIGH: u1, - GPIO20_LEVEL_LOW: u1, - GPIO20_LEVEL_HIGH: u1, - GPIO20_EDGE_LOW: u1, - GPIO20_EDGE_HIGH: u1, - GPIO21_LEVEL_LOW: u1, - GPIO21_LEVEL_HIGH: u1, - GPIO21_EDGE_LOW: u1, - GPIO21_EDGE_HIGH: u1, - GPIO22_LEVEL_LOW: u1, - GPIO22_LEVEL_HIGH: u1, - GPIO22_EDGE_LOW: u1, - GPIO22_EDGE_HIGH: u1, - GPIO23_LEVEL_LOW: u1, - GPIO23_LEVEL_HIGH: u1, - GPIO23_EDGE_LOW: u1, - GPIO23_EDGE_HIGH: u1, - }), - /// Interrupt status after masking & forcing for dormant_wake - DORMANT_WAKE_INTS3: mmio.Mmio(packed struct(u32) { - GPIO24_LEVEL_LOW: u1, - GPIO24_LEVEL_HIGH: u1, - GPIO24_EDGE_LOW: u1, - GPIO24_EDGE_HIGH: u1, - GPIO25_LEVEL_LOW: u1, - GPIO25_LEVEL_HIGH: u1, - GPIO25_EDGE_LOW: u1, - GPIO25_EDGE_HIGH: u1, - GPIO26_LEVEL_LOW: u1, - GPIO26_LEVEL_HIGH: u1, - GPIO26_EDGE_LOW: u1, - GPIO26_EDGE_HIGH: u1, - GPIO27_LEVEL_LOW: u1, - GPIO27_LEVEL_HIGH: u1, - GPIO27_EDGE_LOW: u1, - GPIO27_EDGE_HIGH: u1, - GPIO28_LEVEL_LOW: u1, - GPIO28_LEVEL_HIGH: u1, - GPIO28_EDGE_LOW: u1, - GPIO28_EDGE_HIGH: u1, - GPIO29_LEVEL_LOW: u1, - GPIO29_LEVEL_HIGH: u1, - GPIO29_EDGE_LOW: u1, - GPIO29_EDGE_HIGH: u1, - padding: u8, - }), - }; - - pub const IO_QSPI = extern struct { - /// GPIO status - GPIO_QSPI_SCLK_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO_QSPI_SCLK_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - xip_sclk = 0x0, - sio_30 = 0x5, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO_QSPI_SS_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO_QSPI_SS_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - xip_ss_n = 0x0, - sio_31 = 0x5, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO_QSPI_SD0_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO_QSPI_SD0_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - xip_sd0 = 0x0, - sio_32 = 0x5, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO_QSPI_SD1_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO_QSPI_SD1_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - xip_sd1 = 0x0, - sio_33 = 0x5, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO_QSPI_SD2_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO_QSPI_SD2_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - xip_sd2 = 0x0, - sio_34 = 0x5, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// GPIO status - GPIO_QSPI_SD3_STATUS: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// output signal from selected peripheral, before register override is applied - OUTFROMPERI: u1, - /// output signal to pad after register override is applied - OUTTOPAD: u1, - reserved12: u2, - /// output enable from selected peripheral, before register override is applied - OEFROMPERI: u1, - /// output enable to pad after register override is applied - OETOPAD: u1, - reserved17: u3, - /// input signal from pad, before override is applied - INFROMPAD: u1, - reserved19: u1, - /// input signal to peripheral, after override is applied - INTOPERI: u1, - reserved24: u4, - /// interrupt from pad before override is applied - IRQFROMPAD: u1, - reserved26: u1, - /// interrupt to processors, after override is applied - IRQTOPROC: u1, - padding: u5, - }), - /// GPIO control including function select and overrides. - GPIO_QSPI_SD3_CTRL: mmio.Mmio(packed struct(u32) { - /// 0-31 -> selects pin function according to the gpio table - /// 31 == NULL - FUNCSEL: packed union { - raw: u5, - value: enum(u5) { - xip_sd3 = 0x0, - sio_35 = 0x5, - null = 0x1f, - _, - }, - }, - reserved8: u3, - OUTOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// drive output low - LOW = 0x2, - /// drive output high - HIGH = 0x3, - }, - }, - reserved12: u2, - OEOVER: packed union { - raw: u2, - value: enum(u2) { - /// drive output enable from peripheral signal selected by funcsel - NORMAL = 0x0, - /// drive output enable from inverse of peripheral signal selected by funcsel - INVERT = 0x1, - /// disable output - DISABLE = 0x2, - /// enable output - ENABLE = 0x3, - }, - }, - reserved16: u2, - INOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the peri input - NORMAL = 0x0, - /// invert the peri input - INVERT = 0x1, - /// drive peri input low - LOW = 0x2, - /// drive peri input high - HIGH = 0x3, - }, - }, - reserved28: u10, - IRQOVER: packed union { - raw: u2, - value: enum(u2) { - /// don't invert the interrupt - NORMAL = 0x0, - /// invert the interrupt - INVERT = 0x1, - /// drive interrupt low - LOW = 0x2, - /// drive interrupt high - HIGH = 0x3, - }, - }, - padding: u2, - }), - /// Raw Interrupts - INTR: mmio.Mmio(packed struct(u32) { - GPIO_QSPI_SCLK_LEVEL_LOW: u1, - GPIO_QSPI_SCLK_LEVEL_HIGH: u1, - GPIO_QSPI_SCLK_EDGE_LOW: u1, - GPIO_QSPI_SCLK_EDGE_HIGH: u1, - GPIO_QSPI_SS_LEVEL_LOW: u1, - GPIO_QSPI_SS_LEVEL_HIGH: u1, - GPIO_QSPI_SS_EDGE_LOW: u1, - GPIO_QSPI_SS_EDGE_HIGH: u1, - GPIO_QSPI_SD0_LEVEL_LOW: u1, - GPIO_QSPI_SD0_LEVEL_HIGH: u1, - GPIO_QSPI_SD0_EDGE_LOW: u1, - GPIO_QSPI_SD0_EDGE_HIGH: u1, - GPIO_QSPI_SD1_LEVEL_LOW: u1, - GPIO_QSPI_SD1_LEVEL_HIGH: u1, - GPIO_QSPI_SD1_EDGE_LOW: u1, - GPIO_QSPI_SD1_EDGE_HIGH: u1, - GPIO_QSPI_SD2_LEVEL_LOW: u1, - GPIO_QSPI_SD2_LEVEL_HIGH: u1, - GPIO_QSPI_SD2_EDGE_LOW: u1, - GPIO_QSPI_SD2_EDGE_HIGH: u1, - GPIO_QSPI_SD3_LEVEL_LOW: u1, - GPIO_QSPI_SD3_LEVEL_HIGH: u1, - GPIO_QSPI_SD3_EDGE_LOW: u1, - GPIO_QSPI_SD3_EDGE_HIGH: u1, - padding: u8, - }), - /// Interrupt Enable for proc0 - PROC0_INTE: mmio.Mmio(packed struct(u32) { - GPIO_QSPI_SCLK_LEVEL_LOW: u1, - GPIO_QSPI_SCLK_LEVEL_HIGH: u1, - GPIO_QSPI_SCLK_EDGE_LOW: u1, - GPIO_QSPI_SCLK_EDGE_HIGH: u1, - GPIO_QSPI_SS_LEVEL_LOW: u1, - GPIO_QSPI_SS_LEVEL_HIGH: u1, - GPIO_QSPI_SS_EDGE_LOW: u1, - GPIO_QSPI_SS_EDGE_HIGH: u1, - GPIO_QSPI_SD0_LEVEL_LOW: u1, - GPIO_QSPI_SD0_LEVEL_HIGH: u1, - GPIO_QSPI_SD0_EDGE_LOW: u1, - GPIO_QSPI_SD0_EDGE_HIGH: u1, - GPIO_QSPI_SD1_LEVEL_LOW: u1, - GPIO_QSPI_SD1_LEVEL_HIGH: u1, - GPIO_QSPI_SD1_EDGE_LOW: u1, - GPIO_QSPI_SD1_EDGE_HIGH: u1, - GPIO_QSPI_SD2_LEVEL_LOW: u1, - GPIO_QSPI_SD2_LEVEL_HIGH: u1, - GPIO_QSPI_SD2_EDGE_LOW: u1, - GPIO_QSPI_SD2_EDGE_HIGH: u1, - GPIO_QSPI_SD3_LEVEL_LOW: u1, - GPIO_QSPI_SD3_LEVEL_HIGH: u1, - GPIO_QSPI_SD3_EDGE_LOW: u1, - GPIO_QSPI_SD3_EDGE_HIGH: u1, - padding: u8, - }), - /// Interrupt Force for proc0 - PROC0_INTF: mmio.Mmio(packed struct(u32) { - GPIO_QSPI_SCLK_LEVEL_LOW: u1, - GPIO_QSPI_SCLK_LEVEL_HIGH: u1, - GPIO_QSPI_SCLK_EDGE_LOW: u1, - GPIO_QSPI_SCLK_EDGE_HIGH: u1, - GPIO_QSPI_SS_LEVEL_LOW: u1, - GPIO_QSPI_SS_LEVEL_HIGH: u1, - GPIO_QSPI_SS_EDGE_LOW: u1, - GPIO_QSPI_SS_EDGE_HIGH: u1, - GPIO_QSPI_SD0_LEVEL_LOW: u1, - GPIO_QSPI_SD0_LEVEL_HIGH: u1, - GPIO_QSPI_SD0_EDGE_LOW: u1, - GPIO_QSPI_SD0_EDGE_HIGH: u1, - GPIO_QSPI_SD1_LEVEL_LOW: u1, - GPIO_QSPI_SD1_LEVEL_HIGH: u1, - GPIO_QSPI_SD1_EDGE_LOW: u1, - GPIO_QSPI_SD1_EDGE_HIGH: u1, - GPIO_QSPI_SD2_LEVEL_LOW: u1, - GPIO_QSPI_SD2_LEVEL_HIGH: u1, - GPIO_QSPI_SD2_EDGE_LOW: u1, - GPIO_QSPI_SD2_EDGE_HIGH: u1, - GPIO_QSPI_SD3_LEVEL_LOW: u1, - GPIO_QSPI_SD3_LEVEL_HIGH: u1, - GPIO_QSPI_SD3_EDGE_LOW: u1, - GPIO_QSPI_SD3_EDGE_HIGH: u1, - padding: u8, - }), - /// Interrupt status after masking & forcing for proc0 - PROC0_INTS: mmio.Mmio(packed struct(u32) { - GPIO_QSPI_SCLK_LEVEL_LOW: u1, - GPIO_QSPI_SCLK_LEVEL_HIGH: u1, - GPIO_QSPI_SCLK_EDGE_LOW: u1, - GPIO_QSPI_SCLK_EDGE_HIGH: u1, - GPIO_QSPI_SS_LEVEL_LOW: u1, - GPIO_QSPI_SS_LEVEL_HIGH: u1, - GPIO_QSPI_SS_EDGE_LOW: u1, - GPIO_QSPI_SS_EDGE_HIGH: u1, - GPIO_QSPI_SD0_LEVEL_LOW: u1, - GPIO_QSPI_SD0_LEVEL_HIGH: u1, - GPIO_QSPI_SD0_EDGE_LOW: u1, - GPIO_QSPI_SD0_EDGE_HIGH: u1, - GPIO_QSPI_SD1_LEVEL_LOW: u1, - GPIO_QSPI_SD1_LEVEL_HIGH: u1, - GPIO_QSPI_SD1_EDGE_LOW: u1, - GPIO_QSPI_SD1_EDGE_HIGH: u1, - GPIO_QSPI_SD2_LEVEL_LOW: u1, - GPIO_QSPI_SD2_LEVEL_HIGH: u1, - GPIO_QSPI_SD2_EDGE_LOW: u1, - GPIO_QSPI_SD2_EDGE_HIGH: u1, - GPIO_QSPI_SD3_LEVEL_LOW: u1, - GPIO_QSPI_SD3_LEVEL_HIGH: u1, - GPIO_QSPI_SD3_EDGE_LOW: u1, - GPIO_QSPI_SD3_EDGE_HIGH: u1, - padding: u8, - }), - /// Interrupt Enable for proc1 - PROC1_INTE: mmio.Mmio(packed struct(u32) { - GPIO_QSPI_SCLK_LEVEL_LOW: u1, - GPIO_QSPI_SCLK_LEVEL_HIGH: u1, - GPIO_QSPI_SCLK_EDGE_LOW: u1, - GPIO_QSPI_SCLK_EDGE_HIGH: u1, - GPIO_QSPI_SS_LEVEL_LOW: u1, - GPIO_QSPI_SS_LEVEL_HIGH: u1, - GPIO_QSPI_SS_EDGE_LOW: u1, - GPIO_QSPI_SS_EDGE_HIGH: u1, - GPIO_QSPI_SD0_LEVEL_LOW: u1, - GPIO_QSPI_SD0_LEVEL_HIGH: u1, - GPIO_QSPI_SD0_EDGE_LOW: u1, - GPIO_QSPI_SD0_EDGE_HIGH: u1, - GPIO_QSPI_SD1_LEVEL_LOW: u1, - GPIO_QSPI_SD1_LEVEL_HIGH: u1, - GPIO_QSPI_SD1_EDGE_LOW: u1, - GPIO_QSPI_SD1_EDGE_HIGH: u1, - GPIO_QSPI_SD2_LEVEL_LOW: u1, - GPIO_QSPI_SD2_LEVEL_HIGH: u1, - GPIO_QSPI_SD2_EDGE_LOW: u1, - GPIO_QSPI_SD2_EDGE_HIGH: u1, - GPIO_QSPI_SD3_LEVEL_LOW: u1, - GPIO_QSPI_SD3_LEVEL_HIGH: u1, - GPIO_QSPI_SD3_EDGE_LOW: u1, - GPIO_QSPI_SD3_EDGE_HIGH: u1, - padding: u8, - }), - /// Interrupt Force for proc1 - PROC1_INTF: mmio.Mmio(packed struct(u32) { - GPIO_QSPI_SCLK_LEVEL_LOW: u1, - GPIO_QSPI_SCLK_LEVEL_HIGH: u1, - GPIO_QSPI_SCLK_EDGE_LOW: u1, - GPIO_QSPI_SCLK_EDGE_HIGH: u1, - GPIO_QSPI_SS_LEVEL_LOW: u1, - GPIO_QSPI_SS_LEVEL_HIGH: u1, - GPIO_QSPI_SS_EDGE_LOW: u1, - GPIO_QSPI_SS_EDGE_HIGH: u1, - GPIO_QSPI_SD0_LEVEL_LOW: u1, - GPIO_QSPI_SD0_LEVEL_HIGH: u1, - GPIO_QSPI_SD0_EDGE_LOW: u1, - GPIO_QSPI_SD0_EDGE_HIGH: u1, - GPIO_QSPI_SD1_LEVEL_LOW: u1, - GPIO_QSPI_SD1_LEVEL_HIGH: u1, - GPIO_QSPI_SD1_EDGE_LOW: u1, - GPIO_QSPI_SD1_EDGE_HIGH: u1, - GPIO_QSPI_SD2_LEVEL_LOW: u1, - GPIO_QSPI_SD2_LEVEL_HIGH: u1, - GPIO_QSPI_SD2_EDGE_LOW: u1, - GPIO_QSPI_SD2_EDGE_HIGH: u1, - GPIO_QSPI_SD3_LEVEL_LOW: u1, - GPIO_QSPI_SD3_LEVEL_HIGH: u1, - GPIO_QSPI_SD3_EDGE_LOW: u1, - GPIO_QSPI_SD3_EDGE_HIGH: u1, - padding: u8, - }), - /// Interrupt status after masking & forcing for proc1 - PROC1_INTS: mmio.Mmio(packed struct(u32) { - GPIO_QSPI_SCLK_LEVEL_LOW: u1, - GPIO_QSPI_SCLK_LEVEL_HIGH: u1, - GPIO_QSPI_SCLK_EDGE_LOW: u1, - GPIO_QSPI_SCLK_EDGE_HIGH: u1, - GPIO_QSPI_SS_LEVEL_LOW: u1, - GPIO_QSPI_SS_LEVEL_HIGH: u1, - GPIO_QSPI_SS_EDGE_LOW: u1, - GPIO_QSPI_SS_EDGE_HIGH: u1, - GPIO_QSPI_SD0_LEVEL_LOW: u1, - GPIO_QSPI_SD0_LEVEL_HIGH: u1, - GPIO_QSPI_SD0_EDGE_LOW: u1, - GPIO_QSPI_SD0_EDGE_HIGH: u1, - GPIO_QSPI_SD1_LEVEL_LOW: u1, - GPIO_QSPI_SD1_LEVEL_HIGH: u1, - GPIO_QSPI_SD1_EDGE_LOW: u1, - GPIO_QSPI_SD1_EDGE_HIGH: u1, - GPIO_QSPI_SD2_LEVEL_LOW: u1, - GPIO_QSPI_SD2_LEVEL_HIGH: u1, - GPIO_QSPI_SD2_EDGE_LOW: u1, - GPIO_QSPI_SD2_EDGE_HIGH: u1, - GPIO_QSPI_SD3_LEVEL_LOW: u1, - GPIO_QSPI_SD3_LEVEL_HIGH: u1, - GPIO_QSPI_SD3_EDGE_LOW: u1, - GPIO_QSPI_SD3_EDGE_HIGH: u1, - padding: u8, - }), - /// Interrupt Enable for dormant_wake - DORMANT_WAKE_INTE: mmio.Mmio(packed struct(u32) { - GPIO_QSPI_SCLK_LEVEL_LOW: u1, - GPIO_QSPI_SCLK_LEVEL_HIGH: u1, - GPIO_QSPI_SCLK_EDGE_LOW: u1, - GPIO_QSPI_SCLK_EDGE_HIGH: u1, - GPIO_QSPI_SS_LEVEL_LOW: u1, - GPIO_QSPI_SS_LEVEL_HIGH: u1, - GPIO_QSPI_SS_EDGE_LOW: u1, - GPIO_QSPI_SS_EDGE_HIGH: u1, - GPIO_QSPI_SD0_LEVEL_LOW: u1, - GPIO_QSPI_SD0_LEVEL_HIGH: u1, - GPIO_QSPI_SD0_EDGE_LOW: u1, - GPIO_QSPI_SD0_EDGE_HIGH: u1, - GPIO_QSPI_SD1_LEVEL_LOW: u1, - GPIO_QSPI_SD1_LEVEL_HIGH: u1, - GPIO_QSPI_SD1_EDGE_LOW: u1, - GPIO_QSPI_SD1_EDGE_HIGH: u1, - GPIO_QSPI_SD2_LEVEL_LOW: u1, - GPIO_QSPI_SD2_LEVEL_HIGH: u1, - GPIO_QSPI_SD2_EDGE_LOW: u1, - GPIO_QSPI_SD2_EDGE_HIGH: u1, - GPIO_QSPI_SD3_LEVEL_LOW: u1, - GPIO_QSPI_SD3_LEVEL_HIGH: u1, - GPIO_QSPI_SD3_EDGE_LOW: u1, - GPIO_QSPI_SD3_EDGE_HIGH: u1, - padding: u8, - }), - /// Interrupt Force for dormant_wake - DORMANT_WAKE_INTF: mmio.Mmio(packed struct(u32) { - GPIO_QSPI_SCLK_LEVEL_LOW: u1, - GPIO_QSPI_SCLK_LEVEL_HIGH: u1, - GPIO_QSPI_SCLK_EDGE_LOW: u1, - GPIO_QSPI_SCLK_EDGE_HIGH: u1, - GPIO_QSPI_SS_LEVEL_LOW: u1, - GPIO_QSPI_SS_LEVEL_HIGH: u1, - GPIO_QSPI_SS_EDGE_LOW: u1, - GPIO_QSPI_SS_EDGE_HIGH: u1, - GPIO_QSPI_SD0_LEVEL_LOW: u1, - GPIO_QSPI_SD0_LEVEL_HIGH: u1, - GPIO_QSPI_SD0_EDGE_LOW: u1, - GPIO_QSPI_SD0_EDGE_HIGH: u1, - GPIO_QSPI_SD1_LEVEL_LOW: u1, - GPIO_QSPI_SD1_LEVEL_HIGH: u1, - GPIO_QSPI_SD1_EDGE_LOW: u1, - GPIO_QSPI_SD1_EDGE_HIGH: u1, - GPIO_QSPI_SD2_LEVEL_LOW: u1, - GPIO_QSPI_SD2_LEVEL_HIGH: u1, - GPIO_QSPI_SD2_EDGE_LOW: u1, - GPIO_QSPI_SD2_EDGE_HIGH: u1, - GPIO_QSPI_SD3_LEVEL_LOW: u1, - GPIO_QSPI_SD3_LEVEL_HIGH: u1, - GPIO_QSPI_SD3_EDGE_LOW: u1, - GPIO_QSPI_SD3_EDGE_HIGH: u1, - padding: u8, - }), - /// Interrupt status after masking & forcing for dormant_wake - DORMANT_WAKE_INTS: mmio.Mmio(packed struct(u32) { - GPIO_QSPI_SCLK_LEVEL_LOW: u1, - GPIO_QSPI_SCLK_LEVEL_HIGH: u1, - GPIO_QSPI_SCLK_EDGE_LOW: u1, - GPIO_QSPI_SCLK_EDGE_HIGH: u1, - GPIO_QSPI_SS_LEVEL_LOW: u1, - GPIO_QSPI_SS_LEVEL_HIGH: u1, - GPIO_QSPI_SS_EDGE_LOW: u1, - GPIO_QSPI_SS_EDGE_HIGH: u1, - GPIO_QSPI_SD0_LEVEL_LOW: u1, - GPIO_QSPI_SD0_LEVEL_HIGH: u1, - GPIO_QSPI_SD0_EDGE_LOW: u1, - GPIO_QSPI_SD0_EDGE_HIGH: u1, - GPIO_QSPI_SD1_LEVEL_LOW: u1, - GPIO_QSPI_SD1_LEVEL_HIGH: u1, - GPIO_QSPI_SD1_EDGE_LOW: u1, - GPIO_QSPI_SD1_EDGE_HIGH: u1, - GPIO_QSPI_SD2_LEVEL_LOW: u1, - GPIO_QSPI_SD2_LEVEL_HIGH: u1, - GPIO_QSPI_SD2_EDGE_LOW: u1, - GPIO_QSPI_SD2_EDGE_HIGH: u1, - GPIO_QSPI_SD3_LEVEL_LOW: u1, - GPIO_QSPI_SD3_LEVEL_HIGH: u1, - GPIO_QSPI_SD3_EDGE_LOW: u1, - GPIO_QSPI_SD3_EDGE_HIGH: u1, - padding: u8, - }), - }; - - pub const PADS_BANK0 = extern struct { - /// Voltage select. Per bank control - VOLTAGE_SELECT: mmio.Mmio(packed struct(u32) { - VOLTAGE_SELECT: packed union { - raw: u1, - value: enum(u1) { - /// Set voltage to 3.3V (DVDD >= 2V5) - @"3v3" = 0x0, - /// Set voltage to 1.8V (DVDD <= 1V8) - @"1v8" = 0x1, - }, - }, - padding: u31, - }), - /// Pad control register - GPIO0: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO1: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO2: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO3: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO4: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO5: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO6: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO7: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO8: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO9: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO10: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO11: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO12: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO13: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO14: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO15: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO16: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO17: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO18: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO19: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO20: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO21: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO22: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO23: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO24: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO25: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO26: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO27: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO28: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO29: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - SWCLK: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - SWD: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - }; - - pub const PADS_QSPI = extern struct { - /// Voltage select. Per bank control - VOLTAGE_SELECT: mmio.Mmio(packed struct(u32) { - VOLTAGE_SELECT: packed union { - raw: u1, - value: enum(u1) { - /// Set voltage to 3.3V (DVDD >= 2V5) - @"3v3" = 0x0, - /// Set voltage to 1.8V (DVDD <= 1V8) - @"1v8" = 0x1, - }, - }, - padding: u31, - }), - /// Pad control register - GPIO_QSPI_SCLK: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO_QSPI_SD0: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO_QSPI_SD1: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO_QSPI_SD2: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO_QSPI_SD3: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - /// Pad control register - GPIO_QSPI_SS: mmio.Mmio(packed struct(u32) { - /// Slew rate control. 1 = Fast, 0 = Slow - SLEWFAST: u1, - /// Enable schmitt trigger - SCHMITT: u1, - /// Pull down enable - PDE: u1, - /// Pull up enable - PUE: u1, - /// Drive strength. - DRIVE: packed union { - raw: u2, - value: enum(u2) { - @"2mA" = 0x0, - @"4mA" = 0x1, - @"8mA" = 0x2, - @"12mA" = 0x3, - }, - }, - /// Input enable - IE: u1, - /// Output disable. Has priority over output enable from peripherals - OD: u1, - padding: u24, - }), - }; - - /// Controls the crystal oscillator - pub const XOSC = extern struct { - /// Crystal Oscillator Control - CTRL: mmio.Mmio(packed struct(u32) { - /// Frequency range. This resets to 0xAA0 and cannot be changed. - FREQ_RANGE: packed union { - raw: u12, - value: enum(u12) { - @"1_15MHZ" = 0xaa0, - RESERVED_1 = 0xaa1, - RESERVED_2 = 0xaa2, - RESERVED_3 = 0xaa3, - _, - }, - }, - /// On power-up this field is initialised to DISABLE and the chip runs from the ROSC. - /// If the chip has subsequently been programmed to run from the XOSC then setting this field to DISABLE may lock-up the chip. If this is a concern then run the clk_ref from the ROSC and enable the clk_sys RESUS feature. - /// The 12-bit code is intended to give some protection against accidental writes. An invalid setting will enable the oscillator. - ENABLE: packed union { - raw: u12, - value: enum(u12) { - DISABLE = 0xd1e, - ENABLE = 0xfab, - _, - }, - }, - padding: u8, - }), - /// Crystal Oscillator Status - STATUS: mmio.Mmio(packed struct(u32) { - /// The current frequency range setting, always reads 0 - FREQ_RANGE: packed union { - raw: u2, - value: enum(u2) { - @"1_15MHZ" = 0x0, - RESERVED_1 = 0x1, - RESERVED_2 = 0x2, - RESERVED_3 = 0x3, - }, - }, - reserved12: u10, - /// Oscillator is enabled but not necessarily running and stable, resets to 0 - ENABLED: u1, - reserved24: u11, - /// An invalid value has been written to CTRL_ENABLE or CTRL_FREQ_RANGE or DORMANT - BADWRITE: u1, - reserved31: u6, - /// Oscillator is running and stable - STABLE: u1, - }), - /// Crystal Oscillator pause control - /// This is used to save power by pausing the XOSC - /// On power-up this field is initialised to WAKE - /// An invalid write will also select WAKE - /// WARNING: stop the PLLs before selecting dormant mode - /// WARNING: setup the irq before selecting dormant mode - DORMANT: u32, - /// Controls the startup delay - STARTUP: mmio.Mmio(packed struct(u32) { - /// in multiples of 256*xtal_period. The reset value of 0xc4 corresponds to approx 50 000 cycles. - DELAY: u14, - reserved20: u6, - /// Multiplies the startup_delay by 4. This is of little value to the user given that the delay can be programmed directly. - X4: u1, - padding: u11, - }), - reserved28: [12]u8, - /// A down counter running at the xosc frequency which counts to zero and stops. - /// To start the counter write a non-zero value. - /// Can be used for short software pauses when setting up time sensitive hardware. - COUNT: mmio.Mmio(packed struct(u32) { - COUNT: u8, - padding: u24, - }), - }; - - pub const PLL_SYS = extern struct { - /// Control and Status - /// GENERAL CONSTRAINTS: - /// Reference clock frequency min=5MHz, max=800MHz - /// Feedback divider min=16, max=320 - /// VCO frequency min=400MHz, max=1600MHz - CS: mmio.Mmio(packed struct(u32) { - /// Divides the PLL input reference clock. - /// Behaviour is undefined for div=0. - /// PLL output will be unpredictable during refdiv changes, wait for lock=1 before using it. - REFDIV: u6, - reserved8: u2, - /// Passes the reference clock to the output instead of the divided VCO. The VCO continues to run so the user can switch between the reference clock and the divided VCO but the output will glitch when doing so. - BYPASS: u1, - reserved31: u22, - /// PLL is locked - LOCK: u1, - }), - /// Controls the PLL power modes. - PWR: mmio.Mmio(packed struct(u32) { - /// PLL powerdown - /// To save power set high when PLL output not required. - PD: u1, - reserved2: u1, - /// PLL DSM powerdown - /// Nothing is achieved by setting this low. - DSMPD: u1, - /// PLL post divider powerdown - /// To save power set high when PLL output not required or bypass=1. - POSTDIVPD: u1, - reserved5: u1, - /// PLL VCO powerdown - /// To save power set high when PLL output not required or bypass=1. - VCOPD: u1, - padding: u26, - }), - /// Feedback divisor - /// (note: this PLL does not support fractional division) - FBDIV_INT: mmio.Mmio(packed struct(u32) { - /// see ctrl reg description for constraints - FBDIV_INT: u12, - padding: u20, - }), - /// Controls the PLL post dividers for the primary output - /// (note: this PLL does not have a secondary output) - /// the primary output is driven from VCO divided by postdiv1*postdiv2 - PRIM: mmio.Mmio(packed struct(u32) { - reserved12: u12, - /// divide by 1-7 - POSTDIV2: u3, - reserved16: u1, - /// divide by 1-7 - POSTDIV1: u3, - padding: u13, - }), - }; - - pub const PPB = extern struct { - reserved57360: [57360]u8, - /// Use the SysTick Control and Status Register to enable the SysTick features. - SYST_CSR: mmio.Mmio(packed struct(u32) { - /// Enable SysTick counter: - /// 0 = Counter disabled. - /// 1 = Counter enabled. - ENABLE: u1, - /// Enables SysTick exception request: - /// 0 = Counting down to zero does not assert the SysTick exception request. - /// 1 = Counting down to zero to asserts the SysTick exception request. - TICKINT: u1, - /// SysTick clock source. Always reads as one if SYST_CALIB reports NOREF. - /// Selects the SysTick timer clock source: - /// 0 = External reference clock. - /// 1 = Processor clock. - CLKSOURCE: u1, - reserved16: u13, - /// Returns 1 if timer counted to 0 since last time this was read. Clears on read by application or debugger. - COUNTFLAG: u1, - padding: u15, - }), - /// Use the SysTick Reload Value Register to specify the start value to load into the current value register when the counter reaches 0. It can be any value between 0 and 0x00FFFFFF. A start value of 0 is possible, but has no effect because the SysTick interrupt and COUNTFLAG are activated when counting from 1 to 0. The reset value of this register is UNKNOWN. - /// To generate a multi-shot timer with a period of N processor clock cycles, use a RELOAD value of N-1. For example, if the SysTick interrupt is required every 100 clock pulses, set RELOAD to 99. - SYST_RVR: mmio.Mmio(packed struct(u32) { - /// Value to load into the SysTick Current Value Register when the counter reaches 0. - RELOAD: u24, - padding: u8, - }), - /// Use the SysTick Current Value Register to find the current value in the register. The reset value of this register is UNKNOWN. - SYST_CVR: mmio.Mmio(packed struct(u32) { - /// Reads return the current value of the SysTick counter. This register is write-clear. Writing to it with any value clears the register to 0. Clearing this register also clears the COUNTFLAG bit of the SysTick Control and Status Register. - CURRENT: u24, - padding: u8, - }), - /// Use the SysTick Calibration Value Register to enable software to scale to any required speed using divide and multiply. - SYST_CALIB: mmio.Mmio(packed struct(u32) { - /// An optional Reload value to be used for 10ms (100Hz) timing, subject to system clock skew errors. If the value reads as 0, the calibration value is not known. - TENMS: u24, - reserved30: u6, - /// If reads as 1, the calibration value for 10ms is inexact (due to clock frequency). - SKEW: u1, - /// If reads as 1, the Reference clock is not provided - the CLKSOURCE bit of the SysTick Control and Status register will be forced to 1 and cannot be cleared to 0. - NOREF: u1, - }), - reserved57600: [224]u8, - /// Use the Interrupt Set-Enable Register to enable interrupts and determine which interrupts are currently enabled. - /// If a pending interrupt is enabled, the NVIC activates the interrupt based on its priority. If an interrupt is not enabled, asserting its interrupt signal changes the interrupt state to pending, but the NVIC never activates the interrupt, regardless of its priority. - NVIC_ISER: mmio.Mmio(packed struct(u32) { - /// Interrupt set-enable bits. - /// Write: - /// 0 = No effect. - /// 1 = Enable interrupt. - /// Read: - /// 0 = Interrupt disabled. - /// 1 = Interrupt enabled. - SETENA: u32, - }), - reserved57728: [124]u8, - /// Use the Interrupt Clear-Enable Registers to disable interrupts and determine which interrupts are currently enabled. - NVIC_ICER: mmio.Mmio(packed struct(u32) { - /// Interrupt clear-enable bits. - /// Write: - /// 0 = No effect. - /// 1 = Disable interrupt. - /// Read: - /// 0 = Interrupt disabled. - /// 1 = Interrupt enabled. - CLRENA: u32, - }), - reserved57856: [124]u8, - /// The NVIC_ISPR forces interrupts into the pending state, and shows which interrupts are pending. - NVIC_ISPR: mmio.Mmio(packed struct(u32) { - /// Interrupt set-pending bits. - /// Write: - /// 0 = No effect. - /// 1 = Changes interrupt state to pending. - /// Read: - /// 0 = Interrupt is not pending. - /// 1 = Interrupt is pending. - /// Note: Writing 1 to the NVIC_ISPR bit corresponding to: - /// An interrupt that is pending has no effect. - /// A disabled interrupt sets the state of that interrupt to pending. - SETPEND: u32, - }), - reserved57984: [124]u8, - /// Use the Interrupt Clear-Pending Register to clear pending interrupts and determine which interrupts are currently pending. - NVIC_ICPR: mmio.Mmio(packed struct(u32) { - /// Interrupt clear-pending bits. - /// Write: - /// 0 = No effect. - /// 1 = Removes pending state and interrupt. - /// Read: - /// 0 = Interrupt is not pending. - /// 1 = Interrupt is pending. - CLRPEND: u32, - }), - reserved58368: [380]u8, - /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. - /// Note: Writing 1 to an NVIC_ICPR bit does not affect the active state of the corresponding interrupt. - /// These registers are only word-accessible - NVIC_IPR0: mmio.Mmio(packed struct(u32) { - reserved6: u6, - /// Priority of interrupt 0 - IP_0: u2, - reserved14: u6, - /// Priority of interrupt 1 - IP_1: u2, - reserved22: u6, - /// Priority of interrupt 2 - IP_2: u2, - reserved30: u6, - /// Priority of interrupt 3 - IP_3: u2, - }), - /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. - NVIC_IPR1: mmio.Mmio(packed struct(u32) { - reserved6: u6, - /// Priority of interrupt 4 - IP_4: u2, - reserved14: u6, - /// Priority of interrupt 5 - IP_5: u2, - reserved22: u6, - /// Priority of interrupt 6 - IP_6: u2, - reserved30: u6, - /// Priority of interrupt 7 - IP_7: u2, - }), - /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. - NVIC_IPR2: mmio.Mmio(packed struct(u32) { - reserved6: u6, - /// Priority of interrupt 8 - IP_8: u2, - reserved14: u6, - /// Priority of interrupt 9 - IP_9: u2, - reserved22: u6, - /// Priority of interrupt 10 - IP_10: u2, - reserved30: u6, - /// Priority of interrupt 11 - IP_11: u2, - }), - /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. - NVIC_IPR3: mmio.Mmio(packed struct(u32) { - reserved6: u6, - /// Priority of interrupt 12 - IP_12: u2, - reserved14: u6, - /// Priority of interrupt 13 - IP_13: u2, - reserved22: u6, - /// Priority of interrupt 14 - IP_14: u2, - reserved30: u6, - /// Priority of interrupt 15 - IP_15: u2, - }), - /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. - NVIC_IPR4: mmio.Mmio(packed struct(u32) { - reserved6: u6, - /// Priority of interrupt 16 - IP_16: u2, - reserved14: u6, - /// Priority of interrupt 17 - IP_17: u2, - reserved22: u6, - /// Priority of interrupt 18 - IP_18: u2, - reserved30: u6, - /// Priority of interrupt 19 - IP_19: u2, - }), - /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. - NVIC_IPR5: mmio.Mmio(packed struct(u32) { - reserved6: u6, - /// Priority of interrupt 20 - IP_20: u2, - reserved14: u6, - /// Priority of interrupt 21 - IP_21: u2, - reserved22: u6, - /// Priority of interrupt 22 - IP_22: u2, - reserved30: u6, - /// Priority of interrupt 23 - IP_23: u2, - }), - /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. - NVIC_IPR6: mmio.Mmio(packed struct(u32) { - reserved6: u6, - /// Priority of interrupt 24 - IP_24: u2, - reserved14: u6, - /// Priority of interrupt 25 - IP_25: u2, - reserved22: u6, - /// Priority of interrupt 26 - IP_26: u2, - reserved30: u6, - /// Priority of interrupt 27 - IP_27: u2, - }), - /// Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. - NVIC_IPR7: mmio.Mmio(packed struct(u32) { - reserved6: u6, - /// Priority of interrupt 28 - IP_28: u2, - reserved14: u6, - /// Priority of interrupt 29 - IP_29: u2, - reserved22: u6, - /// Priority of interrupt 30 - IP_30: u2, - reserved30: u6, - /// Priority of interrupt 31 - IP_31: u2, - }), - reserved60672: [2272]u8, - /// Read the CPU ID Base Register to determine: the ID number of the processor core, the version number of the processor core, the implementation details of the processor core. - CPUID: mmio.Mmio(packed struct(u32) { - /// Minor revision number m in the rnpm revision status: - /// 0x1 = Patch 1. - REVISION: u4, - /// Number of processor within family: 0xC60 = Cortex-M0+ - PARTNO: u12, - /// Constant that defines the architecture of the processor: - /// 0xC = ARMv6-M architecture. - ARCHITECTURE: u4, - /// Major revision number n in the rnpm revision status: - /// 0x0 = Revision 0. - VARIANT: u4, - /// Implementor code: 0x41 = ARM - IMPLEMENTER: u8, - }), - /// Use the Interrupt Control State Register to set a pending Non-Maskable Interrupt (NMI), set or clear a pending PendSV, set or clear a pending SysTick, check for pending exceptions, check the vector number of the highest priority pended exception, check the vector number of the active exception. - ICSR: mmio.Mmio(packed struct(u32) { - /// Active exception number field. Reset clears the VECTACTIVE field. - VECTACTIVE: u9, - reserved12: u3, - /// Indicates the exception number for the highest priority pending exception: 0 = no pending exceptions. Non zero = The pending state includes the effect of memory-mapped enable and mask registers. It does not include the PRIMASK special-purpose register qualifier. - VECTPENDING: u9, - reserved22: u1, - /// External interrupt pending flag - ISRPENDING: u1, - /// The system can only access this bit when the core is halted. It indicates that a pending interrupt is to be taken in the next running cycle. If C_MASKINTS is clear in the Debug Halting Control and Status Register, the interrupt is serviced. - ISRPREEMPT: u1, - reserved25: u1, - /// SysTick exception clear-pending bit. - /// Write: - /// 0 = No effect. - /// 1 = Removes the pending state from the SysTick exception. - /// This bit is WO. On a register read its value is Unknown. - PENDSTCLR: u1, - /// SysTick exception set-pending bit. - /// Write: - /// 0 = No effect. - /// 1 = Changes SysTick exception state to pending. - /// Read: - /// 0 = SysTick exception is not pending. - /// 1 = SysTick exception is pending. - PENDSTSET: u1, - /// PendSV clear-pending bit. - /// Write: - /// 0 = No effect. - /// 1 = Removes the pending state from the PendSV exception. - PENDSVCLR: u1, - /// PendSV set-pending bit. - /// Write: - /// 0 = No effect. - /// 1 = Changes PendSV exception state to pending. - /// Read: - /// 0 = PendSV exception is not pending. - /// 1 = PendSV exception is pending. - /// Writing 1 to this bit is the only way to set the PendSV exception state to pending. - PENDSVSET: u1, - reserved31: u2, - /// Setting this bit will activate an NMI. Since NMI is the highest priority exception, it will activate as soon as it is registered. - /// NMI set-pending bit. - /// Write: - /// 0 = No effect. - /// 1 = Changes NMI exception state to pending. - /// Read: - /// 0 = NMI exception is not pending. - /// 1 = NMI exception is pending. - /// Because NMI is the highest-priority exception, normally the processor enters the NMI - /// exception handler as soon as it detects a write of 1 to this bit. Entering the handler then clears - /// this bit to 0. This means a read of this bit by the NMI exception handler returns 1 only if the - /// NMI signal is reasserted while the processor is executing that handler. - NMIPENDSET: u1, - }), - /// The VTOR holds the vector table offset address. - VTOR: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// Bits [31:8] of the indicate the vector table offset address. - TBLOFF: u24, - }), - /// Use the Application Interrupt and Reset Control Register to: determine data endianness, clear all active state information from debug halt mode, request a system reset. - AIRCR: mmio.Mmio(packed struct(u32) { - reserved1: u1, - /// Clears all active state information for fixed and configurable exceptions. This bit: is self-clearing, can only be set by the DAP when the core is halted. When set: clears all active exception status of the processor, forces a return to Thread mode, forces an IPSR of 0. A debugger must re-initialize the stack. - VECTCLRACTIVE: u1, - /// Writing 1 to this bit causes the SYSRESETREQ signal to the outer system to be asserted to request a reset. The intention is to force a large system reset of all major components except for debug. The C_HALT bit in the DHCSR is cleared as a result of the system reset requested. The debugger does not lose contact with the device. - SYSRESETREQ: u1, - reserved15: u12, - /// Data endianness implemented: - /// 0 = Little-endian. - ENDIANESS: u1, - /// Register key: - /// Reads as Unknown - /// On writes, write 0x05FA to VECTKEY, otherwise the write is ignored. - VECTKEY: u16, - }), - /// System Control Register. Use the System Control Register for power-management functions: signal to the system when the processor can enter a low power state, control how the processor enters and exits low power states. - SCR: mmio.Mmio(packed struct(u32) { - reserved1: u1, - /// Indicates sleep-on-exit when returning from Handler mode to Thread mode: - /// 0 = Do not sleep when returning to Thread mode. - /// 1 = Enter sleep, or deep sleep, on return from an ISR to Thread mode. - /// Setting this bit to 1 enables an interrupt driven application to avoid returning to an empty main application. - SLEEPONEXIT: u1, - /// Controls whether the processor uses sleep or deep sleep as its low power mode: - /// 0 = Sleep. - /// 1 = Deep sleep. - SLEEPDEEP: u1, - reserved4: u1, - /// Send Event on Pending bit: - /// 0 = Only enabled interrupts or events can wakeup the processor, disabled interrupts are excluded. - /// 1 = Enabled events and all interrupts, including disabled interrupts, can wakeup the processor. - /// When an event or interrupt becomes pending, the event signal wakes up the processor from WFE. If the - /// processor is not waiting for an event, the event is registered and affects the next WFE. - /// The processor also wakes up on execution of an SEV instruction or an external event. - SEVONPEND: u1, - padding: u27, - }), - /// The Configuration and Control Register permanently enables stack alignment and causes unaligned accesses to result in a Hard Fault. - CCR: mmio.Mmio(packed struct(u32) { - reserved3: u3, - /// Always reads as one, indicates that all unaligned accesses generate a HardFault. - UNALIGN_TRP: u1, - reserved9: u5, - /// Always reads as one, indicates 8-byte stack alignment on exception entry. On exception entry, the processor uses bit[9] of the stacked PSR to indicate the stack alignment. On return from the exception it uses this stacked bit to restore the correct stack alignment. - STKALIGN: u1, - padding: u22, - }), - reserved60700: [4]u8, - /// System handlers are a special class of exception handler that can have their priority set to any of the priority levels. Use the System Handler Priority Register 2 to set the priority of SVCall. - SHPR2: mmio.Mmio(packed struct(u32) { - reserved30: u30, - /// Priority of system handler 11, SVCall - PRI_11: u2, - }), - /// System handlers are a special class of exception handler that can have their priority set to any of the priority levels. Use the System Handler Priority Register 3 to set the priority of PendSV and SysTick. - SHPR3: mmio.Mmio(packed struct(u32) { - reserved22: u22, - /// Priority of system handler 14, PendSV - PRI_14: u2, - reserved30: u6, - /// Priority of system handler 15, SysTick - PRI_15: u2, - }), - /// Use the System Handler Control and State Register to determine or clear the pending status of SVCall. - SHCSR: mmio.Mmio(packed struct(u32) { - reserved15: u15, - /// Reads as 1 if SVCall is Pending. Write 1 to set pending SVCall, write 0 to clear pending SVCall. - SVCALLPENDED: u1, - padding: u16, - }), - reserved60816: [104]u8, - /// Read the MPU Type Register to determine if the processor implements an MPU, and how many regions the MPU supports. - MPU_TYPE: mmio.Mmio(packed struct(u32) { - /// Indicates support for separate instruction and data address maps. Reads as 0 as ARMv6-M only supports a unified MPU. - SEPARATE: u1, - reserved8: u7, - /// Number of regions supported by the MPU. - DREGION: u8, - /// Instruction region. Reads as zero as ARMv6-M only supports a unified MPU. - IREGION: u8, - padding: u8, - }), - /// Use the MPU Control Register to enable and disable the MPU, and to control whether the default memory map is enabled as a background region for privileged accesses, and whether the MPU is enabled for HardFaults and NMIs. - MPU_CTRL: mmio.Mmio(packed struct(u32) { - /// Enables the MPU. If the MPU is disabled, privileged and unprivileged accesses use the default memory map. - /// 0 = MPU disabled. - /// 1 = MPU enabled. - ENABLE: u1, - /// Controls the use of the MPU for HardFaults and NMIs. Setting this bit when ENABLE is clear results in UNPREDICTABLE behaviour. - /// When the MPU is enabled: - /// 0 = MPU is disabled during HardFault and NMI handlers, regardless of the value of the ENABLE bit. - /// 1 = the MPU is enabled during HardFault and NMI handlers. - HFNMIENA: u1, - /// Controls whether the default memory map is enabled as a background region for privileged accesses. This bit is ignored when ENABLE is clear. - /// 0 = If the MPU is enabled, disables use of the default memory map. Any memory access to a location not - /// covered by any enabled region causes a fault. - /// 1 = If the MPU is enabled, enables use of the default memory map as a background region for privileged software accesses. - /// When enabled, the background region acts as if it is region number -1. Any region that is defined and enabled has priority over this default map. - PRIVDEFENA: u1, - padding: u29, - }), - /// Use the MPU Region Number Register to select the region currently accessed by MPU_RBAR and MPU_RASR. - MPU_RNR: mmio.Mmio(packed struct(u32) { - /// Indicates the MPU region referenced by the MPU_RBAR and MPU_RASR registers. - /// The MPU supports 8 memory regions, so the permitted values of this field are 0-7. - REGION: u4, - padding: u28, - }), - /// Read the MPU Region Base Address Register to determine the base address of the region identified by MPU_RNR. Write to update the base address of said region or that of a specified region, with whose number MPU_RNR will also be updated. - MPU_RBAR: mmio.Mmio(packed struct(u32) { - /// On writes, specifies the number of the region whose base address to update provided VALID is set written as 1. On reads, returns bits [3:0] of MPU_RNR. - REGION: u4, - /// On writes, indicates whether the write must update the base address of the region identified by the REGION field, updating the MPU_RNR to indicate this new region. - /// Write: - /// 0 = MPU_RNR not changed, and the processor: - /// Updates the base address for the region specified in the MPU_RNR. - /// Ignores the value of the REGION field. - /// 1 = The processor: - /// Updates the value of the MPU_RNR to the value of the REGION field. - /// Updates the base address for the region specified in the REGION field. - /// Always reads as zero. - VALID: u1, - reserved8: u3, - /// Base address of the region. - ADDR: u24, - }), - /// Use the MPU Region Attribute and Size Register to define the size, access behaviour and memory type of the region identified by MPU_RNR, and enable that region. - MPU_RASR: mmio.Mmio(packed struct(u32) { - /// Enables the region. - ENABLE: u1, - /// Indicates the region size. Region size in bytes = 2^(SIZE+1). The minimum permitted value is 7 (b00111) = 256Bytes - SIZE: u5, - reserved8: u2, - /// Subregion Disable. For regions of 256 bytes or larger, each bit of this field controls whether one of the eight equal subregions is enabled. - SRD: u8, - /// The MPU Region Attribute field. Use to define the region attribute control. - /// 28 = XN: Instruction access disable bit: - /// 0 = Instruction fetches enabled. - /// 1 = Instruction fetches disabled. - /// 26:24 = AP: Access permission field - /// 18 = S: Shareable bit - /// 17 = C: Cacheable bit - /// 16 = B: Bufferable bit - ATTRS: u16, - }), - }; - - /// Register block for busfabric control signals and performance counters - pub const BUSCTRL = extern struct { - /// Set the priority of each master for bus arbitration. - BUS_PRIORITY: mmio.Mmio(packed struct(u32) { - /// 0 - low priority, 1 - high priority - PROC0: u1, - reserved4: u3, - /// 0 - low priority, 1 - high priority - PROC1: u1, - reserved8: u3, - /// 0 - low priority, 1 - high priority - DMA_R: u1, - reserved12: u3, - /// 0 - low priority, 1 - high priority - DMA_W: u1, - padding: u19, - }), - /// Bus priority acknowledge - BUS_PRIORITY_ACK: mmio.Mmio(packed struct(u32) { - /// Goes to 1 once all arbiters have registered the new global priority levels. - /// Arbiters update their local priority when servicing a new nonsequential access. - /// In normal circumstances this will happen almost immediately. - BUS_PRIORITY_ACK: u1, - padding: u31, - }), - /// Bus fabric performance counter 0 - PERFCTR0: mmio.Mmio(packed struct(u32) { - /// Busfabric saturating performance counter 0 - /// Count some event signal from the busfabric arbiters. - /// Write any value to clear. Select an event to count using PERFSEL0 - PERFCTR0: u24, - padding: u8, - }), - /// Bus fabric performance event select for PERFCTR0 - PERFSEL0: mmio.Mmio(packed struct(u32) { - /// Select an event for PERFCTR0. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. - PERFSEL0: packed union { - raw: u5, - value: enum(u5) { - apb_contested = 0x0, - apb = 0x1, - fastperi_contested = 0x2, - fastperi = 0x3, - sram5_contested = 0x4, - sram5 = 0x5, - sram4_contested = 0x6, - sram4 = 0x7, - sram3_contested = 0x8, - sram3 = 0x9, - sram2_contested = 0xa, - sram2 = 0xb, - sram1_contested = 0xc, - sram1 = 0xd, - sram0_contested = 0xe, - sram0 = 0xf, - xip_main_contested = 0x10, - xip_main = 0x11, - rom_contested = 0x12, - rom = 0x13, - _, - }, - }, - padding: u27, - }), - /// Bus fabric performance counter 1 - PERFCTR1: mmio.Mmio(packed struct(u32) { - /// Busfabric saturating performance counter 1 - /// Count some event signal from the busfabric arbiters. - /// Write any value to clear. Select an event to count using PERFSEL1 - PERFCTR1: u24, - padding: u8, - }), - /// Bus fabric performance event select for PERFCTR1 - PERFSEL1: mmio.Mmio(packed struct(u32) { - /// Select an event for PERFCTR1. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. - PERFSEL1: packed union { - raw: u5, - value: enum(u5) { - apb_contested = 0x0, - apb = 0x1, - fastperi_contested = 0x2, - fastperi = 0x3, - sram5_contested = 0x4, - sram5 = 0x5, - sram4_contested = 0x6, - sram4 = 0x7, - sram3_contested = 0x8, - sram3 = 0x9, - sram2_contested = 0xa, - sram2 = 0xb, - sram1_contested = 0xc, - sram1 = 0xd, - sram0_contested = 0xe, - sram0 = 0xf, - xip_main_contested = 0x10, - xip_main = 0x11, - rom_contested = 0x12, - rom = 0x13, - _, - }, - }, - padding: u27, - }), - /// Bus fabric performance counter 2 - PERFCTR2: mmio.Mmio(packed struct(u32) { - /// Busfabric saturating performance counter 2 - /// Count some event signal from the busfabric arbiters. - /// Write any value to clear. Select an event to count using PERFSEL2 - PERFCTR2: u24, - padding: u8, - }), - /// Bus fabric performance event select for PERFCTR2 - PERFSEL2: mmio.Mmio(packed struct(u32) { - /// Select an event for PERFCTR2. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. - PERFSEL2: packed union { - raw: u5, - value: enum(u5) { - apb_contested = 0x0, - apb = 0x1, - fastperi_contested = 0x2, - fastperi = 0x3, - sram5_contested = 0x4, - sram5 = 0x5, - sram4_contested = 0x6, - sram4 = 0x7, - sram3_contested = 0x8, - sram3 = 0x9, - sram2_contested = 0xa, - sram2 = 0xb, - sram1_contested = 0xc, - sram1 = 0xd, - sram0_contested = 0xe, - sram0 = 0xf, - xip_main_contested = 0x10, - xip_main = 0x11, - rom_contested = 0x12, - rom = 0x13, - _, - }, - }, - padding: u27, - }), - /// Bus fabric performance counter 3 - PERFCTR3: mmio.Mmio(packed struct(u32) { - /// Busfabric saturating performance counter 3 - /// Count some event signal from the busfabric arbiters. - /// Write any value to clear. Select an event to count using PERFSEL3 - PERFCTR3: u24, - padding: u8, - }), - /// Bus fabric performance event select for PERFCTR3 - PERFSEL3: mmio.Mmio(packed struct(u32) { - /// Select an event for PERFCTR3. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. - PERFSEL3: packed union { - raw: u5, - value: enum(u5) { - apb_contested = 0x0, - apb = 0x1, - fastperi_contested = 0x2, - fastperi = 0x3, - sram5_contested = 0x4, - sram5 = 0x5, - sram4_contested = 0x6, - sram4 = 0x7, - sram3_contested = 0x8, - sram3 = 0x9, - sram2_contested = 0xa, - sram2 = 0xb, - sram1_contested = 0xc, - sram1 = 0xd, - sram0_contested = 0xe, - sram0 = 0xf, - xip_main_contested = 0x10, - xip_main = 0x11, - rom_contested = 0x12, - rom = 0x13, - _, - }, - }, - padding: u27, - }), - }; - - pub const UART0 = extern struct { - /// Data Register, UARTDR - UARTDR: mmio.Mmio(packed struct(u32) { - /// Receive (read) data character. Transmit (write) data character. - DATA: u8, - /// Framing error. When set to 1, it indicates that the received character did not have a valid stop bit (a valid stop bit is 1). In FIFO mode, this error is associated with the character at the top of the FIFO. - FE: u1, - /// Parity error. When set to 1, it indicates that the parity of the received data character does not match the parity that the EPS and SPS bits in the Line Control Register, UARTLCR_H. In FIFO mode, this error is associated with the character at the top of the FIFO. - PE: u1, - /// Break error. This bit is set to 1 if a break condition was detected, indicating that the received data input was held LOW for longer than a full-word transmission time (defined as start, data, parity and stop bits). In FIFO mode, this error is associated with the character at the top of the FIFO. When a break occurs, only one 0 character is loaded into the FIFO. The next character is only enabled after the receive data input goes to a 1 (marking state), and the next valid start bit is received. - BE: u1, - /// Overrun error. This bit is set to 1 if data is received and the receive FIFO is already full. This is cleared to 0 once there is an empty space in the FIFO and a new character can be written to it. - OE: u1, - padding: u20, - }), - /// Receive Status Register/Error Clear Register, UARTRSR/UARTECR - UARTRSR: mmio.Mmio(packed struct(u32) { - /// Framing error. When set to 1, it indicates that the received character did not have a valid stop bit (a valid stop bit is 1). This bit is cleared to 0 by a write to UARTECR. In FIFO mode, this error is associated with the character at the top of the FIFO. - FE: u1, - /// Parity error. When set to 1, it indicates that the parity of the received data character does not match the parity that the EPS and SPS bits in the Line Control Register, UARTLCR_H. This bit is cleared to 0 by a write to UARTECR. In FIFO mode, this error is associated with the character at the top of the FIFO. - PE: u1, - /// Break error. This bit is set to 1 if a break condition was detected, indicating that the received data input was held LOW for longer than a full-word transmission time (defined as start, data, parity, and stop bits). This bit is cleared to 0 after a write to UARTECR. In FIFO mode, this error is associated with the character at the top of the FIFO. When a break occurs, only one 0 character is loaded into the FIFO. The next character is only enabled after the receive data input goes to a 1 (marking state) and the next valid start bit is received. - BE: u1, - /// Overrun error. This bit is set to 1 if data is received and the FIFO is already full. This bit is cleared to 0 by a write to UARTECR. The FIFO contents remain valid because no more data is written when the FIFO is full, only the contents of the shift register are overwritten. The CPU must now read the data, to empty the FIFO. - OE: u1, - padding: u28, - }), - reserved24: [16]u8, - /// Flag Register, UARTFR - UARTFR: mmio.Mmio(packed struct(u32) { - /// Clear to send. This bit is the complement of the UART clear to send, nUARTCTS, modem status input. That is, the bit is 1 when nUARTCTS is LOW. - CTS: u1, - /// Data set ready. This bit is the complement of the UART data set ready, nUARTDSR, modem status input. That is, the bit is 1 when nUARTDSR is LOW. - DSR: u1, - /// Data carrier detect. This bit is the complement of the UART data carrier detect, nUARTDCD, modem status input. That is, the bit is 1 when nUARTDCD is LOW. - DCD: u1, - /// UART busy. If this bit is set to 1, the UART is busy transmitting data. This bit remains set until the complete byte, including all the stop bits, has been sent from the shift register. This bit is set as soon as the transmit FIFO becomes non-empty, regardless of whether the UART is enabled or not. - BUSY: u1, - /// Receive FIFO empty. The meaning of this bit depends on the state of the FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the receive holding register is empty. If the FIFO is enabled, the RXFE bit is set when the receive FIFO is empty. - RXFE: u1, - /// Transmit FIFO full. The meaning of this bit depends on the state of the FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the transmit holding register is full. If the FIFO is enabled, the TXFF bit is set when the transmit FIFO is full. - TXFF: u1, - /// Receive FIFO full. The meaning of this bit depends on the state of the FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the receive holding register is full. If the FIFO is enabled, the RXFF bit is set when the receive FIFO is full. - RXFF: u1, - /// Transmit FIFO empty. The meaning of this bit depends on the state of the FEN bit in the Line Control Register, UARTLCR_H. If the FIFO is disabled, this bit is set when the transmit holding register is empty. If the FIFO is enabled, the TXFE bit is set when the transmit FIFO is empty. This bit does not indicate if there is data in the transmit shift register. - TXFE: u1, - /// Ring indicator. This bit is the complement of the UART ring indicator, nUARTRI, modem status input. That is, the bit is 1 when nUARTRI is LOW. - RI: u1, - padding: u23, - }), - reserved32: [4]u8, - /// IrDA Low-Power Counter Register, UARTILPR - UARTILPR: mmio.Mmio(packed struct(u32) { - /// 8-bit low-power divisor value. These bits are cleared to 0 at reset. - ILPDVSR: u8, - padding: u24, - }), - /// Integer Baud Rate Register, UARTIBRD - UARTIBRD: mmio.Mmio(packed struct(u32) { - /// The integer baud rate divisor. These bits are cleared to 0 on reset. - BAUD_DIVINT: u16, - padding: u16, - }), - /// Fractional Baud Rate Register, UARTFBRD - UARTFBRD: mmio.Mmio(packed struct(u32) { - /// The fractional baud rate divisor. These bits are cleared to 0 on reset. - BAUD_DIVFRAC: u6, - padding: u26, - }), - /// Line Control Register, UARTLCR_H - UARTLCR_H: mmio.Mmio(packed struct(u32) { - /// Send break. If this bit is set to 1, a low-level is continually output on the UARTTXD output, after completing transmission of the current character. For the proper execution of the break command, the software must set this bit for at least two complete frames. For normal use, this bit must be cleared to 0. - BRK: u1, - /// Parity enable: 0 = parity is disabled and no parity bit added to the data frame 1 = parity checking and generation is enabled. - PEN: u1, - /// Even parity select. Controls the type of parity the UART uses during transmission and reception: 0 = odd parity. The UART generates or checks for an odd number of 1s in the data and parity bits. 1 = even parity. The UART generates or checks for an even number of 1s in the data and parity bits. This bit has no effect when the PEN bit disables parity checking and generation. - EPS: u1, - /// Two stop bits select. If this bit is set to 1, two stop bits are transmitted at the end of the frame. The receive logic does not check for two stop bits being received. - STP2: u1, - /// Enable FIFOs: 0 = FIFOs are disabled (character mode) that is, the FIFOs become 1-byte-deep holding registers 1 = transmit and receive FIFO buffers are enabled (FIFO mode). - FEN: u1, - /// Word length. These bits indicate the number of data bits transmitted or received in a frame as follows: b11 = 8 bits b10 = 7 bits b01 = 6 bits b00 = 5 bits. - WLEN: u2, - /// Stick parity select. 0 = stick parity is disabled 1 = either: * if the EPS bit is 0 then the parity bit is transmitted and checked as a 1 * if the EPS bit is 1 then the parity bit is transmitted and checked as a 0. This bit has no effect when the PEN bit disables parity checking and generation. - SPS: u1, - padding: u24, - }), - /// Control Register, UARTCR - UARTCR: mmio.Mmio(packed struct(u32) { - /// UART enable: 0 = UART is disabled. If the UART is disabled in the middle of transmission or reception, it completes the current character before stopping. 1 = the UART is enabled. Data transmission and reception occurs for either UART signals or SIR signals depending on the setting of the SIREN bit. - UARTEN: u1, - /// SIR enable: 0 = IrDA SIR ENDEC is disabled. nSIROUT remains LOW (no light pulse generated), and signal transitions on SIRIN have no effect. 1 = IrDA SIR ENDEC is enabled. Data is transmitted and received on nSIROUT and SIRIN. UARTTXD remains HIGH, in the marking state. Signal transitions on UARTRXD or modem status inputs have no effect. This bit has no effect if the UARTEN bit disables the UART. - SIREN: u1, - /// SIR low-power IrDA mode. This bit selects the IrDA encoding mode. If this bit is cleared to 0, low-level bits are transmitted as an active high pulse with a width of 3 / 16th of the bit period. If this bit is set to 1, low-level bits are transmitted with a pulse width that is 3 times the period of the IrLPBaud16 input signal, regardless of the selected bit rate. Setting this bit uses less power, but might reduce transmission distances. - SIRLP: u1, - reserved7: u4, - /// Loopback enable. If this bit is set to 1 and the SIREN bit is set to 1 and the SIRTEST bit in the Test Control Register, UARTTCR is set to 1, then the nSIROUT path is inverted, and fed through to the SIRIN path. The SIRTEST bit in the test register must be set to 1 to override the normal half-duplex SIR operation. This must be the requirement for accessing the test registers during normal operation, and SIRTEST must be cleared to 0 when loopback testing is finished. This feature reduces the amount of external coupling required during system test. If this bit is set to 1, and the SIRTEST bit is set to 0, the UARTTXD path is fed through to the UARTRXD path. In either SIR mode or UART mode, when this bit is set, the modem outputs are also fed through to the modem inputs. This bit is cleared to 0 on reset, to disable loopback. - LBE: u1, - /// Transmit enable. If this bit is set to 1, the transmit section of the UART is enabled. Data transmission occurs for either UART signals, or SIR signals depending on the setting of the SIREN bit. When the UART is disabled in the middle of transmission, it completes the current character before stopping. - TXE: u1, - /// Receive enable. If this bit is set to 1, the receive section of the UART is enabled. Data reception occurs for either UART signals or SIR signals depending on the setting of the SIREN bit. When the UART is disabled in the middle of reception, it completes the current character before stopping. - RXE: u1, - /// Data transmit ready. This bit is the complement of the UART data transmit ready, nUARTDTR, modem status output. That is, when the bit is programmed to a 1 then nUARTDTR is LOW. - DTR: u1, - /// Request to send. This bit is the complement of the UART request to send, nUARTRTS, modem status output. That is, when the bit is programmed to a 1 then nUARTRTS is LOW. - RTS: u1, - /// This bit is the complement of the UART Out1 (nUARTOut1) modem status output. That is, when the bit is programmed to a 1 the output is 0. For DTE this can be used as Data Carrier Detect (DCD). - OUT1: u1, - /// This bit is the complement of the UART Out2 (nUARTOut2) modem status output. That is, when the bit is programmed to a 1, the output is 0. For DTE this can be used as Ring Indicator (RI). - OUT2: u1, - /// RTS hardware flow control enable. If this bit is set to 1, RTS hardware flow control is enabled. Data is only requested when there is space in the receive FIFO for it to be received. - RTSEN: u1, - /// CTS hardware flow control enable. If this bit is set to 1, CTS hardware flow control is enabled. Data is only transmitted when the nUARTCTS signal is asserted. - CTSEN: u1, - padding: u16, - }), - /// Interrupt FIFO Level Select Register, UARTIFLS - UARTIFLS: mmio.Mmio(packed struct(u32) { - /// Transmit interrupt FIFO level select. The trigger points for the transmit interrupt are as follows: b000 = Transmit FIFO becomes <= 1 / 8 full b001 = Transmit FIFO becomes <= 1 / 4 full b010 = Transmit FIFO becomes <= 1 / 2 full b011 = Transmit FIFO becomes <= 3 / 4 full b100 = Transmit FIFO becomes <= 7 / 8 full b101-b111 = reserved. - TXIFLSEL: u3, - /// Receive interrupt FIFO level select. The trigger points for the receive interrupt are as follows: b000 = Receive FIFO becomes >= 1 / 8 full b001 = Receive FIFO becomes >= 1 / 4 full b010 = Receive FIFO becomes >= 1 / 2 full b011 = Receive FIFO becomes >= 3 / 4 full b100 = Receive FIFO becomes >= 7 / 8 full b101-b111 = reserved. - RXIFLSEL: u3, - padding: u26, - }), - /// Interrupt Mask Set/Clear Register, UARTIMSC - UARTIMSC: mmio.Mmio(packed struct(u32) { - /// nUARTRI modem interrupt mask. A read returns the current mask for the UARTRIINTR interrupt. On a write of 1, the mask of the UARTRIINTR interrupt is set. A write of 0 clears the mask. - RIMIM: u1, - /// nUARTCTS modem interrupt mask. A read returns the current mask for the UARTCTSINTR interrupt. On a write of 1, the mask of the UARTCTSINTR interrupt is set. A write of 0 clears the mask. - CTSMIM: u1, - /// nUARTDCD modem interrupt mask. A read returns the current mask for the UARTDCDINTR interrupt. On a write of 1, the mask of the UARTDCDINTR interrupt is set. A write of 0 clears the mask. - DCDMIM: u1, - /// nUARTDSR modem interrupt mask. A read returns the current mask for the UARTDSRINTR interrupt. On a write of 1, the mask of the UARTDSRINTR interrupt is set. A write of 0 clears the mask. - DSRMIM: u1, - /// Receive interrupt mask. A read returns the current mask for the UARTRXINTR interrupt. On a write of 1, the mask of the UARTRXINTR interrupt is set. A write of 0 clears the mask. - RXIM: u1, - /// Transmit interrupt mask. A read returns the current mask for the UARTTXINTR interrupt. On a write of 1, the mask of the UARTTXINTR interrupt is set. A write of 0 clears the mask. - TXIM: u1, - /// Receive timeout interrupt mask. A read returns the current mask for the UARTRTINTR interrupt. On a write of 1, the mask of the UARTRTINTR interrupt is set. A write of 0 clears the mask. - RTIM: u1, - /// Framing error interrupt mask. A read returns the current mask for the UARTFEINTR interrupt. On a write of 1, the mask of the UARTFEINTR interrupt is set. A write of 0 clears the mask. - FEIM: u1, - /// Parity error interrupt mask. A read returns the current mask for the UARTPEINTR interrupt. On a write of 1, the mask of the UARTPEINTR interrupt is set. A write of 0 clears the mask. - PEIM: u1, - /// Break error interrupt mask. A read returns the current mask for the UARTBEINTR interrupt. On a write of 1, the mask of the UARTBEINTR interrupt is set. A write of 0 clears the mask. - BEIM: u1, - /// Overrun error interrupt mask. A read returns the current mask for the UARTOEINTR interrupt. On a write of 1, the mask of the UARTOEINTR interrupt is set. A write of 0 clears the mask. - OEIM: u1, - padding: u21, - }), - /// Raw Interrupt Status Register, UARTRIS - UARTRIS: mmio.Mmio(packed struct(u32) { - /// nUARTRI modem interrupt status. Returns the raw interrupt state of the UARTRIINTR interrupt. - RIRMIS: u1, - /// nUARTCTS modem interrupt status. Returns the raw interrupt state of the UARTCTSINTR interrupt. - CTSRMIS: u1, - /// nUARTDCD modem interrupt status. Returns the raw interrupt state of the UARTDCDINTR interrupt. - DCDRMIS: u1, - /// nUARTDSR modem interrupt status. Returns the raw interrupt state of the UARTDSRINTR interrupt. - DSRRMIS: u1, - /// Receive interrupt status. Returns the raw interrupt state of the UARTRXINTR interrupt. - RXRIS: u1, - /// Transmit interrupt status. Returns the raw interrupt state of the UARTTXINTR interrupt. - TXRIS: u1, - /// Receive timeout interrupt status. Returns the raw interrupt state of the UARTRTINTR interrupt. a - RTRIS: u1, - /// Framing error interrupt status. Returns the raw interrupt state of the UARTFEINTR interrupt. - FERIS: u1, - /// Parity error interrupt status. Returns the raw interrupt state of the UARTPEINTR interrupt. - PERIS: u1, - /// Break error interrupt status. Returns the raw interrupt state of the UARTBEINTR interrupt. - BERIS: u1, - /// Overrun error interrupt status. Returns the raw interrupt state of the UARTOEINTR interrupt. - OERIS: u1, - padding: u21, - }), - /// Masked Interrupt Status Register, UARTMIS - UARTMIS: mmio.Mmio(packed struct(u32) { - /// nUARTRI modem masked interrupt status. Returns the masked interrupt state of the UARTRIINTR interrupt. - RIMMIS: u1, - /// nUARTCTS modem masked interrupt status. Returns the masked interrupt state of the UARTCTSINTR interrupt. - CTSMMIS: u1, - /// nUARTDCD modem masked interrupt status. Returns the masked interrupt state of the UARTDCDINTR interrupt. - DCDMMIS: u1, - /// nUARTDSR modem masked interrupt status. Returns the masked interrupt state of the UARTDSRINTR interrupt. - DSRMMIS: u1, - /// Receive masked interrupt status. Returns the masked interrupt state of the UARTRXINTR interrupt. - RXMIS: u1, - /// Transmit masked interrupt status. Returns the masked interrupt state of the UARTTXINTR interrupt. - TXMIS: u1, - /// Receive timeout masked interrupt status. Returns the masked interrupt state of the UARTRTINTR interrupt. - RTMIS: u1, - /// Framing error masked interrupt status. Returns the masked interrupt state of the UARTFEINTR interrupt. - FEMIS: u1, - /// Parity error masked interrupt status. Returns the masked interrupt state of the UARTPEINTR interrupt. - PEMIS: u1, - /// Break error masked interrupt status. Returns the masked interrupt state of the UARTBEINTR interrupt. - BEMIS: u1, - /// Overrun error masked interrupt status. Returns the masked interrupt state of the UARTOEINTR interrupt. - OEMIS: u1, - padding: u21, - }), - /// Interrupt Clear Register, UARTICR - UARTICR: mmio.Mmio(packed struct(u32) { - /// nUARTRI modem interrupt clear. Clears the UARTRIINTR interrupt. - RIMIC: u1, - /// nUARTCTS modem interrupt clear. Clears the UARTCTSINTR interrupt. - CTSMIC: u1, - /// nUARTDCD modem interrupt clear. Clears the UARTDCDINTR interrupt. - DCDMIC: u1, - /// nUARTDSR modem interrupt clear. Clears the UARTDSRINTR interrupt. - DSRMIC: u1, - /// Receive interrupt clear. Clears the UARTRXINTR interrupt. - RXIC: u1, - /// Transmit interrupt clear. Clears the UARTTXINTR interrupt. - TXIC: u1, - /// Receive timeout interrupt clear. Clears the UARTRTINTR interrupt. - RTIC: u1, - /// Framing error interrupt clear. Clears the UARTFEINTR interrupt. - FEIC: u1, - /// Parity error interrupt clear. Clears the UARTPEINTR interrupt. - PEIC: u1, - /// Break error interrupt clear. Clears the UARTBEINTR interrupt. - BEIC: u1, - /// Overrun error interrupt clear. Clears the UARTOEINTR interrupt. - OEIC: u1, - padding: u21, - }), - /// DMA Control Register, UARTDMACR - UARTDMACR: mmio.Mmio(packed struct(u32) { - /// Receive DMA enable. If this bit is set to 1, DMA for the receive FIFO is enabled. - RXDMAE: u1, - /// Transmit DMA enable. If this bit is set to 1, DMA for the transmit FIFO is enabled. - TXDMAE: u1, - /// DMA on error. If this bit is set to 1, the DMA receive request outputs, UARTRXDMASREQ or UARTRXDMABREQ, are disabled when the UART error interrupt is asserted. - DMAONERR: u1, - padding: u29, - }), - reserved4064: [3988]u8, - /// UARTPeriphID0 Register - UARTPERIPHID0: mmio.Mmio(packed struct(u32) { - /// These bits read back as 0x11 - PARTNUMBER0: u8, - padding: u24, - }), - /// UARTPeriphID1 Register - UARTPERIPHID1: mmio.Mmio(packed struct(u32) { - /// These bits read back as 0x0 - PARTNUMBER1: u4, - /// These bits read back as 0x1 - DESIGNER0: u4, - padding: u24, - }), - /// UARTPeriphID2 Register - UARTPERIPHID2: mmio.Mmio(packed struct(u32) { - /// These bits read back as 0x4 - DESIGNER1: u4, - /// This field depends on the revision of the UART: r1p0 0x0 r1p1 0x1 r1p3 0x2 r1p4 0x2 r1p5 0x3 - REVISION: u4, - padding: u24, - }), - /// UARTPeriphID3 Register - UARTPERIPHID3: mmio.Mmio(packed struct(u32) { - /// These bits read back as 0x00 - CONFIGURATION: u8, - padding: u24, - }), - /// UARTPCellID0 Register - UARTPCELLID0: mmio.Mmio(packed struct(u32) { - /// These bits read back as 0x0D - UARTPCELLID0: u8, - padding: u24, - }), - /// UARTPCellID1 Register - UARTPCELLID1: mmio.Mmio(packed struct(u32) { - /// These bits read back as 0xF0 - UARTPCELLID1: u8, - padding: u24, - }), - /// UARTPCellID2 Register - UARTPCELLID2: mmio.Mmio(packed struct(u32) { - /// These bits read back as 0x05 - UARTPCELLID2: u8, - padding: u24, - }), - /// UARTPCellID3 Register - UARTPCELLID3: mmio.Mmio(packed struct(u32) { - /// These bits read back as 0xB1 - UARTPCELLID3: u8, - padding: u24, - }), - }; - - /// Single-cycle IO block - /// Provides core-local and inter-core hardware for the two processors, with single-cycle access. - pub const SIO = extern struct { - /// Processor core identifier - /// Value is 0 when read from processor core 0, and 1 when read from processor core 1. - CPUID: u32, - /// Input value for GPIO pins - GPIO_IN: mmio.Mmio(packed struct(u32) { - /// Input value for GPIO0...29 - GPIO_IN: u30, - padding: u2, - }), - /// Input value for QSPI pins - GPIO_HI_IN: mmio.Mmio(packed struct(u32) { - /// Input value on QSPI IO in order 0..5: SCLK, SSn, SD0, SD1, SD2, SD3 - GPIO_HI_IN: u6, - padding: u26, - }), - reserved16: [4]u8, - /// GPIO output value - GPIO_OUT: mmio.Mmio(packed struct(u32) { - /// Set output level (1/0 -> high/low) for GPIO0...29. - /// Reading back gives the last value written, NOT the input value from the pins. - /// If core 0 and core 1 both write to GPIO_OUT simultaneously (or to a SET/CLR/XOR alias), - /// the result is as though the write from core 0 took place first, - /// and the write from core 1 was then applied to that intermediate result. - GPIO_OUT: u30, - padding: u2, - }), - /// GPIO output value set - GPIO_OUT_SET: mmio.Mmio(packed struct(u32) { - /// Perform an atomic bit-set on GPIO_OUT, i.e. `GPIO_OUT |= wdata` - GPIO_OUT_SET: u30, - padding: u2, - }), - /// GPIO output value clear - GPIO_OUT_CLR: mmio.Mmio(packed struct(u32) { - /// Perform an atomic bit-clear on GPIO_OUT, i.e. `GPIO_OUT &= ~wdata` - GPIO_OUT_CLR: u30, - padding: u2, - }), - /// GPIO output value XOR - GPIO_OUT_XOR: mmio.Mmio(packed struct(u32) { - /// Perform an atomic bitwise XOR on GPIO_OUT, i.e. `GPIO_OUT ^= wdata` - GPIO_OUT_XOR: u30, - padding: u2, - }), - /// GPIO output enable - GPIO_OE: mmio.Mmio(packed struct(u32) { - /// Set output enable (1/0 -> output/input) for GPIO0...29. - /// Reading back gives the last value written. - /// If core 0 and core 1 both write to GPIO_OE simultaneously (or to a SET/CLR/XOR alias), - /// the result is as though the write from core 0 took place first, - /// and the write from core 1 was then applied to that intermediate result. - GPIO_OE: u30, - padding: u2, - }), - /// GPIO output enable set - GPIO_OE_SET: mmio.Mmio(packed struct(u32) { - /// Perform an atomic bit-set on GPIO_OE, i.e. `GPIO_OE |= wdata` - GPIO_OE_SET: u30, - padding: u2, - }), - /// GPIO output enable clear - GPIO_OE_CLR: mmio.Mmio(packed struct(u32) { - /// Perform an atomic bit-clear on GPIO_OE, i.e. `GPIO_OE &= ~wdata` - GPIO_OE_CLR: u30, - padding: u2, - }), - /// GPIO output enable XOR - GPIO_OE_XOR: mmio.Mmio(packed struct(u32) { - /// Perform an atomic bitwise XOR on GPIO_OE, i.e. `GPIO_OE ^= wdata` - GPIO_OE_XOR: u30, - padding: u2, - }), - /// QSPI output value - GPIO_HI_OUT: mmio.Mmio(packed struct(u32) { - /// Set output level (1/0 -> high/low) for QSPI IO0...5. - /// Reading back gives the last value written, NOT the input value from the pins. - /// If core 0 and core 1 both write to GPIO_HI_OUT simultaneously (or to a SET/CLR/XOR alias), - /// the result is as though the write from core 0 took place first, - /// and the write from core 1 was then applied to that intermediate result. - GPIO_HI_OUT: u6, - padding: u26, - }), - /// QSPI output value set - GPIO_HI_OUT_SET: mmio.Mmio(packed struct(u32) { - /// Perform an atomic bit-set on GPIO_HI_OUT, i.e. `GPIO_HI_OUT |= wdata` - GPIO_HI_OUT_SET: u6, - padding: u26, - }), - /// QSPI output value clear - GPIO_HI_OUT_CLR: mmio.Mmio(packed struct(u32) { - /// Perform an atomic bit-clear on GPIO_HI_OUT, i.e. `GPIO_HI_OUT &= ~wdata` - GPIO_HI_OUT_CLR: u6, - padding: u26, - }), - /// QSPI output value XOR - GPIO_HI_OUT_XOR: mmio.Mmio(packed struct(u32) { - /// Perform an atomic bitwise XOR on GPIO_HI_OUT, i.e. `GPIO_HI_OUT ^= wdata` - GPIO_HI_OUT_XOR: u6, - padding: u26, - }), - /// QSPI output enable - GPIO_HI_OE: mmio.Mmio(packed struct(u32) { - /// Set output enable (1/0 -> output/input) for QSPI IO0...5. - /// Reading back gives the last value written. - /// If core 0 and core 1 both write to GPIO_HI_OE simultaneously (or to a SET/CLR/XOR alias), - /// the result is as though the write from core 0 took place first, - /// and the write from core 1 was then applied to that intermediate result. - GPIO_HI_OE: u6, - padding: u26, - }), - /// QSPI output enable set - GPIO_HI_OE_SET: mmio.Mmio(packed struct(u32) { - /// Perform an atomic bit-set on GPIO_HI_OE, i.e. `GPIO_HI_OE |= wdata` - GPIO_HI_OE_SET: u6, - padding: u26, - }), - /// QSPI output enable clear - GPIO_HI_OE_CLR: mmio.Mmio(packed struct(u32) { - /// Perform an atomic bit-clear on GPIO_HI_OE, i.e. `GPIO_HI_OE &= ~wdata` - GPIO_HI_OE_CLR: u6, - padding: u26, - }), - /// QSPI output enable XOR - GPIO_HI_OE_XOR: mmio.Mmio(packed struct(u32) { - /// Perform an atomic bitwise XOR on GPIO_HI_OE, i.e. `GPIO_HI_OE ^= wdata` - GPIO_HI_OE_XOR: u6, - padding: u26, - }), - /// Status register for inter-core FIFOs (mailboxes). - /// There is one FIFO in the core 0 -> core 1 direction, and one core 1 -> core 0. Both are 32 bits wide and 8 words deep. - /// Core 0 can see the read side of the 1->0 FIFO (RX), and the write side of 0->1 FIFO (TX). - /// Core 1 can see the read side of the 0->1 FIFO (RX), and the write side of 1->0 FIFO (TX). - /// The SIO IRQ for each core is the logical OR of the VLD, WOF and ROE fields of its FIFO_ST register. - FIFO_ST: mmio.Mmio(packed struct(u32) { - /// Value is 1 if this core's RX FIFO is not empty (i.e. if FIFO_RD is valid) - VLD: u1, - /// Value is 1 if this core's TX FIFO is not full (i.e. if FIFO_WR is ready for more data) - RDY: u1, - /// Sticky flag indicating the TX FIFO was written when full. This write was ignored by the FIFO. - WOF: u1, - /// Sticky flag indicating the RX FIFO was read when empty. This read was ignored by the FIFO. - ROE: u1, - padding: u28, - }), - /// Write access to this core's TX FIFO - FIFO_WR: u32, - /// Read access to this core's RX FIFO - FIFO_RD: u32, - /// Spinlock state - /// A bitmap containing the state of all 32 spinlocks (1=locked). - /// Mainly intended for debugging. - SPINLOCK_ST: u32, - /// Divider unsigned dividend - /// Write to the DIVIDEND operand of the divider, i.e. the p in `p / q`. - /// Any operand write starts a new calculation. The results appear in QUOTIENT, REMAINDER. - /// UDIVIDEND/SDIVIDEND are aliases of the same internal register. The U alias starts an - /// unsigned calculation, and the S alias starts a signed calculation. - DIV_UDIVIDEND: u32, - /// Divider unsigned divisor - /// Write to the DIVISOR operand of the divider, i.e. the q in `p / q`. - /// Any operand write starts a new calculation. The results appear in QUOTIENT, REMAINDER. - /// UDIVISOR/SDIVISOR are aliases of the same internal register. The U alias starts an - /// unsigned calculation, and the S alias starts a signed calculation. - DIV_UDIVISOR: u32, - /// Divider signed dividend - /// The same as UDIVIDEND, but starts a signed calculation, rather than unsigned. - DIV_SDIVIDEND: u32, - /// Divider signed divisor - /// The same as UDIVISOR, but starts a signed calculation, rather than unsigned. - DIV_SDIVISOR: u32, - /// Divider result quotient - /// The result of `DIVIDEND / DIVISOR` (division). Contents undefined while CSR_READY is low. - /// For signed calculations, QUOTIENT is negative when the signs of DIVIDEND and DIVISOR differ. - /// This register can be written to directly, for context save/restore purposes. This halts any - /// in-progress calculation and sets the CSR_READY and CSR_DIRTY flags. - /// Reading from QUOTIENT clears the CSR_DIRTY flag, so should read results in the order - /// REMAINDER, QUOTIENT if CSR_DIRTY is used. - DIV_QUOTIENT: u32, - /// Divider result remainder - /// The result of `DIVIDEND % DIVISOR` (modulo). Contents undefined while CSR_READY is low. - /// For signed calculations, REMAINDER is negative only when DIVIDEND is negative. - /// This register can be written to directly, for context save/restore purposes. This halts any - /// in-progress calculation and sets the CSR_READY and CSR_DIRTY flags. - DIV_REMAINDER: u32, - /// Control and status register for divider. - DIV_CSR: mmio.Mmio(packed struct(u32) { - /// Reads as 0 when a calculation is in progress, 1 otherwise. - /// Writing an operand (xDIVIDEND, xDIVISOR) will immediately start a new calculation, no - /// matter if one is already in progress. - /// Writing to a result register will immediately terminate any in-progress calculation - /// and set the READY and DIRTY flags. - READY: u1, - /// Changes to 1 when any register is written, and back to 0 when QUOTIENT is read. - /// Software can use this flag to make save/restore more efficient (skip if not DIRTY). - /// If the flag is used in this way, it's recommended to either read QUOTIENT only, - /// or REMAINDER and then QUOTIENT, to prevent data loss on context switch. - DIRTY: u1, - padding: u30, - }), - reserved128: [4]u8, - /// Read/write access to accumulator 0 - INTERP0_ACCUM0: u32, - /// Read/write access to accumulator 1 - INTERP0_ACCUM1: u32, - /// Read/write access to BASE0 register. - INTERP0_BASE0: u32, - /// Read/write access to BASE1 register. - INTERP0_BASE1: u32, - /// Read/write access to BASE2 register. - INTERP0_BASE2: u32, - /// Read LANE0 result, and simultaneously write lane results to both accumulators (POP). - INTERP0_POP_LANE0: u32, - /// Read LANE1 result, and simultaneously write lane results to both accumulators (POP). - INTERP0_POP_LANE1: u32, - /// Read FULL result, and simultaneously write lane results to both accumulators (POP). - INTERP0_POP_FULL: u32, - /// Read LANE0 result, without altering any internal state (PEEK). - INTERP0_PEEK_LANE0: u32, - /// Read LANE1 result, without altering any internal state (PEEK). - INTERP0_PEEK_LANE1: u32, - /// Read FULL result, without altering any internal state (PEEK). - INTERP0_PEEK_FULL: u32, - /// Control register for lane 0 - INTERP0_CTRL_LANE0: mmio.Mmio(packed struct(u32) { - /// Logical right-shift applied to accumulator before masking - SHIFT: u5, - /// The least-significant bit allowed to pass by the mask (inclusive) - MASK_LSB: u5, - /// The most-significant bit allowed to pass by the mask (inclusive) - /// Setting MSB < LSB may cause chip to turn inside-out - MASK_MSB: u5, - /// If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits - /// before adding to BASE0, and LANE0 PEEK/POP appear extended to 32 bits when read by processor. - SIGNED: u1, - /// If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware. - /// Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass) - CROSS_INPUT: u1, - /// If 1, feed the opposite lane's result into this lane's accumulator on POP. - CROSS_RESULT: u1, - /// If 1, mask + shift is bypassed for LANE0 result. This does not affect FULL result. - ADD_RAW: u1, - /// ORed into bits 29:28 of the lane result presented to the processor on the bus. - /// No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence - /// of pointers into flash or SRAM. - FORCE_MSB: u2, - /// Only present on INTERP0 on each core. If BLEND mode is enabled: - /// - LANE1 result is a linear interpolation between BASE0 and BASE1, controlled - /// by the 8 LSBs of lane 1 shift and mask value (a fractional number between - /// 0 and 255/256ths) - /// - LANE0 result does not have BASE0 added (yields only the 8 LSBs of lane 1 shift+mask value) - /// - FULL result does not have lane 1 shift+mask value added (BASE2 + lane 0 shift+mask) - /// LANE1 SIGNED flag controls whether the interpolation is signed or unsigned. - BLEND: u1, - reserved23: u1, - /// Indicates if any masked-off MSBs in ACCUM0 are set. - OVERF0: u1, - /// Indicates if any masked-off MSBs in ACCUM1 are set. - OVERF1: u1, - /// Set if either OVERF0 or OVERF1 is set. - OVERF: u1, - padding: u6, - }), - /// Control register for lane 1 - INTERP0_CTRL_LANE1: mmio.Mmio(packed struct(u32) { - /// Logical right-shift applied to accumulator before masking - SHIFT: u5, - /// The least-significant bit allowed to pass by the mask (inclusive) - MASK_LSB: u5, - /// The most-significant bit allowed to pass by the mask (inclusive) - /// Setting MSB < LSB may cause chip to turn inside-out - MASK_MSB: u5, - /// If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits - /// before adding to BASE1, and LANE1 PEEK/POP appear extended to 32 bits when read by processor. - SIGNED: u1, - /// If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware. - /// Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass) - CROSS_INPUT: u1, - /// If 1, feed the opposite lane's result into this lane's accumulator on POP. - CROSS_RESULT: u1, - /// If 1, mask + shift is bypassed for LANE1 result. This does not affect FULL result. - ADD_RAW: u1, - /// ORed into bits 29:28 of the lane result presented to the processor on the bus. - /// No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence - /// of pointers into flash or SRAM. - FORCE_MSB: u2, - padding: u11, - }), - /// Values written here are atomically added to ACCUM0 - /// Reading yields lane 0's raw shift and mask value (BASE0 not added). - INTERP0_ACCUM0_ADD: mmio.Mmio(packed struct(u32) { - INTERP0_ACCUM0_ADD: u24, - padding: u8, - }), - /// Values written here are atomically added to ACCUM1 - /// Reading yields lane 1's raw shift and mask value (BASE1 not added). - INTERP0_ACCUM1_ADD: mmio.Mmio(packed struct(u32) { - INTERP0_ACCUM1_ADD: u24, - padding: u8, - }), - /// On write, the lower 16 bits go to BASE0, upper bits to BASE1 simultaneously. - /// Each half is sign-extended to 32 bits if that lane's SIGNED flag is set. - INTERP0_BASE_1AND0: u32, - /// Read/write access to accumulator 0 - INTERP1_ACCUM0: u32, - /// Read/write access to accumulator 1 - INTERP1_ACCUM1: u32, - /// Read/write access to BASE0 register. - INTERP1_BASE0: u32, - /// Read/write access to BASE1 register. - INTERP1_BASE1: u32, - /// Read/write access to BASE2 register. - INTERP1_BASE2: u32, - /// Read LANE0 result, and simultaneously write lane results to both accumulators (POP). - INTERP1_POP_LANE0: u32, - /// Read LANE1 result, and simultaneously write lane results to both accumulators (POP). - INTERP1_POP_LANE1: u32, - /// Read FULL result, and simultaneously write lane results to both accumulators (POP). - INTERP1_POP_FULL: u32, - /// Read LANE0 result, without altering any internal state (PEEK). - INTERP1_PEEK_LANE0: u32, - /// Read LANE1 result, without altering any internal state (PEEK). - INTERP1_PEEK_LANE1: u32, - /// Read FULL result, without altering any internal state (PEEK). - INTERP1_PEEK_FULL: u32, - /// Control register for lane 0 - INTERP1_CTRL_LANE0: mmio.Mmio(packed struct(u32) { - /// Logical right-shift applied to accumulator before masking - SHIFT: u5, - /// The least-significant bit allowed to pass by the mask (inclusive) - MASK_LSB: u5, - /// The most-significant bit allowed to pass by the mask (inclusive) - /// Setting MSB < LSB may cause chip to turn inside-out - MASK_MSB: u5, - /// If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits - /// before adding to BASE0, and LANE0 PEEK/POP appear extended to 32 bits when read by processor. - SIGNED: u1, - /// If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware. - /// Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass) - CROSS_INPUT: u1, - /// If 1, feed the opposite lane's result into this lane's accumulator on POP. - CROSS_RESULT: u1, - /// If 1, mask + shift is bypassed for LANE0 result. This does not affect FULL result. - ADD_RAW: u1, - /// ORed into bits 29:28 of the lane result presented to the processor on the bus. - /// No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence - /// of pointers into flash or SRAM. - FORCE_MSB: u2, - reserved22: u1, - /// Only present on INTERP1 on each core. If CLAMP mode is enabled: - /// - LANE0 result is shifted and masked ACCUM0, clamped by a lower bound of - /// BASE0 and an upper bound of BASE1. - /// - Signedness of these comparisons is determined by LANE0_CTRL_SIGNED - CLAMP: u1, - /// Indicates if any masked-off MSBs in ACCUM0 are set. - OVERF0: u1, - /// Indicates if any masked-off MSBs in ACCUM1 are set. - OVERF1: u1, - /// Set if either OVERF0 or OVERF1 is set. - OVERF: u1, - padding: u6, - }), - /// Control register for lane 1 - INTERP1_CTRL_LANE1: mmio.Mmio(packed struct(u32) { - /// Logical right-shift applied to accumulator before masking - SHIFT: u5, - /// The least-significant bit allowed to pass by the mask (inclusive) - MASK_LSB: u5, - /// The most-significant bit allowed to pass by the mask (inclusive) - /// Setting MSB < LSB may cause chip to turn inside-out - MASK_MSB: u5, - /// If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits - /// before adding to BASE1, and LANE1 PEEK/POP appear extended to 32 bits when read by processor. - SIGNED: u1, - /// If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware. - /// Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass) - CROSS_INPUT: u1, - /// If 1, feed the opposite lane's result into this lane's accumulator on POP. - CROSS_RESULT: u1, - /// If 1, mask + shift is bypassed for LANE1 result. This does not affect FULL result. - ADD_RAW: u1, - /// ORed into bits 29:28 of the lane result presented to the processor on the bus. - /// No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence - /// of pointers into flash or SRAM. - FORCE_MSB: u2, - padding: u11, - }), - /// Values written here are atomically added to ACCUM0 - /// Reading yields lane 0's raw shift and mask value (BASE0 not added). - INTERP1_ACCUM0_ADD: mmio.Mmio(packed struct(u32) { - INTERP1_ACCUM0_ADD: u24, - padding: u8, - }), - /// Values written here are atomically added to ACCUM1 - /// Reading yields lane 1's raw shift and mask value (BASE1 not added). - INTERP1_ACCUM1_ADD: mmio.Mmio(packed struct(u32) { - INTERP1_ACCUM1_ADD: u24, - padding: u8, - }), - /// On write, the lower 16 bits go to BASE0, upper bits to BASE1 simultaneously. - /// Each half is sign-extended to 32 bits if that lane's SIGNED flag is set. - INTERP1_BASE_1AND0: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK0: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK1: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK2: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK3: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK4: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK5: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK6: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK7: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK8: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK9: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK10: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK11: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK12: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK13: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK14: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK15: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK16: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK17: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK18: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK19: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK20: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK21: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK22: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK23: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK24: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK25: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK26: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK27: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK28: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK29: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK30: u32, - /// Reading from a spinlock address will: - /// - Return 0 if lock is already locked - /// - Otherwise return nonzero, and simultaneously claim the lock - /// Writing (any value) releases the lock. - /// If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. - /// The value returned on success is 0x1 << lock number. - SPINLOCK31: u32, - }; - - pub const SPI0 = extern struct { - /// Control register 0, SSPCR0 on page 3-4 - SSPCR0: mmio.Mmio(packed struct(u32) { - /// Data Size Select: 0000 Reserved, undefined operation. 0001 Reserved, undefined operation. 0010 Reserved, undefined operation. 0011 4-bit data. 0100 5-bit data. 0101 6-bit data. 0110 7-bit data. 0111 8-bit data. 1000 9-bit data. 1001 10-bit data. 1010 11-bit data. 1011 12-bit data. 1100 13-bit data. 1101 14-bit data. 1110 15-bit data. 1111 16-bit data. - DSS: u4, - /// Frame format: 00 Motorola SPI frame format. 01 TI synchronous serial frame format. 10 National Microwire frame format. 11 Reserved, undefined operation. - FRF: u2, - /// SSPCLKOUT polarity, applicable to Motorola SPI frame format only. See Motorola SPI frame format on page 2-10. - SPO: u1, - /// SSPCLKOUT phase, applicable to Motorola SPI frame format only. See Motorola SPI frame format on page 2-10. - SPH: u1, - /// Serial clock rate. The value SCR is used to generate the transmit and receive bit rate of the PrimeCell SSP. The bit rate is: F SSPCLK CPSDVSR x (1+SCR) where CPSDVSR is an even value from 2-254, programmed through the SSPCPSR register and SCR is a value from 0-255. - SCR: u8, - padding: u16, - }), - /// Control register 1, SSPCR1 on page 3-5 - SSPCR1: mmio.Mmio(packed struct(u32) { - /// Loop back mode: 0 Normal serial port operation enabled. 1 Output of transmit serial shifter is connected to input of receive serial shifter internally. - LBM: u1, - /// Synchronous serial port enable: 0 SSP operation disabled. 1 SSP operation enabled. - SSE: u1, - /// Master or slave mode select. This bit can be modified only when the PrimeCell SSP is disabled, SSE=0: 0 Device configured as master, default. 1 Device configured as slave. - MS: u1, - /// Slave-mode output disable. This bit is relevant only in the slave mode, MS=1. In multiple-slave systems, it is possible for an PrimeCell SSP master to broadcast a message to all slaves in the system while ensuring that only one slave drives data onto its serial output line. In such systems the RXD lines from multiple slaves could be tied together. To operate in such systems, the SOD bit can be set if the PrimeCell SSP slave is not supposed to drive the SSPTXD line: 0 SSP can drive the SSPTXD output in slave mode. 1 SSP must not drive the SSPTXD output in slave mode. - SOD: u1, - padding: u28, - }), - /// Data register, SSPDR on page 3-6 - SSPDR: mmio.Mmio(packed struct(u32) { - /// Transmit/Receive FIFO: Read Receive FIFO. Write Transmit FIFO. You must right-justify data when the PrimeCell SSP is programmed for a data size that is less than 16 bits. Unused bits at the top are ignored by transmit logic. The receive logic automatically right-justifies. - DATA: u16, - padding: u16, - }), - /// Status register, SSPSR on page 3-7 - SSPSR: mmio.Mmio(packed struct(u32) { - /// Transmit FIFO empty, RO: 0 Transmit FIFO is not empty. 1 Transmit FIFO is empty. - TFE: u1, - /// Transmit FIFO not full, RO: 0 Transmit FIFO is full. 1 Transmit FIFO is not full. - TNF: u1, - /// Receive FIFO not empty, RO: 0 Receive FIFO is empty. 1 Receive FIFO is not empty. - RNE: u1, - /// Receive FIFO full, RO: 0 Receive FIFO is not full. 1 Receive FIFO is full. - RFF: u1, - /// PrimeCell SSP busy flag, RO: 0 SSP is idle. 1 SSP is currently transmitting and/or receiving a frame or the transmit FIFO is not empty. - BSY: u1, - padding: u27, - }), - /// Clock prescale register, SSPCPSR on page 3-8 - SSPCPSR: mmio.Mmio(packed struct(u32) { - /// Clock prescale divisor. Must be an even number from 2-254, depending on the frequency of SSPCLK. The least significant bit always returns zero on reads. - CPSDVSR: u8, - padding: u24, - }), - /// Interrupt mask set or clear register, SSPIMSC on page 3-9 - SSPIMSC: mmio.Mmio(packed struct(u32) { - /// Receive overrun interrupt mask: 0 Receive FIFO written to while full condition interrupt is masked. 1 Receive FIFO written to while full condition interrupt is not masked. - RORIM: u1, - /// Receive timeout interrupt mask: 0 Receive FIFO not empty and no read prior to timeout period interrupt is masked. 1 Receive FIFO not empty and no read prior to timeout period interrupt is not masked. - RTIM: u1, - /// Receive FIFO interrupt mask: 0 Receive FIFO half full or less condition interrupt is masked. 1 Receive FIFO half full or less condition interrupt is not masked. - RXIM: u1, - /// Transmit FIFO interrupt mask: 0 Transmit FIFO half empty or less condition interrupt is masked. 1 Transmit FIFO half empty or less condition interrupt is not masked. - TXIM: u1, - padding: u28, - }), - /// Raw interrupt status register, SSPRIS on page 3-10 - SSPRIS: mmio.Mmio(packed struct(u32) { - /// Gives the raw interrupt state, prior to masking, of the SSPRORINTR interrupt - RORRIS: u1, - /// Gives the raw interrupt state, prior to masking, of the SSPRTINTR interrupt - RTRIS: u1, - /// Gives the raw interrupt state, prior to masking, of the SSPRXINTR interrupt - RXRIS: u1, - /// Gives the raw interrupt state, prior to masking, of the SSPTXINTR interrupt - TXRIS: u1, - padding: u28, - }), - /// Masked interrupt status register, SSPMIS on page 3-11 - SSPMIS: mmio.Mmio(packed struct(u32) { - /// Gives the receive over run masked interrupt status, after masking, of the SSPRORINTR interrupt - RORMIS: u1, - /// Gives the receive timeout masked interrupt state, after masking, of the SSPRTINTR interrupt - RTMIS: u1, - /// Gives the receive FIFO masked interrupt state, after masking, of the SSPRXINTR interrupt - RXMIS: u1, - /// Gives the transmit FIFO masked interrupt state, after masking, of the SSPTXINTR interrupt - TXMIS: u1, - padding: u28, - }), - /// Interrupt clear register, SSPICR on page 3-11 - SSPICR: mmio.Mmio(packed struct(u32) { - /// Clears the SSPRORINTR interrupt - RORIC: u1, - /// Clears the SSPRTINTR interrupt - RTIC: u1, - padding: u30, - }), - /// DMA control register, SSPDMACR on page 3-12 - SSPDMACR: mmio.Mmio(packed struct(u32) { - /// Receive DMA Enable. If this bit is set to 1, DMA for the receive FIFO is enabled. - RXDMAE: u1, - /// Transmit DMA Enable. If this bit is set to 1, DMA for the transmit FIFO is enabled. - TXDMAE: u1, - padding: u30, - }), - reserved4064: [4024]u8, - /// Peripheral identification registers, SSPPeriphID0-3 on page 3-13 - SSPPERIPHID0: mmio.Mmio(packed struct(u32) { - /// These bits read back as 0x22 - PARTNUMBER0: u8, - padding: u24, - }), - /// Peripheral identification registers, SSPPeriphID0-3 on page 3-13 - SSPPERIPHID1: mmio.Mmio(packed struct(u32) { - /// These bits read back as 0x0 - PARTNUMBER1: u4, - /// These bits read back as 0x1 - DESIGNER0: u4, - padding: u24, - }), - /// Peripheral identification registers, SSPPeriphID0-3 on page 3-13 - SSPPERIPHID2: mmio.Mmio(packed struct(u32) { - /// These bits read back as 0x4 - DESIGNER1: u4, - /// These bits return the peripheral revision - REVISION: u4, - padding: u24, - }), - /// Peripheral identification registers, SSPPeriphID0-3 on page 3-13 - SSPPERIPHID3: mmio.Mmio(packed struct(u32) { - /// These bits read back as 0x00 - CONFIGURATION: u8, - padding: u24, - }), - /// PrimeCell identification registers, SSPPCellID0-3 on page 3-16 - SSPPCELLID0: mmio.Mmio(packed struct(u32) { - /// These bits read back as 0x0D - SSPPCELLID0: u8, - padding: u24, - }), - /// PrimeCell identification registers, SSPPCellID0-3 on page 3-16 - SSPPCELLID1: mmio.Mmio(packed struct(u32) { - /// These bits read back as 0xF0 - SSPPCELLID1: u8, - padding: u24, - }), - /// PrimeCell identification registers, SSPPCellID0-3 on page 3-16 - SSPPCELLID2: mmio.Mmio(packed struct(u32) { - /// These bits read back as 0x05 - SSPPCELLID2: u8, - padding: u24, - }), - /// PrimeCell identification registers, SSPPCellID0-3 on page 3-16 - SSPPCELLID3: mmio.Mmio(packed struct(u32) { - /// These bits read back as 0xB1 - SSPPCELLID3: u8, - padding: u24, - }), - }; - - /// USB FS/LS controller device registers - pub const USBCTRL_REGS = extern struct { - /// Device address and endpoint control - ADDR_ENDP: mmio.Mmio(packed struct(u32) { - /// In device mode, the address that the device should respond to. Set in response to a SET_ADDR setup packet from the host. In host mode set to the address of the device to communicate with. - ADDRESS: u7, - reserved16: u9, - /// Device endpoint to send data to. Only valid for HOST mode. - ENDPOINT: u4, - padding: u12, - }), - /// Interrupt endpoint 1. Only valid for HOST mode. - ADDR_ENDP1: mmio.Mmio(packed struct(u32) { - /// Device address - ADDRESS: u7, - reserved16: u9, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved25: u5, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding: u5, - }), - /// Interrupt endpoint 2. Only valid for HOST mode. - ADDR_ENDP2: mmio.Mmio(packed struct(u32) { - /// Device address - ADDRESS: u7, - reserved16: u9, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved25: u5, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding: u5, - }), - /// Interrupt endpoint 3. Only valid for HOST mode. - ADDR_ENDP3: mmio.Mmio(packed struct(u32) { - /// Device address - ADDRESS: u7, - reserved16: u9, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved25: u5, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding: u5, - }), - /// Interrupt endpoint 4. Only valid for HOST mode. - ADDR_ENDP4: mmio.Mmio(packed struct(u32) { - /// Device address - ADDRESS: u7, - reserved16: u9, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved25: u5, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding: u5, - }), - /// Interrupt endpoint 5. Only valid for HOST mode. - ADDR_ENDP5: mmio.Mmio(packed struct(u32) { - /// Device address - ADDRESS: u7, - reserved16: u9, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved25: u5, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding: u5, - }), - /// Interrupt endpoint 6. Only valid for HOST mode. - ADDR_ENDP6: mmio.Mmio(packed struct(u32) { - /// Device address - ADDRESS: u7, - reserved16: u9, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved25: u5, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding: u5, - }), - /// Interrupt endpoint 7. Only valid for HOST mode. - ADDR_ENDP7: mmio.Mmio(packed struct(u32) { - /// Device address - ADDRESS: u7, - reserved16: u9, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved25: u5, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding: u5, - }), - /// Interrupt endpoint 8. Only valid for HOST mode. - ADDR_ENDP8: mmio.Mmio(packed struct(u32) { - /// Device address - ADDRESS: u7, - reserved16: u9, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved25: u5, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding: u5, - }), - /// Interrupt endpoint 9. Only valid for HOST mode. - ADDR_ENDP9: mmio.Mmio(packed struct(u32) { - /// Device address - ADDRESS: u7, - reserved16: u9, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved25: u5, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding: u5, - }), - /// Interrupt endpoint 10. Only valid for HOST mode. - ADDR_ENDP10: mmio.Mmio(packed struct(u32) { - /// Device address - ADDRESS: u7, - reserved16: u9, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved25: u5, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding: u5, - }), - /// Interrupt endpoint 11. Only valid for HOST mode. - ADDR_ENDP11: mmio.Mmio(packed struct(u32) { - /// Device address - ADDRESS: u7, - reserved16: u9, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved25: u5, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding: u5, - }), - /// Interrupt endpoint 12. Only valid for HOST mode. - ADDR_ENDP12: mmio.Mmio(packed struct(u32) { - /// Device address - ADDRESS: u7, - reserved16: u9, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved25: u5, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding: u5, - }), - /// Interrupt endpoint 13. Only valid for HOST mode. - ADDR_ENDP13: mmio.Mmio(packed struct(u32) { - /// Device address - ADDRESS: u7, - reserved16: u9, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved25: u5, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding: u5, - }), - /// Interrupt endpoint 14. Only valid for HOST mode. - ADDR_ENDP14: mmio.Mmio(packed struct(u32) { - /// Device address - ADDRESS: u7, - reserved16: u9, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved25: u5, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding: u5, - }), - /// Interrupt endpoint 15. Only valid for HOST mode. - ADDR_ENDP15: mmio.Mmio(packed struct(u32) { - /// Device address - ADDRESS: u7, - reserved16: u9, - /// Endpoint number of the interrupt endpoint - ENDPOINT: u4, - reserved25: u5, - /// Direction of the interrupt endpoint. In=0, Out=1 - INTEP_DIR: u1, - /// Interrupt EP requires preamble (is a low speed device on a full speed hub) - INTEP_PREAMBLE: u1, - padding: u5, - }), - /// Main control register - MAIN_CTRL: mmio.Mmio(packed struct(u32) { - /// Enable controller - CONTROLLER_EN: u1, - /// Device mode = 0, Host mode = 1 - HOST_NDEVICE: u1, - reserved31: u29, - /// Reduced timings for simulation - SIM_TIMING: u1, - }), - /// Set the SOF (Start of Frame) frame number in the host controller. The SOF packet is sent every 1ms and the host will increment the frame number by 1 each time. - SOF_WR: mmio.Mmio(packed struct(u32) { - COUNT: u11, - padding: u21, - }), - /// Read the last SOF (Start of Frame) frame number seen. In device mode the last SOF received from the host. In host mode the last SOF sent by the host. - SOF_RD: mmio.Mmio(packed struct(u32) { - COUNT: u11, - padding: u21, - }), - /// SIE control register - SIE_CTRL: mmio.Mmio(packed struct(u32) { - /// Host: Start transaction - START_TRANS: u1, - /// Host: Send Setup packet - SEND_SETUP: u1, - /// Host: Send transaction (OUT from host) - SEND_DATA: u1, - /// Host: Receive transaction (IN to host) - RECEIVE_DATA: u1, - /// Host: Stop transaction - STOP_TRANS: u1, - reserved6: u1, - /// Host: Preable enable for LS device on FS hub - PREAMBLE_EN: u1, - reserved8: u1, - /// Host: Delay packet(s) until after SOF - SOF_SYNC: u1, - /// Host: Enable SOF generation (for full speed bus) - SOF_EN: u1, - /// Host: Enable keep alive packet (for low speed bus) - KEEP_ALIVE_EN: u1, - /// Host: Enable VBUS - VBUS_EN: u1, - /// Device: Remote wakeup. Device can initiate its own resume after suspend. - RESUME: u1, - /// Host: Reset bus - RESET_BUS: u1, - reserved15: u1, - /// Host: Enable pull down resistors - PULLDOWN_EN: u1, - /// Device: Enable pull up resistor - PULLUP_EN: u1, - /// Device: Pull-up strength (0=1K2, 1=2k3) - RPU_OPT: u1, - /// Power down bus transceiver - TRANSCEIVER_PD: u1, - reserved24: u5, - /// Direct control of DM - DIRECT_DM: u1, - /// Direct control of DP - DIRECT_DP: u1, - /// Direct bus drive enable - DIRECT_EN: u1, - /// Device: Set bit in EP_STATUS_STALL_NAK when EP0 sends a NAK - EP0_INT_NAK: u1, - /// Device: Set bit in BUFF_STATUS for every 2 buffers completed on EP0 - EP0_INT_2BUF: u1, - /// Device: Set bit in BUFF_STATUS for every buffer completed on EP0 - EP0_INT_1BUF: u1, - /// Device: EP0 single buffered = 0, double buffered = 1 - EP0_DOUBLE_BUF: u1, - /// Device: Set bit in EP_STATUS_STALL_NAK when EP0 sends a STALL - EP0_INT_STALL: u1, - }), - /// SIE status register - SIE_STATUS: mmio.Mmio(packed struct(u32) { - /// Device: VBUS Detected - VBUS_DETECTED: u1, - reserved2: u1, - /// USB bus line state - LINE_STATE: u2, - /// Bus in suspended state. Valid for device and host. Host and device will go into suspend if neither Keep Alive / SOF frames are enabled. - SUSPENDED: u1, - reserved8: u3, - /// Host: device speed. Disconnected = 00, LS = 01, FS = 10 - SPEED: u2, - /// VBUS over current detected - VBUS_OVER_CURR: u1, - /// Host: Device has initiated a remote resume. Device: host has initiated a resume. - RESUME: u1, - reserved16: u4, - /// Device: connected - CONNECTED: u1, - /// Device: Setup packet received - SETUP_REC: u1, - /// Transaction complete. - /// Raised by device if: - /// * An IN or OUT packet is sent with the `LAST_BUFF` bit set in the buffer control register - /// Raised by host if: - /// * A setup packet is sent when no data in or data out transaction follows * An IN packet is received and the `LAST_BUFF` bit is set in the buffer control register * An IN packet is received with zero length * An OUT packet is sent and the `LAST_BUFF` bit is set - TRANS_COMPLETE: u1, - /// Device: bus reset received - BUS_RESET: u1, - reserved24: u4, - /// CRC Error. Raised by the Serial RX engine. - CRC_ERROR: u1, - /// Bit Stuff Error. Raised by the Serial RX engine. - BIT_STUFF_ERROR: u1, - /// RX overflow is raised by the Serial RX engine if the incoming data is too fast. - RX_OVERFLOW: u1, - /// RX timeout is raised by both the host and device if an ACK is not received in the maximum time specified by the USB spec. - RX_TIMEOUT: u1, - /// Host: NAK received - NAK_REC: u1, - /// Host: STALL received - STALL_REC: u1, - /// ACK received. Raised by both host and device. - ACK_REC: u1, - /// Data Sequence Error. - /// The device can raise a sequence error in the following conditions: - /// * A SETUP packet is received followed by a DATA1 packet (data phase should always be DATA0) * An OUT packet is received from the host but doesn't match the data pid in the buffer control register read from DPSRAM - /// The host can raise a data sequence error in the following conditions: - /// * An IN packet from the device has the wrong data PID - DATA_SEQ_ERROR: u1, - }), - /// interrupt endpoint control register - INT_EP_CTRL: mmio.Mmio(packed struct(u32) { - reserved1: u1, - /// Host: Enable interrupt endpoint 1 -> 15 - INT_EP_ACTIVE: u15, - padding: u16, - }), - /// Buffer status register. A bit set here indicates that a buffer has completed on the endpoint (if the buffer interrupt is enabled). It is possible for 2 buffers to be completed, so clearing the buffer status bit may instantly re set it on the next clock cycle. - BUFF_STATUS: mmio.Mmio(packed struct(u32) { - EP0_IN: u1, - EP0_OUT: u1, - EP1_IN: u1, - EP1_OUT: u1, - EP2_IN: u1, - EP2_OUT: u1, - EP3_IN: u1, - EP3_OUT: u1, - EP4_IN: u1, - EP4_OUT: u1, - EP5_IN: u1, - EP5_OUT: u1, - EP6_IN: u1, - EP6_OUT: u1, - EP7_IN: u1, - EP7_OUT: u1, - EP8_IN: u1, - EP8_OUT: u1, - EP9_IN: u1, - EP9_OUT: u1, - EP10_IN: u1, - EP10_OUT: u1, - EP11_IN: u1, - EP11_OUT: u1, - EP12_IN: u1, - EP12_OUT: u1, - EP13_IN: u1, - EP13_OUT: u1, - EP14_IN: u1, - EP14_OUT: u1, - EP15_IN: u1, - EP15_OUT: u1, - }), - /// Which of the double buffers should be handled. Only valid if using an interrupt per buffer (i.e. not per 2 buffers). Not valid for host interrupt endpoint polling because they are only single buffered. - BUFF_CPU_SHOULD_HANDLE: mmio.Mmio(packed struct(u32) { - EP0_IN: u1, - EP0_OUT: u1, - EP1_IN: u1, - EP1_OUT: u1, - EP2_IN: u1, - EP2_OUT: u1, - EP3_IN: u1, - EP3_OUT: u1, - EP4_IN: u1, - EP4_OUT: u1, - EP5_IN: u1, - EP5_OUT: u1, - EP6_IN: u1, - EP6_OUT: u1, - EP7_IN: u1, - EP7_OUT: u1, - EP8_IN: u1, - EP8_OUT: u1, - EP9_IN: u1, - EP9_OUT: u1, - EP10_IN: u1, - EP10_OUT: u1, - EP11_IN: u1, - EP11_OUT: u1, - EP12_IN: u1, - EP12_OUT: u1, - EP13_IN: u1, - EP13_OUT: u1, - EP14_IN: u1, - EP14_OUT: u1, - EP15_IN: u1, - EP15_OUT: u1, - }), - /// Device only: Can be set to ignore the buffer control register for this endpoint in case you would like to revoke a buffer. A NAK will be sent for every access to the endpoint until this bit is cleared. A corresponding bit in `EP_ABORT_DONE` is set when it is safe to modify the buffer control register. - EP_ABORT: mmio.Mmio(packed struct(u32) { - EP0_IN: u1, - EP0_OUT: u1, - EP1_IN: u1, - EP1_OUT: u1, - EP2_IN: u1, - EP2_OUT: u1, - EP3_IN: u1, - EP3_OUT: u1, - EP4_IN: u1, - EP4_OUT: u1, - EP5_IN: u1, - EP5_OUT: u1, - EP6_IN: u1, - EP6_OUT: u1, - EP7_IN: u1, - EP7_OUT: u1, - EP8_IN: u1, - EP8_OUT: u1, - EP9_IN: u1, - EP9_OUT: u1, - EP10_IN: u1, - EP10_OUT: u1, - EP11_IN: u1, - EP11_OUT: u1, - EP12_IN: u1, - EP12_OUT: u1, - EP13_IN: u1, - EP13_OUT: u1, - EP14_IN: u1, - EP14_OUT: u1, - EP15_IN: u1, - EP15_OUT: u1, - }), - /// Device only: Used in conjunction with `EP_ABORT`. Set once an endpoint is idle so the programmer knows it is safe to modify the buffer control register. - EP_ABORT_DONE: mmio.Mmio(packed struct(u32) { - EP0_IN: u1, - EP0_OUT: u1, - EP1_IN: u1, - EP1_OUT: u1, - EP2_IN: u1, - EP2_OUT: u1, - EP3_IN: u1, - EP3_OUT: u1, - EP4_IN: u1, - EP4_OUT: u1, - EP5_IN: u1, - EP5_OUT: u1, - EP6_IN: u1, - EP6_OUT: u1, - EP7_IN: u1, - EP7_OUT: u1, - EP8_IN: u1, - EP8_OUT: u1, - EP9_IN: u1, - EP9_OUT: u1, - EP10_IN: u1, - EP10_OUT: u1, - EP11_IN: u1, - EP11_OUT: u1, - EP12_IN: u1, - EP12_OUT: u1, - EP13_IN: u1, - EP13_OUT: u1, - EP14_IN: u1, - EP14_OUT: u1, - EP15_IN: u1, - EP15_OUT: u1, - }), - /// Device: this bit must be set in conjunction with the `STALL` bit in the buffer control register to send a STALL on EP0. The device controller clears these bits when a SETUP packet is received because the USB spec requires that a STALL condition is cleared when a SETUP packet is received. - EP_STALL_ARM: mmio.Mmio(packed struct(u32) { - EP0_IN: u1, - EP0_OUT: u1, - padding: u30, - }), - /// Used by the host controller. Sets the wait time in microseconds before trying again if the device replies with a NAK. - NAK_POLL: mmio.Mmio(packed struct(u32) { - /// NAK polling interval for a low speed device - DELAY_LS: u10, - reserved16: u6, - /// NAK polling interval for a full speed device - DELAY_FS: u10, - padding: u6, - }), - /// Device: bits are set when the `IRQ_ON_NAK` or `IRQ_ON_STALL` bits are set. For EP0 this comes from `SIE_CTRL`. For all other endpoints it comes from the endpoint control register. - EP_STATUS_STALL_NAK: mmio.Mmio(packed struct(u32) { - EP0_IN: u1, - EP0_OUT: u1, - EP1_IN: u1, - EP1_OUT: u1, - EP2_IN: u1, - EP2_OUT: u1, - EP3_IN: u1, - EP3_OUT: u1, - EP4_IN: u1, - EP4_OUT: u1, - EP5_IN: u1, - EP5_OUT: u1, - EP6_IN: u1, - EP6_OUT: u1, - EP7_IN: u1, - EP7_OUT: u1, - EP8_IN: u1, - EP8_OUT: u1, - EP9_IN: u1, - EP9_OUT: u1, - EP10_IN: u1, - EP10_OUT: u1, - EP11_IN: u1, - EP11_OUT: u1, - EP12_IN: u1, - EP12_OUT: u1, - EP13_IN: u1, - EP13_OUT: u1, - EP14_IN: u1, - EP14_OUT: u1, - EP15_IN: u1, - EP15_OUT: u1, - }), - /// Where to connect the USB controller. Should be to_phy by default. - USB_MUXING: mmio.Mmio(packed struct(u32) { - TO_PHY: u1, - TO_EXTPHY: u1, - TO_DIGITAL_PAD: u1, - SOFTCON: u1, - padding: u28, - }), - /// Overrides for the power signals in the event that the VBUS signals are not hooked up to GPIO. Set the value of the override and then the override enable to switch over to the override value. - USB_PWR: mmio.Mmio(packed struct(u32) { - VBUS_EN: u1, - VBUS_EN_OVERRIDE_EN: u1, - VBUS_DETECT: u1, - VBUS_DETECT_OVERRIDE_EN: u1, - OVERCURR_DETECT: u1, - OVERCURR_DETECT_EN: u1, - padding: u26, - }), - /// This register allows for direct control of the USB phy. Use in conjunction with usbphy_direct_override register to enable each override bit. - USBPHY_DIRECT: mmio.Mmio(packed struct(u32) { - /// Enable the second DP pull up resistor. 0 - Pull = Rpu2; 1 - Pull = Rpu1 + Rpu2 - DP_PULLUP_HISEL: u1, - /// DP pull up enable - DP_PULLUP_EN: u1, - /// DP pull down enable - DP_PULLDN_EN: u1, - reserved4: u1, - /// Enable the second DM pull up resistor. 0 - Pull = Rpu2; 1 - Pull = Rpu1 + Rpu2 - DM_PULLUP_HISEL: u1, - /// DM pull up enable - DM_PULLUP_EN: u1, - /// DM pull down enable - DM_PULLDN_EN: u1, - reserved8: u1, - /// Output enable. If TX_DIFFMODE=1, OE for DPP/DPM diff pair. 0 - DPP/DPM in Hi-Z state; 1 - DPP/DPM driving - /// If TX_DIFFMODE=0, OE for DPP only. 0 - DPP in Hi-Z state; 1 - DPP driving - TX_DP_OE: u1, - /// Output enable. If TX_DIFFMODE=1, Ignored. - /// If TX_DIFFMODE=0, OE for DPM only. 0 - DPM in Hi-Z state; 1 - DPM driving - TX_DM_OE: u1, - /// Output data. If TX_DIFFMODE=1, Drives DPP/DPM diff pair. TX_DP_OE=1 to enable drive. DPP=TX_DP, DPM=~TX_DP - /// If TX_DIFFMODE=0, Drives DPP only. TX_DP_OE=1 to enable drive. DPP=TX_DP - TX_DP: u1, - /// Output data. TX_DIFFMODE=1, Ignored - /// TX_DIFFMODE=0, Drives DPM only. TX_DM_OE=1 to enable drive. DPM=TX_DM - TX_DM: u1, - /// RX power down override (if override enable is set). 1 = powered down. - RX_PD: u1, - /// TX power down override (if override enable is set). 1 = powered down. - TX_PD: u1, - /// TX_FSSLEW=0: Low speed slew rate - /// TX_FSSLEW=1: Full speed slew rate - TX_FSSLEW: u1, - /// TX_DIFFMODE=0: Single ended mode - /// TX_DIFFMODE=1: Differential drive mode (TX_DM, TX_DM_OE ignored) - TX_DIFFMODE: u1, - /// Differential RX - RX_DD: u1, - /// DPP pin state - RX_DP: u1, - /// DPM pin state - RX_DM: u1, - /// DP overcurrent - DP_OVCN: u1, - /// DM overcurrent - DM_OVCN: u1, - /// DP over voltage - DP_OVV: u1, - /// DM over voltage - DM_OVV: u1, - padding: u9, - }), - /// Override enable for each control in usbphy_direct - USBPHY_DIRECT_OVERRIDE: mmio.Mmio(packed struct(u32) { - DP_PULLUP_HISEL_OVERRIDE_EN: u1, - DM_PULLUP_HISEL_OVERRIDE_EN: u1, - DP_PULLUP_EN_OVERRIDE_EN: u1, - DP_PULLDN_EN_OVERRIDE_EN: u1, - DM_PULLDN_EN_OVERRIDE_EN: u1, - TX_DP_OE_OVERRIDE_EN: u1, - TX_DM_OE_OVERRIDE_EN: u1, - TX_DP_OVERRIDE_EN: u1, - TX_DM_OVERRIDE_EN: u1, - RX_PD_OVERRIDE_EN: u1, - TX_PD_OVERRIDE_EN: u1, - TX_FSSLEW_OVERRIDE_EN: u1, - DM_PULLUP_OVERRIDE_EN: u1, - reserved15: u2, - TX_DIFFMODE_OVERRIDE_EN: u1, - padding: u16, - }), - /// Used to adjust trim values of USB phy pull down resistors. - USBPHY_TRIM: mmio.Mmio(packed struct(u32) { - /// Value to drive to USB PHY - /// DP pulldown resistor trim control - /// Experimental data suggests that the reset value will work, but this register allows adjustment if required - DP_PULLDN_TRIM: u5, - reserved8: u3, - /// Value to drive to USB PHY - /// DM pulldown resistor trim control - /// Experimental data suggests that the reset value will work, but this register allows adjustment if required - DM_PULLDN_TRIM: u5, - padding: u19, - }), - reserved140: [4]u8, - /// Raw Interrupts - INTR: mmio.Mmio(packed struct(u32) { - /// Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED - HOST_CONN_DIS: u1, - /// Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME - HOST_RESUME: u1, - /// Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD - HOST_SOF: u1, - /// Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit. - TRANS_COMPLETE: u1, - /// Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS. - BUFF_STATUS: u1, - /// Source: SIE_STATUS.DATA_SEQ_ERROR - ERROR_DATA_SEQ: u1, - /// Source: SIE_STATUS.RX_TIMEOUT - ERROR_RX_TIMEOUT: u1, - /// Source: SIE_STATUS.RX_OVERFLOW - ERROR_RX_OVERFLOW: u1, - /// Source: SIE_STATUS.BIT_STUFF_ERROR - ERROR_BIT_STUFF: u1, - /// Source: SIE_STATUS.CRC_ERROR - ERROR_CRC: u1, - /// Source: SIE_STATUS.STALL_REC - STALL: u1, - /// Source: SIE_STATUS.VBUS_DETECTED - VBUS_DETECT: u1, - /// Source: SIE_STATUS.BUS_RESET - BUS_RESET: u1, - /// Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED - DEV_CONN_DIS: u1, - /// Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED - DEV_SUSPEND: u1, - /// Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME - DEV_RESUME_FROM_HOST: u1, - /// Device. Source: SIE_STATUS.SETUP_REC - SETUP_REQ: u1, - /// Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD - DEV_SOF: u1, - /// Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. - ABORT_DONE: u1, - /// Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. - EP_STALL_NAK: u1, - padding: u12, - }), - /// Interrupt Enable - INTE: mmio.Mmio(packed struct(u32) { - /// Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED - HOST_CONN_DIS: u1, - /// Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME - HOST_RESUME: u1, - /// Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD - HOST_SOF: u1, - /// Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit. - TRANS_COMPLETE: u1, - /// Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS. - BUFF_STATUS: u1, - /// Source: SIE_STATUS.DATA_SEQ_ERROR - ERROR_DATA_SEQ: u1, - /// Source: SIE_STATUS.RX_TIMEOUT - ERROR_RX_TIMEOUT: u1, - /// Source: SIE_STATUS.RX_OVERFLOW - ERROR_RX_OVERFLOW: u1, - /// Source: SIE_STATUS.BIT_STUFF_ERROR - ERROR_BIT_STUFF: u1, - /// Source: SIE_STATUS.CRC_ERROR - ERROR_CRC: u1, - /// Source: SIE_STATUS.STALL_REC - STALL: u1, - /// Source: SIE_STATUS.VBUS_DETECTED - VBUS_DETECT: u1, - /// Source: SIE_STATUS.BUS_RESET - BUS_RESET: u1, - /// Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED - DEV_CONN_DIS: u1, - /// Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED - DEV_SUSPEND: u1, - /// Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME - DEV_RESUME_FROM_HOST: u1, - /// Device. Source: SIE_STATUS.SETUP_REC - SETUP_REQ: u1, - /// Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD - DEV_SOF: u1, - /// Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. - ABORT_DONE: u1, - /// Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. - EP_STALL_NAK: u1, - padding: u12, - }), - /// Interrupt Force - INTF: mmio.Mmio(packed struct(u32) { - /// Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED - HOST_CONN_DIS: u1, - /// Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME - HOST_RESUME: u1, - /// Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD - HOST_SOF: u1, - /// Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit. - TRANS_COMPLETE: u1, - /// Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS. - BUFF_STATUS: u1, - /// Source: SIE_STATUS.DATA_SEQ_ERROR - ERROR_DATA_SEQ: u1, - /// Source: SIE_STATUS.RX_TIMEOUT - ERROR_RX_TIMEOUT: u1, - /// Source: SIE_STATUS.RX_OVERFLOW - ERROR_RX_OVERFLOW: u1, - /// Source: SIE_STATUS.BIT_STUFF_ERROR - ERROR_BIT_STUFF: u1, - /// Source: SIE_STATUS.CRC_ERROR - ERROR_CRC: u1, - /// Source: SIE_STATUS.STALL_REC - STALL: u1, - /// Source: SIE_STATUS.VBUS_DETECTED - VBUS_DETECT: u1, - /// Source: SIE_STATUS.BUS_RESET - BUS_RESET: u1, - /// Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED - DEV_CONN_DIS: u1, - /// Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED - DEV_SUSPEND: u1, - /// Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME - DEV_RESUME_FROM_HOST: u1, - /// Device. Source: SIE_STATUS.SETUP_REC - SETUP_REQ: u1, - /// Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD - DEV_SOF: u1, - /// Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. - ABORT_DONE: u1, - /// Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. - EP_STALL_NAK: u1, - padding: u12, - }), - /// Interrupt status after masking & forcing - INTS: mmio.Mmio(packed struct(u32) { - /// Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED - HOST_CONN_DIS: u1, - /// Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME - HOST_RESUME: u1, - /// Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD - HOST_SOF: u1, - /// Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit. - TRANS_COMPLETE: u1, - /// Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS. - BUFF_STATUS: u1, - /// Source: SIE_STATUS.DATA_SEQ_ERROR - ERROR_DATA_SEQ: u1, - /// Source: SIE_STATUS.RX_TIMEOUT - ERROR_RX_TIMEOUT: u1, - /// Source: SIE_STATUS.RX_OVERFLOW - ERROR_RX_OVERFLOW: u1, - /// Source: SIE_STATUS.BIT_STUFF_ERROR - ERROR_BIT_STUFF: u1, - /// Source: SIE_STATUS.CRC_ERROR - ERROR_CRC: u1, - /// Source: SIE_STATUS.STALL_REC - STALL: u1, - /// Source: SIE_STATUS.VBUS_DETECTED - VBUS_DETECT: u1, - /// Source: SIE_STATUS.BUS_RESET - BUS_RESET: u1, - /// Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED - DEV_CONN_DIS: u1, - /// Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED - DEV_SUSPEND: u1, - /// Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME - DEV_RESUME_FROM_HOST: u1, - /// Device. Source: SIE_STATUS.SETUP_REC - SETUP_REQ: u1, - /// Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD - DEV_SOF: u1, - /// Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. - ABORT_DONE: u1, - /// Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. - EP_STALL_NAK: u1, - padding: u12, - }), - }; - - /// DW_apb_i2c address block - /// List of configuration constants for the Synopsys I2C hardware (you may see references to these in I2C register header; these are *fixed* values, set at hardware design time): - /// IC_ULTRA_FAST_MODE ................ 0x0 - /// IC_UFM_TBUF_CNT_DEFAULT ........... 0x8 - /// IC_UFM_SCL_LOW_COUNT .............. 0x0008 - /// IC_UFM_SCL_HIGH_COUNT ............. 0x0006 - /// IC_TX_TL .......................... 0x0 - /// IC_TX_CMD_BLOCK ................... 0x1 - /// IC_HAS_DMA ........................ 0x1 - /// IC_HAS_ASYNC_FIFO ................. 0x0 - /// IC_SMBUS_ARP ...................... 0x0 - /// IC_FIRST_DATA_BYTE_STATUS ......... 0x1 - /// IC_INTR_IO ........................ 0x1 - /// IC_MASTER_MODE .................... 0x1 - /// IC_DEFAULT_ACK_GENERAL_CALL ....... 0x1 - /// IC_INTR_POL ....................... 0x1 - /// IC_OPTIONAL_SAR ................... 0x0 - /// IC_DEFAULT_TAR_SLAVE_ADDR ......... 0x055 - /// IC_DEFAULT_SLAVE_ADDR ............. 0x055 - /// IC_DEFAULT_HS_SPKLEN .............. 0x1 - /// IC_FS_SCL_HIGH_COUNT .............. 0x0006 - /// IC_HS_SCL_LOW_COUNT ............... 0x0008 - /// IC_DEVICE_ID_VALUE ................ 0x0 - /// IC_10BITADDR_MASTER ............... 0x0 - /// IC_CLK_FREQ_OPTIMIZATION .......... 0x0 - /// IC_DEFAULT_FS_SPKLEN .............. 0x7 - /// IC_ADD_ENCODED_PARAMS ............. 0x0 - /// IC_DEFAULT_SDA_HOLD ............... 0x000001 - /// IC_DEFAULT_SDA_SETUP .............. 0x64 - /// IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT . 0x0 - /// IC_CLOCK_PERIOD ................... 100 - /// IC_EMPTYFIFO_HOLD_MASTER_EN ....... 1 - /// IC_RESTART_EN ..................... 0x1 - /// IC_TX_CMD_BLOCK_DEFAULT ........... 0x0 - /// IC_BUS_CLEAR_FEATURE .............. 0x0 - /// IC_CAP_LOADING .................... 100 - /// IC_FS_SCL_LOW_COUNT ............... 0x000d - /// APB_DATA_WIDTH .................... 32 - /// IC_SDA_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff - /// IC_SLV_DATA_NACK_ONLY ............. 0x1 - /// IC_10BITADDR_SLAVE ................ 0x0 - /// IC_CLK_TYPE ....................... 0x0 - /// IC_SMBUS_UDID_MSB ................. 0x0 - /// IC_SMBUS_SUSPEND_ALERT ............ 0x0 - /// IC_HS_SCL_HIGH_COUNT .............. 0x0006 - /// IC_SLV_RESTART_DET_EN ............. 0x1 - /// IC_SMBUS .......................... 0x0 - /// IC_OPTIONAL_SAR_DEFAULT ........... 0x0 - /// IC_PERSISTANT_SLV_ADDR_DEFAULT .... 0x0 - /// IC_USE_COUNTS ..................... 0x0 - /// IC_RX_BUFFER_DEPTH ................ 16 - /// IC_SCL_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff - /// IC_RX_FULL_HLD_BUS_EN ............. 0x1 - /// IC_SLAVE_DISABLE .................. 0x1 - /// IC_RX_TL .......................... 0x0 - /// IC_DEVICE_ID ...................... 0x0 - /// IC_HC_COUNT_VALUES ................ 0x0 - /// I2C_DYNAMIC_TAR_UPDATE ............ 0 - /// IC_SMBUS_CLK_LOW_MEXT_DEFAULT ..... 0xffffffff - /// IC_SMBUS_CLK_LOW_SEXT_DEFAULT ..... 0xffffffff - /// IC_HS_MASTER_CODE ................. 0x1 - /// IC_SMBUS_RST_IDLE_CNT_DEFAULT ..... 0xffff - /// IC_SMBUS_UDID_LSB_DEFAULT ......... 0xffffffff - /// IC_SS_SCL_HIGH_COUNT .............. 0x0028 - /// IC_SS_SCL_LOW_COUNT ............... 0x002f - /// IC_MAX_SPEED_MODE ................. 0x2 - /// IC_STAT_FOR_CLK_STRETCH ........... 0x0 - /// IC_STOP_DET_IF_MASTER_ACTIVE ...... 0x0 - /// IC_DEFAULT_UFM_SPKLEN ............. 0x1 - /// IC_TX_BUFFER_DEPTH ................ 16 - pub const I2C0 = extern struct { - /// I2C Control Register. This register can be written only when the DW_apb_i2c is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. - /// Read/Write Access: - bit 10 is read only. - bit 11 is read only - bit 16 is read only - bit 17 is read only - bits 18 and 19 are read only. - IC_CON: mmio.Mmio(packed struct(u32) { - /// This bit controls whether the DW_apb_i2c master is enabled. - /// NOTE: Software should ensure that if this bit is written with '1' then bit 6 should also be written with a '1'. - MASTER_MODE: packed union { - raw: u1, - value: enum(u1) { - /// Master mode is disabled - DISABLED = 0x0, - /// Master mode is enabled - ENABLED = 0x1, - }, - }, - /// These bits control at which speed the DW_apb_i2c operates; its setting is relevant only if one is operating the DW_apb_i2c in master mode. Hardware protects against illegal values being programmed by software. These bits must be programmed appropriately for slave mode also, as it is used to capture correct value of spike filter as per the speed mode. - /// This register should be programmed only with a value in the range of 1 to IC_MAX_SPEED_MODE; otherwise, hardware updates this register with the value of IC_MAX_SPEED_MODE. - /// 1: standard mode (100 kbit/s) - /// 2: fast mode (<=400 kbit/s) or fast mode plus (<=1000Kbit/s) - /// 3: high speed mode (3.4 Mbit/s) - /// Note: This field is not applicable when IC_ULTRA_FAST_MODE=1 - SPEED: packed union { - raw: u2, - value: enum(u2) { - /// Standard Speed mode of operation - STANDARD = 0x1, - /// Fast or Fast Plus mode of operation - FAST = 0x2, - /// High Speed mode of operation - HIGH = 0x3, - _, - }, - }, - /// When acting as a slave, this bit controls whether the DW_apb_i2c responds to 7- or 10-bit addresses. - 0: 7-bit addressing. The DW_apb_i2c ignores transactions that involve 10-bit addressing; for 7-bit addressing, only the lower 7 bits of the IC_SAR register are compared. - 1: 10-bit addressing. The DW_apb_i2c responds to only 10-bit addressing transfers that match the full 10 bits of the IC_SAR register. - IC_10BITADDR_SLAVE: packed union { - raw: u1, - value: enum(u1) { - /// Slave 7Bit addressing - ADDR_7BITS = 0x0, - /// Slave 10Bit addressing - ADDR_10BITS = 0x1, - }, - }, - /// Controls whether the DW_apb_i2c starts its transfers in 7- or 10-bit addressing mode when acting as a master. - 0: 7-bit addressing - 1: 10-bit addressing - IC_10BITADDR_MASTER: packed union { - raw: u1, - value: enum(u1) { - /// Master 7Bit addressing mode - ADDR_7BITS = 0x0, - /// Master 10Bit addressing mode - ADDR_10BITS = 0x1, - }, - }, - /// Determines whether RESTART conditions may be sent when acting as a master. Some older slaves do not support handling RESTART conditions; however, RESTART conditions are used in several DW_apb_i2c operations. When RESTART is disabled, the master is prohibited from performing the following functions: - Sending a START BYTE - Performing any high-speed mode operation - High-speed mode operation - Performing direction changes in combined format mode - Performing a read operation with a 10-bit address By replacing RESTART condition followed by a STOP and a subsequent START condition, split operations are broken down into multiple DW_apb_i2c transfers. If the above operations are performed, it will result in setting bit 6 (TX_ABRT) of the IC_RAW_INTR_STAT register. - /// Reset value: ENABLED - IC_RESTART_EN: packed union { - raw: u1, - value: enum(u1) { - /// Master restart disabled - DISABLED = 0x0, - /// Master restart enabled - ENABLED = 0x1, - }, - }, - /// This bit controls whether I2C has its slave disabled, which means once the presetn signal is applied, then this bit is set and the slave is disabled. - /// If this bit is set (slave is disabled), DW_apb_i2c functions only as a master and does not perform any action that requires a slave. - /// NOTE: Software should ensure that if this bit is written with 0, then bit 0 should also be written with a 0. - IC_SLAVE_DISABLE: packed union { - raw: u1, - value: enum(u1) { - /// Slave mode is enabled - SLAVE_ENABLED = 0x0, - /// Slave mode is disabled - SLAVE_DISABLED = 0x1, - }, - }, - /// In slave mode: - 1'b1: issues the STOP_DET interrupt only when it is addressed. - 1'b0: issues the STOP_DET irrespective of whether it's addressed or not. Reset value: 0x0 - /// NOTE: During a general call address, this slave does not issue the STOP_DET interrupt if STOP_DET_IF_ADDRESSED = 1'b1, even if the slave responds to the general call address by generating ACK. The STOP_DET interrupt is generated only when the transmitted address matches the slave address (SAR). - STOP_DET_IFADDRESSED: packed union { - raw: u1, - value: enum(u1) { - /// slave issues STOP_DET intr always - DISABLED = 0x0, - /// slave issues STOP_DET intr only if addressed - ENABLED = 0x1, - }, - }, - /// This bit controls the generation of the TX_EMPTY interrupt, as described in the IC_RAW_INTR_STAT register. - /// Reset value: 0x0. - TX_EMPTY_CTRL: packed union { - raw: u1, - value: enum(u1) { - /// Default behaviour of TX_EMPTY interrupt - DISABLED = 0x0, - /// Controlled generation of TX_EMPTY interrupt - ENABLED = 0x1, - }, - }, - /// This bit controls whether DW_apb_i2c should hold the bus when the Rx FIFO is physically full to its RX_BUFFER_DEPTH, as described in the IC_RX_FULL_HLD_BUS_EN parameter. - /// Reset value: 0x0. - RX_FIFO_FULL_HLD_CTRL: packed union { - raw: u1, - value: enum(u1) { - /// Overflow when RX_FIFO is full - DISABLED = 0x0, - /// Hold bus when RX_FIFO is full - ENABLED = 0x1, - }, - }, - /// Master issues the STOP_DET interrupt irrespective of whether master is active or not - STOP_DET_IF_MASTER_ACTIVE: u1, - padding: u21, - }), - /// I2C Target Address Register - /// This register is 12 bits wide, and bits 31:12 are reserved. This register can be written to only when IC_ENABLE[0] is set to 0. - /// Note: If the software or application is aware that the DW_apb_i2c is not using the TAR address for the pending commands in the Tx FIFO, then it is possible to update the TAR address even while the Tx FIFO has entries (IC_STATUS[2]= 0). - It is not necessary to perform any write to this register if DW_apb_i2c is enabled as an I2C slave only. - IC_TAR: mmio.Mmio(packed struct(u32) { - /// This is the target address for any master transaction. When transmitting a General Call, these bits are ignored. To generate a START BYTE, the CPU needs to write only once into these bits. - /// If the IC_TAR and IC_SAR are the same, loopback exists but the FIFOs are shared between master and slave, so full loopback is not feasible. Only one direction loopback mode is supported (simplex), not duplex. A master cannot transmit to itself; it can transmit to only a slave. - IC_TAR: u10, - /// If bit 11 (SPECIAL) is set to 1 and bit 13(Device-ID) is set to 0, then this bit indicates whether a General Call or START byte command is to be performed by the DW_apb_i2c. - 0: General Call Address - after issuing a General Call, only writes may be performed. Attempting to issue a read command results in setting bit 6 (TX_ABRT) of the IC_RAW_INTR_STAT register. The DW_apb_i2c remains in General Call mode until the SPECIAL bit value (bit 11) is cleared. - 1: START BYTE Reset value: 0x0 - GC_OR_START: packed union { - raw: u1, - value: enum(u1) { - /// GENERAL_CALL byte transmission - GENERAL_CALL = 0x0, - /// START byte transmission - START_BYTE = 0x1, - }, - }, - /// This bit indicates whether software performs a Device-ID or General Call or START BYTE command. - 0: ignore bit 10 GC_OR_START and use IC_TAR normally - 1: perform special I2C command as specified in Device_ID or GC_OR_START bit Reset value: 0x0 - SPECIAL: packed union { - raw: u1, - value: enum(u1) { - /// Disables programming of GENERAL_CALL or START_BYTE transmission - DISABLED = 0x0, - /// Enables programming of GENERAL_CALL or START_BYTE transmission - ENABLED = 0x1, - }, - }, - padding: u20, - }), - /// I2C Slave Address Register - IC_SAR: mmio.Mmio(packed struct(u32) { - /// The IC_SAR holds the slave address when the I2C is operating as a slave. For 7-bit addressing, only IC_SAR[6:0] is used. - /// This register can be written only when the I2C interface is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. - /// Note: The default values cannot be any of the reserved address locations: that is, 0x00 to 0x07, or 0x78 to 0x7f. The correct operation of the device is not guaranteed if you program the IC_SAR or IC_TAR to a reserved value. Refer to <> for a complete list of these reserved values. - IC_SAR: u10, - padding: u22, - }), - reserved16: [4]u8, - /// I2C Rx/Tx Data Buffer and Command Register; this is the register the CPU writes to when filling the TX FIFO and the CPU reads from when retrieving bytes from RX FIFO. - /// The size of the register changes as follows: - /// Write: - 11 bits when IC_EMPTYFIFO_HOLD_MASTER_EN=1 - 9 bits when IC_EMPTYFIFO_HOLD_MASTER_EN=0 Read: - 12 bits when IC_FIRST_DATA_BYTE_STATUS = 1 - 8 bits when IC_FIRST_DATA_BYTE_STATUS = 0 Note: In order for the DW_apb_i2c to continue acknowledging reads, a read command should be written for every byte that is to be received; otherwise the DW_apb_i2c will stop acknowledging. - IC_DATA_CMD: mmio.Mmio(packed struct(u32) { - /// This register contains the data to be transmitted or received on the I2C bus. If you are writing to this register and want to perform a read, bits 7:0 (DAT) are ignored by the DW_apb_i2c. However, when you read this register, these bits return the value of data received on the DW_apb_i2c interface. - /// Reset value: 0x0 - DAT: u8, - /// This bit controls whether a read or a write is performed. This bit does not control the direction when the DW_apb_i2con acts as a slave. It controls only the direction when it acts as a master. - /// When a command is entered in the TX FIFO, this bit distinguishes the write and read commands. In slave-receiver mode, this bit is a 'don't care' because writes to this register are not required. In slave-transmitter mode, a '0' indicates that the data in IC_DATA_CMD is to be transmitted. - /// When programming this bit, you should remember the following: attempting to perform a read operation after a General Call command has been sent results in a TX_ABRT interrupt (bit 6 of the IC_RAW_INTR_STAT register), unless bit 11 (SPECIAL) in the IC_TAR register has been cleared. If a '1' is written to this bit after receiving a RD_REQ interrupt, then a TX_ABRT interrupt occurs. - /// Reset value: 0x0 - CMD: packed union { - raw: u1, - value: enum(u1) { - /// Master Write Command - WRITE = 0x0, - /// Master Read Command - READ = 0x1, - }, - }, - /// This bit controls whether a STOP is issued after the byte is sent or received. - /// - 1 - STOP is issued after this byte, regardless of whether or not the Tx FIFO is empty. If the Tx FIFO is not empty, the master immediately tries to start a new transfer by issuing a START and arbitrating for the bus. - 0 - STOP is not issued after this byte, regardless of whether or not the Tx FIFO is empty. If the Tx FIFO is not empty, the master continues the current transfer by sending/receiving data bytes according to the value of the CMD bit. If the Tx FIFO is empty, the master holds the SCL line low and stalls the bus until a new command is available in the Tx FIFO. Reset value: 0x0 - STOP: packed union { - raw: u1, - value: enum(u1) { - /// Don't Issue STOP after this command - DISABLE = 0x0, - /// Issue STOP after this command - ENABLE = 0x1, - }, - }, - /// This bit controls whether a RESTART is issued before the byte is sent or received. - /// 1 - If IC_RESTART_EN is 1, a RESTART is issued before the data is sent/received (according to the value of CMD), regardless of whether or not the transfer direction is changing from the previous command; if IC_RESTART_EN is 0, a STOP followed by a START is issued instead. - /// 0 - If IC_RESTART_EN is 1, a RESTART is issued only if the transfer direction is changing from the previous command; if IC_RESTART_EN is 0, a STOP followed by a START is issued instead. - /// Reset value: 0x0 - RESTART: packed union { - raw: u1, - value: enum(u1) { - /// Don't Issue RESTART before this command - DISABLE = 0x0, - /// Issue RESTART before this command - ENABLE = 0x1, - }, - }, - /// Indicates the first data byte received after the address phase for receive transfer in Master receiver or Slave receiver mode. - /// Reset value : 0x0 - /// NOTE: In case of APB_DATA_WIDTH=8, - /// 1. The user has to perform two APB Reads to IC_DATA_CMD in order to get status on 11 bit. - /// 2. In order to read the 11 bit, the user has to perform the first data byte read [7:0] (offset 0x10) and then perform the second read [15:8] (offset 0x11) in order to know the status of 11 bit (whether the data received in previous read is a first data byte or not). - /// 3. The 11th bit is an optional read field, user can ignore 2nd byte read [15:8] (offset 0x11) if not interested in FIRST_DATA_BYTE status. - FIRST_DATA_BYTE: packed union { - raw: u1, - value: enum(u1) { - /// Sequential data byte received - INACTIVE = 0x0, - /// Non sequential data byte received - ACTIVE = 0x1, - }, - }, - padding: u20, - }), - /// Standard Speed I2C Clock SCL High Count Register - IC_SS_SCL_HCNT: mmio.Mmio(packed struct(u32) { - /// This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock high-period count for standard speed. For more information, refer to 'IC_CLK Frequency Configuration'. - /// This register can be written only when the I2C interface is disabled which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. - /// The minimum valid value is 6; hardware prevents values less than this being written, and if attempted results in 6 being set. For designs with APB_DATA_WIDTH = 8, the order of programming is important to ensure the correct operation of the DW_apb_i2c. The lower byte must be programmed first. Then the upper byte is programmed. - /// NOTE: This register must not be programmed to a value higher than 65525, because DW_apb_i2c uses a 16-bit counter to flag an I2C bus idle condition when this counter reaches a value of IC_SS_SCL_HCNT + 10. - IC_SS_SCL_HCNT: u16, - padding: u16, - }), - /// Standard Speed I2C Clock SCL Low Count Register - IC_SS_SCL_LCNT: mmio.Mmio(packed struct(u32) { - /// This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock low period count for standard speed. For more information, refer to 'IC_CLK Frequency Configuration' - /// This register can be written only when the I2C interface is disabled which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. - /// The minimum valid value is 8; hardware prevents values less than this being written, and if attempted, results in 8 being set. For designs with APB_DATA_WIDTH = 8, the order of programming is important to ensure the correct operation of DW_apb_i2c. The lower byte must be programmed first, and then the upper byte is programmed. - IC_SS_SCL_LCNT: u16, - padding: u16, - }), - /// Fast Mode or Fast Mode Plus I2C Clock SCL High Count Register - IC_FS_SCL_HCNT: mmio.Mmio(packed struct(u32) { - /// This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock high-period count for fast mode or fast mode plus. It is used in high-speed mode to send the Master Code and START BYTE or General CALL. For more information, refer to 'IC_CLK Frequency Configuration'. - /// This register goes away and becomes read-only returning 0s if IC_MAX_SPEED_MODE = standard. This register can be written only when the I2C interface is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. - /// The minimum valid value is 6; hardware prevents values less than this being written, and if attempted results in 6 being set. For designs with APB_DATA_WIDTH == 8 the order of programming is important to ensure the correct operation of the DW_apb_i2c. The lower byte must be programmed first. Then the upper byte is programmed. - IC_FS_SCL_HCNT: u16, - padding: u16, - }), - /// Fast Mode or Fast Mode Plus I2C Clock SCL Low Count Register - IC_FS_SCL_LCNT: mmio.Mmio(packed struct(u32) { - /// This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock low period count for fast speed. It is used in high-speed mode to send the Master Code and START BYTE or General CALL. For more information, refer to 'IC_CLK Frequency Configuration'. - /// This register goes away and becomes read-only returning 0s if IC_MAX_SPEED_MODE = standard. - /// This register can be written only when the I2C interface is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. - /// The minimum valid value is 8; hardware prevents values less than this being written, and if attempted results in 8 being set. For designs with APB_DATA_WIDTH = 8 the order of programming is important to ensure the correct operation of the DW_apb_i2c. The lower byte must be programmed first. Then the upper byte is programmed. If the value is less than 8 then the count value gets changed to 8. - IC_FS_SCL_LCNT: u16, - padding: u16, - }), - reserved44: [8]u8, - /// I2C Interrupt Status Register - /// Each bit in this register has a corresponding mask bit in the IC_INTR_MASK register. These bits are cleared by reading the matching interrupt clear register. The unmasked raw versions of these bits are available in the IC_RAW_INTR_STAT register. - IC_INTR_STAT: mmio.Mmio(packed struct(u32) { - /// See IC_RAW_INTR_STAT for a detailed description of R_RX_UNDER bit. - /// Reset value: 0x0 - R_RX_UNDER: packed union { - raw: u1, - value: enum(u1) { - /// RX_UNDER interrupt is inactive - INACTIVE = 0x0, - /// RX_UNDER interrupt is active - ACTIVE = 0x1, - }, - }, - /// See IC_RAW_INTR_STAT for a detailed description of R_RX_OVER bit. - /// Reset value: 0x0 - R_RX_OVER: packed union { - raw: u1, - value: enum(u1) { - /// R_RX_OVER interrupt is inactive - INACTIVE = 0x0, - /// R_RX_OVER interrupt is active - ACTIVE = 0x1, - }, - }, - /// See IC_RAW_INTR_STAT for a detailed description of R_RX_FULL bit. - /// Reset value: 0x0 - R_RX_FULL: packed union { - raw: u1, - value: enum(u1) { - /// R_RX_FULL interrupt is inactive - INACTIVE = 0x0, - /// R_RX_FULL interrupt is active - ACTIVE = 0x1, - }, - }, - /// See IC_RAW_INTR_STAT for a detailed description of R_TX_OVER bit. - /// Reset value: 0x0 - R_TX_OVER: packed union { - raw: u1, - value: enum(u1) { - /// R_TX_OVER interrupt is inactive - INACTIVE = 0x0, - /// R_TX_OVER interrupt is active - ACTIVE = 0x1, - }, - }, - /// See IC_RAW_INTR_STAT for a detailed description of R_TX_EMPTY bit. - /// Reset value: 0x0 - R_TX_EMPTY: packed union { - raw: u1, - value: enum(u1) { - /// R_TX_EMPTY interrupt is inactive - INACTIVE = 0x0, - /// R_TX_EMPTY interrupt is active - ACTIVE = 0x1, - }, - }, - /// See IC_RAW_INTR_STAT for a detailed description of R_RD_REQ bit. - /// Reset value: 0x0 - R_RD_REQ: packed union { - raw: u1, - value: enum(u1) { - /// R_RD_REQ interrupt is inactive - INACTIVE = 0x0, - /// R_RD_REQ interrupt is active - ACTIVE = 0x1, - }, - }, - /// See IC_RAW_INTR_STAT for a detailed description of R_TX_ABRT bit. - /// Reset value: 0x0 - R_TX_ABRT: packed union { - raw: u1, - value: enum(u1) { - /// R_TX_ABRT interrupt is inactive - INACTIVE = 0x0, - /// R_TX_ABRT interrupt is active - ACTIVE = 0x1, - }, - }, - /// See IC_RAW_INTR_STAT for a detailed description of R_RX_DONE bit. - /// Reset value: 0x0 - R_RX_DONE: packed union { - raw: u1, - value: enum(u1) { - /// R_RX_DONE interrupt is inactive - INACTIVE = 0x0, - /// R_RX_DONE interrupt is active - ACTIVE = 0x1, - }, - }, - /// See IC_RAW_INTR_STAT for a detailed description of R_ACTIVITY bit. - /// Reset value: 0x0 - R_ACTIVITY: packed union { - raw: u1, - value: enum(u1) { - /// R_ACTIVITY interrupt is inactive - INACTIVE = 0x0, - /// R_ACTIVITY interrupt is active - ACTIVE = 0x1, - }, - }, - /// See IC_RAW_INTR_STAT for a detailed description of R_STOP_DET bit. - /// Reset value: 0x0 - R_STOP_DET: packed union { - raw: u1, - value: enum(u1) { - /// R_STOP_DET interrupt is inactive - INACTIVE = 0x0, - /// R_STOP_DET interrupt is active - ACTIVE = 0x1, - }, - }, - /// See IC_RAW_INTR_STAT for a detailed description of R_START_DET bit. - /// Reset value: 0x0 - R_START_DET: packed union { - raw: u1, - value: enum(u1) { - /// R_START_DET interrupt is inactive - INACTIVE = 0x0, - /// R_START_DET interrupt is active - ACTIVE = 0x1, - }, - }, - /// See IC_RAW_INTR_STAT for a detailed description of R_GEN_CALL bit. - /// Reset value: 0x0 - R_GEN_CALL: packed union { - raw: u1, - value: enum(u1) { - /// R_GEN_CALL interrupt is inactive - INACTIVE = 0x0, - /// R_GEN_CALL interrupt is active - ACTIVE = 0x1, - }, - }, - /// See IC_RAW_INTR_STAT for a detailed description of R_RESTART_DET bit. - /// Reset value: 0x0 - R_RESTART_DET: packed union { - raw: u1, - value: enum(u1) { - /// R_RESTART_DET interrupt is inactive - INACTIVE = 0x0, - /// R_RESTART_DET interrupt is active - ACTIVE = 0x1, - }, - }, - padding: u19, - }), - /// I2C Interrupt Mask Register. - /// These bits mask their corresponding interrupt status bits. This register is active low; a value of 0 masks the interrupt, whereas a value of 1 unmasks the interrupt. - IC_INTR_MASK: mmio.Mmio(packed struct(u32) { - /// This bit masks the R_RX_UNDER interrupt in IC_INTR_STAT register. - /// Reset value: 0x1 - M_RX_UNDER: packed union { - raw: u1, - value: enum(u1) { - /// RX_UNDER interrupt is masked - ENABLED = 0x0, - /// RX_UNDER interrupt is unmasked - DISABLED = 0x1, - }, - }, - /// This bit masks the R_RX_OVER interrupt in IC_INTR_STAT register. - /// Reset value: 0x1 - M_RX_OVER: packed union { - raw: u1, - value: enum(u1) { - /// RX_OVER interrupt is masked - ENABLED = 0x0, - /// RX_OVER interrupt is unmasked - DISABLED = 0x1, - }, - }, - /// This bit masks the R_RX_FULL interrupt in IC_INTR_STAT register. - /// Reset value: 0x1 - M_RX_FULL: packed union { - raw: u1, - value: enum(u1) { - /// RX_FULL interrupt is masked - ENABLED = 0x0, - /// RX_FULL interrupt is unmasked - DISABLED = 0x1, - }, - }, - /// This bit masks the R_TX_OVER interrupt in IC_INTR_STAT register. - /// Reset value: 0x1 - M_TX_OVER: packed union { - raw: u1, - value: enum(u1) { - /// TX_OVER interrupt is masked - ENABLED = 0x0, - /// TX_OVER interrupt is unmasked - DISABLED = 0x1, - }, - }, - /// This bit masks the R_TX_EMPTY interrupt in IC_INTR_STAT register. - /// Reset value: 0x1 - M_TX_EMPTY: packed union { - raw: u1, - value: enum(u1) { - /// TX_EMPTY interrupt is masked - ENABLED = 0x0, - /// TX_EMPTY interrupt is unmasked - DISABLED = 0x1, - }, - }, - /// This bit masks the R_RD_REQ interrupt in IC_INTR_STAT register. - /// Reset value: 0x1 - M_RD_REQ: packed union { - raw: u1, - value: enum(u1) { - /// RD_REQ interrupt is masked - ENABLED = 0x0, - /// RD_REQ interrupt is unmasked - DISABLED = 0x1, - }, - }, - /// This bit masks the R_TX_ABRT interrupt in IC_INTR_STAT register. - /// Reset value: 0x1 - M_TX_ABRT: packed union { - raw: u1, - value: enum(u1) { - /// TX_ABORT interrupt is masked - ENABLED = 0x0, - /// TX_ABORT interrupt is unmasked - DISABLED = 0x1, - }, - }, - /// This bit masks the R_RX_DONE interrupt in IC_INTR_STAT register. - /// Reset value: 0x1 - M_RX_DONE: packed union { - raw: u1, - value: enum(u1) { - /// RX_DONE interrupt is masked - ENABLED = 0x0, - /// RX_DONE interrupt is unmasked - DISABLED = 0x1, - }, - }, - /// This bit masks the R_ACTIVITY interrupt in IC_INTR_STAT register. - /// Reset value: 0x0 - M_ACTIVITY: packed union { - raw: u1, - value: enum(u1) { - /// ACTIVITY interrupt is masked - ENABLED = 0x0, - /// ACTIVITY interrupt is unmasked - DISABLED = 0x1, - }, - }, - /// This bit masks the R_STOP_DET interrupt in IC_INTR_STAT register. - /// Reset value: 0x0 - M_STOP_DET: packed union { - raw: u1, - value: enum(u1) { - /// STOP_DET interrupt is masked - ENABLED = 0x0, - /// STOP_DET interrupt is unmasked - DISABLED = 0x1, - }, - }, - /// This bit masks the R_START_DET interrupt in IC_INTR_STAT register. - /// Reset value: 0x0 - M_START_DET: packed union { - raw: u1, - value: enum(u1) { - /// START_DET interrupt is masked - ENABLED = 0x0, - /// START_DET interrupt is unmasked - DISABLED = 0x1, - }, - }, - /// This bit masks the R_GEN_CALL interrupt in IC_INTR_STAT register. - /// Reset value: 0x1 - M_GEN_CALL: packed union { - raw: u1, - value: enum(u1) { - /// GEN_CALL interrupt is masked - ENABLED = 0x0, - /// GEN_CALL interrupt is unmasked - DISABLED = 0x1, - }, - }, - /// This bit masks the R_RESTART_DET interrupt in IC_INTR_STAT register. - /// Reset value: 0x0 - M_RESTART_DET: packed union { - raw: u1, - value: enum(u1) { - /// RESTART_DET interrupt is masked - ENABLED = 0x0, - /// RESTART_DET interrupt is unmasked - DISABLED = 0x1, - }, - }, - padding: u19, - }), - /// I2C Raw Interrupt Status Register - /// Unlike the IC_INTR_STAT register, these bits are not masked so they always show the true status of the DW_apb_i2c. - IC_RAW_INTR_STAT: mmio.Mmio(packed struct(u32) { - /// Set if the processor attempts to read the receive buffer when it is empty by reading from the IC_DATA_CMD register. If the module is disabled (IC_ENABLE[0]=0), this bit keeps its level until the master or slave state machines go into idle, and when ic_en goes to 0, this interrupt is cleared. - /// Reset value: 0x0 - RX_UNDER: packed union { - raw: u1, - value: enum(u1) { - /// RX_UNDER interrupt is inactive - INACTIVE = 0x0, - /// RX_UNDER interrupt is active - ACTIVE = 0x1, - }, - }, - /// Set if the receive buffer is completely filled to IC_RX_BUFFER_DEPTH and an additional byte is received from an external I2C device. The DW_apb_i2c acknowledges this, but any data bytes received after the FIFO is full are lost. If the module is disabled (IC_ENABLE[0]=0), this bit keeps its level until the master or slave state machines go into idle, and when ic_en goes to 0, this interrupt is cleared. - /// Note: If bit 9 of the IC_CON register (RX_FIFO_FULL_HLD_CTRL) is programmed to HIGH, then the RX_OVER interrupt never occurs, because the Rx FIFO never overflows. - /// Reset value: 0x0 - RX_OVER: packed union { - raw: u1, - value: enum(u1) { - /// RX_OVER interrupt is inactive - INACTIVE = 0x0, - /// RX_OVER interrupt is active - ACTIVE = 0x1, - }, - }, - /// Set when the receive buffer reaches or goes above the RX_TL threshold in the IC_RX_TL register. It is automatically cleared by hardware when buffer level goes below the threshold. If the module is disabled (IC_ENABLE[0]=0), the RX FIFO is flushed and held in reset; therefore the RX FIFO is not full. So this bit is cleared once the IC_ENABLE bit 0 is programmed with a 0, regardless of the activity that continues. - /// Reset value: 0x0 - RX_FULL: packed union { - raw: u1, - value: enum(u1) { - /// RX_FULL interrupt is inactive - INACTIVE = 0x0, - /// RX_FULL interrupt is active - ACTIVE = 0x1, - }, - }, - /// Set during transmit if the transmit buffer is filled to IC_TX_BUFFER_DEPTH and the processor attempts to issue another I2C command by writing to the IC_DATA_CMD register. When the module is disabled, this bit keeps its level until the master or slave state machines go into idle, and when ic_en goes to 0, this interrupt is cleared. - /// Reset value: 0x0 - TX_OVER: packed union { - raw: u1, - value: enum(u1) { - /// TX_OVER interrupt is inactive - INACTIVE = 0x0, - /// TX_OVER interrupt is active - ACTIVE = 0x1, - }, - }, - /// The behavior of the TX_EMPTY interrupt status differs based on the TX_EMPTY_CTRL selection in the IC_CON register. - When TX_EMPTY_CTRL = 0: This bit is set to 1 when the transmit buffer is at or below the threshold value set in the IC_TX_TL register. - When TX_EMPTY_CTRL = 1: This bit is set to 1 when the transmit buffer is at or below the threshold value set in the IC_TX_TL register and the transmission of the address/data from the internal shift register for the most recently popped command is completed. It is automatically cleared by hardware when the buffer level goes above the threshold. When IC_ENABLE[0] is set to 0, the TX FIFO is flushed and held in reset. There the TX FIFO looks like it has no data within it, so this bit is set to 1, provided there is activity in the master or slave state machines. When there is no longer any activity, then with ic_en=0, this bit is set to 0. - /// Reset value: 0x0. - TX_EMPTY: packed union { - raw: u1, - value: enum(u1) { - /// TX_EMPTY interrupt is inactive - INACTIVE = 0x0, - /// TX_EMPTY interrupt is active - ACTIVE = 0x1, - }, - }, - /// This bit is set to 1 when DW_apb_i2c is acting as a slave and another I2C master is attempting to read data from DW_apb_i2c. The DW_apb_i2c holds the I2C bus in a wait state (SCL=0) until this interrupt is serviced, which means that the slave has been addressed by a remote master that is asking for data to be transferred. The processor must respond to this interrupt and then write the requested data to the IC_DATA_CMD register. This bit is set to 0 just after the processor reads the IC_CLR_RD_REQ register. - /// Reset value: 0x0 - RD_REQ: packed union { - raw: u1, - value: enum(u1) { - /// RD_REQ interrupt is inactive - INACTIVE = 0x0, - /// RD_REQ interrupt is active - ACTIVE = 0x1, - }, - }, - /// This bit indicates if DW_apb_i2c, as an I2C transmitter, is unable to complete the intended actions on the contents of the transmit FIFO. This situation can occur both as an I2C master or an I2C slave, and is referred to as a 'transmit abort'. When this bit is set to 1, the IC_TX_ABRT_SOURCE register indicates the reason why the transmit abort takes places. - /// Note: The DW_apb_i2c flushes/resets/empties the TX_FIFO and RX_FIFO whenever there is a transmit abort caused by any of the events tracked by the IC_TX_ABRT_SOURCE register. The FIFOs remains in this flushed state until the register IC_CLR_TX_ABRT is read. Once this read is performed, the Tx FIFO is then ready to accept more data bytes from the APB interface. - /// Reset value: 0x0 - TX_ABRT: packed union { - raw: u1, - value: enum(u1) { - /// TX_ABRT interrupt is inactive - INACTIVE = 0x0, - /// TX_ABRT interrupt is active - ACTIVE = 0x1, - }, - }, - /// When the DW_apb_i2c is acting as a slave-transmitter, this bit is set to 1 if the master does not acknowledge a transmitted byte. This occurs on the last byte of the transmission, indicating that the transmission is done. - /// Reset value: 0x0 - RX_DONE: packed union { - raw: u1, - value: enum(u1) { - /// RX_DONE interrupt is inactive - INACTIVE = 0x0, - /// RX_DONE interrupt is active - ACTIVE = 0x1, - }, - }, - /// This bit captures DW_apb_i2c activity and stays set until it is cleared. There are four ways to clear it: - Disabling the DW_apb_i2c - Reading the IC_CLR_ACTIVITY register - Reading the IC_CLR_INTR register - System reset Once this bit is set, it stays set unless one of the four methods is used to clear it. Even if the DW_apb_i2c module is idle, this bit remains set until cleared, indicating that there was activity on the bus. - /// Reset value: 0x0 - ACTIVITY: packed union { - raw: u1, - value: enum(u1) { - /// RAW_INTR_ACTIVITY interrupt is inactive - INACTIVE = 0x0, - /// RAW_INTR_ACTIVITY interrupt is active - ACTIVE = 0x1, - }, - }, - /// Indicates whether a STOP condition has occurred on the I2C interface regardless of whether DW_apb_i2c is operating in slave or master mode. - /// In Slave Mode: - If IC_CON[7]=1'b1 (STOP_DET_IFADDRESSED), the STOP_DET interrupt will be issued only if slave is addressed. Note: During a general call address, this slave does not issue a STOP_DET interrupt if STOP_DET_IF_ADDRESSED=1'b1, even if the slave responds to the general call address by generating ACK. The STOP_DET interrupt is generated only when the transmitted address matches the slave address (SAR). - If IC_CON[7]=1'b0 (STOP_DET_IFADDRESSED), the STOP_DET interrupt is issued irrespective of whether it is being addressed. In Master Mode: - If IC_CON[10]=1'b1 (STOP_DET_IF_MASTER_ACTIVE),the STOP_DET interrupt will be issued only if Master is active. - If IC_CON[10]=1'b0 (STOP_DET_IFADDRESSED),the STOP_DET interrupt will be issued irrespective of whether master is active or not. Reset value: 0x0 - STOP_DET: packed union { - raw: u1, - value: enum(u1) { - /// STOP_DET interrupt is inactive - INACTIVE = 0x0, - /// STOP_DET interrupt is active - ACTIVE = 0x1, - }, - }, - /// Indicates whether a START or RESTART condition has occurred on the I2C interface regardless of whether DW_apb_i2c is operating in slave or master mode. - /// Reset value: 0x0 - START_DET: packed union { - raw: u1, - value: enum(u1) { - /// START_DET interrupt is inactive - INACTIVE = 0x0, - /// START_DET interrupt is active - ACTIVE = 0x1, - }, - }, - /// Set only when a General Call address is received and it is acknowledged. It stays set until it is cleared either by disabling DW_apb_i2c or when the CPU reads bit 0 of the IC_CLR_GEN_CALL register. DW_apb_i2c stores the received data in the Rx buffer. - /// Reset value: 0x0 - GEN_CALL: packed union { - raw: u1, - value: enum(u1) { - /// GEN_CALL interrupt is inactive - INACTIVE = 0x0, - /// GEN_CALL interrupt is active - ACTIVE = 0x1, - }, - }, - /// Indicates whether a RESTART condition has occurred on the I2C interface when DW_apb_i2c is operating in Slave mode and the slave is being addressed. Enabled only when IC_SLV_RESTART_DET_EN=1. - /// Note: However, in high-speed mode or during a START BYTE transfer, the RESTART comes before the address field as per the I2C protocol. In this case, the slave is not the addressed slave when the RESTART is issued, therefore DW_apb_i2c does not generate the RESTART_DET interrupt. - /// Reset value: 0x0 - RESTART_DET: packed union { - raw: u1, - value: enum(u1) { - /// RESTART_DET interrupt is inactive - INACTIVE = 0x0, - /// RESTART_DET interrupt is active - ACTIVE = 0x1, - }, - }, - padding: u19, - }), - /// I2C Receive FIFO Threshold Register - IC_RX_TL: mmio.Mmio(packed struct(u32) { - /// Receive FIFO Threshold Level. - /// Controls the level of entries (or above) that triggers the RX_FULL interrupt (bit 2 in IC_RAW_INTR_STAT register). The valid range is 0-255, with the additional restriction that hardware does not allow this value to be set to a value larger than the depth of the buffer. If an attempt is made to do that, the actual value set will be the maximum depth of the buffer. A value of 0 sets the threshold for 1 entry, and a value of 255 sets the threshold for 256 entries. - RX_TL: u8, - padding: u24, - }), - /// I2C Transmit FIFO Threshold Register - IC_TX_TL: mmio.Mmio(packed struct(u32) { - /// Transmit FIFO Threshold Level. - /// Controls the level of entries (or below) that trigger the TX_EMPTY interrupt (bit 4 in IC_RAW_INTR_STAT register). The valid range is 0-255, with the additional restriction that it may not be set to value larger than the depth of the buffer. If an attempt is made to do that, the actual value set will be the maximum depth of the buffer. A value of 0 sets the threshold for 0 entries, and a value of 255 sets the threshold for 255 entries. - TX_TL: u8, - padding: u24, - }), - /// Clear Combined and Individual Interrupt Register - IC_CLR_INTR: mmio.Mmio(packed struct(u32) { - /// Read this register to clear the combined interrupt, all individual interrupts, and the IC_TX_ABRT_SOURCE register. This bit does not clear hardware clearable interrupts but software clearable interrupts. Refer to Bit 9 of the IC_TX_ABRT_SOURCE register for an exception to clearing IC_TX_ABRT_SOURCE. - /// Reset value: 0x0 - CLR_INTR: u1, - padding: u31, - }), - /// Clear RX_UNDER Interrupt Register - IC_CLR_RX_UNDER: mmio.Mmio(packed struct(u32) { - /// Read this register to clear the RX_UNDER interrupt (bit 0) of the IC_RAW_INTR_STAT register. - /// Reset value: 0x0 - CLR_RX_UNDER: u1, - padding: u31, - }), - /// Clear RX_OVER Interrupt Register - IC_CLR_RX_OVER: mmio.Mmio(packed struct(u32) { - /// Read this register to clear the RX_OVER interrupt (bit 1) of the IC_RAW_INTR_STAT register. - /// Reset value: 0x0 - CLR_RX_OVER: u1, - padding: u31, - }), - /// Clear TX_OVER Interrupt Register - IC_CLR_TX_OVER: mmio.Mmio(packed struct(u32) { - /// Read this register to clear the TX_OVER interrupt (bit 3) of the IC_RAW_INTR_STAT register. - /// Reset value: 0x0 - CLR_TX_OVER: u1, - padding: u31, - }), - /// Clear RD_REQ Interrupt Register - IC_CLR_RD_REQ: mmio.Mmio(packed struct(u32) { - /// Read this register to clear the RD_REQ interrupt (bit 5) of the IC_RAW_INTR_STAT register. - /// Reset value: 0x0 - CLR_RD_REQ: u1, - padding: u31, - }), - /// Clear TX_ABRT Interrupt Register - IC_CLR_TX_ABRT: mmio.Mmio(packed struct(u32) { - /// Read this register to clear the TX_ABRT interrupt (bit 6) of the IC_RAW_INTR_STAT register, and the IC_TX_ABRT_SOURCE register. This also releases the TX FIFO from the flushed/reset state, allowing more writes to the TX FIFO. Refer to Bit 9 of the IC_TX_ABRT_SOURCE register for an exception to clearing IC_TX_ABRT_SOURCE. - /// Reset value: 0x0 - CLR_TX_ABRT: u1, - padding: u31, - }), - /// Clear RX_DONE Interrupt Register - IC_CLR_RX_DONE: mmio.Mmio(packed struct(u32) { - /// Read this register to clear the RX_DONE interrupt (bit 7) of the IC_RAW_INTR_STAT register. - /// Reset value: 0x0 - CLR_RX_DONE: u1, - padding: u31, - }), - /// Clear ACTIVITY Interrupt Register - IC_CLR_ACTIVITY: mmio.Mmio(packed struct(u32) { - /// Reading this register clears the ACTIVITY interrupt if the I2C is not active anymore. If the I2C module is still active on the bus, the ACTIVITY interrupt bit continues to be set. It is automatically cleared by hardware if the module is disabled and if there is no further activity on the bus. The value read from this register to get status of the ACTIVITY interrupt (bit 8) of the IC_RAW_INTR_STAT register. - /// Reset value: 0x0 - CLR_ACTIVITY: u1, - padding: u31, - }), - /// Clear STOP_DET Interrupt Register - IC_CLR_STOP_DET: mmio.Mmio(packed struct(u32) { - /// Read this register to clear the STOP_DET interrupt (bit 9) of the IC_RAW_INTR_STAT register. - /// Reset value: 0x0 - CLR_STOP_DET: u1, - padding: u31, - }), - /// Clear START_DET Interrupt Register - IC_CLR_START_DET: mmio.Mmio(packed struct(u32) { - /// Read this register to clear the START_DET interrupt (bit 10) of the IC_RAW_INTR_STAT register. - /// Reset value: 0x0 - CLR_START_DET: u1, - padding: u31, - }), - /// Clear GEN_CALL Interrupt Register - IC_CLR_GEN_CALL: mmio.Mmio(packed struct(u32) { - /// Read this register to clear the GEN_CALL interrupt (bit 11) of IC_RAW_INTR_STAT register. - /// Reset value: 0x0 - CLR_GEN_CALL: u1, - padding: u31, - }), - /// I2C Enable Register - IC_ENABLE: mmio.Mmio(packed struct(u32) { - /// Controls whether the DW_apb_i2c is enabled. - 0: Disables DW_apb_i2c (TX and RX FIFOs are held in an erased state) - 1: Enables DW_apb_i2c Software can disable DW_apb_i2c while it is active. However, it is important that care be taken to ensure that DW_apb_i2c is disabled properly. A recommended procedure is described in 'Disabling DW_apb_i2c'. - /// When DW_apb_i2c is disabled, the following occurs: - The TX FIFO and RX FIFO get flushed. - Status bits in the IC_INTR_STAT register are still active until DW_apb_i2c goes into IDLE state. If the module is transmitting, it stops as well as deletes the contents of the transmit buffer after the current transfer is complete. If the module is receiving, the DW_apb_i2c stops the current transfer at the end of the current byte and does not acknowledge the transfer. - /// In systems with asynchronous pclk and ic_clk when IC_CLK_TYPE parameter set to asynchronous (1), there is a two ic_clk delay when enabling or disabling the DW_apb_i2c. For a detailed description on how to disable DW_apb_i2c, refer to 'Disabling DW_apb_i2c' - /// Reset value: 0x0 - ENABLE: packed union { - raw: u1, - value: enum(u1) { - /// I2C is disabled - DISABLED = 0x0, - /// I2C is enabled - ENABLED = 0x1, - }, - }, - /// When set, the controller initiates the transfer abort. - 0: ABORT not initiated or ABORT done - 1: ABORT operation in progress The software can abort the I2C transfer in master mode by setting this bit. The software can set this bit only when ENABLE is already set; otherwise, the controller ignores any write to ABORT bit. The software cannot clear the ABORT bit once set. In response to an ABORT, the controller issues a STOP and flushes the Tx FIFO after completing the current transfer, then sets the TX_ABORT interrupt after the abort operation. The ABORT bit is cleared automatically after the abort operation. - /// For a detailed description on how to abort I2C transfers, refer to 'Aborting I2C Transfers'. - /// Reset value: 0x0 - ABORT: packed union { - raw: u1, - value: enum(u1) { - /// ABORT operation not in progress - DISABLE = 0x0, - /// ABORT operation in progress - ENABLED = 0x1, - }, - }, - /// In Master mode: - 1'b1: Blocks the transmission of data on I2C bus even if Tx FIFO has data to transmit. - 1'b0: The transmission of data starts on I2C bus automatically, as soon as the first data is available in the Tx FIFO. Note: To block the execution of Master commands, set the TX_CMD_BLOCK bit only when Tx FIFO is empty (IC_STATUS[2]==1) and Master is in Idle state (IC_STATUS[5] == 0). Any further commands put in the Tx FIFO are not executed until TX_CMD_BLOCK bit is unset. Reset value: IC_TX_CMD_BLOCK_DEFAULT - TX_CMD_BLOCK: packed union { - raw: u1, - value: enum(u1) { - /// Tx Command execution not blocked - NOT_BLOCKED = 0x0, - /// Tx Command execution blocked - BLOCKED = 0x1, - }, - }, - padding: u29, - }), - /// I2C Status Register - /// This is a read-only register used to indicate the current transfer status and FIFO status. The status register may be read at any time. None of the bits in this register request an interrupt. - /// When the I2C is disabled by writing 0 in bit 0 of the IC_ENABLE register: - Bits 1 and 2 are set to 1 - Bits 3 and 10 are set to 0 When the master or slave state machines goes to idle and ic_en=0: - Bits 5 and 6 are set to 0 - IC_STATUS: mmio.Mmio(packed struct(u32) { - /// I2C Activity Status. Reset value: 0x0 - ACTIVITY: packed union { - raw: u1, - value: enum(u1) { - /// I2C is idle - INACTIVE = 0x0, - /// I2C is active - ACTIVE = 0x1, - }, - }, - /// Transmit FIFO Not Full. Set when the transmit FIFO contains one or more empty locations, and is cleared when the FIFO is full. - 0: Transmit FIFO is full - 1: Transmit FIFO is not full Reset value: 0x1 - TFNF: packed union { - raw: u1, - value: enum(u1) { - /// Tx FIFO is full - FULL = 0x0, - /// Tx FIFO not full - NOT_FULL = 0x1, - }, - }, - /// Transmit FIFO Completely Empty. When the transmit FIFO is completely empty, this bit is set. When it contains one or more valid entries, this bit is cleared. This bit field does not request an interrupt. - 0: Transmit FIFO is not empty - 1: Transmit FIFO is empty Reset value: 0x1 - TFE: packed union { - raw: u1, - value: enum(u1) { - /// Tx FIFO not empty - NON_EMPTY = 0x0, - /// Tx FIFO is empty - EMPTY = 0x1, - }, - }, - /// Receive FIFO Not Empty. This bit is set when the receive FIFO contains one or more entries; it is cleared when the receive FIFO is empty. - 0: Receive FIFO is empty - 1: Receive FIFO is not empty Reset value: 0x0 - RFNE: packed union { - raw: u1, - value: enum(u1) { - /// Rx FIFO is empty - EMPTY = 0x0, - /// Rx FIFO not empty - NOT_EMPTY = 0x1, - }, - }, - /// Receive FIFO Completely Full. When the receive FIFO is completely full, this bit is set. When the receive FIFO contains one or more empty location, this bit is cleared. - 0: Receive FIFO is not full - 1: Receive FIFO is full Reset value: 0x0 - RFF: packed union { - raw: u1, - value: enum(u1) { - /// Rx FIFO not full - NOT_FULL = 0x0, - /// Rx FIFO is full - FULL = 0x1, - }, - }, - /// Master FSM Activity Status. When the Master Finite State Machine (FSM) is not in the IDLE state, this bit is set. - 0: Master FSM is in IDLE state so the Master part of DW_apb_i2c is not Active - 1: Master FSM is not in IDLE state so the Master part of DW_apb_i2c is Active Note: IC_STATUS[0]-that is, ACTIVITY bit-is the OR of SLV_ACTIVITY and MST_ACTIVITY bits. - /// Reset value: 0x0 - MST_ACTIVITY: packed union { - raw: u1, - value: enum(u1) { - /// Master is idle - IDLE = 0x0, - /// Master not idle - ACTIVE = 0x1, - }, - }, - /// Slave FSM Activity Status. When the Slave Finite State Machine (FSM) is not in the IDLE state, this bit is set. - 0: Slave FSM is in IDLE state so the Slave part of DW_apb_i2c is not Active - 1: Slave FSM is not in IDLE state so the Slave part of DW_apb_i2c is Active Reset value: 0x0 - SLV_ACTIVITY: packed union { - raw: u1, - value: enum(u1) { - /// Slave is idle - IDLE = 0x0, - /// Slave not idle - ACTIVE = 0x1, - }, - }, - padding: u25, - }), - /// I2C Transmit FIFO Level Register This register contains the number of valid data entries in the transmit FIFO buffer. It is cleared whenever: - The I2C is disabled - There is a transmit abort - that is, TX_ABRT bit is set in the IC_RAW_INTR_STAT register - The slave bulk transmit mode is aborted The register increments whenever data is placed into the transmit FIFO and decrements when data is taken from the transmit FIFO. - IC_TXFLR: mmio.Mmio(packed struct(u32) { - /// Transmit FIFO Level. Contains the number of valid data entries in the transmit FIFO. - /// Reset value: 0x0 - TXFLR: u5, - padding: u27, - }), - /// I2C Receive FIFO Level Register This register contains the number of valid data entries in the receive FIFO buffer. It is cleared whenever: - The I2C is disabled - Whenever there is a transmit abort caused by any of the events tracked in IC_TX_ABRT_SOURCE The register increments whenever data is placed into the receive FIFO and decrements when data is taken from the receive FIFO. - IC_RXFLR: mmio.Mmio(packed struct(u32) { - /// Receive FIFO Level. Contains the number of valid data entries in the receive FIFO. - /// Reset value: 0x0 - RXFLR: u5, - padding: u27, - }), - /// I2C SDA Hold Time Length Register - /// The bits [15:0] of this register are used to control the hold time of SDA during transmit in both slave and master mode (after SCL goes from HIGH to LOW). - /// The bits [23:16] of this register are used to extend the SDA transition (if any) whenever SCL is HIGH in the receiver in either master or slave mode. - /// Writes to this register succeed only when IC_ENABLE[0]=0. - /// The values in this register are in units of ic_clk period. The value programmed in IC_SDA_TX_HOLD must be greater than the minimum hold time in each mode (one cycle in master mode, seven cycles in slave mode) for the value to be implemented. - /// The programmed SDA hold time during transmit (IC_SDA_TX_HOLD) cannot exceed at any time the duration of the low part of scl. Therefore the programmed value cannot be larger than N_SCL_LOW-2, where N_SCL_LOW is the duration of the low part of the scl period measured in ic_clk cycles. - IC_SDA_HOLD: mmio.Mmio(packed struct(u32) { - /// Sets the required SDA hold time in units of ic_clk period, when DW_apb_i2c acts as a transmitter. - /// Reset value: IC_DEFAULT_SDA_HOLD[15:0]. - IC_SDA_TX_HOLD: u16, - /// Sets the required SDA hold time in units of ic_clk period, when DW_apb_i2c acts as a receiver. - /// Reset value: IC_DEFAULT_SDA_HOLD[23:16]. - IC_SDA_RX_HOLD: u8, - padding: u8, - }), - /// I2C Transmit Abort Source Register - /// This register has 32 bits that indicate the source of the TX_ABRT bit. Except for Bit 9, this register is cleared whenever the IC_CLR_TX_ABRT register or the IC_CLR_INTR register is read. To clear Bit 9, the source of the ABRT_SBYTE_NORSTRT must be fixed first; RESTART must be enabled (IC_CON[5]=1), the SPECIAL bit must be cleared (IC_TAR[11]), or the GC_OR_START bit must be cleared (IC_TAR[10]). - /// Once the source of the ABRT_SBYTE_NORSTRT is fixed, then this bit can be cleared in the same manner as other bits in this register. If the source of the ABRT_SBYTE_NORSTRT is not fixed before attempting to clear this bit, Bit 9 clears for one cycle and is then re-asserted. - IC_TX_ABRT_SOURCE: mmio.Mmio(packed struct(u32) { - /// This field indicates that the Master is in 7-bit addressing mode and the address sent was not acknowledged by any slave. - /// Reset value: 0x0 - /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver - ABRT_7B_ADDR_NOACK: packed union { - raw: u1, - value: enum(u1) { - /// This abort is not generated - INACTIVE = 0x0, - /// This abort is generated because of NOACK for 7-bit address - ACTIVE = 0x1, - }, - }, - /// This field indicates that the Master is in 10-bit address mode and the first 10-bit address byte was not acknowledged by any slave. - /// Reset value: 0x0 - /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver - ABRT_10ADDR1_NOACK: packed union { - raw: u1, - value: enum(u1) { - /// This abort is not generated - INACTIVE = 0x0, - /// Byte 1 of 10Bit Address not ACKed by any slave - ACTIVE = 0x1, - }, - }, - /// This field indicates that the Master is in 10-bit address mode and that the second address byte of the 10-bit address was not acknowledged by any slave. - /// Reset value: 0x0 - /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver - ABRT_10ADDR2_NOACK: packed union { - raw: u1, - value: enum(u1) { - /// This abort is not generated - INACTIVE = 0x0, - /// Byte 2 of 10Bit Address not ACKed by any slave - ACTIVE = 0x1, - }, - }, - /// This field indicates the master-mode only bit. When the master receives an acknowledgement for the address, but when it sends data byte(s) following the address, it did not receive an acknowledge from the remote slave(s). - /// Reset value: 0x0 - /// Role of DW_apb_i2c: Master-Transmitter - ABRT_TXDATA_NOACK: packed union { - raw: u1, - value: enum(u1) { - /// Transmitted data non-ACKed by addressed slave-scenario not present - ABRT_TXDATA_NOACK_VOID = 0x0, - /// Transmitted data not ACKed by addressed slave - ABRT_TXDATA_NOACK_GENERATED = 0x1, - }, - }, - /// This field indicates that DW_apb_i2c in master mode has sent a General Call and no slave on the bus acknowledged the General Call. - /// Reset value: 0x0 - /// Role of DW_apb_i2c: Master-Transmitter - ABRT_GCALL_NOACK: packed union { - raw: u1, - value: enum(u1) { - /// GCALL not ACKed by any slave-scenario not present - ABRT_GCALL_NOACK_VOID = 0x0, - /// GCALL not ACKed by any slave - ABRT_GCALL_NOACK_GENERATED = 0x1, - }, - }, - /// This field indicates that DW_apb_i2c in the master mode has sent a General Call but the user programmed the byte following the General Call to be a read from the bus (IC_DATA_CMD[9] is set to 1). - /// Reset value: 0x0 - /// Role of DW_apb_i2c: Master-Transmitter - ABRT_GCALL_READ: packed union { - raw: u1, - value: enum(u1) { - /// GCALL is followed by read from bus-scenario not present - ABRT_GCALL_READ_VOID = 0x0, - /// GCALL is followed by read from bus - ABRT_GCALL_READ_GENERATED = 0x1, - }, - }, - /// This field indicates that the Master is in High Speed mode and the High Speed Master code was acknowledged (wrong behavior). - /// Reset value: 0x0 - /// Role of DW_apb_i2c: Master - ABRT_HS_ACKDET: packed union { - raw: u1, - value: enum(u1) { - /// HS Master code ACKed in HS Mode- scenario not present - ABRT_HS_ACK_VOID = 0x0, - /// HS Master code ACKed in HS Mode - ABRT_HS_ACK_GENERATED = 0x1, - }, - }, - /// This field indicates that the Master has sent a START Byte and the START Byte was acknowledged (wrong behavior). - /// Reset value: 0x0 - /// Role of DW_apb_i2c: Master - ABRT_SBYTE_ACKDET: packed union { - raw: u1, - value: enum(u1) { - /// ACK detected for START byte- scenario not present - ABRT_SBYTE_ACKDET_VOID = 0x0, - /// ACK detected for START byte - ABRT_SBYTE_ACKDET_GENERATED = 0x1, - }, - }, - /// This field indicates that the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) =0) and the user is trying to use the master to transfer data in High Speed mode. - /// Reset value: 0x0 - /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver - ABRT_HS_NORSTRT: packed union { - raw: u1, - value: enum(u1) { - /// User trying to switch Master to HS mode when RESTART disabled- scenario not present - ABRT_HS_NORSTRT_VOID = 0x0, - /// User trying to switch Master to HS mode when RESTART disabled - ABRT_HS_NORSTRT_GENERATED = 0x1, - }, - }, - /// To clear Bit 9, the source of the ABRT_SBYTE_NORSTRT must be fixed first; restart must be enabled (IC_CON[5]=1), the SPECIAL bit must be cleared (IC_TAR[11]), or the GC_OR_START bit must be cleared (IC_TAR[10]). Once the source of the ABRT_SBYTE_NORSTRT is fixed, then this bit can be cleared in the same manner as other bits in this register. If the source of the ABRT_SBYTE_NORSTRT is not fixed before attempting to clear this bit, bit 9 clears for one cycle and then gets reasserted. When this field is set to 1, the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) =0) and the user is trying to send a START Byte. - /// Reset value: 0x0 - /// Role of DW_apb_i2c: Master - ABRT_SBYTE_NORSTRT: packed union { - raw: u1, - value: enum(u1) { - /// User trying to send START byte when RESTART disabled- scenario not present - ABRT_SBYTE_NORSTRT_VOID = 0x0, - /// User trying to send START byte when RESTART disabled - ABRT_SBYTE_NORSTRT_GENERATED = 0x1, - }, - }, - /// This field indicates that the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) =0) and the master sends a read command in 10-bit addressing mode. - /// Reset value: 0x0 - /// Role of DW_apb_i2c: Master-Receiver - ABRT_10B_RD_NORSTRT: packed union { - raw: u1, - value: enum(u1) { - /// Master not trying to read in 10Bit addressing mode when RESTART disabled - ABRT_10B_RD_VOID = 0x0, - /// Master trying to read in 10Bit addressing mode when RESTART disabled - ABRT_10B_RD_GENERATED = 0x1, - }, - }, - /// This field indicates that the User tries to initiate a Master operation with the Master mode disabled. - /// Reset value: 0x0 - /// Role of DW_apb_i2c: Master-Transmitter or Master-Receiver - ABRT_MASTER_DIS: packed union { - raw: u1, - value: enum(u1) { - /// User initiating master operation when MASTER disabled- scenario not present - ABRT_MASTER_DIS_VOID = 0x0, - /// User initiating master operation when MASTER disabled - ABRT_MASTER_DIS_GENERATED = 0x1, - }, - }, - /// This field specifies that the Master has lost arbitration, or if IC_TX_ABRT_SOURCE[14] is also set, then the slave transmitter has lost arbitration. - /// Reset value: 0x0 - /// Role of DW_apb_i2c: Master-Transmitter or Slave-Transmitter - ARB_LOST: packed union { - raw: u1, - value: enum(u1) { - /// Master or Slave-Transmitter lost arbitration- scenario not present - ABRT_LOST_VOID = 0x0, - /// Master or Slave-Transmitter lost arbitration - ABRT_LOST_GENERATED = 0x1, - }, - }, - /// This field specifies that the Slave has received a read command and some data exists in the TX FIFO, so the slave issues a TX_ABRT interrupt to flush old data in TX FIFO. - /// Reset value: 0x0 - /// Role of DW_apb_i2c: Slave-Transmitter - ABRT_SLVFLUSH_TXFIFO: packed union { - raw: u1, - value: enum(u1) { - /// Slave flushes existing data in TX-FIFO upon getting read command- scenario not present - ABRT_SLVFLUSH_TXFIFO_VOID = 0x0, - /// Slave flushes existing data in TX-FIFO upon getting read command - ABRT_SLVFLUSH_TXFIFO_GENERATED = 0x1, - }, - }, - /// This field indicates that a Slave has lost the bus while transmitting data to a remote master. IC_TX_ABRT_SOURCE[12] is set at the same time. Note: Even though the slave never 'owns' the bus, something could go wrong on the bus. This is a fail safe check. For instance, during a data transmission at the low-to-high transition of SCL, if what is on the data bus is not what is supposed to be transmitted, then DW_apb_i2c no longer own the bus. - /// Reset value: 0x0 - /// Role of DW_apb_i2c: Slave-Transmitter - ABRT_SLV_ARBLOST: packed union { - raw: u1, - value: enum(u1) { - /// Slave lost arbitration to remote master- scenario not present - ABRT_SLV_ARBLOST_VOID = 0x0, - /// Slave lost arbitration to remote master - ABRT_SLV_ARBLOST_GENERATED = 0x1, - }, - }, - /// 1: When the processor side responds to a slave mode request for data to be transmitted to a remote master and user writes a 1 in CMD (bit 8) of IC_DATA_CMD register. - /// Reset value: 0x0 - /// Role of DW_apb_i2c: Slave-Transmitter - ABRT_SLVRD_INTX: packed union { - raw: u1, - value: enum(u1) { - /// Slave trying to transmit to remote master in read mode- scenario not present - ABRT_SLVRD_INTX_VOID = 0x0, - /// Slave trying to transmit to remote master in read mode - ABRT_SLVRD_INTX_GENERATED = 0x1, - }, - }, - /// This is a master-mode-only bit. Master has detected the transfer abort (IC_ENABLE[1]) - /// Reset value: 0x0 - /// Role of DW_apb_i2c: Master-Transmitter - ABRT_USER_ABRT: packed union { - raw: u1, - value: enum(u1) { - /// Transfer abort detected by master- scenario not present - ABRT_USER_ABRT_VOID = 0x0, - /// Transfer abort detected by master - ABRT_USER_ABRT_GENERATED = 0x1, - }, - }, - reserved23: u6, - /// This field indicates the number of Tx FIFO Data Commands which are flushed due to TX_ABRT interrupt. It is cleared whenever I2C is disabled. - /// Reset value: 0x0 - /// Role of DW_apb_i2c: Master-Transmitter or Slave-Transmitter - TX_FLUSH_CNT: u9, - }), - /// Generate Slave Data NACK Register - /// The register is used to generate a NACK for the data part of a transfer when DW_apb_i2c is acting as a slave-receiver. This register only exists when the IC_SLV_DATA_NACK_ONLY parameter is set to 1. When this parameter disabled, this register does not exist and writing to the register's address has no effect. - /// A write can occur on this register if both of the following conditions are met: - DW_apb_i2c is disabled (IC_ENABLE[0] = 0) - Slave part is inactive (IC_STATUS[6] = 0) Note: The IC_STATUS[6] is a register read-back location for the internal slv_activity signal; the user should poll this before writing the ic_slv_data_nack_only bit. - IC_SLV_DATA_NACK_ONLY: mmio.Mmio(packed struct(u32) { - /// Generate NACK. This NACK generation only occurs when DW_apb_i2c is a slave-receiver. If this register is set to a value of 1, it can only generate a NACK after a data byte is received; hence, the data transfer is aborted and the data received is not pushed to the receive buffer. - /// When the register is set to a value of 0, it generates NACK/ACK, depending on normal criteria. - 1: generate NACK after data byte received - 0: generate NACK/ACK normally Reset value: 0x0 - NACK: packed union { - raw: u1, - value: enum(u1) { - /// Slave receiver generates NACK normally - DISABLED = 0x0, - /// Slave receiver generates NACK upon data reception only - ENABLED = 0x1, - }, - }, - padding: u31, - }), - /// DMA Control Register - /// The register is used to enable the DMA Controller interface operation. There is a separate bit for transmit and receive. This can be programmed regardless of the state of IC_ENABLE. - IC_DMA_CR: mmio.Mmio(packed struct(u32) { - /// Receive DMA Enable. This bit enables/disables the receive FIFO DMA channel. Reset value: 0x0 - RDMAE: packed union { - raw: u1, - value: enum(u1) { - /// Receive FIFO DMA channel disabled - DISABLED = 0x0, - /// Receive FIFO DMA channel enabled - ENABLED = 0x1, - }, - }, - /// Transmit DMA Enable. This bit enables/disables the transmit FIFO DMA channel. Reset value: 0x0 - TDMAE: packed union { - raw: u1, - value: enum(u1) { - /// transmit FIFO DMA channel disabled - DISABLED = 0x0, - /// Transmit FIFO DMA channel enabled - ENABLED = 0x1, - }, - }, - padding: u30, - }), - /// DMA Transmit Data Level Register - IC_DMA_TDLR: mmio.Mmio(packed struct(u32) { - /// Transmit Data Level. This bit field controls the level at which a DMA request is made by the transmit logic. It is equal to the watermark level; that is, the dma_tx_req signal is generated when the number of valid data entries in the transmit FIFO is equal to or below this field value, and TDMAE = 1. - /// Reset value: 0x0 - DMATDL: u4, - padding: u28, - }), - /// I2C Receive Data Level Register - IC_DMA_RDLR: mmio.Mmio(packed struct(u32) { - /// Receive Data Level. This bit field controls the level at which a DMA request is made by the receive logic. The watermark level = DMARDL+1; that is, dma_rx_req is generated when the number of valid data entries in the receive FIFO is equal to or more than this field value + 1, and RDMAE =1. For instance, when DMARDL is 0, then dma_rx_req is asserted when 1 or more data entries are present in the receive FIFO. - /// Reset value: 0x0 - DMARDL: u4, - padding: u28, - }), - /// I2C SDA Setup Register - /// This register controls the amount of time delay (in terms of number of ic_clk clock periods) introduced in the rising edge of SCL - relative to SDA changing - when DW_apb_i2c services a read request in a slave-transmitter operation. The relevant I2C requirement is tSU:DAT (note 4) as detailed in the I2C Bus Specification. This register must be programmed with a value equal to or greater than 2. - /// Writes to this register succeed only when IC_ENABLE[0] = 0. - /// Note: The length of setup time is calculated using [(IC_SDA_SETUP - 1) * (ic_clk_period)], so if the user requires 10 ic_clk periods of setup time, they should program a value of 11. The IC_SDA_SETUP register is only used by the DW_apb_i2c when operating as a slave transmitter. - IC_SDA_SETUP: mmio.Mmio(packed struct(u32) { - /// SDA Setup. It is recommended that if the required delay is 1000ns, then for an ic_clk frequency of 10 MHz, IC_SDA_SETUP should be programmed to a value of 11. IC_SDA_SETUP must be programmed with a minimum value of 2. - SDA_SETUP: u8, - padding: u24, - }), - /// I2C ACK General Call Register - /// The register controls whether DW_apb_i2c responds with a ACK or NACK when it receives an I2C General Call address. - /// This register is applicable only when the DW_apb_i2c is in slave mode. - IC_ACK_GENERAL_CALL: mmio.Mmio(packed struct(u32) { - /// ACK General Call. When set to 1, DW_apb_i2c responds with a ACK (by asserting ic_data_oe) when it receives a General Call. Otherwise, DW_apb_i2c responds with a NACK (by negating ic_data_oe). - ACK_GEN_CALL: packed union { - raw: u1, - value: enum(u1) { - /// Generate NACK for a General Call - DISABLED = 0x0, - /// Generate ACK for a General Call - ENABLED = 0x1, - }, - }, - padding: u31, - }), - /// I2C Enable Status Register - /// The register is used to report the DW_apb_i2c hardware status when the IC_ENABLE[0] register is set from 1 to 0; that is, when DW_apb_i2c is disabled. - /// If IC_ENABLE[0] has been set to 1, bits 2:1 are forced to 0, and bit 0 is forced to 1. - /// If IC_ENABLE[0] has been set to 0, bits 2:1 is only be valid as soon as bit 0 is read as '0'. - /// Note: When IC_ENABLE[0] has been set to 0, a delay occurs for bit 0 to be read as 0 because disabling the DW_apb_i2c depends on I2C bus activities. - IC_ENABLE_STATUS: mmio.Mmio(packed struct(u32) { - /// ic_en Status. This bit always reflects the value driven on the output port ic_en. - When read as 1, DW_apb_i2c is deemed to be in an enabled state. - When read as 0, DW_apb_i2c is deemed completely inactive. Note: The CPU can safely read this bit anytime. When this bit is read as 0, the CPU can safely read SLV_RX_DATA_LOST (bit 2) and SLV_DISABLED_WHILE_BUSY (bit 1). - /// Reset value: 0x0 - IC_EN: packed union { - raw: u1, - value: enum(u1) { - /// I2C disabled - DISABLED = 0x0, - /// I2C enabled - ENABLED = 0x1, - }, - }, - /// Slave Disabled While Busy (Transmit, Receive). This bit indicates if a potential or active Slave operation has been aborted due to the setting bit 0 of the IC_ENABLE register from 1 to 0. This bit is set when the CPU writes a 0 to the IC_ENABLE register while: - /// (a) DW_apb_i2c is receiving the address byte of the Slave-Transmitter operation from a remote master; - /// OR, - /// (b) address and data bytes of the Slave-Receiver operation from a remote master. - /// When read as 1, DW_apb_i2c is deemed to have forced a NACK during any part of an I2C transfer, irrespective of whether the I2C address matches the slave address set in DW_apb_i2c (IC_SAR register) OR if the transfer is completed before IC_ENABLE is set to 0 but has not taken effect. - /// Note: If the remote I2C master terminates the transfer with a STOP condition before the DW_apb_i2c has a chance to NACK a transfer, and IC_ENABLE[0] has been set to 0, then this bit will also be set to 1. - /// When read as 0, DW_apb_i2c is deemed to have been disabled when there is master activity, or when the I2C bus is idle. - /// Note: The CPU can safely read this bit when IC_EN (bit 0) is read as 0. - /// Reset value: 0x0 - SLV_DISABLED_WHILE_BUSY: packed union { - raw: u1, - value: enum(u1) { - /// Slave is disabled when it is idle - INACTIVE = 0x0, - /// Slave is disabled when it is active - ACTIVE = 0x1, - }, - }, - /// Slave Received Data Lost. This bit indicates if a Slave-Receiver operation has been aborted with at least one data byte received from an I2C transfer due to the setting bit 0 of IC_ENABLE from 1 to 0. When read as 1, DW_apb_i2c is deemed to have been actively engaged in an aborted I2C transfer (with matching address) and the data phase of the I2C transfer has been entered, even though a data byte has been responded with a NACK. - /// Note: If the remote I2C master terminates the transfer with a STOP condition before the DW_apb_i2c has a chance to NACK a transfer, and IC_ENABLE[0] has been set to 0, then this bit is also set to 1. - /// When read as 0, DW_apb_i2c is deemed to have been disabled without being actively involved in the data phase of a Slave-Receiver transfer. - /// Note: The CPU can safely read this bit when IC_EN (bit 0) is read as 0. - /// Reset value: 0x0 - SLV_RX_DATA_LOST: packed union { - raw: u1, - value: enum(u1) { - /// Slave RX Data is not lost - INACTIVE = 0x0, - /// Slave RX Data is lost - ACTIVE = 0x1, - }, - }, - padding: u29, - }), - /// I2C SS, FS or FM+ spike suppression limit - /// This register is used to store the duration, measured in ic_clk cycles, of the longest spike that is filtered out by the spike suppression logic when the component is operating in SS, FS or FM+ modes. The relevant I2C requirement is tSP (table 4) as detailed in the I2C Bus Specification. This register must be programmed with a minimum value of 1. - IC_FS_SPKLEN: mmio.Mmio(packed struct(u32) { - /// This register must be set before any I2C bus transaction can take place to ensure stable operation. This register sets the duration, measured in ic_clk cycles, of the longest spike in the SCL or SDA lines that will be filtered out by the spike suppression logic. This register can be written only when the I2C interface is disabled which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. The minimum valid value is 1; hardware prevents values less than this being written, and if attempted results in 1 being set. or more information, refer to 'Spike Suppression'. - IC_FS_SPKLEN: u8, - padding: u24, - }), - reserved168: [4]u8, - /// Clear RESTART_DET Interrupt Register - IC_CLR_RESTART_DET: mmio.Mmio(packed struct(u32) { - /// Read this register to clear the RESTART_DET interrupt (bit 12) of IC_RAW_INTR_STAT register. - /// Reset value: 0x0 - CLR_RESTART_DET: u1, - padding: u31, - }), - reserved244: [72]u8, - /// Component Parameter Register 1 - /// Note This register is not implemented and therefore reads as 0. If it was implemented it would be a constant read-only register that contains encoded information about the component's parameter settings. Fields shown below are the settings for those parameters - IC_COMP_PARAM_1: mmio.Mmio(packed struct(u32) { - /// APB data bus width is 32 bits - APB_DATA_WIDTH: u2, - /// MAX SPEED MODE = FAST MODE - MAX_SPEED_MODE: u2, - /// Programmable count values for each mode. - HC_COUNT_VALUES: u1, - /// COMBINED Interrupt outputs - INTR_IO: u1, - /// DMA handshaking signals are enabled - HAS_DMA: u1, - /// Encoded parameters not visible - ADD_ENCODED_PARAMS: u1, - /// RX Buffer Depth = 16 - RX_BUFFER_DEPTH: u8, - /// TX Buffer Depth = 16 - TX_BUFFER_DEPTH: u8, - padding: u8, - }), - /// I2C Component Version Register - IC_COMP_VERSION: mmio.Mmio(packed struct(u32) { - IC_COMP_VERSION: u32, - }), - /// I2C Component Type Register - IC_COMP_TYPE: mmio.Mmio(packed struct(u32) { - /// Designware Component Type number = 0x44_57_01_40. This assigned unique hex value is constant and is derived from the two ASCII letters 'DW' followed by a 16-bit unsigned number. - IC_COMP_TYPE: u32, - }), - }; - - /// Programmable IO block - pub const PIO0 = extern struct { - /// PIO control register - CTRL: mmio.Mmio(packed struct(u32) { - /// Enable/disable each of the four state machines by writing 1/0 to each of these four bits. When disabled, a state machine will cease executing instructions, except those written directly to SMx_INSTR by the system. Multiple bits can be set/cleared at once to run/halt multiple state machines simultaneously. - SM_ENABLE: u4, - /// Write 1 to instantly clear internal SM state which may be otherwise difficult to access and will affect future execution. - /// Specifically, the following are cleared: input and output shift counters; the contents of the input shift register; the delay counter; the waiting-on-IRQ state; any stalled instruction written to SMx_INSTR or run by OUT/MOV EXEC; any pin write left asserted due to OUT_STICKY. - SM_RESTART: u4, - /// Restart a state machine's clock divider from an initial phase of 0. Clock dividers are free-running, so once started, their output (including fractional jitter) is completely determined by the integer/fractional divisor configured in SMx_CLKDIV. This means that, if multiple clock dividers with the same divisor are restarted simultaneously, by writing multiple 1 bits to this field, the execution clocks of those state machines will run in precise lockstep. - /// Note that setting/clearing SM_ENABLE does not stop the clock divider from running, so once multiple state machines' clocks are synchronised, it is safe to disable/reenable a state machine, whilst keeping the clock dividers in sync. - /// Note also that CLKDIV_RESTART can be written to whilst the state machine is running, and this is useful to resynchronise clock dividers after the divisors (SMx_CLKDIV) have been changed on-the-fly. - CLKDIV_RESTART: u4, - padding: u20, - }), - /// FIFO status register - FSTAT: mmio.Mmio(packed struct(u32) { - /// State machine RX FIFO is full - RXFULL: u4, - reserved8: u4, - /// State machine RX FIFO is empty - RXEMPTY: u4, - reserved16: u4, - /// State machine TX FIFO is full - TXFULL: u4, - reserved24: u4, - /// State machine TX FIFO is empty - TXEMPTY: u4, - padding: u4, - }), - /// FIFO debug register - FDEBUG: mmio.Mmio(packed struct(u32) { - /// State machine has stalled on full RX FIFO during a blocking PUSH, or an IN with autopush enabled. This flag is also set when a nonblocking PUSH to a full FIFO took place, in which case the state machine has dropped data. Write 1 to clear. - RXSTALL: u4, - reserved8: u4, - /// RX FIFO underflow (i.e. read-on-empty by the system) has occurred. Write 1 to clear. Note that read-on-empty does not perturb the state of the FIFO in any way, but the data returned by reading from an empty FIFO is undefined, so this flag generally only becomes set due to some kind of software error. - RXUNDER: u4, - reserved16: u4, - /// TX FIFO overflow (i.e. write-on-full by the system) has occurred. Write 1 to clear. Note that write-on-full does not alter the state or contents of the FIFO in any way, but the data that the system attempted to write is dropped, so if this flag is set, your software has quite likely dropped some data on the floor. - TXOVER: u4, - reserved24: u4, - /// State machine has stalled on empty TX FIFO during a blocking PULL, or an OUT with autopull enabled. Write 1 to clear. - TXSTALL: u4, - padding: u4, - }), - /// FIFO levels - FLEVEL: mmio.Mmio(packed struct(u32) { - TX0: u4, - RX0: u4, - TX1: u4, - RX1: u4, - TX2: u4, - RX2: u4, - TX3: u4, - RX3: u4, - }), - /// Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. - TXF0: u32, - /// Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. - TXF1: u32, - /// Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. - TXF2: u32, - /// Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. - TXF3: u32, - /// Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. - RXF0: u32, - /// Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. - RXF1: u32, - /// Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. - RXF2: u32, - /// Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. - RXF3: u32, - /// State machine IRQ flags register. Write 1 to clear. There are 8 state machine IRQ flags, which can be set, cleared, and waited on by the state machines. There's no fixed association between flags and state machines -- any state machine can use any flag. - /// Any of the 8 flags can be used for timing synchronisation between state machines, using IRQ and WAIT instructions. The lower four of these flags are also routed out to system-level interrupt requests, alongside FIFO status interrupts -- see e.g. IRQ0_INTE. - IRQ: mmio.Mmio(packed struct(u32) { - IRQ: u8, - padding: u24, - }), - /// Writing a 1 to each of these bits will forcibly assert the corresponding IRQ. Note this is different to the INTF register: writing here affects PIO internal state. INTF just asserts the processor-facing IRQ signal for testing ISRs, and is not visible to the state machines. - IRQ_FORCE: mmio.Mmio(packed struct(u32) { - IRQ_FORCE: u8, - padding: u24, - }), - /// There is a 2-flipflop synchronizer on each GPIO input, which protects PIO logic from metastabilities. This increases input delay, and for fast synchronous IO (e.g. SPI) these synchronizers may need to be bypassed. Each bit in this register corresponds to one GPIO. - /// 0 -> input is synchronized (default) - /// 1 -> synchronizer is bypassed - /// If in doubt, leave this register as all zeroes. - INPUT_SYNC_BYPASS: u32, - /// Read to sample the pad output values PIO is currently driving to the GPIOs. On RP2040 there are 30 GPIOs, so the two most significant bits are hardwired to 0. - DBG_PADOUT: u32, - /// Read to sample the pad output enables (direction) PIO is currently driving to the GPIOs. On RP2040 there are 30 GPIOs, so the two most significant bits are hardwired to 0. - DBG_PADOE: u32, - /// The PIO hardware has some free parameters that may vary between chip products. - /// These should be provided in the chip datasheet, but are also exposed here. - DBG_CFGINFO: mmio.Mmio(packed struct(u32) { - /// The depth of the state machine TX/RX FIFOs, measured in words. - /// Joining fifos via SHIFTCTRL_FJOIN gives one FIFO with double - /// this depth. - FIFO_DEPTH: u6, - reserved8: u2, - /// The number of state machines this PIO instance is equipped with. - SM_COUNT: u4, - reserved16: u4, - /// The size of the instruction memory, measured in units of one instruction - IMEM_SIZE: u6, - padding: u10, - }), - /// Write-only access to instruction memory location 0 - INSTR_MEM0: mmio.Mmio(packed struct(u32) { - INSTR_MEM0: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 1 - INSTR_MEM1: mmio.Mmio(packed struct(u32) { - INSTR_MEM1: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 2 - INSTR_MEM2: mmio.Mmio(packed struct(u32) { - INSTR_MEM2: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 3 - INSTR_MEM3: mmio.Mmio(packed struct(u32) { - INSTR_MEM3: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 4 - INSTR_MEM4: mmio.Mmio(packed struct(u32) { - INSTR_MEM4: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 5 - INSTR_MEM5: mmio.Mmio(packed struct(u32) { - INSTR_MEM5: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 6 - INSTR_MEM6: mmio.Mmio(packed struct(u32) { - INSTR_MEM6: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 7 - INSTR_MEM7: mmio.Mmio(packed struct(u32) { - INSTR_MEM7: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 8 - INSTR_MEM8: mmio.Mmio(packed struct(u32) { - INSTR_MEM8: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 9 - INSTR_MEM9: mmio.Mmio(packed struct(u32) { - INSTR_MEM9: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 10 - INSTR_MEM10: mmio.Mmio(packed struct(u32) { - INSTR_MEM10: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 11 - INSTR_MEM11: mmio.Mmio(packed struct(u32) { - INSTR_MEM11: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 12 - INSTR_MEM12: mmio.Mmio(packed struct(u32) { - INSTR_MEM12: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 13 - INSTR_MEM13: mmio.Mmio(packed struct(u32) { - INSTR_MEM13: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 14 - INSTR_MEM14: mmio.Mmio(packed struct(u32) { - INSTR_MEM14: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 15 - INSTR_MEM15: mmio.Mmio(packed struct(u32) { - INSTR_MEM15: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 16 - INSTR_MEM16: mmio.Mmio(packed struct(u32) { - INSTR_MEM16: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 17 - INSTR_MEM17: mmio.Mmio(packed struct(u32) { - INSTR_MEM17: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 18 - INSTR_MEM18: mmio.Mmio(packed struct(u32) { - INSTR_MEM18: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 19 - INSTR_MEM19: mmio.Mmio(packed struct(u32) { - INSTR_MEM19: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 20 - INSTR_MEM20: mmio.Mmio(packed struct(u32) { - INSTR_MEM20: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 21 - INSTR_MEM21: mmio.Mmio(packed struct(u32) { - INSTR_MEM21: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 22 - INSTR_MEM22: mmio.Mmio(packed struct(u32) { - INSTR_MEM22: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 23 - INSTR_MEM23: mmio.Mmio(packed struct(u32) { - INSTR_MEM23: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 24 - INSTR_MEM24: mmio.Mmio(packed struct(u32) { - INSTR_MEM24: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 25 - INSTR_MEM25: mmio.Mmio(packed struct(u32) { - INSTR_MEM25: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 26 - INSTR_MEM26: mmio.Mmio(packed struct(u32) { - INSTR_MEM26: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 27 - INSTR_MEM27: mmio.Mmio(packed struct(u32) { - INSTR_MEM27: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 28 - INSTR_MEM28: mmio.Mmio(packed struct(u32) { - INSTR_MEM28: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 29 - INSTR_MEM29: mmio.Mmio(packed struct(u32) { - INSTR_MEM29: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 30 - INSTR_MEM30: mmio.Mmio(packed struct(u32) { - INSTR_MEM30: u16, - padding: u16, - }), - /// Write-only access to instruction memory location 31 - INSTR_MEM31: mmio.Mmio(packed struct(u32) { - INSTR_MEM31: u16, - padding: u16, - }), - /// Clock divisor register for state machine 0 - /// Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) - SM0_CLKDIV: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// Fractional part of clock divisor - FRAC: u8, - /// Effective frequency is sysclk/(int + frac/256). - /// Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. - INT: u16, - }), - /// Execution/behavioural settings for state machine 0 - SM0_EXECCTRL: mmio.Mmio(packed struct(u32) { - /// Comparison level for the MOV x, STATUS instruction - STATUS_N: u4, - /// Comparison used for the MOV x, STATUS instruction. - STATUS_SEL: packed union { - raw: u1, - value: enum(u1) { - /// All-ones if TX FIFO level < N, otherwise all-zeroes - TXLEVEL = 0x0, - /// All-ones if RX FIFO level < N, otherwise all-zeroes - RXLEVEL = 0x1, - }, - }, - reserved7: u2, - /// After reaching wrap_top, execution is wrapped to this address. - WRAP_BOTTOM: u5, - /// After reaching this address, execution is wrapped to wrap_bottom. - /// If the instruction is a jump, and the jump condition is true, the jump takes priority. - WRAP_TOP: u5, - /// Continuously assert the most recent OUT/SET to the pins - OUT_STICKY: u1, - /// If 1, use a bit of OUT data as an auxiliary write enable - /// When used in conjunction with OUT_STICKY, writes with an enable of 0 will - /// deassert the latest pin write. This can create useful masking/override behaviour - /// due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) - INLINE_OUT_EN: u1, - /// Which data bit to use for inline OUT enable - OUT_EN_SEL: u5, - /// The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. - JMP_PIN: u5, - /// If 1, side-set data is asserted to pin directions, instead of pin values - SIDE_PINDIR: u1, - /// If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit. - SIDE_EN: u1, - /// If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes. - EXEC_STALLED: u1, - }), - /// Control behaviour of the input/output shift registers for state machine 0 - SM0_SHIFTCTRL: mmio.Mmio(packed struct(u32) { - reserved16: u16, - /// Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH. - AUTOPUSH: u1, - /// Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH. - AUTOPULL: u1, - /// 1 = shift input shift register to right (data enters from left). 0 = to left. - IN_SHIFTDIR: u1, - /// 1 = shift out of output shift register to right. 0 = to left. - OUT_SHIFTDIR: u1, - /// Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place. - /// Write 0 for value of 32. - PUSH_THRESH: u5, - /// Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place. - /// Write 0 for value of 32. - PULL_THRESH: u5, - /// When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep. - /// RX FIFO is disabled as a result (always reads as both full and empty). - /// FIFOs are flushed when this bit is changed. - FJOIN_TX: u1, - /// When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep. - /// TX FIFO is disabled as a result (always reads as both full and empty). - /// FIFOs are flushed when this bit is changed. - FJOIN_RX: u1, - }), - /// Current instruction address of state machine 0 - SM0_ADDR: mmio.Mmio(packed struct(u32) { - SM0_ADDR: u5, - padding: u27, - }), - /// Read to see the instruction currently addressed by state machine 0's program counter - /// Write to execute an instruction immediately (including jumps) and then resume execution. - SM0_INSTR: mmio.Mmio(packed struct(u32) { - SM0_INSTR: u16, - padding: u16, - }), - /// State machine pin control - SM0_PINCTRL: mmio.Mmio(packed struct(u32) { - /// The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. - OUT_BASE: u5, - /// The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data. - SET_BASE: u5, - /// The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins. - SIDESET_BASE: u5, - /// The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number. - IN_BASE: u5, - /// The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive. - OUT_COUNT: u6, - /// The number of pins asserted by a SET. In the range 0 to 5 inclusive. - SET_COUNT: u3, - /// The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay). - SIDESET_COUNT: u3, - }), - /// Clock divisor register for state machine 1 - /// Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) - SM1_CLKDIV: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// Fractional part of clock divisor - FRAC: u8, - /// Effective frequency is sysclk/(int + frac/256). - /// Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. - INT: u16, - }), - /// Execution/behavioural settings for state machine 1 - SM1_EXECCTRL: mmio.Mmio(packed struct(u32) { - /// Comparison level for the MOV x, STATUS instruction - STATUS_N: u4, - /// Comparison used for the MOV x, STATUS instruction. - STATUS_SEL: packed union { - raw: u1, - value: enum(u1) { - /// All-ones if TX FIFO level < N, otherwise all-zeroes - TXLEVEL = 0x0, - /// All-ones if RX FIFO level < N, otherwise all-zeroes - RXLEVEL = 0x1, - }, - }, - reserved7: u2, - /// After reaching wrap_top, execution is wrapped to this address. - WRAP_BOTTOM: u5, - /// After reaching this address, execution is wrapped to wrap_bottom. - /// If the instruction is a jump, and the jump condition is true, the jump takes priority. - WRAP_TOP: u5, - /// Continuously assert the most recent OUT/SET to the pins - OUT_STICKY: u1, - /// If 1, use a bit of OUT data as an auxiliary write enable - /// When used in conjunction with OUT_STICKY, writes with an enable of 0 will - /// deassert the latest pin write. This can create useful masking/override behaviour - /// due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) - INLINE_OUT_EN: u1, - /// Which data bit to use for inline OUT enable - OUT_EN_SEL: u5, - /// The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. - JMP_PIN: u5, - /// If 1, side-set data is asserted to pin directions, instead of pin values - SIDE_PINDIR: u1, - /// If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit. - SIDE_EN: u1, - /// If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes. - EXEC_STALLED: u1, - }), - /// Control behaviour of the input/output shift registers for state machine 1 - SM1_SHIFTCTRL: mmio.Mmio(packed struct(u32) { - reserved16: u16, - /// Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH. - AUTOPUSH: u1, - /// Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH. - AUTOPULL: u1, - /// 1 = shift input shift register to right (data enters from left). 0 = to left. - IN_SHIFTDIR: u1, - /// 1 = shift out of output shift register to right. 0 = to left. - OUT_SHIFTDIR: u1, - /// Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place. - /// Write 0 for value of 32. - PUSH_THRESH: u5, - /// Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place. - /// Write 0 for value of 32. - PULL_THRESH: u5, - /// When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep. - /// RX FIFO is disabled as a result (always reads as both full and empty). - /// FIFOs are flushed when this bit is changed. - FJOIN_TX: u1, - /// When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep. - /// TX FIFO is disabled as a result (always reads as both full and empty). - /// FIFOs are flushed when this bit is changed. - FJOIN_RX: u1, - }), - /// Current instruction address of state machine 1 - SM1_ADDR: mmio.Mmio(packed struct(u32) { - SM1_ADDR: u5, - padding: u27, - }), - /// Read to see the instruction currently addressed by state machine 1's program counter - /// Write to execute an instruction immediately (including jumps) and then resume execution. - SM1_INSTR: mmio.Mmio(packed struct(u32) { - SM1_INSTR: u16, - padding: u16, - }), - /// State machine pin control - SM1_PINCTRL: mmio.Mmio(packed struct(u32) { - /// The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. - OUT_BASE: u5, - /// The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data. - SET_BASE: u5, - /// The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins. - SIDESET_BASE: u5, - /// The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number. - IN_BASE: u5, - /// The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive. - OUT_COUNT: u6, - /// The number of pins asserted by a SET. In the range 0 to 5 inclusive. - SET_COUNT: u3, - /// The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay). - SIDESET_COUNT: u3, - }), - /// Clock divisor register for state machine 2 - /// Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) - SM2_CLKDIV: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// Fractional part of clock divisor - FRAC: u8, - /// Effective frequency is sysclk/(int + frac/256). - /// Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. - INT: u16, - }), - /// Execution/behavioural settings for state machine 2 - SM2_EXECCTRL: mmio.Mmio(packed struct(u32) { - /// Comparison level for the MOV x, STATUS instruction - STATUS_N: u4, - /// Comparison used for the MOV x, STATUS instruction. - STATUS_SEL: packed union { - raw: u1, - value: enum(u1) { - /// All-ones if TX FIFO level < N, otherwise all-zeroes - TXLEVEL = 0x0, - /// All-ones if RX FIFO level < N, otherwise all-zeroes - RXLEVEL = 0x1, - }, - }, - reserved7: u2, - /// After reaching wrap_top, execution is wrapped to this address. - WRAP_BOTTOM: u5, - /// After reaching this address, execution is wrapped to wrap_bottom. - /// If the instruction is a jump, and the jump condition is true, the jump takes priority. - WRAP_TOP: u5, - /// Continuously assert the most recent OUT/SET to the pins - OUT_STICKY: u1, - /// If 1, use a bit of OUT data as an auxiliary write enable - /// When used in conjunction with OUT_STICKY, writes with an enable of 0 will - /// deassert the latest pin write. This can create useful masking/override behaviour - /// due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) - INLINE_OUT_EN: u1, - /// Which data bit to use for inline OUT enable - OUT_EN_SEL: u5, - /// The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. - JMP_PIN: u5, - /// If 1, side-set data is asserted to pin directions, instead of pin values - SIDE_PINDIR: u1, - /// If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit. - SIDE_EN: u1, - /// If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes. - EXEC_STALLED: u1, - }), - /// Control behaviour of the input/output shift registers for state machine 2 - SM2_SHIFTCTRL: mmio.Mmio(packed struct(u32) { - reserved16: u16, - /// Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH. - AUTOPUSH: u1, - /// Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH. - AUTOPULL: u1, - /// 1 = shift input shift register to right (data enters from left). 0 = to left. - IN_SHIFTDIR: u1, - /// 1 = shift out of output shift register to right. 0 = to left. - OUT_SHIFTDIR: u1, - /// Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place. - /// Write 0 for value of 32. - PUSH_THRESH: u5, - /// Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place. - /// Write 0 for value of 32. - PULL_THRESH: u5, - /// When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep. - /// RX FIFO is disabled as a result (always reads as both full and empty). - /// FIFOs are flushed when this bit is changed. - FJOIN_TX: u1, - /// When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep. - /// TX FIFO is disabled as a result (always reads as both full and empty). - /// FIFOs are flushed when this bit is changed. - FJOIN_RX: u1, - }), - /// Current instruction address of state machine 2 - SM2_ADDR: mmio.Mmio(packed struct(u32) { - SM2_ADDR: u5, - padding: u27, - }), - /// Read to see the instruction currently addressed by state machine 2's program counter - /// Write to execute an instruction immediately (including jumps) and then resume execution. - SM2_INSTR: mmio.Mmio(packed struct(u32) { - SM2_INSTR: u16, - padding: u16, - }), - /// State machine pin control - SM2_PINCTRL: mmio.Mmio(packed struct(u32) { - /// The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. - OUT_BASE: u5, - /// The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data. - SET_BASE: u5, - /// The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins. - SIDESET_BASE: u5, - /// The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number. - IN_BASE: u5, - /// The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive. - OUT_COUNT: u6, - /// The number of pins asserted by a SET. In the range 0 to 5 inclusive. - SET_COUNT: u3, - /// The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay). - SIDESET_COUNT: u3, - }), - /// Clock divisor register for state machine 3 - /// Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) - SM3_CLKDIV: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// Fractional part of clock divisor - FRAC: u8, - /// Effective frequency is sysclk/(int + frac/256). - /// Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. - INT: u16, - }), - /// Execution/behavioural settings for state machine 3 - SM3_EXECCTRL: mmio.Mmio(packed struct(u32) { - /// Comparison level for the MOV x, STATUS instruction - STATUS_N: u4, - /// Comparison used for the MOV x, STATUS instruction. - STATUS_SEL: packed union { - raw: u1, - value: enum(u1) { - /// All-ones if TX FIFO level < N, otherwise all-zeroes - TXLEVEL = 0x0, - /// All-ones if RX FIFO level < N, otherwise all-zeroes - RXLEVEL = 0x1, - }, - }, - reserved7: u2, - /// After reaching wrap_top, execution is wrapped to this address. - WRAP_BOTTOM: u5, - /// After reaching this address, execution is wrapped to wrap_bottom. - /// If the instruction is a jump, and the jump condition is true, the jump takes priority. - WRAP_TOP: u5, - /// Continuously assert the most recent OUT/SET to the pins - OUT_STICKY: u1, - /// If 1, use a bit of OUT data as an auxiliary write enable - /// When used in conjunction with OUT_STICKY, writes with an enable of 0 will - /// deassert the latest pin write. This can create useful masking/override behaviour - /// due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) - INLINE_OUT_EN: u1, - /// Which data bit to use for inline OUT enable - OUT_EN_SEL: u5, - /// The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. - JMP_PIN: u5, - /// If 1, side-set data is asserted to pin directions, instead of pin values - SIDE_PINDIR: u1, - /// If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit. - SIDE_EN: u1, - /// If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes. - EXEC_STALLED: u1, - }), - /// Control behaviour of the input/output shift registers for state machine 3 - SM3_SHIFTCTRL: mmio.Mmio(packed struct(u32) { - reserved16: u16, - /// Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH. - AUTOPUSH: u1, - /// Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH. - AUTOPULL: u1, - /// 1 = shift input shift register to right (data enters from left). 0 = to left. - IN_SHIFTDIR: u1, - /// 1 = shift out of output shift register to right. 0 = to left. - OUT_SHIFTDIR: u1, - /// Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place. - /// Write 0 for value of 32. - PUSH_THRESH: u5, - /// Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place. - /// Write 0 for value of 32. - PULL_THRESH: u5, - /// When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep. - /// RX FIFO is disabled as a result (always reads as both full and empty). - /// FIFOs are flushed when this bit is changed. - FJOIN_TX: u1, - /// When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep. - /// TX FIFO is disabled as a result (always reads as both full and empty). - /// FIFOs are flushed when this bit is changed. - FJOIN_RX: u1, - }), - /// Current instruction address of state machine 3 - SM3_ADDR: mmio.Mmio(packed struct(u32) { - SM3_ADDR: u5, - padding: u27, - }), - /// Read to see the instruction currently addressed by state machine 3's program counter - /// Write to execute an instruction immediately (including jumps) and then resume execution. - SM3_INSTR: mmio.Mmio(packed struct(u32) { - SM3_INSTR: u16, - padding: u16, - }), - /// State machine pin control - SM3_PINCTRL: mmio.Mmio(packed struct(u32) { - /// The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. - OUT_BASE: u5, - /// The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data. - SET_BASE: u5, - /// The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins. - SIDESET_BASE: u5, - /// The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number. - IN_BASE: u5, - /// The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive. - OUT_COUNT: u6, - /// The number of pins asserted by a SET. In the range 0 to 5 inclusive. - SET_COUNT: u3, - /// The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay). - SIDESET_COUNT: u3, - }), - /// Raw Interrupts - INTR: mmio.Mmio(packed struct(u32) { - SM0_RXNEMPTY: u1, - SM1_RXNEMPTY: u1, - SM2_RXNEMPTY: u1, - SM3_RXNEMPTY: u1, - SM0_TXNFULL: u1, - SM1_TXNFULL: u1, - SM2_TXNFULL: u1, - SM3_TXNFULL: u1, - SM0: u1, - SM1: u1, - SM2: u1, - SM3: u1, - padding: u20, - }), - /// Interrupt Enable for irq0 - IRQ0_INTE: mmio.Mmio(packed struct(u32) { - SM0_RXNEMPTY: u1, - SM1_RXNEMPTY: u1, - SM2_RXNEMPTY: u1, - SM3_RXNEMPTY: u1, - SM0_TXNFULL: u1, - SM1_TXNFULL: u1, - SM2_TXNFULL: u1, - SM3_TXNFULL: u1, - SM0: u1, - SM1: u1, - SM2: u1, - SM3: u1, - padding: u20, - }), - /// Interrupt Force for irq0 - IRQ0_INTF: mmio.Mmio(packed struct(u32) { - SM0_RXNEMPTY: u1, - SM1_RXNEMPTY: u1, - SM2_RXNEMPTY: u1, - SM3_RXNEMPTY: u1, - SM0_TXNFULL: u1, - SM1_TXNFULL: u1, - SM2_TXNFULL: u1, - SM3_TXNFULL: u1, - SM0: u1, - SM1: u1, - SM2: u1, - SM3: u1, - padding: u20, - }), - /// Interrupt status after masking & forcing for irq0 - IRQ0_INTS: mmio.Mmio(packed struct(u32) { - SM0_RXNEMPTY: u1, - SM1_RXNEMPTY: u1, - SM2_RXNEMPTY: u1, - SM3_RXNEMPTY: u1, - SM0_TXNFULL: u1, - SM1_TXNFULL: u1, - SM2_TXNFULL: u1, - SM3_TXNFULL: u1, - SM0: u1, - SM1: u1, - SM2: u1, - SM3: u1, - padding: u20, - }), - /// Interrupt Enable for irq1 - IRQ1_INTE: mmio.Mmio(packed struct(u32) { - SM0_RXNEMPTY: u1, - SM1_RXNEMPTY: u1, - SM2_RXNEMPTY: u1, - SM3_RXNEMPTY: u1, - SM0_TXNFULL: u1, - SM1_TXNFULL: u1, - SM2_TXNFULL: u1, - SM3_TXNFULL: u1, - SM0: u1, - SM1: u1, - SM2: u1, - SM3: u1, - padding: u20, - }), - /// Interrupt Force for irq1 - IRQ1_INTF: mmio.Mmio(packed struct(u32) { - SM0_RXNEMPTY: u1, - SM1_RXNEMPTY: u1, - SM2_RXNEMPTY: u1, - SM3_RXNEMPTY: u1, - SM0_TXNFULL: u1, - SM1_TXNFULL: u1, - SM2_TXNFULL: u1, - SM3_TXNFULL: u1, - SM0: u1, - SM1: u1, - SM2: u1, - SM3: u1, - padding: u20, - }), - /// Interrupt status after masking & forcing for irq1 - IRQ1_INTS: mmio.Mmio(packed struct(u32) { - SM0_RXNEMPTY: u1, - SM1_RXNEMPTY: u1, - SM2_RXNEMPTY: u1, - SM3_RXNEMPTY: u1, - SM0_TXNFULL: u1, - SM1_TXNFULL: u1, - SM2_TXNFULL: u1, - SM3_TXNFULL: u1, - SM0: u1, - SM1: u1, - SM2: u1, - SM3: u1, - padding: u20, - }), - }; - - /// Control and data interface to SAR ADC - pub const ADC = extern struct { - /// ADC Control and Status - CS: mmio.Mmio(packed struct(u32) { - /// Power on ADC and enable its clock. - /// 1 - enabled. 0 - disabled. - EN: u1, - /// Power on temperature sensor. 1 - enabled. 0 - disabled. - TS_EN: u1, - /// Start a single conversion. Self-clearing. Ignored if start_many is asserted. - START_ONCE: u1, - /// Continuously perform conversions whilst this bit is 1. A new conversion will start immediately after the previous finishes. - START_MANY: u1, - reserved8: u4, - /// 1 if the ADC is ready to start a new conversion. Implies any previous conversion has completed. - /// 0 whilst conversion in progress. - READY: u1, - /// The most recent ADC conversion encountered an error; result is undefined or noisy. - ERR: u1, - /// Some past ADC conversion encountered an error. Write 1 to clear. - ERR_STICKY: u1, - reserved12: u1, - /// Select analog mux input. Updated automatically in round-robin mode. - AINSEL: u3, - reserved16: u1, - /// Round-robin sampling. 1 bit per channel. Set all bits to 0 to disable. - /// Otherwise, the ADC will cycle through each enabled channel in a round-robin fashion. - /// The first channel to be sampled will be the one currently indicated by AINSEL. - /// AINSEL will be updated after each conversion with the newly-selected channel. - RROBIN: u5, - padding: u11, - }), - /// Result of most recent ADC conversion - RESULT: mmio.Mmio(packed struct(u32) { - RESULT: u12, - padding: u20, - }), - /// FIFO control and status - FCS: mmio.Mmio(packed struct(u32) { - /// If 1: write result to the FIFO after each conversion. - EN: u1, - /// If 1: FIFO results are right-shifted to be one byte in size. Enables DMA to byte buffers. - SHIFT: u1, - /// If 1: conversion error bit appears in the FIFO alongside the result - ERR: u1, - /// If 1: assert DMA requests when FIFO contains data - DREQ_EN: u1, - reserved8: u4, - EMPTY: u1, - FULL: u1, - /// 1 if the FIFO has been underflowed. Write 1 to clear. - UNDER: u1, - /// 1 if the FIFO has been overflowed. Write 1 to clear. - OVER: u1, - reserved16: u4, - /// The number of conversion results currently waiting in the FIFO - LEVEL: u4, - reserved24: u4, - /// DREQ/IRQ asserted when level >= threshold - THRESH: u4, - padding: u4, - }), - /// Conversion result FIFO - FIFO: mmio.Mmio(packed struct(u32) { - VAL: u12, - reserved15: u3, - /// 1 if this particular sample experienced a conversion error. Remains in the same location if the sample is shifted. - ERR: u1, - padding: u16, - }), - /// Clock divider. If non-zero, CS_START_MANY will start conversions - /// at regular intervals rather than back-to-back. - /// The divider is reset when either of these fields are written. - /// Total period is 1 + INT + FRAC / 256 - DIV: mmio.Mmio(packed struct(u32) { - /// Fractional part of clock divisor. First-order delta-sigma. - FRAC: u8, - /// Integer part of clock divisor. - INT: u16, - padding: u8, - }), - /// Raw Interrupts - INTR: mmio.Mmio(packed struct(u32) { - /// Triggered when the sample FIFO reaches a certain level. - /// This level can be programmed via the FCS_THRESH field. - FIFO: u1, - padding: u31, - }), - /// Interrupt Enable - INTE: mmio.Mmio(packed struct(u32) { - /// Triggered when the sample FIFO reaches a certain level. - /// This level can be programmed via the FCS_THRESH field. - FIFO: u1, - padding: u31, - }), - /// Interrupt Force - INTF: mmio.Mmio(packed struct(u32) { - /// Triggered when the sample FIFO reaches a certain level. - /// This level can be programmed via the FCS_THRESH field. - FIFO: u1, - padding: u31, - }), - /// Interrupt status after masking & forcing - INTS: mmio.Mmio(packed struct(u32) { - /// Triggered when the sample FIFO reaches a certain level. - /// This level can be programmed via the FCS_THRESH field. - FIFO: u1, - padding: u31, - }), - }; - - /// Simple PWM - pub const PWM = extern struct { - /// Control and status register - CH0_CSR: mmio.Mmio(packed struct(u32) { - /// Enable the PWM channel. - EN: u1, - /// 1: Enable phase-correct modulation. 0: Trailing-edge - PH_CORRECT: u1, - /// Invert output A - A_INV: u1, - /// Invert output B - B_INV: u1, - DIVMODE: packed union { - raw: u2, - value: enum(u2) { - /// Free-running counting at rate dictated by fractional divider - div = 0x0, - /// Fractional divider operation is gated by the PWM B pin. - level = 0x1, - /// Counter advances with each rising edge of the PWM B pin. - rise = 0x2, - /// Counter advances with each falling edge of the PWM B pin. - fall = 0x3, - }, - }, - /// Retard the phase of the counter by 1 count, while it is running. - /// Self-clearing. Write a 1, and poll until low. Counter must be running. - PH_RET: u1, - /// Advance the phase of the counter by 1 count, while it is running. - /// Self-clearing. Write a 1, and poll until low. Counter must be running - /// at less than full speed (div_int + div_frac / 16 > 1) - PH_ADV: u1, - padding: u24, - }), - /// INT and FRAC form a fixed-point fractional number. - /// Counting rate is system clock frequency divided by this number. - /// Fractional division uses simple 1st-order sigma-delta. - CH0_DIV: mmio.Mmio(packed struct(u32) { - FRAC: u4, - INT: u8, - padding: u20, - }), - /// Direct access to the PWM counter - CH0_CTR: mmio.Mmio(packed struct(u32) { - CH0_CTR: u16, - padding: u16, - }), - /// Counter compare values - CH0_CC: mmio.Mmio(packed struct(u32) { - A: u16, - B: u16, - }), - /// Counter wrap value - CH0_TOP: mmio.Mmio(packed struct(u32) { - CH0_TOP: u16, - padding: u16, - }), - /// Control and status register - CH1_CSR: mmio.Mmio(packed struct(u32) { - /// Enable the PWM channel. - EN: u1, - /// 1: Enable phase-correct modulation. 0: Trailing-edge - PH_CORRECT: u1, - /// Invert output A - A_INV: u1, - /// Invert output B - B_INV: u1, - DIVMODE: packed union { - raw: u2, - value: enum(u2) { - /// Free-running counting at rate dictated by fractional divider - div = 0x0, - /// Fractional divider operation is gated by the PWM B pin. - level = 0x1, - /// Counter advances with each rising edge of the PWM B pin. - rise = 0x2, - /// Counter advances with each falling edge of the PWM B pin. - fall = 0x3, - }, - }, - /// Retard the phase of the counter by 1 count, while it is running. - /// Self-clearing. Write a 1, and poll until low. Counter must be running. - PH_RET: u1, - /// Advance the phase of the counter by 1 count, while it is running. - /// Self-clearing. Write a 1, and poll until low. Counter must be running - /// at less than full speed (div_int + div_frac / 16 > 1) - PH_ADV: u1, - padding: u24, - }), - /// INT and FRAC form a fixed-point fractional number. - /// Counting rate is system clock frequency divided by this number. - /// Fractional division uses simple 1st-order sigma-delta. - CH1_DIV: mmio.Mmio(packed struct(u32) { - FRAC: u4, - INT: u8, - padding: u20, - }), - /// Direct access to the PWM counter - CH1_CTR: mmio.Mmio(packed struct(u32) { - CH1_CTR: u16, - padding: u16, - }), - /// Counter compare values - CH1_CC: mmio.Mmio(packed struct(u32) { - A: u16, - B: u16, - }), - /// Counter wrap value - CH1_TOP: mmio.Mmio(packed struct(u32) { - CH1_TOP: u16, - padding: u16, - }), - /// Control and status register - CH2_CSR: mmio.Mmio(packed struct(u32) { - /// Enable the PWM channel. - EN: u1, - /// 1: Enable phase-correct modulation. 0: Trailing-edge - PH_CORRECT: u1, - /// Invert output A - A_INV: u1, - /// Invert output B - B_INV: u1, - DIVMODE: packed union { - raw: u2, - value: enum(u2) { - /// Free-running counting at rate dictated by fractional divider - div = 0x0, - /// Fractional divider operation is gated by the PWM B pin. - level = 0x1, - /// Counter advances with each rising edge of the PWM B pin. - rise = 0x2, - /// Counter advances with each falling edge of the PWM B pin. - fall = 0x3, - }, - }, - /// Retard the phase of the counter by 1 count, while it is running. - /// Self-clearing. Write a 1, and poll until low. Counter must be running. - PH_RET: u1, - /// Advance the phase of the counter by 1 count, while it is running. - /// Self-clearing. Write a 1, and poll until low. Counter must be running - /// at less than full speed (div_int + div_frac / 16 > 1) - PH_ADV: u1, - padding: u24, - }), - /// INT and FRAC form a fixed-point fractional number. - /// Counting rate is system clock frequency divided by this number. - /// Fractional division uses simple 1st-order sigma-delta. - CH2_DIV: mmio.Mmio(packed struct(u32) { - FRAC: u4, - INT: u8, - padding: u20, - }), - /// Direct access to the PWM counter - CH2_CTR: mmio.Mmio(packed struct(u32) { - CH2_CTR: u16, - padding: u16, - }), - /// Counter compare values - CH2_CC: mmio.Mmio(packed struct(u32) { - A: u16, - B: u16, - }), - /// Counter wrap value - CH2_TOP: mmio.Mmio(packed struct(u32) { - CH2_TOP: u16, - padding: u16, - }), - /// Control and status register - CH3_CSR: mmio.Mmio(packed struct(u32) { - /// Enable the PWM channel. - EN: u1, - /// 1: Enable phase-correct modulation. 0: Trailing-edge - PH_CORRECT: u1, - /// Invert output A - A_INV: u1, - /// Invert output B - B_INV: u1, - DIVMODE: packed union { - raw: u2, - value: enum(u2) { - /// Free-running counting at rate dictated by fractional divider - div = 0x0, - /// Fractional divider operation is gated by the PWM B pin. - level = 0x1, - /// Counter advances with each rising edge of the PWM B pin. - rise = 0x2, - /// Counter advances with each falling edge of the PWM B pin. - fall = 0x3, - }, - }, - /// Retard the phase of the counter by 1 count, while it is running. - /// Self-clearing. Write a 1, and poll until low. Counter must be running. - PH_RET: u1, - /// Advance the phase of the counter by 1 count, while it is running. - /// Self-clearing. Write a 1, and poll until low. Counter must be running - /// at less than full speed (div_int + div_frac / 16 > 1) - PH_ADV: u1, - padding: u24, - }), - /// INT and FRAC form a fixed-point fractional number. - /// Counting rate is system clock frequency divided by this number. - /// Fractional division uses simple 1st-order sigma-delta. - CH3_DIV: mmio.Mmio(packed struct(u32) { - FRAC: u4, - INT: u8, - padding: u20, - }), - /// Direct access to the PWM counter - CH3_CTR: mmio.Mmio(packed struct(u32) { - CH3_CTR: u16, - padding: u16, - }), - /// Counter compare values - CH3_CC: mmio.Mmio(packed struct(u32) { - A: u16, - B: u16, - }), - /// Counter wrap value - CH3_TOP: mmio.Mmio(packed struct(u32) { - CH3_TOP: u16, - padding: u16, - }), - /// Control and status register - CH4_CSR: mmio.Mmio(packed struct(u32) { - /// Enable the PWM channel. - EN: u1, - /// 1: Enable phase-correct modulation. 0: Trailing-edge - PH_CORRECT: u1, - /// Invert output A - A_INV: u1, - /// Invert output B - B_INV: u1, - DIVMODE: packed union { - raw: u2, - value: enum(u2) { - /// Free-running counting at rate dictated by fractional divider - div = 0x0, - /// Fractional divider operation is gated by the PWM B pin. - level = 0x1, - /// Counter advances with each rising edge of the PWM B pin. - rise = 0x2, - /// Counter advances with each falling edge of the PWM B pin. - fall = 0x3, - }, - }, - /// Retard the phase of the counter by 1 count, while it is running. - /// Self-clearing. Write a 1, and poll until low. Counter must be running. - PH_RET: u1, - /// Advance the phase of the counter by 1 count, while it is running. - /// Self-clearing. Write a 1, and poll until low. Counter must be running - /// at less than full speed (div_int + div_frac / 16 > 1) - PH_ADV: u1, - padding: u24, - }), - /// INT and FRAC form a fixed-point fractional number. - /// Counting rate is system clock frequency divided by this number. - /// Fractional division uses simple 1st-order sigma-delta. - CH4_DIV: mmio.Mmio(packed struct(u32) { - FRAC: u4, - INT: u8, - padding: u20, - }), - /// Direct access to the PWM counter - CH4_CTR: mmio.Mmio(packed struct(u32) { - CH4_CTR: u16, - padding: u16, - }), - /// Counter compare values - CH4_CC: mmio.Mmio(packed struct(u32) { - A: u16, - B: u16, - }), - /// Counter wrap value - CH4_TOP: mmio.Mmio(packed struct(u32) { - CH4_TOP: u16, - padding: u16, - }), - /// Control and status register - CH5_CSR: mmio.Mmio(packed struct(u32) { - /// Enable the PWM channel. - EN: u1, - /// 1: Enable phase-correct modulation. 0: Trailing-edge - PH_CORRECT: u1, - /// Invert output A - A_INV: u1, - /// Invert output B - B_INV: u1, - DIVMODE: packed union { - raw: u2, - value: enum(u2) { - /// Free-running counting at rate dictated by fractional divider - div = 0x0, - /// Fractional divider operation is gated by the PWM B pin. - level = 0x1, - /// Counter advances with each rising edge of the PWM B pin. - rise = 0x2, - /// Counter advances with each falling edge of the PWM B pin. - fall = 0x3, - }, - }, - /// Retard the phase of the counter by 1 count, while it is running. - /// Self-clearing. Write a 1, and poll until low. Counter must be running. - PH_RET: u1, - /// Advance the phase of the counter by 1 count, while it is running. - /// Self-clearing. Write a 1, and poll until low. Counter must be running - /// at less than full speed (div_int + div_frac / 16 > 1) - PH_ADV: u1, - padding: u24, - }), - /// INT and FRAC form a fixed-point fractional number. - /// Counting rate is system clock frequency divided by this number. - /// Fractional division uses simple 1st-order sigma-delta. - CH5_DIV: mmio.Mmio(packed struct(u32) { - FRAC: u4, - INT: u8, - padding: u20, - }), - /// Direct access to the PWM counter - CH5_CTR: mmio.Mmio(packed struct(u32) { - CH5_CTR: u16, - padding: u16, - }), - /// Counter compare values - CH5_CC: mmio.Mmio(packed struct(u32) { - A: u16, - B: u16, - }), - /// Counter wrap value - CH5_TOP: mmio.Mmio(packed struct(u32) { - CH5_TOP: u16, - padding: u16, - }), - /// Control and status register - CH6_CSR: mmio.Mmio(packed struct(u32) { - /// Enable the PWM channel. - EN: u1, - /// 1: Enable phase-correct modulation. 0: Trailing-edge - PH_CORRECT: u1, - /// Invert output A - A_INV: u1, - /// Invert output B - B_INV: u1, - DIVMODE: packed union { - raw: u2, - value: enum(u2) { - /// Free-running counting at rate dictated by fractional divider - div = 0x0, - /// Fractional divider operation is gated by the PWM B pin. - level = 0x1, - /// Counter advances with each rising edge of the PWM B pin. - rise = 0x2, - /// Counter advances with each falling edge of the PWM B pin. - fall = 0x3, - }, - }, - /// Retard the phase of the counter by 1 count, while it is running. - /// Self-clearing. Write a 1, and poll until low. Counter must be running. - PH_RET: u1, - /// Advance the phase of the counter by 1 count, while it is running. - /// Self-clearing. Write a 1, and poll until low. Counter must be running - /// at less than full speed (div_int + div_frac / 16 > 1) - PH_ADV: u1, - padding: u24, - }), - /// INT and FRAC form a fixed-point fractional number. - /// Counting rate is system clock frequency divided by this number. - /// Fractional division uses simple 1st-order sigma-delta. - CH6_DIV: mmio.Mmio(packed struct(u32) { - FRAC: u4, - INT: u8, - padding: u20, - }), - /// Direct access to the PWM counter - CH6_CTR: mmio.Mmio(packed struct(u32) { - CH6_CTR: u16, - padding: u16, - }), - /// Counter compare values - CH6_CC: mmio.Mmio(packed struct(u32) { - A: u16, - B: u16, - }), - /// Counter wrap value - CH6_TOP: mmio.Mmio(packed struct(u32) { - CH6_TOP: u16, - padding: u16, - }), - /// Control and status register - CH7_CSR: mmio.Mmio(packed struct(u32) { - /// Enable the PWM channel. - EN: u1, - /// 1: Enable phase-correct modulation. 0: Trailing-edge - PH_CORRECT: u1, - /// Invert output A - A_INV: u1, - /// Invert output B - B_INV: u1, - DIVMODE: packed union { - raw: u2, - value: enum(u2) { - /// Free-running counting at rate dictated by fractional divider - div = 0x0, - /// Fractional divider operation is gated by the PWM B pin. - level = 0x1, - /// Counter advances with each rising edge of the PWM B pin. - rise = 0x2, - /// Counter advances with each falling edge of the PWM B pin. - fall = 0x3, - }, - }, - /// Retard the phase of the counter by 1 count, while it is running. - /// Self-clearing. Write a 1, and poll until low. Counter must be running. - PH_RET: u1, - /// Advance the phase of the counter by 1 count, while it is running. - /// Self-clearing. Write a 1, and poll until low. Counter must be running - /// at less than full speed (div_int + div_frac / 16 > 1) - PH_ADV: u1, - padding: u24, - }), - /// INT and FRAC form a fixed-point fractional number. - /// Counting rate is system clock frequency divided by this number. - /// Fractional division uses simple 1st-order sigma-delta. - CH7_DIV: mmio.Mmio(packed struct(u32) { - FRAC: u4, - INT: u8, - padding: u20, - }), - /// Direct access to the PWM counter - CH7_CTR: mmio.Mmio(packed struct(u32) { - CH7_CTR: u16, - padding: u16, - }), - /// Counter compare values - CH7_CC: mmio.Mmio(packed struct(u32) { - A: u16, - B: u16, - }), - /// Counter wrap value - CH7_TOP: mmio.Mmio(packed struct(u32) { - CH7_TOP: u16, - padding: u16, - }), - /// This register aliases the CSR_EN bits for all channels. - /// Writing to this register allows multiple channels to be enabled - /// or disabled simultaneously, so they can run in perfect sync. - /// For each channel, there is only one physical EN register bit, - /// which can be accessed through here or CHx_CSR. - EN: mmio.Mmio(packed struct(u32) { - CH0: u1, - CH1: u1, - CH2: u1, - CH3: u1, - CH4: u1, - CH5: u1, - CH6: u1, - CH7: u1, - padding: u24, - }), - /// Raw Interrupts - INTR: mmio.Mmio(packed struct(u32) { - CH0: u1, - CH1: u1, - CH2: u1, - CH3: u1, - CH4: u1, - CH5: u1, - CH6: u1, - CH7: u1, - padding: u24, - }), - /// Interrupt Enable - INTE: mmio.Mmio(packed struct(u32) { - CH0: u1, - CH1: u1, - CH2: u1, - CH3: u1, - CH4: u1, - CH5: u1, - CH6: u1, - CH7: u1, - padding: u24, - }), - /// Interrupt Force - INTF: mmio.Mmio(packed struct(u32) { - CH0: u1, - CH1: u1, - CH2: u1, - CH3: u1, - CH4: u1, - CH5: u1, - CH6: u1, - CH7: u1, - padding: u24, - }), - /// Interrupt status after masking & forcing - INTS: mmio.Mmio(packed struct(u32) { - CH0: u1, - CH1: u1, - CH2: u1, - CH3: u1, - CH4: u1, - CH5: u1, - CH6: u1, - CH7: u1, - padding: u24, - }), - }; - - /// Controls time and alarms - /// time is a 64 bit value indicating the time in usec since power-on - /// timeh is the top 32 bits of time & timel is the bottom 32 bits - /// to change time write to timelw before timehw - /// to read time read from timelr before timehr - /// An alarm is set by setting alarm_enable and writing to the corresponding alarm register - /// When an alarm is pending, the corresponding alarm_running signal will be high - /// An alarm can be cancelled before it has finished by clearing the alarm_enable - /// When an alarm fires, the corresponding alarm_irq is set and alarm_running is cleared - /// To clear the interrupt write a 1 to the corresponding alarm_irq - pub const TIMER = extern struct { - /// Write to bits 63:32 of time - /// always write timelw before timehw - TIMEHW: u32, - /// Write to bits 31:0 of time - /// writes do not get copied to time until timehw is written - TIMELW: u32, - /// Read from bits 63:32 of time - /// always read timelr before timehr - TIMEHR: u32, - /// Read from bits 31:0 of time - TIMELR: u32, - /// Arm alarm 0, and configure the time it will fire. - /// Once armed, the alarm fires when TIMER_ALARM0 == TIMELR. - /// The alarm will disarm itself once it fires, and can - /// be disarmed early using the ARMED status register. - ALARM0: u32, - /// Arm alarm 1, and configure the time it will fire. - /// Once armed, the alarm fires when TIMER_ALARM1 == TIMELR. - /// The alarm will disarm itself once it fires, and can - /// be disarmed early using the ARMED status register. - ALARM1: u32, - /// Arm alarm 2, and configure the time it will fire. - /// Once armed, the alarm fires when TIMER_ALARM2 == TIMELR. - /// The alarm will disarm itself once it fires, and can - /// be disarmed early using the ARMED status register. - ALARM2: u32, - /// Arm alarm 3, and configure the time it will fire. - /// Once armed, the alarm fires when TIMER_ALARM3 == TIMELR. - /// The alarm will disarm itself once it fires, and can - /// be disarmed early using the ARMED status register. - ALARM3: u32, - /// Indicates the armed/disarmed status of each alarm. - /// A write to the corresponding ALARMx register arms the alarm. - /// Alarms automatically disarm upon firing, but writing ones here - /// will disarm immediately without waiting to fire. - ARMED: mmio.Mmio(packed struct(u32) { - ARMED: u4, - padding: u28, - }), - /// Raw read from bits 63:32 of time (no side effects) - TIMERAWH: u32, - /// Raw read from bits 31:0 of time (no side effects) - TIMERAWL: u32, - /// Set bits high to enable pause when the corresponding debug ports are active - DBGPAUSE: mmio.Mmio(packed struct(u32) { - reserved1: u1, - /// Pause when processor 0 is in debug mode - DBG0: u1, - /// Pause when processor 1 is in debug mode - DBG1: u1, - padding: u29, - }), - /// Set high to pause the timer - PAUSE: mmio.Mmio(packed struct(u32) { - PAUSE: u1, - padding: u31, - }), - /// Raw Interrupts - INTR: mmio.Mmio(packed struct(u32) { - ALARM_0: u1, - ALARM_1: u1, - ALARM_2: u1, - ALARM_3: u1, - padding: u28, - }), - /// Interrupt Enable - INTE: mmio.Mmio(packed struct(u32) { - ALARM_0: u1, - ALARM_1: u1, - ALARM_2: u1, - ALARM_3: u1, - padding: u28, - }), - /// Interrupt Force - INTF: mmio.Mmio(packed struct(u32) { - ALARM_0: u1, - ALARM_1: u1, - ALARM_2: u1, - ALARM_3: u1, - padding: u28, - }), - /// Interrupt status after masking & forcing - INTS: mmio.Mmio(packed struct(u32) { - ALARM_0: u1, - ALARM_1: u1, - ALARM_2: u1, - ALARM_3: u1, - padding: u28, - }), - }; - - pub const WATCHDOG = extern struct { - /// Watchdog control - /// The rst_wdsel register determines which subsystems are reset when the watchdog is triggered. - /// The watchdog can be triggered in software. - CTRL: mmio.Mmio(packed struct(u32) { - /// Indicates the number of ticks / 2 (see errata RP2040-E1) before a watchdog reset will be triggered - TIME: u24, - /// Pause the watchdog timer when JTAG is accessing the bus fabric - PAUSE_JTAG: u1, - /// Pause the watchdog timer when processor 0 is in debug mode - PAUSE_DBG0: u1, - /// Pause the watchdog timer when processor 1 is in debug mode - PAUSE_DBG1: u1, - reserved30: u3, - /// When not enabled the watchdog timer is paused - ENABLE: u1, - /// Trigger a watchdog reset - TRIGGER: u1, - }), - /// Load the watchdog timer. The maximum setting is 0xffffff which corresponds to 0xffffff / 2 ticks before triggering a watchdog reset (see errata RP2040-E1). - LOAD: mmio.Mmio(packed struct(u32) { - LOAD: u24, - padding: u8, - }), - /// Logs the reason for the last reset. Both bits are zero for the case of a hardware reset. - REASON: mmio.Mmio(packed struct(u32) { - TIMER: u1, - FORCE: u1, - padding: u30, - }), - /// Scratch register. Information persists through soft reset of the chip. - SCRATCH0: u32, - /// Scratch register. Information persists through soft reset of the chip. - SCRATCH1: u32, - /// Scratch register. Information persists through soft reset of the chip. - SCRATCH2: u32, - /// Scratch register. Information persists through soft reset of the chip. - SCRATCH3: u32, - /// Scratch register. Information persists through soft reset of the chip. - SCRATCH4: u32, - /// Scratch register. Information persists through soft reset of the chip. - SCRATCH5: u32, - /// Scratch register. Information persists through soft reset of the chip. - SCRATCH6: u32, - /// Scratch register. Information persists through soft reset of the chip. - SCRATCH7: u32, - /// Controls the tick generator - TICK: mmio.Mmio(packed struct(u32) { - /// Total number of clk_tick cycles before the next tick. - CYCLES: u9, - /// start / stop tick generation - ENABLE: u1, - /// Is the tick generator running? - RUNNING: u1, - /// Count down timer: the remaining number clk_tick cycles before the next tick is generated. - COUNT: u9, - padding: u12, - }), - }; - - /// Register block to control RTC - pub const RTC = extern struct { - /// Divider minus 1 for the 1 second counter. Safe to change the value when RTC is not enabled. - CLKDIV_M1: mmio.Mmio(packed struct(u32) { - CLKDIV_M1: u16, - padding: u16, - }), - /// RTC setup register 0 - SETUP_0: mmio.Mmio(packed struct(u32) { - /// Day of the month (1..31) - DAY: u5, - reserved8: u3, - /// Month (1..12) - MONTH: u4, - /// Year - YEAR: u12, - padding: u8, - }), - /// RTC setup register 1 - SETUP_1: mmio.Mmio(packed struct(u32) { - /// Seconds - SEC: u6, - reserved8: u2, - /// Minutes - MIN: u6, - reserved16: u2, - /// Hours - HOUR: u5, - reserved24: u3, - /// Day of the week: 1-Monday...0-Sunday ISO 8601 mod 7 - DOTW: u3, - padding: u5, - }), - /// RTC Control and status - CTRL: mmio.Mmio(packed struct(u32) { - /// Enable RTC - RTC_ENABLE: u1, - /// RTC enabled (running) - RTC_ACTIVE: u1, - reserved4: u2, - /// Load RTC - LOAD: u1, - reserved8: u3, - /// If set, leapyear is forced off. - /// Useful for years divisible by 100 but not by 400 - FORCE_NOTLEAPYEAR: u1, - padding: u23, - }), - /// Interrupt setup register 0 - IRQ_SETUP_0: mmio.Mmio(packed struct(u32) { - /// Day of the month (1..31) - DAY: u5, - reserved8: u3, - /// Month (1..12) - MONTH: u4, - /// Year - YEAR: u12, - /// Enable day matching - DAY_ENA: u1, - /// Enable month matching - MONTH_ENA: u1, - /// Enable year matching - YEAR_ENA: u1, - reserved28: u1, - /// Global match enable. Don't change any other value while this one is enabled - MATCH_ENA: u1, - MATCH_ACTIVE: u1, - padding: u2, - }), - /// Interrupt setup register 1 - IRQ_SETUP_1: mmio.Mmio(packed struct(u32) { - /// Seconds - SEC: u6, - reserved8: u2, - /// Minutes - MIN: u6, - reserved16: u2, - /// Hours - HOUR: u5, - reserved24: u3, - /// Day of the week - DOTW: u3, - reserved28: u1, - /// Enable second matching - SEC_ENA: u1, - /// Enable minute matching - MIN_ENA: u1, - /// Enable hour matching - HOUR_ENA: u1, - /// Enable day of the week matching - DOTW_ENA: u1, - }), - /// RTC register 1. - RTC_1: mmio.Mmio(packed struct(u32) { - /// Day of the month (1..31) - DAY: u5, - reserved8: u3, - /// Month (1..12) - MONTH: u4, - /// Year - YEAR: u12, - padding: u8, - }), - /// RTC register 0 - /// Read this before RTC 1! - RTC_0: mmio.Mmio(packed struct(u32) { - /// Seconds - SEC: u6, - reserved8: u2, - /// Minutes - MIN: u6, - reserved16: u2, - /// Hours - HOUR: u5, - reserved24: u3, - /// Day of the week - DOTW: u3, - padding: u5, - }), - /// Raw Interrupts - INTR: mmio.Mmio(packed struct(u32) { - RTC: u1, - padding: u31, - }), - /// Interrupt Enable - INTE: mmio.Mmio(packed struct(u32) { - RTC: u1, - padding: u31, - }), - /// Interrupt Force - INTF: mmio.Mmio(packed struct(u32) { - RTC: u1, - padding: u31, - }), - /// Interrupt status after masking & forcing - INTS: mmio.Mmio(packed struct(u32) { - RTC: u1, - padding: u31, - }), - }; - - pub const ROSC = extern struct { - /// Ring Oscillator control - CTRL: mmio.Mmio(packed struct(u32) { - /// Controls the number of delay stages in the ROSC ring - /// LOW uses stages 0 to 7 - /// MEDIUM uses stages 0 to 5 - /// HIGH uses stages 0 to 3 - /// TOOHIGH uses stages 0 to 1 and should not be used because its frequency exceeds design specifications - /// The clock output will not glitch when changing the range up one step at a time - /// The clock output will glitch when changing the range down - /// Note: the values here are gray coded which is why HIGH comes before TOOHIGH - FREQ_RANGE: packed union { - raw: u12, - value: enum(u12) { - LOW = 0xfa4, - MEDIUM = 0xfa5, - HIGH = 0xfa7, - TOOHIGH = 0xfa6, - _, - }, - }, - /// On power-up this field is initialised to ENABLE - /// The system clock must be switched to another source before setting this field to DISABLE otherwise the chip will lock up - /// The 12-bit code is intended to give some protection against accidental writes. An invalid setting will enable the oscillator. - ENABLE: packed union { - raw: u12, - value: enum(u12) { - DISABLE = 0xd1e, - ENABLE = 0xfab, - _, - }, - }, - padding: u8, - }), - /// The FREQA & FREQB registers control the frequency by controlling the drive strength of each stage - /// The drive strength has 4 levels determined by the number of bits set - /// Increasing the number of bits set increases the drive strength and increases the oscillation frequency - /// 0 bits set is the default drive strength - /// 1 bit set doubles the drive strength - /// 2 bits set triples drive strength - /// 3 bits set quadruples drive strength - FREQA: mmio.Mmio(packed struct(u32) { - /// Stage 0 drive strength - DS0: u3, - reserved4: u1, - /// Stage 1 drive strength - DS1: u3, - reserved8: u1, - /// Stage 2 drive strength - DS2: u3, - reserved12: u1, - /// Stage 3 drive strength - DS3: u3, - reserved16: u1, - /// Set to 0x9696 to apply the settings - /// Any other value in this field will set all drive strengths to 0 - PASSWD: packed union { - raw: u16, - value: enum(u16) { - PASS = 0x9696, - _, - }, - }, - }), - /// For a detailed description see freqa register - FREQB: mmio.Mmio(packed struct(u32) { - /// Stage 4 drive strength - DS4: u3, - reserved4: u1, - /// Stage 5 drive strength - DS5: u3, - reserved8: u1, - /// Stage 6 drive strength - DS6: u3, - reserved12: u1, - /// Stage 7 drive strength - DS7: u3, - reserved16: u1, - /// Set to 0x9696 to apply the settings - /// Any other value in this field will set all drive strengths to 0 - PASSWD: packed union { - raw: u16, - value: enum(u16) { - PASS = 0x9696, - _, - }, - }, - }), - /// Ring Oscillator pause control - /// This is used to save power by pausing the ROSC - /// On power-up this field is initialised to WAKE - /// An invalid write will also select WAKE - /// Warning: setup the irq before selecting dormant mode - DORMANT: u32, - /// Controls the output divider - DIV: mmio.Mmio(packed struct(u32) { - /// set to 0xaa0 + div where - /// div = 0 divides by 32 - /// div = 1-31 divides by div - /// any other value sets div=31 - /// this register resets to div=16 - DIV: packed union { - raw: u12, - value: enum(u12) { - PASS = 0xaa0, - _, - }, - }, - padding: u20, - }), - /// Controls the phase shifted output - PHASE: mmio.Mmio(packed struct(u32) { - /// phase shift the phase-shifted output by SHIFT input clocks - /// this can be changed on-the-fly - /// must be set to 0 before setting div=1 - SHIFT: u2, - /// invert the phase-shifted output - /// this is ignored when div=1 - FLIP: u1, - /// enable the phase-shifted output - /// this can be changed on-the-fly - ENABLE: u1, - /// set to 0xaa - /// any other value enables the output with shift=0 - PASSWD: u8, - padding: u20, - }), - /// Ring Oscillator Status - STATUS: mmio.Mmio(packed struct(u32) { - reserved12: u12, - /// Oscillator is enabled but not necessarily running and stable - /// this resets to 0 but transitions to 1 during chip startup - ENABLED: u1, - reserved16: u3, - /// post-divider is running - /// this resets to 0 but transitions to 1 during chip startup - DIV_RUNNING: u1, - reserved24: u7, - /// An invalid value has been written to CTRL_ENABLE or CTRL_FREQ_RANGE or FREQA or FREQB or DIV or PHASE or DORMANT - BADWRITE: u1, - reserved31: u6, - /// Oscillator is running and stable - STABLE: u1, - }), - /// This just reads the state of the oscillator output so randomness is compromised if the ring oscillator is stopped or run at a harmonic of the bus frequency - RANDOMBIT: mmio.Mmio(packed struct(u32) { - RANDOMBIT: u1, - padding: u31, - }), - /// A down counter running at the ROSC frequency which counts to zero and stops. - /// To start the counter write a non-zero value. - /// Can be used for short software pauses when setting up time sensitive hardware. - COUNT: mmio.Mmio(packed struct(u32) { - COUNT: u8, - padding: u24, - }), - }; - - /// control and status for on-chip voltage regulator and chip level reset subsystem - pub const VREG_AND_CHIP_RESET = extern struct { - /// Voltage regulator control and status - VREG: mmio.Mmio(packed struct(u32) { - /// enable - /// 0=not enabled, 1=enabled - EN: u1, - /// high impedance mode select - /// 0=not in high impedance mode, 1=in high impedance mode - HIZ: u1, - reserved4: u2, - /// output voltage select - /// 0000 to 0101 - 0.80V - /// 0110 - 0.85V - /// 0111 - 0.90V - /// 1000 - 0.95V - /// 1001 - 1.00V - /// 1010 - 1.05V - /// 1011 - 1.10V (default) - /// 1100 - 1.15V - /// 1101 - 1.20V - /// 1110 - 1.25V - /// 1111 - 1.30V - VSEL: u4, - reserved12: u4, - /// regulation status - /// 0=not in regulation, 1=in regulation - ROK: u1, - padding: u19, - }), - /// brown-out detection control - BOD: mmio.Mmio(packed struct(u32) { - /// enable - /// 0=not enabled, 1=enabled - EN: u1, - reserved4: u3, - /// threshold select - /// 0000 - 0.473V - /// 0001 - 0.516V - /// 0010 - 0.559V - /// 0011 - 0.602V - /// 0100 - 0.645V - /// 0101 - 0.688V - /// 0110 - 0.731V - /// 0111 - 0.774V - /// 1000 - 0.817V - /// 1001 - 0.860V (default) - /// 1010 - 0.903V - /// 1011 - 0.946V - /// 1100 - 0.989V - /// 1101 - 1.032V - /// 1110 - 1.075V - /// 1111 - 1.118V - VSEL: u4, - padding: u24, - }), - /// Chip reset control and status - CHIP_RESET: mmio.Mmio(packed struct(u32) { - reserved8: u8, - /// Last reset was from the power-on reset or brown-out detection blocks - HAD_POR: u1, - reserved16: u7, - /// Last reset was from the RUN pin - HAD_RUN: u1, - reserved20: u3, - /// Last reset was from the debug port - HAD_PSM_RESTART: u1, - reserved24: u3, - /// This is set by psm_restart from the debugger. - /// Its purpose is to branch bootcode to a safe mode when the debugger has issued a psm_restart in order to recover from a boot lock-up. - /// In the safe mode the debugger can repair the boot code, clear this flag then reboot the processor. - PSM_RESTART_FLAG: u1, - padding: u7, - }), - }; - - /// Testbench manager. Allows the programmer to know what platform their software is running on. - pub const TBMAN = extern struct { - /// Indicates the type of platform in use - PLATFORM: mmio.Mmio(packed struct(u32) { - /// Indicates the platform is an ASIC - ASIC: u1, - /// Indicates the platform is an FPGA - FPGA: u1, - padding: u30, - }), - }; - - /// DMA with separate read and write masters - pub const DMA = extern struct { - /// DMA Channel 0 Read Address pointer - /// This register updates automatically each time a read completes. The current value is the next address to be read by this channel. - CH0_READ_ADDR: u32, - /// DMA Channel 0 Write Address pointer - /// This register updates automatically each time a write completes. The current value is the next address to be written by this channel. - CH0_WRITE_ADDR: u32, - /// DMA Channel 0 Transfer Count - /// Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). - /// When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. - /// Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. - /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. - CH0_TRANS_COUNT: u32, - /// DMA Channel 0 Control and Status - CH0_CTRL_TRIG: mmio.Mmio(packed struct(u32) { - /// DMA Channel Enable. - /// When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) - EN: u1, - /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. - /// This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. - HIGH_PRIORITY: u1, - /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. - DATA_SIZE: packed union { - raw: u2, - value: enum(u2) { - SIZE_BYTE = 0x0, - SIZE_HALFWORD = 0x1, - SIZE_WORD = 0x2, - _, - }, - }, - /// If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. - /// Generally this should be disabled for peripheral-to-memory transfers. - INCR_READ: u1, - /// If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. - /// Generally this should be disabled for memory-to-peripheral transfers. - INCR_WRITE: u1, - /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. - /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. - RING_SIZE: packed union { - raw: u4, - value: enum(u4) { - RING_NONE = 0x0, - _, - }, - }, - /// Select whether RING_SIZE applies to read or write addresses. - /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. - RING_SEL: u1, - /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. - CHAIN_TO: u4, - /// Select a Transfer Request signal. - /// The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). - /// 0x0 to 0x3a -> select DREQ n as TREQ - TREQ_SEL: packed union { - raw: u6, - value: enum(u6) { - /// Select Timer 0 as TREQ - TIMER0 = 0x3b, - /// Select Timer 1 as TREQ - TIMER1 = 0x3c, - /// Select Timer 2 as TREQ (Optional) - TIMER2 = 0x3d, - /// Select Timer 3 as TREQ (Optional) - TIMER3 = 0x3e, - /// Permanent request, for unpaced transfers. - PERMANENT = 0x3f, - _, - }, - }, - /// In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. - /// This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. - IRQ_QUIET: u1, - /// Apply byte-swap transformation to DMA data. - /// For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. - BSWAP: u1, - /// If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. - /// This allows checksum to be enabled or disabled on a per-control- block basis. - SNIFF_EN: u1, - /// This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. - /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. - BUSY: u1, - reserved29: u4, - /// If 1, the channel received a write bus error. Write one to clear. - /// WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later) - WRITE_ERROR: u1, - /// If 1, the channel received a read bus error. Write one to clear. - /// READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later) - READ_ERROR: u1, - /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. - AHB_ERROR: u1, - }), - /// Alias for channel 0 CTRL register - CH0_AL1_CTRL: u32, - /// Alias for channel 0 READ_ADDR register - CH0_AL1_READ_ADDR: u32, - /// Alias for channel 0 WRITE_ADDR register - CH0_AL1_WRITE_ADDR: u32, - /// Alias for channel 0 TRANS_COUNT register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH0_AL1_TRANS_COUNT_TRIG: u32, - /// Alias for channel 0 CTRL register - CH0_AL2_CTRL: u32, - /// Alias for channel 0 TRANS_COUNT register - CH0_AL2_TRANS_COUNT: u32, - /// Alias for channel 0 READ_ADDR register - CH0_AL2_READ_ADDR: u32, - /// Alias for channel 0 WRITE_ADDR register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH0_AL2_WRITE_ADDR_TRIG: u32, - /// Alias for channel 0 CTRL register - CH0_AL3_CTRL: u32, - /// Alias for channel 0 WRITE_ADDR register - CH0_AL3_WRITE_ADDR: u32, - /// Alias for channel 0 TRANS_COUNT register - CH0_AL3_TRANS_COUNT: u32, - /// Alias for channel 0 READ_ADDR register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH0_AL3_READ_ADDR_TRIG: u32, - /// DMA Channel 1 Read Address pointer - /// This register updates automatically each time a read completes. The current value is the next address to be read by this channel. - CH1_READ_ADDR: u32, - /// DMA Channel 1 Write Address pointer - /// This register updates automatically each time a write completes. The current value is the next address to be written by this channel. - CH1_WRITE_ADDR: u32, - /// DMA Channel 1 Transfer Count - /// Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). - /// When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. - /// Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. - /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. - CH1_TRANS_COUNT: u32, - /// DMA Channel 1 Control and Status - CH1_CTRL_TRIG: mmio.Mmio(packed struct(u32) { - /// DMA Channel Enable. - /// When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) - EN: u1, - /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. - /// This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. - HIGH_PRIORITY: u1, - /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. - DATA_SIZE: packed union { - raw: u2, - value: enum(u2) { - SIZE_BYTE = 0x0, - SIZE_HALFWORD = 0x1, - SIZE_WORD = 0x2, - _, - }, - }, - /// If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. - /// Generally this should be disabled for peripheral-to-memory transfers. - INCR_READ: u1, - /// If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. - /// Generally this should be disabled for memory-to-peripheral transfers. - INCR_WRITE: u1, - /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. - /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. - RING_SIZE: packed union { - raw: u4, - value: enum(u4) { - RING_NONE = 0x0, - _, - }, - }, - /// Select whether RING_SIZE applies to read or write addresses. - /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. - RING_SEL: u1, - /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. - CHAIN_TO: u4, - /// Select a Transfer Request signal. - /// The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). - /// 0x0 to 0x3a -> select DREQ n as TREQ - TREQ_SEL: packed union { - raw: u6, - value: enum(u6) { - /// Select Timer 0 as TREQ - TIMER0 = 0x3b, - /// Select Timer 1 as TREQ - TIMER1 = 0x3c, - /// Select Timer 2 as TREQ (Optional) - TIMER2 = 0x3d, - /// Select Timer 3 as TREQ (Optional) - TIMER3 = 0x3e, - /// Permanent request, for unpaced transfers. - PERMANENT = 0x3f, - _, - }, - }, - /// In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. - /// This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. - IRQ_QUIET: u1, - /// Apply byte-swap transformation to DMA data. - /// For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. - BSWAP: u1, - /// If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. - /// This allows checksum to be enabled or disabled on a per-control- block basis. - SNIFF_EN: u1, - /// This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. - /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. - BUSY: u1, - reserved29: u4, - /// If 1, the channel received a write bus error. Write one to clear. - /// WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later) - WRITE_ERROR: u1, - /// If 1, the channel received a read bus error. Write one to clear. - /// READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later) - READ_ERROR: u1, - /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. - AHB_ERROR: u1, - }), - /// Alias for channel 1 CTRL register - CH1_AL1_CTRL: u32, - /// Alias for channel 1 READ_ADDR register - CH1_AL1_READ_ADDR: u32, - /// Alias for channel 1 WRITE_ADDR register - CH1_AL1_WRITE_ADDR: u32, - /// Alias for channel 1 TRANS_COUNT register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH1_AL1_TRANS_COUNT_TRIG: u32, - /// Alias for channel 1 CTRL register - CH1_AL2_CTRL: u32, - /// Alias for channel 1 TRANS_COUNT register - CH1_AL2_TRANS_COUNT: u32, - /// Alias for channel 1 READ_ADDR register - CH1_AL2_READ_ADDR: u32, - /// Alias for channel 1 WRITE_ADDR register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH1_AL2_WRITE_ADDR_TRIG: u32, - /// Alias for channel 1 CTRL register - CH1_AL3_CTRL: u32, - /// Alias for channel 1 WRITE_ADDR register - CH1_AL3_WRITE_ADDR: u32, - /// Alias for channel 1 TRANS_COUNT register - CH1_AL3_TRANS_COUNT: u32, - /// Alias for channel 1 READ_ADDR register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH1_AL3_READ_ADDR_TRIG: u32, - /// DMA Channel 2 Read Address pointer - /// This register updates automatically each time a read completes. The current value is the next address to be read by this channel. - CH2_READ_ADDR: u32, - /// DMA Channel 2 Write Address pointer - /// This register updates automatically each time a write completes. The current value is the next address to be written by this channel. - CH2_WRITE_ADDR: u32, - /// DMA Channel 2 Transfer Count - /// Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). - /// When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. - /// Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. - /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. - CH2_TRANS_COUNT: u32, - /// DMA Channel 2 Control and Status - CH2_CTRL_TRIG: mmio.Mmio(packed struct(u32) { - /// DMA Channel Enable. - /// When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) - EN: u1, - /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. - /// This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. - HIGH_PRIORITY: u1, - /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. - DATA_SIZE: packed union { - raw: u2, - value: enum(u2) { - SIZE_BYTE = 0x0, - SIZE_HALFWORD = 0x1, - SIZE_WORD = 0x2, - _, - }, - }, - /// If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. - /// Generally this should be disabled for peripheral-to-memory transfers. - INCR_READ: u1, - /// If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. - /// Generally this should be disabled for memory-to-peripheral transfers. - INCR_WRITE: u1, - /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. - /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. - RING_SIZE: packed union { - raw: u4, - value: enum(u4) { - RING_NONE = 0x0, - _, - }, - }, - /// Select whether RING_SIZE applies to read or write addresses. - /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. - RING_SEL: u1, - /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. - CHAIN_TO: u4, - /// Select a Transfer Request signal. - /// The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). - /// 0x0 to 0x3a -> select DREQ n as TREQ - TREQ_SEL: packed union { - raw: u6, - value: enum(u6) { - /// Select Timer 0 as TREQ - TIMER0 = 0x3b, - /// Select Timer 1 as TREQ - TIMER1 = 0x3c, - /// Select Timer 2 as TREQ (Optional) - TIMER2 = 0x3d, - /// Select Timer 3 as TREQ (Optional) - TIMER3 = 0x3e, - /// Permanent request, for unpaced transfers. - PERMANENT = 0x3f, - _, - }, - }, - /// In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. - /// This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. - IRQ_QUIET: u1, - /// Apply byte-swap transformation to DMA data. - /// For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. - BSWAP: u1, - /// If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. - /// This allows checksum to be enabled or disabled on a per-control- block basis. - SNIFF_EN: u1, - /// This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. - /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. - BUSY: u1, - reserved29: u4, - /// If 1, the channel received a write bus error. Write one to clear. - /// WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later) - WRITE_ERROR: u1, - /// If 1, the channel received a read bus error. Write one to clear. - /// READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later) - READ_ERROR: u1, - /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. - AHB_ERROR: u1, - }), - /// Alias for channel 2 CTRL register - CH2_AL1_CTRL: u32, - /// Alias for channel 2 READ_ADDR register - CH2_AL1_READ_ADDR: u32, - /// Alias for channel 2 WRITE_ADDR register - CH2_AL1_WRITE_ADDR: u32, - /// Alias for channel 2 TRANS_COUNT register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH2_AL1_TRANS_COUNT_TRIG: u32, - /// Alias for channel 2 CTRL register - CH2_AL2_CTRL: u32, - /// Alias for channel 2 TRANS_COUNT register - CH2_AL2_TRANS_COUNT: u32, - /// Alias for channel 2 READ_ADDR register - CH2_AL2_READ_ADDR: u32, - /// Alias for channel 2 WRITE_ADDR register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH2_AL2_WRITE_ADDR_TRIG: u32, - /// Alias for channel 2 CTRL register - CH2_AL3_CTRL: u32, - /// Alias for channel 2 WRITE_ADDR register - CH2_AL3_WRITE_ADDR: u32, - /// Alias for channel 2 TRANS_COUNT register - CH2_AL3_TRANS_COUNT: u32, - /// Alias for channel 2 READ_ADDR register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH2_AL3_READ_ADDR_TRIG: u32, - /// DMA Channel 3 Read Address pointer - /// This register updates automatically each time a read completes. The current value is the next address to be read by this channel. - CH3_READ_ADDR: u32, - /// DMA Channel 3 Write Address pointer - /// This register updates automatically each time a write completes. The current value is the next address to be written by this channel. - CH3_WRITE_ADDR: u32, - /// DMA Channel 3 Transfer Count - /// Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). - /// When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. - /// Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. - /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. - CH3_TRANS_COUNT: u32, - /// DMA Channel 3 Control and Status - CH3_CTRL_TRIG: mmio.Mmio(packed struct(u32) { - /// DMA Channel Enable. - /// When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) - EN: u1, - /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. - /// This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. - HIGH_PRIORITY: u1, - /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. - DATA_SIZE: packed union { - raw: u2, - value: enum(u2) { - SIZE_BYTE = 0x0, - SIZE_HALFWORD = 0x1, - SIZE_WORD = 0x2, - _, - }, - }, - /// If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. - /// Generally this should be disabled for peripheral-to-memory transfers. - INCR_READ: u1, - /// If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. - /// Generally this should be disabled for memory-to-peripheral transfers. - INCR_WRITE: u1, - /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. - /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. - RING_SIZE: packed union { - raw: u4, - value: enum(u4) { - RING_NONE = 0x0, - _, - }, - }, - /// Select whether RING_SIZE applies to read or write addresses. - /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. - RING_SEL: u1, - /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. - CHAIN_TO: u4, - /// Select a Transfer Request signal. - /// The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). - /// 0x0 to 0x3a -> select DREQ n as TREQ - TREQ_SEL: packed union { - raw: u6, - value: enum(u6) { - /// Select Timer 0 as TREQ - TIMER0 = 0x3b, - /// Select Timer 1 as TREQ - TIMER1 = 0x3c, - /// Select Timer 2 as TREQ (Optional) - TIMER2 = 0x3d, - /// Select Timer 3 as TREQ (Optional) - TIMER3 = 0x3e, - /// Permanent request, for unpaced transfers. - PERMANENT = 0x3f, - _, - }, - }, - /// In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. - /// This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. - IRQ_QUIET: u1, - /// Apply byte-swap transformation to DMA data. - /// For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. - BSWAP: u1, - /// If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. - /// This allows checksum to be enabled or disabled on a per-control- block basis. - SNIFF_EN: u1, - /// This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. - /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. - BUSY: u1, - reserved29: u4, - /// If 1, the channel received a write bus error. Write one to clear. - /// WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later) - WRITE_ERROR: u1, - /// If 1, the channel received a read bus error. Write one to clear. - /// READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later) - READ_ERROR: u1, - /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. - AHB_ERROR: u1, - }), - /// Alias for channel 3 CTRL register - CH3_AL1_CTRL: u32, - /// Alias for channel 3 READ_ADDR register - CH3_AL1_READ_ADDR: u32, - /// Alias for channel 3 WRITE_ADDR register - CH3_AL1_WRITE_ADDR: u32, - /// Alias for channel 3 TRANS_COUNT register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH3_AL1_TRANS_COUNT_TRIG: u32, - /// Alias for channel 3 CTRL register - CH3_AL2_CTRL: u32, - /// Alias for channel 3 TRANS_COUNT register - CH3_AL2_TRANS_COUNT: u32, - /// Alias for channel 3 READ_ADDR register - CH3_AL2_READ_ADDR: u32, - /// Alias for channel 3 WRITE_ADDR register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH3_AL2_WRITE_ADDR_TRIG: u32, - /// Alias for channel 3 CTRL register - CH3_AL3_CTRL: u32, - /// Alias for channel 3 WRITE_ADDR register - CH3_AL3_WRITE_ADDR: u32, - /// Alias for channel 3 TRANS_COUNT register - CH3_AL3_TRANS_COUNT: u32, - /// Alias for channel 3 READ_ADDR register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH3_AL3_READ_ADDR_TRIG: u32, - /// DMA Channel 4 Read Address pointer - /// This register updates automatically each time a read completes. The current value is the next address to be read by this channel. - CH4_READ_ADDR: u32, - /// DMA Channel 4 Write Address pointer - /// This register updates automatically each time a write completes. The current value is the next address to be written by this channel. - CH4_WRITE_ADDR: u32, - /// DMA Channel 4 Transfer Count - /// Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). - /// When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. - /// Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. - /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. - CH4_TRANS_COUNT: u32, - /// DMA Channel 4 Control and Status - CH4_CTRL_TRIG: mmio.Mmio(packed struct(u32) { - /// DMA Channel Enable. - /// When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) - EN: u1, - /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. - /// This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. - HIGH_PRIORITY: u1, - /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. - DATA_SIZE: packed union { - raw: u2, - value: enum(u2) { - SIZE_BYTE = 0x0, - SIZE_HALFWORD = 0x1, - SIZE_WORD = 0x2, - _, - }, - }, - /// If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. - /// Generally this should be disabled for peripheral-to-memory transfers. - INCR_READ: u1, - /// If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. - /// Generally this should be disabled for memory-to-peripheral transfers. - INCR_WRITE: u1, - /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. - /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. - RING_SIZE: packed union { - raw: u4, - value: enum(u4) { - RING_NONE = 0x0, - _, - }, - }, - /// Select whether RING_SIZE applies to read or write addresses. - /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. - RING_SEL: u1, - /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. - CHAIN_TO: u4, - /// Select a Transfer Request signal. - /// The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). - /// 0x0 to 0x3a -> select DREQ n as TREQ - TREQ_SEL: packed union { - raw: u6, - value: enum(u6) { - /// Select Timer 0 as TREQ - TIMER0 = 0x3b, - /// Select Timer 1 as TREQ - TIMER1 = 0x3c, - /// Select Timer 2 as TREQ (Optional) - TIMER2 = 0x3d, - /// Select Timer 3 as TREQ (Optional) - TIMER3 = 0x3e, - /// Permanent request, for unpaced transfers. - PERMANENT = 0x3f, - _, - }, - }, - /// In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. - /// This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. - IRQ_QUIET: u1, - /// Apply byte-swap transformation to DMA data. - /// For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. - BSWAP: u1, - /// If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. - /// This allows checksum to be enabled or disabled on a per-control- block basis. - SNIFF_EN: u1, - /// This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. - /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. - BUSY: u1, - reserved29: u4, - /// If 1, the channel received a write bus error. Write one to clear. - /// WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later) - WRITE_ERROR: u1, - /// If 1, the channel received a read bus error. Write one to clear. - /// READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later) - READ_ERROR: u1, - /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. - AHB_ERROR: u1, - }), - /// Alias for channel 4 CTRL register - CH4_AL1_CTRL: u32, - /// Alias for channel 4 READ_ADDR register - CH4_AL1_READ_ADDR: u32, - /// Alias for channel 4 WRITE_ADDR register - CH4_AL1_WRITE_ADDR: u32, - /// Alias for channel 4 TRANS_COUNT register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH4_AL1_TRANS_COUNT_TRIG: u32, - /// Alias for channel 4 CTRL register - CH4_AL2_CTRL: u32, - /// Alias for channel 4 TRANS_COUNT register - CH4_AL2_TRANS_COUNT: u32, - /// Alias for channel 4 READ_ADDR register - CH4_AL2_READ_ADDR: u32, - /// Alias for channel 4 WRITE_ADDR register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH4_AL2_WRITE_ADDR_TRIG: u32, - /// Alias for channel 4 CTRL register - CH4_AL3_CTRL: u32, - /// Alias for channel 4 WRITE_ADDR register - CH4_AL3_WRITE_ADDR: u32, - /// Alias for channel 4 TRANS_COUNT register - CH4_AL3_TRANS_COUNT: u32, - /// Alias for channel 4 READ_ADDR register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH4_AL3_READ_ADDR_TRIG: u32, - /// DMA Channel 5 Read Address pointer - /// This register updates automatically each time a read completes. The current value is the next address to be read by this channel. - CH5_READ_ADDR: u32, - /// DMA Channel 5 Write Address pointer - /// This register updates automatically each time a write completes. The current value is the next address to be written by this channel. - CH5_WRITE_ADDR: u32, - /// DMA Channel 5 Transfer Count - /// Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). - /// When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. - /// Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. - /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. - CH5_TRANS_COUNT: u32, - /// DMA Channel 5 Control and Status - CH5_CTRL_TRIG: mmio.Mmio(packed struct(u32) { - /// DMA Channel Enable. - /// When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) - EN: u1, - /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. - /// This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. - HIGH_PRIORITY: u1, - /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. - DATA_SIZE: packed union { - raw: u2, - value: enum(u2) { - SIZE_BYTE = 0x0, - SIZE_HALFWORD = 0x1, - SIZE_WORD = 0x2, - _, - }, - }, - /// If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. - /// Generally this should be disabled for peripheral-to-memory transfers. - INCR_READ: u1, - /// If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. - /// Generally this should be disabled for memory-to-peripheral transfers. - INCR_WRITE: u1, - /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. - /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. - RING_SIZE: packed union { - raw: u4, - value: enum(u4) { - RING_NONE = 0x0, - _, - }, - }, - /// Select whether RING_SIZE applies to read or write addresses. - /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. - RING_SEL: u1, - /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. - CHAIN_TO: u4, - /// Select a Transfer Request signal. - /// The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). - /// 0x0 to 0x3a -> select DREQ n as TREQ - TREQ_SEL: packed union { - raw: u6, - value: enum(u6) { - /// Select Timer 0 as TREQ - TIMER0 = 0x3b, - /// Select Timer 1 as TREQ - TIMER1 = 0x3c, - /// Select Timer 2 as TREQ (Optional) - TIMER2 = 0x3d, - /// Select Timer 3 as TREQ (Optional) - TIMER3 = 0x3e, - /// Permanent request, for unpaced transfers. - PERMANENT = 0x3f, - _, - }, - }, - /// In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. - /// This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. - IRQ_QUIET: u1, - /// Apply byte-swap transformation to DMA data. - /// For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. - BSWAP: u1, - /// If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. - /// This allows checksum to be enabled or disabled on a per-control- block basis. - SNIFF_EN: u1, - /// This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. - /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. - BUSY: u1, - reserved29: u4, - /// If 1, the channel received a write bus error. Write one to clear. - /// WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later) - WRITE_ERROR: u1, - /// If 1, the channel received a read bus error. Write one to clear. - /// READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later) - READ_ERROR: u1, - /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. - AHB_ERROR: u1, - }), - /// Alias for channel 5 CTRL register - CH5_AL1_CTRL: u32, - /// Alias for channel 5 READ_ADDR register - CH5_AL1_READ_ADDR: u32, - /// Alias for channel 5 WRITE_ADDR register - CH5_AL1_WRITE_ADDR: u32, - /// Alias for channel 5 TRANS_COUNT register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH5_AL1_TRANS_COUNT_TRIG: u32, - /// Alias for channel 5 CTRL register - CH5_AL2_CTRL: u32, - /// Alias for channel 5 TRANS_COUNT register - CH5_AL2_TRANS_COUNT: u32, - /// Alias for channel 5 READ_ADDR register - CH5_AL2_READ_ADDR: u32, - /// Alias for channel 5 WRITE_ADDR register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH5_AL2_WRITE_ADDR_TRIG: u32, - /// Alias for channel 5 CTRL register - CH5_AL3_CTRL: u32, - /// Alias for channel 5 WRITE_ADDR register - CH5_AL3_WRITE_ADDR: u32, - /// Alias for channel 5 TRANS_COUNT register - CH5_AL3_TRANS_COUNT: u32, - /// Alias for channel 5 READ_ADDR register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH5_AL3_READ_ADDR_TRIG: u32, - /// DMA Channel 6 Read Address pointer - /// This register updates automatically each time a read completes. The current value is the next address to be read by this channel. - CH6_READ_ADDR: u32, - /// DMA Channel 6 Write Address pointer - /// This register updates automatically each time a write completes. The current value is the next address to be written by this channel. - CH6_WRITE_ADDR: u32, - /// DMA Channel 6 Transfer Count - /// Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). - /// When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. - /// Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. - /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. - CH6_TRANS_COUNT: u32, - /// DMA Channel 6 Control and Status - CH6_CTRL_TRIG: mmio.Mmio(packed struct(u32) { - /// DMA Channel Enable. - /// When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) - EN: u1, - /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. - /// This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. - HIGH_PRIORITY: u1, - /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. - DATA_SIZE: packed union { - raw: u2, - value: enum(u2) { - SIZE_BYTE = 0x0, - SIZE_HALFWORD = 0x1, - SIZE_WORD = 0x2, - _, - }, - }, - /// If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. - /// Generally this should be disabled for peripheral-to-memory transfers. - INCR_READ: u1, - /// If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. - /// Generally this should be disabled for memory-to-peripheral transfers. - INCR_WRITE: u1, - /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. - /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. - RING_SIZE: packed union { - raw: u4, - value: enum(u4) { - RING_NONE = 0x0, - _, - }, - }, - /// Select whether RING_SIZE applies to read or write addresses. - /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. - RING_SEL: u1, - /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. - CHAIN_TO: u4, - /// Select a Transfer Request signal. - /// The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). - /// 0x0 to 0x3a -> select DREQ n as TREQ - TREQ_SEL: packed union { - raw: u6, - value: enum(u6) { - /// Select Timer 0 as TREQ - TIMER0 = 0x3b, - /// Select Timer 1 as TREQ - TIMER1 = 0x3c, - /// Select Timer 2 as TREQ (Optional) - TIMER2 = 0x3d, - /// Select Timer 3 as TREQ (Optional) - TIMER3 = 0x3e, - /// Permanent request, for unpaced transfers. - PERMANENT = 0x3f, - _, - }, - }, - /// In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. - /// This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. - IRQ_QUIET: u1, - /// Apply byte-swap transformation to DMA data. - /// For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. - BSWAP: u1, - /// If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. - /// This allows checksum to be enabled or disabled on a per-control- block basis. - SNIFF_EN: u1, - /// This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. - /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. - BUSY: u1, - reserved29: u4, - /// If 1, the channel received a write bus error. Write one to clear. - /// WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later) - WRITE_ERROR: u1, - /// If 1, the channel received a read bus error. Write one to clear. - /// READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later) - READ_ERROR: u1, - /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. - AHB_ERROR: u1, - }), - /// Alias for channel 6 CTRL register - CH6_AL1_CTRL: u32, - /// Alias for channel 6 READ_ADDR register - CH6_AL1_READ_ADDR: u32, - /// Alias for channel 6 WRITE_ADDR register - CH6_AL1_WRITE_ADDR: u32, - /// Alias for channel 6 TRANS_COUNT register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH6_AL1_TRANS_COUNT_TRIG: u32, - /// Alias for channel 6 CTRL register - CH6_AL2_CTRL: u32, - /// Alias for channel 6 TRANS_COUNT register - CH6_AL2_TRANS_COUNT: u32, - /// Alias for channel 6 READ_ADDR register - CH6_AL2_READ_ADDR: u32, - /// Alias for channel 6 WRITE_ADDR register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH6_AL2_WRITE_ADDR_TRIG: u32, - /// Alias for channel 6 CTRL register - CH6_AL3_CTRL: u32, - /// Alias for channel 6 WRITE_ADDR register - CH6_AL3_WRITE_ADDR: u32, - /// Alias for channel 6 TRANS_COUNT register - CH6_AL3_TRANS_COUNT: u32, - /// Alias for channel 6 READ_ADDR register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH6_AL3_READ_ADDR_TRIG: u32, - /// DMA Channel 7 Read Address pointer - /// This register updates automatically each time a read completes. The current value is the next address to be read by this channel. - CH7_READ_ADDR: u32, - /// DMA Channel 7 Write Address pointer - /// This register updates automatically each time a write completes. The current value is the next address to be written by this channel. - CH7_WRITE_ADDR: u32, - /// DMA Channel 7 Transfer Count - /// Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). - /// When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. - /// Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. - /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. - CH7_TRANS_COUNT: u32, - /// DMA Channel 7 Control and Status - CH7_CTRL_TRIG: mmio.Mmio(packed struct(u32) { - /// DMA Channel Enable. - /// When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) - EN: u1, - /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. - /// This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. - HIGH_PRIORITY: u1, - /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. - DATA_SIZE: packed union { - raw: u2, - value: enum(u2) { - SIZE_BYTE = 0x0, - SIZE_HALFWORD = 0x1, - SIZE_WORD = 0x2, - _, - }, - }, - /// If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. - /// Generally this should be disabled for peripheral-to-memory transfers. - INCR_READ: u1, - /// If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. - /// Generally this should be disabled for memory-to-peripheral transfers. - INCR_WRITE: u1, - /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. - /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. - RING_SIZE: packed union { - raw: u4, - value: enum(u4) { - RING_NONE = 0x0, - _, - }, - }, - /// Select whether RING_SIZE applies to read or write addresses. - /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. - RING_SEL: u1, - /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. - CHAIN_TO: u4, - /// Select a Transfer Request signal. - /// The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). - /// 0x0 to 0x3a -> select DREQ n as TREQ - TREQ_SEL: packed union { - raw: u6, - value: enum(u6) { - /// Select Timer 0 as TREQ - TIMER0 = 0x3b, - /// Select Timer 1 as TREQ - TIMER1 = 0x3c, - /// Select Timer 2 as TREQ (Optional) - TIMER2 = 0x3d, - /// Select Timer 3 as TREQ (Optional) - TIMER3 = 0x3e, - /// Permanent request, for unpaced transfers. - PERMANENT = 0x3f, - _, - }, - }, - /// In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. - /// This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. - IRQ_QUIET: u1, - /// Apply byte-swap transformation to DMA data. - /// For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. - BSWAP: u1, - /// If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. - /// This allows checksum to be enabled or disabled on a per-control- block basis. - SNIFF_EN: u1, - /// This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. - /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. - BUSY: u1, - reserved29: u4, - /// If 1, the channel received a write bus error. Write one to clear. - /// WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later) - WRITE_ERROR: u1, - /// If 1, the channel received a read bus error. Write one to clear. - /// READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later) - READ_ERROR: u1, - /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. - AHB_ERROR: u1, - }), - /// Alias for channel 7 CTRL register - CH7_AL1_CTRL: u32, - /// Alias for channel 7 READ_ADDR register - CH7_AL1_READ_ADDR: u32, - /// Alias for channel 7 WRITE_ADDR register - CH7_AL1_WRITE_ADDR: u32, - /// Alias for channel 7 TRANS_COUNT register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH7_AL1_TRANS_COUNT_TRIG: u32, - /// Alias for channel 7 CTRL register - CH7_AL2_CTRL: u32, - /// Alias for channel 7 TRANS_COUNT register - CH7_AL2_TRANS_COUNT: u32, - /// Alias for channel 7 READ_ADDR register - CH7_AL2_READ_ADDR: u32, - /// Alias for channel 7 WRITE_ADDR register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH7_AL2_WRITE_ADDR_TRIG: u32, - /// Alias for channel 7 CTRL register - CH7_AL3_CTRL: u32, - /// Alias for channel 7 WRITE_ADDR register - CH7_AL3_WRITE_ADDR: u32, - /// Alias for channel 7 TRANS_COUNT register - CH7_AL3_TRANS_COUNT: u32, - /// Alias for channel 7 READ_ADDR register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH7_AL3_READ_ADDR_TRIG: u32, - /// DMA Channel 8 Read Address pointer - /// This register updates automatically each time a read completes. The current value is the next address to be read by this channel. - CH8_READ_ADDR: u32, - /// DMA Channel 8 Write Address pointer - /// This register updates automatically each time a write completes. The current value is the next address to be written by this channel. - CH8_WRITE_ADDR: u32, - /// DMA Channel 8 Transfer Count - /// Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). - /// When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. - /// Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. - /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. - CH8_TRANS_COUNT: u32, - /// DMA Channel 8 Control and Status - CH8_CTRL_TRIG: mmio.Mmio(packed struct(u32) { - /// DMA Channel Enable. - /// When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) - EN: u1, - /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. - /// This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. - HIGH_PRIORITY: u1, - /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. - DATA_SIZE: packed union { - raw: u2, - value: enum(u2) { - SIZE_BYTE = 0x0, - SIZE_HALFWORD = 0x1, - SIZE_WORD = 0x2, - _, - }, - }, - /// If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. - /// Generally this should be disabled for peripheral-to-memory transfers. - INCR_READ: u1, - /// If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. - /// Generally this should be disabled for memory-to-peripheral transfers. - INCR_WRITE: u1, - /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. - /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. - RING_SIZE: packed union { - raw: u4, - value: enum(u4) { - RING_NONE = 0x0, - _, - }, - }, - /// Select whether RING_SIZE applies to read or write addresses. - /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. - RING_SEL: u1, - /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. - CHAIN_TO: u4, - /// Select a Transfer Request signal. - /// The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). - /// 0x0 to 0x3a -> select DREQ n as TREQ - TREQ_SEL: packed union { - raw: u6, - value: enum(u6) { - /// Select Timer 0 as TREQ - TIMER0 = 0x3b, - /// Select Timer 1 as TREQ - TIMER1 = 0x3c, - /// Select Timer 2 as TREQ (Optional) - TIMER2 = 0x3d, - /// Select Timer 3 as TREQ (Optional) - TIMER3 = 0x3e, - /// Permanent request, for unpaced transfers. - PERMANENT = 0x3f, - _, - }, - }, - /// In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. - /// This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. - IRQ_QUIET: u1, - /// Apply byte-swap transformation to DMA data. - /// For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. - BSWAP: u1, - /// If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. - /// This allows checksum to be enabled or disabled on a per-control- block basis. - SNIFF_EN: u1, - /// This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. - /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. - BUSY: u1, - reserved29: u4, - /// If 1, the channel received a write bus error. Write one to clear. - /// WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later) - WRITE_ERROR: u1, - /// If 1, the channel received a read bus error. Write one to clear. - /// READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later) - READ_ERROR: u1, - /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. - AHB_ERROR: u1, - }), - /// Alias for channel 8 CTRL register - CH8_AL1_CTRL: u32, - /// Alias for channel 8 READ_ADDR register - CH8_AL1_READ_ADDR: u32, - /// Alias for channel 8 WRITE_ADDR register - CH8_AL1_WRITE_ADDR: u32, - /// Alias for channel 8 TRANS_COUNT register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH8_AL1_TRANS_COUNT_TRIG: u32, - /// Alias for channel 8 CTRL register - CH8_AL2_CTRL: u32, - /// Alias for channel 8 TRANS_COUNT register - CH8_AL2_TRANS_COUNT: u32, - /// Alias for channel 8 READ_ADDR register - CH8_AL2_READ_ADDR: u32, - /// Alias for channel 8 WRITE_ADDR register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH8_AL2_WRITE_ADDR_TRIG: u32, - /// Alias for channel 8 CTRL register - CH8_AL3_CTRL: u32, - /// Alias for channel 8 WRITE_ADDR register - CH8_AL3_WRITE_ADDR: u32, - /// Alias for channel 8 TRANS_COUNT register - CH8_AL3_TRANS_COUNT: u32, - /// Alias for channel 8 READ_ADDR register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH8_AL3_READ_ADDR_TRIG: u32, - /// DMA Channel 9 Read Address pointer - /// This register updates automatically each time a read completes. The current value is the next address to be read by this channel. - CH9_READ_ADDR: u32, - /// DMA Channel 9 Write Address pointer - /// This register updates automatically each time a write completes. The current value is the next address to be written by this channel. - CH9_WRITE_ADDR: u32, - /// DMA Channel 9 Transfer Count - /// Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). - /// When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. - /// Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. - /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. - CH9_TRANS_COUNT: u32, - /// DMA Channel 9 Control and Status - CH9_CTRL_TRIG: mmio.Mmio(packed struct(u32) { - /// DMA Channel Enable. - /// When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) - EN: u1, - /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. - /// This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. - HIGH_PRIORITY: u1, - /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. - DATA_SIZE: packed union { - raw: u2, - value: enum(u2) { - SIZE_BYTE = 0x0, - SIZE_HALFWORD = 0x1, - SIZE_WORD = 0x2, - _, - }, - }, - /// If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. - /// Generally this should be disabled for peripheral-to-memory transfers. - INCR_READ: u1, - /// If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. - /// Generally this should be disabled for memory-to-peripheral transfers. - INCR_WRITE: u1, - /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. - /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. - RING_SIZE: packed union { - raw: u4, - value: enum(u4) { - RING_NONE = 0x0, - _, - }, - }, - /// Select whether RING_SIZE applies to read or write addresses. - /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. - RING_SEL: u1, - /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. - CHAIN_TO: u4, - /// Select a Transfer Request signal. - /// The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). - /// 0x0 to 0x3a -> select DREQ n as TREQ - TREQ_SEL: packed union { - raw: u6, - value: enum(u6) { - /// Select Timer 0 as TREQ - TIMER0 = 0x3b, - /// Select Timer 1 as TREQ - TIMER1 = 0x3c, - /// Select Timer 2 as TREQ (Optional) - TIMER2 = 0x3d, - /// Select Timer 3 as TREQ (Optional) - TIMER3 = 0x3e, - /// Permanent request, for unpaced transfers. - PERMANENT = 0x3f, - _, - }, - }, - /// In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. - /// This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. - IRQ_QUIET: u1, - /// Apply byte-swap transformation to DMA data. - /// For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. - BSWAP: u1, - /// If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. - /// This allows checksum to be enabled or disabled on a per-control- block basis. - SNIFF_EN: u1, - /// This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. - /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. - BUSY: u1, - reserved29: u4, - /// If 1, the channel received a write bus error. Write one to clear. - /// WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later) - WRITE_ERROR: u1, - /// If 1, the channel received a read bus error. Write one to clear. - /// READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later) - READ_ERROR: u1, - /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. - AHB_ERROR: u1, - }), - /// Alias for channel 9 CTRL register - CH9_AL1_CTRL: u32, - /// Alias for channel 9 READ_ADDR register - CH9_AL1_READ_ADDR: u32, - /// Alias for channel 9 WRITE_ADDR register - CH9_AL1_WRITE_ADDR: u32, - /// Alias for channel 9 TRANS_COUNT register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH9_AL1_TRANS_COUNT_TRIG: u32, - /// Alias for channel 9 CTRL register - CH9_AL2_CTRL: u32, - /// Alias for channel 9 TRANS_COUNT register - CH9_AL2_TRANS_COUNT: u32, - /// Alias for channel 9 READ_ADDR register - CH9_AL2_READ_ADDR: u32, - /// Alias for channel 9 WRITE_ADDR register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH9_AL2_WRITE_ADDR_TRIG: u32, - /// Alias for channel 9 CTRL register - CH9_AL3_CTRL: u32, - /// Alias for channel 9 WRITE_ADDR register - CH9_AL3_WRITE_ADDR: u32, - /// Alias for channel 9 TRANS_COUNT register - CH9_AL3_TRANS_COUNT: u32, - /// Alias for channel 9 READ_ADDR register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH9_AL3_READ_ADDR_TRIG: u32, - /// DMA Channel 10 Read Address pointer - /// This register updates automatically each time a read completes. The current value is the next address to be read by this channel. - CH10_READ_ADDR: u32, - /// DMA Channel 10 Write Address pointer - /// This register updates automatically each time a write completes. The current value is the next address to be written by this channel. - CH10_WRITE_ADDR: u32, - /// DMA Channel 10 Transfer Count - /// Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). - /// When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. - /// Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. - /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. - CH10_TRANS_COUNT: u32, - /// DMA Channel 10 Control and Status - CH10_CTRL_TRIG: mmio.Mmio(packed struct(u32) { - /// DMA Channel Enable. - /// When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) - EN: u1, - /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. - /// This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. - HIGH_PRIORITY: u1, - /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. - DATA_SIZE: packed union { - raw: u2, - value: enum(u2) { - SIZE_BYTE = 0x0, - SIZE_HALFWORD = 0x1, - SIZE_WORD = 0x2, - _, - }, - }, - /// If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. - /// Generally this should be disabled for peripheral-to-memory transfers. - INCR_READ: u1, - /// If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. - /// Generally this should be disabled for memory-to-peripheral transfers. - INCR_WRITE: u1, - /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. - /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. - RING_SIZE: packed union { - raw: u4, - value: enum(u4) { - RING_NONE = 0x0, - _, - }, - }, - /// Select whether RING_SIZE applies to read or write addresses. - /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. - RING_SEL: u1, - /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. - CHAIN_TO: u4, - /// Select a Transfer Request signal. - /// The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). - /// 0x0 to 0x3a -> select DREQ n as TREQ - TREQ_SEL: packed union { - raw: u6, - value: enum(u6) { - /// Select Timer 0 as TREQ - TIMER0 = 0x3b, - /// Select Timer 1 as TREQ - TIMER1 = 0x3c, - /// Select Timer 2 as TREQ (Optional) - TIMER2 = 0x3d, - /// Select Timer 3 as TREQ (Optional) - TIMER3 = 0x3e, - /// Permanent request, for unpaced transfers. - PERMANENT = 0x3f, - _, - }, - }, - /// In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. - /// This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. - IRQ_QUIET: u1, - /// Apply byte-swap transformation to DMA data. - /// For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. - BSWAP: u1, - /// If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. - /// This allows checksum to be enabled or disabled on a per-control- block basis. - SNIFF_EN: u1, - /// This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. - /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. - BUSY: u1, - reserved29: u4, - /// If 1, the channel received a write bus error. Write one to clear. - /// WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later) - WRITE_ERROR: u1, - /// If 1, the channel received a read bus error. Write one to clear. - /// READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later) - READ_ERROR: u1, - /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. - AHB_ERROR: u1, - }), - /// Alias for channel 10 CTRL register - CH10_AL1_CTRL: u32, - /// Alias for channel 10 READ_ADDR register - CH10_AL1_READ_ADDR: u32, - /// Alias for channel 10 WRITE_ADDR register - CH10_AL1_WRITE_ADDR: u32, - /// Alias for channel 10 TRANS_COUNT register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH10_AL1_TRANS_COUNT_TRIG: u32, - /// Alias for channel 10 CTRL register - CH10_AL2_CTRL: u32, - /// Alias for channel 10 TRANS_COUNT register - CH10_AL2_TRANS_COUNT: u32, - /// Alias for channel 10 READ_ADDR register - CH10_AL2_READ_ADDR: u32, - /// Alias for channel 10 WRITE_ADDR register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH10_AL2_WRITE_ADDR_TRIG: u32, - /// Alias for channel 10 CTRL register - CH10_AL3_CTRL: u32, - /// Alias for channel 10 WRITE_ADDR register - CH10_AL3_WRITE_ADDR: u32, - /// Alias for channel 10 TRANS_COUNT register - CH10_AL3_TRANS_COUNT: u32, - /// Alias for channel 10 READ_ADDR register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH10_AL3_READ_ADDR_TRIG: u32, - /// DMA Channel 11 Read Address pointer - /// This register updates automatically each time a read completes. The current value is the next address to be read by this channel. - CH11_READ_ADDR: u32, - /// DMA Channel 11 Write Address pointer - /// This register updates automatically each time a write completes. The current value is the next address to be written by this channel. - CH11_WRITE_ADDR: u32, - /// DMA Channel 11 Transfer Count - /// Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). - /// When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. - /// Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. - /// The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. - CH11_TRANS_COUNT: u32, - /// DMA Channel 11 Control and Status - CH11_CTRL_TRIG: mmio.Mmio(packed struct(u32) { - /// DMA Channel Enable. - /// When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) - EN: u1, - /// HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. - /// This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. - HIGH_PRIORITY: u1, - /// Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. - DATA_SIZE: packed union { - raw: u2, - value: enum(u2) { - SIZE_BYTE = 0x0, - SIZE_HALFWORD = 0x1, - SIZE_WORD = 0x2, - _, - }, - }, - /// If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. - /// Generally this should be disabled for peripheral-to-memory transfers. - INCR_READ: u1, - /// If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. - /// Generally this should be disabled for memory-to-peripheral transfers. - INCR_WRITE: u1, - /// Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. - /// Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. - RING_SIZE: packed union { - raw: u4, - value: enum(u4) { - RING_NONE = 0x0, - _, - }, - }, - /// Select whether RING_SIZE applies to read or write addresses. - /// If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. - RING_SEL: u1, - /// When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. - CHAIN_TO: u4, - /// Select a Transfer Request signal. - /// The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). - /// 0x0 to 0x3a -> select DREQ n as TREQ - TREQ_SEL: packed union { - raw: u6, - value: enum(u6) { - /// Select Timer 0 as TREQ - TIMER0 = 0x3b, - /// Select Timer 1 as TREQ - TIMER1 = 0x3c, - /// Select Timer 2 as TREQ (Optional) - TIMER2 = 0x3d, - /// Select Timer 3 as TREQ (Optional) - TIMER3 = 0x3e, - /// Permanent request, for unpaced transfers. - PERMANENT = 0x3f, - _, - }, - }, - /// In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. - /// This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. - IRQ_QUIET: u1, - /// Apply byte-swap transformation to DMA data. - /// For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. - BSWAP: u1, - /// If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. - /// This allows checksum to be enabled or disabled on a per-control- block basis. - SNIFF_EN: u1, - /// This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. - /// To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. - BUSY: u1, - reserved29: u4, - /// If 1, the channel received a write bus error. Write one to clear. - /// WRITE_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 5 transfers later) - WRITE_ERROR: u1, - /// If 1, the channel received a read bus error. Write one to clear. - /// READ_ADDR shows the approximate address where the bus error was encountered (will not to be earlier, or more than 3 transfers later) - READ_ERROR: u1, - /// Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. - AHB_ERROR: u1, - }), - /// Alias for channel 11 CTRL register - CH11_AL1_CTRL: u32, - /// Alias for channel 11 READ_ADDR register - CH11_AL1_READ_ADDR: u32, - /// Alias for channel 11 WRITE_ADDR register - CH11_AL1_WRITE_ADDR: u32, - /// Alias for channel 11 TRANS_COUNT register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH11_AL1_TRANS_COUNT_TRIG: u32, - /// Alias for channel 11 CTRL register - CH11_AL2_CTRL: u32, - /// Alias for channel 11 TRANS_COUNT register - CH11_AL2_TRANS_COUNT: u32, - /// Alias for channel 11 READ_ADDR register - CH11_AL2_READ_ADDR: u32, - /// Alias for channel 11 WRITE_ADDR register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH11_AL2_WRITE_ADDR_TRIG: u32, - /// Alias for channel 11 CTRL register - CH11_AL3_CTRL: u32, - /// Alias for channel 11 WRITE_ADDR register - CH11_AL3_WRITE_ADDR: u32, - /// Alias for channel 11 TRANS_COUNT register - CH11_AL3_TRANS_COUNT: u32, - /// Alias for channel 11 READ_ADDR register - /// This is a trigger register (0xc). Writing a nonzero value will - /// reload the channel counter and start the channel. - CH11_AL3_READ_ADDR_TRIG: u32, - reserved1024: [256]u8, - /// Interrupt Status (raw) - INTR: mmio.Mmio(packed struct(u32) { - /// Raw interrupt status for DMA Channels 0..15. Bit n corresponds to channel n. Ignores any masking or forcing. Channel interrupts can be cleared by writing a bit mask to INTR, INTS0 or INTS1. - /// Channel interrupts can be routed to either of two system-level IRQs based on INTE0 and INTE1. - /// This can be used vector different channel interrupts to different ISRs: this might be done to allow NVIC IRQ preemption for more time-critical channels, or to spread IRQ load across different cores. - /// It is also valid to ignore this behaviour and just use INTE0/INTS0/IRQ 0. - INTR: u16, - padding: u16, - }), - /// Interrupt Enables for IRQ 0 - INTE0: mmio.Mmio(packed struct(u32) { - /// Set bit n to pass interrupts from channel n to DMA IRQ 0. - INTE0: u16, - padding: u16, - }), - /// Force Interrupts - INTF0: mmio.Mmio(packed struct(u32) { - /// Write 1s to force the corresponding bits in INTE0. The interrupt remains asserted until INTF0 is cleared. - INTF0: u16, - padding: u16, - }), - /// Interrupt Status for IRQ 0 - INTS0: mmio.Mmio(packed struct(u32) { - /// Indicates active channel interrupt requests which are currently causing IRQ 0 to be asserted. - /// Channel interrupts can be cleared by writing a bit mask here. - INTS0: u16, - padding: u16, - }), - reserved1044: [4]u8, - /// Interrupt Enables for IRQ 1 - INTE1: mmio.Mmio(packed struct(u32) { - /// Set bit n to pass interrupts from channel n to DMA IRQ 1. - INTE1: u16, - padding: u16, - }), - /// Force Interrupts for IRQ 1 - INTF1: mmio.Mmio(packed struct(u32) { - /// Write 1s to force the corresponding bits in INTE0. The interrupt remains asserted until INTF0 is cleared. - INTF1: u16, - padding: u16, - }), - /// Interrupt Status (masked) for IRQ 1 - INTS1: mmio.Mmio(packed struct(u32) { - /// Indicates active channel interrupt requests which are currently causing IRQ 1 to be asserted. - /// Channel interrupts can be cleared by writing a bit mask here. - INTS1: u16, - padding: u16, - }), - /// Pacing (X/Y) Fractional Timer - /// The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. - TIMER0: mmio.Mmio(packed struct(u32) { - /// Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. - Y: u16, - /// Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. - X: u16, - }), - /// Pacing (X/Y) Fractional Timer - /// The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. - TIMER1: mmio.Mmio(packed struct(u32) { - /// Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. - Y: u16, - /// Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. - X: u16, - }), - /// Pacing (X/Y) Fractional Timer - /// The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. - TIMER2: mmio.Mmio(packed struct(u32) { - /// Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. - Y: u16, - /// Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. - X: u16, - }), - /// Pacing (X/Y) Fractional Timer - /// The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. - TIMER3: mmio.Mmio(packed struct(u32) { - /// Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. - Y: u16, - /// Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. - X: u16, - }), - /// Trigger one or more channels simultaneously - MULTI_CHAN_TRIGGER: mmio.Mmio(packed struct(u32) { - /// Each bit in this register corresponds to a DMA channel. Writing a 1 to the relevant bit is the same as writing to that channel's trigger register; the channel will start if it is currently enabled and not already busy. - MULTI_CHAN_TRIGGER: u16, - padding: u16, - }), - /// Sniffer Control - SNIFF_CTRL: mmio.Mmio(packed struct(u32) { - /// Enable sniffer - EN: u1, - /// DMA channel for Sniffer to observe - DMACH: u4, - CALC: packed union { - raw: u4, - value: enum(u4) { - /// Calculate a CRC-32 (IEEE802.3 polynomial) - CRC32 = 0x0, - /// Calculate a CRC-32 (IEEE802.3 polynomial) with bit reversed data - CRC32R = 0x1, - /// Calculate a CRC-16-CCITT - CRC16 = 0x2, - /// Calculate a CRC-16-CCITT with bit reversed data - CRC16R = 0x3, - /// XOR reduction over all data. == 1 if the total 1 population count is odd. - EVEN = 0xe, - /// Calculate a simple 32-bit checksum (addition with a 32 bit accumulator) - SUM = 0xf, - _, - }, - }, - /// Locally perform a byte reverse on the sniffed data, before feeding into checksum. - /// Note that the sniff hardware is downstream of the DMA channel byteswap performed in the read master: if channel CTRL_BSWAP and SNIFF_CTRL_BSWAP are both enabled, their effects cancel from the sniffer's point of view. - BSWAP: u1, - /// If set, the result appears bit-reversed when read. This does not affect the way the checksum is calculated; the result is transformed on-the-fly between the result register and the bus. - OUT_REV: u1, - /// If set, the result appears inverted (bitwise complement) when read. This does not affect the way the checksum is calculated; the result is transformed on-the-fly between the result register and the bus. - OUT_INV: u1, - padding: u20, - }), - /// Data accumulator for sniff hardware - /// Write an initial seed value here before starting a DMA transfer on the channel indicated by SNIFF_CTRL_DMACH. The hardware will update this register each time it observes a read from the indicated channel. Once the channel completes, the final result can be read from this register. - SNIFF_DATA: u32, - reserved1088: [4]u8, - /// Debug RAF, WAF, TDF levels - FIFO_LEVELS: mmio.Mmio(packed struct(u32) { - /// Current Transfer-Data-FIFO fill level - TDF_LVL: u8, - /// Current Write-Address-FIFO fill level - WAF_LVL: u8, - /// Current Read-Address-FIFO fill level - RAF_LVL: u8, - padding: u8, - }), - /// Abort an in-progress transfer sequence on one or more channels - CHAN_ABORT: mmio.Mmio(packed struct(u32) { - /// Each bit corresponds to a channel. Writing a 1 aborts whatever transfer sequence is in progress on that channel. The bit will remain high until any in-flight transfers have been flushed through the address and data FIFOs. - /// After writing, this register must be polled until it returns all-zero. Until this point, it is unsafe to restart the channel. - CHAN_ABORT: u16, - padding: u16, - }), - /// The number of channels this DMA instance is equipped with. This DMA supports up to 16 hardware channels, but can be configured with as few as one, to minimise silicon area. - N_CHANNELS: mmio.Mmio(packed struct(u32) { - N_CHANNELS: u5, - padding: u27, - }), - reserved2048: [948]u8, - /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. - CH0_DBG_CTDREQ: mmio.Mmio(packed struct(u32) { - CH0_DBG_CTDREQ: u6, - padding: u26, - }), - /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer - CH0_DBG_TCR: u32, - reserved2112: [56]u8, - /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. - CH1_DBG_CTDREQ: mmio.Mmio(packed struct(u32) { - CH1_DBG_CTDREQ: u6, - padding: u26, - }), - /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer - CH1_DBG_TCR: u32, - reserved2176: [56]u8, - /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. - CH2_DBG_CTDREQ: mmio.Mmio(packed struct(u32) { - CH2_DBG_CTDREQ: u6, - padding: u26, - }), - /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer - CH2_DBG_TCR: u32, - reserved2240: [56]u8, - /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. - CH3_DBG_CTDREQ: mmio.Mmio(packed struct(u32) { - CH3_DBG_CTDREQ: u6, - padding: u26, - }), - /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer - CH3_DBG_TCR: u32, - reserved2304: [56]u8, - /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. - CH4_DBG_CTDREQ: mmio.Mmio(packed struct(u32) { - CH4_DBG_CTDREQ: u6, - padding: u26, - }), - /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer - CH4_DBG_TCR: u32, - reserved2368: [56]u8, - /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. - CH5_DBG_CTDREQ: mmio.Mmio(packed struct(u32) { - CH5_DBG_CTDREQ: u6, - padding: u26, - }), - /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer - CH5_DBG_TCR: u32, - reserved2432: [56]u8, - /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. - CH6_DBG_CTDREQ: mmio.Mmio(packed struct(u32) { - CH6_DBG_CTDREQ: u6, - padding: u26, - }), - /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer - CH6_DBG_TCR: u32, - reserved2496: [56]u8, - /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. - CH7_DBG_CTDREQ: mmio.Mmio(packed struct(u32) { - CH7_DBG_CTDREQ: u6, - padding: u26, - }), - /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer - CH7_DBG_TCR: u32, - reserved2560: [56]u8, - /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. - CH8_DBG_CTDREQ: mmio.Mmio(packed struct(u32) { - CH8_DBG_CTDREQ: u6, - padding: u26, - }), - /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer - CH8_DBG_TCR: u32, - reserved2624: [56]u8, - /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. - CH9_DBG_CTDREQ: mmio.Mmio(packed struct(u32) { - CH9_DBG_CTDREQ: u6, - padding: u26, - }), - /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer - CH9_DBG_TCR: u32, - reserved2688: [56]u8, - /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. - CH10_DBG_CTDREQ: mmio.Mmio(packed struct(u32) { - CH10_DBG_CTDREQ: u6, - padding: u26, - }), - /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer - CH10_DBG_TCR: u32, - reserved2752: [56]u8, - /// Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. - CH11_DBG_CTDREQ: mmio.Mmio(packed struct(u32) { - CH11_DBG_CTDREQ: u6, - padding: u26, - }), - /// Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer - CH11_DBG_TCR: u32, - }; - - /// DPRAM layout for USB device. - pub const USBCTRL_DPRAM = extern struct { - /// Bytes 0-3 of the SETUP packet from the host. - SETUP_PACKET_LOW: mmio.Mmio(packed struct(u32) { - BMREQUESTTYPE: u8, - BREQUEST: u8, - WVALUE: u16, - }), - /// Bytes 4-7 of the setup packet from the host. - SETUP_PACKET_HIGH: mmio.Mmio(packed struct(u32) { - WINDEX: u16, - WLENGTH: u16, - }), - EP1_IN_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP1_OUT_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP2_IN_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP2_OUT_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP3_IN_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP3_OUT_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP4_IN_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP4_OUT_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP5_IN_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP5_OUT_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP6_IN_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP6_OUT_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP7_IN_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP7_OUT_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP8_IN_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP8_OUT_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP9_IN_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP9_OUT_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP10_IN_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP10_OUT_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP11_IN_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP11_OUT_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP12_IN_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP12_OUT_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP13_IN_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP13_OUT_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP14_IN_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP14_OUT_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP15_IN_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - EP15_OUT_CONTROL: mmio.Mmio(packed struct(u32) { - /// 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. - BUFFER_ADDRESS: u16, - /// Trigger an interrupt if a NAK is sent. Intended for debug only. - INTERRUPT_ON_NAK: u1, - /// Trigger an interrupt if a STALL is sent. Intended for debug only. - INTERRUPT_ON_STALL: u1, - reserved26: u8, - ENDPOINT_TYPE: packed union { - raw: u2, - value: enum(u2) { - Control = 0x0, - Isochronous = 0x1, - Bulk = 0x2, - Interrupt = 0x3, - }, - }, - /// Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. - INTERRUPT_PER_DOUBLE_BUFF: u1, - /// Trigger an interrupt each time a buffer is done. - INTERRUPT_PER_BUFF: u1, - /// This endpoint is double buffered. - DOUBLE_BUFFERED: u1, - /// Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. - ENABLE: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP0_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP0_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP1_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP1_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP2_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP2_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP3_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP3_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP4_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP4_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP5_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP5_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP6_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP6_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP7_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP7_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP8_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP8_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP9_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP9_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP10_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP10_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP11_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP11_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP12_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP12_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP13_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP13_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP14_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP14_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP15_IN_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - /// Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. - /// Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. - EP15_OUT_BUFFER_CONTROL: mmio.Mmio(packed struct(u32) { - /// The length of the data in buffer 0. - LENGTH_0: u10, - /// Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_0: u1, - /// Reply with a stall (valid for both buffers). - STALL: u1, - /// Reset the buffer selector to buffer 0. - RESET: u1, - /// The data pid of buffer 0. - PID_0: u1, - /// Buffer 0 is the last buffer of the transfer. - LAST_0: u1, - /// Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_0: u1, - /// The length of the data in buffer 1. - LENGTH_1: u10, - /// Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. - AVAILABLE_1: u1, - /// The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. - /// For a non Isochronous endpoint the offset is always 64 bytes. - DOUBLE_BUFFER_ISO_OFFSET: packed union { - raw: u2, - value: enum(u2) { - @"128" = 0x0, - @"256" = 0x1, - @"512" = 0x2, - @"1024" = 0x3, - }, - }, - /// The data pid of buffer 1. - PID_1: u1, - /// Buffer 1 is the last buffer of the transfer. - LAST_1: u1, - /// Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. - FULL_1: u1, - }), - }; - }; -};