risc-v/esp32-c3: Adds oneshot timer driver.

This commit is contained in:
Sara Souza 2021-04-12 14:37:05 -03:00 committed by Abdelatif Guettouche
parent ae42005712
commit 7a80cbf93f
10 changed files with 1185 additions and 38 deletions

View File

@ -341,6 +341,19 @@ config ESP32C3_RT_TIMER_TASK_STACK_SIZE
endmenu # Real-Time Timer
if ESP32C3_TIMER
menu "Timer/counter Configuration"
config ESP32C3_ONESHOT
bool "One-shot wrapper"
default n
---help---
Enable a wrapper around the low level timer/counter functions to
support one-shot timer.
endmenu # Timer/counter Configuration
endif # ESP32C3_TIMER
menu "Wi-Fi configuration"
depends on ESP32C3_WIRELESS

View File

@ -85,6 +85,13 @@ CHIP_CSRCS += esp32c3_tim_lowerhalf.c
endif
endif
ifeq ($(CONFIG_ESP32C3_ONESHOT),y)
CHIP_CSRCS += esp32c3_oneshot.c
ifeq ($(CONFIG_ONESHOT),y)
CHIP_CSRCS += esp32c3_oneshot_lowerhalf.c
endif
endif
ifeq ($(CONFIG_ESP32C3_RT_TIMER),y)
CHIP_CSRCS += esp32c3_rt_timer.c
endif

View File

@ -0,0 +1,456 @@
/****************************************************************************
* arch/risc-v/src/esp32c3/esp32c3_oneshot.c
*
* 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <nuttx/timers/oneshot.h>
#include <nuttx/clock.h>
#include "hardware/esp32c3_soc.h"
#include "esp32c3_tim.h"
#include "esp32c3_clockconfig.h"
#include "esp32c3_oneshot.h"
#ifdef CONFIG_ESP32C3_ONESHOT
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define MAX_TIMER_COUNTER() ((uint64_t)1 << 53) /* 2^53 */
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static int esp32c3_oneshot_handler(int irq, void * context, void *arg);
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: esp32c3_oneshot_handler
*
* Description:
* Oneshot interrupt Handler. When any oneshot timer interrupt
* expires, this function will be triggered. It will forward the call to
* the next level up.
*
* Input Parameters:
* irq - IRQ associated to that interrupt
* arg - A pointer to the argument provided when the interrupt was
* registered.
*
* Returned Value:
* Zero on success; a negated errno value on failure.
*
****************************************************************************/
static int esp32c3_oneshot_handler(int irq, void * context, void *arg)
{
int ret = OK;
struct esp32c3_oneshot_s *oneshot = (struct esp32c3_oneshot_s *)arg;
DEBUGASSERT(oneshot != NULL && oneshot->handler != NULL);
tmrinfo("Oneshot handler triggered\n");
/* Stop timer
* Note: It's not necessary to disable the alarm because
* it automatically disables each time it expires.
*/
ESP32C3_TIM_STOP(oneshot->tim);
/* Disable interrupts */
ESP32C3_TIM_DISABLEINT(oneshot->tim);
/* Detach handler */
ret = ESP32C3_TIM_SETISR(oneshot->tim, NULL, NULL);
/* Call the callback */
oneshot->handler((void *)oneshot->arg);
/* Restore state */
oneshot->running = false;
oneshot->handler = NULL;
oneshot->arg = NULL;
/* Clear the Interrupt */
ESP32C3_TIM_ACKINT(oneshot->tim);
return ret;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: esp32c3_oneshot_initialize
*
* Description:
* Initialize the oneshot timer wrapper.
*
* Input Parameters:
* oneshot Caller allocated instance of the oneshot state structure.
* chan Timer counter channel to be used.
* resolution The required resolution of the timer in units of
* microseconds. NOTE that the range is restricted to the
* range of uint16_t (excluding zero).
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
int esp32c3_oneshot_initialize(struct esp32c3_oneshot_s *oneshot, int chan,
uint16_t resolution)
{
int ret = OK;
tmrinfo("chan=%d resolution=%d usecs\n", chan, resolution);
DEBUGASSERT(oneshot != NULL);
DEBUGASSERT(resolution > 0);
oneshot->chan = chan;
oneshot->tim = esp32c3_tim_init(chan);
if (oneshot->tim == NULL)
{
tmrerr("ERROR: Failed to allocate TIM %d\n", chan);
ret = -EBUSY;
}
else
{
uint16_t pre;
/* Initialize the remaining fields in the state structure. */
oneshot->running = false;
oneshot->handler = NULL;
oneshot->arg = NULL;
oneshot->resolution = resolution;
/* Ensure timer is disabled.
* Change the prescaler divider with the timer enabled can lead to
* unpredictable results.
*/
ESP32C3_TIM_STOP(oneshot->tim);
/* Calculate the suitable prescaler according to the current apb
* frequency to generate a period equals to resolution.
*/
pre = (esp32c3_clk_apb_freq() * resolution) / USEC_PER_SEC;
/* Configure TIMER prescaler */
ESP32C3_TIM_SETPRE(oneshot->tim, pre);
}
return ret;
}
/****************************************************************************
* Name: esp32c3_oneshot_max_delay
*
* Description:
* Return the maximum delay supported by the timer.
*
* Input Parameters:
* oneshot Caller allocated instance of the oneshot state structure. This
* structure must have been previously initialized via a call to
* esp32c3_oneshot_initialize();
* usec The maximum delay in us.
*
* Returned Value:
* Zero (OK).
*
****************************************************************************/
int esp32c3_oneshot_max_delay(struct esp32c3_oneshot_s *oneshot,
uint64_t *usec)
{
DEBUGASSERT(oneshot != NULL && usec != NULL);
/* In theory, Maximum delay (us) = resolution (us) * MAX_TIMER_COUNTER
* But if the resolution is bigger than 1 us, the value will not fit
* in a uint64_t. So, this function assumes the max delay using a
* resolution of 1 us.
*/
*usec = MAX_TIMER_COUNTER();
return OK;
}
/****************************************************************************
* Name: esp32c3_oneshot_start
*
* Description:
* Start the oneshot timer
*
* Input Parameters:
* oneshot Caller allocated instance of the oneshot state structure. This
* structure must have been previously initialized via a call to
* esp32c3_oneshot_initialize();
* handler The function to call when when the oneshot timer expires.
* arg An opaque argument that will accompany the callback.
* ts Provides the duration of the one shot timer.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
int esp32c3_oneshot_start(struct esp32c3_oneshot_s *oneshot,
oneshot_handler_t handler, void *arg,
const struct timespec *ts)
{
uint64_t timeout_us;
int ret = OK;
tmrinfo("handler=%p arg=%p, ts=(%lu, %lu)\n",
handler, arg, (unsigned long)ts->tv_sec,
(unsigned long)ts->tv_nsec);
DEBUGASSERT(oneshot != NULL);
DEBUGASSERT(handler != NULL);
DEBUGASSERT(ts != NULL);
if (oneshot->running)
{
tmrinfo("One shot timer already in use. Cancelling it ...\n");
/* If the oneshot timer was already started, cancel it and then
* restart.
*/
esp32c3_oneshot_cancel(oneshot, NULL);
}
/* Save the new callback and its argument */
oneshot->handler = handler;
oneshot->arg = arg;
/* Retrieve the duration from timespec in microsecond */
timeout_us = (uint64_t)ts->tv_sec * USEC_PER_SEC +
(uint64_t)(ts->tv_nsec / NSEC_PER_USEC);
/* Verify if it is a multiple of the configured resolution.
* In case it isn't, warn the user.
*/
if ((timeout_us % oneshot->resolution) != 0)
{
tmrwarn("Warning: The interval is not multiple of the resolution.\n"
"Adjust the resolution in your bringup file.\n");
}
/* Set the timer */
/* Ensure timer is stopped */
ESP32C3_TIM_STOP(oneshot->tim);
/* Configure TIMER mode */
ESP32C3_TIM_SETMODE(oneshot->tim, ESP32C3_TIM_MODE_UP);
/* Clear TIMER counter value */
ESP32C3_TIM_CLEAR(oneshot->tim);
/* Disable autoreload */
ESP32C3_TIM_SETARLD(oneshot->tim, false);
/* Set the timeout */
ESP32C3_TIM_SETALRVL(oneshot->tim, timeout_us / oneshot->resolution);
/* Enable TIMER alarm */
ESP32C3_TIM_SETALRM(oneshot->tim, true);
/* Clear Interrupt Bits Status */
ESP32C3_TIM_ACKINT(oneshot->tim);
/* Set the interrupt */
/* Register the handler that calls the callback */
ret = ESP32C3_TIM_SETISR(oneshot->tim, esp32c3_oneshot_handler, oneshot);
if (ret == OK)
{
ESP32C3_TIM_ENABLEINT(oneshot->tim);
/* Finally, start the TIMER */
ESP32C3_TIM_START(oneshot->tim);
oneshot->running = true;
}
return ret;
}
/****************************************************************************
* Name: esp32c3_oneshot_cancel
*
* Description:
* Cancel the oneshot timer and return the time remaining on the timer.
*
* Input Parameters:
* oneshot Caller allocated instance of the oneshot state structure. This
* structure must have been previously initialized via a call to
* esp32c3_oneshot_initialize();
* ts The location in which to return the time remaining on the
* oneshot timer. A time of zero is returned if the timer is
* not running. ts may be zero in which case the time remaining
* is not returned.
*
* Returned Value:
* Zero (OK) is returned on success. A call to up_timer_cancel() when
* the timer is not active should also return success; a negated errno
* value is returned on any failure.
*
****************************************************************************/
int esp32c3_oneshot_cancel(struct esp32c3_oneshot_s *oneshot,
struct timespec *ts)
{
int ret = OK;
uint64_t current_us;
uint64_t remaining_us;
uint64_t timeout_us;
uint64_t counter_value;
uint64_t alarm_value;
DEBUGASSERT(oneshot);
if (oneshot->running == false)
{
tmrinfo("Trying to cancel a non started oneshot timer.\n");
ts->tv_sec = 0;
ts->tv_nsec = 0;
}
else
{
/* Stop timer */
ESP32C3_TIM_STOP(oneshot->tim);
/* Disable int */
ESP32C3_TIM_DISABLEINT(oneshot->tim);
/* Detach handler */
ret = ESP32C3_TIM_SETISR(oneshot->tim, NULL, NULL);
if (ts != NULL)
{
/* Get the current counter value */
ESP32C3_TIM_GETCTR(oneshot->tim, &counter_value);
/* Get the current configured timeout */
ESP32C3_TIM_GETALRVL(oneshot->tim, &alarm_value);
current_us = counter_value * oneshot->resolution;
timeout_us = alarm_value * oneshot->resolution;
/* Remaining time (us) = timeout (us) - current (us) */
remaining_us = timeout_us - current_us;
ts->tv_sec = remaining_us / USEC_PER_SEC;
remaining_us = remaining_us - ts->tv_sec * USEC_PER_SEC;
ts->tv_nsec = remaining_us * NSEC_PER_USEC;
}
oneshot->running = false;
oneshot->handler = NULL;
oneshot->arg = NULL;
}
return ret;
}
/****************************************************************************
* Name: esp32c3_oneshot_current
*
* Description:
* Get the current time.
*
* Input Parameters:
* oneshot Caller allocated instance of the oneshot state structure. This
* structure must have been previously initialized via a call to
* esp32c3_oneshot_initialize();
* usec The maximum delay in us.
*
* Returned Value:
* Zero (OK).
*
****************************************************************************/
int esp32c3_oneshot_current(struct esp32c3_oneshot_s *oneshot,
uint64_t *usec)
{
/* Get the current counter value */
ESP32C3_TIM_GETCTR(oneshot->tim, usec);
*usec = *usec * (uint64_t)oneshot->resolution;
return OK;
}
#endif /* CONFIG_ESP32C3_ONESHOT */

View File

@ -0,0 +1,204 @@
/****************************************************************************
* arch/risc-v/src/esp32c3/esp32c3_oneshot.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_RISCV_SRC_ESP32C3_ONESHOT_H
#define __ARCH_RISCV_SRC_ESP32C3_ONESHOT_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <time.h>
#include "esp32c3_tim.h"
#ifdef CONFIG_ESP32C3_ONESHOT
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Types
****************************************************************************/
/* This describes the callback function that will be invoked when the oneshot
* timer expires. The oneshot fires, the client will receive:
*
* arg - The opaque argument provided when the interrupt was registered
*/
typedef void (*oneshot_handler_t)(void *arg);
/* The oneshot client must allocate an instance of this structure and call
* esp32c3_oneshot_initialize() before using the oneshot facilities. The
* client should not access the contents of this structure directly since
* the contents are subject to change.
*/
struct esp32c3_oneshot_s
{
uint8_t chan; /* The timer/counter in use */
volatile bool running; /* True: the timer is running */
FAR struct esp32c3_tim_dev_s *tim; /* Pointer returned by
* esp32c3_tim_init() */
volatile oneshot_handler_t handler; /* Oneshot expiration callback */
volatile void *arg; /* The argument that will accompany
* the callback */
uint32_t resolution; /* us */
};
/****************************************************************************
* Public Data
****************************************************************************/
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: esp32c3_oneshot_initialize
*
* Description:
* Initialize the oneshot timer wrapper.
*
* Input Parameters:
* oneshot Allocated instance of the oneshot state structure.
* chan Timer counter channel to be used.
* resolution The required resolution of the timer in units of
* microseconds. NOTE that the range is restricted to the
* range of uint16_t (excluding zero).
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
int esp32c3_oneshot_initialize(struct esp32c3_oneshot_s *oneshot, int chan,
uint16_t resolution);
/****************************************************************************
* Name: esp32c3_oneshot_max_delay
*
* Description:
* Determine the maximum delay of the one-shot timer (in microseconds).
*
* Input Parameters:
* oneshot Allocated instance of the oneshot state structure.
* chan The location in which to return the maximum delay in us.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
int esp32c3_oneshot_max_delay(struct esp32c3_oneshot_s *oneshot,
uint64_t *usec);
/****************************************************************************
* Name: esp32c3_oneshot_start
*
* Description:
* Start the oneshot timer
*
* Input Parameters:
* oneshot Allocated instance of the oneshot state structure. This
* structure must have been previously initialized via a call to
* esp32c3_oneshot_initialize();
* handler The function to call when the oneshot timer expires.
* arg An opaque argument that will accompany the callback.
* ts Provides the duration of the one shot timer.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
int esp32c3_oneshot_start(struct esp32c3_oneshot_s *oneshot,
oneshot_handler_t handler, void *arg,
const struct timespec *ts);
/****************************************************************************
* Name: esp32c3_oneshot_cancel
*
* Description:
* Cancel the oneshot timer and return the time remaining on the timer.
*
*
* Input Parameters:
* oneshot Allocated instance of the oneshot state structure. This
* structure must have been previously initialized via a call to
* esp32c3_oneshot_initialize();
* ts The location in which to return the time remaining on the
* oneshot timer. A time of zero is returned if the timer is
* not running.
*
* Returned Value:
* Zero (OK) is returned on success. A call to up_timer_cancel() when
* the timer is not active should also return success; a negated errno
* value is returned on any failure.
*
****************************************************************************/
int esp32c3_oneshot_cancel(struct esp32c3_oneshot_s *oneshot,
struct timespec *ts);
/****************************************************************************
* Name: esp32c3_oneshot_current
*
* Description:
* Get the current time.
*
* Input Parameters:
* oneshot Caller allocated instance of the oneshot state structure. This
* structure must have been previously initialized via a call to
* esp32c3_oneshot_initialize();
* usec The maximum delay in us.
*
* Returned Value:
* Zero (OK).
*
****************************************************************************/
int esp32c3_oneshot_current(struct esp32c3_oneshot_s *oneshot,
uint64_t *usec);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* CONFIG_ESP32C3_ONESHOT */
#endif /* __ARCH_RISCV_SRC_ESP32C3_ONESHOT_H */

View File

@ -0,0 +1,369 @@
/****************************************************************************
* arch/risc-v/src/esp32c3/esp32c3_oneshot_lowerhalf.c
*
* 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <debug.h>
#include <stdio.h>
#include <nuttx/arch.h>
#include <nuttx/timers/oneshot.h>
#include <nuttx/kmalloc.h>
#include "esp32c3_oneshot.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
struct esp32c3_oneshot_lowerhalf_s
{
/* This is the part of the lower half driver that is visible to the upper-
* half client of the driver. This must be the first thing in this
* structure so that pointers to struct oneshot_lowerhalf_s are cast
* compatible to struct esp32c3_oneshot_lowerhalf_s and vice versa.
*/
struct oneshot_lowerhalf_s lh; /* Lower half instance */
struct esp32c3_oneshot_s oneshot; /* ESP32C3-specific oneshot state */
oneshot_callback_t callback; /* Upper half Interrupt callback */
FAR void *arg; /* Argument passed to handler */
uint16_t resolution;
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static void esp32c3_oneshot_lh_handler(void *arg);
/* "Lower half" driver methods **********************************************/
static int oneshot_lh_max_delay(FAR struct oneshot_lowerhalf_s *lower,
FAR struct timespec *ts);
static int oneshot_lh_start(FAR struct oneshot_lowerhalf_s *lower,
oneshot_callback_t callback,
FAR void *arg,
FAR const struct timespec *ts);
static int oneshot_lh_cancel(FAR struct oneshot_lowerhalf_s *lower,
FAR struct timespec *ts);
static int oneshot_lh_current(FAR struct oneshot_lowerhalf_s *lower,
FAR struct timespec *ts);
/****************************************************************************
* Private Data
****************************************************************************/
/* "Lower half" driver methods */
static const struct oneshot_operations_s g_esp32c3_timer_ops =
{
.max_delay = oneshot_lh_max_delay,
.start = oneshot_lh_start,
.cancel = oneshot_lh_cancel,
.current = oneshot_lh_current
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: esp32c3_oneshot_lh_handler
*
* Description:
* Timer expiration handler.
*
* Input Parameters:
* arg - Should be the same argument provided when esp32c3_oneshot_start()
* was called.
*
****************************************************************************/
static void esp32c3_oneshot_lh_handler(void *arg)
{
FAR struct esp32c3_oneshot_lowerhalf_s *priv =
(FAR struct esp32c3_oneshot_lowerhalf_s *)arg;
DEBUGASSERT(priv != NULL);
DEBUGASSERT(priv->callback != NULL);
tmrinfo("Oneshot LH handler triggered\n");
/* Call the callback */
priv->callback(&priv->lh, priv->arg);
/* Restore state */
priv->callback = NULL;
priv->arg = NULL;
}
/****************************************************************************
* Name: oneshot_lh_max_delay
*
* Description:
* Determine the maximum delay of the one-shot timer (in microseconds).
*
* Input Parameters:
* lower An instance of the lower-half oneshot state structure. This
* structure must have been previously initialized via a call to
* oneshot_initialize();
* ts The location in which to return the maximum delay.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
static int oneshot_lh_max_delay(FAR struct oneshot_lowerhalf_s *lower,
FAR struct timespec *ts)
{
DEBUGASSERT(ts != NULL);
/* The real maximum delay surpass the limit that timespec can
* reprent. Even using the better case: a resolution of
* 1 us.
* Therefore, here, fulfill the timespec with the
* maximum value it can represent.
*/
ts->tv_sec = UINT32_MAX;
ts->tv_nsec = NSEC_PER_SEC - 1;
tmrinfo("max sec=%" PRIu32 "\n", ts->tv_sec);
tmrinfo("max nsec=%ld\n", ts->tv_nsec);
return OK;
}
/****************************************************************************
* Name: oneshot_lh_start
*
* Description:
* Start the oneshot timer.
*
* Input Parameters:
* lower An instance of the lower-half oneshot state structure. This
* structure must have been previously initialized via a call to
* oneshot_initialize();
* callback The function to call when when the oneshot timer expires.
* Inside the handler scope.
* arg A pointer to the argument that will accompany the callback.
* ts Provides the duration of the one shot timer.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
static int oneshot_lh_start(FAR struct oneshot_lowerhalf_s *lower,
oneshot_callback_t callback,
FAR void *arg,
FAR const struct timespec *ts)
{
FAR struct esp32c3_oneshot_lowerhalf_s *priv =
(FAR struct esp32c3_oneshot_lowerhalf_s *)lower;
int ret;
irqstate_t flags;
DEBUGASSERT(priv != NULL);
DEBUGASSERT(callback != NULL);
DEBUGASSERT(arg != NULL);
DEBUGASSERT(ts != NULL);
/* Save the callback information and start the timer */
flags = enter_critical_section();
priv->callback = callback;
priv->arg = arg;
ret = esp32c3_oneshot_start(&priv->oneshot,
esp32c3_oneshot_lh_handler,
priv,
ts);
leave_critical_section(flags);
if (ret < 0)
{
tmrerr("ERROR: esp32c3_oneshot_start failed: %d\n", ret);
}
return ret;
}
/****************************************************************************
* Name: oneshot_lh_cancel
*
* Description:
* Cancel the oneshot timer and return the time remaining on the timer.
*
* NOTE: This function may execute at a high rate with no timer running (as
* when pre-emption is enabled and disabled).
*
* Input Parameters:
* lower Caller allocated instance of the oneshot state structure. This
* structure must have been previously initialized via a call to
* oneshot_initialize();
* ts The location in which to return the time remaining on the
* oneshot timer. A time of zero is returned if the timer is
* not running.
*
* Returned Value:
* Zero (OK) is returned on success. A call to up_timer_cancel() when
* the timer is not active should also return success; a negated errno
* value is returned on any failure.
*
****************************************************************************/
static int oneshot_lh_cancel(FAR struct oneshot_lowerhalf_s *lower,
FAR struct timespec *ts)
{
FAR struct esp32c3_oneshot_lowerhalf_s *priv =
(FAR struct esp32c3_oneshot_lowerhalf_s *)lower;
irqstate_t flags;
int ret;
DEBUGASSERT(priv != NULL);
/* Cancel the timer */
flags = enter_critical_section();
ret = esp32c3_oneshot_cancel(&priv->oneshot, ts);
priv->callback = NULL;
priv->arg = NULL;
leave_critical_section(flags);
if (ret < 0)
{
tmrerr("ERROR: esp32c3_oneshot_cancel failed: %d\n", flags);
}
return ret;
}
/****************************************************************************
* Name: oneshot_lh_current
*
* Description:
* Get the current time.
*
* Input Parameters:
* lower Caller allocated instance of the oneshot state structure. This
* structure must have been previously initialized via a call to
* oneshot_initialize();
* ts The location in which to return the current time. A time of zero
* is returned for the initialization moment.
*
* Returned Value:
* Zero (OK) is returned on success, a negated errno value is returned on
* any failure.
*
****************************************************************************/
static int oneshot_lh_current(FAR struct oneshot_lowerhalf_s *lower,
FAR struct timespec *ts)
{
FAR struct esp32c3_oneshot_lowerhalf_s *priv =
(FAR struct esp32c3_oneshot_lowerhalf_s *)lower;
uint64_t current_us;
DEBUGASSERT(priv != NULL);
DEBUGASSERT(ts != NULL);
esp32c3_oneshot_current(&priv->oneshot, &current_us);
ts->tv_sec = current_us / USEC_PER_SEC;
current_us = current_us - ts->tv_sec * USEC_PER_SEC;
ts->tv_nsec = current_us * NSEC_PER_USEC;
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: oneshot_initialize
*
* Description:
* Initialize the oneshot timer and return a oneshot lower half driver
* instance.
*
* Input Parameters:
* chan Timer counter channel to be used.
* resolution The required resolution of the timer in units of
* microseconds. NOTE that the range is restricted to the
* range of uint16_t (excluding zero).
*
* Returned Value:
* On success, a non-NULL instance of the oneshot lower-half driver is
* returned. NULL is return on any failure.
*
****************************************************************************/
FAR struct oneshot_lowerhalf_s *oneshot_initialize(int chan,
uint16_t resolution)
{
FAR struct esp32c3_oneshot_lowerhalf_s *priv;
int ret;
/* Allocate an instance of the lower half driver */
priv = (FAR struct esp32c3_oneshot_lowerhalf_s *)kmm_zalloc(
sizeof(struct esp32c3_oneshot_lowerhalf_s));
if (priv == NULL)
{
tmrerr("ERROR: Failed to initialize oneshot state structure\n");
return NULL;
}
priv->lh.ops = &g_esp32c3_timer_ops; /* Pointer to the LH operations */
priv->callback = NULL; /* No callback yet */
priv->arg = NULL; /* No arg yet */
priv->resolution = resolution; /* Configured resolution */
/* Initialize esp32c3_oneshot_s structure */
ret = esp32c3_oneshot_initialize(&priv->oneshot, chan, resolution);
if (ret < 0)
{
tmrerr("ERROR: esp32c3_oneshot_initialize failed: %d\n", ret);
kmm_free(priv);
return NULL;
}
return &priv->lh;
}

View File

@ -0,0 +1,52 @@
#
# This file is autogenerated: PLEASE DO NOT EDIT IT.
#
# You can use "make menuconfig" to make any modifications to the installed .config file.
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
# modifications.
#
# CONFIG_NSH_ARGCAT is not set
# CONFIG_NSH_CMDOPT_HEXDUMP is not set
# CONFIG_NSH_CMDPARMS is not set
CONFIG_ARCH="risc-v"
CONFIG_ARCH_BOARD="esp32c3-devkit"
CONFIG_ARCH_BOARD_ESP32C3_DEVKIT=y
CONFIG_ARCH_CHIP="esp32c3"
CONFIG_ARCH_CHIP_ESP32C3=y
CONFIG_ARCH_CHIP_ESP32C3WROOM02=y
CONFIG_ARCH_INTERRUPTSTACK=1536
CONFIG_ARCH_RISCV=y
CONFIG_ARCH_STACKDUMP=y
CONFIG_BOARD_LOOPSPERMSEC=15000
CONFIG_BUILTIN=y
CONFIG_DEV_ZERO=y
CONFIG_ESP32C3_ONESHOT=y
CONFIG_ESP32C3_TIMER0=y
CONFIG_ESP32C3_TIMER1=y
CONFIG_EXAMPLES_ONESHOT=y
CONFIG_EXAMPLES_ONESHOT_DELAY=2000000
CONFIG_EXAMPLES_TIMER=y
CONFIG_FS_PROCFS=y
CONFIG_IDLETHREAD_STACKSIZE=2048
CONFIG_INTELHEX_BINARY=y
CONFIG_LIBC_PERROR_STDOUT=y
CONFIG_LIBC_STRERROR=y
CONFIG_MAX_TASKS=8
CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6
CONFIG_NSH_ARCHINIT=y
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_FILEIOSIZE=512
CONFIG_NSH_READLINE=y
CONFIG_NSH_STRERROR=y
CONFIG_ONESHOT=y
CONFIG_PREALLOC_TIMERS=0
CONFIG_RAW_BINARY=y
CONFIG_RR_INTERVAL=200
CONFIG_SCHED_WAITPID=y
CONFIG_START_DAY=29
CONFIG_START_MONTH=11
CONFIG_START_YEAR=2019
CONFIG_SYSTEM_NSH=y
CONFIG_TIMER=y
CONFIG_UART0_SERIAL_CONSOLE=y
CONFIG_USER_ENTRYPOINT="nsh_main"

View File

@ -54,8 +54,8 @@ ifeq ($(CONFIG_WATCHDOG),y)
CSRCS += esp32c3_wdt.c
endif
ifeq ($(CONFIG_TIMER),y)
CSRCS += esp32c3_timer.c
ifeq ($(CONFIG_ONESHOT),y)
CSRCS += esp32c3_oneshot.c
endif
SCRIPTIN = $(SCRIPTDIR)$(DELIM)esp32c3.template.ld

View File

@ -31,6 +31,16 @@
* Pre-processor Definitions
****************************************************************************/
/* TIMERS */
#define TIMER0 0
#define TIMER1 1
/* ONESHOT */
#define ONESHOT_TIMER 1
#define ONESHOT_RESOLUTION_US 1
/****************************************************************************
* Public Types
****************************************************************************/
@ -101,10 +111,14 @@ int board_i2c_init(void);
#endif
/****************************************************************************
* Name: board_tim_init
* Name: board_oneshot_init
*
* Description:
* Configure the timer driver.
* Configure the oneshot timer driver.
*
* Input Parameters:
* timer - Timer instance to be used as oneshot timer.
* resolution - Oneshot timer resolution.
*
* Returned Value:
* Zero (OK) is returned on success; A negated errno value is returned
@ -112,8 +126,8 @@ int board_i2c_init(void);
*
****************************************************************************/
#ifdef CONFIG_TIMER
int board_tim_init(void);
#ifdef CONFIG_ONESHOT
int board_oneshot_init(int timer, uint16_t resolution);
#endif
/****************************************************************************

View File

@ -42,6 +42,10 @@
#include "esp32c3_partition.h"
#include "esp32c3-devkit.h"
#ifdef CONFIG_TIMER
# include "esp32c3_tim_lowerhalf.h"
#endif
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@ -193,18 +197,46 @@ int esp32c3_bringup(void)
}
#endif
#ifdef CONFIG_TIMER
/* Configure timer timer */
/* First, register the timer drivers and let timer 1 for oneshot
* if it is enabled.
*/
ret = board_tim_init();
#ifdef CONFIG_TIMER
#if defined(CONFIG_ESP32C3_TIMER0) && !defined(CONFIG_ESP32C3_RT_TIMER)
ret = esp32c3_timer_initialize("/dev/timer0", TIMER0);
if (ret < 0)
{
syslog(LOG_ERR,
"ERROR: Failed to initialize timer drivers: %d\n",
"ERROR: Failed to initialize timer driver: %d\n",
ret);
}
#endif
#if defined(CONFIG_ESP32C3_TIMER1) && !defined(CONFIG_ONESHOT)
ret = esp32c3_timer_initialize("/dev/timer1", TIMER1);
if (ret < 0)
{
syslog(LOG_ERR,
"ERROR: Failed to initialize timer driver: %d\n",
ret);
}
#endif
#endif /* CONFIG_TIMER */
/* Now register one oneshot driver */
#if defined(CONFIG_ONESHOT) && defined(CONFIG_ESP32C3_TIMER1)
ret = board_oneshot_init(ONESHOT_TIMER, ONESHOT_RESOLUTION_US);
if (ret < 0)
{
syslog(LOG_ERR, "ERROR: board_oneshot_init() failed: %d\n", ret);
}
#endif /* CONFIG_ONESHOT */
#ifdef CONFIG_ESP32C3_WIRELESS
#ifdef CONFIG_ESP32C3_WIFI_SAVE_PARAM

View File

@ -1,5 +1,5 @@
/****************************************************************************
* boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_timer.c
* boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_oneshot.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@ -24,12 +24,11 @@
#include <nuttx/config.h>
#include <sys/types.h>
#include <debug.h>
#include "esp32c3_tim_lowerhalf.h"
#include "esp32c3_tim.h"
#include <sys/types.h>
#include <nuttx/timers/timer.h>
#include <nuttx/clock.h>
#include <nuttx/timers/oneshot.h>
#include "esp32c3-devkit.h"
/****************************************************************************
@ -41,10 +40,10 @@
****************************************************************************/
/****************************************************************************
* Name: board_tim_init
* Name: board_oneshot_init
*
* Description:
* Configure the timer driver.
* Configure the oneshot timer driver.
*
* Returned Value:
* Zero (OK) is returned on success; A negated errno value is returned
@ -52,32 +51,33 @@
*
****************************************************************************/
int board_tim_init(void)
int board_oneshot_init(int timer, uint16_t resolution)
{
int ret = OK;
FAR struct oneshot_lowerhalf_s *os_lower = NULL;
#if defined(CONFIG_ESP32C3_TIMER0) && !defined(CONFIG_ESP32C3_RT_TIMER)
ret = esp32c3_timer_initialize("/dev/timer0", ESP32C3_TIMER0);
if (ret < 0)
os_lower = oneshot_initialize(timer, resolution);
if (os_lower != NULL)
{
syslog(LOG_ERR,
"ERROR: Failed to initialize timer driver: %d\n",
ret);
return ret;
}
#endif /* CONFIG_ESP32C3_TIMER0 */
#if defined(CONFIG_CPULOAD_ONESHOT)
/* Configure the oneshot timer to support CPU load measurement */
#ifdef CONFIG_ESP32C3_TIMER1
ret = esp32c3_timer_initialize("/dev/timer1", ESP32C3_TIMER1);
if (ret < 0)
{
syslog(LOG_ERR,
"ERROR: Failed to initialize timer driver: %d\n",
ret);
return ret;
nxsched_oneshot_extclk(os_lower);
#else
ret = oneshot_register("/dev/oneshot", os_lower);
if (ret < 0)
{
syslog(LOG_ERR,
"ERROR: Failed to register oneshot at /dev/oneshot: %d\n", ret);
}
#endif /* CONFIG_CPULOAD_ONESHOT */
}
else
{
syslog(LOG_ERR, "ERROR: oneshot_initialize failed\n");
ret = -EBUSY;
}
#endif /* CONFIG_ESP32C3_TIMER1 */
return ret;
}