From b5fe84a250836b77cda083b6de5d210276306b05 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 | 25 +++++++++++++------ 6 files changed, 68 insertions(+), 20 deletions(-) diff --git a/components/esp_system/startup.c b/components/esp_system/startup.c index 42cc6765ac..5007b3e55a 100644 --- a/components/esp_system/startup.c +++ b/components/esp_system/startup.c @@ -244,7 +244,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) @@ -268,6 +267,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 3b594c785f..9e76c0c4c2 100644 --- a/components/esp_timer/include/esp_timer.h +++ b/components/esp_timer/include/esp_timer.h @@ -85,11 +85,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 6a77dab9df..bcecc21ef0 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 b9b6308f69..873739f87b 100644 --- a/components/esp_timer/src/esp_timer.c +++ b/components/esp_timer/src/esp_timer.c @@ -364,6 +364,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 f8ca8d5461..819c79dc50 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; } @@ -207,13 +204,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); @@ -221,6 +215,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; esp_err_t err = esp_intr_alloc(INTR_SOURCE_LACT, ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_IRAM, @@ -239,10 +244,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 3272fad348..39149d85ac 100644 --- a/components/esp_timer/src/esp_timer_impl_systimer.c +++ b/components/esp_timer/src/esp_timer_impl_systimer.c @@ -65,9 +65,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 systimer_hal_get_time(SYSTIMER_COUNTER_0); } @@ -100,6 +97,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; @@ -117,11 +131,6 @@ esp_err_t esp_timer_impl_init(intr_handler_t alarm_handler) goto err_intr_alloc; } - systimer_hal_init(); - systimer_hal_enable_counter(SYSTIMER_COUNTER_0); - systimer_hal_select_alarm_mode(SYSTIMER_ALARM_2, SYSTIMER_ALARM_MODE_ONESHOT); - systimer_hal_connect_alarm_counter(SYSTIMER_ALARM_2, SYSTIMER_COUNTER_0); - /* 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 173f7e87aa33df496781a4431e81fbed412fa643 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 9e76c0c4c2..762bb0b77d 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 bcecc21ef0..f2cd26fe86 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 873739f87b..e83a3c4398 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 @@ -366,7 +358,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) @@ -388,10 +384,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 819c79dc50..8b48d04258 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 39149d85ac..21f60c3b46 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 "esp_timer_impl.h" #include "esp_err.h" From b0c1ceca06c378f11f33e6c3f79dfabff4efaaf4 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. --- .../esp_timer/src/esp_timer_impl_systimer.c | 14 +++------- components/spi_flash/flash_ops.c | 5 +++- components/spi_flash/spi_flash_os_func_app.c | 26 +++++++------------ 3 files changed, 18 insertions(+), 27 deletions(-) diff --git a/components/esp_timer/src/esp_timer_impl_systimer.c b/components/esp_timer/src/esp_timer_impl_systimer.c index 21f60c3b46..13656c4235 100644 --- a/components/esp_timer/src/esp_timer_impl_systimer.c +++ b/components/esp_timer/src/esp_timer_impl_systimer.c @@ -91,17 +91,11 @@ void esp_timer_impl_advance(int64_t time_us) esp_err_t esp_timer_impl_early_init(void) { - systimer_hal_init(&systimer_hal); + systimer_hal_init(); -#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); + systimer_hal_enable_counter(SYSTIMER_COUNTER_0); + systimer_hal_select_alarm_mode(SYSTIMER_ALARM_2, SYSTIMER_ALARM_MODE_ONESHOT); + systimer_hal_connect_alarm_counter(SYSTIMER_ALARM_2, SYSTIMER_COUNTER_0); return ESP_OK; } diff --git a/components/spi_flash/flash_ops.c b/components/spi_flash/flash_ops.c index 544860b7e1..5a8c689c2d 100644 --- a/components/spi_flash/flash_ops.c +++ b/components/spi_flash/flash_ops.c @@ -50,6 +50,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); @@ -230,7 +231,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 f3ea7c8fab..2cdce6c2c4 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; }