diff --git a/core/embed/firmware/main.c b/core/embed/firmware/main.c index b3d206d89d..304699f88c 100644 --- a/core/embed/firmware/main.c +++ b/core/embed/firmware/main.c @@ -300,6 +300,9 @@ 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; default: stack[0] = 0xffffffff; break; diff --git a/core/embed/trezorhal/common.h b/core/embed/trezorhal/common.h index 1781ed4c85..d032a27318 100644 --- a/core/embed/trezorhal/common.h +++ b/core/embed/trezorhal/common.h @@ -76,6 +76,7 @@ void show_pin_too_many_screen(void); void hal_delay(uint32_t ms); uint32_t hal_ticks_ms(); +void hal_delay_us(uint16_t delay_us); void collect_hw_entropy(void); #define HW_ENTROPY_LEN (12 + 32) diff --git a/core/embed/trezorhal/optiga/optiga_transport.c b/core/embed/trezorhal/optiga/optiga_transport.c index 9a724f6ec5..5a827dfe9c 100644 --- a/core/embed/trezorhal/optiga/optiga_transport.c +++ b/core/embed/trezorhal/optiga/optiga_transport.c @@ -175,8 +175,10 @@ static optiga_result optiga_i2c_write(const uint8_t *data, uint16_t data_size) { } if (HAL_OK == i2c_transmit(OPTIGA_I2C_INSTANCE, OPTIGA_ADDRESS, (uint8_t *)data, data_size, I2C_TIMEOUT)) { + hal_delay_us(1000); return OPTIGA_SUCCESS; } + hal_delay_us(1000); } return OPTIGA_ERR_I2C_WRITE; } diff --git a/core/embed/trezorhal/stm32f4/common.c b/core/embed/trezorhal/stm32f4/common.c index 3af562b941..427f10b0be 100644 --- a/core/embed/trezorhal/stm32f4/common.c +++ b/core/embed/trezorhal/stm32f4/common.c @@ -46,6 +46,8 @@ #define COLOR_FATAL_ERROR COLOR_BLACK #endif +uint32_t systick_val_copy = 0; + // from util.s extern void shutdown_privileged(void); @@ -154,6 +156,17 @@ void __assert_func(const char *file, int line, const char *func, 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) diff --git a/core/embed/trezorhal/stm32f4/i2c.c b/core/embed/trezorhal/stm32f4/i2c.c index 65ce9076f5..ba65738c69 100644 --- a/core/embed/trezorhal/stm32f4/i2c.c +++ b/core/embed/trezorhal/stm32f4/i2c.c @@ -171,9 +171,19 @@ HAL_StatusTypeDef i2c_transmit(uint16_t idx, uint8_t addr, uint8_t *data, uint16_t len, uint32_t timeout) { return HAL_I2C_Master_Transmit(&i2c_handle[idx], addr, data, len, timeout); } + HAL_StatusTypeDef i2c_receive(uint16_t idx, uint8_t addr, uint8_t *data, uint16_t len, uint32_t timeout) { - return HAL_I2C_Master_Receive(&i2c_handle[idx], addr, data, len, timeout); + HAL_StatusTypeDef ret = + HAL_I2C_Master_Receive(&i2c_handle[idx], addr, data, len, timeout); +#ifdef USE_OPTIGA + if (idx == OPTIGA_I2C_INSTANCE) { + // apply GUARD_TIME as specified by the OPTIGA datasheet + // (only applies to the I2C bus to which the OPTIGA is connected) + hal_delay_us(50); + } +#endif + return ret; } HAL_StatusTypeDef i2c_mem_write(uint16_t idx, uint8_t addr, uint16_t mem_addr, diff --git a/core/embed/trezorhal/stm32f4/supervise.h b/core/embed/trezorhal/stm32f4/supervise.h index 7d51530d69..27699c5c73 100644 --- a/core/embed/trezorhal/stm32f4/supervise.h +++ b/core/embed/trezorhal/stm32f4/supervise.h @@ -6,11 +6,15 @@ #define SVC_SHUTDOWN 4 #define SVC_REBOOT_TO_BOOTLOADER 5 #define SVC_REBOOT_COPY_IMAGE_HEADER 6 +#define SVC_GET_SYSTICK_VAL 7 #include #include "common.h" #include "image.h" +// from common.c +extern uint32_t systick_val_copy; + // from util.s extern void shutdown_privileged(void); extern void reboot_to_bootloader(void); @@ -87,3 +91,13 @@ static inline void svc_reboot_copy_image_header(const uint8_t *image_address) { reboot_to_bootloader(); } } + +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; + } +}