xtensa/esp32: Add real-time timer support for WiFi
This commit is contained in:
parent
d0966b800f
commit
d86fd84a8e
@ -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
|
||||
|
@ -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
|
||||
|
576
arch/xtensa/src/esp32/esp32_rt_timer.c
Normal file
576
arch/xtensa/src/esp32/esp32_rt_timer.c
Normal 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);
|
||||
}
|
178
arch/xtensa/src/esp32/esp32_rt_timer.h
Normal file
178
arch/xtensa/src/esp32/esp32_rt_timer.h
Normal 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 */
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user