Skip to content

Commit

Permalink
some predefined registers for Cortex M (#190)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattnite authored May 14, 2024
1 parent 095630e commit ea809c6
Show file tree
Hide file tree
Showing 8 changed files with 232 additions and 24 deletions.
3 changes: 3 additions & 0 deletions build/build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ pub fn add_firmware(
.target = mz.host_build.resolveTargetQuery(chip.cpu.target),
.linkage = .static,
.root_source_file = .{ .cwd_relative = mz.microzig_core.builder.pathFromRoot("src/start.zig") },
.strip = options.strip,
}),
.target = options.target,
.output_files = Firmware.OutputFileMap.init(host_build.allocator),
Expand Down Expand Up @@ -358,6 +359,8 @@ pub const FirmwareOptions = struct {

/// If set, overrides the `linker_script` property of the target.
linker_script: ?LazyPath = null,

strip: bool = false,
};

/// Configuration options for firmware installation.
Expand Down
8 changes: 4 additions & 4 deletions core/build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub const cpus = struct {

pub const cortex_m0 = MicroZig.Cpu{
.name = "ARM Cortex-M0",
.root_source_file = .{ .path = build_root ++ "/src/cpus/cortex-m.zig" },
.root_source_file = .{ .path = build_root ++ "/src/cpus/cortex_m.zig" },
.target = std.zig.CrossTarget{
.cpu_arch = .thumb,
.cpu_model = .{ .explicit = &std.Target.arm.cpu.cortex_m0 },
Expand All @@ -40,7 +40,7 @@ pub const cpus = struct {

pub const cortex_m0plus = MicroZig.Cpu{
.name = "ARM Cortex-M0+",
.root_source_file = .{ .path = build_root ++ "/src/cpus/cortex-m.zig" },
.root_source_file = .{ .path = build_root ++ "/src/cpus/cortex_m.zig" },
.target = std.zig.CrossTarget{
.cpu_arch = .thumb,
.cpu_model = .{ .explicit = &std.Target.arm.cpu.cortex_m0plus },
Expand All @@ -51,7 +51,7 @@ pub const cpus = struct {

pub const cortex_m3 = MicroZig.Cpu{
.name = "ARM Cortex-M3",
.root_source_file = .{ .path = build_root ++ "/src/cpus/cortex-m.zig" },
.root_source_file = .{ .path = build_root ++ "/src/cpus/cortex_m.zig" },
.target = std.zig.CrossTarget{
.cpu_arch = .thumb,
.cpu_model = .{ .explicit = &std.Target.arm.cpu.cortex_m3 },
Expand All @@ -62,7 +62,7 @@ pub const cpus = struct {

pub const cortex_m4 = MicroZig.Cpu{
.name = "ARM Cortex-M4",
.root_source_file = .{ .path = build_root ++ "/src/cpus/cortex-m.zig" },
.root_source_file = .{ .path = build_root ++ "/src/cpus/cortex_m.zig" },
.target = std.zig.CrossTarget{
.cpu_arch = .thumb,
.cpu_model = .{ .explicit = &std.Target.arm.cpu.cortex_m4 },
Expand Down
59 changes: 40 additions & 19 deletions core/src/cpus/cortex-m.zig → core/src/cpus/cortex_m.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,49 @@ const microzig = @import("microzig");
const mmio = microzig.mmio;
const root = @import("root");

pub const regs = struct {
// Interrupt Control and State Register
pub const ICSR: *volatile mmio.Mmio(packed struct {
VECTACTIVE: u9,
reserved0: u2,
RETTOBASE: u1,
VECTPENDING: u9,
reserved1: u1,
ISRPENDING: u1,
ISRPREEMPT: u1,
reserved2: u1,
PENDSTCLR: u1,
PENDSTSET: u1,
PENDSVCLR: u1,
PENDSVSET: u1,
reserved3: u2,
NMIPENDSET: u1,
}) = @ptrFromInt(0xE000ED04);
const scs_base = 0xE000E000;
const itm_base = 0xE0000000;
const dwt_base = 0xE0001000;
const tpi_base = 0xE0040000;
const coredebug_base = 0xE000EDF0;
const systick_base = scs_base + 0x0010;
const nvic_base = scs_base + 0x0100;
const scb_base = scs_base + 0x0D00;
const mpu_base = scs_base + 0x0D90;

const Core = enum {
@"ARM Cortex-M0",
@"ARM Cortex-M0+",
@"ARM Cortex-M3",
@"ARM Cortex-M4",
};

const core: type = blk: {
const cortex_m = std.meta.stringToEnum(microzig.config.cpu_name) orelse @panic(std.fmt.comptimePrint("Unrecognized Cortex-M core name: {s}", .{microzig.config.cpu_name}));
break :blk switch (cortex_m) {
.@"ARM Cortex-M0" => @import("cortex_m/m0"),
.@"ARM Cortex-M0+" => @import("cortex_m/m0plus.zig"),
.@"ARM Cortex-M3" => @import("cortex_m/m3.zig"),
.@"ARM Cortex-M4" => @import("cortex_m/m4.zig"),
};
};

const properties = microzig.chip.properties;
// TODO: will have to standardize this with regz code generation
const mpu_present = @hasDecl(properties, "__MPU_PRESENT") and std.mem.eql(u8, properties.__MPU_PRESENT, "1");

/// System Control Block (SCB)
pub const scb: *volatile core.SystemControlBlock = @ptrFromInt(scb_base);
/// Nested Vector Interrupt Controller (NVIC)
pub const nvic: *volatile core.NestedVectorInterruptController = @ptrFromInt(nvic_base);
/// Memory Protection Unit (MPU)
pub const mpu: *volatile core.MemoryProtectionUnit = if (mpu_present)
@ptrFromInt(mpu_base)
else
@compileError("Cortex-M does not have an MPU");

pub fn executing_isr() bool {
return regs.ICSR.read().VECTACTIVE != 0;
return scb.ICSR.read().VECTACTIVE != 0;
}

pub fn enable_interrupts() void {
Expand Down
3 changes: 3 additions & 0 deletions core/src/cpus/cortex_m/m0.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub const SystemControlBlock = @compileError("TODO");
pub const NestedVectorInterruptController = @compileError("TODO");
pub const MemoryProtectionUnit = @compileError("TODO");
3 changes: 3 additions & 0 deletions core/src/cpus/cortex_m/m0plus.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub const SystemControlBlock = @compileError("TODO");
pub const NestedVectorInterruptController = @compileError("TODO");
pub const MemoryProtectionUnit = @compileError("TODO");
3 changes: 3 additions & 0 deletions core/src/cpus/cortex_m/m3.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub const SystemControlBlock = @compileError("TODO");
pub const NestedVectorInterruptController = @compileError("TODO");
pub const MemoryProtectionUnit = @compileError("TODO");
156 changes: 156 additions & 0 deletions core/src/cpus/cortex_m/m4.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
const microzig = @import("microzig");
const mmio = microzig.mmio;

pub const SystemControlBlock = extern struct {
/// CPUID Base Register
CPUID: u32,
/// Interrupt Control and State Register
ICSR: mmio.Mmio(packed struct(u32) {
VECTACTIVE: u9,
reserved0: u2 = 0,
RETTOBASE: u1,
VECTPENDING: u9,
reserved1: u1 = 0,
ISRPENDING: u1,
ISRPREEMPT: u1,
reserved2: u1 = 0,
PENDSTCLR: u1,
PENDSTSET: u1,
PENDSVCLR: u1,
PENDSVSET: u1,
reserved3: u2 = 0,
NMIPENDSET: u1,
}),
/// Vector Table Offset Register
VTOR: u32,
/// Application Interrupt and Reset Control Register
AIRCR: u32,
/// System Control Register
SCR: u32,
/// Configuration Control Register
CCR: mmio.Mmio(packed struct(u32) {
NONBASETHRDENA: u1,
USERSETMPEND: u1,
_reserved0: u1 = 0,
UNALIGN_TRP: u1,
DIV_0_TRP: u1,
_reserved1: u3 = 0,
BFHFNMIGN: u1,
STKALIGN: u1,
_padding: u22 = 0,
}),
/// System Handlers Priority Registers
SHP: [12]u8,
/// System Handler Contol and State Register
SHCSR: u32,
/// Configurable Fault Status Register
CFSR: u32,
/// HardFault Status Register
HFSR: u32,
/// Debug Fault Status Register
DFSR: u32,
/// MemManage Fault Address Register
MMFAR: u32,
/// BusFault Address Register
BFAR: u32,
/// Auxilary Feature Register
AFSR: u32,
/// Processor Feature Register
PFR: [2]u32,
/// Debug Feature Register
DFR: u32,
/// Auxilary Feature Register
ADR: u32,
/// Memory Model Feature Register
MMFR: [4]u32,
/// Instruction Set Attributes Register
ISAR: [5]u32,
RESERVED0: [5]u32,
/// Coprocessor Access Control Register
CPACR: u32,
};

pub const NestedVectorInterruptController = extern struct {
ISER: [8]u32,
_reserved0: [24]u32,
ICER: [8]u32,
_reserved1: [24]u32,
ISPR: [8]u32,
_reserved2: [24]u32,
ICPR: [8]u32,
_reserved3: [24]u32,
IABR: [8]u32,
_reserved4: [56]u32,
IP: [240]u8,
_reserved5: [644]u32,
STIR: u32,
};

pub const MemoryProtectionUnit = extern struct {
/// MPU Type Register
TYPE: mmio.Mmio(packed struct(u32) {
SEPARATE: u1,
_reserved0: u7,
DREGION: u8,
IREGION: u8,
_reserved1: u8,
}),
/// MPU Control Register
CTRL: mmio.Mmio(packed struct(u32) {
ENABLE: u1,
HFNMIENA: u1,
PRIVDEFENA: u1,
padding: u29,
}),
/// MPU RNRber Register
RNR: mmio.Mmio(packed struct(u32) {
REGION: u8,
padding: u24,
}),
/// MPU Region Base Address Register
RBAR: RBAR,
/// MPU Region Attribute and Size Register
RASR: RASR,
/// MPU Alias 1 Region Base Address Register
RBAR_A1: RBAR,
/// MPU Alias 1 Region Attribute and Size Register
RASR_A1: RASR,
/// MPU Alias 2 Region Base Address Register
RBAR_A2: RBAR,
/// MPU Alias 2 Region Attribute and Size Register
RASR_A2: RASR,
/// MPU Alias 3 Region Base Address Register
RBAR_A3: RBAR,
/// MPU Alias 3 Region Attribute and Size Register
RASR_A3: RASR,

pub const RBAR = mmio.Mmio(packed struct(u32) {
REGION: u4,
VALID: u1,
ADDR: u27,
});

pub const RASR = mmio.Mmio(packed struct(u32) {
/// Region enable bit
ENABLE: u1,
/// Region Size
SIZE: u5,
_reserved0: u2,
/// Sub-Region Disable
SRD: u8,
/// ATTRS.B
B: u1,
/// ATTRS.C
C: u1,
/// ATTRS.S
S: u1,
/// ATTRS.TEX
TEX: u3,
_reserved1: u2,
/// ATTRS.AP
AP: u3,
/// ATTRS.XN
XN: u1,
padding: u4,
});
};
21 changes: 20 additions & 1 deletion tools/regz/src/atdf.zig
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ fn load_device(ctx: *Context, node: xml.Node) !void {
if (node.find_child(&.{"interrupts"})) |interrupts_node|
try load_interrupts(ctx, interrupts_node, id);

var param_it = node.iterate(&.{"parameters"}, &.{"param"});
while (param_it.next()) |param_node|
try load_param(ctx, param_node, id);

try infer_peripheral_offsets(ctx);
try infer_enum_sizes(ctx);

Expand All @@ -98,11 +102,26 @@ fn load_device(ctx: *Context, node: xml.Node) !void {
// events.generators.generator
// events.users.user
// interfaces.interface.parameters.param
// parameters.param

// property-groups.property-group.property
}

fn load_param(ctx: *Context, node: xml.Node, device_id: EntityId) !void {
const db = ctx.db;
assert(db.entity_is("instance.device", device_id));
validate_attrs(node, &.{
"name",
"value",
});

const name = node.get_attribute("name") orelse return error.MissingParamName;
const value = node.get_attribute("value") orelse return error.MissingParamName;
// TODO: do something with caption
_ = node.get_attribute("caption");

try db.add_device_property(device_id, name, value);
}

fn load_interrupts(ctx: *Context, node: xml.Node, device_id: EntityId) !void {
var interrupt_it = node.iterate(&.{}, &.{"interrupt"});
while (interrupt_it.next()) |interrupt_node|
Expand Down

0 comments on commit ea809c6

Please sign in to comment.