mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-03-03 08:46:05 +00:00
feat(core): reset peripherals during handovers
[no changelog]
This commit is contained in:
parent
236c377e20
commit
f99030938e
@ -413,6 +413,10 @@
|
||||
#endif /* USE_FULL_ASSERT */
|
||||
|
||||
|
||||
#ifndef HardFault_IRQn
|
||||
#define HardFault_IRQn (-13) // not defined in stm32lib/cmsis/stm32f429xx.h
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -49,8 +49,17 @@ void ensure_thread_mode(void);
|
||||
void ensure_compatible_settings(void);
|
||||
|
||||
// Clears USB peripheral fifo memory
|
||||
//
|
||||
// Used to wipe sensitive data from USB peripheral memory.
|
||||
void clear_otg_hs_memory(void);
|
||||
|
||||
// Resets critical peripherals, disables all interrupts, and clears
|
||||
// pending interrupts in the NVIC controller.
|
||||
//
|
||||
// This function is used to stop pending DMA transfers and interrupts,
|
||||
// ensuring it is safe to jump to the next stage or initiate rescue mode.
|
||||
void reset_peripherals_and_interrupts(void);
|
||||
|
||||
// Jumps to the binary using its vector table.
|
||||
//
|
||||
// The target binary is called with interrupts disabled, and all registers
|
||||
|
@ -104,6 +104,10 @@ static void reboot_with_args_phase_2(uint32_t arg1, uint32_t arg2) {
|
||||
// any variables in the .bss and .data sections, so we must
|
||||
// be careful and avoid using them altogether.
|
||||
|
||||
// Reset peripherals (so we are sure that no DMA is pending)
|
||||
// and disable all interrupts and clear all pending ones
|
||||
reset_peripherals_and_interrupts();
|
||||
|
||||
// Clear unused part of stack
|
||||
clear_unused_stack();
|
||||
|
||||
@ -174,6 +178,10 @@ static void jump_to_next_stage_phase_2(uint32_t arg1, uint32_t arg2) {
|
||||
// any variables in the .bss and .data sections, so we must
|
||||
// be careful and avoid using them altogether.
|
||||
|
||||
// Reset peripherals (so we are sure that no DMA is pending)
|
||||
// and disable all interrupts and clear all pending ones
|
||||
reset_peripherals_and_interrupts();
|
||||
|
||||
// Clear unused part of stack
|
||||
clear_unused_stack();
|
||||
|
||||
|
@ -260,4 +260,99 @@ __attribute((naked, noreturn, no_stack_protector)) void jump_to_vectbl(
|
||||
);
|
||||
}
|
||||
|
||||
void reset_peripherals_and_interrupts(void) {
|
||||
#ifdef __HAL_RCC_DMA2D_FORCE_RESET
|
||||
__HAL_RCC_DMA2D_CLK_DISABLE();
|
||||
__HAL_RCC_DMA2D_FORCE_RESET();
|
||||
__HAL_RCC_DMA2D_RELEASE_RESET();
|
||||
#endif
|
||||
|
||||
#ifdef __HAL_RCC_DSI_FORCE_RESET
|
||||
__HAL_RCC_DSI_CLK_DISABLE();
|
||||
__HAL_RCC_DSI_FORCE_RESET();
|
||||
__HAL_RCC_DSI_RELEASE_RESET();
|
||||
#endif
|
||||
|
||||
#ifdef __HAL_RCC_GFXMMU_FORCE_RESET
|
||||
__HAL_RCC_GFXMMU_CLK_DISABLE();
|
||||
__HAL_RCC_GFXMMU_FORCE_RESET();
|
||||
__HAL_RCC_GFXMMU_RELEASE_RESET();
|
||||
#endif
|
||||
|
||||
#ifdef __HAL_RCC_LTDC_FORCE_RESET
|
||||
__HAL_RCC_LTDC_CLK_DISABLE();
|
||||
__HAL_RCC_LTDC_FORCE_RESET();
|
||||
__HAL_RCC_LTDC_RELEASE_RESET();
|
||||
#endif
|
||||
|
||||
#ifdef __HAL_RCC_GPDMA1_FORCE_RESET
|
||||
__HAL_RCC_GPDMA1_CLK_DISABLE();
|
||||
__HAL_RCC_GPDMA1_FORCE_RESET();
|
||||
__HAL_RCC_GPDMA1_RELEASE_RESET();
|
||||
#endif
|
||||
|
||||
#ifdef __HAL_RCC_DMA1_FORCE_RESET
|
||||
__HAL_RCC_DMA1_CLK_DISABLE();
|
||||
__HAL_RCC_DMA1_FORCE_RESET();
|
||||
__HAL_RCC_DMA1_RELEASE_RESET();
|
||||
#endif
|
||||
|
||||
#ifdef __HAL_RCC_DMA2_FORCE_RESET
|
||||
__HAL_RCC_DMA2_CLK_DISABLE();
|
||||
__HAL_RCC_DMA2_FORCE_RESET();
|
||||
__HAL_RCC_DMA2_RELEASE_RESET();
|
||||
#endif
|
||||
|
||||
// Disable all NVIC interrupts and clear pending flags
|
||||
// so later the global interrupt can be re-enabled without
|
||||
// firing any pending interrupt
|
||||
for (int irqn = 0; irqn < 255; irqn++) {
|
||||
NVIC_DisableIRQ(irqn);
|
||||
NVIC_ClearPendingIRQ(irqn);
|
||||
}
|
||||
|
||||
// Disable SysTick
|
||||
SysTick->CTRL = 0;
|
||||
|
||||
// Clear PENDSV flag to prevent the PendSV_Handler call
|
||||
SCB->ICSR &= ~SCB_ICSR_PENDSVSET_Msk;
|
||||
|
||||
// Clear SCB->SHCSR exception flags so we can return back
|
||||
// to thread mode without any exception active
|
||||
|
||||
uint32_t preserved_flag = 0;
|
||||
|
||||
switch ((__get_IPSR() & IPSR_ISR_Msk) - 16) {
|
||||
case MemoryManagement_IRQn:
|
||||
preserved_flag = SCB_SHCSR_MEMFAULTACT_Msk;
|
||||
break;
|
||||
case BusFault_IRQn:
|
||||
preserved_flag = SCB_SHCSR_BUSFAULTACT_Msk;
|
||||
break;
|
||||
case UsageFault_IRQn:
|
||||
preserved_flag = SCB_SHCSR_USGFAULTACT_Msk;
|
||||
break;
|
||||
case PendSV_IRQn:
|
||||
preserved_flag = SCB_SHCSR_PENDSVACT_Msk;
|
||||
break;
|
||||
case SysTick_IRQn:
|
||||
preserved_flag = SCB_SHCSR_SYSTICKACT_Msk;
|
||||
break;
|
||||
case SVCall_IRQn:
|
||||
preserved_flag = SCB_SHCSR_SVCALLACT_Msk;
|
||||
break;
|
||||
case HardFault_IRQn:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const uint32_t cleared_flags =
|
||||
SCB_SHCSR_MEMFAULTACT_Msk | SCB_SHCSR_BUSFAULTACT_Msk |
|
||||
SCB_SHCSR_USGFAULTACT_Msk | SCB_SHCSR_SVCALLACT_Msk |
|
||||
SCB_SHCSR_MONITORACT_Msk | SCB_SHCSR_PENDSVACT_Msk |
|
||||
SCB_SHCSR_SYSTICKACT_Msk;
|
||||
|
||||
SCB->SHCSR &= ~(cleared_flags & ~preserved_flag);
|
||||
}
|
||||
|
||||
#endif // KERNEL_MODE
|
||||
|
@ -38,10 +38,6 @@
|
||||
#include "../stm32f4/startup_init.h"
|
||||
#endif
|
||||
|
||||
#ifndef HardFault_IRQn
|
||||
#define HardFault_IRQn (-13) // not defined in stm32lib/cmsis/stm32429xx.h
|
||||
#endif
|
||||
|
||||
#ifdef KERNEL_MODE
|
||||
|
||||
void system_init(systask_error_handler_t error_handler) {
|
||||
@ -81,109 +77,12 @@ void system_exit_fatal_ex(const char* message, size_t message_len,
|
||||
systask_exit_fatal(NULL, message, message_len, file, file_len, line);
|
||||
}
|
||||
|
||||
__attribute__((used)) static void emergency_reset(void) {
|
||||
// Reset peripherals
|
||||
|
||||
#ifdef __HAL_RCC_DMA2D_FORCE_RESET
|
||||
__HAL_RCC_DMA2D_CLK_DISABLE();
|
||||
__HAL_RCC_DMA2D_FORCE_RESET();
|
||||
__HAL_RCC_DMA2D_RELEASE_RESET();
|
||||
#endif
|
||||
|
||||
#ifdef __HAL_RCC_DSI_FORCE_RESET
|
||||
__HAL_RCC_DSI_CLK_DISABLE();
|
||||
__HAL_RCC_DSI_FORCE_RESET();
|
||||
__HAL_RCC_DSI_RELEASE_RESET();
|
||||
#endif
|
||||
|
||||
#ifdef __HAL_RCC_GFXMMU_FORCE_RESET
|
||||
__HAL_RCC_GFXMMU_CLK_DISABLE();
|
||||
__HAL_RCC_GFXMMU_FORCE_RESET();
|
||||
__HAL_RCC_GFXMMU_RELEASE_RESET();
|
||||
#endif
|
||||
|
||||
#ifdef __HAL_RCC_LTDC_FORCE_RESET
|
||||
__HAL_RCC_LTDC_CLK_DISABLE();
|
||||
__HAL_RCC_LTDC_FORCE_RESET();
|
||||
__HAL_RCC_LTDC_RELEASE_RESET();
|
||||
#endif
|
||||
|
||||
#ifdef __HAL_RCC_GPDMA1_FORCE_RESET
|
||||
__HAL_RCC_GPDMA1_CLK_DISABLE();
|
||||
__HAL_RCC_GPDMA1_FORCE_RESET();
|
||||
__HAL_RCC_GPDMA1_RELEASE_RESET();
|
||||
#endif
|
||||
|
||||
#ifdef __HAL_RCC_DMA1_FORCE_RESET
|
||||
__HAL_RCC_DMA1_CLK_DISABLE();
|
||||
__HAL_RCC_DMA1_FORCE_RESET();
|
||||
__HAL_RCC_DMA1_RELEASE_RESET();
|
||||
#endif
|
||||
|
||||
#ifdef __HAL_RCC_DMA2_FORCE_RESET
|
||||
__HAL_RCC_DMA2_CLK_DISABLE();
|
||||
__HAL_RCC_DMA2_FORCE_RESET();
|
||||
__HAL_RCC_DMA2_RELEASE_RESET();
|
||||
#endif
|
||||
|
||||
// Disable all NVIC interrupts and clear pending flags
|
||||
// so later the global interrupt can be re-enabled without
|
||||
// firing any pending interrupt
|
||||
for (int irqn = 0; irqn < 255; irqn++) {
|
||||
NVIC_DisableIRQ(irqn);
|
||||
NVIC_ClearPendingIRQ(irqn);
|
||||
}
|
||||
|
||||
// Disable SysTick
|
||||
SysTick->CTRL = 0;
|
||||
|
||||
// Clear PENDSV flag to prevent the PendSV_Handler call
|
||||
SCB->ICSR &= ~SCB_ICSR_PENDSVSET_Msk;
|
||||
|
||||
// Clear SCB->SHCSR exception flags so we can return back
|
||||
// to thread mode without any exception active
|
||||
|
||||
uint32_t preserved_flag = 0;
|
||||
|
||||
switch ((__get_IPSR() & IPSR_ISR_Msk) - 16) {
|
||||
case MemoryManagement_IRQn:
|
||||
preserved_flag = SCB_SHCSR_MEMFAULTACT_Msk;
|
||||
break;
|
||||
case BusFault_IRQn:
|
||||
preserved_flag = SCB_SHCSR_BUSFAULTACT_Msk;
|
||||
break;
|
||||
case UsageFault_IRQn:
|
||||
preserved_flag = SCB_SHCSR_USGFAULTACT_Msk;
|
||||
break;
|
||||
case PendSV_IRQn:
|
||||
preserved_flag = SCB_SHCSR_PENDSVACT_Msk;
|
||||
break;
|
||||
case SysTick_IRQn:
|
||||
preserved_flag = SCB_SHCSR_SYSTICKACT_Msk;
|
||||
break;
|
||||
case SVCall_IRQn:
|
||||
preserved_flag = SCB_SHCSR_SVCALLACT_Msk;
|
||||
break;
|
||||
case HardFault_IRQn:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const uint32_t cleared_flags =
|
||||
SCB_SHCSR_MEMFAULTACT_Msk | SCB_SHCSR_BUSFAULTACT_Msk |
|
||||
SCB_SHCSR_USGFAULTACT_Msk | SCB_SHCSR_SVCALLACT_Msk |
|
||||
SCB_SHCSR_MONITORACT_Msk | SCB_SHCSR_PENDSVACT_Msk |
|
||||
SCB_SHCSR_SYSTICKACT_Msk;
|
||||
|
||||
SCB->SHCSR &= ~(cleared_flags & ~preserved_flag);
|
||||
}
|
||||
|
||||
__attribute((noreturn, no_stack_protector)) static void
|
||||
system_emergency_rescue_phase_2(uint32_t arg1, uint32_t arg2) {
|
||||
systask_error_handler_t error_handler = (systask_error_handler_t)arg1;
|
||||
|
||||
// Reset peripherals (so we are sure that no DMA is pending)
|
||||
emergency_reset();
|
||||
reset_peripherals_and_interrupts();
|
||||
|
||||
// Copy pminfo from to our stack
|
||||
// MPU is now disable, we have full access to bootargs.
|
||||
|
Loading…
Reference in New Issue
Block a user