From 6ac96671513d40bfec5d0e14712323a4845db698 Mon Sep 17 00:00:00 2001 From: Benjamin Koch <bbbsnowball@gmail.com> Date: Sun, 11 Jun 2023 00:36:44 +0200 Subject: [PATCH] refactoring: move ProgramInfoBuilder into dedicated file --- firmware/rust1/src/bin/heizung.rs | 203 +---------------------------- firmware/rust1/src/lib.rs | 1 + firmware/rust1/src/program_info.rs | 203 +++++++++++++++++++++++++++++ 3 files changed, 208 insertions(+), 199 deletions(-) create mode 100644 firmware/rust1/src/program_info.rs diff --git a/firmware/rust1/src/bin/heizung.rs b/firmware/rust1/src/bin/heizung.rs index 1845fe3..371d6c9 100644 --- a/firmware/rust1/src/bin/heizung.rs +++ b/firmware/rust1/src/bin/heizung.rs @@ -25,6 +25,7 @@ use heapless::String; use heizung::i2c_scan::{self, ScanResultForBus}; use heizung::modbus_server::{ModbusServer, ModbusRegisters, ModbusErrorCode, ModbusAdressMatch, U16Pusher}; +use heizung::program_info::ProgramInfoBuilder; use heizung::rs485::RS485; use heizung::uf2updater::UF2UpdateHandler; use heizung::watchdog::WatchdogFixed; @@ -700,203 +701,7 @@ fn init_early() { // Add program info. #[used] #[link_section = ".program_info"] -pub static PROGRAM_INFO: [u8; 4096] = make_program_info(); - -struct ProgramInfoBuilder { - addr: u32, - buf: [u8; 4096], - info_pos: usize, - data_pos: usize, - info_table_size: usize, - data_end_offset: usize, -} - -impl ProgramInfoBuilder { - const fn new(addr: u32, info_table_size: u32, copy_table_size: u32) -> Self { - let copy_table_size = copy_table_size as usize; - let dummy_item_ptr = addr + info_table_size; - let dummy_item_size = 4; - - core::assert!(info_table_size % 4 == 0); - - ProgramInfoBuilder { - addr, - buf: { - let mut x = [0xff; 4096]; - // mark end of copy table with zero in first entry - x[4096 - copy_table_size + 0] = 0; - x[4096 - copy_table_size + 1] = 0; - x[4096 - copy_table_size + 2] = 0; - x[4096 - copy_table_size + 3] = 0; - x - }, - info_pos: 0, - data_pos: info_table_size as usize + dummy_item_size, - data_end_offset: 4096 - copy_table_size as usize, - info_table_size: info_table_size as usize, - } - } - - const fn build(mut self: Self) -> [u8; 4096] { - if self.info_pos < self.info_table_size { - self = self.align(); - let addr = self.addr + self.data_pos as u32; - self = self.push_u32(0xffffffff).fill_info_table(addr); - } - self.buf - } - - const fn push_info_u8(mut self: Self, value: u8) -> Self { - self.buf[self.info_pos] = value; - self.info_pos += 1; - if self.info_pos > self.info_table_size { - core::panic!("ProgramInfoBuilder: too much data for info table") - } - self - } - - const fn push_info_ptr(mut self: Self, value: u32) -> Self { - self - .push_info_u8((value & 0xff) as u8) - .push_info_u8(((value >> 8) & 0xff) as u8) - .push_info_u8(((value >> 16) & 0xff) as u8) - .push_info_u8(((value >> 24) & 0xff) as u8) - } - - const fn push_current_info_ptr(mut self: Self) -> Self { - self = self.align(); - let addr = self.addr + self.data_pos as u32; - self.push_info_ptr(addr) - } - - const fn fill_info_table(mut self: Self, value: u32) -> Self { - if self.info_pos < self.info_table_size { - self = self.push_info_ptr(value); - } - if self.info_pos < self.info_table_size { - self = self.push_info_ptr(value); - } - if self.info_pos < self.info_table_size { - self = self.push_info_ptr(value); - } - if self.info_pos < self.info_table_size { - self = self.push_info_ptr(value); - } - if self.info_pos < self.info_table_size { - self.fill_info_table(value) - } else { - self - } - } - - const fn push(mut self: Self, value: u8) -> Self { - self.buf[self.data_pos] = value; - self.data_pos += 1; - if self.data_pos > self.data_end_offset { - core::panic!("ProgramInfoBuilder: too much data") - } - self - } - - const fn align(mut self: Self) -> Self { - if self.data_pos % 4 != 0 { - self = self.push(0xff); - } - if self.data_pos % 4 != 0 { - self = self.push(0xff); - } - if self.data_pos % 4 != 0 { - self = self.push(0xff); - } - self - } - - const fn push_u16(self: Self, value: u16) -> Self { - self - .push((value & 0xff) as u8) - .push(((value >> 8) & 0xff) as u8) - } - - const fn push_u32(self: Self, value: u32) -> Self { - self - .push((value & 0xff) as u8) - .push(((value >> 8) & 0xff) as u8) - .push(((value >> 16) & 0xff) as u8) - .push(((value >> 24) & 0xff) as u8) - } - - const fn push_raspberry_tag(self: Self) -> Self { - self.push('R' as u8) - .push('P' as u8) - } - - const fn push_extra_data(mut self: Self, value: &[u8]) -> (Self, u32) { - if self.data_pos - self.info_pos < value.len() { - core::panic!("ProgramInfoBuilder: too much data") - } - let offset = self.data_pos; - //self.buf[offset..self.data_pos].copy_from_slice(value); - //for i in 0..value.len() { - // self.buf[offset+i] = value[i]; - //} - if value.len() > 0 { self.buf[offset+0] = value[0]; } - if value.len() > 1 { self.buf[offset+1] = value[1]; } - if value.len() > 2 { self.buf[offset+2] = value[2]; } - if value.len() > 3 { self.buf[offset+3] = value[3]; } - if value.len() > 4 { self.buf[offset+4] = value[4]; } - if value.len() > 5 { self.buf[offset+5] = value[5]; } - if value.len() > 6 { self.buf[offset+6] = value[6]; } - if value.len() > 7 { self.buf[offset+7] = value[7]; } - if value.len() > 8 { core::panic!("too long") } - - self.data_pos += value.len(); - let addr = self.addr + offset as u32; - (self, addr) - } - - const fn push_string(mut self: Self, value: &str) -> Self { - if self.data_pos - self.info_pos < value.len() { - core::panic!("ProgramInfoBuilder: too much data") - } - let x1 = self.data_pos; - self = self.push_u32(0); - - let (self2, addr) = self.push_extra_data(value.as_bytes()); - self = self2; - (self, _) = self.push_extra_data(&[0]); - - let x2 = self.data_pos; - self.data_pos = x1; - self = self.push_u32(addr); - self.data_pos = x2; - - self - } - - const BINARY_INFO_TYPE_ID_AND_INT: u16 = 5; - const BINARY_INFO_TYPE_ID_AND_STRING: u16 = 6; - const BINARY_INFO_ID_RP_PROGRAM_NAME: u32 = 0x02031c86; - const BINARY_INFO_ID_RP_BINARY_END: u32 = 0x68f465de; - - const fn push_program_name(self: Self, value: &str) -> Self { - self.push_current_info_ptr() - .push_u16(Self::BINARY_INFO_TYPE_ID_AND_STRING) - .push_raspberry_tag() - .push_u32(Self::BINARY_INFO_ID_RP_PROGRAM_NAME) - .push_string(value) - } - - #[allow(unused)] - const fn push_binary_end(self: Self, value: &str) -> Self { - self.push_current_info_ptr() - .push_u16(Self::BINARY_INFO_TYPE_ID_AND_INT) - .push_raspberry_tag() - .push_u32(Self::BINARY_INFO_ID_RP_BINARY_END) - .push_string(value) - } -} - -const fn make_program_info() -> [u8; 4096] { +pub static PROGRAM_INFO: [u8; 4096] = { // all of these must match the values in the bootloader const PROGRAM_INFO_FLASH_OFFSET: u32 = 0x10087000 - PROGRAM_INFO_TOTAL_SIZE; // last 4k of active partition const PROGRAM_INFO_TOTAL_SIZE: u32 = 4096; @@ -904,6 +709,6 @@ const fn make_program_info() -> [u8; 4096] { const PROGRAM_INFO_COPY_TABLE_SIZE: u32 = 128; // 3*u32 for each entry, picotool stops after 10 entries ProgramInfoBuilder::new(PROGRAM_INFO_FLASH_OFFSET, PROGRAM_INFO_TABLE_SIZE, PROGRAM_INFO_COPY_TABLE_SIZE) - .push_program_name("Test 123") + .program_name("Test 123") .build() -} +}; diff --git a/firmware/rust1/src/lib.rs b/firmware/rust1/src/lib.rs index da50916..052ee5d 100644 --- a/firmware/rust1/src/lib.rs +++ b/firmware/rust1/src/lib.rs @@ -8,3 +8,4 @@ pub mod clear_bootloader_state; pub mod uf2; pub mod uf2updater; pub mod watchdog; +pub mod program_info; diff --git a/firmware/rust1/src/program_info.rs b/firmware/rust1/src/program_info.rs new file mode 100644 index 0000000..de20db1 --- /dev/null +++ b/firmware/rust1/src/program_info.rs @@ -0,0 +1,203 @@ + +pub struct ProgramInfoBuilder { + addr: u32, + buf: [u8; 4096], + info_pos: usize, + data_pos: usize, + info_table_size: usize, + data_end_offset: usize, +} + +const fn copy(mut buf: [u8; 4096], offset: usize, source: &[u8], source_offset: usize) -> [u8; 4096] { + if source_offset >= source.len() { + buf + } else { + buf[offset] = source[source_offset]; + copy(buf, offset+1, source, source_offset+1) + } +} + +impl ProgramInfoBuilder { + pub const fn new(addr: u32, info_table_size: u32, copy_table_size: u32) -> Self { + let copy_table_size = copy_table_size as usize; + + core::assert!(info_table_size % 4 == 0); + + ProgramInfoBuilder { + addr, + buf: { + let mut x = [0xff; 4096]; + // mark end of copy table with zero in first entry + x[4096 - copy_table_size + 0] = 0; + x[4096 - copy_table_size + 1] = 0; + x[4096 - copy_table_size + 2] = 0; + x[4096 - copy_table_size + 3] = 0; + x + }, + info_pos: 0, + data_pos: info_table_size as usize, + data_end_offset: 4096 - copy_table_size as usize, + info_table_size: info_table_size as usize, + } + } + + pub const fn build(mut self: Self) -> [u8; 4096] { + if self.info_pos < self.info_table_size { + self = self.align(); + let addr = self.addr + self.data_pos as u32; + self = self.push_u32(0xffffffff).fill_info_table(addr); + } + self.buf + } + + const fn push_info_u8(mut self: Self, value: u8) -> Self { + self.buf[self.info_pos] = value; + self.info_pos += 1; + if self.info_pos > self.info_table_size { + core::panic!("ProgramInfoBuilder: too much data for info table") + } + self + } + + const fn push_info_ptr(self: Self, value: u32) -> Self { + self + .push_info_u8((value & 0xff) as u8) + .push_info_u8(((value >> 8) & 0xff) as u8) + .push_info_u8(((value >> 16) & 0xff) as u8) + .push_info_u8(((value >> 24) & 0xff) as u8) + } + + const fn push_current_info_ptr(mut self: Self) -> Self { + self = self.align(); + let addr = self.addr + self.data_pos as u32; + self.push_info_ptr(addr) + } + + const fn fill_info_table(mut self: Self, value: u32) -> Self { + if self.info_pos < self.info_table_size { + self = self.push_info_ptr(value); + } + if self.info_pos < self.info_table_size { + self = self.push_info_ptr(value); + } + if self.info_pos < self.info_table_size { + self = self.push_info_ptr(value); + } + if self.info_pos < self.info_table_size { + self = self.push_info_ptr(value); + } + if self.info_pos < self.info_table_size { + self.fill_info_table(value) + } else { + self + } + } + + const fn push(mut self: Self, value: u8) -> Self { + self.buf[self.data_pos] = value; + self.data_pos += 1; + if self.data_pos > self.data_end_offset { + core::panic!("ProgramInfoBuilder: too much data") + } + self + } + + pub const fn align(mut self: Self) -> Self { + if self.data_pos % 4 != 0 { + self = self.push(0xff); + } + if self.data_pos % 4 != 0 { + self = self.push(0xff); + } + if self.data_pos % 4 != 0 { + self = self.push(0xff); + } + self + } + + const fn push_u16(self: Self, value: u16) -> Self { + self + .push((value & 0xff) as u8) + .push(((value >> 8) & 0xff) as u8) + } + + const fn push_u32(self: Self, value: u32) -> Self { + self + .push((value & 0xff) as u8) + .push(((value >> 8) & 0xff) as u8) + .push(((value >> 16) & 0xff) as u8) + .push(((value >> 24) & 0xff) as u8) + } + + const fn push_raspberry_tag(self: Self) -> Self { + self.push('R' as u8) + .push('P' as u8) + } + + const fn push_extra_data(mut self: Self, value: &[u8]) -> (Self, u32) { + if self.data_end_offset - self.data_pos < value.len() { + core::panic!("ProgramInfoBuilder: too much data") + } + let offset = self.data_pos; + //self.buf[offset..offset+value.len()].copy_from_slice(value); + self.buf = copy(self.buf, offset, value, 0); + + self.data_pos += value.len(); + let addr = self.addr + offset as u32; + (self, addr) + } + + //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 { + if self.data_pos - self.info_pos < value.len() { + core::panic!("ProgramInfoBuilder: too much data") + } + + // push dummy value (will be replaced by address) + let x1 = self.data_pos; + self = self.push_u32(0); + + let (self2, addr) = self.push_extra_data(value.as_bytes()); + self = self2; + (self, _) = self.push_extra_data(&[0]); + + // replace dummy by actual address + let x2 = self.data_pos; + self.data_pos = x1; + self = self.push_u32(addr); + self.data_pos = x2; + + self + } + + const BINARY_INFO_TYPE_ID_AND_INT: u16 = 5; + const BINARY_INFO_TYPE_ID_AND_STRING: u16 = 6; + + pub const BINARY_INFO_ID_RP_PROGRAM_NAME: u32 = 0x02031c86; + pub const BINARY_INFO_ID_RP_PROGRAM_VERSION_STRING: u32 = 0x11a9bc3a; + pub const BINARY_INFO_ID_RP_PROGRAM_BUILD_DATE_STRING: u32 = 0x9da22254; + pub const BINARY_INFO_ID_RP_BINARY_END: u32 = 0x68f465de; + pub const BINARY_INFO_ID_RP_PROGRAM_URL: u32 = 0x1856239a; + pub const BINARY_INFO_ID_RP_PROGRAM_DESCRIPTION: u32 = 0xb6a07c19; + 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 { + self.push_current_info_ptr() + .push_u16(Self::BINARY_INFO_TYPE_ID_AND_STRING) + .push_raspberry_tag() + .push_u32(Self::BINARY_INFO_ID_RP_PROGRAM_NAME) + .push_string(value) + } + + pub const fn binary_end_address(self: Self, value: u32) -> Self { + self.push_current_info_ptr() + .push_u16(Self::BINARY_INFO_TYPE_ID_AND_INT) + .push_raspberry_tag() + .push_u32(Self::BINARY_INFO_ID_RP_BINARY_END) + .push_u32(value) + } +} -- GitLab