ZigEmbeddedGroup / microzig

Unified abstraction layer and HAL for several microcontrollers
zlib License
1.19k stars 90 forks source link

Incorrect CPU specified for all STM32 variants with cortex-m4 #245

Open Copper280z opened 3 days ago

Copper280z commented 3 days ago

Every STM32 with a cortex m4 has the incorrect CPU specified, all are specified with MicroZig.cpus.cortex_m4 when I believe they should be MicroZig.cpus.cortex_m4f. I don't think ST has an M4 without FPU, but if they do it's an outlier.

Example:

pub const STM32F401CC = MicroZig.Target{
    .preferred_format = .elf,
    .chip = .{
        .name = "STM32F401CC",
        .cpu = MicroZig.cpus.cortex_m4,
        .memory_regions = &.{
            .{ .offset = 0x8000000, .length = 0x10000, .kind = .flash },
            .{ .offset = 0x8010000, .length = 0x10000, .kind = .flash },
            .{ .offset = 0x8020000, .length = 0x20000, .kind = .flash },
            .{ .offset = 0x20000000, .length = 0x10000, .kind = .ram },
        },
        .register_definition = .{
            .zig = .{ .cwd_relative = register_definition_path },
        },
    },
};

This makes it rather unintuitive to use the FPU because you need to fix/replace the definition in your projects build.zig, and as far as I can see there's no public way to access the register definitions in all.zig.

ikskuh commented 3 days ago

Feel free to create a PR to fix all of those in the port :)

Copper280z commented 2 days ago

I assume these files are generated by generate.zig+regz? It seems that the ST svd doesn't specify that there is an FPU, I assume the embassy database is similar, but it does show up as a peripheral. This seems like it falls into patching vs "intelligent parsing logic" design decision. Is checking for an FPU peripheral and setting the target as m4f if it's present an acceptable solution? Same for the MPU, since I see the same pattern in the snips below.

pub const devices = struct {
    ///  STM32F446
    pub const STM32F446 = struct {
        pub const properties = struct {
            pub const @"cpu.endian" = "little";
            pub const @"cpu.mpuPresent" = "false";
            pub const @"cpu.revision" = "r1p0";
            pub const @"cpu.name" = "CM4";
            pub const @"cpu.nvicPrioBits" = "3";
            pub const @"cpu.vendorSystickConfig" = "false";
            pub const @"cpu.fpuPresent" = "false";
        };
            pub const FPU_CPACR: *volatile types.peripherals.FPU_CPACR = @ptrFromInt(0xe000ed88);
            ///  Memory protection unit
            pub const MPU: *volatile types.peripherals.MPU = @ptrFromInt(0xe000ed90);
            ///  Nested vectored interrupt controller
            pub const NVIC_STIR: *volatile types.peripherals.NVIC_STIR = @ptrFromInt(0xe000ef00);
            ///  Floting point unit
            pub const FPU: *volatile types.peripherals.FPU = @ptrFromInt(0xe000ef34);

We could also sidestep for now and make the register defs public and suggest using a project scope defined target that points to them.

ikskuh commented 2 days ago

Is checking for an FPU peripheral and setting the target as m4f if it's present an acceptable solution?

I'd say so