diff --git a/embedded-service/src/ec_type/generator/ec-memory-generator.py b/embedded-service/src/ec_type/generator/ec-memory-generator.py deleted file mode 100644 index 000196b1..00000000 --- a/embedded-service/src/ec_type/generator/ec-memory-generator.py +++ /dev/null @@ -1,116 +0,0 @@ -import sys,yaml - -# Function to convert YAML data to Rust structures -def yaml_to_rust(data): - rust_code = "//! EC Internal Data Structures\n\n" - rust_code += "#[allow(missing_docs)]\n" - rust_code += "pub const EC_MEMMAP_VERSION: Version = Version {major: 0, minor: 1, spin: 0, res0: 0};\n\n" - for key, value in data.items(): - rust_code += "#[allow(missing_docs)]\n" - rust_code += "#[repr(C, packed)]\n" - rust_code += "#[derive(Clone, Copy, Debug, Default)]\n" - rust_code += f"pub struct {key} {{\n" - for sub_key, sub_value in value.items(): - if isinstance(sub_value, dict) and 'type' in sub_value: - rust_code += f" pub {sub_key}: {sub_value['type']},\n" - else: - rust_code += f" pub {sub_key}: {sub_value},\n" - rust_code += "}\n\n" - - return rust_code - -# Function to convert YAML data to C structures -def yaml_to_c(data): - c_code = "#pragma once\n\n" - c_code += "#include \n\n" - c_code += "#pragma pack(push, 1)\n\n" - for key, value in data.items(): - c_code += "typedef struct {\n" - for sub_key, sub_value in value.items(): - if isinstance(sub_value, dict) and 'type' in sub_value: - c_code += f" {type_to_c_type(sub_value['type'])} {sub_key};\n" - else: - c_code += f" {sub_value} {sub_key};\n" - c_code += f"}} {key};\n\n" - - c_code += "#pragma pack(pop)\n\n" - - c_code += "const Version EC_MEMMAP_VERSION = {0x00, 0x01, 0x00, 0x00};\n" - return c_code - -def type_to_c_type(type_str): - if type_str == 'u32': - return 'uint32_t' - elif type_str == 'u16': - return 'uint16_t' - elif type_str == 'u8': - return 'uint8_t' - elif type_str == 'i32': - return 'int32_t' - elif type_str == 'i16': - return 'int16_t' - elif type_str == 'i8': - return 'int8_t' - else: - return type_str - -def open_file(file_path): - try: - with open(file_path, 'r') as file: - data = file.read() - return data - except FileNotFoundError: - print(f"File not found: {file_path}") - except Exception as e: - print(f"An error occurred: {e}") - -def check_for_32bit_alignment(data): - sizes = {'u32': 4, 'u16': 2, 'u8': 1, 'i32': 4, 'i16': 2, 'i8': 1} - for key, value in data.items(): - size = 0 - for sub_key, sub_value in value.items(): - if isinstance(sub_value, dict) and 'type' in sub_value: - size += sizes[sub_value['type']] - sizes[key] = size - - for key, size in sizes.items(): - if not is_primitive_type(key) and size % 4 != 0: - print(f"Warning: {key} is not 32-bit aligned. Size: {size} bytes") - -def is_primitive_type(type_str): - return type_str in ['u32', 'u16', 'u8', 'i32', 'i16', 'i8'] - -if __name__ == "__main__": - if len(sys.argv) != 2: - print("Usage: python yamltorust.py ") - sys.exit(1) - else: - file_path = sys.argv[1] - yaml_data = open_file(file_path) - - # Load the YAML data - data = yaml.safe_load(yaml_data) - - check_for_32bit_alignment(data) - - # Convert the YAML data to Rust structures and print the result - rust_code = yaml_to_rust(data) - - c_code = yaml_to_c(data) - - rust_output_filename = "structure.rs" - c_output_filename = "ecmemory.h" - - try: - with open(rust_output_filename, "w") as output_file: - output_file.write(rust_code) - print(f"Rust code has been written to {rust_output_filename}") - except Exception as e: - print(f"An error occurred while writing to {rust_output_filename}: {e}") - - try: - with open(c_output_filename, "w") as output_file: - output_file.write(c_code) - print(f"C code has been written to {c_output_filename}") - except Exception as e: - print(f"An error occurred while writing to {c_output_filename}: {e}") diff --git a/embedded-service/src/ec_type/generator/ec_memory_map.yaml b/embedded-service/src/ec_type/generator/ec_memory_map.yaml deleted file mode 100644 index 59e20535..00000000 --- a/embedded-service/src/ec_type/generator/ec_memory_map.yaml +++ /dev/null @@ -1,148 +0,0 @@ -# EC Memory layout definition - -Version: - major: - type: u8 - minor: - type: u8 - spin: - type: u8 - res0: - type: u8 - -# Size 0x14 -Capabilities: - events: - type: u32 - fw_version: - type: Version - secure_state: - type: u8 - variants: - INSECURE: 0 - SECURE: 1 - boot_status: - type: u8 - variants: - SUCCESS: 0 - ERROR: 1 - fan_mask: - type: u8 - battery_mask: - type: u8 - temp_mask: - type: u16 - key_mask: - type: u16 - debug_mask: - type: u16 - res0: - type: u16 - -# Size 0x64 -Battery: - events: - type: u32 - status: - type: u32 - last_full_charge: - type: u32 - cycle_count: - type: u32 - state: - type: u32 - present_rate: - type: u32 - remain_cap: - type: u32 - present_volt: - type: u32 - psr_state: - type: u32 - psr_max_out: - type: u32 - psr_max_in: - type: u32 - peak_level: - type: u32 - peak_power: - type: u32 - sus_level: - type: u32 - sus_power: - type: u32 - peak_thres: - type: u32 - sus_thres: - type: u32 - trip_thres: - type: u32 - bmc_data: - type: u32 - bmd_data: - type: u32 - bmd_flags: - type: u32 - bmd_count: - type: u32 - charge_time: - type: u32 - run_time: - type: u32 - sample_time: - type: u32 - -# Size 0x38 -Thermal: - events: - type: u32 - cool_mode: - type: u32 - dba_limit: - type: u32 - sonne_limit: - type: u32 - ma_limit: - type: u32 - fan1_on_temp: - type: u32 - fan1_ramp_temp: - type: u32 - fan1_max_temp: - type: u32 - fan1_crt_temp: - type: u32 - fan1_hot_temp: - type: u32 - fan1_max_rpm: - type: u32 - fan1_cur_rpm: - type: u32 - tmp1_val: - type: u32 - tmp1_timeout: - type: u32 - tmp1_low: - type: u32 - tmp1_high: - type: u32 - -Notifications: - service: - type: u16 - event: - type: u16 - -ECMemory: - ver: - type: Version - caps: - type: Capabilities - notif: - type: Notifications - alarm: - type: TimeAlarm - batt: - type: Battery - therm: - type: Thermal diff --git a/embedded-service/src/ec_type/message.rs b/embedded-service/src/ec_type/message.rs deleted file mode 100644 index f31f178a..00000000 --- a/embedded-service/src/ec_type/message.rs +++ /dev/null @@ -1,88 +0,0 @@ -//! EC Internal Messages - -#[allow(missing_docs)] -#[derive(Clone, Copy, Debug)] -pub enum CapabilitiesMessage { - Events(u32), - FwVersion(super::structure::Version), - SecureState(u8), - BootStatus(u8), - FanMask(u8), - BatteryMask(u8), - TempMask(u16), - KeyMask(u16), - DebugMask(u16), -} - -#[allow(missing_docs)] -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum TimeAlarmMessage { - Events(u32), - Capability(u32), - Year(u16), - Month(u8), - Day(u8), - Hour(u8), - Minute(u8), - Second(u8), - Valid(u8), - Daylight(u8), - Res1(u8), - Milli(u16), - TimeZone(u16), - Res2(u16), - AlarmStatus(u32), - AcTimeVal(u32), - DcTimeVal(u32), -} - -#[allow(missing_docs)] -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum BatteryMessage { - Events(u32), - Status(u32), - LastFullCharge(u32), - CycleCount(u32), - State(u32), - PresentRate(u32), - RemainCap(u32), - PresentVolt(u32), - PsrState(u32), - PsrMaxOut(u32), - PsrMaxIn(u32), - PeakLevel(u32), - PeakPower(u32), - SusLevel(u32), - SusPower(u32), - PeakThres(u32), - SusThres(u32), - TripThres(u32), - BmcData(u32), - BmdData(u32), - BmdFlags(u32), - BmdCount(u32), - ChargeTime(u32), - RunTime(u32), - SampleTime(u32), -} - -#[allow(missing_docs)] -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum ThermalMessage { - Events(u32), - CoolMode(u32), - DbaLimit(u32), - SonneLimit(u32), - MaLimit(u32), - Fan1OnTemp(u32), - Fan1RampTemp(u32), - Fan1MaxTemp(u32), - Fan1CrtTemp(u32), - Fan1HotTemp(u32), - Fan1MaxRpm(u32), - Fan1CurRpm(u32), - Tmp1Val(u32), - Tmp1Timeout(u32), - Tmp1Low(u32), - Tmp1High(u32), -} diff --git a/embedded-service/src/ec_type/mod.rs b/embedded-service/src/ec_type/mod.rs deleted file mode 100644 index 0a73a17c..00000000 --- a/embedded-service/src/ec_type/mod.rs +++ /dev/null @@ -1,885 +0,0 @@ -//! Standard EC types -use core::mem::offset_of; - -pub mod message; -pub mod structure; - -/// Error type -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum Error { - /// The requested base + offset is invalid - InvalidLocation, -} - -/// Update battery section of memory map based on battery message -pub fn update_battery_section(msg: &message::BatteryMessage, memory_map: &mut structure::ECMemory) { - match msg { - message::BatteryMessage::Events(events) => memory_map.batt.events = *events, - message::BatteryMessage::Status(status) => memory_map.batt.status = *status, - message::BatteryMessage::LastFullCharge(last_full_charge) => { - memory_map.batt.last_full_charge = *last_full_charge - } - message::BatteryMessage::CycleCount(cycle_count) => memory_map.batt.cycle_count = *cycle_count, - message::BatteryMessage::State(state) => memory_map.batt.state = *state, - message::BatteryMessage::PresentRate(present_rate) => memory_map.batt.present_rate = *present_rate, - message::BatteryMessage::RemainCap(remain_cap) => memory_map.batt.remain_cap = *remain_cap, - message::BatteryMessage::PresentVolt(present_volt) => memory_map.batt.present_volt = *present_volt, - message::BatteryMessage::PsrState(psr_state) => memory_map.batt.psr_state = *psr_state, - message::BatteryMessage::PsrMaxOut(psr_max_out) => memory_map.batt.psr_max_out = *psr_max_out, - message::BatteryMessage::PsrMaxIn(psr_max_in) => memory_map.batt.psr_max_in = *psr_max_in, - message::BatteryMessage::PeakLevel(peak_level) => memory_map.batt.peak_level = *peak_level, - message::BatteryMessage::PeakPower(peak_power) => memory_map.batt.peak_power = *peak_power, - message::BatteryMessage::SusLevel(sus_level) => memory_map.batt.sus_level = *sus_level, - message::BatteryMessage::SusPower(sus_power) => memory_map.batt.sus_power = *sus_power, - message::BatteryMessage::PeakThres(peak_thres) => memory_map.batt.peak_thres = *peak_thres, - message::BatteryMessage::SusThres(sus_thres) => memory_map.batt.sus_thres = *sus_thres, - message::BatteryMessage::TripThres(trip_thres) => memory_map.batt.trip_thres = *trip_thres, - message::BatteryMessage::BmcData(bmc_data) => memory_map.batt.bmc_data = *bmc_data, - message::BatteryMessage::BmdData(bmd_data) => memory_map.batt.bmd_data = *bmd_data, - message::BatteryMessage::BmdFlags(bmd_flags) => memory_map.batt.bmd_flags = *bmd_flags, - message::BatteryMessage::BmdCount(bmd_count) => memory_map.batt.bmd_count = *bmd_count, - message::BatteryMessage::ChargeTime(charge_time) => memory_map.batt.charge_time = *charge_time, - message::BatteryMessage::RunTime(run_time) => memory_map.batt.run_time = *run_time, - message::BatteryMessage::SampleTime(sample_time) => memory_map.batt.sample_time = *sample_time, - } -} - -/// Update capabilities section of memory map based on battery message -pub fn update_capabilities_section(msg: &message::CapabilitiesMessage, memory_map: &mut structure::ECMemory) { - match msg { - message::CapabilitiesMessage::Events(events) => memory_map.caps.events = *events, - message::CapabilitiesMessage::FwVersion(fw_version) => memory_map.caps.fw_version = *fw_version, - message::CapabilitiesMessage::SecureState(secure_state) => memory_map.caps.secure_state = *secure_state, - message::CapabilitiesMessage::BootStatus(boot_status) => memory_map.caps.boot_status = *boot_status, - message::CapabilitiesMessage::FanMask(fan_mask) => memory_map.caps.fan_mask = *fan_mask, - message::CapabilitiesMessage::BatteryMask(battery_mask) => memory_map.caps.battery_mask = *battery_mask, - message::CapabilitiesMessage::TempMask(temp_mask) => memory_map.caps.temp_mask = *temp_mask, - message::CapabilitiesMessage::KeyMask(key_mask) => memory_map.caps.key_mask = *key_mask, - message::CapabilitiesMessage::DebugMask(debug_mask) => memory_map.caps.debug_mask = *debug_mask, - } -} - -/// Update thermal section of memory map based on battery message -pub fn update_thermal_section(msg: &message::ThermalMessage, memory_map: &mut structure::ECMemory) { - match msg { - message::ThermalMessage::Events(events) => memory_map.therm.events = *events, - message::ThermalMessage::CoolMode(cool_mode) => memory_map.therm.cool_mode = *cool_mode, - message::ThermalMessage::DbaLimit(dba_limit) => memory_map.therm.dba_limit = *dba_limit, - message::ThermalMessage::SonneLimit(sonne_limit) => memory_map.therm.sonne_limit = *sonne_limit, - message::ThermalMessage::MaLimit(ma_limit) => memory_map.therm.ma_limit = *ma_limit, - message::ThermalMessage::Fan1OnTemp(fan1_on_temp) => memory_map.therm.fan1_on_temp = *fan1_on_temp, - message::ThermalMessage::Fan1RampTemp(fan1_ramp_temp) => memory_map.therm.fan1_ramp_temp = *fan1_ramp_temp, - message::ThermalMessage::Fan1MaxTemp(fan1_max_temp) => memory_map.therm.fan1_max_temp = *fan1_max_temp, - message::ThermalMessage::Fan1CrtTemp(fan1_crt_temp) => memory_map.therm.fan1_crt_temp = *fan1_crt_temp, - message::ThermalMessage::Fan1HotTemp(fan1_hot_temp) => memory_map.therm.fan1_hot_temp = *fan1_hot_temp, - message::ThermalMessage::Fan1MaxRpm(fan1_max_rpm) => memory_map.therm.fan1_max_rpm = *fan1_max_rpm, - message::ThermalMessage::Fan1CurRpm(fan1_cur_rpm) => memory_map.therm.fan1_cur_rpm = *fan1_cur_rpm, - message::ThermalMessage::Tmp1Val(tmp1_val) => memory_map.therm.tmp1_val = *tmp1_val, - message::ThermalMessage::Tmp1Timeout(tmp1_timeout) => memory_map.therm.tmp1_timeout = *tmp1_timeout, - message::ThermalMessage::Tmp1Low(tmp1_low) => memory_map.therm.tmp1_low = *tmp1_low, - message::ThermalMessage::Tmp1High(tmp1_high) => memory_map.therm.tmp1_high = *tmp1_high, - } -} - -/// Helper macro to simplify the conversion of memory map to message -macro_rules! into_message { - ($offset:ident, $length:ident, $member:expr, $msg:expr) => { - let value = $member; - *$offset += size_of_val(&value); - *$length -= size_of_val(&value); - return Ok($msg(value)); - }; -} - -/// Convert from memory map offset and length to battery message -/// Modifies offset and length -pub fn mem_map_to_battery_msg( - memory_map: &structure::ECMemory, - offset: &mut usize, - length: &mut usize, -) -> Result { - let local_offset = *offset - offset_of!(structure::ECMemory, batt); - - if local_offset == offset_of!(structure::Battery, events) { - into_message!(offset, length, memory_map.batt.events, message::BatteryMessage::Events); - } else if local_offset == offset_of!(structure::Battery, status) { - into_message!(offset, length, memory_map.batt.status, message::BatteryMessage::Status); - } else if local_offset == offset_of!(structure::Battery, last_full_charge) { - into_message!( - offset, - length, - memory_map.batt.last_full_charge, - message::BatteryMessage::LastFullCharge - ); - } else if local_offset == offset_of!(structure::Battery, cycle_count) { - into_message!( - offset, - length, - memory_map.batt.cycle_count, - message::BatteryMessage::CycleCount - ); - } else if local_offset == offset_of!(structure::Battery, state) { - into_message!(offset, length, memory_map.batt.state, message::BatteryMessage::State); - } else if local_offset == offset_of!(structure::Battery, present_rate) { - into_message!( - offset, - length, - memory_map.batt.present_rate, - message::BatteryMessage::PresentRate - ); - } else if local_offset == offset_of!(structure::Battery, remain_cap) { - into_message!( - offset, - length, - memory_map.batt.remain_cap, - message::BatteryMessage::RemainCap - ); - } else if local_offset == offset_of!(structure::Battery, present_volt) { - into_message!( - offset, - length, - memory_map.batt.present_volt, - message::BatteryMessage::PresentVolt - ); - } else if local_offset == offset_of!(structure::Battery, psr_state) { - into_message!( - offset, - length, - memory_map.batt.psr_state, - message::BatteryMessage::PsrState - ); - } else if local_offset == offset_of!(structure::Battery, psr_max_out) { - into_message!( - offset, - length, - memory_map.batt.psr_max_out, - message::BatteryMessage::PsrMaxOut - ); - } else if local_offset == offset_of!(structure::Battery, psr_max_in) { - into_message!( - offset, - length, - memory_map.batt.psr_max_in, - message::BatteryMessage::PsrMaxIn - ); - } else if local_offset == offset_of!(structure::Battery, peak_level) { - into_message!( - offset, - length, - memory_map.batt.peak_level, - message::BatteryMessage::PeakLevel - ); - } else if local_offset == offset_of!(structure::Battery, peak_power) { - into_message!( - offset, - length, - memory_map.batt.peak_power, - message::BatteryMessage::PeakPower - ); - } else if local_offset == offset_of!(structure::Battery, sus_level) { - into_message!( - offset, - length, - memory_map.batt.sus_level, - message::BatteryMessage::SusLevel - ); - } else if local_offset == offset_of!(structure::Battery, sus_power) { - into_message!( - offset, - length, - memory_map.batt.sus_power, - message::BatteryMessage::SusPower - ); - } else if local_offset == offset_of!(structure::Battery, peak_thres) { - into_message!( - offset, - length, - memory_map.batt.peak_thres, - message::BatteryMessage::PeakThres - ); - } else if local_offset == offset_of!(structure::Battery, sus_thres) { - into_message!( - offset, - length, - memory_map.batt.sus_thres, - message::BatteryMessage::SusThres - ); - } else if local_offset == offset_of!(structure::Battery, trip_thres) { - into_message!( - offset, - length, - memory_map.batt.trip_thres, - message::BatteryMessage::TripThres - ); - } else if local_offset == offset_of!(structure::Battery, bmc_data) { - into_message!( - offset, - length, - memory_map.batt.bmc_data, - message::BatteryMessage::BmcData - ); - } else if local_offset == offset_of!(structure::Battery, bmd_data) { - into_message!( - offset, - length, - memory_map.batt.bmd_data, - message::BatteryMessage::BmdData - ); - } else if local_offset == offset_of!(structure::Battery, bmd_flags) { - into_message!( - offset, - length, - memory_map.batt.bmd_flags, - message::BatteryMessage::BmdFlags - ); - } else if local_offset == offset_of!(structure::Battery, bmd_count) { - into_message!( - offset, - length, - memory_map.batt.bmd_count, - message::BatteryMessage::BmdCount - ); - } else if local_offset == offset_of!(structure::Battery, charge_time) { - into_message!( - offset, - length, - memory_map.batt.charge_time, - message::BatteryMessage::ChargeTime - ); - } else if local_offset == offset_of!(structure::Battery, run_time) { - into_message!( - offset, - length, - memory_map.batt.run_time, - message::BatteryMessage::RunTime - ); - } else if local_offset == offset_of!(structure::Battery, sample_time) { - into_message!( - offset, - length, - memory_map.batt.sample_time, - message::BatteryMessage::SampleTime - ); - } else { - Err(Error::InvalidLocation) - } -} - -/// Convert from memory map offset and length to thermal message -/// Modifies offset and length -pub fn mem_map_to_thermal_msg( - memory_map: &structure::ECMemory, - offset: &mut usize, - length: &mut usize, -) -> Result { - let local_offset = *offset - offset_of!(structure::ECMemory, therm); - - if local_offset == offset_of!(structure::Thermal, events) { - into_message!(offset, length, memory_map.therm.events, message::ThermalMessage::Events); - } else if local_offset == offset_of!(structure::Thermal, cool_mode) { - into_message!( - offset, - length, - memory_map.therm.cool_mode, - message::ThermalMessage::CoolMode - ); - } else if local_offset == offset_of!(structure::Thermal, dba_limit) { - into_message!( - offset, - length, - memory_map.therm.dba_limit, - message::ThermalMessage::DbaLimit - ); - } else if local_offset == offset_of!(structure::Thermal, sonne_limit) { - into_message!( - offset, - length, - memory_map.therm.sonne_limit, - message::ThermalMessage::SonneLimit - ); - } else if local_offset == offset_of!(structure::Thermal, ma_limit) { - into_message!( - offset, - length, - memory_map.therm.ma_limit, - message::ThermalMessage::MaLimit - ); - } else if local_offset == offset_of!(structure::Thermal, fan1_on_temp) { - into_message!( - offset, - length, - memory_map.therm.fan1_on_temp, - message::ThermalMessage::Fan1OnTemp - ); - } else if local_offset == offset_of!(structure::Thermal, fan1_ramp_temp) { - into_message!( - offset, - length, - memory_map.therm.fan1_ramp_temp, - message::ThermalMessage::Fan1RampTemp - ); - } else if local_offset == offset_of!(structure::Thermal, fan1_max_temp) { - into_message!( - offset, - length, - memory_map.therm.fan1_max_temp, - message::ThermalMessage::Fan1MaxTemp - ); - } else if local_offset == offset_of!(structure::Thermal, fan1_crt_temp) { - into_message!( - offset, - length, - memory_map.therm.fan1_crt_temp, - message::ThermalMessage::Fan1CrtTemp - ); - } else if local_offset == offset_of!(structure::Thermal, fan1_hot_temp) { - into_message!( - offset, - length, - memory_map.therm.fan1_hot_temp, - message::ThermalMessage::Fan1HotTemp - ); - } else if local_offset == offset_of!(structure::Thermal, fan1_max_rpm) { - into_message!( - offset, - length, - memory_map.therm.fan1_max_rpm, - message::ThermalMessage::Fan1MaxRpm - ); - } else if local_offset == offset_of!(structure::Thermal, fan1_cur_rpm) { - into_message!( - offset, - length, - memory_map.therm.fan1_cur_rpm, - message::ThermalMessage::Fan1CurRpm - ); - } else if local_offset == offset_of!(structure::Thermal, tmp1_val) { - into_message!( - offset, - length, - memory_map.therm.tmp1_val, - message::ThermalMessage::Tmp1Val - ); - } else if local_offset == offset_of!(structure::Thermal, tmp1_timeout) { - into_message!( - offset, - length, - memory_map.therm.tmp1_timeout, - message::ThermalMessage::Tmp1Timeout - ); - } else if local_offset == offset_of!(structure::Thermal, tmp1_low) { - into_message!( - offset, - length, - memory_map.therm.tmp1_low, - message::ThermalMessage::Tmp1Low - ); - } else if local_offset == offset_of!(structure::Thermal, tmp1_high) { - into_message!( - offset, - length, - memory_map.therm.tmp1_high, - message::ThermalMessage::Tmp1High - ); - } else { - Err(Error::InvalidLocation) - } -} - -#[cfg(test)] -#[allow(clippy::unwrap_used)] -mod tests { - use super::*; - - macro_rules! test_field { - ($memory_map:ident, $offset:ident, $length:ident, $field:expr, $func:ident, $msg:expr) => { - let field = $field; - let next_offset = $offset + size_of_val(&field); - let next_length = $length - size_of_val(&field); - let msg = $func(&$memory_map, &mut $offset, &mut $length).unwrap(); - assert_eq!(msg, $msg(field)); - assert_eq!($offset, next_offset); - assert_eq!($length, next_length); - }; - } - - #[test] - fn test_mem_map_to_battery_msg() { - use crate::ec_type::message::BatteryMessage; - use crate::ec_type::structure::{Battery, ECMemory}; - - let memory_map = ECMemory { - batt: Battery { - events: 1, - status: 2, - last_full_charge: 3, - cycle_count: 4, - state: 5, - present_rate: 6, - remain_cap: 7, - present_volt: 8, - psr_state: 9, - psr_max_out: 10, - psr_max_in: 11, - peak_level: 12, - peak_power: 13, - sus_level: 14, - sus_power: 15, - peak_thres: 16, - sus_thres: 17, - trip_thres: 18, - bmc_data: 19, - bmd_data: 20, - bmd_flags: 21, - bmd_count: 22, - charge_time: 23, - run_time: 24, - sample_time: 25, - }, - ..Default::default() - }; - - let mut offset = offset_of!(ECMemory, batt); - let mut length = size_of::(); - - test_field!( - memory_map, - offset, - length, - memory_map.batt.events, - mem_map_to_battery_msg, - BatteryMessage::Events - ); - test_field!( - memory_map, - offset, - length, - memory_map.batt.status, - mem_map_to_battery_msg, - BatteryMessage::Status - ); - test_field!( - memory_map, - offset, - length, - memory_map.batt.last_full_charge, - mem_map_to_battery_msg, - BatteryMessage::LastFullCharge - ); - test_field!( - memory_map, - offset, - length, - memory_map.batt.cycle_count, - mem_map_to_battery_msg, - BatteryMessage::CycleCount - ); - test_field!( - memory_map, - offset, - length, - memory_map.batt.state, - mem_map_to_battery_msg, - BatteryMessage::State - ); - test_field!( - memory_map, - offset, - length, - memory_map.batt.present_rate, - mem_map_to_battery_msg, - BatteryMessage::PresentRate - ); - test_field!( - memory_map, - offset, - length, - memory_map.batt.remain_cap, - mem_map_to_battery_msg, - BatteryMessage::RemainCap - ); - test_field!( - memory_map, - offset, - length, - memory_map.batt.present_volt, - mem_map_to_battery_msg, - BatteryMessage::PresentVolt - ); - test_field!( - memory_map, - offset, - length, - memory_map.batt.psr_state, - mem_map_to_battery_msg, - BatteryMessage::PsrState - ); - test_field!( - memory_map, - offset, - length, - memory_map.batt.psr_max_out, - mem_map_to_battery_msg, - BatteryMessage::PsrMaxOut - ); - test_field!( - memory_map, - offset, - length, - memory_map.batt.psr_max_in, - mem_map_to_battery_msg, - BatteryMessage::PsrMaxIn - ); - test_field!( - memory_map, - offset, - length, - memory_map.batt.peak_level, - mem_map_to_battery_msg, - BatteryMessage::PeakLevel - ); - test_field!( - memory_map, - offset, - length, - memory_map.batt.peak_power, - mem_map_to_battery_msg, - BatteryMessage::PeakPower - ); - test_field!( - memory_map, - offset, - length, - memory_map.batt.sus_level, - mem_map_to_battery_msg, - BatteryMessage::SusLevel - ); - test_field!( - memory_map, - offset, - length, - memory_map.batt.sus_power, - mem_map_to_battery_msg, - BatteryMessage::SusPower - ); - test_field!( - memory_map, - offset, - length, - memory_map.batt.peak_thres, - mem_map_to_battery_msg, - BatteryMessage::PeakThres - ); - test_field!( - memory_map, - offset, - length, - memory_map.batt.sus_thres, - mem_map_to_battery_msg, - BatteryMessage::SusThres - ); - test_field!( - memory_map, - offset, - length, - memory_map.batt.trip_thres, - mem_map_to_battery_msg, - BatteryMessage::TripThres - ); - test_field!( - memory_map, - offset, - length, - memory_map.batt.bmc_data, - mem_map_to_battery_msg, - BatteryMessage::BmcData - ); - test_field!( - memory_map, - offset, - length, - memory_map.batt.bmd_data, - mem_map_to_battery_msg, - BatteryMessage::BmdData - ); - test_field!( - memory_map, - offset, - length, - memory_map.batt.bmd_flags, - mem_map_to_battery_msg, - BatteryMessage::BmdFlags - ); - test_field!( - memory_map, - offset, - length, - memory_map.batt.bmd_count, - mem_map_to_battery_msg, - BatteryMessage::BmdCount - ); - test_field!( - memory_map, - offset, - length, - memory_map.batt.charge_time, - mem_map_to_battery_msg, - BatteryMessage::ChargeTime - ); - test_field!( - memory_map, - offset, - length, - memory_map.batt.run_time, - mem_map_to_battery_msg, - BatteryMessage::RunTime - ); - test_field!( - memory_map, - offset, - length, - memory_map.batt.sample_time, - mem_map_to_battery_msg, - BatteryMessage::SampleTime - ); - - assert_eq!(length, 0); - } - - #[test] - fn test_mem_map_to_battery_msg_error() { - use crate::ec_type::structure::{Battery, ECMemory}; - - let memory_map = ECMemory { - batt: Battery { - events: 1, - status: 2, - last_full_charge: 3, - cycle_count: 4, - state: 5, - present_rate: 6, - remain_cap: 7, - present_volt: 8, - psr_state: 9, - psr_max_out: 10, - psr_max_in: 11, - peak_level: 12, - peak_power: 13, - sus_level: 14, - sus_power: 15, - peak_thres: 16, - sus_thres: 17, - trip_thres: 18, - bmc_data: 19, - bmd_data: 20, - bmd_flags: 21, - bmd_count: 22, - charge_time: 23, - run_time: 24, - sample_time: 25, - }, - ..Default::default() - }; - - let mut offset = offset_of!(ECMemory, batt) + 1; - let mut length = size_of::(); - - let res = mem_map_to_battery_msg(&memory_map, &mut offset, &mut length); - assert!(res.is_err() && res.unwrap_err() == Error::InvalidLocation); - } - - #[test] - fn test_mem_map_to_thermal_msg() { - use crate::ec_type::message::ThermalMessage; - use crate::ec_type::structure::{ECMemory, Thermal}; - - let memory_map = ECMemory { - therm: Thermal { - events: 1, - cool_mode: 2, - dba_limit: 3, - sonne_limit: 4, - ma_limit: 5, - fan1_on_temp: 6, - fan1_ramp_temp: 7, - fan1_max_temp: 8, - fan1_crt_temp: 9, - fan1_hot_temp: 10, - fan1_max_rpm: 11, - fan1_cur_rpm: 12, - tmp1_val: 13, - tmp1_timeout: 14, - tmp1_low: 15, - tmp1_high: 16, - }, - ..Default::default() - }; - - let mut offset = offset_of!(ECMemory, therm); - let mut length = size_of::(); - - test_field!( - memory_map, - offset, - length, - memory_map.therm.events, - mem_map_to_thermal_msg, - ThermalMessage::Events - ); - test_field!( - memory_map, - offset, - length, - memory_map.therm.cool_mode, - mem_map_to_thermal_msg, - ThermalMessage::CoolMode - ); - test_field!( - memory_map, - offset, - length, - memory_map.therm.dba_limit, - mem_map_to_thermal_msg, - ThermalMessage::DbaLimit - ); - test_field!( - memory_map, - offset, - length, - memory_map.therm.sonne_limit, - mem_map_to_thermal_msg, - ThermalMessage::SonneLimit - ); - test_field!( - memory_map, - offset, - length, - memory_map.therm.ma_limit, - mem_map_to_thermal_msg, - ThermalMessage::MaLimit - ); - test_field!( - memory_map, - offset, - length, - memory_map.therm.fan1_on_temp, - mem_map_to_thermal_msg, - ThermalMessage::Fan1OnTemp - ); - test_field!( - memory_map, - offset, - length, - memory_map.therm.fan1_ramp_temp, - mem_map_to_thermal_msg, - ThermalMessage::Fan1RampTemp - ); - test_field!( - memory_map, - offset, - length, - memory_map.therm.fan1_max_temp, - mem_map_to_thermal_msg, - ThermalMessage::Fan1MaxTemp - ); - test_field!( - memory_map, - offset, - length, - memory_map.therm.fan1_crt_temp, - mem_map_to_thermal_msg, - ThermalMessage::Fan1CrtTemp - ); - test_field!( - memory_map, - offset, - length, - memory_map.therm.fan1_hot_temp, - mem_map_to_thermal_msg, - ThermalMessage::Fan1HotTemp - ); - test_field!( - memory_map, - offset, - length, - memory_map.therm.fan1_max_rpm, - mem_map_to_thermal_msg, - ThermalMessage::Fan1MaxRpm - ); - test_field!( - memory_map, - offset, - length, - memory_map.therm.fan1_cur_rpm, - mem_map_to_thermal_msg, - ThermalMessage::Fan1CurRpm - ); - test_field!( - memory_map, - offset, - length, - memory_map.therm.tmp1_val, - mem_map_to_thermal_msg, - ThermalMessage::Tmp1Val - ); - test_field!( - memory_map, - offset, - length, - memory_map.therm.tmp1_timeout, - mem_map_to_thermal_msg, - ThermalMessage::Tmp1Timeout - ); - test_field!( - memory_map, - offset, - length, - memory_map.therm.tmp1_low, - mem_map_to_thermal_msg, - ThermalMessage::Tmp1Low - ); - test_field!( - memory_map, - offset, - length, - memory_map.therm.tmp1_high, - mem_map_to_thermal_msg, - ThermalMessage::Tmp1High - ); - - assert_eq!(length, 0); - } - - #[test] - fn test_mem_map_to_thermal_msg_error() { - use crate::ec_type::structure::{ECMemory, Thermal}; - - let memory_map = ECMemory { - therm: Thermal { - events: 1, - cool_mode: 2, - dba_limit: 3, - sonne_limit: 4, - ma_limit: 5, - fan1_on_temp: 6, - fan1_ramp_temp: 7, - fan1_max_temp: 8, - fan1_crt_temp: 9, - fan1_hot_temp: 10, - fan1_max_rpm: 11, - fan1_cur_rpm: 12, - tmp1_val: 13, - tmp1_timeout: 14, - tmp1_low: 15, - tmp1_high: 16, - }, - ..Default::default() - }; - - let mut offset = offset_of!(ECMemory, therm) + 1; - let mut length = size_of::(); - - let res = mem_map_to_thermal_msg(&memory_map, &mut offset, &mut length); - assert!(res.is_err() && res.unwrap_err() == Error::InvalidLocation); - } -} diff --git a/embedded-service/src/ec_type/structure.rs b/embedded-service/src/ec_type/structure.rs deleted file mode 100644 index 558b9d47..00000000 --- a/embedded-service/src/ec_type/structure.rs +++ /dev/null @@ -1,107 +0,0 @@ -//! EC Internal Data Structures - -#[allow(missing_docs)] -pub const EC_MEMMAP_VERSION: Version = Version { - major: 0, - minor: 1, - spin: 0, - res0: 0, -}; - -#[allow(missing_docs)] -#[repr(C, packed)] -#[derive(Clone, Copy, Debug, Default)] -pub struct Version { - pub major: u8, - pub minor: u8, - pub spin: u8, - pub res0: u8, -} - -#[allow(missing_docs)] -#[repr(C, packed)] -#[derive(Clone, Copy, Debug, Default)] -pub struct Capabilities { - pub events: u32, - pub fw_version: Version, - pub secure_state: u8, - pub boot_status: u8, - pub fan_mask: u8, - pub battery_mask: u8, - pub temp_mask: u16, - pub key_mask: u16, - pub debug_mask: u16, - pub res0: u16, -} - -#[allow(missing_docs)] -#[repr(C, packed)] -#[derive(Clone, Copy, Debug, Default)] -pub struct Battery { - pub events: u32, - pub status: u32, - pub last_full_charge: u32, - pub cycle_count: u32, - pub state: u32, - pub present_rate: u32, - pub remain_cap: u32, - pub present_volt: u32, - pub psr_state: u32, - pub psr_max_out: u32, - pub psr_max_in: u32, - pub peak_level: u32, - pub peak_power: u32, - pub sus_level: u32, - pub sus_power: u32, - pub peak_thres: u32, - pub sus_thres: u32, - pub trip_thres: u32, - pub bmc_data: u32, - pub bmd_data: u32, - pub bmd_flags: u32, - pub bmd_count: u32, - pub charge_time: u32, - pub run_time: u32, - pub sample_time: u32, -} - -#[allow(missing_docs)] -#[repr(C, packed)] -#[derive(Clone, Copy, Debug, Default)] -pub struct Thermal { - pub events: u32, - pub cool_mode: u32, - pub dba_limit: u32, - pub sonne_limit: u32, - pub ma_limit: u32, - pub fan1_on_temp: u32, - pub fan1_ramp_temp: u32, - pub fan1_max_temp: u32, - pub fan1_crt_temp: u32, - pub fan1_hot_temp: u32, - pub fan1_max_rpm: u32, - pub fan1_cur_rpm: u32, - pub tmp1_val: u32, - pub tmp1_timeout: u32, - pub tmp1_low: u32, - pub tmp1_high: u32, -} - -#[allow(missing_docs)] -#[repr(C, packed)] -#[derive(Clone, Copy, Debug, Default)] -pub struct Notifications { - pub service: u16, - pub event: u16, -} - -#[allow(missing_docs)] -#[repr(C, packed)] -#[derive(Clone, Copy, Debug, Default)] -pub struct ECMemory { - pub ver: Version, - pub caps: Capabilities, - pub notif: Notifications, - pub batt: Battery, - pub therm: Thermal, -} diff --git a/embedded-service/src/lib.rs b/embedded-service/src/lib.rs index 7facbbe0..660aaf5a 100644 --- a/embedded-service/src/lib.rs +++ b/embedded-service/src/lib.rs @@ -16,7 +16,6 @@ pub mod broadcaster; pub mod buffer; pub mod cfu; pub mod comms; -pub mod ec_type; pub mod fmt; pub mod hid; pub mod init; diff --git a/espi-service/src/espi_service.rs b/espi-service/src/espi_service.rs index 74fd5582..79b2ac03 100644 --- a/espi-service/src/espi_service.rs +++ b/espi-service/src/espi_service.rs @@ -4,11 +4,10 @@ use crate::mctp::{HostRequest, HostResult, OdpHeader, OdpMessageType, OdpService use core::borrow::BorrowMut; use embassy_imxrt::espi; use embassy_sync::channel::Channel; -use embassy_sync::mutex::Mutex; use embassy_sync::once_lock::OnceLock; use embedded_services::buffer::OwnedRef; use embedded_services::comms::{self, EndpointID, External}; -use embedded_services::{GlobalRawMutex, debug, ec_type, error, info, trace}; +use embedded_services::{GlobalRawMutex, debug, error, info, trace}; use mctp_rs::smbus_espi::SmbusEspiMedium; use mctp_rs::smbus_espi::SmbusEspiReplyContext; @@ -39,16 +38,15 @@ pub enum Error { pub struct Service<'a> { endpoint: comms::Endpoint, - _ec_memory: Mutex, host_tx_queue: Channel, assembly_buf_owned_ref: OwnedRef<'a, u8>, } impl Service<'_> { - pub fn new(ec_memory: &'static mut ec_type::structure::ECMemory) -> Self { + #[allow(clippy::new_without_default)] // When we break the dependency on embassy-imxrt, we'll need to take an eSPI trait implementation as an argument, so it doesn't make sense to provide a default implementation + pub fn new() -> Self { Service { endpoint: comms::Endpoint::uninit(EndpointID::External(External::Host)), - _ec_memory: Mutex::new(ec_memory), host_tx_queue: Channel::new(), assembly_buf_owned_ref: assembly_buf::get_mut().unwrap(), } diff --git a/espi-service/src/task.rs b/espi-service/src/task.rs index dc7ac53c..45830259 100644 --- a/espi-service/src/task.rs +++ b/espi-service/src/task.rs @@ -1,34 +1,15 @@ use embassy_futures::select::select; use embassy_imxrt::espi; -use embedded_services::{comms, ec_type, info}; +use embedded_services::comms; use crate::{ESPI_SERVICE, Service, process_controller_event}; pub async fn espi_service( mut espi: espi::Espi<'static>, - memory_map_buffer: &'static mut [u8], ) -> Result { - info!("Reserved eSPI memory map buffer size: {}", memory_map_buffer.len()); - info!("eSPI MemoryMap size: {}", size_of::()); - - if size_of::() > memory_map_buffer.len() { - panic!("eSPI MemoryMap is too big for reserved memory buffer!!!"); - } - - memory_map_buffer.fill(0); - - let memory_map: &mut ec_type::structure::ECMemory = - unsafe { &mut *(memory_map_buffer.as_mut_ptr() as *mut ec_type::structure::ECMemory) }; - espi.wait_for_plat_reset().await; - info!("Initializing memory map"); - memory_map.ver.major = ec_type::structure::EC_MEMMAP_VERSION.major; - memory_map.ver.minor = ec_type::structure::EC_MEMMAP_VERSION.minor; - memory_map.ver.spin = ec_type::structure::EC_MEMMAP_VERSION.spin; - memory_map.ver.res0 = ec_type::structure::EC_MEMMAP_VERSION.res0; - - let espi_service = ESPI_SERVICE.get_or_init(|| Service::new(memory_map)); + let espi_service = ESPI_SERVICE.get_or_init(Service::new); comms::register_endpoint(espi_service, espi_service.endpoint()) .await .unwrap(); diff --git a/examples/rt633/src/bin/espi.rs b/examples/rt633/src/bin/espi.rs deleted file mode 100644 index 60850559..00000000 --- a/examples/rt633/src/bin/espi.rs +++ /dev/null @@ -1,177 +0,0 @@ -#![no_std] -#![no_main] - -extern crate rt633_examples; - -use core::slice::{self}; - -use defmt::info; -use embassy_executor::Spawner; -use embassy_imxrt::bind_interrupts; -use embassy_imxrt::espi::BaseOrAsz; -use embassy_imxrt::espi::{Base, Capabilities, Config, Direction, Espi, InterruptHandler, Len, Maxspd, PortConfig}; -use embassy_imxrt::peripherals::ESPI; -use {defmt_rtt as _, panic_probe as _}; - -// Mock battery service -mod battery_service { - use defmt::info; - use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; - use embassy_sync::once_lock::OnceLock; - use embassy_sync::signal::Signal; - use embedded_services::comms::{self, EndpointID, External, Internal}; - use embedded_services::ec_type; - - struct Service { - endpoint: comms::Endpoint, - - // This is can be an Embassy signal or channel or whatever Embassy async notification construct - signal: Signal, - } - - impl Service { - fn new() -> Self { - Service { - endpoint: comms::Endpoint::uninit(EndpointID::Internal(Internal::Battery)), - signal: Signal::new(), - } - } - } - - impl comms::MailboxDelegate for Service { - fn receive(&self, message: &comms::Message) -> Result<(), comms::MailboxDelegateError> { - let msg = message - .data - .get::() - .ok_or(comms::MailboxDelegateError::MessageNotFound)?; - - self.signal.signal(*msg); - - Ok(()) - } - } - - static BATTERY_SERVICE: OnceLock = OnceLock::new(); - - // Initialize battery service - pub async fn init() { - let battery_service = BATTERY_SERVICE.get_or_init(Service::new); - - comms::register_endpoint(battery_service, &battery_service.endpoint) - .await - .unwrap(); - } - - // Service to update the battery value in the memory map periodically - #[embassy_executor::task] - pub async fn battery_update_service() { - let battery_service = BATTERY_SERVICE.get().await; - - let mut battery_remain_cap = u32::MAX; - - loop { - battery_service - .endpoint - .send( - EndpointID::External(External::Host), - &ec_type::message::BatteryMessage::RemainCap(battery_remain_cap), - ) - .await - .unwrap(); - info!("Sending updated battery status to espi service"); - battery_remain_cap -= 1; - - embassy_time::Timer::after_secs(1).await; - } - } -} - -bind_interrupts!(struct Irqs { - ESPI => InterruptHandler; -}); - -// SAFETY: These are symbols defined by the linker and guaranteed to point to valid memory -unsafe extern "C" { - static __start_espi_data: u8; - static __end_espi_data: u8; -} - -#[embassy_executor::task] -async fn espi_service_task(espi: embassy_imxrt::espi::Espi<'static>, memory_map_buffer: &'static mut [u8]) -> ! { - let Err(e) = espi_service::task::espi_service(espi, memory_map_buffer).await; - panic!("espi_service_task error: {e:?}"); -} - -#[embassy_executor::main] -async fn main(spawner: Spawner) { - let p = embassy_imxrt::init(Default::default()); - - embedded_services::init().await; - - let espi = Espi::new( - p.ESPI, - p.PIO7_29, - p.PIO7_26, - p.PIO7_27, - p.PIO7_28, - p.PIO7_30, - p.PIO7_31, - p.PIO7_25, - p.PIO7_24, - Irqs, - Config { - caps: Capabilities { - max_speed: Maxspd::SmallThan20m, - alert_as_a_pin: true, - ..Default::default() - }, - ram_base: 0x2000_0000, - base0_addr: 0x2002_0000, - base1_addr: 0x2003_0000, - status_addr: Some(0x480), - status_base: Base::OffsetFrom0, - ports_config: [ - PortConfig::MailboxShared { - direction: Direction::BidirectionalUnenforced, - base_sel: BaseOrAsz::OffsetFrom0, - offset: 0, - length: Len::Len256, - }, - Default::default(), - Default::default(), - Default::default(), - Default::default(), - ], - ..Default::default() - }, - ); - - let memory_map_buffer = unsafe { - let start_espi_data = &__start_espi_data as *const u8 as *mut u8; - let end_espi_data = &__end_espi_data as *const u8 as *mut u8; - let espi_data_len = end_espi_data.offset_from(start_espi_data) as usize; - - slice::from_raw_parts_mut(start_espi_data, espi_data_len) - }; - - spawner.must_spawn(espi_service_task(espi, memory_map_buffer)); - - battery_service::init().await; - - spawner.spawn(battery_service::battery_update_service()).unwrap(); - - loop { - embassy_time::Timer::after_secs(10).await; - info!("The uptime is {} secs", embassy_time::Instant::now().as_secs()); - - let data = unsafe { - let start_espi_data = &__start_espi_data as *const u8 as *mut u8; - let end_espi_data = &__end_espi_data as *const u8 as *mut u8; - let espi_data_len = end_espi_data.offset_from(start_espi_data) as usize; - - slice::from_raw_parts_mut(start_espi_data, espi_data_len) - }; - - info!("Memory map contents: {:?}", data[..256]); - } -} diff --git a/examples/rt633/src/bin/espi_battery.rs b/examples/rt633/src/bin/espi_battery.rs deleted file mode 100644 index eb735976..00000000 --- a/examples/rt633/src/bin/espi_battery.rs +++ /dev/null @@ -1,268 +0,0 @@ -#![no_std] -#![no_main] - -extern crate rt633_examples; - -use battery_service::context::BatteryEvent; -use core::slice::{self}; -use embassy_imxrt::dma::NoDma; -use embassy_time::{Duration, Timer}; -use embedded_batteries_async::smart_battery::SmartBattery; -use embedded_services::{error, info}; - -use battery_service::controller::{Controller, ControllerEvent}; -use battery_service::device::{Device, DeviceId, DynamicBatteryMsgs, StaticBatteryMsgs}; -use battery_service::wrapper::Wrapper; -use bq40z50_rx::Bq40z50R5; -use embassy_embedded_hal::shared_bus::asynch::i2c::I2cDevice; -use embassy_executor::Spawner; -use embassy_imxrt::bind_interrupts; -use embassy_imxrt::espi::BaseOrAsz; -use embassy_imxrt::espi::{Base, Capabilities, Config, Direction, Espi, InterruptHandler, Len, Maxspd, PortConfig}; -use embassy_imxrt::i2c::Async; -use embassy_imxrt::i2c::master::I2cMaster; -use embassy_imxrt::peripherals::ESPI; -use embassy_sync::blocking_mutex::raw::NoopRawMutex; -use embassy_sync::mutex::Mutex; -use static_cell::StaticCell; -use {defmt_rtt as _, panic_probe as _}; - -bind_interrupts!(struct IrqsFg { - FLEXCOMM15 => embassy_imxrt::i2c::InterruptHandler; -}); - -static I2C_BUS_FG: StaticCell< - Mutex>, -> = StaticCell::new(); -static FG_DEVICE: StaticCell = StaticCell::new(); - -/// Wrapper struct for the fuel gauge driver -struct Bq40z50Controller { - driver: Bq40z50R5< - I2cDevice<'static, NoopRawMutex, embassy_imxrt::i2c::master::I2cMaster<'static, embassy_imxrt::i2c::Async>>, - embassy_time::Delay, - >, -} - -embedded_batteries_async::impl_smart_battery_for_wrapper_type!(Bq40z50Controller, driver, >, embassy_time::Delay> as embedded_batteries_async::smart_battery::ErrorType>::Error); - -impl Controller for Bq40z50Controller { - type ControllerError = >, embassy_time::Delay> as embedded_batteries_async::smart_battery::ErrorType>::Error; - - async fn initialize(&mut self) -> Result<(), Self::ControllerError> { - info!("Fuel gauge inited!"); - Ok(()) - } - - async fn get_static_data(&mut self) -> Result { - info!("Sending static data"); - - Ok(StaticBatteryMsgs { ..Default::default() }) - } - - async fn get_dynamic_data(&mut self) -> Result { - info!("Sending dynamic data"); - info!("Voltage = {}", self.voltage().await?); - info!("Current = {}", self.current().await?); - info!("Cycle count = {}", self.cycle_count().await?); - - Ok(DynamicBatteryMsgs { ..Default::default() }) - } - - async fn get_device_event(&mut self) -> ControllerEvent { - loop { - Timer::after_secs(1000000).await; - } - } - - async fn ping(&mut self) -> Result<(), Self::ControllerError> { - info!("Ping!"); - Ok(()) - } - - fn get_timeout(&self) -> Duration { - unimplemented!() - } - - fn set_timeout(&mut self, _duration: Duration) { - unimplemented!() - } -} - -bind_interrupts!(struct Irqs { - ESPI => InterruptHandler; -}); - -// SAFETY: These are symbols defined by the linker and guaranteed to point to valid memory -unsafe extern "C" { - static __start_espi_data: u8; - static __end_espi_data: u8; -} - -#[embassy_executor::task] -async fn battery_publish_task(battery_service: &'static battery_service::Service, fg_device: &'static Device) { - loop { - Timer::after_secs(1).await; - // Get dynamic cache - let cache = fg_device.get_dynamic_battery_cache().await; - - // Send cache data to eSpi service - battery_service - .comms_send( - embedded_services::comms::EndpointID::External(embedded_services::comms::External::Host), - &embedded_services::ec_type::message::BatteryMessage::CycleCount(cache.cycle_count.into()), - ) - .await - .unwrap(); - } -} - -#[embassy_executor::task] -async fn wrapper_task(wrapper: Wrapper<'static, Bq40z50Controller>) { - loop { - wrapper.process().await; - info!("Got new wrapper message"); - } -} - -#[embassy_executor::task] -async fn espi_service_task(espi: embassy_imxrt::espi::Espi<'static>, memory_map_buffer: &'static mut [u8]) -> ! { - let Err(e) = espi_service::task::espi_service(espi, memory_map_buffer).await; - panic!("espi_service_task error: {e:?}"); -} - -#[embassy_executor::task] -async fn battery_service_task( - service: &'static battery_service::Service, - device: [&'static battery_service::device::Device; 1], -) { - if battery_service::task::task(service, device).await.is_err() { - error!("Failed to start battery service") - } -} - -#[embassy_executor::main] -async fn main(spawner: Spawner) { - let p = embassy_imxrt::init(Default::default()); - - embedded_services::init().await; - - let espi = Espi::new( - p.ESPI, - p.PIO7_29, - p.PIO7_26, - p.PIO7_27, - p.PIO7_28, - p.PIO7_30, - p.PIO7_31, - p.PIO7_25, - p.PIO7_24, - Irqs, - Config { - caps: Capabilities { - max_speed: Maxspd::SmallThan20m, - alert_as_a_pin: true, - ..Default::default() - }, - ram_base: 0x2000_0000, - base0_addr: 0x2002_0000, - base1_addr: 0x2003_0000, - status_addr: Some(0x480), - status_base: Base::OffsetFrom0, - ports_config: [ - PortConfig::MailboxShared { - direction: Direction::BidirectionalUnenforced, - base_sel: BaseOrAsz::OffsetFrom0, - offset: 0, - length: Len::Len512, - }, - Default::default(), - Default::default(), - Default::default(), - Default::default(), - ], - ..Default::default() - }, - ); - - let memory_map_buffer = unsafe { - let start_espi_data = &__start_espi_data as *const u8 as *mut u8; - let end_espi_data = &__end_espi_data as *const u8 as *mut u8; - let espi_data_len = end_espi_data.offset_from(start_espi_data) as usize; - - slice::from_raw_parts_mut(start_espi_data, espi_data_len) - }; - - spawner.must_spawn(espi_service_task(espi, memory_map_buffer)); - - let config = embassy_imxrt::i2c::master::Config { - speed: embassy_imxrt::i2c::master::Speed::Standard, - duty_cycle: embassy_imxrt::i2c::master::DutyCycle::new(50).unwrap(), - strict_mode: false, - }; - - let i2c_fg = embassy_imxrt::i2c::master::I2cMaster::new_async( - p.FLEXCOMM15, - p.PIOFC15_SCL, - p.PIOFC15_SDA, - IrqsFg, - config, - unsafe { embassy_imxrt::Peri::new_unchecked(NoDma) }, - ) - .unwrap(); - - let i2c_bus_fg = I2C_BUS_FG.init(Mutex::new(i2c_fg)); - - let fg_bus = I2cDevice::new(i2c_bus_fg); - - static BATTERY_SERVICE: battery_service::Service = battery_service::Service::new(); - - let fg = FG_DEVICE.init(Device::new(DeviceId(0))); - - let wrap = Wrapper::new( - fg, - Bq40z50Controller { - driver: Bq40z50R5::new(fg_bus, embassy_time::Delay), - }, - ); - - spawner.must_spawn(wrapper_task(wrap)); - spawner.must_spawn(battery_service_task(&BATTERY_SERVICE, [fg])); - - spawner.must_spawn(battery_publish_task(&BATTERY_SERVICE, fg)); - - if let Err(e) = BATTERY_SERVICE - .execute_event(BatteryEvent { - device_id: DeviceId(0), - event: battery_service::context::BatteryEventInner::DoInit, - }) - .await - { - error!("Error initializing fuel gauge, error: {:?}", e); - } - - loop { - embassy_time::Timer::after_secs(10).await; - info!("The uptime is {} secs", embassy_time::Instant::now().as_secs()); - - let data = unsafe { - let start_espi_data = &__start_espi_data as *const u8 as *mut u8; - let end_espi_data = &__end_espi_data as *const u8 as *mut u8; - let espi_data_len = end_espi_data.offset_from(start_espi_data) as usize; - - slice::from_raw_parts_mut(start_espi_data, espi_data_len) - }; - - info!("Memory map contents: {:?}", data[..64]); - - if let Err(e) = BATTERY_SERVICE - .execute_event(BatteryEvent { - device_id: DeviceId(0), - event: battery_service::context::BatteryEventInner::PollDynamicData, - }) - .await - { - error!("Error getting dynamic fuel gauge data, error: {:?}", e); - } - } -} diff --git a/examples/std/src/bin/battery.rs b/examples/std/src/bin/battery.rs deleted file mode 100644 index 605416e1..00000000 --- a/examples/std/src/bin/battery.rs +++ /dev/null @@ -1,504 +0,0 @@ -use std::convert::Infallible; - -use battery_service::controller::{Controller, ControllerEvent}; -use battery_service::device::{Device, DeviceId, DynamicBatteryMsgs, StaticBatteryMsgs}; -use battery_service::wrapper::Wrapper; -use embassy_executor::Spawner; -use embassy_sync::once_lock::OnceLock; -use embassy_time::{Duration, Timer}; -use embedded_batteries_async::charger::{MilliAmps, MilliVolts}; -use embedded_batteries_async::smart_battery::{ - self, BatteryModeFields, BatteryStatusFields, CapacityModeSignedValue, CapacityModeValue, Cycles, DeciKelvin, - ManufactureDate, MilliAmpsSigned, Minutes, Percent, SmartBattery, SpecificationInfoFields, -}; -use embedded_hal_mock::eh1::i2c::Mock; -use embedded_services::{error, info}; - -mod espi_service { - use battery_service::context::{BatteryEvent, BatteryEventInner}; - use battery_service::device::DeviceId; - use embassy_sync::once_lock::OnceLock; - use embassy_sync::signal::Signal; - use embassy_time::Timer; - use embedded_services::comms::{self, EndpointID, External}; - use embedded_services::ec_type::message::BatteryMessage; - use embedded_services::{GlobalRawMutex, error}; - use log::info; - - pub struct Service { - endpoint: comms::Endpoint, - _signal: Signal, - } - - impl Service { - pub fn new() -> Self { - Service { - endpoint: comms::Endpoint::uninit(EndpointID::External(External::Host)), - _signal: Signal::new(), - } - } - } - - impl comms::MailboxDelegate for Service { - fn receive(&self, message: &comms::Message) -> Result<(), comms::MailboxDelegateError> { - let msg = message - .data - .get::() - .ok_or(comms::MailboxDelegateError::MessageNotFound)?; - - match msg { - BatteryMessage::CycleCount(cycles) => { - info!("Bat cycles: {cycles}"); - Ok(()) - } - _ => Err(comms::MailboxDelegateError::InvalidData), - } - } - } - - static ESPI_SERVICE: OnceLock = OnceLock::new(); - - pub async fn init() { - let espi_service = ESPI_SERVICE.get_or_init(Service::new); - - comms::register_endpoint(espi_service, &espi_service.endpoint) - .await - .unwrap(); - } - - #[embassy_executor::task] - pub async fn task(battery_service: &'static battery_service::Service) { - let espi_service = ESPI_SERVICE.get().await; - - espi_service - .endpoint - .send( - EndpointID::Internal(comms::Internal::Battery), - &BatteryEvent { - device_id: DeviceId(0), - event: BatteryEventInner::DoInit, - }, - ) - .await - .unwrap(); - - if let Err(e) = battery_service.wait_for_battery_response().await { - error!("Init request failed with {:?}", e); - } - Timer::after_secs(5).await; - - espi_service - .endpoint - .send( - EndpointID::Internal(comms::Internal::Battery), - &BatteryEvent { - device_id: DeviceId(0), - event: BatteryEventInner::PollStaticData, - }, - ) - .await - .unwrap(); - - if let Err(e) = battery_service.wait_for_battery_response().await { - error!("static data request failed with {:?}", e); - } - - loop { - espi_service - .endpoint - .send( - EndpointID::Internal(comms::Internal::Battery), - &BatteryEvent { - device_id: DeviceId(0), - event: BatteryEventInner::PollDynamicData, - }, - ) - .await - .unwrap(); - - if let Err(e) = battery_service.wait_for_battery_response().await { - error!("dynamic data request failed with {:?}", e); - } - Timer::after_secs(5).await; - } - } -} - -struct FuelGaugeController { - driver: MockFuelGaugeDriver, -} - -impl smart_battery::ErrorType for FuelGaugeController { - type Error = Infallible; -} - -impl SmartBattery for FuelGaugeController { - async fn absolute_state_of_charge(&mut self) -> Result { - self.driver.absolute_state_of_charge().await - } - async fn at_rate(&mut self) -> Result { - self.driver.at_rate().await - } - async fn at_rate_ok(&mut self) -> Result { - self.driver.at_rate_ok().await - } - async fn at_rate_time_to_empty(&mut self) -> Result { - self.driver.at_rate_time_to_empty().await - } - async fn at_rate_time_to_full(&mut self) -> Result { - self.driver.at_rate_time_to_full().await - } - async fn average_current(&mut self) -> Result { - self.driver.average_current().await - } - async fn average_time_to_empty(&mut self) -> Result { - self.driver.average_time_to_empty().await - } - async fn average_time_to_full(&mut self) -> Result { - self.driver.average_time_to_full().await - } - async fn battery_mode(&mut self) -> Result { - self.driver.battery_mode().await - } - async fn battery_status(&mut self) -> Result { - self.driver.battery_status().await - } - async fn charging_current(&mut self) -> Result { - self.driver.charging_current().await - } - async fn charging_voltage(&mut self) -> Result { - self.driver.charging_voltage().await - } - async fn current(&mut self) -> Result { - self.driver.current().await - } - async fn cycle_count(&mut self) -> Result { - self.driver.cycle_count().await - } - async fn design_capacity(&mut self) -> Result { - self.driver.design_capacity().await - } - async fn design_voltage(&mut self) -> Result { - self.driver.design_voltage().await - } - async fn device_chemistry(&mut self, chemistry: &mut [u8]) -> Result<(), Self::Error> { - self.driver.device_chemistry(chemistry).await - } - async fn device_name(&mut self, name: &mut [u8]) -> Result<(), Self::Error> { - self.driver.device_name(name).await - } - async fn full_charge_capacity(&mut self) -> Result { - self.driver.full_charge_capacity().await - } - async fn manufacture_date(&mut self) -> Result { - self.driver.manufacture_date().await - } - async fn manufacturer_name(&mut self, name: &mut [u8]) -> Result<(), Self::Error> { - self.driver.manufacturer_name(name).await - } - async fn max_error(&mut self) -> Result { - self.driver.max_error().await - } - async fn relative_state_of_charge(&mut self) -> Result { - self.driver.relative_state_of_charge().await - } - async fn remaining_capacity(&mut self) -> Result { - self.driver.remaining_capacity().await - } - async fn remaining_capacity_alarm(&mut self) -> Result { - self.driver.remaining_capacity_alarm().await - } - async fn remaining_time_alarm(&mut self) -> Result { - self.driver.remaining_time_alarm().await - } - async fn run_time_to_empty(&mut self) -> Result { - self.driver.run_time_to_empty().await - } - async fn serial_number(&mut self) -> Result { - self.driver.serial_number().await - } - async fn set_at_rate(&mut self, rate: CapacityModeSignedValue) -> Result<(), Self::Error> { - self.driver.set_at_rate(rate).await - } - async fn set_battery_mode(&mut self, flags: BatteryModeFields) -> Result<(), Self::Error> { - self.driver.set_battery_mode(flags).await - } - async fn set_remaining_capacity_alarm(&mut self, capacity: CapacityModeValue) -> Result<(), Self::Error> { - self.driver.set_remaining_capacity_alarm(capacity).await - } - async fn set_remaining_time_alarm(&mut self, time: Minutes) -> Result<(), Self::Error> { - self.driver.set_remaining_time_alarm(time).await - } - async fn specification_info(&mut self) -> Result { - self.driver.specification_info().await - } - async fn temperature(&mut self) -> Result { - self.driver.temperature().await - } - async fn voltage(&mut self) -> Result { - self.driver.voltage().await - } -} - -impl Controller for FuelGaugeController { - type ControllerError = Infallible; - - async fn initialize(&mut self) -> Result<(), Self::ControllerError> { - info!("Fuel gauge inited!"); - Ok(()) - } - - async fn get_static_data(&mut self) -> Result { - info!("Sending static data"); - - Ok(StaticBatteryMsgs { ..Default::default() }) - } - - async fn get_dynamic_data(&mut self) -> Result { - info!("Sending dynamic data"); - Ok(DynamicBatteryMsgs { ..Default::default() }) - } - - async fn get_device_event(&mut self) -> ControllerEvent { - loop { - Timer::after_secs(1000000).await; - } - } - - async fn ping(&mut self) -> Result<(), Self::ControllerError> { - info!("Ping!"); - Ok(()) - } - - fn get_timeout(&self) -> Duration { - Duration::from_secs(5) - } - - fn set_timeout(&mut self, _duration: Duration) { - unimplemented!() - } -} - -struct MockFuelGaugeDriver { - _mock_bus: I2c, -} - -impl MockFuelGaugeDriver { - pub fn new(i2c: I2c) -> Self { - MockFuelGaugeDriver { _mock_bus: i2c } - } -} - -impl embedded_batteries_async::smart_battery::ErrorType - for MockFuelGaugeDriver -{ - type Error = Infallible; -} - -impl embedded_batteries_async::smart_battery::SmartBattery - for MockFuelGaugeDriver -{ - async fn remaining_capacity_alarm(&mut self) -> Result { - Ok(CapacityModeValue::MilliAmpUnsigned(0)) - } - - async fn set_remaining_capacity_alarm(&mut self, _capacity: CapacityModeValue) -> Result<(), Self::Error> { - Ok(()) - } - - async fn remaining_time_alarm(&mut self) -> Result { - Ok(0) - } - - async fn set_remaining_time_alarm(&mut self, _time: Minutes) -> Result<(), Self::Error> { - Ok(()) - } - - async fn battery_mode(&mut self) -> Result { - Ok(BatteryModeFields::new()) - } - - async fn set_battery_mode(&mut self, _flags: BatteryModeFields) -> Result<(), Self::Error> { - Ok(()) - } - - async fn at_rate(&mut self) -> Result { - Ok(CapacityModeSignedValue::MilliAmpSigned(0)) - } - - async fn set_at_rate(&mut self, _rate: CapacityModeSignedValue) -> Result<(), Self::Error> { - Ok(()) - } - - async fn at_rate_time_to_full(&mut self) -> Result { - Ok(0) - } - - async fn at_rate_time_to_empty(&mut self) -> Result { - Ok(0) - } - - async fn at_rate_ok(&mut self) -> Result { - Ok(true) - } - - async fn temperature(&mut self) -> Result { - Ok(0) - } - - async fn voltage(&mut self) -> Result { - Ok(0) - } - - async fn charging_voltage(&mut self) -> Result { - Ok(0) - } - - async fn current(&mut self) -> Result { - Ok(0) - } - - async fn charging_current(&mut self) -> Result { - Ok(0) - } - - async fn average_current( - &mut self, - ) -> Result { - Ok(0) - } - - async fn max_error(&mut self) -> Result { - Ok(0) - } - - async fn relative_state_of_charge( - &mut self, - ) -> Result { - Ok(0) - } - - async fn absolute_state_of_charge( - &mut self, - ) -> Result { - Ok(0) - } - - async fn remaining_capacity( - &mut self, - ) -> Result { - Ok(CapacityModeValue::MilliAmpUnsigned(0)) - } - - async fn full_charge_capacity( - &mut self, - ) -> Result { - Ok(CapacityModeValue::MilliAmpUnsigned(0)) - } - - async fn run_time_to_empty(&mut self) -> Result { - Ok(0) - } - - async fn average_time_to_empty(&mut self) -> Result { - Ok(0) - } - - async fn average_time_to_full(&mut self) -> Result { - Ok(0) - } - - async fn battery_status( - &mut self, - ) -> Result { - Ok(BatteryStatusFields::new()) - } - - async fn cycle_count(&mut self) -> Result { - Ok(33) - } - - async fn design_capacity( - &mut self, - ) -> Result { - Ok(CapacityModeValue::MilliAmpUnsigned(0)) - } - - async fn design_voltage(&mut self) -> Result { - Ok(0) - } - - async fn specification_info(&mut self) -> Result { - Ok(SpecificationInfoFields::new()) - } - - async fn manufacture_date( - &mut self, - ) -> Result { - Ok(ManufactureDate::new()) - } - - async fn serial_number(&mut self) -> Result { - Ok(0) - } - - async fn manufacturer_name(&mut self, _name: &mut [u8]) -> Result<(), Self::Error> { - Ok(()) - } - - async fn device_name(&mut self, _name: &mut [u8]) -> Result<(), Self::Error> { - Ok(()) - } - - async fn device_chemistry(&mut self, _chemistry: &mut [u8]) -> Result<(), Self::Error> { - Ok(()) - } -} - -#[embassy_executor::task] -async fn wrapper_task(wrapper: Wrapper<'static, FuelGaugeController>) { - loop { - wrapper.process().await; - info!("Got new wrapper message"); - } -} - -#[embassy_executor::task] -async fn battery_service_task( - service: &'static battery_service::Service, - device: [&'static battery_service::device::Device; 1], -) { - if let Err(e) = battery_service::task::task(service, device).await { - error!("Failed to start battery service with error {:?}", e) - } -} - -#[embassy_executor::main] -async fn main(spawner: Spawner) { - env_logger::builder().filter_level(log::LevelFilter::Info).init(); - - let expectations = vec![]; - - static DEV: OnceLock = OnceLock::new(); - - let dev = DEV.get_or_init(|| Device::new(DeviceId(0))); - - static SERVICE: battery_service::Service = battery_service::Service::new(); - - let wrap = Wrapper::new( - dev, - FuelGaugeController { - driver: MockFuelGaugeDriver::new(Mock::new(&expectations)), - }, - ); - - embedded_services::init().await; - info!("services init'd"); - - espi_service::init().await; - info!("espi service init'd"); - - spawner.must_spawn(espi_service::task(&SERVICE)); - spawner.must_spawn(wrapper_task(wrap)); - spawner.must_spawn(battery_service_task(&SERVICE, [dev])); -}