mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-11 17:08:15 +00:00
feat(core): introduce powerctl module
[no changelog]
This commit is contained in:
parent
3b4e451dad
commit
d5c42dfceb
@ -309,7 +309,8 @@ env.Replace(
|
|||||||
'-ffreestanding '
|
'-ffreestanding '
|
||||||
'-fstack-protector-all '
|
'-fstack-protector-all '
|
||||||
+ env.get('ENV')["CPU_CCFLAGS"] + CCFLAGS_MOD,
|
+ env.get('ENV')["CPU_CCFLAGS"] + CCFLAGS_MOD,
|
||||||
LINKFLAGS='-T build/kernel/memory.ld -Wl,--gc-sections -Wl,--print-memory-usage -Wl,-Map=build/kernel/kernel.map -Wl,--warn-common',
|
LINKFLAGS='-T build/kernel/memory.ld -Wl,--gc-sections -Wl,--print-memory-usage '
|
||||||
|
' -Wl,-Map=build/kernel/kernel.map -Wl,--warn-common -Wl,--undefined=__errno',
|
||||||
CPPPATH=ALLPATHS,
|
CPPPATH=ALLPATHS,
|
||||||
CPPDEFINES=[
|
CPPDEFINES=[
|
||||||
'KERNEL',
|
'KERNEL',
|
||||||
|
@ -55,6 +55,10 @@
|
|||||||
#include <sec/optiga_transport.h>
|
#include <sec/optiga_transport.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_POWERCTL
|
||||||
|
#include <sys/powerctl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef USE_PVD
|
#ifdef USE_PVD
|
||||||
#include <sys/pvd.h>
|
#include <sys/pvd.h>
|
||||||
#endif
|
#endif
|
||||||
@ -104,6 +108,10 @@ static void optiga_log_hex(const char *prefix, const uint8_t *data,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void drivers_init() {
|
void drivers_init() {
|
||||||
|
#ifdef USE_POWERCTL
|
||||||
|
powerctl_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef USE_TAMPER
|
#ifdef USE_TAMPER
|
||||||
tamper_init();
|
tamper_init();
|
||||||
#endif
|
#endif
|
||||||
|
58
core/embed/sys/powerctl/inc/sys/powerctl.h
Normal file
58
core/embed/sys/powerctl/inc/sys/powerctl.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TREZORHAL_POWERCTL_H
|
||||||
|
#define TREZORHAL_POWERCTL_H
|
||||||
|
|
||||||
|
// Initializes power control module.
|
||||||
|
//
|
||||||
|
// Returns true if the initialization was successful.
|
||||||
|
bool powerctl_init(void);
|
||||||
|
|
||||||
|
// Deinitializes power control module.
|
||||||
|
void powerctl_deinit(void);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
POWER_SOURCE_BATT,
|
||||||
|
POWER_SOURCE_USB,
|
||||||
|
POWER_SOURCE_WIRELESS,
|
||||||
|
} power_source_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
// Current power source
|
||||||
|
power_source_t power_source;
|
||||||
|
// Set if charging is active
|
||||||
|
bool charging;
|
||||||
|
// Battery charge level in percents
|
||||||
|
// (or -1 if the battery level is unknown)
|
||||||
|
int charge_level;
|
||||||
|
// Set if the temperature is too low
|
||||||
|
bool low_temperature;
|
||||||
|
// Set if the temperature is too high
|
||||||
|
bool high_temperature;
|
||||||
|
} powerctl_status_t;
|
||||||
|
|
||||||
|
// Gets the current power status.
|
||||||
|
void powerctl_get_status(powerctl_status_t* status);
|
||||||
|
|
||||||
|
// Enters low-power mode
|
||||||
|
//
|
||||||
|
void powerctl_suspend(void);
|
||||||
|
|
||||||
|
#endif // TREZORHAL_POWERCTL_H
|
44
core/embed/sys/powerctl/inc/sys/wakeup_flags.h
Normal file
44
core/embed/sys/powerctl/inc/sys/wakeup_flags.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TREZORHAL_WAKEUP_FLAGS_H
|
||||||
|
#define TREZORHAL_WAKEUP_FLAGS_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// Wakeup flags used to signal the reason of the wakeup
|
||||||
|
// from the STOP mode
|
||||||
|
|
||||||
|
#define WAKEUP_FLAG_BUTTON 0x01 // Button pressed
|
||||||
|
#define WAKEUP_FLAG_WPC 0x02 // Wireless power charging event
|
||||||
|
#define WAKEUP_FLAG_BLE 0x04 // Bluetooth connection event
|
||||||
|
#define WAKEUP_FLAG_NFC 0x08 // NFC event
|
||||||
|
#define WAKEUP_FLAG_USB 0x10 // USB event
|
||||||
|
#define WAKEUP_FLAG_TIMER 0x20 // Timer event
|
||||||
|
|
||||||
|
// Sets the wakeup flag
|
||||||
|
void wakeup_flags_set(uint16_t flags);
|
||||||
|
|
||||||
|
// Resets all wakeup flags
|
||||||
|
void wakeup_flags_reset(void);
|
||||||
|
|
||||||
|
// Gets current wakeup flags
|
||||||
|
uint16_t wakeup_flags_get(void);
|
||||||
|
|
||||||
|
#endif // TREZORHAL_WAKEUP_FLAGS_H
|
92
core/embed/sys/powerctl/stm32u5/powerctl.c
Normal file
92
core/embed/sys/powerctl/stm32u5/powerctl.c
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <trezor_bsp.h>
|
||||||
|
#include <trezor_rtl.h>
|
||||||
|
|
||||||
|
#include <sys/powerctl.h>
|
||||||
|
|
||||||
|
#include "../npm1300/npm1300.h"
|
||||||
|
#include "../stwlc38/stwlc38.h"
|
||||||
|
|
||||||
|
#ifdef KERNEL_MODE
|
||||||
|
|
||||||
|
// Power control driver state
|
||||||
|
typedef struct {
|
||||||
|
// True if the driver is initialized
|
||||||
|
bool initialized;
|
||||||
|
|
||||||
|
} powerctl_driver_t;
|
||||||
|
|
||||||
|
// Power control driver instance
|
||||||
|
static powerctl_driver_t g_powerctl_driver = {.initialized = false};
|
||||||
|
|
||||||
|
bool powerctl_init(void) {
|
||||||
|
powerctl_driver_t* drv = &g_powerctl_driver;
|
||||||
|
|
||||||
|
if (drv->initialized) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize PMIC
|
||||||
|
if (!npm1300_init()) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize wireless charging
|
||||||
|
if (!stwlc38_init()) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
drv->initialized = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
stwlc38_deinit();
|
||||||
|
npm1300_deinit();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void powerctl_deinit(void) {
|
||||||
|
powerctl_driver_t* drv = &g_powerctl_driver;
|
||||||
|
|
||||||
|
if (!drv->initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stwlc38_deinit();
|
||||||
|
npm1300_deinit();
|
||||||
|
|
||||||
|
drv->initialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void powerctl_get_status(powerctl_status_t* status) {
|
||||||
|
powerctl_driver_t* drv = &g_powerctl_driver;
|
||||||
|
|
||||||
|
memset(status, 0, sizeof(powerctl_status_t));
|
||||||
|
|
||||||
|
if (!drv->initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // KERNEL_MODE
|
124
core/embed/sys/powerctl/stm32u5/powerctl_suspend.c
Normal file
124
core/embed/sys/powerctl/stm32u5/powerctl_suspend.c
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <trezor_bsp.h>
|
||||||
|
#include <trezor_rtl.h>
|
||||||
|
|
||||||
|
#include <io/display.h>
|
||||||
|
#include <io/usb.h>
|
||||||
|
#include <sys/irq.h>
|
||||||
|
#include <sys/wakeup_flags.h>
|
||||||
|
|
||||||
|
#ifdef USE_TOUCH
|
||||||
|
#include <io/touch.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_HAPTIC
|
||||||
|
#include <io/haptic.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef KERNEL_MODE
|
||||||
|
|
||||||
|
static void background_tasks_suspend(void) {
|
||||||
|
// stwlc38
|
||||||
|
// npm1300
|
||||||
|
// nrf52
|
||||||
|
// ble
|
||||||
|
// powerctl
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool background_tasks_suspended(void) { return true; }
|
||||||
|
|
||||||
|
static void background_tasks_resume(void) {}
|
||||||
|
|
||||||
|
void powerctl_suspend(void) {
|
||||||
|
// Clear all wakeup flags. From this point, any wakeup event that
|
||||||
|
// sets a wakeup flag causes this function to return.
|
||||||
|
wakeup_flags_reset();
|
||||||
|
|
||||||
|
// Deinitialize all drivers that are not required in low-power mode
|
||||||
|
// (e.g., USB, display, touch, haptic, etc.).
|
||||||
|
usb_stop();
|
||||||
|
#ifdef USE_HAPTIC
|
||||||
|
haptic_deinit();
|
||||||
|
#endif
|
||||||
|
#ifdef USE_TOUCH
|
||||||
|
touch_deinit();
|
||||||
|
#endif
|
||||||
|
int backlight_level = display_get_backlight();
|
||||||
|
display_deinit(DISPLAY_RESET_CONTENT);
|
||||||
|
|
||||||
|
// In the following loop, the system will attempt to enter low-power mode.
|
||||||
|
// Low-power mode may be exited for various reasons, but the loop will
|
||||||
|
// terminate only if a wakeup flag is set, indicating that user interaction
|
||||||
|
// is required or the user needs to be notified.
|
||||||
|
|
||||||
|
while (wakeup_flags_get() == 0) {
|
||||||
|
// Notify state machines running in the interrupt context about the
|
||||||
|
// impending low-power mode. They should complete any pending operations
|
||||||
|
// and avoid starting new ones.
|
||||||
|
background_tasks_suspend();
|
||||||
|
|
||||||
|
// Wait until all state machines are idle and the system is ready to enter
|
||||||
|
// low-power mode. This loop also exits if any wakeup flag is set
|
||||||
|
// (e.g., due to a button press).
|
||||||
|
do {
|
||||||
|
__WFI();
|
||||||
|
|
||||||
|
// TODO: Implement a 5-second timeout to trigger a fatal error.
|
||||||
|
|
||||||
|
} while (!background_tasks_suspended() && (wakeup_flags_get() == 0));
|
||||||
|
|
||||||
|
if (wakeup_flags_get() == 0) {
|
||||||
|
// Disable interrupts by setting PRIMASK to 1.
|
||||||
|
//
|
||||||
|
// The system can wake up, but interrupts will not be processed until
|
||||||
|
// PRIMASK is cleared again. This is necessary to restore the system clock
|
||||||
|
// immediately after exiting STOP2 mode.
|
||||||
|
irq_key_t irq_key = irq_lock();
|
||||||
|
|
||||||
|
// Enter STOP2 mode
|
||||||
|
HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
|
||||||
|
|
||||||
|
// Recover system clock
|
||||||
|
SystemInit();
|
||||||
|
|
||||||
|
irq_unlock(irq_key);
|
||||||
|
|
||||||
|
// At this point, all pending interrupts are processed.
|
||||||
|
// Some of them may set wakeup flags.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resume state machines running in the interrupt context
|
||||||
|
background_tasks_resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reinitialize all drivers that were stopped earlier
|
||||||
|
display_init(DISPLAY_RESET_CONTENT);
|
||||||
|
display_set_backlight(backlight_level);
|
||||||
|
#ifdef USE_TOUCH
|
||||||
|
touch_init();
|
||||||
|
#endif
|
||||||
|
#ifdef USE_HAPTIC
|
||||||
|
haptic_init();
|
||||||
|
#endif
|
||||||
|
usb_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // KERNEL_MODE
|
46
core/embed/sys/powerctl/wakeup_flags.c
Normal file
46
core/embed/sys/powerctl/wakeup_flags.c
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/irq.h>
|
||||||
|
#include <sys/wakeup_flags.h>
|
||||||
|
|
||||||
|
#ifdef KERNEL_MODE
|
||||||
|
|
||||||
|
static uint16_t g_wakeup_flags = 0;
|
||||||
|
|
||||||
|
void wakeup_flags_set(uint16_t flags) {
|
||||||
|
irq_key_t irq_key = irq_lock();
|
||||||
|
g_wakeup_flags |= flags;
|
||||||
|
irq_unlock(irq_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wakeup_flags_reset(void) {
|
||||||
|
irq_key_t irq_key = irq_lock();
|
||||||
|
g_wakeup_flags = 0;
|
||||||
|
irq_unlock(irq_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t wakeup_flags_get(void) {
|
||||||
|
irq_key_t irq_key = irq_lock();
|
||||||
|
uint16_t flags = g_wakeup_flags;
|
||||||
|
irq_unlock(irq_key);
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // KERNEL_MODE
|
@ -149,8 +149,13 @@ def configure(
|
|||||||
|
|
||||||
sources += [
|
sources += [
|
||||||
"embed/sys/powerctl/npm1300/npm1300.c",
|
"embed/sys/powerctl/npm1300/npm1300.c",
|
||||||
"embed/sys/powerctl/stwlc38/stwlc38.c"
|
"embed/sys/powerctl/stwlc38/stwlc38.c",
|
||||||
|
"embed/sys/powerctl/stm32u5/powerctl.c",
|
||||||
|
"embed/sys/powerctl/stm32u5/powerctl_suspend.c",
|
||||||
|
"embed/sys/powerctl/wakeup_flags.c",
|
||||||
]
|
]
|
||||||
|
paths += ["embed/sys/powerctl/inc"]
|
||||||
|
defines += [("USE_POWERCTL", "1")]
|
||||||
|
|
||||||
env.get("ENV")["LINKER_SCRIPT"] = linker_script
|
env.get("ENV")["LINKER_SCRIPT"] = linker_script
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user