mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-22 14:28:07 +00:00
feat(core/embed): introduce systick and systimer drivers
[no changelog]
This commit is contained in:
parent
58d9f6115e
commit
1443f86983
@ -154,6 +154,8 @@ SOURCE_TREZORHAL = [
|
||||
'embed/trezorhal/unix/random_delays.c',
|
||||
'embed/trezorhal/unix/rng.c',
|
||||
'embed/trezorhal/unix/secret.c',
|
||||
'embed/trezorhal/unix/systick.c',
|
||||
'embed/trezorhal/unix/systimer.c',
|
||||
'embed/trezorhal/unix/usb.c',
|
||||
]
|
||||
|
||||
|
@ -424,6 +424,8 @@ SOURCE_UNIX = [
|
||||
'embed/trezorhal/unix/flash.c',
|
||||
'embed/trezorhal/unix/random_delays.c',
|
||||
'embed/trezorhal/unix/rng.c',
|
||||
'embed/trezorhal/unix/systick.c',
|
||||
'embed/trezorhal/unix/systimer.c',
|
||||
'embed/trezorhal/unix/time_estimate.c',
|
||||
'embed/trezorhal/unix/usb.c',
|
||||
'embed/unix/main_main.c',
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "model.h"
|
||||
#include "mpu.h"
|
||||
#include "rng.h"
|
||||
#include "systimer.h"
|
||||
#include "terminal.h"
|
||||
|
||||
#ifdef USE_SD_CARD
|
||||
@ -232,6 +233,9 @@ static secbool copy_sdcard(void) {
|
||||
#endif
|
||||
|
||||
int main(void) {
|
||||
systick_init();
|
||||
systimer_init();
|
||||
|
||||
reset_flags_reset();
|
||||
|
||||
// need the systick timer running before many HAL operations.
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "random_delays.h"
|
||||
#include "secbool.h"
|
||||
#include "secret.h"
|
||||
#include "systimer.h"
|
||||
|
||||
#ifdef USE_DMA2D
|
||||
#ifdef NEW_RENDERING
|
||||
@ -359,7 +360,10 @@ int bootloader_main(void) {
|
||||
#endif
|
||||
secbool stay_in_bootloader = secfalse;
|
||||
|
||||
random_delays_init();
|
||||
systick_init();
|
||||
systimer_init();
|
||||
|
||||
rdi_init();
|
||||
|
||||
#if defined TREZOR_MODEL_T
|
||||
set_core_clock(CLOCK_180_MHZ);
|
||||
|
@ -176,7 +176,10 @@ static secbool check_vendor_header_lock(const vendor_header *const vhdr) {
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
random_delays_init();
|
||||
systick_init();
|
||||
systimer_init();
|
||||
|
||||
rdi_init();
|
||||
#ifdef USE_TOUCH
|
||||
touch_init();
|
||||
#endif
|
||||
|
@ -48,27 +48,10 @@
|
||||
#include "py/runtime.h"
|
||||
#include "py/mphal.h"
|
||||
#include "irq.h"
|
||||
#include "systick.h"
|
||||
|
||||
extern __IO uint32_t uwTick;
|
||||
|
||||
// We provide our own version of HAL_Delay that calls __WFI while waiting,
|
||||
// and works when interrupts are disabled. This function is intended to be
|
||||
// used only by the ST HAL functions.
|
||||
void HAL_Delay(uint32_t Delay) {
|
||||
if (IS_IRQ_ENABLED(query_irq())) {
|
||||
// IRQs enabled, so can use systick counter to do the delay
|
||||
uint32_t start = uwTick;
|
||||
// Wraparound of tick is taken care of by 2's complement arithmetic.
|
||||
while (uwTick - start < Delay) {
|
||||
// Enter sleep mode, waiting for (at least) the SysTick interrupt.
|
||||
__WFI();
|
||||
}
|
||||
} else {
|
||||
// IRQs disabled, use mp_hal_delay_ms routine.
|
||||
mp_hal_delay_ms(Delay);
|
||||
}
|
||||
}
|
||||
|
||||
// Core delay function that does an efficient sleep and may switch thread context.
|
||||
// If IRQs are enabled then we must have the GIL.
|
||||
void mp_hal_delay_ms(mp_uint_t Delay) {
|
||||
@ -110,9 +93,9 @@ void mp_hal_delay_us(mp_uint_t usec) {
|
||||
}
|
||||
|
||||
mp_uint_t mp_hal_ticks_ms(void) {
|
||||
return uwTick;
|
||||
return systick_ms();
|
||||
}
|
||||
|
||||
mp_uint_t mp_hal_ticks_us(void) {
|
||||
return uwTick * 1000;
|
||||
return systick_ms() * 1000;
|
||||
}
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "random_delays.h"
|
||||
#include "rust_ui.h"
|
||||
#include "secure_aes.h"
|
||||
#include "systimer.h"
|
||||
|
||||
#include TREZOR_BOARD
|
||||
|
||||
@ -132,8 +133,10 @@ static void optiga_log_hex(const char *prefix, const uint8_t *data,
|
||||
|
||||
int main(void) {
|
||||
svc_init();
|
||||
systick_init();
|
||||
systimer_init();
|
||||
|
||||
random_delays_init();
|
||||
rdi_init();
|
||||
|
||||
#ifdef RDI
|
||||
rdi_start();
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "sdcard.h"
|
||||
#include "secbool.h"
|
||||
#include "supervise.h"
|
||||
#include "systimer.h"
|
||||
#include "touch.h"
|
||||
#include "usb.h"
|
||||
#include "version.h"
|
||||
@ -777,8 +778,11 @@ void cpuid_read(void) {
|
||||
|
||||
int main(void) {
|
||||
svc_init();
|
||||
systick_init();
|
||||
systimer_init();
|
||||
rdi_init();
|
||||
display_init(DISPLAY_RETAIN_CONTENT);
|
||||
random_delays_init();
|
||||
|
||||
#ifdef STM32U5
|
||||
secure_aes_init();
|
||||
#endif
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "sbu.h"
|
||||
#include "sdcard.h"
|
||||
#include "secbool.h"
|
||||
#include "systimer.h"
|
||||
#include "terminal.h"
|
||||
#include "touch.h"
|
||||
|
||||
@ -68,6 +69,9 @@ static void flash_from_sdcard(const flash_area_t* area, uint32_t source,
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
systick_init();
|
||||
systimer_init();
|
||||
|
||||
sdcard_init();
|
||||
touch_init();
|
||||
|
||||
|
@ -399,9 +399,9 @@ fn generate_trezorhal_bindings() {
|
||||
.allowlist_function("random_uniform")
|
||||
// rgb led
|
||||
.allowlist_function("rgb_led_set_color")
|
||||
// time
|
||||
.allowlist_function("hal_delay")
|
||||
.allowlist_function("hal_ticks_ms")
|
||||
// systick
|
||||
.allowlist_function("systick_delay_ms")
|
||||
.allowlist_function("systick_ms")
|
||||
// toif
|
||||
.allowlist_type("toif_format_t")
|
||||
// dma2d
|
||||
|
@ -3,11 +3,11 @@ use crate::time::Duration;
|
||||
use super::ffi;
|
||||
|
||||
pub fn ticks_ms() -> u32 {
|
||||
unsafe { ffi::hal_ticks_ms() as _ }
|
||||
unsafe { ffi::systick_ms() as _ }
|
||||
}
|
||||
|
||||
pub fn sleep(delay: Duration) {
|
||||
unsafe {
|
||||
ffi::hal_delay(delay.to_millis() as _);
|
||||
ffi::systick_delay_ms(delay.to_millis() as _);
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include "error_handling.h"
|
||||
#include "platform.h"
|
||||
#include "systick.h"
|
||||
|
||||
#ifndef MIN_8bits
|
||||
#define MIN_8bits(a, b) \
|
||||
@ -54,10 +55,6 @@
|
||||
|
||||
void __attribute__((noreturn)) trezor_shutdown(void);
|
||||
|
||||
void hal_delay(uint32_t ms);
|
||||
uint32_t hal_ticks_ms();
|
||||
void hal_delay_us(uint16_t delay_us);
|
||||
|
||||
// Invalidates firmware on the device
|
||||
// Note: only works when write access to firmware area is enabled by MPU
|
||||
void invalidate_firmware(void);
|
||||
|
@ -22,12 +22,11 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void random_delays_init(void);
|
||||
void rdi_init(void);
|
||||
|
||||
void rdi_start(void);
|
||||
void rdi_stop(void);
|
||||
void rdi_refresh_session_delay(void);
|
||||
void rdi_handler(uint32_t uw_tick);
|
||||
|
||||
void wait_random(void);
|
||||
#endif
|
||||
|
@ -36,8 +36,6 @@
|
||||
#include "backlight_pwm.h"
|
||||
#endif
|
||||
|
||||
uint32_t systick_val_copy = 0;
|
||||
|
||||
// from util.s
|
||||
extern void shutdown_privileged(void);
|
||||
|
||||
@ -54,20 +52,6 @@ void __attribute__((noreturn)) trezor_shutdown(void) {
|
||||
;
|
||||
}
|
||||
|
||||
void hal_delay(uint32_t ms) { HAL_Delay(ms); }
|
||||
uint32_t hal_ticks_ms() { return HAL_GetTick(); }
|
||||
void hal_delay_us(uint16_t delay_us) {
|
||||
uint32_t val = svc_get_systick_val();
|
||||
uint32_t t = hal_ticks_ms() * 1000 +
|
||||
(((SystemCoreClock / 1000) - val) / (SystemCoreClock / 1000000));
|
||||
uint32_t t2 = t;
|
||||
do {
|
||||
val = svc_get_systick_val();
|
||||
t2 = hal_ticks_ms() * 1000 +
|
||||
(((SystemCoreClock / 1000) - val) / (SystemCoreClock / 1000000));
|
||||
} while ((t2 - t) < delay_us);
|
||||
}
|
||||
|
||||
// reference RM0090 section 35.12.1 Figure 413
|
||||
#define USB_OTG_HS_DATA_FIFO_RAM (USB_OTG_HS_PERIPH_BASE + 0x20000U)
|
||||
#define USB_OTG_HS_DATA_FIFO_SIZE (4096U)
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "platform.h"
|
||||
#include "rng.h"
|
||||
#include "systick.h"
|
||||
#include TREZOR_BOARD
|
||||
|
||||
const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0,
|
||||
@ -193,7 +194,7 @@ void set_core_clock(clock_settings_t settings) {
|
||||
/* Enable PLL as main clock */
|
||||
RCC->CFGR = (RCC->CFGR & ~(RCC_CFGR_SW)) | RCC_CFGR_SW_PLL;
|
||||
|
||||
HAL_InitTick(TICK_INT_PRIORITY);
|
||||
systick_update_freq();
|
||||
|
||||
// turn off the HSI as it is now unused (it will be turned on again
|
||||
// automatically if a clock security failure occurs)
|
||||
|
@ -44,6 +44,7 @@ https://link.springer.com/content/pdf/10.1007%2F978-3-540-72354-7_3.pdf
|
||||
#include "common.h"
|
||||
#include "memzero.h"
|
||||
#include "rand.h"
|
||||
#include "systimer.h"
|
||||
|
||||
// from util.s
|
||||
extern void shutdown_privileged(void);
|
||||
@ -151,7 +152,16 @@ static void wait(uint32_t delay) {
|
||||
: "r0", "r1");
|
||||
}
|
||||
|
||||
void random_delays_init() { drbg_init(); }
|
||||
// forward declaration
|
||||
static void rdi_handler(void *context);
|
||||
|
||||
void rdi_init() {
|
||||
drbg_init();
|
||||
|
||||
systimer_t *timer = systimer_create(rdi_handler, NULL);
|
||||
ensure(sectrue * (timer != NULL), "rdi_init failed");
|
||||
systimer_set_periodic(timer, 1);
|
||||
}
|
||||
|
||||
void rdi_start(void) {
|
||||
ensure(drbg_initialized, NULL);
|
||||
@ -174,7 +184,7 @@ void rdi_refresh_session_delay(void) {
|
||||
refresh_session_delay = true;
|
||||
}
|
||||
|
||||
void rdi_handler(uint32_t uw_tick) {
|
||||
static void rdi_handler(void *context) {
|
||||
if (rdi_disabled == secfalse) { // if rdi enabled
|
||||
if (refresh_session_delay) {
|
||||
session_delay = drbg_random8();
|
||||
|
@ -102,9 +102,6 @@ void SVC_C_Handler(uint32_t *stack) {
|
||||
// raising privileges.
|
||||
stack[6] = (uintptr_t)_reboot_to_bootloader;
|
||||
return;
|
||||
case SVC_GET_SYSTICK_VAL:
|
||||
systick_val_copy = SysTick->VAL;
|
||||
break;
|
||||
case SVC_REBOOT:
|
||||
NVIC_SystemReset();
|
||||
break;
|
||||
|
@ -5,17 +5,13 @@
|
||||
#define SVC_SET_PRIORITY 2
|
||||
#define SVC_SHUTDOWN 4
|
||||
#define SVC_REBOOT_TO_BOOTLOADER 5
|
||||
#define SVC_GET_SYSTICK_VAL 6
|
||||
#define SVC_REBOOT 7
|
||||
#define SVC_REBOOT 6
|
||||
|
||||
#include <string.h>
|
||||
#include "boot_args.h"
|
||||
#include "common.h"
|
||||
#include "image.h"
|
||||
|
||||
// from common.c
|
||||
extern uint32_t systick_val_copy;
|
||||
|
||||
// from util.s
|
||||
extern void shutdown_privileged(void);
|
||||
|
||||
@ -76,13 +72,3 @@ static inline void svc_shutdown(void) {
|
||||
void svc_reboot_to_bootloader(void);
|
||||
|
||||
void svc_reboot(void);
|
||||
|
||||
static inline uint32_t svc_get_systick_val(void) {
|
||||
if (is_mode_unprivileged() && !is_mode_handler()) {
|
||||
__asm__ __volatile__("svc %0" ::"i"(SVC_GET_SYSTICK_VAL) : "memory");
|
||||
return systick_val_copy;
|
||||
} else {
|
||||
systick_val_copy = SysTick->VAL;
|
||||
return systick_val_copy;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,3 @@
|
||||
// clang-format off
|
||||
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
@ -19,52 +17,194 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013, 2014 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "irq.h"
|
||||
#include "systick.h"
|
||||
|
||||
#ifdef RDI
|
||||
#include "random_delays.h"
|
||||
#endif
|
||||
|
||||
#include "platform.h"
|
||||
#include "systemview.h"
|
||||
|
||||
extern __IO uint32_t uwTick;
|
||||
#include "systick.h"
|
||||
#include "systick_internal.h"
|
||||
#include "systimer.h"
|
||||
|
||||
// SysTick driver state
|
||||
typedef struct {
|
||||
// Set if the driver is initialized
|
||||
bool initialized;
|
||||
// Number of hw cycles per millisecond (tick period)
|
||||
uint32_t cycles_per_ms;
|
||||
// Number of hw cycles per microsecond
|
||||
uint32_t cycles_per_us;
|
||||
// Current tick value in hardware cycles
|
||||
volatile uint64_t cycles;
|
||||
// Number of ticks (ms) since the system start
|
||||
volatile uint32_t ticks;
|
||||
} systick_driver_t;
|
||||
|
||||
static systick_driver_t g_systick_driver = {
|
||||
.initialized = false,
|
||||
};
|
||||
|
||||
void systick_init(void) {
|
||||
systick_driver_t* drv = &g_systick_driver;
|
||||
|
||||
if (drv->initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
drv->cycles = 0;
|
||||
drv->ticks = 0;
|
||||
|
||||
// Set 1ms tick period
|
||||
drv->cycles_per_ms = HAL_RCC_GetSysClockFreq() / 1000;
|
||||
drv->cycles_per_us = drv->cycles_per_ms / 1000;
|
||||
|
||||
// Initialize and enable SysTick timer
|
||||
SysTick_Config(drv->cycles_per_ms);
|
||||
|
||||
// We need to ensure that SysTick has the expected priority.
|
||||
// The SysTick priority is configured in the boardloader,
|
||||
// and some early versions didn't set this properly.
|
||||
NVIC_SetPriority(SysTick_IRQn, IRQ_PRI_NORMAL);
|
||||
|
||||
drv->initialized = true;
|
||||
}
|
||||
|
||||
void systick_deinit(void) {
|
||||
systick_driver_t* drv = &g_systick_driver;
|
||||
|
||||
if (!drv->initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
NVIC_DisableIRQ(SysTick_IRQn);
|
||||
SysTick->CTRL = 0;
|
||||
NVIC_ClearPendingIRQ(SysTick_IRQn);
|
||||
|
||||
drv->initialized = false;
|
||||
}
|
||||
|
||||
void systick_update_freq(void) {
|
||||
systick_driver_t* drv = &g_systick_driver;
|
||||
|
||||
if (!drv->initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t clock_freq = HAL_RCC_GetSysClockFreq();
|
||||
drv->cycles_per_ms = clock_freq / 1000;
|
||||
drv->cycles_per_us = drv->cycles_per_ms / 1000;
|
||||
SysTick_Config(drv->cycles_per_ms);
|
||||
|
||||
// We need to ensure that SysTick has the expected priority.
|
||||
// The SysTick priority is configured in the boardloader,
|
||||
// and some early versions didn't set this properly.
|
||||
NVIC_SetPriority(SysTick_IRQn, IRQ_PRI_NORMAL);
|
||||
}
|
||||
|
||||
uint64_t systick_cycles(void) {
|
||||
systick_driver_t* drv = &g_systick_driver;
|
||||
|
||||
uint32_t irq_state = disable_irq();
|
||||
|
||||
// Current value of the SysTick counter
|
||||
uint32_t val = SysTick->VAL;
|
||||
|
||||
// Check if the SysTick has already counted down to 0 or wrapped around
|
||||
// Reading CTRL register automatically clears COUNTFLAG
|
||||
if ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) != 0) {
|
||||
// Re-read the current value of the SysTick counter
|
||||
val = SysTick->VAL;
|
||||
// Update the hardware cycles counter
|
||||
// Since we have cleared COUNTFLAG, SysTick_Handler will not increment
|
||||
drv->cycles += drv->cycles_per_ms;
|
||||
// Increment regular ticks counter
|
||||
drv->ticks++;
|
||||
}
|
||||
|
||||
uint64_t cycles = drv->cycles + ((val > 0) ? (drv->cycles_per_ms - val) : 0);
|
||||
|
||||
enable_irq(irq_state);
|
||||
|
||||
return cycles;
|
||||
}
|
||||
|
||||
uint64_t systick_us_to_cycles(uint64_t us) {
|
||||
systick_driver_t* drv = &g_systick_driver;
|
||||
|
||||
return us * drv->cycles_per_us;
|
||||
}
|
||||
|
||||
uint32_t systick_ms(void) {
|
||||
systick_driver_t* drv = &g_systick_driver;
|
||||
|
||||
return drv->ticks;
|
||||
}
|
||||
|
||||
uint64_t systick_us(void) {
|
||||
systick_driver_t* drv = &g_systick_driver;
|
||||
|
||||
if (drv->cycles_per_us == 0) {
|
||||
// The driver was not initialized yet - this could happen
|
||||
// only if the function is called from the early initialization
|
||||
// stage, before the `systick_init()` was called. In this case,
|
||||
// we can't provide the correct value, so we return 0.
|
||||
return 0;
|
||||
}
|
||||
|
||||
return systick_cycles() / drv->cycles_per_us;
|
||||
}
|
||||
|
||||
void SysTick_Handler(void) {
|
||||
SEGGER_SYSVIEW_RecordEnterISR();
|
||||
// this is a millisecond tick counter that wraps after approximately
|
||||
// 49.71 days = (0xffffffff / (24 * 60 * 60 * 1000))
|
||||
uint32_t uw_tick = uwTick + 1;
|
||||
uwTick = uw_tick;
|
||||
#ifdef RDI
|
||||
rdi_handler(uw_tick);
|
||||
#endif
|
||||
|
||||
systick_driver_t* drv = &g_systick_driver;
|
||||
|
||||
if (drv->initialized) {
|
||||
// Increment `cycles` counter if COUNTFLAG is set.
|
||||
// If COUNTFLAG is not set, `cycles` were already incremented
|
||||
// in `systick_cycles()` that also cleared the COUNTFLAG.
|
||||
if ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) != 0) {
|
||||
// Clear COUNTFLAG by reading VAL
|
||||
(void)SysTick->VAL;
|
||||
// Increment cycles counter by SysTick period
|
||||
drv->cycles += drv->cycles_per_ms;
|
||||
// Increment regular ticks counter
|
||||
drv->ticks++;
|
||||
}
|
||||
|
||||
// Invoke callbacks of expired timers
|
||||
systimer_dispatch_expired_timers(drv->cycles);
|
||||
}
|
||||
|
||||
SEGGER_SYSVIEW_RecordExitISR();
|
||||
}
|
||||
|
||||
void systick_delay_us(uint64_t us) {
|
||||
uint64_t delay_cycles = systick_us_to_cycles(us);
|
||||
int64_t cycles_per_ms = systick_us_to_cycles(1000);
|
||||
|
||||
uint64_t end = systick_cycles() + delay_cycles;
|
||||
bool irq_enabled = IS_IRQ_ENABLED(query_irq());
|
||||
int64_t diff;
|
||||
|
||||
while ((diff = end - systick_cycles()) > 0) {
|
||||
if (irq_enabled && (diff > cycles_per_ms)) {
|
||||
// Enter sleep mode and wait for (at least)
|
||||
// the SysTick interrupt.
|
||||
__WFI();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void systick_delay_ms(uint32_t ms) { systick_delay_us((uint64_t)ms * 1000); }
|
||||
|
||||
// We provide our own version of HAL_Delay that calls __WFI while waiting,
|
||||
// and works when interrupts are disabled. This function is intended to be
|
||||
// used only by the ST HAL functions.
|
||||
void HAL_Delay(uint32_t ms) { systick_delay_ms(ms); }
|
||||
|
||||
// We provide our own version of HAL_GetTick that replaces the default
|
||||
// ST HAL function reading uwTick global variable.
|
||||
uint32_t HAL_GetTick(void) { return systick_ms(); }
|
||||
|
@ -1,37 +0,0 @@
|
||||
// clang-format off
|
||||
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013, 2014 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef MICROPY_INCLUDED_STM32_SYSTICK_H
|
||||
#define MICROPY_INCLUDED_STM32_SYSTICK_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
// Works for x between 0 and 16 inclusive
|
||||
#define POW2_CEIL(x) ((((x) - 1) | ((x) - 1) >> 1 | ((x) - 1) >> 2 | ((x) - 1) >> 3) + 1)
|
||||
|
||||
#endif // MICROPY_INCLUDED_STM32_SYSTICK_H
|
12
core/embed/trezorhal/stm32f4/systick_internal.h
Normal file
12
core/embed/trezorhal/stm32f4/systick_internal.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef TREZORHAL_SYSTICK_INTERNAL_H
|
||||
#define TREZORHAL_SYSTICK_INTERNAL_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "systick.h"
|
||||
|
||||
// Internal function called from interrupt context.
|
||||
// Handles expired timers and invoked their callbacks.
|
||||
void systimer_dispatch_expired_timers(uint64_t cycles);
|
||||
|
||||
#endif // TREZORHAL_SYSTICK_INTERNAL_H
|
237
core/embed/trezorhal/stm32f4/systimer.c
Normal file
237
core/embed/trezorhal/stm32f4/systimer.c
Normal file
@ -0,0 +1,237 @@
|
||||
/*
|
||||
* 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 <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "irq.h"
|
||||
#include "platform.h"
|
||||
#include "systick_internal.h"
|
||||
#include "systimer.h"
|
||||
|
||||
// Maximum number of registered user timer
|
||||
//
|
||||
// Consider different implementation (i.e. priority queue
|
||||
// using binary heap if MAX_SYSTIMERS exceeds 10 or more)
|
||||
#define MAX_SYSTIMERS 4
|
||||
|
||||
// User timer instance
|
||||
struct systimer {
|
||||
// User callback function
|
||||
// Non-NULL if the timer entry is valid
|
||||
volatile systimer_callback_t callback;
|
||||
// User callback context
|
||||
void* context;
|
||||
// Set if the timer is suspended
|
||||
volatile bool suspended;
|
||||
// Set if the timer is scheduled
|
||||
volatile bool scheduled;
|
||||
// Expiration time (valid if scheduled is set)
|
||||
volatile uint64_t expiration;
|
||||
// Period (= 0 for non-periodic timers)
|
||||
volatile uint64_t period;
|
||||
};
|
||||
|
||||
// systimer driver state
|
||||
typedef struct {
|
||||
// Set if the driver is initialized
|
||||
bool initialized;
|
||||
// Registered timers
|
||||
// (unused slots have callback field set to NULL)
|
||||
systimer_t timers[MAX_SYSTIMERS];
|
||||
} systimer_driver_t;
|
||||
|
||||
static systimer_driver_t g_systimer_driver = {
|
||||
.initialized = false,
|
||||
};
|
||||
|
||||
void systimer_init(void) {
|
||||
systimer_driver_t* drv = &g_systimer_driver;
|
||||
|
||||
if (drv->initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(drv, 0, sizeof(systimer_driver_t));
|
||||
drv->initialized = true;
|
||||
}
|
||||
|
||||
void systimer_deinit(void) {
|
||||
systimer_driver_t* drv = &g_systimer_driver;
|
||||
|
||||
drv->initialized = false;
|
||||
}
|
||||
|
||||
static inline bool timer_valid(const systimer_driver_t* drv,
|
||||
const systimer_t* timer) {
|
||||
return drv->initialized && (timer >= &drv->timers[0]) &&
|
||||
(timer < &drv->timers[MAX_SYSTIMERS]);
|
||||
}
|
||||
|
||||
systimer_t* systimer_create(systimer_callback_t callback, void* context) {
|
||||
systimer_driver_t* drv = &g_systimer_driver;
|
||||
|
||||
if (!drv->initialized) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (callback == NULL) {
|
||||
// Since the callback is used to determine if the
|
||||
// timer is valid, it must be non-NULL.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t irq_state = disable_irq();
|
||||
|
||||
// Find a free timer entry
|
||||
for (int i = 0; i < MAX_SYSTIMERS; i++) {
|
||||
systimer_t* timer = &drv->timers[i];
|
||||
|
||||
if (timer->callback == NULL) {
|
||||
timer->scheduled = false;
|
||||
timer->suspended = false;
|
||||
timer->context = context;
|
||||
timer->callback = callback;
|
||||
|
||||
enable_irq(irq_state);
|
||||
return timer;
|
||||
}
|
||||
}
|
||||
|
||||
// No free timer entry found
|
||||
enable_irq(irq_state);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void systimer_delete(systimer_t* timer) {
|
||||
systimer_driver_t* drv = &g_systimer_driver;
|
||||
if (!timer_valid(drv, timer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
timer->callback = NULL;
|
||||
}
|
||||
|
||||
void systimer_set(systimer_t* timer, uint32_t delay_ms) {
|
||||
systimer_driver_t* drv = &g_systimer_driver;
|
||||
|
||||
if (!timer_valid(drv, timer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t delay = systick_us_to_cycles((uint64_t)delay_ms * 1000);
|
||||
uint64_t expiration = systick_cycles() + delay;
|
||||
|
||||
uint32_t irq_state = disable_irq();
|
||||
timer->expiration = expiration;
|
||||
timer->period = 0;
|
||||
timer->scheduled = true;
|
||||
enable_irq(irq_state);
|
||||
}
|
||||
|
||||
void systimer_set_periodic(systimer_t* timer, uint32_t period_ms) {
|
||||
systimer_driver_t* drv = &g_systimer_driver;
|
||||
|
||||
if (!timer_valid(drv, timer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t period = systick_us_to_cycles((uint64_t)period_ms * 1000);
|
||||
uint64_t expiration = systick_cycles() + period;
|
||||
|
||||
uint32_t irq_state = disable_irq();
|
||||
timer->expiration = expiration;
|
||||
timer->period = period;
|
||||
timer->scheduled = true;
|
||||
enable_irq(irq_state);
|
||||
}
|
||||
|
||||
bool systimer_unset(systimer_t* timer) {
|
||||
systimer_driver_t* drv = &g_systimer_driver;
|
||||
|
||||
if (!timer_valid(drv, timer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t irq_state = disable_irq();
|
||||
bool was_scheduled = timer->scheduled;
|
||||
timer->scheduled = false;
|
||||
enable_irq(irq_state);
|
||||
return was_scheduled;
|
||||
}
|
||||
|
||||
systimer_key_t systimer_suspend(systimer_t* timer) {
|
||||
systimer_driver_t* drv = &g_systimer_driver;
|
||||
|
||||
if (!timer_valid(drv, timer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t irq_state = disable_irq();
|
||||
bool was_suspended = timer->suspended;
|
||||
timer->suspended = true;
|
||||
enable_irq(irq_state);
|
||||
return was_suspended;
|
||||
}
|
||||
|
||||
void systimer_resume(systimer_t* timer, systimer_key_t key) {
|
||||
systimer_driver_t* drv = &g_systimer_driver;
|
||||
|
||||
if (!timer_valid(drv, timer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
timer->suspended = key;
|
||||
}
|
||||
|
||||
// Called from interrupt context
|
||||
void systimer_dispatch_expired_timers(uint64_t cycles) {
|
||||
systimer_driver_t* drv = &g_systimer_driver;
|
||||
|
||||
if (!drv->initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Go through all timer slots and invoke callbacks of expired timers
|
||||
// This algorithm is not efficient for large number of timers
|
||||
// but it is good enough if MAX_SYSTIMERS ~ 10
|
||||
|
||||
for (int i = 0; i < MAX_SYSTIMERS; i++) {
|
||||
systimer_t* timer = &drv->timers[i];
|
||||
|
||||
if (timer->callback == NULL || timer->suspended || !timer->scheduled) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cycles < timer->expiration) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (timer->period > 0) {
|
||||
// Reschedule periodic timer
|
||||
timer->expiration = cycles + timer->period;
|
||||
} else {
|
||||
// Stop one-shot timer
|
||||
timer->scheduled = false;
|
||||
}
|
||||
|
||||
// Callback is invoked from interrupt context
|
||||
timer->callback(timer->context);
|
||||
}
|
||||
}
|
@ -32,8 +32,6 @@
|
||||
|
||||
#include "stm32u5xx_ll_utils.h"
|
||||
|
||||
uint32_t systick_val_copy = 0;
|
||||
|
||||
// from util.s
|
||||
extern void shutdown_privileged(void);
|
||||
|
||||
@ -55,20 +53,6 @@ void __attribute__((noreturn)) trezor_shutdown(void) {
|
||||
;
|
||||
}
|
||||
|
||||
void hal_delay(uint32_t ms) { HAL_Delay(ms); }
|
||||
uint32_t hal_ticks_ms() { return HAL_GetTick(); }
|
||||
void hal_delay_us(uint16_t delay_us) {
|
||||
uint32_t val = svc_get_systick_val();
|
||||
uint32_t t = hal_ticks_ms() * 1000 +
|
||||
(((SystemCoreClock / 1000) - val) / (SystemCoreClock / 1000000));
|
||||
uint32_t t2 = t;
|
||||
do {
|
||||
val = svc_get_systick_val();
|
||||
t2 = hal_ticks_ms() * 1000 +
|
||||
(((SystemCoreClock / 1000) - val) / (SystemCoreClock / 1000000));
|
||||
} while ((t2 - t) < delay_us);
|
||||
}
|
||||
|
||||
uint32_t __stack_chk_guard = 0;
|
||||
|
||||
void __attribute__((noreturn)) __stack_chk_fail(void) {
|
||||
|
@ -1 +0,0 @@
|
||||
../stm32f4/systick.h
|
1
core/embed/trezorhal/stm32u5/systick_internal.h
Symbolic link
1
core/embed/trezorhal/stm32u5/systick_internal.h
Symbolic link
@ -0,0 +1 @@
|
||||
../stm32f4/systick_internal.h
|
1
core/embed/trezorhal/stm32u5/systimer.c
Symbolic link
1
core/embed/trezorhal/stm32u5/systimer.c
Symbolic link
@ -0,0 +1 @@
|
||||
../stm32f4/systimer.c
|
96
core/embed/trezorhal/systick.h
Normal file
96
core/embed/trezorhal/systick.h
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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_SYSTICK_H
|
||||
#define TREZORHAL_SYSTICK_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Initializes systick subsystem
|
||||
//
|
||||
// Before calling this function, none of the other functions
|
||||
// from this module should be called.
|
||||
void systick_init(void);
|
||||
|
||||
// Deinitialize systick subsystem
|
||||
//
|
||||
// The function should be called before jumping to the
|
||||
// next bootloader stage or firmware.
|
||||
void systick_deinit(void);
|
||||
|
||||
// Updates systick subsystem with new system clock frequency
|
||||
//
|
||||
// The function should be called after the system clock frequency
|
||||
// has been changed.
|
||||
void systick_update_freq(void);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Tick functions
|
||||
|
||||
// Returns number of system clock cycles since the system start.
|
||||
//
|
||||
// Read monotonic counter with high resolution (Cortex-M SysTick clock)
|
||||
// (On 160MHz CPU, 1 cycles is 1 / 160MHz = 6.25ns)
|
||||
uint64_t systick_cycles(void);
|
||||
|
||||
// Returns number of microseconds since the system start.
|
||||
uint64_t systick_us(void);
|
||||
|
||||
// Returns number of ticks (milliseconds) since the system start.
|
||||
//
|
||||
// The returned value is a 32-bit unsigned integer that wraps
|
||||
// around every 49.7 days.
|
||||
uint32_t systick_ms(void);
|
||||
|
||||
// Converts microseconds to system clock cycles
|
||||
uint64_t systick_us_to_cycles(uint64_t us);
|
||||
|
||||
// Number of ticks (milliseconds)
|
||||
typedef uint32_t ticks_t;
|
||||
|
||||
//
|
||||
#define ticks() systick_ms()
|
||||
|
||||
// Helper function for building expiration time
|
||||
#define ticks_timeout(timeout) (systick_ms() + (timeout))
|
||||
|
||||
// Helper function for checking ticks expiration
|
||||
//
|
||||
// It copes with the wrap-around of the `ticks_t` type but
|
||||
// still assumes that the difference between the two ticks
|
||||
// is less than half of the `ticks_t` range.
|
||||
#define ticks_expired(ticks) ((int32_t)(systick_ms() - (ticks)) >= 0)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Delay functions
|
||||
|
||||
// Waits for at least `ms` milliseconds
|
||||
void systick_delay_ms(uint32_t ms);
|
||||
|
||||
// Waits for at least `us` microseconds
|
||||
void systick_delay_us(uint64_t us);
|
||||
|
||||
// legacy functions
|
||||
|
||||
static inline uint32_t hal_ticks_ms(void) { return systick_ms(); }
|
||||
static inline void hal_delay(uint32_t ms) { systick_delay_ms(ms); }
|
||||
static inline void hal_delay_us(uint64_t us) { systick_delay_us(us); }
|
||||
|
||||
#endif // TREZORHAL_SYSTICK_H
|
93
core/embed/trezorhal/systimer.h
Normal file
93
core/embed/trezorhal/systimer.h
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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_SYSTIMER_H
|
||||
#define TREZORHAL_SYSTIMER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Initializes systimer subsystem
|
||||
//
|
||||
// Before calling this function, none of the other functions
|
||||
// from this module should be called.
|
||||
void systimer_init(void);
|
||||
|
||||
// Deinitialize sytimer subsystem
|
||||
void systimer_deinit(void);
|
||||
|
||||
// Timer handle
|
||||
typedef struct systimer systimer_t;
|
||||
|
||||
// Timer callback routine invoked when timer expires
|
||||
//
|
||||
// The callback should be as short as possible and should not
|
||||
// block. It is invoked from the timer interrupt context.
|
||||
//
|
||||
// `context` is the pointer passed to `timer_create`
|
||||
typedef void (*systimer_callback_t)(void* context);
|
||||
|
||||
// Initializes the timer and returns its handle.
|
||||
//
|
||||
// There a limited number of timers and `NULL` is returned
|
||||
// if no timer is available.
|
||||
systimer_t* systimer_create(systimer_callback_t callback, void* context);
|
||||
|
||||
// Deletes the timer
|
||||
//
|
||||
// Timer is unset and its resources are released.
|
||||
void systimer_delete(systimer_t* timer);
|
||||
|
||||
// Sets the timer to expire in `delay_ms` milliseconds
|
||||
//
|
||||
// If the timer is already set, it will be rescheduled.
|
||||
void systimer_set(systimer_t* timer, uint32_t delay_ms);
|
||||
|
||||
// Sets the timer to expire periodically every `period_ms` milliseconds
|
||||
//
|
||||
// If the timer is already set, it will be rescheduled.
|
||||
void systimer_set_periodic(systimer_t* timer, uint32_t period_ms);
|
||||
|
||||
// Unsets the timer (cancels the expiration)
|
||||
//
|
||||
// Timer is not deleted and can be set again.
|
||||
//
|
||||
// Returns `true` if the timer was unset before its expiration
|
||||
// so the callback will not be invoked.
|
||||
bool systimer_unset(systimer_t* timer);
|
||||
|
||||
// Timer suspension state (opaque type).
|
||||
// Allows to recursively suspend/resume timer.
|
||||
typedef bool systimer_key_t;
|
||||
|
||||
// Suspends timer callback invocation
|
||||
//
|
||||
// The purpose of this function is to prevent the timer callback
|
||||
// from being invoked for synchronization purposes. The function
|
||||
// returns a lock that should be passed to `systimer_resume()` to
|
||||
// resume the timer callback invocation.
|
||||
systimer_key_t systimer_suspend(systimer_t* timer);
|
||||
|
||||
// Resumes timer callback invocation
|
||||
//
|
||||
// The timer callback invocation is resumed. The `key` should
|
||||
// be the same as returned by `timer_suspend()`.
|
||||
void systimer_resume(systimer_t* timer, systimer_key_t key);
|
||||
|
||||
#endif // TREZORHAL_SYSTIMER_H
|
@ -40,14 +40,6 @@ void __attribute__((noreturn)) trezor_shutdown(void) {
|
||||
exit(3);
|
||||
}
|
||||
|
||||
void hal_delay(uint32_t ms) { usleep(1000 * ms); }
|
||||
|
||||
uint32_t hal_ticks_ms() {
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||
}
|
||||
|
||||
static int SDLCALL emulator_event_filter(void *userdata, SDL_Event *event) {
|
||||
switch (event->type) {
|
||||
case SDL_QUIT:
|
||||
|
@ -21,4 +21,4 @@
|
||||
|
||||
void wait_random(void) {}
|
||||
|
||||
void random_delays_init(void) {}
|
||||
void rdi_init(void) {}
|
||||
|
@ -20,7 +20,7 @@
|
||||
#ifndef __TREZORHAL_RANDOM_DELAYS_H__
|
||||
#define __TREZORHAL_RANDOM_DELAYS_H__
|
||||
|
||||
void random_delays_init(void);
|
||||
void rdi_init(void);
|
||||
void wait_random(void);
|
||||
|
||||
#endif
|
||||
|
128
core/embed/trezorhal/unix/systick.c
Normal file
128
core/embed/trezorhal/unix/systick.c
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* 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 <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "systick.h"
|
||||
|
||||
// Systick driver state
|
||||
typedef struct {
|
||||
// Set if the driver is initialized
|
||||
bool initialized;
|
||||
// Instant time [us] of driver initialization
|
||||
uint64_t initial_time;
|
||||
// Instant time [us] of driver deinitialization
|
||||
uint64_t final_time;
|
||||
|
||||
} systick_driver_t;
|
||||
|
||||
static systick_driver_t g_systick_driver = {
|
||||
.initialized = false,
|
||||
};
|
||||
|
||||
// Returns number of microseconds since the os started
|
||||
static uint64_t get_monotonic_clock(void) {
|
||||
struct timespec tp;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &tp);
|
||||
return tp.tv_sec * 1000000UL + tp.tv_nsec / 1000;
|
||||
}
|
||||
|
||||
void systick_init(void) {
|
||||
systick_driver_t* drv = &g_systick_driver;
|
||||
|
||||
if (drv->initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(drv, 0, sizeof(systick_driver_t));
|
||||
drv->initial_time = get_monotonic_clock();
|
||||
drv->initialized = true;
|
||||
}
|
||||
|
||||
void systick_deinit(void) {
|
||||
systick_driver_t* drv = &g_systick_driver;
|
||||
|
||||
if (!drv->initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
// This will ensure that the time return by `systick_ms()` and
|
||||
// `systick_us()` will not be reset to 0 after the `systick_deinit()` call.
|
||||
drv->final_time = get_monotonic_clock();
|
||||
|
||||
drv->initialized = false;
|
||||
}
|
||||
|
||||
void systick_update_freq(void){};
|
||||
|
||||
uint32_t systick_ms() {
|
||||
systick_driver_t* drv = &g_systick_driver;
|
||||
|
||||
if (!drv->initialized) {
|
||||
systick_init(); // temporary workaround required by rust unit tests
|
||||
// return drv->final_time / 1000;
|
||||
}
|
||||
|
||||
return (get_monotonic_clock() - drv->initial_time) / 1000;
|
||||
}
|
||||
|
||||
uint64_t systick_us(void) {
|
||||
systick_driver_t* drv = &g_systick_driver;
|
||||
|
||||
if (!drv->initialized) {
|
||||
systick_init(); // temporary workaround required by rust unit tests
|
||||
// return drv->final_time;
|
||||
}
|
||||
|
||||
return get_monotonic_clock() - drv->initial_time;
|
||||
}
|
||||
|
||||
void systick_delay_us(uint64_t us) {
|
||||
systick_driver_t* drv = &g_systick_driver;
|
||||
|
||||
if (!drv->initialized) {
|
||||
systick_init(); // temporary workaround required by rust unit tests
|
||||
// return;
|
||||
}
|
||||
|
||||
struct timespec tp;
|
||||
tp.tv_sec = us / 1000000;
|
||||
tp.tv_nsec = (us % 1000000) * 1000;
|
||||
nanosleep(&tp, NULL);
|
||||
}
|
||||
|
||||
void systick_delay_ms(uint32_t ms) {
|
||||
systick_driver_t* drv = &g_systick_driver;
|
||||
|
||||
if (!drv->initialized) {
|
||||
systick_init(); // temporary workaround required by rust unit tests
|
||||
// return;
|
||||
}
|
||||
|
||||
struct timespec tp;
|
||||
tp.tv_sec = ms / 1000;
|
||||
tp.tv_nsec = (ms % 1000) * 1000000;
|
||||
nanosleep(&tp, NULL);
|
||||
}
|
52
core/embed/trezorhal/unix/systimer.c
Normal file
52
core/embed/trezorhal/unix/systimer.c
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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 <string.h>
|
||||
|
||||
#include "systimer.h"
|
||||
|
||||
// systimer driver state
|
||||
typedef struct {
|
||||
// Set if the driver is initialized
|
||||
bool initialized;
|
||||
} systimer_driver_t;
|
||||
|
||||
static systimer_driver_t g_systimer_driver = {
|
||||
.initialized = false,
|
||||
};
|
||||
|
||||
void systimer_init(void) {
|
||||
systimer_driver_t* drv = &g_systimer_driver;
|
||||
|
||||
if (drv->initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&drv, 0, sizeof(systimer_driver_t));
|
||||
drv->initialized = true;
|
||||
}
|
||||
|
||||
void systimer_deinit(void) {
|
||||
systimer_driver_t* drv = &g_systimer_driver;
|
||||
|
||||
drv->initialized = false;
|
||||
}
|
||||
|
||||
// Timer driver is not fully implemented for unix platform
|
||||
// since not neeeded for the emulator
|
@ -53,6 +53,7 @@
|
||||
#include "py/repl.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/stackctrl.h"
|
||||
#include "systimer.h"
|
||||
#include "touch.h"
|
||||
|
||||
#include "common.h"
|
||||
@ -486,6 +487,9 @@ MP_NOINLINE int main_(int argc, char **argv) {
|
||||
|
||||
pre_process_options(argc, argv);
|
||||
|
||||
systick_init();
|
||||
systimer_init();
|
||||
|
||||
display_init(DISPLAY_RESET_CONTENT);
|
||||
|
||||
#if USE_TOUCH
|
||||
|
@ -53,6 +53,7 @@ def stm32f4_common_files(env, defines, sources, paths):
|
||||
"embed/trezorhal/stm32f4/platform.c",
|
||||
"embed/trezorhal/stm32f4/secret.c",
|
||||
"embed/trezorhal/stm32f4/systick.c",
|
||||
"embed/trezorhal/stm32f4/systimer.c",
|
||||
"embed/trezorhal/stm32f4/supervise.c",
|
||||
"embed/trezorhal/stm32f4/time_estimate.c",
|
||||
"embed/trezorhal/stm32f4/random_delays.c",
|
||||
|
@ -64,6 +64,7 @@ def stm32u5_common_files(env, defines, sources, paths):
|
||||
"embed/trezorhal/stm32u5/secret.c",
|
||||
"embed/trezorhal/stm32u5/secure_aes.c",
|
||||
"embed/trezorhal/stm32u5/systick.c",
|
||||
"embed/trezorhal/stm32f4/systimer.c",
|
||||
"embed/trezorhal/stm32f4/supervise.c",
|
||||
"embed/trezorhal/stm32u5/random_delays.c",
|
||||
"embed/trezorhal/stm32u5/rng.c",
|
||||
|
Loading…
Reference in New Issue
Block a user