Merge branch 'bugfix/esp_timer_before_init' into 'master'

esp_timer: allow querying the timer before esp_timer_init is called

Closes IDF-3570

See merge request espressif/esp-idf!14428
This commit is contained in:
Cao Sen Miao 2021-10-27 05:49:06 +00:00
commit bd2a524a12
7 changed files with 97 additions and 99 deletions

View File

@ -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();

View File

@ -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
@ -83,11 +75,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

View File

@ -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
@ -28,9 +20,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);

View File

@ -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 <sys/param.h>
#include <string.h>
@ -428,6 +420,15 @@ static IRAM_ATTR inline bool is_initialized(void)
return s_timer_task != NULL;
}
esp_err_t esp_timer_early_init(void)
{
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)
{
esp_err_t err;
@ -447,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:

View File

@ -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"
@ -146,9 +138,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 +206,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 +217,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 +247,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;

View File

@ -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"
@ -72,9 +64,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 +108,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 +143,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.

View File

@ -1157,12 +1157,7 @@ components/esp_system/test_eh_frame_parser/linker.ld
components/esp_system/test_eh_frame_parser/main.c
components/esp_system/ubsan.c
components/esp_timer/include/esp_private/esp_timer_private.h
components/esp_timer/include/esp_timer.h
components/esp_timer/private_include/esp_timer_impl.h
components/esp_timer/src/esp_timer.c
components/esp_timer/src/esp_timer_impl_frc_legacy.c
components/esp_timer/src/esp_timer_impl_lac.c
components/esp_timer/src/esp_timer_impl_systimer.c
components/esp_timer/src/ets_timer_legacy.c
components/esp_timer/src/system_time.c
components/esp_timer/test/test_esp_timer.c