diff --git a/core/src/cpus/cortex_m/m33.zig b/core/src/cpus/cortex_m/m33.zig index e04c1cd89..eeeb135e4 100644 --- a/core/src/cpus/cortex_m/m33.zig +++ b/core/src/cpus/cortex_m/m33.zig @@ -238,7 +238,30 @@ pub const SystemControlBlock = extern struct { _AFSR: u32, reserved1: [18]u32, /// Coprocessor Access Control Register. - CPACR: u32, + CPACR: mmio.Mmio(packed struct(u32) { + CP0: Privilege, + CP1: Privilege, + CP2: Privilege, + CP3: Privilege, + CP4: Privilege, + CP5: Privilege, + CP6: Privilege, + CP7: Privilege, + reserved16: u4, + CP10: Privilege, + CP11: Privilege, + reserved24: u8, + + pub const Privilege = enum(u2) { + /// Access denied. Any attempted access generates a NOCP UsageFault. + access_denied = 0b00, + /// Privileged access only. An unprivileged access generates a NOCP UsageFault. + priviledged_access_only = 0b01, + reserved = 0b10, + /// Full access. + full_access = 0b11, + }; + }), /// Non-secure Access Control Register. NSACR: u32, }; diff --git a/port/raspberrypi/rp2xxx/src/hal.zig b/port/raspberrypi/rp2xxx/src/hal.zig index 56f887f02..5addbaacf 100644 --- a/port/raspberrypi/rp2xxx/src/hal.zig +++ b/port/raspberrypi/rp2xxx/src/hal.zig @@ -99,33 +99,7 @@ const is_fpu_used: bool = builtin.abi.float() == .hard; /// Allows user to easily swap in their own clock config while still /// using the recommended initialization sequence pub fn init_sequence(comptime clock_cfg: clocks.config.Global) void { - if (compatibility.chip == .RP2350 and - compatibility.arch == .arm) - { - var cpacr: u32 = microzig.cpu.peripherals.scb.CPACR; - - if (microzig.options.hal.enable_fpu) { - if (is_fpu_used) { - // enable lazy state preservation - microzig.cpu.peripherals.fpu.FPCCR.modify(.{ - .ASPEN = 1, - .LSPEN = 1, - }); - - // enable the FPU - cpacr |= 0xF << 20; - } else { - @compileError("target doesn't have FPU features enabled"); - } - } - - if (microzig.options.hal.use_dcp) { - // enable the DCP - cpacr |= 0b11 << 8; - } - - microzig.cpu.peripherals.scb.CPACR = cpacr; - } + maybe_enable_fpu_and_dcp(); // Disable the watchdog as a soft reset doesn't disable the WD automatically! watchdog.disable(); @@ -155,6 +129,40 @@ pub fn init_sequence(comptime clock_cfg: clocks.config.Global) void { resets.unreset_block_wait(resets.masks.all); } +/// Enables fpu and/or dcp on RP2350 arm if requested in HAL options. On RP2350 +/// riscv and RP2040 this is a noop. Called in init_sequence and on core1 +/// startup. +pub fn maybe_enable_fpu_and_dcp() void { + if (compatibility.chip == .RP2350 and + compatibility.arch == .arm) + { + if (microzig.options.hal.enable_fpu) { + if (is_fpu_used) { + // enable lazy state preservation + microzig.cpu.peripherals.fpu.FPCCR.modify(.{ + .ASPEN = 1, + .LSPEN = 1, + }); + + // enable the FPU for the current core + microzig.cpu.peripherals.scb.CPACR.modify(.{ + .CP10 = .full_access, + .CP11 = .full_access, + }); + } else { + @compileError("target doesn't have FPU features enabled"); + } + } + + if (microzig.options.hal.use_dcp) { + // enable the DCP for the current core + microzig.cpu.peripherals.scb.CPACR.modify(.{ + .CP4 = .full_access, + }); + } + } +} + pub fn get_cpu_id() u32 { return SIO.CPUID.read().CPUID; } diff --git a/port/raspberrypi/rp2xxx/src/hal/multicore.zig b/port/raspberrypi/rp2xxx/src/hal/multicore.zig index 40da185f0..b99061498 100644 --- a/port/raspberrypi/rp2xxx/src/hal/multicore.zig +++ b/port/raspberrypi/rp2xxx/src/hal/multicore.zig @@ -77,6 +77,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; + microzig.hal.maybe_enable_fpu_and_dcp(); @as(*const fn () void, @ptrFromInt(entry))(); } }._wrapper;