From e0797131eca42411e6c31d799b9f7c407f50a79e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Mon, 20 May 2024 19:17:01 +0100 Subject: [PATCH] FuriHal: add flash ops stats, workaround bug in SHCI_C2_SetSystemClock (#3657) * FuriHal: add flash ops stats, workaround bug in SHCI_C2_SetSystemClock * hal: flash: added FLASH_OP_DEBUG to enable latency measurement Co-authored-by: hedger Co-authored-by: hedger --- targets/f7/furi_hal/furi_hal_clock.c | 20 +++++++++++--------- targets/f7/furi_hal/furi_hal_flash.c | 27 +++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/targets/f7/furi_hal/furi_hal_clock.c b/targets/f7/furi_hal/furi_hal_clock.c index 9184fa715..ca4c7ad4d 100644 --- a/targets/f7/furi_hal/furi_hal_clock.c +++ b/targets/f7/furi_hal/furi_hal_clock.c @@ -133,7 +133,7 @@ void furi_hal_clock_switch_hse2hsi(void) { ; LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSI); - furi_assert(LL_RCC_GetSMPSClockSelection() == LL_RCC_SMPS_CLKSOURCE_HSI); + furi_check(LL_RCC_GetSMPSClockSelection() == LL_RCC_SMPS_CLKSOURCE_HSI); while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI) ; @@ -170,7 +170,7 @@ void furi_hal_clock_switch_hsi2hse(void) { } bool furi_hal_clock_switch_hse2pll(void) { - furi_assert(LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_HSE); + furi_check(LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_HSE); LL_RCC_PLL_Enable(); LL_RCC_PLLSAI1_Enable(); @@ -180,12 +180,13 @@ bool furi_hal_clock_switch_hse2pll(void) { while(!LL_RCC_PLLSAI1_IsReady()) ; - if(SHCI_C2_SetSystemClock(SET_SYSTEM_CLOCK_HSE_TO_PLL) != SHCI_Success) { + // This API returns garbage if stack version < 1.20.0 + SHCI_C2_SetSystemClock(SET_SYSTEM_CLOCK_HSE_TO_PLL); + // So we'll check results by asking hardware directly + if(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) { return false; } - furi_check(LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_PLL); - LL_SetSystemCoreClock(CPU_CLOCK_PLL_HZ); SysTick->LOAD = (uint32_t)((SystemCoreClock / 1000) - 1UL); @@ -193,18 +194,19 @@ bool furi_hal_clock_switch_hse2pll(void) { } bool furi_hal_clock_switch_pll2hse(void) { - furi_assert(LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_PLL); + furi_check(LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_PLL); LL_RCC_HSE_Enable(); while(!LL_RCC_HSE_IsReady()) ; - if(SHCI_C2_SetSystemClock(SET_SYSTEM_CLOCK_PLL_ON_TO_HSE) != SHCI_Success) { + // This API returns garbage if stack version < 1.20.0 + SHCI_C2_SetSystemClock(SET_SYSTEM_CLOCK_PLL_ON_TO_HSE); + // So we'll check results by asking hardware directly + if(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSE) { return false; } - furi_check(LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_HSE); - LL_SetSystemCoreClock(CPU_CLOCK_HSE_HZ); SysTick->LOAD = (uint32_t)((SystemCoreClock / 1000) - 1UL); diff --git a/targets/f7/furi_hal/furi_hal_flash.c b/targets/f7/furi_hal/furi_hal_flash.c index 138e07eab..43f80c61e 100644 --- a/targets/f7/furi_hal/furi_hal_flash.c +++ b/targets/f7/furi_hal/furi_hal_flash.c @@ -16,6 +16,12 @@ #define TAG "FuriHalFlash" +#ifdef FLASH_OP_DEBUG +#undef FURI_LOG_T +#define FURI_LOG_T(...) +#else +#endif + #define FURI_HAL_CRITICAL_MSG "Critical flash operation fail" #define FURI_HAL_FLASH_READ_BLOCK (8U) #define FURI_HAL_FLASH_WRITE_BLOCK (8U) @@ -291,6 +297,7 @@ bool furi_hal_flash_wait_last_operation(uint32_t timeout) { } void furi_hal_flash_erase(uint8_t page) { + uint32_t op_stat = DWT->CYCCNT; furi_hal_flash_begin(true); /* Ensure that controller state is valid */ @@ -313,6 +320,12 @@ void furi_hal_flash_erase(uint8_t page) { furi_hal_flush_cache(); furi_hal_flash_end(true); + op_stat = DWT->CYCCNT - op_stat; + FURI_LOG_T( + TAG, + "erase took %lu clocks or %fus", + op_stat, + (double)((float)op_stat / (float)furi_hal_cortex_instructions_per_microsecond())); } static inline void furi_hal_flash_write_dword_internal_nowait(size_t address, uint64_t* data) { @@ -335,6 +348,7 @@ static inline void furi_hal_flash_write_dword_internal(size_t address, uint64_t* } void furi_hal_flash_write_dword(size_t address, uint64_t data) { + uint32_t op_stat = DWT->CYCCNT; furi_hal_flash_begin(false); /* Ensure that controller state is valid */ @@ -357,6 +371,12 @@ void furi_hal_flash_write_dword(size_t address, uint64_t data) { /* Wait for last operation to be completed */ furi_check(furi_hal_flash_wait_last_operation(FURI_HAL_FLASH_TIMEOUT)); + op_stat = DWT->CYCCNT - op_stat; + FURI_LOG_T( + TAG, + "write_dword took %lu clocks or %fus", + op_stat, + (double)((float)op_stat / (float)furi_hal_cortex_instructions_per_microsecond())); } static size_t furi_hal_flash_get_page_address(uint8_t page) { @@ -369,6 +389,7 @@ void furi_hal_flash_program_page(const uint8_t page, const uint8_t* data, uint16 furi_hal_flash_erase(page); + uint32_t op_stat = DWT->CYCCNT; furi_hal_flash_begin(false); furi_check(furi_hal_flash_wait_last_operation(FURI_HAL_FLASH_TIMEOUT)); @@ -428,6 +449,12 @@ void furi_hal_flash_program_page(const uint8_t page, const uint8_t* data, uint16 CLEAR_BIT(FLASH->CR, FLASH_CR_PG); furi_hal_flash_end(false); + op_stat = DWT->CYCCNT - op_stat; + FURI_LOG_T( + TAG, + "program_page took %lu clocks or %fus", + op_stat, + (double)((float)op_stat / (float)furi_hal_cortex_instructions_per_microsecond())); } int16_t furi_hal_flash_get_page_number(size_t address) {