xtensa/esp32: Add real-time timer support for WiFi

This commit is contained in:
Dong Heng 2020-10-20 16:32:47 +08:00 committed by Alan Carvalho de Assis
parent d0966b800f
commit d86fd84a8e
7 changed files with 895 additions and 128 deletions

View File

@ -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

View File

@ -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

View File

@ -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 <nuttx/config.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <fcntl.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/irq.h>
#include <nuttx/kthread.h>
#include <nuttx/kmalloc.h>
#include <nuttx/semaphore.h>
#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);
}

View File

@ -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 <nuttx/config.h>
#include <stdint.h>
#include <sys/types.h>
#include <nuttx/list.h>
#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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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;
}