Skip to content

Commit

Permalink
remove unnecessary casts and modify rp2040-only rom func control flow
Browse files Browse the repository at this point in the history
  • Loading branch information
piotrfila committed Feb 10, 2025
1 parent 6c561fe commit 5543589
Showing 1 changed file with 81 additions and 85 deletions.
166 changes: 81 additions & 85 deletions port/raspberrypi/rp2xxx/src/hal/rom.zig
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ const microzig = @import("microzig");
const chip = microzig.hal.compatibility.chip;

/// Function codes to lookup public functions that provide useful RP2040 functionality
pub const Code = enum(u32) {
popcount32 = rom_table_code('P', '3'), // Only avaiable on: RP2040
reverse32 = rom_table_code('R', '3'), // Only avaiable on: RP2040
clz32 = rom_table_code('L', '3'), // Only avaiable on: RP2040
ctz32 = rom_table_code('T', '3'), // Only avaiable on: RP2040
memset = rom_table_code('M', 'S'), // Only avaiable on: RP2040
memset4 = rom_table_code('S', '4'), // Only avaiable on: RP2040
memcpy = rom_table_code('M', 'C'), // Only avaiable on: RP2040
memcpy44 = rom_table_code('C', '4'), // Only avaiable on: RP2040
pub const Code = enum(u16) {
popcount32 = rom_table_code('P', '3'), // Only avaiable on: RP2040
reverse32 = rom_table_code('R', '3'), // Only avaiable on: RP2040
clz32 = rom_table_code('L', '3'), // Only avaiable on: RP2040
ctz32 = rom_table_code('T', '3'), // Only avaiable on: RP2040
memset = rom_table_code('M', 'S'), // Only avaiable on: RP2040
memset4 = rom_table_code('S', '4'), // Only avaiable on: RP2040
memcpy = rom_table_code('M', 'C'), // Only avaiable on: RP2040
memcpy44 = rom_table_code('C', '4'), // Only avaiable on: RP2040
connect_internal_flash = rom_table_code('I', 'F'),
flash_exit_xip = rom_table_code('E', 'X'),
flash_range_erase = rom_table_code('R', 'E'),
Expand All @@ -36,7 +36,7 @@ pub const Code = enum(u32) {
/// Signatures of all public bootrom functions
pub const signatures = struct {
/// Returns the 32 bit pointer into the ROM if found or NULL otherwise
const rom_table_lookup = fn (table: *u16, code: u32) *anyopaque;
const rom_table_lookup = fn (table: [*]u16, code: u32) *anyopaque;
/// Signature for popcount32: Return a count of the number of 1 bits in value
const popcount32 = fn (value: u32) u32;
/// Signature for reverse32: Return the bits of value in the reverse order
Expand Down Expand Up @@ -90,8 +90,8 @@ pub const signatures = struct {
/// # Returns
///
/// A 32 bit address pointing into bootrom
pub fn rom_table_code(c1: u8, c2: u8) u32 {
return @as(u32, @intCast(c1)) | (@as(u32, @intCast(c2)) << 8);
pub fn rom_table_code(c1: u8, c2: u8) u16 {
return @as(u32, c1) | (@as(u32, c2) << 8);
}

/// Convert a 16 bit pointer stored at the given rom address into a pointer
Expand All @@ -103,8 +103,8 @@ pub fn rom_table_code(c1: u8, c2: u8) u32 {
///
/// The converted pointer
pub inline fn rom_hword_as_ptr(rom_addr: u32) *anyopaque {
const ptr_to_ptr = @as(*u16, @ptrFromInt(rom_addr));
return @as(*anyopaque, @ptrFromInt(@as(usize, @intCast(ptr_to_ptr.*))));
const ptr_to_ptr: *u16 = @ptrFromInt(rom_addr);
return @ptrFromInt(ptr_to_ptr.*);
}

/// Lookup a bootrom function by code (inline)
Expand All @@ -116,8 +116,8 @@ pub inline fn rom_hword_as_ptr(rom_addr: u32) *anyopaque {
///
/// A anyopaque pointer to the function; must be cast by the caller
pub inline fn _rom_func_lookup(code: Code) *anyopaque {
const rom_table_lookup = @as(*signatures.rom_table_lookup, @ptrCast(rom_hword_as_ptr(0x18)));
const func_table = @as(*u16, @ptrCast(@alignCast(rom_hword_as_ptr(0x14))));
const rom_table_lookup: *signatures.rom_table_lookup = @ptrCast(rom_hword_as_ptr(0x18));
const func_table: [*]u16 = @ptrCast(@alignCast(rom_hword_as_ptr(0x14)));
return rom_table_lookup(func_table, @intFromEnum(code));
}

Expand All @@ -139,62 +139,69 @@ pub fn rom_func_lookup(code: Code) *anyopaque {

/// Return a count of the number of 1 bits in value
pub fn popcount32(value: u32) u32 {
if (chip == .RP2350) {
// RP2350, supports fast assembly version
return @popCount(value);
}

const S = struct {
var f: ?*signatures.popcount32 = null;
};

if (S.f == null) S.f = @as(*signatures.popcount32, @ptrCast(_rom_func_lookup(Code.popcount32)));
return S.f.?(value);
switch (chip) {
.RP2040 => {
if (S.f == null)
S.f = @ptrCast(_rom_func_lookup(Code.popcount32));
return S.f.?(value);
},
.RP2350 => return @popCount(value),
}
}

/// Return a count of the number of 1 bits in value
pub fn reverse32(value: u32) u32 {
if (chip == .RP2350) {
// RP2350, supports fast assembly version
return @bitReverse(value);
}

const S = struct {
var f: ?*signatures.reverse32 = null;
};

if (S.f == null) S.f = @as(*signatures.reverse32, @ptrCast(_rom_func_lookup(Code.reverse32)));
return S.f.?(value);
switch (chip) {
.RP2040 => {
if (S.f == null)
S.f = @ptrCast(_rom_func_lookup(Code.reverse32));
return S.f.?(value);
},
// RP2350, supports fast assembly version
.RP2350 => return @bitReverse(value),
}
}

/// Return the number of consecutive high order 0 bits of value
pub fn clz32(value: u32) u32 {
if (chip == .RP2350) {
// RP2350, supports fast assembly version
return @clz(value);
}

const S = struct {
var f: ?*signatures.clz32 = null;
};

if (S.f == null) S.f = @as(*signatures.clz32, @ptrCast(_rom_func_lookup(Code.clz32)));
return S.f.?(value);
switch (chip) {
.RP2040 => {
if (S.f == null)
S.f = @ptrCast(_rom_func_lookup(Code.clz32));
return S.f.?(value);
},
// RP2350, supports fast assembly version
.RP2350 => return @clz(value),
}
}

/// Return the number of consecutive low order 0 bits of value
pub fn ctz32(value: u32) u32 {
if (chip == .RP2350) {
// RP2350, supports fast assembly version
return @ctz(value);
}

const S = struct {
var f: ?*signatures.ctz32 = null;
};

if (S.f == null) S.f = @as(*signatures.ctz32, @ptrCast(_rom_func_lookup(Code.ctz32)));
return S.f.?(value);
switch (chip) {
.RP2040 => {
if (S.f == null)
S.f = @ptrCast(_rom_func_lookup(Code.ctz32));
return S.f.?(value);
},
// RP2350, supports fast assembly version
.RP2350 => return @ctz(value),
}
}

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Expand All @@ -203,35 +210,42 @@ pub fn ctz32(value: u32) u32 {

/// Sets all bytes of dest to the value c and returns ptr
pub fn memset(dest: []u8, c: u8) []u8 {
if (chip == .RP2350) {
@memset(dest, c);
return dest;
}

const S = struct {
var f: ?*signatures.memset = null;
};

if (S.f == null) S.f = @as(*signatures.memset, @ptrCast(_rom_func_lookup(Code.memset)));
return S.f.?(dest.ptr, c, dest.len)[0..dest.len];
switch (chip) {
.RP2040 => {
if (S.f == null)
S.f = @ptrCast(_rom_func_lookup(Code.memset));
return S.f.?(dest.ptr, c, dest.len)[0..dest.len];
},
.RP2350 => {
@memset(dest, c);
return dest;
},
}
}

/// Copies n bytes from src to dest; The number of bytes copied is the size of the smaller slice
pub fn memcpy(dest: []u8, src: []const u8) []u8 {
if (chip == .RP2350) {
// For some reason @memcpy crash chip with HardFault interrupt (UNALIGNED)
std.mem.copyForwards(u8, dest, src);
return dest;
}

const S = struct {
var f: ?*signatures.memcpy = null;
};

const n = if (dest.len <= src.len) dest.len else src.len;

if (S.f == null) S.f = @as(*signatures.memcpy, @ptrCast(_rom_func_lookup(Code.memcpy)));
return S.f.?(dest.ptr, src.ptr, n)[0..n];
switch (chip) {
.RP2040 => {
const n = @min(dest.len, src.len);
if (S.f == null)
S.f = @ptrCast(_rom_func_lookup(Code.memcpy));
return S.f.?(dest.ptr, src.ptr, n)[0..n];
},
// For some reason @memcpy crash chip with HardFault interrupt (UNALIGNED)
.RP2350 => {
std.mem.copyForwards(u8, dest, src);
return dest;
},
}
}

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Expand All @@ -240,10 +254,7 @@ pub fn memcpy(dest: []u8, src: []const u8) []u8 {

/// Restore all QSPI pad controls to their default state, and connect the SSI to the QSPI pads
pub inline fn connect_internal_flash() *signatures.connect_internal_flash {
return @as(
*signatures.connect_internal_flash,
@ptrCast(_rom_func_lookup(Code.connect_internal_flash)),
);
return @ptrCast(_rom_func_lookup(Code.connect_internal_flash));
}

/// First set up the SSI for serial-mode operations, then issue the fixed XIP exit
Expand All @@ -252,10 +263,7 @@ pub inline fn connect_internal_flash() *signatures.connect_internal_flash {
/// SSI to XIP mode (e.g. by a call to _flash_flush_cache). This function configures
/// the SSI with a fixed SCK clock divisor of /6.
pub inline fn flash_exit_xip() *signatures.flash_exit_xip {
return @as(
*signatures.flash_exit_xip,
@ptrCast(_rom_func_lookup(Code.flash_exit_xip)),
);
return @ptrCast(_rom_func_lookup(Code.flash_exit_xip));
}

/// Erase a count bytes, starting at addr (offset from start of flash). Optionally,
Expand All @@ -264,29 +272,20 @@ pub inline fn flash_exit_xip() *signatures.flash_exit_xip {
/// possible, for much higher erase speed. addr must be aligned to a 4096-byte sector,
/// and count must be a multiple of 4096 bytes.
pub inline fn flash_range_erase() *signatures.flash_range_erase {
return @as(
*signatures.flash_range_erase,
@ptrCast(_rom_func_lookup(Code.flash_range_erase)),
);
return @ptrCast(_rom_func_lookup(Code.flash_range_erase));
}

/// Program data to a range of flash addresses starting at addr (offset from the
/// start of flash) and count bytes in size. addr must be aligned to a 256-byte
/// boundary, and the length of data must be a multiple of 256.
pub inline fn flash_range_program() *signatures.flash_range_program {
return @as(
*signatures.flash_range_program,
@ptrCast(_rom_func_lookup(Code.flash_range_program)),
);
return @ptrCast(_rom_func_lookup(Code.flash_range_program));
}

/// Flush and enable the XIP cache. Also clears the IO forcing on QSPI CSn, so that
/// the SSI can drive the flash chip select as normal.
pub inline fn flash_flush_cache() *signatures.flash_flush_cache {
return @as(
*signatures.flash_flush_cache,
@ptrCast(_rom_func_lookup(Code.flash_flush_cache)),
);
return @ptrCast(_rom_func_lookup(Code.flash_flush_cache));
}

/// Configure the SSI to generate a standard 03h serial read command, with 24 address
Expand All @@ -296,8 +295,5 @@ pub inline fn flash_flush_cache() *signatures.flash_flush_cache {
/// visible to the debug host, without having to know exactly what kind of flash
/// device is connected.
pub inline fn flash_enter_cmd_xip() *signatures.flash_enter_cmd_xip {
return @as(
*signatures.flash_enter_cmd_xip,
@ptrCast(_rom_func_lookup(Code.flash_enter_cmd_xip)),
);
return @ptrCast(_rom_func_lookup(Code.flash_enter_cmd_xip));
}

0 comments on commit 5543589

Please sign in to comment.