mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-19 05:58:09 +00:00
refactor(embed/core): replace enable/disable_irq by irq_lock/unlock
[no changelog]
This commit is contained in:
parent
91649dc7cb
commit
ed74f8302f
@ -345,7 +345,7 @@ void real_jump_to_firmware(void) {
|
|||||||
__attribute__((noreturn)) void jump_to_fw_through_reset(void) {
|
__attribute__((noreturn)) void jump_to_fw_through_reset(void) {
|
||||||
display_fade(display_backlight(-1), 0, 200);
|
display_fade(display_backlight(-1), 0, 200);
|
||||||
|
|
||||||
disable_irq();
|
__disable_irq();
|
||||||
delete_secrets();
|
delete_secrets();
|
||||||
NVIC_SystemReset();
|
NVIC_SystemReset();
|
||||||
for (;;)
|
for (;;)
|
||||||
|
@ -194,8 +194,8 @@ typedef long mp_off_t;
|
|||||||
|
|
||||||
#include "irq.h"
|
#include "irq.h"
|
||||||
|
|
||||||
#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq()
|
#define MICROPY_BEGIN_ATOMIC_SECTION() irq_lock()
|
||||||
#define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state)
|
#define MICROPY_END_ATOMIC_SECTION(state) irq_unlock(state)
|
||||||
#define MICROPY_EVENT_POLL_HOOK \
|
#define MICROPY_EVENT_POLL_HOOK \
|
||||||
do { \
|
do { \
|
||||||
extern void mp_handle_pending(bool); \
|
extern void mp_handle_pending(bool); \
|
||||||
|
@ -72,7 +72,7 @@ void reboot_to_bootloader(void) {
|
|||||||
#ifdef STM32U5
|
#ifdef STM32U5
|
||||||
// extern uint32_t g_boot_command;
|
// extern uint32_t g_boot_command;
|
||||||
g_boot_command = boot_command;
|
g_boot_command = boot_command;
|
||||||
disable_irq();
|
__disable_irq();
|
||||||
delete_secrets();
|
delete_secrets();
|
||||||
NVIC_SystemReset();
|
NVIC_SystemReset();
|
||||||
#else
|
#else
|
||||||
|
@ -367,9 +367,9 @@ void i2c_bus_close(i2c_bus_t* bus) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
i2c_status_t i2c_packet_status(const i2c_packet_t* packet) {
|
i2c_status_t i2c_packet_status(const i2c_packet_t* packet) {
|
||||||
uint32_t irq_state = disable_irq();
|
irq_key_t irq_key = irq_lock();
|
||||||
i2c_status_t status = packet->status;
|
i2c_status_t status = packet->status;
|
||||||
enable_irq(irq_state);
|
irq_unlock(irq_key);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -460,14 +460,14 @@ i2c_status_t i2c_bus_submit(i2c_bus_t* bus, i2c_packet_t* packet) {
|
|||||||
packet->status = I2C_STATUS_PENDING;
|
packet->status = I2C_STATUS_PENDING;
|
||||||
|
|
||||||
// Insert packet into the queue
|
// Insert packet into the queue
|
||||||
uint32_t irq_state = disable_irq();
|
irq_key_t irq_key = irq_lock();
|
||||||
if (i2c_bus_add_packet(bus, packet)) {
|
if (i2c_bus_add_packet(bus, packet)) {
|
||||||
// The queue was empty, start the operation
|
// The queue was empty, start the operation
|
||||||
if (!bus->callback_executed && !bus->abort_pending) {
|
if (!bus->callback_executed && !bus->abort_pending) {
|
||||||
i2c_bus_head_continue(bus);
|
i2c_bus_head_continue(bus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
enable_irq(irq_state);
|
irq_unlock(irq_key);
|
||||||
|
|
||||||
return I2C_STATUS_OK;
|
return I2C_STATUS_OK;
|
||||||
}
|
}
|
||||||
@ -478,7 +478,7 @@ void i2c_bus_abort(i2c_bus_t* bus, i2c_packet_t* packet) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t irq_state = disable_irq();
|
irq_key_t irq_key = irq_lock();
|
||||||
|
|
||||||
if (packet->status == I2C_STATUS_PENDING) {
|
if (packet->status == I2C_STATUS_PENDING) {
|
||||||
if (i2c_bus_remove_packet(bus, packet) && bus->next_op > 0) {
|
if (i2c_bus_remove_packet(bus, packet) && bus->next_op > 0) {
|
||||||
@ -502,7 +502,7 @@ void i2c_bus_abort(i2c_bus_t* bus, i2c_packet_t* packet) {
|
|||||||
packet->status = I2C_STATUS_ABORTED;
|
packet->status = I2C_STATUS_ABORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
enable_irq(irq_state);
|
irq_unlock(irq_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Completes the current packet by removing it from the queue
|
// Completes the current packet by removing it from the queue
|
||||||
|
@ -36,22 +36,56 @@ extern uint32_t irq_stats[IRQ_STATS_MAX];
|
|||||||
#define IRQ_EXIT(irq)
|
#define IRQ_EXIT(irq)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef uint32_t irq_key_t;
|
||||||
|
|
||||||
// Checks if interrupts are enabled
|
// Checks if interrupts are enabled
|
||||||
#define IS_IRQ_ENABLED(state) (((state) & 1) == 0)
|
#define IS_IRQ_ENABLED(key) (((key) & 1) == 0)
|
||||||
|
|
||||||
// Get the current value of the CPU's exception mask register.
|
// Get the current value of the CPU's exception mask register.
|
||||||
// The least significant bit indicates if interrupts are enabled or disabled.
|
// The least significant bit indicates if interrupts are enabled or disabled.
|
||||||
static inline uint32_t query_irq(void) { return __get_PRIMASK(); }
|
static inline irq_key_t query_irq(void) { return __get_PRIMASK(); }
|
||||||
|
|
||||||
// Restore the CPU's exception mask register to a previous state
|
// Disables interrupts and returns the previous interrupt state.
|
||||||
static inline void enable_irq(uint32_t state) { __set_PRIMASK(state); }
|
//
|
||||||
|
// This function is used to create critical sections by disabling interrupts
|
||||||
|
// on a Cortex-M platform. It returns the current state of the PRIMASK register,
|
||||||
|
// which controls the global interrupt enable/disable state.
|
||||||
|
//
|
||||||
|
// Important:
|
||||||
|
// - The `"memory"` clobber is included to prevent the compiler from reordering
|
||||||
|
// memory operations across this function, ensuring that all memory accesses
|
||||||
|
// efore `irq_lock()` are completed before interrupts are disabled.
|
||||||
|
// - The order of operations on non-volatile variables relative to this
|
||||||
|
// function is not guaranteed without memory barriers or other
|
||||||
|
// synchronization mechanisms.
|
||||||
|
// - When using Link-Time Optimization (LTO), ensure that the behavior of these
|
||||||
|
// functions is thoroughly tested, as LTO can lead to more aggressive
|
||||||
|
// optimizations. While GCC typically respects the order of `volatile`
|
||||||
|
// operations, this is not guaranteed by the C standard.
|
||||||
|
static inline irq_key_t irq_lock(void) {
|
||||||
|
uint32_t key;
|
||||||
|
__asm volatile(
|
||||||
|
"MRS %0, PRIMASK\n"
|
||||||
|
"CPSID i"
|
||||||
|
: "=r"(key)
|
||||||
|
:
|
||||||
|
: "memory" // Clobber memory to ensure correct memory operations
|
||||||
|
);
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
// Disable all interrupts and return the current state of the
|
// Restores the interrupt state to what it was before `irq_lock`.
|
||||||
// CPU's exception mask register
|
//
|
||||||
static inline uint32_t disable_irq(void) {
|
// This function re-enables interrupts based on the PRIMASK state passed to it.
|
||||||
uint32_t state = __get_PRIMASK();
|
// It should be used in conjunction with `irq_lock` to restore the previous
|
||||||
__disable_irq();
|
// interrupt state after a critical section.
|
||||||
return state;
|
static inline void irq_unlock(irq_key_t key) {
|
||||||
|
__asm volatile(
|
||||||
|
"MSR PRIMASK, %0\n"
|
||||||
|
:
|
||||||
|
: "r"(key)
|
||||||
|
: "memory" // Clobber memory to ensure correct memory operations
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// IRQ priority levels used throughout the system
|
// IRQ priority levels used throughout the system
|
||||||
|
@ -253,13 +253,13 @@ static HAL_StatusTypeDef sdcard_wait_finished(SD_HandleTypeDef *sd,
|
|||||||
uint32_t start = HAL_GetTick();
|
uint32_t start = HAL_GetTick();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// Do an atomic check of the state; WFI will exit even if IRQs are disabled
|
// Do an atomic check of the state; WFI will exit even if IRQs are disabled
|
||||||
uint32_t irq_state = disable_irq();
|
irq_key_t irq_key = irq_lock();
|
||||||
if (sd->State != HAL_SD_STATE_BUSY) {
|
if (sd->State != HAL_SD_STATE_BUSY) {
|
||||||
enable_irq(irq_state);
|
irq_unlock(irq_key);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
__WFI();
|
__WFI();
|
||||||
enable_irq(irq_state);
|
irq_unlock(irq_key);
|
||||||
if (HAL_GetTick() - start >= timeout) {
|
if (HAL_GetTick() - start >= timeout) {
|
||||||
return HAL_TIMEOUT;
|
return HAL_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ void systick_update_freq(void) {
|
|||||||
uint64_t systick_cycles(void) {
|
uint64_t systick_cycles(void) {
|
||||||
systick_driver_t* drv = &g_systick_driver;
|
systick_driver_t* drv = &g_systick_driver;
|
||||||
|
|
||||||
uint32_t irq_state = disable_irq();
|
irq_key_t irq_key = irq_lock();
|
||||||
|
|
||||||
// Current value of the SysTick counter
|
// Current value of the SysTick counter
|
||||||
uint32_t val = SysTick->VAL;
|
uint32_t val = SysTick->VAL;
|
||||||
@ -125,7 +125,7 @@ uint64_t systick_cycles(void) {
|
|||||||
|
|
||||||
uint64_t cycles = drv->cycles + ((val > 0) ? (drv->cycles_per_ms - val) : 0);
|
uint64_t cycles = drv->cycles + ((val > 0) ? (drv->cycles_per_ms - val) : 0);
|
||||||
|
|
||||||
enable_irq(irq_state);
|
irq_unlock(irq_key);
|
||||||
|
|
||||||
return cycles;
|
return cycles;
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ systimer_t* systimer_create(systimer_callback_t callback, void* context) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t irq_state = disable_irq();
|
irq_key_t irq_key = irq_lock();
|
||||||
|
|
||||||
// Find a free timer entry
|
// Find a free timer entry
|
||||||
for (int i = 0; i < MAX_SYSTIMERS; i++) {
|
for (int i = 0; i < MAX_SYSTIMERS; i++) {
|
||||||
@ -109,13 +109,13 @@ systimer_t* systimer_create(systimer_callback_t callback, void* context) {
|
|||||||
timer->context = context;
|
timer->context = context;
|
||||||
timer->callback = callback;
|
timer->callback = callback;
|
||||||
|
|
||||||
enable_irq(irq_state);
|
irq_unlock(irq_key);
|
||||||
return timer;
|
return timer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// No free timer entry found
|
// No free timer entry found
|
||||||
enable_irq(irq_state);
|
irq_unlock(irq_key);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,11 +138,11 @@ void systimer_set(systimer_t* timer, uint32_t delay_ms) {
|
|||||||
uint64_t delay = systick_us_to_cycles((uint64_t)delay_ms * 1000);
|
uint64_t delay = systick_us_to_cycles((uint64_t)delay_ms * 1000);
|
||||||
uint64_t expiration = systick_cycles() + delay;
|
uint64_t expiration = systick_cycles() + delay;
|
||||||
|
|
||||||
uint32_t irq_state = disable_irq();
|
irq_key_t irq_key = irq_lock();
|
||||||
timer->expiration = expiration;
|
timer->expiration = expiration;
|
||||||
timer->period = 0;
|
timer->period = 0;
|
||||||
timer->scheduled = true;
|
timer->scheduled = true;
|
||||||
enable_irq(irq_state);
|
irq_unlock(irq_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void systimer_set_periodic(systimer_t* timer, uint32_t period_ms) {
|
void systimer_set_periodic(systimer_t* timer, uint32_t period_ms) {
|
||||||
@ -155,11 +155,11 @@ void systimer_set_periodic(systimer_t* timer, uint32_t period_ms) {
|
|||||||
uint64_t period = systick_us_to_cycles((uint64_t)period_ms * 1000);
|
uint64_t period = systick_us_to_cycles((uint64_t)period_ms * 1000);
|
||||||
uint64_t expiration = systick_cycles() + period;
|
uint64_t expiration = systick_cycles() + period;
|
||||||
|
|
||||||
uint32_t irq_state = disable_irq();
|
irq_key_t irq_key = irq_lock();
|
||||||
timer->expiration = expiration;
|
timer->expiration = expiration;
|
||||||
timer->period = period;
|
timer->period = period;
|
||||||
timer->scheduled = true;
|
timer->scheduled = true;
|
||||||
enable_irq(irq_state);
|
irq_unlock(irq_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool systimer_unset(systimer_t* timer) {
|
bool systimer_unset(systimer_t* timer) {
|
||||||
@ -169,10 +169,10 @@ bool systimer_unset(systimer_t* timer) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t irq_state = disable_irq();
|
irq_key_t irq_key = irq_lock();
|
||||||
bool was_scheduled = timer->scheduled;
|
bool was_scheduled = timer->scheduled;
|
||||||
timer->scheduled = false;
|
timer->scheduled = false;
|
||||||
enable_irq(irq_state);
|
irq_unlock(irq_key);
|
||||||
return was_scheduled;
|
return was_scheduled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,10 +183,10 @@ systimer_key_t systimer_suspend(systimer_t* timer) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t irq_state = disable_irq();
|
irq_key_t irq_key = irq_lock();
|
||||||
bool was_suspended = timer->suspended;
|
bool was_suspended = timer->suspended;
|
||||||
timer->suspended = true;
|
timer->suspended = true;
|
||||||
enable_irq(irq_state);
|
irq_unlock(irq_key);
|
||||||
return was_suspended;
|
return was_suspended;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,9 +367,9 @@ void i2c_bus_close(i2c_bus_t* bus) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
i2c_status_t i2c_packet_status(const i2c_packet_t* packet) {
|
i2c_status_t i2c_packet_status(const i2c_packet_t* packet) {
|
||||||
uint32_t irq_state = disable_irq();
|
irq_key_t irq_key = irq_lock();
|
||||||
i2c_status_t status = packet->status;
|
i2c_status_t status = packet->status;
|
||||||
enable_irq(irq_state);
|
irq_unlock(irq_key);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -506,14 +506,14 @@ i2c_status_t i2c_bus_submit(i2c_bus_t* bus, i2c_packet_t* packet) {
|
|||||||
packet->status = I2C_STATUS_PENDING;
|
packet->status = I2C_STATUS_PENDING;
|
||||||
|
|
||||||
// Insert packet into the queue
|
// Insert packet into the queue
|
||||||
uint32_t irq_state = disable_irq();
|
irq_key_t irq_key = irq_lock();
|
||||||
if (i2c_bus_add_packet(bus, packet)) {
|
if (i2c_bus_add_packet(bus, packet)) {
|
||||||
// The queue was empty, start the operation
|
// The queue was empty, start the operation
|
||||||
if (!bus->callback_executed && !bus->abort_pending) {
|
if (!bus->callback_executed && !bus->abort_pending) {
|
||||||
i2c_bus_head_continue(bus);
|
i2c_bus_head_continue(bus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
enable_irq(irq_state);
|
irq_unlock(irq_key);
|
||||||
|
|
||||||
return I2C_STATUS_OK;
|
return I2C_STATUS_OK;
|
||||||
}
|
}
|
||||||
@ -524,7 +524,7 @@ void i2c_bus_abort(i2c_bus_t* bus, i2c_packet_t* packet) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t irq_state = disable_irq();
|
irq_key_t irq_key = irq_lock();
|
||||||
|
|
||||||
if (packet->status == I2C_STATUS_PENDING) {
|
if (packet->status == I2C_STATUS_PENDING) {
|
||||||
if (i2c_bus_remove_packet(bus, packet) && bus->next_op > 0) {
|
if (i2c_bus_remove_packet(bus, packet) && bus->next_op > 0) {
|
||||||
@ -553,7 +553,7 @@ void i2c_bus_abort(i2c_bus_t* bus, i2c_packet_t* packet) {
|
|||||||
packet->status = I2C_STATUS_ABORTED;
|
packet->status = I2C_STATUS_ABORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
enable_irq(irq_state);
|
irq_unlock(irq_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Completes the current packet by removing it from the queue
|
// Completes the current packet by removing it from the queue
|
||||||
|
@ -256,13 +256,13 @@ static HAL_StatusTypeDef sdcard_wait_finished(SD_HandleTypeDef *sd,
|
|||||||
uint32_t start = HAL_GetTick();
|
uint32_t start = HAL_GetTick();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// Do an atomic check of the state; WFI will exit even if IRQs are disabled
|
// Do an atomic check of the state; WFI will exit even if IRQs are disabled
|
||||||
uint32_t irq_state = disable_irq();
|
irq_key_t irq_key = irq_lock();
|
||||||
if (sd->State != HAL_SD_STATE_BUSY) {
|
if (sd->State != HAL_SD_STATE_BUSY) {
|
||||||
enable_irq(irq_state);
|
irq_unlock(irq_key);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
__WFI();
|
__WFI();
|
||||||
enable_irq(irq_state);
|
irq_unlock(irq_key);
|
||||||
if (HAL_GetTick() - start >= timeout) {
|
if (HAL_GetTick() - start >= timeout) {
|
||||||
return HAL_TIMEOUT;
|
return HAL_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user