From 179047ab6542d1042bac16444bf400aa7e6d992d Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Thu, 7 Jul 2022 23:00:18 -0700 Subject: [PATCH] fix colliding ISRs by making sure they each get memoized (#60) * fix colliding ISRs by making sure they each get memoized * add change from regz codegen --- src/core/microzig.zig | 17 +++++++- src/modules/chips/atmega328p/registers.zig | 20 +-------- src/modules/chips/lpc1768/registers.zig | 12 +++--- src/modules/chips/nrf52/registers.zig | 34 +--------------- src/modules/chips/stm32f103/registers.zig | 2 +- src/modules/chips/stm32f303/registers.zig | 2 +- src/modules/chips/stm32f407/registers.zig | 3 +- src/modules/chips/stm32f429/registers.zig | 3 +- src/modules/cpus/cortex-m/cortex-m.zig | 47 ++++++++++++++-------- 9 files changed, 58 insertions(+), 82 deletions(-) diff --git a/src/core/microzig.zig b/src/core/microzig.zig index 0353d35..aab89b8 100644 --- a/src/core/microzig.zig +++ b/src/core/microzig.zig @@ -68,7 +68,22 @@ usingnamespace if (@hasDecl(app, "log")) pub const log = app.log; } else - struct {}; + struct { + // log is a no-op by default. Parts of microzig use the stdlib logging + // facility and compilations will now fail on freestanding systems that + // use it but do not explicitly set `root.log` + pub fn log( + comptime message_level: std.log.Level, + comptime scope: @Type(.EnumLiteral), + comptime format: []const u8, + args: anytype, + ) void { + _ = message_level; + _ = scope; + _ = format; + _ = args; + } + }; /// The microzig default panic handler. Will disable interrupts and loop endlessly. pub fn microzig_panic(message: []const u8, maybe_stack_trace: ?*std.builtin.StackTrace) noreturn { diff --git a/src/modules/chips/atmega328p/registers.zig b/src/modules/chips/atmega328p/registers.zig index 0c27f21..53e47b2 100644 --- a/src/modules/chips/atmega328p/registers.zig +++ b/src/modules/chips/atmega328p/registers.zig @@ -61,10 +61,8 @@ pub const VectorTable = extern struct { }; pub const registers = struct { - /// Fuses pub const FUSE = struct { - /// address: 0x2 pub const EXTENDED = @intToPtr(*volatile Mmio(8, packed struct { /// Brown-out Detector trigger level @@ -173,7 +171,6 @@ pub const registers = struct { /// Lockbits pub const LOCKBIT = struct { - /// address: 0x0 pub const LOCKBIT = @intToPtr(*volatile Mmio(8, packed struct { /// Memory Lock @@ -203,7 +200,6 @@ pub const registers = struct { /// USART pub const USART0 = struct { - /// address: 0xc6 /// USART I/O Data Register pub const UDR0 = @intToPtr(*volatile u8, 0xc6); @@ -284,7 +280,6 @@ pub const registers = struct { /// Two Wire Serial Interface pub const TWI = struct { - /// address: 0xbd /// TWI (Slave) Address Mask Register pub const TWAMR = @intToPtr(*volatile Mmio(8, packed struct { @@ -347,7 +342,6 @@ pub const registers = struct { /// Timer/Counter, 16-bit pub const TC1 = struct { - /// address: 0x6f /// Timer/Counter Interrupt Mask Register pub const TIMSK1 = @intToPtr(*volatile Mmio(8, packed struct { @@ -465,7 +459,6 @@ pub const registers = struct { /// Timer/Counter, 8-bit Async pub const TC2 = struct { - /// address: 0x70 /// Timer/Counter Interrupt Mask register pub const TIMSK2 = @intToPtr(*volatile Mmio(8, packed struct { @@ -585,7 +578,6 @@ pub const registers = struct { /// Analog-to-Digital Converter pub const ADC = struct { - /// address: 0x7c /// The ADC multiplexer Selection Register pub const ADMUX = @intToPtr(*volatile Mmio(8, packed struct { @@ -682,7 +674,6 @@ pub const registers = struct { /// Analog Comparator pub const AC = struct { - /// address: 0x50 /// Analog Comparator Control And Status Register pub const ACSR = @intToPtr(*volatile Mmio(8, packed struct { @@ -725,7 +716,6 @@ pub const registers = struct { /// I/O Port pub const PORTB = struct { - /// address: 0x25 /// Port B Data Register pub const PORTB = @intToPtr(*volatile u8, 0x25); @@ -741,7 +731,6 @@ pub const registers = struct { /// I/O Port pub const PORTC = struct { - /// address: 0x28 /// Port C Data Register pub const PORTC = @intToPtr(*volatile u7, 0x28); @@ -757,7 +746,6 @@ pub const registers = struct { /// I/O Port pub const PORTD = struct { - /// address: 0x2b /// Port D Data Register pub const PORTD = @intToPtr(*volatile u8, 0x2b); @@ -773,7 +761,6 @@ pub const registers = struct { /// Timer/Counter, 8-bit pub const TC0 = struct { - /// address: 0x48 /// Timer/Counter0 Output Compare Register pub const OCR0B = @intToPtr(*volatile u8, 0x48); @@ -872,7 +859,6 @@ pub const registers = struct { /// External Interrupts pub const EXINT = struct { - /// address: 0x69 /// External Interrupt Control Register pub const EICRA = @intToPtr(*volatile Mmio(8, packed struct { @@ -971,7 +957,6 @@ pub const registers = struct { /// Serial Peripheral Interface pub const SPI = struct { - /// address: 0x4e /// SPI Data Register pub const SPDR = @intToPtr(*volatile u8, 0x4e); @@ -1019,7 +1004,6 @@ pub const registers = struct { /// Watchdog Timer pub const WDT = struct { - /// address: 0x60 /// Watchdog Timer Control Register pub const WDTCSR = @intToPtr(*volatile Mmio(8, packed struct { @@ -1040,7 +1024,6 @@ pub const registers = struct { /// CPU Registers pub const CPU = struct { - /// address: 0x64 /// Power Reduction Register pub const PRR = @intToPtr(*volatile Mmio(8, packed struct { @@ -1202,7 +1185,6 @@ pub const registers = struct { /// EEPROM pub const EEPROM = struct { - /// address: 0x41 /// EEPROM Address Register Bytes pub const EEAR = @intToPtr(*volatile u10, 0x41); @@ -1312,7 +1294,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 diff --git a/src/modules/chips/lpc1768/registers.zig b/src/modules/chips/lpc1768/registers.zig index 12d3ba1..0cd697c 100644 --- a/src/modules/chips/lpc1768/registers.zig +++ b/src/modules/chips/lpc1768/registers.zig @@ -647,7 +647,7 @@ pub const registers = struct { /// characters must be written before an interrupt or DMA request is activated. RXTRIGLVL: u2, /// Reserved. Read value is undefined, only zero should be written. - RESERVED0: u8, + RESERVED0: u8, RESERVED1: u16, }), base_address + 0x8); @@ -8703,7 +8703,7 @@ pub const registers = struct { PLLC0: u1, /// Reserved, user software should not write ones to reserved bits. The value read /// from a reserved bit is not defined. - RESERVED: u30=0, + RESERVED: u30 = 0, }), base_address + 0x80); /// address: 0x400fc084 @@ -9036,7 +9036,7 @@ pub const registers = struct { CLKSRC: u2, /// Reserved, user software should not write ones to reserved bits. The value read /// from a reserved bit is not defined. - RESERVED: u30=0, + RESERVED: u30 = 0, }), base_address + 0x10c); /// address: 0x400fc110 @@ -9238,7 +9238,7 @@ pub const registers = struct { /// Peripheral clock selection for I2C1. PCLK_I2C1: u2, /// Reserved. - RESERVED0: u2=1, + RESERVED0: u2 = 1, /// Peripheral clock selection for SSP0. PCLK_SSP0: u2, /// Peripheral clock selection for TIMER2. @@ -9254,7 +9254,7 @@ pub const registers = struct { /// Peripheral clock selection for I2S. PCLK_I2S: u2, /// Reserved. - RESERVED1: u2=1, + RESERVED1: u2 = 1, /// Peripheral clock selection for Repetitive Interrupt Timer. PCLK_RIT: u2, /// Peripheral clock selection for the System Control block. @@ -18796,7 +18796,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 diff --git a/src/modules/chips/nrf52/registers.zig b/src/modules/chips/nrf52/registers.zig index 617e52f..a2333fd 100644 --- a/src/modules/chips/nrf52/registers.zig +++ b/src/modules/chips/nrf52/registers.zig @@ -93,7 +93,6 @@ pub const registers = struct { /// Device info pub const INFO = struct { - /// address: 0x10000000 /// Part code pub const PART = @intToPtr(*volatile u32, base_address + 0x0); @@ -121,7 +120,6 @@ pub const registers = struct { /// Registers storing factory TEMP module linearization coefficients pub const TEMP = struct { - /// address: 0x10000000 /// Slope definition A0. pub const A0 = @intToPtr(*volatile Mmio(32, packed struct { @@ -591,7 +589,6 @@ pub const registers = struct { }; pub const NFC = struct { - /// address: 0x10000000 /// Default header for NFC Tag. Software can read these values to populate /// NFCID1_3RD_LAST, NFCID1_2ND_LAST and NFCID1_LAST. @@ -2896,7 +2893,6 @@ pub const registers = struct { }), base_address + 0x56c); pub const PSEL = struct { - /// address: 0x40002000 /// Pin select for RTS signal pub const RTS = @intToPtr(*volatile Mmio(32, packed struct { @@ -3040,7 +3036,6 @@ pub const registers = struct { /// RXD EasyDMA channel pub const RXD = struct { - /// address: 0x40002000 /// Data pointer pub const PTR = @intToPtr(*volatile u32, base_address + 0x0); @@ -3056,7 +3051,6 @@ pub const registers = struct { /// TXD EasyDMA channel pub const TXD = struct { - /// address: 0x40002000 /// Data pointer pub const PTR = @intToPtr(*volatile u32, base_address + 0x0); @@ -3569,7 +3563,6 @@ pub const registers = struct { pub const ORC = @intToPtr(*volatile MmioInt(32, u8), base_address + 0x5c0); pub const PSEL = struct { - /// address: 0x40003000 /// Pin select for SCK pub const SCK = @intToPtr(*volatile Mmio(32, packed struct { @@ -3678,7 +3671,6 @@ pub const registers = struct { /// RXD EasyDMA channel pub const RXD = struct { - /// address: 0x40003000 /// Data pointer pub const PTR = @intToPtr(*volatile u32, base_address + 0x0); @@ -3698,7 +3690,6 @@ pub const registers = struct { /// TXD EasyDMA channel pub const TXD = struct { - /// address: 0x40003000 /// Data pointer pub const PTR = @intToPtr(*volatile u32, base_address + 0x0); @@ -3954,7 +3945,6 @@ pub const registers = struct { pub const ORC = @intToPtr(*volatile MmioInt(32, u8), base_address + 0x5c0); pub const PSEL = struct { - /// address: 0x40003000 /// Pin select for SCK pub const SCK = @intToPtr(*volatile Mmio(32, packed struct { @@ -4097,7 +4087,6 @@ pub const registers = struct { }; pub const RXD = struct { - /// address: 0x40003000 /// RXD data pointer pub const PTR = @intToPtr(*volatile u32, base_address + 0x0); @@ -4112,7 +4101,6 @@ pub const registers = struct { }; pub const TXD = struct { - /// address: 0x40003000 /// TXD data pointer pub const PTR = @intToPtr(*volatile u32, base_address + 0x0); @@ -4406,7 +4394,6 @@ pub const registers = struct { pub const ADDRESS = @intToPtr(*volatile MmioInt(32, u7), base_address + 0x588); pub const PSEL = struct { - /// address: 0x40003000 /// Pin select for SCL signal pub const SCL = @intToPtr(*volatile Mmio(32, packed struct { @@ -4480,7 +4467,6 @@ pub const registers = struct { /// RXD EasyDMA channel pub const RXD = struct { - /// address: 0x40003000 /// Data pointer pub const PTR = @intToPtr(*volatile u32, base_address + 0x0); @@ -4500,7 +4486,6 @@ pub const registers = struct { /// TXD EasyDMA channel pub const TXD = struct { - /// address: 0x40003000 /// Data pointer pub const PTR = @intToPtr(*volatile u32, base_address + 0x0); @@ -4831,7 +4816,6 @@ pub const registers = struct { pub const ORC = @intToPtr(*volatile MmioInt(32, u8), base_address + 0x5c0); pub const PSEL = struct { - /// address: 0x40003000 /// Pin select for SCL signal pub const SCL = @intToPtr(*volatile Mmio(32, packed struct { @@ -4905,7 +4889,6 @@ pub const registers = struct { /// RXD EasyDMA channel pub const RXD = struct { - /// address: 0x40003000 /// RXD Data pointer pub const PTR = @intToPtr(*volatile u32, base_address + 0x0); @@ -4921,7 +4904,6 @@ pub const registers = struct { /// TXD EasyDMA channel pub const TXD = struct { - /// address: 0x40003000 /// TXD Data pointer pub const PTR = @intToPtr(*volatile u32, base_address + 0x0); @@ -5076,7 +5058,6 @@ pub const registers = struct { }), base_address + 0x554); pub const PSEL = struct { - /// address: 0x40003000 /// Pin select for SCK pub const SCK = @intToPtr(*volatile Mmio(32, packed struct { @@ -7289,7 +7270,6 @@ pub const registers = struct { }), base_address + 0x5a4); pub const FRAMESTATUS = struct { - /// address: 0x40005000 /// Result of last incoming frames pub const RX = @intToPtr(*volatile Mmio(32, packed struct { @@ -7332,7 +7312,6 @@ pub const registers = struct { }; pub const TXD = struct { - /// address: 0x40005000 /// Configuration of outgoing frames pub const FRAMECONFIG = @intToPtr(*volatile Mmio(32, packed struct { @@ -7407,7 +7386,6 @@ pub const registers = struct { }; pub const RXD = struct { - /// address: 0x40005000 /// Configuration of incoming frames pub const FRAMECONFIG = @intToPtr(*volatile Mmio(32, packed struct { @@ -8002,7 +7980,6 @@ pub const registers = struct { /// RESULT EasyDMA channel pub const RESULT = struct { - /// address: 0x40007000 /// Data pointer pub const PTR = @intToPtr(*volatile u32, base_address + 0x0); @@ -10333,7 +10310,6 @@ pub const registers = struct { pub const ACCDBLREAD = @intToPtr(*volatile MmioInt(32, u4), base_address + 0x548); pub const PSEL = struct { - /// address: 0x40012000 /// Pin select for LED signal pub const LED = @intToPtr(*volatile Mmio(32, packed struct { @@ -12739,7 +12715,6 @@ pub const registers = struct { }, base_address + 0x520); pub const PSEL = struct { - /// address: 0x4001c000 /// Description collection[0]: Output pin select for PWM channel 0 pub const OUT = @intToPtr(*volatile [4]Mmio(32, packed struct { @@ -12980,7 +12955,6 @@ pub const registers = struct { pub const GAINR = @intToPtr(*volatile MmioInt(32, u8), base_address + 0x51c); pub const PSEL = struct { - /// address: 0x4001d000 /// Pin number configuration for PDM CLK signal pub const CLK = @intToPtr(*volatile Mmio(32, packed struct { @@ -13053,7 +13027,6 @@ pub const registers = struct { }; pub const SAMPLE = struct { - /// address: 0x4001d000 /// RAM address pointer to write samples to with EasyDMA pub const PTR = @intToPtr(*volatile Mmio(32, packed struct { @@ -15873,7 +15846,6 @@ pub const registers = struct { pub const ENABLE = @intToPtr(*volatile MmioInt(32, u1), base_address + 0x500); pub const CONFIG = struct { - /// address: 0x40025000 /// I2S mode. pub const MODE = @intToPtr(*volatile MmioInt(32, u1), base_address + 0x0); @@ -15916,28 +15888,24 @@ pub const registers = struct { }; pub const RXD = struct { - /// address: 0x40025000 /// Receive buffer RAM start address. pub const PTR = @intToPtr(*volatile u32, base_address + 0x0); }; pub const TXD = struct { - /// address: 0x40025000 /// Transmit buffer RAM start address. pub const PTR = @intToPtr(*volatile u32, base_address + 0x0); }; pub const RXTXD = struct { - /// address: 0x40025000 /// Size of RXD and TXD buffers. pub const MAXCNT = @intToPtr(*volatile MmioInt(32, u14), base_address + 0x0); }; pub const PSEL = struct { - /// address: 0x40025000 /// Pin select for MCK signal. pub const MCK = @intToPtr(*volatile Mmio(32, packed struct { @@ -16833,7 +16801,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 diff --git a/src/modules/chips/stm32f103/registers.zig b/src/modules/chips/stm32f103/registers.zig index 10d7649..1edfad7 100644 --- a/src/modules/chips/stm32f103/registers.zig +++ b/src/modules/chips/stm32f103/registers.zig @@ -23541,7 +23541,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 diff --git a/src/modules/chips/stm32f303/registers.zig b/src/modules/chips/stm32f303/registers.zig index 64ff216..a4bf055 100644 --- a/src/modules/chips/stm32f303/registers.zig +++ b/src/modules/chips/stm32f303/registers.zig @@ -34397,7 +34397,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 diff --git a/src/modules/chips/stm32f407/registers.zig b/src/modules/chips/stm32f407/registers.zig index 7e08713..2b24c31 100644 --- a/src/modules/chips/stm32f407/registers.zig +++ b/src/modules/chips/stm32f407/registers.zig @@ -211,7 +211,6 @@ pub const VectorTable = extern struct { }; pub const registers = struct { - /// Random number generator pub const RNG = struct { pub const base_address = 0x50060800; @@ -52830,7 +52829,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 diff --git a/src/modules/chips/stm32f429/registers.zig b/src/modules/chips/stm32f429/registers.zig index 7bd4b62..077fcae 100644 --- a/src/modules/chips/stm32f429/registers.zig +++ b/src/modules/chips/stm32f429/registers.zig @@ -220,7 +220,6 @@ pub const VectorTable = extern struct { }; pub const registers = struct { - /// Random number generator pub const RNG = struct { pub const base_address = 0x50060800; @@ -53872,7 +53871,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 diff --git a/src/modules/cpus/cortex-m/cortex-m.zig b/src/modules/cpus/cortex-m/cortex-m.zig index bd1ecda..c2c6bc7 100644 --- a/src/modules/cpus/cortex-m/cortex-m.zig +++ b/src/modules/cpus/cortex-m/cortex-m.zig @@ -95,8 +95,7 @@ pub var vector_table: VectorTable = blk: { @compileLog("root.interrupts must be a struct"); inline for (@typeInfo(app.interrupts).Struct.decls) |decl| { - const calling_convention = @typeInfo(@TypeOf(@field(app.interrupts, decl.name))).Fn.calling_convention; - const handler = @field(app.interrupts, decl.name); + const function = @field(app.interrupts, decl.name); if (!@hasField(VectorTable, decl.name)) { var msg: []const u8 = "There is no such interrupt as '" ++ decl.name ++ "'. Declarations in 'interrupts' must be one of:\n"; @@ -112,22 +111,36 @@ pub var vector_table: VectorTable = blk: { if (!isValidField(decl.name)) @compileError("You are not allowed to specify '" ++ decl.name ++ "' in the vector table, for your sins you must now pay a $5 fine to the ZSF: https://github.com/sponsors/ziglang"); - @field(tmp, decl.name) = switch (calling_convention) { - .C => .{ .C = handler }, - .Naked => .{ .Naked = handler }, - // for unspecified calling convention we are going to generate small wrapper - .Unspecified => .{ - .C = struct { - fn wrapper() callconv(.C) void { - if (calling_convention == .Unspecified) // TODO: workaround for some weird stage1 bug - @call(.{ .modifier = .always_inline }, handler, .{}); - } - }.wrapper, - }, - - else => @compileError("unsupported calling convention for function " ++ decl.name), - }; + @field(tmp, decl.name) = createInterruptVector(function); } } break :blk tmp; }; + +fn createInterruptVector( + comptime function: anytype, +) microzig.chip.InterruptVector { + const calling_convention = @typeInfo(@TypeOf(function)).Fn.calling_convention; + return switch (calling_convention) { + .C => .{ .C = function }, + .Naked => .{ .Naked = function }, + // for unspecified calling convention we are going to generate small wrapper + .Unspecified => .{ + .C = struct { + fn wrapper() callconv(.C) void { + if (calling_convention == .Unspecified) // TODO: workaround for some weird stage1 bug + @call(.{ .modifier = .always_inline }, function, .{}); + } + }.wrapper, + }, + + else => |val| { + const conv_name = inline for (std.meta.fields(std.builtin.CallingConvention)) |field| { + if (val == @field(std.builtin.CallingConvention, field.name)) + break field.name; + } else unreachable; + + @compileError("unsupported calling convention for interrupt vector: " ++ conv_name); + }, + }; +}