Skip to content
Snippets Groups Projects
Commit 55613c5f authored by Benjamin Koch's avatar Benjamin Koch
Browse files

add more program info

parent c7286a08
No related branches found
No related tags found
No related merge requests found
...@@ -3,6 +3,8 @@ edition = "2021" ...@@ -3,6 +3,8 @@ edition = "2021"
name = "heizung" name = "heizung"
version = "0.1.0" version = "0.1.0"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
homepage = "https://git.c3pb.de/c3pb/heizung/-/tree/main/firmware/rust1"
description = "Heating control for Subraum"
[features] [features]
......
...@@ -699,6 +699,8 @@ fn init_early() { ...@@ -699,6 +699,8 @@ fn init_early() {
// Add program info. // Add program info.
// Show with: picotool info heizung-release.uf2 -a
// or `picotool info` if actual hardware is connected in bootloader mode
#[used] #[used]
#[link_section = ".program_info"] #[link_section = ".program_info"]
pub static PROGRAM_INFO: [u8; 4096] = { pub static PROGRAM_INFO: [u8; 4096] = {
...@@ -708,7 +710,23 @@ pub static PROGRAM_INFO: [u8; 4096] = { ...@@ -708,7 +710,23 @@ pub static PROGRAM_INFO: [u8; 4096] = {
const PROGRAM_INFO_TABLE_SIZE: u32 = 128; // one pointer (4 bytes) for each piece of data, all must be valid pointers const PROGRAM_INFO_TABLE_SIZE: u32 = 128; // one pointer (4 bytes) for each piece of data, all must be valid pointers
const PROGRAM_INFO_COPY_TABLE_SIZE: u32 = 128; // 3*u32 for each entry, picotool stops after 10 entries const PROGRAM_INFO_COPY_TABLE_SIZE: u32 = 128; // 3*u32 for each entry, picotool stops after 10 entries
#[cfg(debug_assertions)]
let build_type = "Debug";
#[cfg(not(debug_assertions))]
let build_type = "Release";
// We can fill in some values from info that is provided by Cargo.
// see https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates
ProgramInfoBuilder::new(PROGRAM_INFO_FLASH_OFFSET, PROGRAM_INFO_TABLE_SIZE, PROGRAM_INFO_COPY_TABLE_SIZE) ProgramInfoBuilder::new(PROGRAM_INFO_FLASH_OFFSET, PROGRAM_INFO_TABLE_SIZE, PROGRAM_INFO_COPY_TABLE_SIZE)
.program_name("Test 123") .program_name("subraum-heizung")
.program_description(env!("CARGO_PKG_DESCRIPTION"))
.program_version_string(env!("CARGO_PKG_VERSION"))
.program_url(env!("CARGO_PKG_HOMEPAGE"))
.board("subraum-heizung base v1.0")
.sdk_version("Embassy")
.program_build_attribute(build_type)
//FIXME should be based on what is selected for embassy-rp crate
.boot2_name("boot2_w25q080")
.build() .build()
}; };
pub struct ProgramInfoBuilder { pub struct ProgramInfoBuilder {
addr: u32, addr: u32,
buf: [u8; 4096], buf: [u8; 4096],
...@@ -8,6 +7,16 @@ pub struct ProgramInfoBuilder { ...@@ -8,6 +7,16 @@ pub struct ProgramInfoBuilder {
data_end_offset: usize, data_end_offset: usize,
} }
#[repr(u16)]
#[allow(non_camel_case_types)]
pub enum GroupFlags {
NONE = 0x0000,
SHOW_IF_EMPTY = 0x0001, // default is to hide
SEPARATE_COMMAS = 0x0002, // default is newlines
SORT_ALPHA = 0x0004, // default is no sort
ADVANCED = 0x0008, // if set, then only shown in say info -a
}
const fn copy(mut buf: [u8; 4096], offset: usize, source: &[u8], source_offset: usize) -> [u8; 4096] { const fn copy(mut buf: [u8; 4096], offset: usize, source: &[u8], source_offset: usize) -> [u8; 4096] {
if source_offset >= source.len() { if source_offset >= source.len() {
buf buf
...@@ -129,9 +138,9 @@ impl ProgramInfoBuilder { ...@@ -129,9 +138,9 @@ impl ProgramInfoBuilder {
.push(((value >> 24) & 0xff) as u8) .push(((value >> 24) & 0xff) as u8)
} }
const fn push_raspberry_tag(self: Self) -> Self { const fn push_tag(self: Self, tag: [char; 2]) -> Self {
self.push('R' as u8) self.push(tag[0] as u8)
.push('P' as u8) .push(tag[1] as u8)
} }
const fn push_extra_data(mut self: Self, value: &[u8]) -> (Self, u32) { const fn push_extra_data(mut self: Self, value: &[u8]) -> (Self, u32) {
...@@ -149,7 +158,7 @@ impl ProgramInfoBuilder { ...@@ -149,7 +158,7 @@ impl ProgramInfoBuilder {
//NOTE This will push the address and then add the string so this must be the last item of the data record. //NOTE This will push the address and then add the string so this must be the last item of the data record.
const fn push_string(mut self: Self, value: &str) -> Self { const fn push_string(mut self: Self, value: &str) -> Self {
if self.data_pos - self.info_pos < value.len() { if self.data_pos - self.info_pos < value.len() + 1 {
core::panic!("ProgramInfoBuilder: too much data") core::panic!("ProgramInfoBuilder: too much data")
} }
...@@ -170,34 +179,179 @@ impl ProgramInfoBuilder { ...@@ -170,34 +179,179 @@ impl ProgramInfoBuilder {
self self
} }
const BINARY_INFO_TYPE_ID_AND_INT: u16 = 5; const fn append_to_last_string(mut self: Self, value: &str) -> Self {
const BINARY_INFO_TYPE_ID_AND_STRING: u16 = 6; if self.data_pos - self.info_pos < value.len() {
core::panic!("ProgramInfoBuilder: too much data")
}
self.data_pos -= 1;
(self, _) = self.push_extra_data(value.as_bytes());
(self, _) = self.push_extra_data(&[0]);
self
}
pub const BINARY_INFO_ID_RP_PROGRAM_NAME: u32 = 0x02031c86; const fn bi_int(self: Self, tag: [char; 2], id: u32, value: u32) -> Self {
pub const BINARY_INFO_ID_RP_PROGRAM_VERSION_STRING: u32 = 0x11a9bc3a; self.push_current_info_ptr()
pub const BINARY_INFO_ID_RP_PROGRAM_BUILD_DATE_STRING: u32 = 0x9da22254; .push_u16(Self::BINARY_INFO_TYPE_ID_AND_INT)
pub const BINARY_INFO_ID_RP_BINARY_END: u32 = 0x68f465de; .push_tag(tag)
pub const BINARY_INFO_ID_RP_PROGRAM_URL: u32 = 0x1856239a; .push_u32(id)
pub const BINARY_INFO_ID_RP_PROGRAM_DESCRIPTION: u32 = 0xb6a07c19; .push_u32(value)
pub const BINARY_INFO_ID_RP_PROGRAM_FEATURE: u32 = 0xa1f4b453; }
pub const BINARY_INFO_ID_RP_PROGRAM_BUILD_ATTRIBUTE: u32 = 0x4275f0d3;
pub const BINARY_INFO_ID_RP_SDK_VERSION: u32 = 0x5360b3ab;
pub const BINARY_INFO_ID_RP_PICO_BOARD: u32 = 0xb63cffbb;
pub const BINARY_INFO_ID_RP_BOOT2_NAME: u32 = 0x7f8882e1;
pub const fn program_name(self: Self, value: &str) -> Self { const fn bi_string(self: Self, tag: [char; 2], id: u32, value: &str) -> Self {
self.push_current_info_ptr() self.push_current_info_ptr()
.push_u16(Self::BINARY_INFO_TYPE_ID_AND_STRING) .push_u16(Self::BINARY_INFO_TYPE_ID_AND_STRING)
.push_raspberry_tag() .push_tag(tag)
.push_u32(Self::BINARY_INFO_ID_RP_PROGRAM_NAME) .push_u32(id)
.push_string(value) .push_string(value)
} }
pub const fn binary_end_address(self: Self, value: u32) -> Self { const fn bi_named_group(self: Self, tag: [char; 2], id: u32, flags: u16, group_tag: u16, group_id: u32, label: &str) -> Self {
self.push_current_info_ptr() self.push_current_info_ptr()
.push_u16(Self::BINARY_INFO_TYPE_ID_AND_INT) .push_u16(Self::BINARY_INFO_TYPE_NAMED_GROUP)
.push_raspberry_tag() .push_tag(tag)
.push_u32(Self::BINARY_INFO_ID_RP_BINARY_END) .push_u32(id)
.push_u16(flags)
.push_u16(group_tag)
.push_u32(group_id)
.push_string(label)
}
const fn bi_encoded_pins_with_func(self: Self, value: u32) -> Self {
self.push_current_info_ptr()
.push_u16(Self::BINARY_INFO_TYPE_PINS_WITH_FUNC)
.push_tag(Self::BINARY_INFO_TAG_RASPBERRY_PI)
.push_u32(value) .push_u32(value)
} }
const fn bi_pins_with_names(self: Self, pin_mask: u32, label: &str) -> Self {
self.push_current_info_ptr()
.push_u16(Self::BINARY_INFO_TYPE_PINS_WITH_NAME)
.push_tag(Self::BINARY_INFO_TAG_RASPBERRY_PI)
.push_u32(pin_mask)
.push_string(label)
}
const BINARY_INFO_TAG_RASPBERRY_PI: [char; 2] = ['R', 'P'];
#[allow(unused)] const BINARY_INFO_TYPE_RAW_DATA: u16 = 1;
#[allow(unused)] const BINARY_INFO_TYPE_SIZED_DATA: u16 = 2;
#[allow(unused)] const BINARY_INFO_TYPE_BINARY_INFO_LIST_ZERO_TERMINATED: u16 = 3;
#[allow(unused)] const BINARY_INFO_TYPE_BSON: u16 = 4;
#[allow(unused)] const BINARY_INFO_TYPE_ID_AND_INT: u16 = 5;
#[allow(unused)] const BINARY_INFO_TYPE_ID_AND_STRING: u16 = 6;
#[allow(unused)] const BINARY_INFO_TYPE_BLOCK_DEVICE: u16 = 7;
#[allow(unused)] const BINARY_INFO_TYPE_PINS_WITH_FUNC: u16 = 8;
#[allow(unused)] const BINARY_INFO_TYPE_PINS_WITH_NAME: u16 = 9;
#[allow(unused)] const BINARY_INFO_TYPE_PINS_WITH_NAMES: u16 = 9;
#[allow(unused)] const BINARY_INFO_TYPE_NAMED_GROUP: u16 = 10;
#[allow(unused)] const BINARY_INFO_ID_RP_PROGRAM_NAME: u32 = 0x02031c86;
#[allow(unused)] const BINARY_INFO_ID_RP_PROGRAM_VERSION_STRING: u32 = 0x11a9bc3a;
#[allow(unused)] const BINARY_INFO_ID_RP_PROGRAM_BUILD_DATE_STRING: u32 = 0x9da22254;
#[allow(unused)] const BINARY_INFO_ID_RP_BINARY_END: u32 = 0x68f465de;
#[allow(unused)] const BINARY_INFO_ID_RP_PROGRAM_URL: u32 = 0x1856239a;
#[allow(unused)] const BINARY_INFO_ID_RP_PROGRAM_DESCRIPTION: u32 = 0xb6a07c19;
#[allow(unused)] const BINARY_INFO_ID_RP_PROGRAM_FEATURE: u32 = 0xa1f4b453;
#[allow(unused)] const BINARY_INFO_ID_RP_PROGRAM_BUILD_ATTRIBUTE: u32 = 0x4275f0d3;
#[allow(unused)] const BINARY_INFO_ID_RP_SDK_VERSION: u32 = 0x5360b3ab;
#[allow(unused)] const BINARY_INFO_ID_RP_PICO_BOARD: u32 = 0xb63cffbb;
#[allow(unused)] const BINARY_INFO_ID_RP_BOOT2_NAME: u32 = 0x7f8882e1;
pub const fn binary_end_address(self: Self, value: u32) -> Self {
self.bi_int(Self::BINARY_INFO_TAG_RASPBERRY_PI, Self::BINARY_INFO_ID_RP_BINARY_END, value)
}
pub const fn program_name(self: Self, name: &str) -> Self {
self.bi_string(Self::BINARY_INFO_TAG_RASPBERRY_PI, Self::BINARY_INFO_ID_RP_PROGRAM_NAME, name)
}
pub const fn program_description(self: Self, description: &str) -> Self {
self.bi_string(Self::BINARY_INFO_TAG_RASPBERRY_PI, Self::BINARY_INFO_ID_RP_PROGRAM_DESCRIPTION, description)
}
pub const fn program_version_string(self: Self, version_string: &str) -> Self {
self.bi_string(Self::BINARY_INFO_TAG_RASPBERRY_PI, Self::BINARY_INFO_ID_RP_PROGRAM_VERSION_STRING, version_string)
}
pub const fn program_build_date_string(self: Self, date_string: &str) -> Self {
self.bi_string(Self::BINARY_INFO_TAG_RASPBERRY_PI, Self::BINARY_INFO_ID_RP_PROGRAM_BUILD_DATE_STRING, date_string)
}
pub const fn program_url(self: Self, url: &str) -> Self {
self.bi_string(Self::BINARY_INFO_TAG_RASPBERRY_PI, Self::BINARY_INFO_ID_RP_PROGRAM_URL, url)
}
// multiple of these may be added
pub const fn program_feature(self: Self, feature: &str) -> Self {
self.bi_string(Self::BINARY_INFO_TAG_RASPBERRY_PI, Self::BINARY_INFO_ID_RP_PROGRAM_FEATURE, feature)
}
pub const fn program_build_attribute(self: Self, attr: &str) -> Self {
self.bi_string(Self::BINARY_INFO_TAG_RASPBERRY_PI, Self::BINARY_INFO_ID_RP_PROGRAM_BUILD_ATTRIBUTE, attr)
}
pub const fn sdk_version(self: Self, attr: &str) -> Self {
self.bi_string(Self::BINARY_INFO_TAG_RASPBERRY_PI, Self::BINARY_INFO_ID_RP_SDK_VERSION, attr)
}
pub const fn board(self: Self, attr: &str) -> Self {
self.bi_string(Self::BINARY_INFO_TAG_RASPBERRY_PI, Self::BINARY_INFO_ID_RP_PICO_BOARD, attr)
}
pub const fn boot2_name(self: Self, attr: &str) -> Self {
self.bi_string(Self::BINARY_INFO_TAG_RASPBERRY_PI, Self::BINARY_INFO_ID_RP_BOOT2_NAME, attr)
}
pub const fn program_feature_group(self: Self, tag: u16, id: u32, label: &str) -> Self {
self.program_feature_group_with_flags(tag, id, label, GroupFlags::NONE)
}
pub const fn program_feature_group_with_flags(self: Self, tag: u16, id: u32, label: &str, flags: GroupFlags) -> Self {
self.bi_named_group(Self::BINARY_INFO_TAG_RASPBERRY_PI, Self::BINARY_INFO_ID_RP_PROGRAM_FEATURE,
flags as u16, tag, id, label)
}
pub const fn pins_with_func(self: Self, func: u8, pins: &[u8]) -> Self {
assert!(func < 16);
assert!(pins.len() > 0 && pins.len() < 6);
const BI_PINS_ENCODING_MULTI: u32 = 2;
let encoded = if pins.len() == 1 {
BI_PINS_ENCODING_MULTI | ((func as u32) << 3) | ((pins[0] as u32) << 7) | ((pins[0] as u32) << 12)
} else if pins.len() == 2 {
BI_PINS_ENCODING_MULTI | ((func as u32) << 3) | ((pins[0] as u32) << 7) | ((pins[1] as u32) << 12) | ((pins[1] as u32) << 17)
} else if pins.len() == 3 {
BI_PINS_ENCODING_MULTI | ((func as u32) << 3) | ((pins[0] as u32) << 7) | ((pins[1] as u32) << 12) | ((pins[2] as u32) << 17) | ((pins[2] as u32) << 22)
} else if pins.len() == 4 {
BI_PINS_ENCODING_MULTI | ((func as u32) << 3) | ((pins[0] as u32) << 7) | ((pins[1] as u32) << 12) | ((pins[2] as u32) << 17) | ((pins[3] as u32) << 22) | ((pins[3] as u32) << 27)
} else if pins.len() == 5 {
BI_PINS_ENCODING_MULTI | ((func as u32) << 3) | ((pins[0] as u32) << 7) | ((pins[1] as u32) << 12) | ((pins[2] as u32) << 17) | ((pins[3] as u32) << 22) | ((pins[4] as u32) << 27)
} else {
assert!(false);
0
};
self.bi_encoded_pins_with_func(encoded)
}
pub const fn pin_range_with_func(self: Self, func: u8, pin_range: (u8, u8)) -> Self {
assert!(func < 16);
let (plo, phi) = pin_range;
const BI_PINS_ENCODING_RANGE: u32 = 1;
let encoded = BI_PINS_ENCODING_RANGE | ((func as u32) << 3) | ((plo as u32) << 7) | ((phi as u32) << 12);
self.bi_encoded_pins_with_func(encoded)
}
pub const fn pins_with_names(mut self: Self, pins: &[(u8, &str)]) -> Self {
const fn collect_mask(mask: u32, pins: &[(u8, &str)], offset: usize) -> u32 {
if offset >= pins.len() {
mask
} else {
collect_mask(mask | (1 << pins[offset].0), pins, offset+1)
}
}
self = self.bi_pins_with_names(collect_mask(0, pins, 0), pins[0].1);
const fn append_names(acc: ProgramInfoBuilder, pins: &[(u8, &str)], offset: usize) -> ProgramInfoBuilder {
if offset >= pins.len() {
acc
} else {
append_names(acc.append_to_last_string("|").append_to_last_string(pins[offset].1), pins, offset+1)
}
}
append_names(self, pins, 1)
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment