diff --git a/arch/xtensa/src/esp32/Kconfig b/arch/xtensa/src/esp32/Kconfig index 6ca1e6f8ee..e4836d56b6 100644 --- a/arch/xtensa/src/esp32/Kconfig +++ b/arch/xtensa/src/esp32/Kconfig @@ -25,6 +25,10 @@ config ESP32_DEFAULT_CPU_FREQ_MHZ default 160 if ESP32_DEFAULT_CPU_FREQ_160 default 240 if ESP32_DEFAULT_CPU_FREQ_240 +config ESP32_RT_TIMER + bool "Real-time Timer" + default n + menu "ESP32 Peripheral Selection" config ESP32_UART @@ -259,6 +263,8 @@ config ESP32_WIRELESS select NET select ARCH_PHY_INTERRUPT select ESP32_RNG + select ESP32_RT_TIMER + select ESP32_TIMER0 ---help--- No yet implemented @@ -665,4 +671,21 @@ config ESP32_WIFI_FS_MOUNTPT endmenu # ESP32_WIRELESS +menu "Real-Time Timer" + depends on ESP32_RT_TIMER + +config ESP32_RT_TIMER_TASK_NAME + string "Timer task name" + default "rt_timer" + +config ESP32_RT_TIMER_TASK_PRIORITY + int "Timer task priority" + default 223 # Lower than high priority workqueue + +config ESP32_RT_TIMER_TASK_STACK_SIZE + int "Timer task stack size" + default 2048 + +endmenu # Real-Time Timer + endif # ARCH_CHIP_ESP32 diff --git a/arch/xtensa/src/esp32/Make.defs b/arch/xtensa/src/esp32/Make.defs index cbb8c5141e..a43f537b69 100644 --- a/arch/xtensa/src/esp32/Make.defs +++ b/arch/xtensa/src/esp32/Make.defs @@ -158,6 +158,10 @@ CHIP_CSRCS += esp32_modtext.c CMN_ASRCS += xtensa_loadstore.S endif +ifeq ($(CONFIG_ESP32_RT_TIMER),y) +CHIP_CSRCS += esp32_rt_timer.c +endif + ifeq ($(CONFIG_ESP32_WIRELESS),y) WIRELESS_DRV_UNPACK = esp-wireless-drivers-3rdparty WIRELESS_DRV_ID = 5cb6561 diff --git a/arch/xtensa/src/esp32/esp32_rt_timer.c b/arch/xtensa/src/esp32/esp32_rt_timer.c new file mode 100644 index 0000000000..2696548cf5 --- /dev/null +++ b/arch/xtensa/src/esp32/esp32_rt_timer.c @@ -0,0 +1,576 @@ +/**************************************************************************** + * arch/xtensa/src/esp32/esp32_rt_timer.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this args for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "hardware/esp32_soc.h" +#include "esp32_tim.h" +#include "esp32_rt_timer.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_SCHED_HPWORKPRIORITY +# if CONFIG_ESP32_RT_TIMER_TASK_PRIORITY >= CONFIG_SCHED_HPWORKPRIORITY +# error "RT timer priority should be smaller that high-prio workqueue" +# endif +#endif + +#define RT_TIMER_TASK_NAME CONFIG_ESP32_RT_TIMER_TASK_NAME +#define RT_TIMER_TASK_PRIORITY CONFIG_ESP32_RT_TIMER_TASK_PRIORITY +#define RT_TIMER_TASK_STACK_SIZE CONFIG_ESP32_RT_TIMER_TASK_STACK_SIZE + +#define ESP32_TIMER_PRESCALER (APB_CLK_FREQ / (1000 * 1000)) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static int s_pid; + +static sem_t s_toutsem; + +static struct list_node s_runlist; +static struct list_node s_toutlist; + +static struct esp32_tim_dev_s *s_esp32_tim_dev; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: start_rt_timer + * + * Description: + * Start timer by inserting it into running list and reset hardware timer + * alarm value if this timer in head of list. + * + * Input Parameters: + * timer - RT timer pointer + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static void start_rt_timer(FAR struct rt_timer_s *timer) +{ + irqstate_t flags; + struct rt_timer_s *p; + bool inserted = false; + uint64_t counter; + struct esp32_tim_dev_s *tim = s_esp32_tim_dev; + + flags = enter_critical_section(); + + /* Check if timer is "not started" */ + + if (!timer->started) + { + /* Calculate the timer's alarm value */ + + ESP32_TIM_GETCTR(tim, &counter); + timer->alarm = timer->timeout + counter; + + /** Scan timer list and insert the new timer into previous + * node of timer whose alarm value is larger than new one + */ + + list_for_every_entry(&s_runlist, p, struct rt_timer_s, list) + { + if (p->alarm > timer->alarm) + { + list_add_before(&p->list, &timer->list); + inserted = true; + break; + } + } + + /* If not find a larger one, insert new timer into tail of list */ + + if (!inserted) + { + list_add_tail(&s_runlist, &timer->list); + } + + timer->started = true; + + /* If this timer is in head of list */ + + if (timer == container_of(s_runlist.next, struct rt_timer_s, list)) + { + /* Reset hardware timer alarm */ + + ESP32_TIM_SETALRVL(tim, timer->alarm); + ESP32_TIM_SETALRM(tim, true); + } + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: stop_rt_timer + * + * Description: + * Stop timer by removing it from running list and reset hardware timer + * alarm value if this timer is in head of list. + * + * Input Parameters: + * timer - RT timer pointer + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static void stop_rt_timer(FAR struct rt_timer_s *timer) +{ + irqstate_t flags; + bool ishead; + struct rt_timer_s *next_timer; + uint64_t alarm; + struct esp32_tim_dev_s *tim = s_esp32_tim_dev; + + flags = enter_critical_section(); + + /* Check if timer is "started" */ + + if (timer->started) + { + /* Check if timer is in head of list */ + + if (timer == container_of(s_runlist.next, struct rt_timer_s, list)) + { + ishead = true; + } + else + { + ishead = false; + } + + list_delete(&timer->list); + timer->started = false; + + /* If timer is in in head of list */ + + if (ishead) + { + /* If list is not empty */ + + if (!list_is_empty(&s_runlist)) + { + /* Reset hardware timer alarm value to be next timer's */ + + next_timer = container_of(s_runlist.next, + struct rt_timer_s, + list); + alarm = next_timer->alarm; + + ESP32_TIM_SETALRVL(tim, alarm); + ESP32_TIM_SETALRM(tim, true); + } + } + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: rt_timer_thread + * + * Description: + * RT timer working thread, it wait for a timeout semaphore, scan + * the timeout list and process all timers in this list. + * + * Input Parameters: + * argc - Not used + * argv - Not used + * + * Returned Value: + * 0. + * + ****************************************************************************/ + +static int rt_timer_thread(int argc, FAR char *argv[]) +{ + int ret; + irqstate_t flags; + struct rt_timer_s *timer; + + while (1) + { + /* Waiting for timers timeout */ + + ret = nxsem_wait(&s_toutsem); + if (ret) + { + tmrerr("ERROR: Wait s_toutsem error=%d\n", ret); + assert(0); + } + + /* Enter critical to check global timer timeout list */ + + flags = enter_critical_section(); + + /* Process all timers in list */ + + while (!list_is_empty(&s_toutlist)) + { + /* Get first timer in list */ + + timer = container_of(s_toutlist.next, struct rt_timer_s, list); + + /* Delete timer from list */ + + list_delete(&timer->list); + timer->started = false; + + /* Leave from critical to start to call "callback" function */ + + leave_critical_section(flags); + + timer->callback(timer->arg); + + /* Check if timer is repeat */ + + if (timer->flags & RT_TIMER_REPEAT) + { + /* Check if timer is "not started" */ + + if (timer->started == false) + { + /* Restart timer */ + + start_rt_timer(timer); + } + } + + /* Enter critical for next scaning list */ + + flags = enter_critical_section(); + } + + leave_critical_section(flags); + } + + return 0; +} + +/**************************************************************************** + * Name: rt_timer_isr + * + * Description: + * Hardware timer interrupt service function. + * + * Input Parameters: + * irq - Not used + * context - Not used + * arg - Not used + * + * Returned Value: + * 0. + * + ****************************************************************************/ + +static int rt_timer_isr(int irq, void *context, void *arg) +{ + irqstate_t flags; + struct rt_timer_s *timer; + uint64_t alarm; + struct esp32_tim_dev_s *tim = s_esp32_tim_dev; + + /* Clear interrupt register status */ + + ESP32_TIM_ACKINT(tim); + + /* Wake up thread to process timeout timers */ + + nxsem_post(&s_toutsem); + + flags = enter_critical_section(); + + /* Check if there is timer running */ + + if (!list_is_empty(&s_runlist)) + { + /* Remove first timer in running list and add it into timeout list */ + + timer = container_of(s_runlist.next, struct rt_timer_s, list); + list_delete(&timer->list); + timer->started = false; + list_add_after(&s_toutlist, &timer->list); + + /* Check if thers is timer running */ + + if (!list_is_empty(&s_runlist)) + { + /* Reset hardware timer alarm with next timer's alarm value */ + + timer = container_of(s_runlist.next, struct rt_timer_s, list); + alarm = timer->alarm; + + ESP32_TIM_SETALRVL(tim, alarm); + ESP32_TIM_SETALRM(tim, true); + } + } + + leave_critical_section(flags); + + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rt_timer_create + * + * Description: + * Create RT timer by into timer creation arguments + * + * Input Parameters: + * args - Input RT timer creation arguments + * timer_handle - Output RT timer handle pointer + * + * Returned Value: + * 0 is returned on success. Otherwise, a negated errno value is returned. + * + ****************************************************************************/ + +int rt_timer_create(FAR const struct rt_timer_args_s *args, + FAR struct rt_timer_s **timer_handle) +{ + struct rt_timer_s *timer; + + timer = (struct rt_timer_s *)kmm_malloc(sizeof(*timer)); + if (!timer) + { + tmrerr("ERROR: Failed to allocate %d bytes\n", sizeof(*timer)); + return -ENOMEM; + } + + timer->callback = args->callback; + timer->arg = args->arg; + timer->flags = RT_TIMER_NOFLAGS; + timer->started = false; + list_initialize(&timer->list); + + *timer_handle = timer; + + return 0; +} + +/**************************************************************************** + * Name: rt_timer_start + * + * Description: + * Start RT timer. + * + * Input Parameters: + * timer - RT timer pointer + * timeout - Timeout value + * repeat - If the timer run repeat + * + * Returned Value: + * None + * + ****************************************************************************/ + +void rt_timer_start(FAR struct rt_timer_s *timer, + uint32_t timeout, + bool repeat) +{ + stop_rt_timer(timer); + + if (repeat) + { + timer->flags |= RT_TIMER_REPEAT; + } + else + { + timer->flags &= ~RT_TIMER_REPEAT; + } + + timer->timeout = timeout; + + start_rt_timer(timer); +} + +/**************************************************************************** + * Name: rt_timer_stop + * + * Description: + * Stop RT timer. + * + * Input Parameters: + * timer - RT timer pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +void rt_timer_stop(FAR struct rt_timer_s *timer) +{ + stop_rt_timer(timer); +} + +/**************************************************************************** + * Name: rt_timer_delete + * + * Description: + * Stop and deleta RT timer. + * + * Input Parameters: + * timer - RT timer pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +void rt_timer_delete(FAR struct rt_timer_s *timer) +{ + stop_rt_timer(timer); + + kmm_free(timer); +} + +/**************************************************************************** + * Name: esp32_rt_timer_init + * + * Description: + * Initialize ESP32 RT timer. + * + * Input Parameters: + * timer_no - Hardware timer number + * + * Returned Value: + * 0 is returned on success. Otherwise, a negated errno value is returned. + * + ****************************************************************************/ + +int esp32_rt_timer_init(void) +{ + int pid; + irqstate_t flags; + struct esp32_tim_dev_s *tim; + + tim = esp32_tim0_init(); + if (!tim) + { + tmrerr("ERROR: Failed to initialize ESP32 timer0\n"); + return -EINVAL; + } + + nxsem_init(&s_toutsem, 0, 0); + + pid = kthread_create(RT_TIMER_TASK_NAME, + RT_TIMER_TASK_PRIORITY, + RT_TIMER_TASK_STACK_SIZE, + rt_timer_thread, + NULL); + if (pid < 0) + { + tmrerr("ERROR: Failed to create RT timer task error=%d\n", pid); + esp32_tim_deinit(tim); + return pid; + } + + list_initialize(&s_runlist); + list_initialize(&s_toutlist); + + s_esp32_tim_dev = tim; + s_pid = pid; + + flags = enter_critical_section(); + + /** + * ESP32 hardware timer configuration: + * - 1 counter = 1us + * - Counter increase mode + * - Non-reload mode + */ + + ESP32_TIM_SETPRE(tim, ESP32_TIMER_PRESCALER); + ESP32_TIM_SETMODE(tim, ESP32_TIM_MODE_UP); + ESP32_TIM_SETARLD(tim, false); + ESP32_TIM_CLEAR(tim); + + ESP32_TIM_SETISR(tim, rt_timer_isr, NULL); + ESP32_TIM_ENABLEINT(tim); + + ESP32_TIM_START(tim); + + leave_critical_section(flags); + + return 0; +} + +/**************************************************************************** + * Name: esp32_rt_timer_deinit + * + * Description: + * Deinitialize ESP32 RT timer. + * + * Input Parameters: + * None + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void esp32_rt_timer_deinit(void) +{ + irqstate_t flags; + + flags = enter_critical_section(); + + ESP32_TIM_STOP(s_esp32_tim_dev); + s_esp32_tim_dev = NULL; + + leave_critical_section(flags); + + kthread_delete(s_pid); + nxsem_destroy(&s_toutsem); +} diff --git a/arch/xtensa/src/esp32/esp32_rt_timer.h b/arch/xtensa/src/esp32/esp32_rt_timer.h new file mode 100644 index 0000000000..9e60d66de8 --- /dev/null +++ b/arch/xtensa/src/esp32/esp32_rt_timer.h @@ -0,0 +1,178 @@ +/**************************************************************************** + * arch/xtensa/src/esp32/esp32_rt_timer.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +#ifndef __ARCH_XTENSA_SRC_ESP32_ESP32_RT_TIMER_H +#define __ARCH_XTENSA_SRC_ESP32_ESP32_RT_TIMER_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#define RT_TIMER_NOFLAGS (0) /* Timer support no feature */ +#define RT_TIMER_REPEAT (1 << 0) /* Timer is repeat */ + +/** + * RT timer data structure + */ + +struct rt_timer_s +{ + uint32_t timeout; /* Timeout value */ + uint64_t alarm; /* Timeout period */ + void (*callback)(void *arg); /* Callback function */ + void *arg; /* Private data */ + uint16_t flags; /* Support feature */ + bool started; /* Mark if timer is started */ + struct list_node list; /* Working list */ +}; + +/** + * RT timer creation arguments data structure + */ + +struct rt_timer_args_s +{ + void (*callback)(void *arg); /* Callback function */ + void *arg; /* Private data */ +}; + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: rt_timer_create + * + * Description: + * Create RT timer by into timer creation arguments + * + * Input Parameters: + * args - Input RT timer creation arguments + * timer_handle - Output RT timer handle pointer + * + * Returned Value: + * 0 is returned on success. Otherwise, a negated errno value is returned. + * + ****************************************************************************/ + +int rt_timer_create(FAR const struct rt_timer_args_s *args, + FAR struct rt_timer_s **timer_handle); + +/**************************************************************************** + * Name: rt_timer_start + * + * Description: + * Start RT timer. + * + * Input Parameters: + * timer - RT timer pointer + * timeout - Timeout value + * repeat - If the timer run repeat + * + * Returned Value: + * None + * + ****************************************************************************/ + +void rt_timer_start(FAR struct rt_timer_s *timer, + uint32_t timeout, + bool repeat); + +/**************************************************************************** + * Name: rt_timer_stop + * + * Description: + * Stop RT timer. + * + * Input Parameters: + * timer - RT timer pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +void rt_timer_stop(FAR struct rt_timer_s *timer); + +/**************************************************************************** + * Name: rt_timer_delete + * + * Description: + * Stop and deleta RT timer. + * + * Input Parameters: + * timer - RT timer pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +void rt_timer_delete(FAR struct rt_timer_s *timer); + +/**************************************************************************** + * Name: esp32_rt_timer_init + * + * Description: + * Initialize ESP32 RT timer. + * + * Input Parameters: + * None + * + * Returned Value: + * 0 is returned on success. Otherwise, a negated errno value is returned. + * + ****************************************************************************/ + +int esp32_rt_timer_init(void); + +/**************************************************************************** + * Name: esp32_rt_timer_deinit + * + * Description: + * Deinitialize ESP32 RT timer. + * + * Input Parameters: + * None + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void esp32_rt_timer_deinit(void); + +#ifdef __cplusplus +} +#endif +#undef EXTERN + +#endif /* __ARCH_XTENSA_SRC_ESP32_ESP32_RT_TIMER_H */ diff --git a/arch/xtensa/src/esp32/esp32_tim.c b/arch/xtensa/src/esp32/esp32_tim.c index 364592926b..b0f21bad12 100644 --- a/arch/xtensa/src/esp32/esp32_tim.c +++ b/arch/xtensa/src/esp32/esp32_tim.c @@ -834,7 +834,9 @@ static int esp32_tim_ackint(FAR struct esp32_tim_dev_s *dev) * Name: esp32_tim_init * * Description: - * Initialize TIMER device + * Initialize TIMER device, if software real-time timer + * (CONFIG_ESP32_RT_TIMER) is enable, then timer0 can't + * be initialized by this function directly. * ****************************************************************************/ @@ -846,7 +848,7 @@ FAR struct esp32_tim_dev_s *esp32_tim_init(int timer) switch (timer) { -#ifdef CONFIG_ESP32_TIMER0 +#if defined(CONFIG_ESP32_TIMER0) && !defined(CONFIG_ESP32_RT_TIMER) case 0: { tim = &g_esp32_tim0_priv; @@ -915,3 +917,29 @@ int esp32_tim_deinit(FAR struct esp32_tim_dev_s *dev) return OK; } + +/**************************************************************************** + * Name: esp32_tim0_init + * + * Description: + * Initialize TIMER0 device, this function is only used by software + * real-time timer(esp32_rt_timer.c). + * + ****************************************************************************/ + +#ifdef CONFIG_ESP32_RT_TIMER + +FAR struct esp32_tim_dev_s *esp32_tim0_init(void) +{ + FAR struct esp32_tim_priv_s *tim = &g_esp32_tim0_priv; + + if (tim->inuse == true) + { + tmrerr("ERROR: TIMER %d is already in use\n", timer); + tim = NULL; + } + + return (FAR struct esp32_tim_dev_s *)tim; +} + +#endif /* CONFIG_ESP32_RT_TIMER */ diff --git a/arch/xtensa/src/esp32/esp32_tim.h b/arch/xtensa/src/esp32/esp32_tim.h index c92c7a126e..2e3ee5aa96 100644 --- a/arch/xtensa/src/esp32/esp32_tim.h +++ b/arch/xtensa/src/esp32/esp32_tim.h @@ -123,5 +123,6 @@ struct esp32_tim_ops_s FAR struct esp32_tim_dev_s *esp32_tim_init(int timer); int esp32_tim_deinit(FAR struct esp32_tim_dev_s *dev); +FAR struct esp32_tim_dev_s *esp32_tim0_init(void); #endif /* __ARCH_XTENSA_SRC_ESP32_ESP32_TIM_H */ diff --git a/arch/xtensa/src/esp32/esp32_wifi_adapter.c b/arch/xtensa/src/esp32/esp32_wifi_adapter.c index c8fe5d55f1..859eda40b2 100644 --- a/arch/xtensa/src/esp32/esp32_wifi_adapter.c +++ b/arch/xtensa/src/esp32/esp32_wifi_adapter.c @@ -51,6 +51,7 @@ #include "hardware/esp32_emac.h" #include "esp32_cpuint.h" #include "esp32_wifi_adapter.h" +#include "esp32_rt_timer.h" #include "espidf_wifi.h" @@ -68,6 +69,8 @@ #define WIFI_CONNECT_TIMEOUT CONFIG_ESP32_WIFI_CONNECT_TIMEOUT +#define TIMER_INITIALIZED_VAL (0x5aa5a55a) + /**************************************************************************** * Private Types ****************************************************************************/ @@ -209,7 +212,6 @@ static void esp_timer_arm(void *timer, uint32_t tmout, bool repeat); static void esp_timer_disarm(void *timer); static void esp32_timer_done(void *timer); static void esp_timer_setfn(void *timer, void *pfunction, void *parg); -static void esp_timer_cb(wdparm_t parm); static void esp_timer_arm_us(void *timer, uint32_t us, bool repeat); static void esp_periph_module_enable(uint32_t periph); static void esp_periph_module_disable(uint32_t periph); @@ -2333,15 +2335,12 @@ static void esp_timer_arm(void *ptimer, uint32_t ms, bool repeat) static void esp_timer_disarm(void *ptimer) { - struct timer_adpt *timer_adpt; struct ets_timer *ets_timer = (struct ets_timer *)ptimer; + esp_timer_handle_t esp_timer = (esp_timer_handle_t)ets_timer->priv; - if (ets_timer->priv) + if (ets_timer->expire == TIMER_INITIALIZED_VAL) { - timer_adpt = (struct timer_adpt *)ets_timer->priv; - - wd_cancel(&timer_adpt->wdog); - work_cancel(LPWORK, &timer_adpt->work); + esp_timer_stop(esp_timer); } } @@ -2361,18 +2360,13 @@ static void esp_timer_disarm(void *ptimer) static void esp32_timer_done(void *ptimer) { - struct timer_adpt *timer_adpt; struct ets_timer *ets_timer = (struct ets_timer *)ptimer; + esp_timer_handle_t esp_timer = (esp_timer_handle_t)ets_timer->priv; - if (ets_timer->priv) + if (ets_timer->expire == TIMER_INITIALIZED_VAL) { - timer_adpt = (struct timer_adpt *)ets_timer->priv; - - wd_cancel(&timer_adpt->wdog); - work_cancel(LPWORK, &timer_adpt->work); - - kmm_free(timer_adpt); - + ets_timer->expire = 0; + esp_timer_delete(esp_timer); ets_timer->priv = NULL; } } @@ -2395,79 +2389,36 @@ static void esp32_timer_done(void *ptimer) static void esp_timer_setfn(void *ptimer, void *pfunction, void *parg) { - struct timer_adpt *timer_adpt; + int ret; + esp_timer_handle_t esp_timer; struct ets_timer *ets_timer = (struct ets_timer *)ptimer; - if (ets_timer->priv) + if (ets_timer->expire != TIMER_INITIALIZED_VAL) { - return ; + ets_timer->priv = NULL; } - timer_adpt = kmm_zalloc(sizeof(struct timer_adpt)); - if (!timer_adpt) + if (ets_timer->priv == NULL) { - wlerr("ERROR: Failed to malloc\n"); - return ; + const esp_timer_create_args_t create_args = + { + .callback = pfunction, + .arg = parg, + .name = "ETSTimer", + .dispatch_method = ESP_TIMER_TASK + }; + + ret = esp_timer_create(&create_args, &esp_timer); + if (ret) + { + wlerr("ERROR: Failed to create ets_timer error=%d\n", ret); + } + else + { + ets_timer->priv = esp_timer; + ets_timer->expire = TIMER_INITIALIZED_VAL; + } } - - timer_adpt->func = pfunction; - timer_adpt->priv = parg; - - ets_timer->priv = timer_adpt; -} - -/**************************************************************************** - * Name: esp_timer_work_cb - * - * Description: - * Process timer callback function in workqueue and active - * it if it has repeat flag - * - * Input Parameters: - * arg - Timer data pointer - * - * Returned Value: - * None - * - ****************************************************************************/ - -static void esp_timer_work_cb(FAR void *arg) -{ - struct ets_timer *ets_timer = (struct ets_timer *)arg; - struct timer_adpt *timer_adpt = - (struct timer_adpt *)ets_timer->priv; - - timer_adpt->func(timer_adpt->priv); - if (timer_adpt->repeat) - { - wd_start(&timer_adpt->wdog, timer_adpt->delay, - esp_timer_cb, (wdparm_t)ets_timer); - } -} - -/**************************************************************************** - * Name: esp_timer_cb - * - * Description: - * Post event to work queue and let work queue to process the timer's - * real callback function - * - * Input Parameters: - * parm - Timer data pointer - * - * Returned Value: - * None - * - ****************************************************************************/ - -static void esp_timer_cb(wdparm_t parm) -{ - struct ets_timer *ets_timer = (struct ets_timer *)parm; - struct timer_adpt *timer_adpt = - (struct timer_adpt *)ets_timer->priv; - - work_queue(LPWORK, &timer_adpt->work, - esp_timer_work_cb, ets_timer, 0); } /**************************************************************************** @@ -2488,23 +2439,28 @@ static void esp_timer_cb(wdparm_t parm) static void esp_timer_arm_us(void *ptimer, uint32_t us, bool repeat) { - uint32_t delay; - struct timer_adpt *timer_adpt; + int ret; struct ets_timer *ets_timer = (struct ets_timer *)ptimer; + esp_timer_handle_t esp_timer = (esp_timer_handle_t)ets_timer->priv; - if (ets_timer->priv) + if (ets_timer->expire == TIMER_INITIALIZED_VAL) { - timer_adpt = (struct timer_adpt *)ets_timer->priv; + esp_timer_stop(esp_timer); + if (!repeat) + { + ret = esp_timer_start_once(esp_timer, us); + } + else + { + ret = esp_timer_start_periodic(esp_timer, us); + } - wd_cancel(&timer_adpt->wdog); - work_cancel(LPWORK, &timer_adpt->work); - - delay = USEC2TICK(us); - timer_adpt->repeat = (uint32_t)repeat; - timer_adpt->delay = delay; - - wd_start(&timer_adpt->wdog, delay, - esp_timer_cb, (wdparm_t)ets_timer); + if (ret) + { + wlerr("ERROR: Fail to start %s timer error%d\n", + repeat ? "periodic" : "once", + ret); + } } } @@ -3861,23 +3817,21 @@ int net80211_printf(const char *format, ...) int32_t esp_timer_create(const esp_timer_create_args_t *create_args, esp_timer_handle_t *out_handle) { - struct ets_timer *ets_timer; + int ret; + struct rt_timer_args_s rt_timer_args; + struct rt_timer_s *rt_timer; - ets_timer = kmm_zalloc(sizeof(struct ets_timer)); - if (!ets_timer) + rt_timer_args.arg = create_args->arg; + rt_timer_args.callback = create_args->callback; + + ret = rt_timer_create(&rt_timer_args, &rt_timer); + if (ret) { - wlerr("ERROR: Failed to malloc\n"); - return -1; + wlerr("ERROR: Failed to create rt_timer error=%d\n", ret); + return ret; } - esp_timer_setfn(ets_timer, create_args->callback, create_args->arg); - if (!ets_timer->priv) - { - wlerr("ERROR: Failed to set timer func\n"); - return -1; - } - - *out_handle = (esp_timer_handle_t)ets_timer; + *out_handle = (esp_timer_handle_t)rt_timer; return 0; } @@ -3899,9 +3853,11 @@ int32_t esp_timer_create(const esp_timer_create_args_t *create_args, int32_t esp_timer_start_once(esp_timer_handle_t timer, uint64_t timeout_us) { - struct ets_timer *ets_timer = (struct ets_timer *)timer; + struct rt_timer_s *rt_timer = (struct rt_timer_s *)timer; - esp_timer_arm_us(ets_timer, timeout_us, false); + DEBUGASSERT(timeout_us <= UINT32_MAX); + + rt_timer_start(rt_timer, timeout_us, false); return 0; } @@ -3923,9 +3879,11 @@ int32_t esp_timer_start_once(esp_timer_handle_t timer, uint64_t timeout_us) int32_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period) { - struct ets_timer *ets_timer = (struct ets_timer *)timer; + struct rt_timer_s *rt_timer = (struct rt_timer_s *)timer; - esp_timer_arm_us(ets_timer, period, true); + DEBUGASSERT(period <= UINT32_MAX); + + rt_timer_start(rt_timer, period, true); return 0; } @@ -3946,9 +3904,9 @@ int32_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period) int32_t esp_timer_stop(esp_timer_handle_t timer) { - struct ets_timer *ets_timer = (struct ets_timer *)timer; + struct rt_timer_s *rt_timer = (struct rt_timer_s *)timer; - esp_timer_disarm(ets_timer); + rt_timer_stop(rt_timer); return 0; } @@ -3969,10 +3927,9 @@ int32_t esp_timer_stop(esp_timer_handle_t timer) int32_t esp_timer_delete(esp_timer_handle_t timer) { - struct ets_timer *ets_timer = (struct ets_timer *)timer; + struct rt_timer_s *rt_timer = (struct rt_timer_s *)timer; - esp32_timer_done(ets_timer); - kmm_free(ets_timer); + rt_timer_delete(rt_timer); return 0; } @@ -4288,20 +4245,20 @@ int esp_wifi_adapter_init(void) init_cfg.nvs_enable = 0; #endif + ret = esp32_rt_timer_init(); + if (ret < 0) + { + wlerr("ERROR: Failed to initialize RT timer error=%d\n", ret); + sem_destroy(&s_connect_sem); + return -1; + } + ret = esp_wifi_init(&init_cfg); if (ret) { wlerr("ERROR: Failed to initialize WiFi error=%d\n", ret); sem_destroy(&s_connect_sem); - return -1; - } - - ret = esp_wifi_set_ps(WIFI_PS_NONE); - if (ret) - { - wlerr("ERROR: Failed to close power save, error=%d\n", ret); - esp_wifi_deinit(); - sem_destroy(&s_connect_sem); + esp32_rt_timer_deinit(); return -1; }