Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Some predefined registers for Cortex M #190

Merged
merged 1 commit into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading