mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-07-23 15:08:19 +00:00
feat(core): event polling for power manager
[no changelog]
This commit is contained in:
parent
e3be94d599
commit
c89ca35bbc
@ -266,47 +266,47 @@ void prodtest_pm_event_monitor(cli_t* cli) {
|
||||
cli_error(cli, CLI_ERROR, "Failed to get power manager events");
|
||||
}
|
||||
|
||||
if (event_flag & PM_EVENT_USB_CONNECTED) {
|
||||
if (event_flag.flags.usb_connected) {
|
||||
cli_trace(cli, "USB connected");
|
||||
}
|
||||
|
||||
if (event_flag & PM_EVENT_USB_DISCONNECTED) {
|
||||
if (event_flag.flags.usb_disconnected) {
|
||||
cli_trace(cli, "USB disconnected");
|
||||
}
|
||||
|
||||
if (event_flag & PM_EVENT_WIRELESS_CONNECTED) {
|
||||
if (event_flag.flags.wireless_connected) {
|
||||
cli_trace(cli, "WLC connected");
|
||||
}
|
||||
|
||||
if (event_flag & PM_EVENT_WIRELESS_DISCONNECTED) {
|
||||
if (event_flag.flags.wireless_disconnected) {
|
||||
cli_trace(cli, "WLC disconnected");
|
||||
}
|
||||
|
||||
if (event_flag & PM_EVENT_ENTERED_MODE_ACTIVE) {
|
||||
if (event_flag.flags.entered_mode_active) {
|
||||
cli_trace(cli, "Power manager entered active mode");
|
||||
}
|
||||
|
||||
if (event_flag & PM_EVENT_ENTERED_MODE_POWER_SAVE) {
|
||||
if (event_flag.flags.entered_mode_power_save) {
|
||||
cli_trace(cli, "Power manager entered power save mode");
|
||||
}
|
||||
|
||||
if (event_flag & PM_EVENT_ENTERED_MODE_SHUTTING_DOWN) {
|
||||
if (event_flag.flags.entered_mode_shutting_down) {
|
||||
cli_trace(cli, "Power manager entered shutting down mode");
|
||||
}
|
||||
|
||||
if (event_flag & PM_EVENT_ENTERED_MODE_SUSPEND) {
|
||||
if (event_flag.flags.entered_mode_suspend) {
|
||||
cli_trace(cli, "Power manager entered suspend mode");
|
||||
}
|
||||
|
||||
if (event_flag & PM_EVENT_ENTERED_MODE_CHARGING) {
|
||||
if (event_flag.flags.entered_mode_charging) {
|
||||
cli_trace(cli, "Power manager entered charging mode");
|
||||
}
|
||||
|
||||
if (event_flag & PM_EVENT_ENTERED_MODE_HIBERNATE) {
|
||||
if (event_flag.flags.entered_mode_hibernate) {
|
||||
cli_trace(cli, "Power manager entered hibernate mode");
|
||||
}
|
||||
|
||||
if (event_flag & PM_EVENT_SOC_UPDATED) {
|
||||
if (event_flag.flags.soc_updated) {
|
||||
status = pm_get_state(&state);
|
||||
cli_trace(cli, "Power manager SOC changed to %d %%", state.soc);
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ const DEFAULT_BINDGEN_MACROS_COMMON: &[&str] = &[
|
||||
"-I../sec/entropy/inc",
|
||||
"-I../sys/time/inc",
|
||||
"-I../sys/task/inc",
|
||||
"-I../sys/power_manager/inc",
|
||||
"-I../util/flash/inc",
|
||||
"-I../util/translations/inc",
|
||||
"-I../models",
|
||||
@ -54,6 +55,7 @@ const DEFAULT_BINDGEN_MACROS_COMMON: &[&str] = &[
|
||||
"-DUSE_HAPTIC",
|
||||
"-DUSE_RGB_LED",
|
||||
"-DUSE_BLE",
|
||||
"-DUSE_POWER_MANAGER",
|
||||
"-DUSE_HW_JPEG_DECODER",
|
||||
];
|
||||
|
||||
@ -443,6 +445,10 @@ fn generate_trezorhal_bindings() {
|
||||
.allowlist_type("syshandle_t")
|
||||
.allowlist_type("sysevents_t")
|
||||
.allowlist_function("sysevents_poll")
|
||||
// power manager
|
||||
.allowlist_type("pm_event_t")
|
||||
.allowlist_function("pm_get_events")
|
||||
.allowlist_function("pm_get_state")
|
||||
// c_layout
|
||||
.allowlist_type("c_layout_t");
|
||||
|
||||
|
@ -3,5 +3,7 @@
|
||||
#![allow(clippy::upper_case_acronyms)]
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(clippy::transmute_int_to_bool)]
|
||||
#![allow(clippy::too_many_arguments)]
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/trezorhal.rs"));
|
||||
|
@ -39,5 +39,8 @@ pub mod time;
|
||||
#[cfg(feature = "ui")]
|
||||
pub mod sysevent;
|
||||
|
||||
#[cfg(feature = "bootloader")]
|
||||
#[cfg(feature = "power_manager")]
|
||||
pub mod power_manager;
|
||||
|
||||
#[cfg(any(feature = "bootloader", feature = "prodtest"))]
|
||||
pub mod layout_buf;
|
||||
|
46
core/embed/rust/src/trezorhal/power_manager.rs
Normal file
46
core/embed/rust/src/trezorhal/power_manager.rs
Normal file
@ -0,0 +1,46 @@
|
||||
use super::ffi;
|
||||
|
||||
use crate::ui::event::PMEvent;
|
||||
|
||||
pub enum ChargingState {
|
||||
Discharging,
|
||||
Charging,
|
||||
Idle,
|
||||
}
|
||||
|
||||
pub fn pm_parse_event(event: ffi::pm_event_t) -> PMEvent {
|
||||
let mut pm_event = PMEvent::default();
|
||||
|
||||
unsafe {
|
||||
pm_event.usb_connected = event.flags.usb_connected();
|
||||
pm_event.usb_disconnected = event.flags.usb_disconnected();
|
||||
pm_event.wireless_connected = event.flags.wireless_connected();
|
||||
pm_event.wireless_disconnected = event.flags.wireless_disconnected();
|
||||
pm_event.entered_mode_active = event.flags.entered_mode_active();
|
||||
pm_event.entered_mode_power_save = event.flags.entered_mode_power_save();
|
||||
pm_event.entered_mode_shutting_down = event.flags.entered_mode_shutting_down();
|
||||
pm_event.entered_mode_charging = event.flags.entered_mode_charging();
|
||||
pm_event.entered_mode_suspend = event.flags.entered_mode_suspend();
|
||||
pm_event.entered_mode_hibernate = event.flags.entered_mode_hibernate();
|
||||
pm_event.soc_updated = event.flags.soc_updated();
|
||||
pm_event.state_changed = event.flags.state_changed();
|
||||
}
|
||||
pm_event
|
||||
}
|
||||
|
||||
pub fn soc() -> u8 {
|
||||
let mut state: ffi::pm_state_t = unsafe { core::mem::zeroed() };
|
||||
unsafe { ffi::pm_get_state(&mut state as _) };
|
||||
state.soc
|
||||
}
|
||||
|
||||
pub fn charging_state() -> ChargingState {
|
||||
let mut state: ffi::pm_state_t = unsafe { core::mem::zeroed() };
|
||||
unsafe { ffi::pm_get_state(&mut state as _) };
|
||||
match state.charging_status {
|
||||
ffi::pm_charging_status_t_PM_BATTERY_DISCHARGING => ChargingState::Discharging,
|
||||
ffi::pm_charging_status_t_PM_BATTERY_CHARGING => ChargingState::Charging,
|
||||
ffi::pm_charging_status_t_PM_BATTERY_IDLE => ChargingState::Idle,
|
||||
_ => panic!("Unknown charging status"),
|
||||
}
|
||||
}
|
@ -16,6 +16,11 @@ use crate::trezorhal::touch::touch_get_event;
|
||||
#[cfg(feature = "touch")]
|
||||
use crate::ui::event::TouchEvent;
|
||||
|
||||
#[cfg(feature = "power_manager")]
|
||||
use crate::trezorhal::power_manager::pm_parse_event;
|
||||
#[cfg(feature = "power_manager")]
|
||||
use crate::ui::event::PMEvent;
|
||||
|
||||
#[cfg(feature = "button")]
|
||||
use crate::trezorhal::button::button_parse_event;
|
||||
#[cfg(feature = "button")]
|
||||
@ -123,6 +128,16 @@ pub fn parse_event(signalled: &sysevents_t) -> Option<Event> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "power_manager")]
|
||||
if signalled.read_ready & (1 << ffi::syshandle_t_SYSHANDLE_POWER_MANAGER) != 0 {
|
||||
let mut pm_event: ffi::pm_event_t = unsafe { mem::zeroed() };
|
||||
let event_available = unsafe { ffi::pm_get_events(&mut pm_event) };
|
||||
if event_available {
|
||||
let pm_event = pm_parse_event(pm_event);
|
||||
return Some(Event::PM(pm_event));
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,8 @@ use crate::{
|
||||
use crate::ui::event::BLEEvent;
|
||||
#[cfg(feature = "button")]
|
||||
use crate::ui::event::ButtonEvent;
|
||||
#[cfg(feature = "power_manager")]
|
||||
use crate::ui::event::PMEvent;
|
||||
use crate::ui::event::USBEvent;
|
||||
#[cfg(feature = "touch")]
|
||||
use crate::ui::{
|
||||
@ -324,6 +326,8 @@ pub enum Event {
|
||||
Touch(TouchEvent),
|
||||
#[cfg(feature = "ble")]
|
||||
BLE(BLEEvent),
|
||||
#[cfg(feature = "power_manager")]
|
||||
PM(PMEvent),
|
||||
USB(USBEvent),
|
||||
/// Previously requested timer was triggered. This invalidates the timer
|
||||
/// token (another timer has to be requested).
|
||||
|
@ -8,10 +8,15 @@ pub mod usb;
|
||||
#[cfg(feature = "ble")]
|
||||
mod ble;
|
||||
|
||||
#[cfg(feature = "power_manager")]
|
||||
mod power_manager;
|
||||
|
||||
#[cfg(feature = "ble")]
|
||||
pub use ble::BLEEvent;
|
||||
#[cfg(feature = "button")]
|
||||
pub use button::{ButtonEvent, PhysicalButton};
|
||||
#[cfg(feature = "power_manager")]
|
||||
pub use power_manager::PMEvent;
|
||||
#[cfg(feature = "touch")]
|
||||
pub use touch::{SwipeEvent, TouchEvent};
|
||||
|
||||
|
16
core/embed/rust/src/ui/event/power_manager.rs
Normal file
16
core/embed/rust/src/ui/event/power_manager.rs
Normal file
@ -0,0 +1,16 @@
|
||||
#[derive(Default, Copy, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "debug", derive(ufmt::derive::uDebug))]
|
||||
pub struct PMEvent {
|
||||
pub state_changed: bool,
|
||||
pub usb_connected: bool,
|
||||
pub usb_disconnected: bool,
|
||||
pub wireless_connected: bool,
|
||||
pub wireless_disconnected: bool,
|
||||
pub entered_mode_active: bool,
|
||||
pub entered_mode_power_save: bool,
|
||||
pub entered_mode_shutting_down: bool,
|
||||
pub entered_mode_charging: bool,
|
||||
pub entered_mode_suspend: bool,
|
||||
pub entered_mode_hibernate: bool,
|
||||
pub soc_updated: bool,
|
||||
}
|
@ -38,6 +38,10 @@
|
||||
#include <io/touch.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_POWER_MANAGER
|
||||
#include <sys/power_manager.h>
|
||||
#endif
|
||||
|
||||
#include "bip39.h"
|
||||
#include "rand.h"
|
||||
#include "slip39.h"
|
||||
|
@ -54,20 +54,22 @@ typedef enum {
|
||||
} pm_internal_state_t;
|
||||
|
||||
/* Power system events */
|
||||
typedef enum {
|
||||
PM_EVENT_NONE = 0,
|
||||
PM_EVENT_STATE_CHANGED = 1,
|
||||
PM_EVENT_USB_CONNECTED = 1 << 1,
|
||||
PM_EVENT_USB_DISCONNECTED = 1 << 2,
|
||||
PM_EVENT_WIRELESS_CONNECTED = 1 << 3,
|
||||
PM_EVENT_WIRELESS_DISCONNECTED = 1 << 4,
|
||||
PM_EVENT_ENTERED_MODE_HIBERNATE = 1 << 5,
|
||||
PM_EVENT_ENTERED_MODE_CHARGING = 1 << 6,
|
||||
PM_EVENT_ENTERED_MODE_SUSPEND = 1 << 7,
|
||||
PM_EVENT_ENTERED_MODE_SHUTTING_DOWN = 1 << 8,
|
||||
PM_EVENT_ENTERED_MODE_POWER_SAVE = 1 << 9,
|
||||
PM_EVENT_ENTERED_MODE_ACTIVE = 1 << 10,
|
||||
PM_EVENT_SOC_UPDATED = 1 << 11,
|
||||
typedef union {
|
||||
uint32_t all;
|
||||
struct {
|
||||
bool state_changed : 1;
|
||||
bool usb_connected : 1;
|
||||
bool usb_disconnected : 1;
|
||||
bool wireless_connected : 1;
|
||||
bool wireless_disconnected : 1;
|
||||
bool entered_mode_hibernate : 1;
|
||||
bool entered_mode_charging : 1;
|
||||
bool entered_mode_suspend : 1;
|
||||
bool entered_mode_active : 1;
|
||||
bool entered_mode_power_save : 1;
|
||||
bool entered_mode_shutting_down : 1;
|
||||
bool soc_updated : 1;
|
||||
} flags;
|
||||
} pm_event_t;
|
||||
|
||||
typedef struct {
|
||||
@ -99,7 +101,7 @@ typedef struct {
|
||||
/* Public API functions */
|
||||
pm_status_t pm_init(bool inherit_state);
|
||||
void pm_deinit(void);
|
||||
pm_status_t pm_get_events(pm_event_t* event_flags);
|
||||
bool pm_get_events(pm_event_t* event_flags);
|
||||
pm_status_t pm_get_state(pm_state_t* state);
|
||||
pm_status_t pm_suspend(void);
|
||||
pm_status_t pm_hibernate(void);
|
||||
|
198
core/embed/sys/power_manager/power_manager_poll.c
Normal file
198
core/embed/sys/power_manager/power_manager_poll.c
Normal file
@ -0,0 +1,198 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef KERNEL_MODE
|
||||
|
||||
#include <trezor_rtl.h>
|
||||
|
||||
#include <sys/power_manager.h>
|
||||
#include <sys/sysevent_source.h>
|
||||
#include <sys/systick.h>
|
||||
|
||||
#include "power_manager_poll.h"
|
||||
|
||||
typedef struct {
|
||||
// Time (in ticks) when the tls was last updated
|
||||
uint32_t update_ticks;
|
||||
// Last state
|
||||
pm_state_t pm_state;
|
||||
// Pending events
|
||||
pm_event_t event;
|
||||
bool pending_event;
|
||||
|
||||
} pm_fsm_t;
|
||||
|
||||
// State machine for each task
|
||||
static pm_fsm_t tls[SYSTASK_MAX_TASKS] = {0};
|
||||
|
||||
// Forward declarations
|
||||
static const syshandle_vmt_t g_pm_handle_vmt;
|
||||
|
||||
bool pm_poll_init(void) {
|
||||
return syshandle_register(SYSHANDLE_POWER_MANAGER, &g_pm_handle_vmt, NULL);
|
||||
}
|
||||
|
||||
void pm_poll_deinit(void) { syshandle_unregister(SYSHANDLE_POWER_MANAGER); }
|
||||
|
||||
void pm_fsm_clear(pm_fsm_t* fsm) { memset(fsm, 0, sizeof(pm_fsm_t)); }
|
||||
|
||||
static void pm_clear_state_flags(pm_fsm_t* fsm) {
|
||||
fsm->event.flags.entered_mode_active = false;
|
||||
fsm->event.flags.entered_mode_power_save = false;
|
||||
fsm->event.flags.entered_mode_shutting_down = false;
|
||||
fsm->event.flags.entered_mode_charging = false;
|
||||
fsm->event.flags.entered_mode_suspend = false;
|
||||
fsm->event.flags.entered_mode_hibernate = false;
|
||||
}
|
||||
|
||||
bool pm_fsm_event_ready(pm_fsm_t* fsm, pm_state_t* new_state) {
|
||||
bool event_detected = false;
|
||||
|
||||
// Remember state changes
|
||||
fsm->update_ticks = systick_ms();
|
||||
|
||||
// Return true if there are any state changes
|
||||
if (new_state->soc != fsm->pm_state.soc) {
|
||||
fsm->event.flags.soc_updated = true;
|
||||
event_detected = true;
|
||||
}
|
||||
|
||||
if (new_state->usb_connected && !fsm->pm_state.usb_connected) {
|
||||
fsm->event.flags.usb_connected = true;
|
||||
fsm->event.flags.usb_disconnected = false;
|
||||
}
|
||||
|
||||
if (!new_state->usb_connected && fsm->pm_state.usb_connected) {
|
||||
fsm->event.flags.usb_disconnected = true;
|
||||
fsm->event.flags.usb_connected = false;
|
||||
}
|
||||
|
||||
if (new_state->wireless_connected && !fsm->pm_state.wireless_connected) {
|
||||
fsm->event.flags.wireless_connected = true;
|
||||
fsm->event.flags.wireless_disconnected = false;
|
||||
}
|
||||
|
||||
if (!new_state->wireless_connected && fsm->pm_state.wireless_connected) {
|
||||
fsm->event.flags.wireless_disconnected = true;
|
||||
fsm->event.flags.wireless_connected = false;
|
||||
}
|
||||
|
||||
if (new_state->power_state == PM_STATE_ACTIVE) {
|
||||
if (fsm->pm_state.power_state != PM_STATE_ACTIVE) {
|
||||
pm_clear_state_flags(fsm);
|
||||
fsm->event.flags.entered_mode_active = true;
|
||||
event_detected = true;
|
||||
}
|
||||
} else if (new_state->power_state == PM_STATE_POWER_SAVE) {
|
||||
if (fsm->pm_state.power_state != PM_STATE_POWER_SAVE) {
|
||||
pm_clear_state_flags(fsm);
|
||||
fsm->event.flags.entered_mode_power_save = true;
|
||||
event_detected = true;
|
||||
}
|
||||
} else if (new_state->power_state == PM_STATE_SHUTTING_DOWN) {
|
||||
if (fsm->pm_state.power_state != PM_STATE_SHUTTING_DOWN) {
|
||||
pm_clear_state_flags(fsm);
|
||||
fsm->event.flags.entered_mode_shutting_down = true;
|
||||
event_detected = true;
|
||||
}
|
||||
} else if (new_state->power_state == PM_STATE_CHARGING) {
|
||||
if (fsm->pm_state.power_state != PM_STATE_CHARGING) {
|
||||
pm_clear_state_flags(fsm);
|
||||
fsm->event.flags.entered_mode_charging = true;
|
||||
event_detected = true;
|
||||
}
|
||||
} else if (new_state->power_state == PM_STATE_SUSPEND) {
|
||||
if (fsm->pm_state.power_state != PM_STATE_SUSPEND) {
|
||||
pm_clear_state_flags(fsm);
|
||||
fsm->event.flags.entered_mode_suspend = true;
|
||||
event_detected = true;
|
||||
}
|
||||
} else if (new_state->power_state == PM_STATE_HIBERNATE) {
|
||||
if (fsm->pm_state.power_state != PM_STATE_HIBERNATE) {
|
||||
pm_clear_state_flags(fsm);
|
||||
fsm->event.flags.entered_mode_hibernate = true;
|
||||
event_detected = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_state->charging_status != fsm->pm_state.charging_status) {
|
||||
fsm->event.flags.state_changed = true;
|
||||
event_detected = true;
|
||||
}
|
||||
|
||||
if (event_detected) {
|
||||
fsm->pending_event = true;
|
||||
}
|
||||
|
||||
memcpy(&fsm->pm_state, new_state, sizeof(pm_state_t));
|
||||
|
||||
return event_detected;
|
||||
}
|
||||
|
||||
bool pm_fsm_get_event(pm_fsm_t* fsm, pm_event_t* event) {
|
||||
if (fsm->pending_event) {
|
||||
memcpy(event, &fsm->event, sizeof(pm_event_t));
|
||||
memset(&fsm->event, 0, sizeof(pm_event_t));
|
||||
fsm->pending_event = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void on_task_created(void* context, systask_id_t task_id) {
|
||||
pm_fsm_t* fsm = &tls[task_id];
|
||||
pm_fsm_clear(fsm);
|
||||
}
|
||||
|
||||
static void on_event_poll(void* context, bool read_awaited,
|
||||
bool write_awaited) {
|
||||
UNUSED(write_awaited);
|
||||
|
||||
if (read_awaited) {
|
||||
pm_state_t state = {0};
|
||||
pm_get_state(&state);
|
||||
syshandle_signal_read_ready(SYSHANDLE_POWER_MANAGER, &state);
|
||||
}
|
||||
}
|
||||
|
||||
static bool on_check_read_ready(void* context, systask_id_t task_id,
|
||||
void* param) {
|
||||
pm_fsm_t* fsm = &tls[task_id];
|
||||
|
||||
pm_state_t* new_state = (pm_state_t*)param;
|
||||
|
||||
return pm_fsm_event_ready(fsm, new_state);
|
||||
}
|
||||
|
||||
static const syshandle_vmt_t g_pm_handle_vmt = {
|
||||
.task_created = on_task_created,
|
||||
.task_killed = NULL,
|
||||
.check_read_ready = on_check_read_ready,
|
||||
.check_write_ready = NULL,
|
||||
.poll = on_event_poll,
|
||||
};
|
||||
|
||||
bool pm_get_events(pm_event_t* event_flags) {
|
||||
pm_fsm_t* fsm = &tls[systask_id(systask_active())];
|
||||
|
||||
return pm_fsm_get_event(fsm, event_flags);
|
||||
}
|
||||
|
||||
#endif // KERNEL_MODE
|
27
core/embed/sys/power_manager/power_manager_poll.h
Normal file
27
core/embed/sys/power_manager/power_manager_poll.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// This module implements system event evaluation & polling mechanism for power
|
||||
// manager.
|
||||
|
||||
bool pm_poll_init(void);
|
||||
|
||||
void pm_poll_deinit(void);
|
@ -25,6 +25,7 @@
|
||||
#include <sys/systimer.h>
|
||||
#include <trezor_rtl.h>
|
||||
|
||||
#include "../power_manager_poll.h"
|
||||
#include "../stwlc38/stwlc38.h"
|
||||
#include "power_manager_internal.h"
|
||||
|
||||
@ -55,6 +56,11 @@ pm_status_t pm_init(bool inherit_state) {
|
||||
return PM_ERROR;
|
||||
}
|
||||
|
||||
if (!pm_poll_init()) {
|
||||
pm_deinit();
|
||||
return PM_ERROR;
|
||||
}
|
||||
|
||||
// Initialize fuel gauge
|
||||
fuel_gauge_init(&drv->fuel_gauge, PM_FUEL_GAUGE_R, PM_FUEL_GAUGE_Q,
|
||||
PM_FUEL_GAUGE_R_AGGRESSIVE, PM_FUEL_GAUGE_Q_AGGRESSIVE,
|
||||
@ -128,6 +134,8 @@ pm_status_t pm_init(bool inherit_state) {
|
||||
void pm_deinit(void) {
|
||||
pm_driver_t* drv = &g_pm;
|
||||
|
||||
pm_poll_deinit();
|
||||
|
||||
if (drv->monitoring_timer) {
|
||||
systimer_delete(drv->monitoring_timer);
|
||||
drv->monitoring_timer = NULL;
|
||||
@ -148,21 +156,6 @@ void pm_deinit(void) {
|
||||
drv->initialized = false;
|
||||
}
|
||||
|
||||
pm_status_t pm_get_events(pm_event_t* event_flags) {
|
||||
pm_driver_t* drv = &g_pm;
|
||||
|
||||
if (!drv->initialized) {
|
||||
return PM_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
irq_key_t irq_key = irq_lock();
|
||||
*event_flags = drv->event_flags;
|
||||
PM_CLEAR_ALL_EVENTS(drv->event_flags);
|
||||
irq_unlock(irq_key);
|
||||
|
||||
return PM_OK;
|
||||
}
|
||||
|
||||
pm_status_t pm_get_state(pm_state_t* state) {
|
||||
pm_driver_t* drv = &g_pm;
|
||||
|
||||
|
@ -46,11 +46,6 @@
|
||||
#define PM_FUEL_GAUGE_Q_AGGRESSIVE 0.01f
|
||||
#define PM_FUEL_GAUGE_P_INIT 0.1f
|
||||
|
||||
// Event flag manipulation macros
|
||||
#define PM_SET_EVENT(flags, event) ((flags) |= (event))
|
||||
#define PM_CLEAR_EVENT(flags, event) ((flags) &= ~(event))
|
||||
#define PM_CLEAR_ALL_EVENTS(flags) ((flags) = 0)
|
||||
|
||||
// Power manager battery sampling data structure
|
||||
typedef struct {
|
||||
float vbat; // Battery voltage [V]
|
||||
@ -63,7 +58,6 @@ typedef struct {
|
||||
bool initialized;
|
||||
bool state_machine_stabilized;
|
||||
pm_internal_state_t state;
|
||||
pm_event_t event_flags;
|
||||
|
||||
// Fuel gauge
|
||||
fuel_gauge_state_t fuel_gauge;
|
||||
|
@ -40,12 +40,10 @@ void pm_monitor_power_sources(void) {
|
||||
if (drv->pmic_data.usb_status != 0x0) {
|
||||
if (!drv->usb_connected) {
|
||||
drv->usb_connected = true;
|
||||
PM_SET_EVENT(drv->event_flags, PM_EVENT_USB_CONNECTED);
|
||||
}
|
||||
} else {
|
||||
if (drv->usb_connected) {
|
||||
drv->usb_connected = false;
|
||||
PM_SET_EVENT(drv->event_flags, PM_EVENT_USB_DISCONNECTED);
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,12 +51,10 @@ void pm_monitor_power_sources(void) {
|
||||
if (drv->wireless_data.vout_ready) {
|
||||
if (!drv->wireless_connected) {
|
||||
drv->wireless_connected = true;
|
||||
PM_SET_EVENT(drv->event_flags, PM_EVENT_WIRELESS_CONNECTED);
|
||||
}
|
||||
} else {
|
||||
if (drv->wireless_connected) {
|
||||
drv->wireless_connected = false;
|
||||
PM_SET_EVENT(drv->event_flags, PM_EVENT_WIRELESS_DISCONNECTED);
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,7 +100,6 @@ void pm_monitor_power_sources(void) {
|
||||
uint8_t soc_ceiled_temp = (int)(drv->fuel_gauge.soc_latched * 100 + 0.999f);
|
||||
if (soc_ceiled_temp != drv->soc_ceiled) {
|
||||
drv->soc_ceiled = soc_ceiled_temp;
|
||||
PM_SET_EVENT(drv->event_flags, PM_EVENT_SOC_UPDATED);
|
||||
}
|
||||
|
||||
// Check battery voltage for low threshold
|
||||
@ -260,3 +255,5 @@ void pm_battery_initial_soc_guess(void) {
|
||||
|
||||
fuel_gauge_initial_guess(&drv->fuel_gauge, vbat_g, ibat_g, ntc_temp_g);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -88,7 +88,6 @@ void pm_process_state_machine(void) {
|
||||
|
||||
// Update state
|
||||
drv->state = new_state;
|
||||
PM_SET_EVENT(drv->event_flags, PM_EVENT_STATE_CHANGED);
|
||||
|
||||
// Enter new state
|
||||
if (state_handlers[new_state].enter != NULL) {
|
||||
@ -236,39 +235,29 @@ pm_internal_state_t pm_handle_state_active(pm_driver_t* drv) {
|
||||
// State enter/exit actions
|
||||
|
||||
void pm_enter_hibernate(pm_driver_t* drv) {
|
||||
PM_SET_EVENT(drv->event_flags, PM_EVENT_ENTERED_MODE_HIBERNATE);
|
||||
|
||||
// Store power manager data with request to hibernate, power manager
|
||||
// will try to hibernate immediately after reboot.
|
||||
pm_store_data_to_backup_ram();
|
||||
reboot_device();
|
||||
}
|
||||
|
||||
void pm_enter_charging(pm_driver_t* drv) {
|
||||
PM_SET_EVENT(drv->event_flags, PM_EVENT_ENTERED_MODE_CHARGING);
|
||||
}
|
||||
void pm_enter_charging(pm_driver_t* drv) {}
|
||||
|
||||
void pm_enter_suspend(pm_driver_t* drv) {
|
||||
PM_SET_EVENT(drv->event_flags, PM_EVENT_ENTERED_MODE_SUSPEND);
|
||||
pm_control_suspend();
|
||||
}
|
||||
void pm_enter_suspend(pm_driver_t* drv) { pm_control_suspend(); }
|
||||
|
||||
void pm_enter_shutting_down(pm_driver_t* drv) {
|
||||
// Set shutdown timer
|
||||
systimer_set(drv->shutdown_timer, PM_SHUTDOWN_TIMEOUT_MS);
|
||||
PM_SET_EVENT(drv->event_flags, PM_EVENT_ENTERED_MODE_SHUTTING_DOWN);
|
||||
}
|
||||
|
||||
void pm_enter_power_save(pm_driver_t* drv) {
|
||||
// Limit backlight
|
||||
backlight_set_max_level(130);
|
||||
PM_SET_EVENT(drv->event_flags, PM_EVENT_ENTERED_MODE_POWER_SAVE);
|
||||
}
|
||||
|
||||
void pm_enter_active(pm_driver_t* drv) {
|
||||
// Set unlimited backlight
|
||||
backlight_set_max_level(255);
|
||||
PM_SET_EVENT(drv->event_flags, PM_EVENT_ENTERED_MODE_ACTIVE);
|
||||
}
|
||||
|
||||
void pm_exit_shutting_down(pm_driver_t* drv) {
|
||||
|
@ -27,7 +27,7 @@ typedef enum {
|
||||
SYSHANDLE_USB_IFACE_7 = SYSHANDLE_USB_IFACE_0 + 7,
|
||||
SYSHANDLE_BLE_IFACE_0,
|
||||
// SYSHANDLE_BLE_IFACE_N = SYSHANDLE_BLE_IFACE_0 + N - 1,
|
||||
SYSHANDLE_POWERCTL,
|
||||
SYSHANDLE_POWER_MANAGER,
|
||||
SYSHANDLE_BUTTON,
|
||||
SYSHANDLE_TOUCH,
|
||||
SYSHANDLE_USB,
|
||||
|
@ -251,6 +251,7 @@ def configure(
|
||||
"embed/sys/power_manager/fuel_gauge/battery_model.c",
|
||||
"embed/sys/power_manager/stwlc38/stwlc38.c",
|
||||
"embed/sys/power_manager/stwlc38/stwlc38_patching.c",
|
||||
"embed/sys/power_manager/power_manager_poll.c",
|
||||
]
|
||||
paths += ["embed/sys/power_manager/inc"]
|
||||
defines += [("USE_POWER_MANAGER", "1")]
|
||||
|
@ -256,6 +256,7 @@ def configure(
|
||||
"embed/sys/power_manager/fuel_gauge/battery_model.c",
|
||||
"embed/sys/power_manager/stwlc38/stwlc38.c",
|
||||
"embed/sys/power_manager/stwlc38/stwlc38_patching.c",
|
||||
"embed/sys/power_manager/power_manager_poll.c",
|
||||
]
|
||||
paths += ["embed/sys/power_manager/inc"]
|
||||
defines += [("USE_POWER_MANAGER", "1")]
|
||||
|
@ -256,6 +256,7 @@ def configure(
|
||||
"embed/sys/power_manager/fuel_gauge/battery_model.c",
|
||||
"embed/sys/power_manager/stwlc38/stwlc38.c",
|
||||
"embed/sys/power_manager/stwlc38/stwlc38_patching.c",
|
||||
"embed/sys/power_manager/power_manager_poll.c",
|
||||
]
|
||||
paths += ["embed/sys/power_manager/inc"]
|
||||
defines += [("USE_POWER_MANAGER", "1")]
|
||||
|
Loading…
Reference in New Issue
Block a user