From 85bc2d7240cd53e15507c5d6239944ff0705e7e6 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 20 Jul 2021 03:31:25 +0200 Subject: [PATCH 1/3] esp_timer: allow querying the timer before esp_timer_init is called --- components/esp_system/startup.c | 7 ++++- components/esp_timer/include/esp_timer.h | 17 +++++++++++ .../private_include/esp_timer_impl.h | 11 +++++++ components/esp_timer/src/esp_timer.c | 5 ++++ components/esp_timer/src/esp_timer_impl_lac.c | 23 +++++++------- .../esp_timer/src/esp_timer_impl_systimer.c | 30 +++++++++++-------- 6 files changed, 68 insertions(+), 25 deletions(-) diff --git a/components/esp_system/startup.c b/components/esp_system/startup.c index 719afd108f..11fd441dbe 100644 --- a/components/esp_system/startup.c +++ b/components/esp_system/startup.c @@ -241,7 +241,6 @@ static void do_core_init(void) fail initializing it properly. */ heap_caps_init(); esp_newlib_init(); - esp_newlib_time_init(); if (g_spiram_ok) { #if CONFIG_SPIRAM_BOOT_INIT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC) @@ -266,6 +265,12 @@ static void do_core_init(void) esp_brownout_init(); #endif + // esp_timer early initialization is required for esp_timer_get_time to work. + // This needs to happen before VFS initialization, since some USB_SERIAL_JTAG VFS driver uses + // esp_timer_get_time to determine timeout conditions. + esp_timer_early_init(); + esp_newlib_time_init(); + #ifdef CONFIG_VFS_SUPPORT_IO #ifdef CONFIG_ESP_CONSOLE_UART esp_vfs_dev_uart_register(); diff --git a/components/esp_timer/include/esp_timer.h b/components/esp_timer/include/esp_timer.h index 8c94298947..02f9379736 100644 --- a/components/esp_timer/include/esp_timer.h +++ b/components/esp_timer/include/esp_timer.h @@ -83,11 +83,28 @@ typedef struct { bool skip_unhandled_events; //!< Skip unhandled events for periodic timers } esp_timer_create_args_t; + +/** + * @brief Minimal initialization of esp_timer + * + * @note This function is called from startup code. Applications do not need + * to call this function before using other esp_timer APIs. + * + * This function can be called very early in startup process, after this call + * only esp_timer_get_time function can be used. + * + * @return + * - ESP_OK on success + */ +esp_err_t esp_timer_early_init(void); + /** * @brief Initialize esp_timer library * * @note This function is called from startup code. Applications do not need * to call this function before using other esp_timer APIs. + * Before calling this function, esp_timer_early_init must be called by the + * startup code. * * @return * - ESP_OK on success diff --git a/components/esp_timer/private_include/esp_timer_impl.h b/components/esp_timer/private_include/esp_timer_impl.h index 63daba0d9e..888461f9fa 100644 --- a/components/esp_timer/private_include/esp_timer_impl.h +++ b/components/esp_timer/private_include/esp_timer_impl.h @@ -28,9 +28,20 @@ #include "esp_err.h" #include "esp_intr_alloc.h" +/** + * @brief Minimal initialization of platform specific layer of esp_timer + * This function can be called very early in startup process, after this call + * only esp_timer_get_time function can be used. + * esp_timer_impl_init has to be called after this function to initialize the + * rest of esp_timer implementation. + * @return ESP_OK + */ +esp_err_t esp_timer_impl_early_init(void); + /** * @brief Initialize platform specific layer of esp_timer * @param alarm_handler function to call on timer interrupt + * Before calling this function, esp_timer_impl_early_init must be called. * @return ESP_OK, ESP_ERR_NO_MEM, or one of the errors from interrupt allocator */ esp_err_t esp_timer_impl_init(intr_handler_t alarm_handler); diff --git a/components/esp_timer/src/esp_timer.c b/components/esp_timer/src/esp_timer.c index ad185760f5..375cad6c4d 100644 --- a/components/esp_timer/src/esp_timer.c +++ b/components/esp_timer/src/esp_timer.c @@ -428,6 +428,11 @@ static IRAM_ATTR inline bool is_initialized(void) return s_timer_task != NULL; } +esp_err_t esp_timer_early_init(void) +{ + return esp_timer_impl_early_init(); +} + esp_err_t esp_timer_init(void) { esp_err_t err; diff --git a/components/esp_timer/src/esp_timer_impl_lac.c b/components/esp_timer/src/esp_timer_impl_lac.c index aa414709e7..13338f0874 100644 --- a/components/esp_timer/src/esp_timer_impl_lac.c +++ b/components/esp_timer/src/esp_timer_impl_lac.c @@ -146,9 +146,6 @@ uint64_t IRAM_ATTR esp_timer_impl_get_counter_reg(void) int64_t IRAM_ATTR esp_timer_impl_get_time(void) { - if (s_alarm_handler == NULL) { - return 0; - } return esp_timer_impl_get_counter_reg() / TICKS_PER_US; } @@ -217,13 +214,10 @@ void esp_timer_impl_advance(int64_t time_diff_us) portEXIT_CRITICAL(&s_time_update_lock); } -esp_err_t esp_timer_impl_init(intr_handler_t alarm_handler) +esp_err_t esp_timer_impl_early_init(void) { - s_alarm_handler = alarm_handler; - periph_module_enable(PERIPH_LACT); - /* Reset the state */ REG_WRITE(CONFIG_REG, 0); REG_WRITE(LOAD_LO_REG, 0); REG_WRITE(LOAD_HI_REG, 0); @@ -231,6 +225,17 @@ esp_err_t esp_timer_impl_init(intr_handler_t alarm_handler) REG_WRITE(ALARM_HI_REG, UINT32_MAX); REG_WRITE(LOAD_REG, 1); REG_SET_BIT(INT_CLR_REG, TIMG_LACT_INT_CLR); + REG_SET_FIELD(CONFIG_REG, TIMG_LACT_DIVIDER, APB_CLK_FREQ / 1000000 / TICKS_PER_US); + REG_SET_BIT(CONFIG_REG, TIMG_LACT_INCREASE | + TIMG_LACT_LEVEL_INT_EN | + TIMG_LACT_EN); + + return ESP_OK; +} + +esp_err_t esp_timer_impl_init(intr_handler_t alarm_handler) +{ + s_alarm_handler = alarm_handler; const int interrupt_lvl = (1 << CONFIG_ESP_TIMER_INTERRUPT_LEVEL) & ESP_INTR_FLAG_LEVELMASK; esp_err_t err = esp_intr_alloc(INTR_SOURCE_LACT, @@ -250,10 +255,6 @@ esp_err_t esp_timer_impl_init(intr_handler_t alarm_handler) esp_timer_impl_update_apb_freq(esp_clk_apb_freq() / 1000000); - REG_SET_BIT(CONFIG_REG, TIMG_LACT_INCREASE | - TIMG_LACT_LEVEL_INT_EN | - TIMG_LACT_EN); - // Set the step for the sleep mode when the timer will work // from a slow_clk frequency instead of the APB frequency. uint32_t slowclk_ticks_per_us = esp_clk_slowclk_cal_get() * TICKS_PER_US; diff --git a/components/esp_timer/src/esp_timer_impl_systimer.c b/components/esp_timer/src/esp_timer_impl_systimer.c index 28bdb07212..833e845460 100644 --- a/components/esp_timer/src/esp_timer_impl_systimer.c +++ b/components/esp_timer/src/esp_timer_impl_systimer.c @@ -72,9 +72,6 @@ uint64_t IRAM_ATTR esp_timer_impl_get_counter_reg(void) int64_t IRAM_ATTR esp_timer_impl_get_time(void) { - if (unlikely(s_alarm_handler == NULL)) { - return 0; - } return systimer_hal_get_counter_value(&systimer_hal, SYSTIMER_LL_COUNTER_CLOCK) / SYSTIMER_LL_TICKS_PER_US; } @@ -119,6 +116,23 @@ void esp_timer_impl_advance(int64_t time_us) portEXIT_CRITICAL_SAFE(&s_time_update_lock); } +esp_err_t esp_timer_impl_early_init(void) +{ + systimer_hal_init(&systimer_hal); + +#if !SOC_SYSTIMER_FIXED_TICKS_US + assert(rtc_clk_xtal_freq_get() == 40 && "update the step for xtal to support other XTAL:APB frequency ratios"); + systimer_hal_set_steps_per_tick(&systimer_hal, 0, 2); // for xtal + systimer_hal_set_steps_per_tick(&systimer_hal, 1, 1); // for pll +#endif + + systimer_hal_enable_counter(&systimer_hal, SYSTIMER_LL_COUNTER_CLOCK); + systimer_hal_select_alarm_mode(&systimer_hal, SYSTIMER_LL_ALARM_CLOCK, SYSTIMER_ALARM_MODE_ONESHOT); + systimer_hal_connect_alarm_counter(&systimer_hal, SYSTIMER_LL_ALARM_CLOCK, SYSTIMER_LL_COUNTER_CLOCK); + + return ESP_OK; +} + esp_err_t esp_timer_impl_init(intr_handler_t alarm_handler) { s_alarm_handler = alarm_handler; @@ -137,16 +151,6 @@ esp_err_t esp_timer_impl_init(intr_handler_t alarm_handler) goto err_intr_alloc; } - systimer_hal_init(&systimer_hal); -#if !SOC_SYSTIMER_FIXED_TICKS_US - assert(rtc_clk_xtal_freq_get() == 40 && "update the step for xtal to support other XTAL:APB frequency ratios"); - systimer_hal_set_steps_per_tick(&systimer_hal, 0, 2); // for xtal - systimer_hal_set_steps_per_tick(&systimer_hal, 1, 1); // for pll -#endif - systimer_hal_enable_counter(&systimer_hal, SYSTIMER_LL_COUNTER_CLOCK); - systimer_hal_select_alarm_mode(&systimer_hal, SYSTIMER_LL_ALARM_CLOCK, SYSTIMER_ALARM_MODE_ONESHOT); - systimer_hal_connect_alarm_counter(&systimer_hal, SYSTIMER_LL_ALARM_CLOCK, SYSTIMER_LL_COUNTER_CLOCK); - /* TODO: if SYSTIMER is used for anything else, access to SYSTIMER_INT_ENA_REG has to be * protected by a shared spinlock. Since this code runs as part of early startup, this * is practically not an issue. From 99caa4950cef8832bd1ecf770f4a65c81666b5d0 Mon Sep 17 00:00:00 2001 From: Cao Sen Miao Date: Wed, 20 Oct 2021 10:34:40 +0800 Subject: [PATCH 2/3] esp_timer: init rtc timer and system timer in early init --- components/esp_timer/include/esp_timer.h | 18 ++++-------- .../private_include/esp_timer_impl.h | 18 ++++-------- components/esp_timer/src/esp_timer.c | 28 +++++++------------ components/esp_timer/src/esp_timer_impl_lac.c | 18 ++++-------- .../esp_timer/src/esp_timer_impl_systimer.c | 18 ++++-------- 5 files changed, 30 insertions(+), 70 deletions(-) diff --git a/components/esp_timer/include/esp_timer.h b/components/esp_timer/include/esp_timer.h index 02f9379736..eb4c6d707a 100644 --- a/components/esp_timer/include/esp_timer.h +++ b/components/esp_timer/include/esp_timer.h @@ -1,16 +1,8 @@ -// Copyright 2017 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_timer/private_include/esp_timer_impl.h b/components/esp_timer/private_include/esp_timer_impl.h index 888461f9fa..d59a13eb13 100644 --- a/components/esp_timer/private_include/esp_timer_impl.h +++ b/components/esp_timer/private_include/esp_timer_impl.h @@ -1,16 +1,8 @@ -// Copyright 2017 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_timer/src/esp_timer.c b/components/esp_timer/src/esp_timer.c index 375cad6c4d..fbabcfda4a 100644 --- a/components/esp_timer/src/esp_timer.c +++ b/components/esp_timer/src/esp_timer.c @@ -1,16 +1,8 @@ -// Copyright 2017 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -430,7 +422,11 @@ static IRAM_ATTR inline bool is_initialized(void) esp_err_t esp_timer_early_init(void) { - return esp_timer_impl_early_init(); + esp_timer_impl_early_init(); +#if CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER + esp_timer_impl_init_system_time(); +#endif + return ESP_OK; } esp_err_t esp_timer_init(void) @@ -452,10 +448,6 @@ esp_err_t esp_timer_init(void) goto out; } -#if CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER - esp_timer_impl_init_system_time(); -#endif - return ESP_OK; out: diff --git a/components/esp_timer/src/esp_timer_impl_lac.c b/components/esp_timer/src/esp_timer_impl_lac.c index 13338f0874..a9c93ef0fe 100644 --- a/components/esp_timer/src/esp_timer_impl_lac.c +++ b/components/esp_timer/src/esp_timer_impl_lac.c @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "sys/param.h" #include "esp_timer_impl.h" diff --git a/components/esp_timer/src/esp_timer_impl_systimer.c b/components/esp_timer/src/esp_timer_impl_systimer.c index 833e845460..b279ab213d 100644 --- a/components/esp_timer/src/esp_timer_impl_systimer.c +++ b/components/esp_timer/src/esp_timer_impl_systimer.c @@ -1,16 +1,8 @@ -// Copyright 2017-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "sys/param.h" #include "esp_timer_impl.h" From deff19706f083a2e7eecb6d3bb289837093bc484 Mon Sep 17 00:00:00 2001 From: KonstantinKondrashov Date: Fri, 29 Oct 2021 17:32:28 +0800 Subject: [PATCH 3/3] spi_flash: No CPU release time for an erase operation when OS is not running During the early start, the virtual eFuse mode can call erase operations when OS is not yet running. Possible workaround: CONFIG_SPI_FLASH_YIELD_DURING_ERASE=n Fixed for the legacy flash driver as well. --- components/spi_flash/flash_ops.c | 5 +++- components/spi_flash/spi_flash_os_func_app.c | 26 ++++++++------------ 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/components/spi_flash/flash_ops.c b/components/spi_flash/flash_ops.c index 0ecb6866d3..d3b696c96a 100644 --- a/components/spi_flash/flash_ops.c +++ b/components/spi_flash/flash_ops.c @@ -51,6 +51,7 @@ #include "esp_flash.h" #include "esp_attr.h" #include "bootloader_flash.h" +#include "esp_compiler.h" esp_rom_spiflash_result_t IRAM_ATTR spi_flash_write_encrypted_chip(size_t dest_addr, const void *src, size_t size); @@ -254,7 +255,9 @@ static inline void IRAM_ATTR spi_flash_guard_op_unlock(void) static void IRAM_ATTR spi_flash_os_yield(void) { #ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE - vTaskDelay(CONFIG_SPI_FLASH_ERASE_YIELD_TICKS); + if (likely(xTaskGetSchedulerState() == taskSCHEDULER_RUNNING)) { + vTaskDelay(CONFIG_SPI_FLASH_ERASE_YIELD_TICKS); + } #endif } diff --git a/components/spi_flash/spi_flash_os_func_app.c b/components/spi_flash/spi_flash_os_func_app.c index c38f405acd..97033d1ab9 100644 --- a/components/spi_flash/spi_flash_os_func_app.c +++ b/components/spi_flash/spi_flash_os_func_app.c @@ -1,16 +1,8 @@ -// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include //For max/min @@ -24,7 +16,7 @@ #include "hal/spi_types.h" #include "sdkconfig.h" #include "esp_log.h" - +#include "esp_compiler.h" #include "esp_rom_sys.h" #include "driver/spi_common_internal.h" @@ -140,11 +132,13 @@ static IRAM_ATTR esp_err_t spi1_flash_os_check_yield(void *arg, uint32_t chip_st static IRAM_ATTR esp_err_t spi1_flash_os_yield(void *arg, uint32_t* out_status) { + if (likely(xTaskGetSchedulerState() == taskSCHEDULER_RUNNING)) { #ifdef CONFIG_SPI_FLASH_ERASE_YIELD_TICKS - vTaskDelay(CONFIG_SPI_FLASH_ERASE_YIELD_TICKS); + vTaskDelay(CONFIG_SPI_FLASH_ERASE_YIELD_TICKS); #else - vTaskDelay(1); + vTaskDelay(1); #endif + } on_spi1_yielded((spi1_app_func_arg_t*)arg); return ESP_OK; }