arch/mips/src/pic32mz: Add support for the PIC32MZ timers (driver, lowerhalf, freerun and oneshot)

This commit is contained in:
Abdelatif Guettouche
2019-02-02 17:42:33 -06:00
committed by Gregory Nutt
parent d8943be51c
commit 06e27e5547
13 changed files with 4299 additions and 21 deletions
File diff suppressed because it is too large Load Diff
+19 -1
View File
@@ -1,7 +1,7 @@
############################################################################
# arch/mips/src/pic32mz/Make.defs
#
# Copyright (C) 2015, 2018 Gregory Nutt. All rights reserved.
# Copyright (C) 2015, 2018, 2019 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@@ -90,6 +90,24 @@ ifeq ($(CONFIG_PIC32MZ_I2C),y)
CHIP_CSRCS += pic32mz-i2c.c
endif
ifeq ($(CONFIG_PIC32MZ_TIMER),y)
CHIP_CSRCS += pic32mz-timer.c
endif
ifeq ($(CONFIG_TIMER),y)
CHIP_CSRCS += pic32mz-timer-lowerhalf.c
else ifeq ($(CONFIG_PIC32MZ_ONESHOT),y)
CHIP_CSRCS += pic32mz-timer-lowerhalf.c
endif
ifeq ($(CONFIG_PIC32MZ_FREERUN),y)
CHIP_CSRCS += pic32mz-freerun.c
endif
ifeq ($(CONFIG_PIC32MZ_ONESHOT),y)
CHIP_CSRCS += pic32mz-oneshot.c
endif
ifeq ($(CONFIG_PIC32MZ_ETHERNET),y)
CHIP_CSRCS += pic32mz-ethernet.c
endif
+3 -3
View File
@@ -33,8 +33,8 @@
*
************************************************************************************/
#ifndef __ARCH_MIPS_SRC_PIC32MZ_PIC32MZ_TIMER_H
#define __ARCH_MIPS_SRC_PIC32MZ_PIC32MZ_TIMER_H
#ifndef __ARCH_MIPS_SRC_PIC32MZ_CHIP_PIC32MZ_TIMER_H
#define __ARCH_MIPS_SRC_PIC32MZ_CHIP_PIC32MZ_TIMER_H
/************************************************************************************
* Included Files
@@ -308,4 +308,4 @@ extern "C"
#endif /* __ASSEMBLY__ */
#endif /* CHIP_NTIMERS > 0 */
#endif /* __ARCH_MIPS_SRC_PIC32MZ_PIC32MZ_TIMER_H */
#endif /* __ARCH_MIPS_SRC_PIC32MZ_CHIP_PIC32MZ_TIMER_H */
+2 -1
View File
@@ -1,7 +1,7 @@
/********************************************************************************************
* arch/mips/src/pic32mz/pic32mzec-pps.h
*
* Copyright (C) 2015 Gregory Nutt. All rights reserved.
* Copyright (C) 2015, 2019 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -45,6 +45,7 @@
/********************************************************************************************
* Pre-processor Definitions
********************************************************************************************/
/* PPS Register Offsets *********************************************************************/
/* Peripheral pin select input register map */
+16 -16
View File
@@ -55,14 +55,14 @@
# define PIC32MZ_INT3R_OFFSET 0x140c
# define PIC32MZ_INT4R_OFFSET 0x1410
#define PIC32MZ_TnCKR_OFFSET(n) (0x1410 + ((n << 2)) /* n=2..9 */
# define PIC32MZ_I2TKR_OFFSET 0x1418
# define PIC32MZ_I3TKR_OFFSET 0x141c
# define PIC32MZ_I4TKR_OFFSET 0x1420
# define PIC32MZ_I5TKR_OFFSET 0x1424
# define PIC32MZ_I6TKR_OFFSET 0x1428
# define PIC32MZ_I7TKR_OFFSET 0x142c
# define PIC32MZ_I8TKR_OFFSET 0x1430
# define PIC32MZ_I9TKR_OFFSET 0x1434
# define PIC32MZ_T2CKR_OFFSET 0x1418
# define PIC32MZ_T3CKR_OFFSET 0x141c
# define PIC32MZ_T4CKR_OFFSET 0x1420
# define PIC32MZ_T5CKR_OFFSET 0x1424
# define PIC32MZ_T6CKR_OFFSET 0x1428
# define PIC32MZ_T7CKR_OFFSET 0x142c
# define PIC32MZ_T8CKR_OFFSET 0x1430
# define PIC32MZ_T9CKR_OFFSET 0x1434
#define PIC32MZ_ICnR_OFFSET(n) (0x1434 + ((n << 2)) /* n=1..9 */
# define PIC32MZ_IC1R_OFFSET 0x1438
# define PIC32MZ_IC2R_OFFSET 0x143c
@@ -189,14 +189,14 @@
# define PIC32MZ_INT3R (PIC32MZ_SFR_K1BASE+PIC32MZ_INT3R_OFFSET)
# define PIC32MZ_INT4R (PIC32MZ_SFR_K1BASE+PIC32MZ_INT4R_OFFSET)
#define PIC32MZ_TnCKR(n) (PIC32MZ_SFR_K1BASE+PIC32MZ_TnCKR_OFFSET(n))
# define PIC32MZ_I2TKR (PIC32MZ_SFR_K1BASE+PIC32MZ_I2TKR_OFFSET)
# define PIC32MZ_I3TKR (PIC32MZ_SFR_K1BASE+PIC32MZ_I3TKR_OFFSET)
# define PIC32MZ_I4TKR (PIC32MZ_SFR_K1BASE+PIC32MZ_I4TKR_OFFSET)
# define PIC32MZ_I5TKR (PIC32MZ_SFR_K1BASE+PIC32MZ_I5TKR_OFFSET)
# define PIC32MZ_I6TKR (PIC32MZ_SFR_K1BASE+PIC32MZ_I6TKR_OFFSET)
# define PIC32MZ_I7TKR (PIC32MZ_SFR_K1BASE+PIC32MZ_I7TKR_OFFSET)
# define PIC32MZ_I8TKR (PIC32MZ_SFR_K1BASE+PIC32MZ_I8TKR_OFFSET)
# define PIC32MZ_I9TKR (PIC32MZ_SFR_K1BASE+PIC32MZ_I9TKR_OFFSET)
# define PIC32MZ_T2CKR (PIC32MZ_SFR_K1BASE+PIC32MZ_T2CKR_OFFSET)
# define PIC32MZ_T3CKR (PIC32MZ_SFR_K1BASE+PIC32MZ_T3CKR_OFFSET)
# define PIC32MZ_T4CKR (PIC32MZ_SFR_K1BASE+PIC32MZ_T4CKR_OFFSET)
# define PIC32MZ_T5CKR (PIC32MZ_SFR_K1BASE+PIC32MZ_T5CKR_OFFSET)
# define PIC32MZ_T6CKR (PIC32MZ_SFR_K1BASE+PIC32MZ_T6CKR_OFFSET)
# define PIC32MZ_T7CKR (PIC32MZ_SFR_K1BASE+PIC32MZ_T7CKR_OFFSET)
# define PIC32MZ_T8CKR (PIC32MZ_SFR_K1BASE+PIC32MZ_T8CKR_OFFSET)
# define PIC32MZ_T9CKR (PIC32MZ_SFR_K1BASE+PIC32MZ_T9CKR_OFFSET)
#define PIC32MZ_ICnR(n) (PIC32MZ_SFR_K1BASE+PIC32MZ_ICnR_OFFSET(n))
# define PIC32MZ_IC1R (PIC32MZ_SFR_K1BASE+PIC32MZ_IC1R_OFFSET)
# define PIC32MZ_IC2R (PIC32MZ_SFR_K1BASE+PIC32MZ_IC2R_OFFSET)
+335
View File
@@ -0,0 +1,335 @@
/****************************************************************************
* arch/mips/src/pic32mz/chip/pic32mz-freerun.c
*
* Copyright (C) 2019 Abdelatif Guettouche. All rights reserved.
* Author: Abdelatif Guettouche <abdelatif.guettouche@gmail.com>
*
* This file is a part of NuttX:
*
* Copyright (C) 2019 Gregory Nutt. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
#include <errno.h>
#include <nuttx/irq.h>
#include <nuttx/clock.h>
#include "pic32mz-freerun.h"
#ifdef CONFIG_PIC32MZ_FREERUN
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
#ifndef CONFIG_CLOCK_TIMEKEEPING
static int pic32mz_freerun_handler(int irq, void *context, void *arg);
#endif /* CONFIG_CLOCK_TIMEKEEPING */
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: pic32mz_freerun_handler
*
* Description:
* Timer interrupt callback. When the freerun timer counter overflows,
* this interrupt will occur. We will just increment an overflow count.
*
* Input Parameters:
* irq Number of the IRQ that generated the interrupt
* context Interrupt register state save info (architecture-specific)
* arg An opaque argument provided when the interrupt was registered
*
* Returned Value:
* OK on success
*
****************************************************************************/
#ifndef CONFIG_CLOCK_TIMEKEEPING
static int pic32mz_freerun_handler(int irq, void *context, void *arg)
{
struct pic32mz_freerun_s *freerun = (struct pic32mz_freerun_s *) arg;
DEBUGASSERT(freerun != NULL && freerun->overflow < UINT32_MAX);
freerun->overflow++;
PIC32MZ_TIMER_ACKINT(freerun->timer);
return OK;
}
#endif /* CONFIG_CLOCK_TIMEKEEPING */
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: pic32mz_freerun_initialize
*
* Description:
* Initialize the freerun timer wrapper
*
* Input Parameters:
* freerun Caller allocated instance of the freerun 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 pic32mz_freerun_initialize(struct pic32mz_freerun_s *freerun, int chan,
uint16_t resolution)
{
uint32_t freq;
tmrinfo("chan=%d resolution=%d usec\n", chan, resolution);
DEBUGASSERT(freerun != NULL && resolution > 0);
freerun->timer = pic32mz_timer_init(chan);
if (!freerun->timer)
{
tmrerr("ERROR: Failed to allocate timer%d\n", chan);
return -EBUSY;
}
/* Get the timer's frequency that corresponds to the requested resolution */
freq = USEC_PER_SEC / (uint32_t)resolution;
tmrinfo("Setting frequency=%luHz\n", freq);
if (!PIC32MZ_TIMER_SETFREQ(freerun->timer, freq))
{
tmrerr("Cannot set frequency=%luHz\n", freq);
return -EAGAIN;
}
/* Initialize the remaining fields in the state structure.
*
* The timer's frequency might not be the same as requested,
* due to the lack of prescale values. Get it from the driver.
*/
freerun->freq = PIC32MZ_TIMER_GETFREQ(freerun->timer);
freerun->width = PIC32MZ_TIMER_GETWIDTH(freerun->timer);
freerun->chan = chan;
freerun->running = false;
#ifdef CONFIG_CLOCK_TIMEKEEPING
if (freerun->width == 32)
{
freerun->counter_mask = 0xffffffffull;
}
else
{
freerun->counter_mask = 0x0000ffffull;
}
#endif
#ifndef CONFIG_CLOCK_TIMEKEEPING
freerun->overflow = 0;
/* Set up to receive the callback when the counter overflow occurs */
PIC32MZ_TIMER_ACKINT(freerun->timer);
PIC32MZ_TIMER_SETISR(freerun->timer, pic32mz_freerun_handler, freerun);
#endif
/* Set the period */
PIC32MZ_TIMER_SETPERIOD(freerun->timer,
(uint32_t)((1ull << freerun->width) - 1ul));
/* Start the timer */
PIC32MZ_TIMER_START(freerun->timer);
freerun->running = true;
return OK;
}
/****************************************************************************
* Name: pic32mz_freerun_counter
*
* Description:
* Read the counter register of the free-running timer.
*
* Input Parameters:
* freerun Caller allocated instance of the freerun state structure. This
* structure must have been previously initialized via a call to
* pic32mz_freerun_initialize();
* ts The location in which to return the time from the free-running
* timer.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
#ifndef CONFIG_CLOCK_TIMEKEEPING
int pic32mz_freerun_counter(struct pic32mz_freerun_s *freerun,
struct timespec *ts)
{
uint64_t usec;
uint32_t counter;
uint32_t verify;
uint32_t overflow;
uint32_t sec;
bool pending;
irqstate_t flags;
DEBUGASSERT(freerun && freerun->timer && ts);
/* Temporarily disable the overflow counter. */
flags = enter_critical_section();
overflow = freerun->overflow;
counter = PIC32MZ_TIMER_GETCOUNTER(freerun->timer);
pending = PIC32MZ_TIMER_CHECKINT(freerun->timer);
verify = PIC32MZ_TIMER_GETCOUNTER(freerun->timer);
/* If an interrupt was pending before we re-enabled interrupts,
* then the overflow needs to be incremented.
*/
if (pending)
{
PIC32MZ_TIMER_ACKINT(freerun->timer);
/* Increment the overflow count and use the value of the
* guaranteed to be AFTER the overflow occurred.
*/
overflow++;
counter = verify;
/* Update freerun overflow counter. */
freerun->overflow = overflow;
}
leave_critical_section(flags);
tmrinfo("counter=%lu (%lu) overflow=%lu, pending=%i\n",
(unsigned long)counter, (unsigned long)verify,
(unsigned long)overflow, pending);
tmrinfo("frequency=%u\n", freerun->freq);
/* Convert the whole thing to units of microseconds.
*
* frequency = ticks / second
* seconds = ticks * frequency
* usecs = (ticks * USEC_PER_SEC) / frequency;
*/
usec = ((((uint64_t)overflow << freerun->width) +
(uint64_t)counter) * USEC_PER_SEC) / freerun->freq;
/* And return the value of the timer */
sec = (uint32_t)(usec / USEC_PER_SEC);
ts->tv_sec = sec;
ts->tv_nsec = (usec - (sec * USEC_PER_SEC)) * NSEC_PER_USEC;
tmrinfo("usec=%llu ts=(%u, %lu)\n",
usec, (unsigned long)ts->tv_sec, (unsigned long)ts->tv_nsec);
return OK;
}
#else /* CONFIG_CLOCK_TIMEKEEPING */
int pic32mz_freerun_counter(struct pic32mz_freerun_s *freerun,
uint64_t *counter)
{
*counter = (uint64_t)PIC32MZ_TIMER_GETCOUNTER(freerun->timer) &
freerun->counter_mask;
return OK;
}
#endif /* CONFIG_CLOCK_TIMEKEEPING */
/****************************************************************************
* Name: pic32mz_freerun_uninitialize
*
* Description:
* Stop the free-running timer and release all resources that it uses.
*
* Input Parameters:
* freerun Caller allocated instance of the freerun state structure. This
* structure must have been previously initialized via a call to
* pic32mz_freerun_initialize();
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
int pic32mz_freerun_uninitialize(struct pic32mz_freerun_s *freerun)
{
DEBUGASSERT(freerun && freerun->timer);
/* Now we can disable the timer interrupt */
PIC32MZ_TIMER_SETISR(freerun->timer, NULL, NULL);
/* Free the timer, this will stop the timer as well */
pic32mz_timer_deinit(freerun->timer);
freerun->running = false;
freerun->timer = NULL;
return OK;
}
#endif /* CONFIG_PIC32MZ_FREERUN */
+179
View File
@@ -0,0 +1,179 @@
/****************************************************************************
* arch/mips/src/pic32mz/chip/pic32mz-freerun.h
*
* Copyright (C) 2019 Abdelatif Guettouche. All rights reserved.
* Author: Abdelatif Guettouche <abdelatif.guettouche@gmail.com>
*
* This file is a part of NuttX:
*
* Copyright (C) 2019 Gregory Nutt. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __ARCH_MIPS_SRC_PIC32MZ_PIC32MZ_FREERUN_H
#define __ARCH_MIPS_SRC_PIC32MZ_PIC32MZ_FREERUN_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <time.h>
#include <debug.h>
#include "pic32mz-timer.h"
#ifdef CONFIG_PIC32MZ_FREERUN
/****************************************************************************
* Public Types
****************************************************************************/
/* The freerun client must allocate an instance of this structure and call
* pic32mz_freerun_initialize() before using the freerun facilities.
* The client should not access the contents of this structure directly
* since the contents are subject to change.
*/
struct pic32mz_freerun_s
{
uint8_t chan; /* The timer in use */
uint8_t width; /* Width of timer (16- or 32) */
bool running; /* True: the timer is running */
FAR struct pic32mz_timer_dev_s *timer; /* PIC32MZ timer driver */
uint32_t freq; /* Timer's frequency (Hz) */
#ifndef CONFIG_CLOCK_TIMEKEEPING
uint32_t overflow; /* Timer's counter overflow */
#endif
#ifdef CONFIG_CLOCK_TIMEKEEPING
uint64_t counter_mask; /* Timer's count register mask */
#endif
};
/****************************************************************************
* Public Data
****************************************************************************/
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: pic32mz_freerun_initialize
*
* Description:
* Initialize the freerun timer wrapper
*
* Input Parameters:
* freerun Caller allocated instance of the freerun state structure
* chan Timer 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 pic32mz_freerun_initialize(struct pic32mz_freerun_s *freerun, int chan,
uint16_t resolution);
/****************************************************************************
* Name: pic32mz_freerun_counter
*
* Description:
* Read the counter register of the free-running timer.
*
* Input Parameters:
* freerun Caller allocated instance of the freerun state structure. This
* structure must have been previously initialized via a call to
* pic32mz_freerun_initialize();
* ts The location in which to return the time remaining on the
* oneshot timer.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
#ifndef CONFIG_CLOCK_TIMEKEEPING
int pic32mz_freerun_counter(struct pic32mz_freerun_s *freerun,
struct timespec *ts);
#else /* CONFIG_CLOCK_TIMEKEEPING */
int pic32mz_freerun_counter(struct pic32mz_freerun_s *freerun,
uint64_t *counter);
#endif /* CONFIG_CLOCK_TIMEKEEPING */
/****************************************************************************
* Name: pic32mz_freerun_uninitialize
*
* Description:
* Stop the free-running timer and release all resources that it uses.
*
* Input Parameters:
* freerun Caller allocated instance of the freerun state structure. This
* structure must have been previously initialized via a call to
* pic32mz_freerun_initialize();
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
int pic32mz_freerun_uninitialize(struct pic32mz_freerun_s *freerun);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* CONFIG_PIC32MZ_FREERUN */
#endif /* __ARCH_MIPS_SRC_PIC32MZ_PIC32MZ_FREERUN_H */
@@ -0,0 +1,353 @@
/****************************************************************************
* arch/mips/src/pic32mz/chip/pic32mz-oneshot-lowerhalf.c
*
* Copyright (C) 2019 Abdelatif Guettouche. All rights reserved.
* Author: Abdelatif Guettouche <abdelatif.guettouche@gmail.com>
*
* This file is a part of NuttX:
*
* Copyright (C) 2019 Gregory Nutt. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <time.h>
#include <assert.h>
#include <debug.h>
#include <nuttx/irq.h>
#include <nuttx/kmalloc.h>
#include <nuttx/timers/oneshot.h>
#include "pic32mz-oneshot.h"
/****************************************************************************
* Private Types
****************************************************************************/
/* This structure describes the state of the oneshot lower-half driver */
struct pic32mz_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 pic32mz_oneshot_lowerhalf_s and vice versa.
*/
struct oneshot_lowerhalf_s lh; /* Common lower-half driver fields */
/* Private lower half data follows */
struct pic32mz_oneshot_s oneshot; /* PIC32MZ-specific oneshot state */
oneshot_callback_t callback; /* Handler that receives callback */
FAR void *arg; /* Argument passed to the handler */
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static void pic32mz_oneshot_handler(void *arg);
static int pic32mz_max_delay(FAR struct oneshot_lowerhalf_s *lower,
FAR struct timespec *ts);
static int pic32mz_start(FAR struct oneshot_lowerhalf_s *lower,
oneshot_callback_t callback, FAR void *arg,
FAR const struct timespec *ts);
static int pic32mz_cancel(FAR struct oneshot_lowerhalf_s *lower,
FAR struct timespec *ts);
/****************************************************************************
* Private Data
****************************************************************************/
/* Lower half operations */
static const struct oneshot_operations_s g_oneshot_ops =
{
.max_delay = pic32mz_max_delay,
.start = pic32mz_start,
.cancel = pic32mz_cancel,
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: pic32mz_oneshot_handler
*
* Description:
* Timer expiration handler
*
* Input Parameters:
* arg Should be the same argument provided when pic32mz_oneshot_start()
* was called.
*
* Returned Value:
* None
*
****************************************************************************/
static void pic32mz_oneshot_handler(void *arg)
{
FAR struct pic32mz_oneshot_lowerhalf_s *priv =
(FAR struct pic32mz_oneshot_lowerhalf_s *)arg;
oneshot_callback_t callback;
FAR void *cbarg;
DEBUGASSERT(priv != NULL);
/* Perhaps the callback was nullified in a race condition with
* pic32mz_cancel?
*/
if (priv->callback)
{
/* Sample and nullify BEFORE executing callback (in case the callback
* restarts the oneshot).
*/
callback = priv->callback;
cbarg = priv->arg;
priv->callback = NULL;
priv->arg = NULL;
/* Then perform the callback */
callback(&priv->lh, cbarg);
}
}
/****************************************************************************
* Name: pic32mz_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 maxumum delay.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
static int pic32mz_max_delay(FAR struct oneshot_lowerhalf_s *lower,
FAR struct timespec *ts)
{
FAR struct pic32mz_oneshot_lowerhalf_s *priv =
(FAR struct pic32mz_oneshot_lowerhalf_s *)lower;
uint64_t usecs;
int ret;
DEBUGASSERT(priv != NULL && ts != NULL);
ret = pic32mz_oneshot_max_delay(&priv->oneshot, &usecs);
tmrinfo("max delay %lu\n", usecs);
if (ret >= 0)
{
uint64_t sec = usecs / 1000000;
usecs -= 1000000 * sec;
ts->tv_sec = (time_t)sec;
ts->tv_nsec = (long)(usecs * 1000);
}
return ret;
}
/****************************************************************************
* Name: pic32mz_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();
* 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.
*
****************************************************************************/
static int pic32mz_start(FAR struct oneshot_lowerhalf_s *lower,
oneshot_callback_t callback, FAR void *arg,
FAR const struct timespec *ts)
{
FAR struct pic32mz_oneshot_lowerhalf_s *priv =
(FAR struct pic32mz_oneshot_lowerhalf_s *)lower;
irqstate_t flags;
int ret;
DEBUGASSERT(priv != NULL && callback != NULL && ts != NULL);
/* Save the callback information and start the timer */
flags = enter_critical_section();
priv->callback = callback;
priv->arg = arg;
ret = pic32mz_oneshot_start(&priv->oneshot,
pic32mz_oneshot_handler,
priv, ts);
leave_critical_section(flags);
if (ret < 0)
{
tmrerr("ERROR: pic32mz_oneshot_start failed: %d\n", flags);
}
return ret;
}
/****************************************************************************
* Name: pic32mz_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 pic32mz_cancel(FAR struct oneshot_lowerhalf_s *lower,
FAR struct timespec *ts)
{
FAR struct pic32mz_oneshot_lowerhalf_s *priv =
(FAR struct pic32mz_oneshot_lowerhalf_s *)lower;
irqstate_t flags;
int ret;
DEBUGASSERT(priv != NULL);
/* Cancel the timer */
flags = enter_critical_section();
ret = pic32mz_oneshot_cancel(&priv->oneshot, ts);
priv->callback = NULL;
priv->arg = NULL;
leave_critical_section(flags);
if (ret < 0)
{
tmrerr("ERROR: pic32mz_oneshot_cancel failed: %d\n", flags);
}
return ret;
}
/****************************************************************************
* 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 pic32mz_oneshot_lowerhalf_s *priv;
int ret;
/* Allocate an instance of the lower half driver */
priv = (FAR struct pic32mz_oneshot_lowerhalf_s *)
kmm_zalloc(sizeof(struct pic32mz_oneshot_lowerhalf_s));
if (priv == NULL)
{
tmrerr("ERROR: Failed to initialized state structure\n");
return NULL;
}
/* Initialize the lower-half driver structure */
priv->lh.ops = &g_oneshot_ops;
/* Initialize the contained PIC32MZ oneshot timer */
ret = pic32mz_oneshot_initialize(&priv->oneshot, chan, resolution);
if (ret < 0)
{
tmrerr("ERROR: pic32mz_oneshot_initialize failed: %d\n", ret);
kmm_free(priv);
return NULL;
}
return &priv->lh;
}
+464
View File
@@ -0,0 +1,464 @@
/****************************************************************************
* arch/mips/src/pic32mz/chip/pic32mz-oneshot.c
*
* Copyright (C) 2019 Abdelatif Guettouche. All rights reserved.
* Author: Abdelatif Guettouche <abdelatif.guettouche@gmail.com>
*
* This file is a part of NuttX:
*
* Copyright (C) 2019 Gregory Nutt. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <sched.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/irq.h>
#include <nuttx/clock.h>
#include "pic32mz-oneshot.h"
#ifdef CONFIG_PIC32MZ_ONESHOT
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static int pic32mz_oneshot_handler(int irg_num, void * context, void *arg);
static inline int pic32mz_allocate_handler(struct pic32mz_oneshot_s *oneshot);
/****************************************************************************
* Private Data
****************************************************************************/
static struct pic32mz_oneshot_s *g_oneshot[CONFIG_PIC32MZ_ONESHOT_MAXTIMERS];
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: pic32mz_oneshot_handler
*
* Description:
* Common timer interrupt callback. When any oneshot timer interrupt
* expires, this function will be called. It will forward the call to
* the next level up.
*
* Input Parameters:
* oneshot The state associated with the expired timer
*
* Returned Value:
* Always returns OK
*
****************************************************************************/
static int pic32mz_oneshot_handler(int irg_num, void * context, void *arg)
{
struct pic32mz_oneshot_s * oneshot = (struct pic32mz_oneshot_s *) arg;
oneshot_handler_t oneshot_handler;
void *oneshot_arg;
tmrinfo("Expired...\n");
DEBUGASSERT(oneshot != NULL && oneshot->handler);
/* Stop the timer and disable any further interrupts */
PIC32MZ_TIMER_ACKINT(oneshot->timer);
PIC32MZ_TIMER_SETISR(oneshot->timer, NULL, NULL);
PIC32MZ_TIMER_STOP(oneshot->timer);
/* The timer is no longer running */
oneshot->running = false;
/* Forward the event, clearing out any vestiges */
oneshot_handler = (oneshot_handler_t)oneshot->handler;
oneshot->handler = NULL;
oneshot_arg = (void *)oneshot->arg;
oneshot->arg = NULL;
oneshot_handler(oneshot_arg);
return OK;
}
/****************************************************************************
* Name: pic32mz_allocate_handler
*
* Description:
* Allocate a timer callback handler for the oneshot instance.
*
* Input Parameters:
* oneshot The state instance the new oneshot timer
*
* Returned Value:
* Returns zero (OK) on success. This can only fail if the number of
* timers exceeds CONFIG_PIC32MZ_ONESHOT_MAXTIMERS.
*
****************************************************************************/
static inline int pic32mz_allocate_handler(struct pic32mz_oneshot_s *oneshot)
{
#if CONFIG_PIC32MZ_ONESHOT_MAXTIMERS > 1
int ret = -EBUSY;
int i;
/* Search for an unused handler */
sched_lock();
for (i = 0; i < CONFIG_PIC32MZ_ONESHOT_MAXTIMERS; i++)
{
/* Is this handler available? */
if (g_oneshot[i] == NULL)
{
/* Yes... assign it to this oneshot */
g_oneshot[i] = oneshot;
oneshot->cbndx = i;
ret = OK;
break;
}
}
sched_unlock();
return ret;
#else
if (g_oneshot[0] == NULL)
{
g_oneshot[0] = oneshot;
return OK;
}
return -EBUSY;
#endif
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: pic32mz_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 pic32mz_oneshot_initialize(struct pic32mz_oneshot_s *oneshot, int chan,
uint16_t resolution)
{
uint32_t freq;
tmrinfo("chan=%d resolution=%d usec\n", chan, resolution);
DEBUGASSERT(oneshot && resolution > 0);
oneshot->timer = pic32mz_timer_init(chan);
if (!oneshot->timer)
{
tmrerr("ERROR: Failed to allocate timer%d\n", chan);
return -EBUSY;
}
/* Get the timer's frequency that corresponds to the requested resolution */
freq = USEC_PER_SEC / (uint32_t)resolution;
tmrinfo("Setting frequency=%luHz\n", freq);
if (!PIC32MZ_TIMER_SETFREQ(oneshot->timer, freq))
{
tmrerr("Cannot set frequency=%luHz\n", freq);
return -EAGAIN;
}
/* Initialize the remaining fields in the state structure.
*
* The timer's frequency might not be the same as requested,
* due to the lack of prescale values. Get it from the driver.
*/
oneshot->freq = PIC32MZ_TIMER_GETFREQ(oneshot->timer);
oneshot->width = PIC32MZ_TIMER_GETWIDTH(oneshot->timer);
oneshot->chan = chan;
oneshot->running = false;
oneshot->handler = NULL;
oneshot->arg = NULL;
/* Assign a callback handler to the oneshot */
return pic32mz_allocate_handler(oneshot);
}
/****************************************************************************
* Name: pic32mz_oneshot_max_delay
*
* Description:
* Determine the maximum delay of the one-shot timer (in microseconds)
*
****************************************************************************/
int pic32mz_oneshot_max_delay(struct pic32mz_oneshot_s *oneshot,
uint64_t *usec)
{
uint32_t maxticks;
maxticks = (1ull << oneshot->width) - 1ul;
DEBUGASSERT(oneshot != NULL && usec != NULL);
tmrinfo("width=%u freq=%lu max ticks=%lu\n",
oneshot->width, oneshot->freq, maxticks);
*usec = (maxticks / oneshot->freq) * USEC_PER_SEC;
tmrinfo("max delay %lu\n", *usec);
return OK;
}
/****************************************************************************
* Name: pic32mz_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 pic32mz_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 pic32mz_oneshot_start(struct pic32mz_oneshot_s *oneshot,
oneshot_handler_t handler, void *arg,
const struct timespec *ts)
{
uint64_t usec;
uint64_t period;
irqstate_t flags;
tmrinfo("handler=%p arg=%p, ts=(%lu, %lu)\n",
handler, arg, (unsigned long)ts->tv_sec, (unsigned long)ts->tv_nsec);
DEBUGASSERT(oneshot && handler && ts);
DEBUGASSERT(oneshot->timer);
flags = enter_critical_section();
/* Was the oneshot already running? */
if (oneshot->running)
{
/* Yes.. then cancel it */
tmrinfo("Already running... cancelling\n");
(void)pic32mz_oneshot_cancel(oneshot, NULL);
}
/* Save the new handler and its argument */
oneshot->handler = handler;
oneshot->arg = arg;
/* Express the delay in microseconds */
usec = (uint64_t)ts->tv_sec * USEC_PER_SEC +
(uint64_t)(ts->tv_nsec / NSEC_PER_USEC);
period = (usec * (uint64_t)oneshot->freq) / USEC_PER_SEC;
tmrinfo("usec=%llu period=%08llx\n", usec, period);
DEBUGASSERT(period <= ((1ull << oneshot->width) - 1ul));
/* Set timer period */
oneshot->period = (uint32_t)period;
PIC32MZ_TIMER_SETPERIOD(oneshot->timer, (uint32_t)period);
/* Set up to receive the callback and start the timer */
PIC32MZ_TIMER_ACKINT(oneshot->timer);
PIC32MZ_TIMER_SETISR(oneshot->timer, pic32mz_oneshot_handler, oneshot);
PIC32MZ_TIMER_START(oneshot->timer);
oneshot->running = true;
leave_critical_section(flags);
return OK;
}
/****************************************************************************
* Name: pic32mz_oneshot_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:
* oneshot Caller allocated instance of the oneshot state structure. This
* structure must have been previously initialized via a call to
* pic32mz_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 pic32mz_oneshot_cancel(struct pic32mz_oneshot_s *oneshot,
struct timespec *ts)
{
irqstate_t flags;
uint64_t usec;
uint64_t sec;
uint64_t nsec;
uint32_t count;
uint32_t period;
flags = enter_critical_section();
/* Was the timer running? */
if (!oneshot->running)
{
/* No.. Just return zero timer remaining and successful cancellation.
* This function may execute at a high rate with no timer running
* (as when pre-emption is enabled and disabled).
*/
ts->tv_sec = 0;
ts->tv_nsec = 0;
leave_critical_section(flags);
return OK;
}
/* Yes.. Get the timer counter and period registers and stop the counter. */
tmrinfo("Cancelling...\n");
count = PIC32MZ_TIMER_GETCOUNTER(oneshot->timer);
period = oneshot->period;
PIC32MZ_TIMER_SETISR(oneshot->timer, NULL, NULL);
PIC32MZ_TIMER_STOP(oneshot->timer);
oneshot->running = false;
oneshot->handler = NULL;
oneshot->arg = NULL;
leave_critical_section(flags);
/* Did the caller provide us with a location to return the time
* remaining?
*/
if (ts)
{
/* Yes.. then calculate and return the time remaining on the
* oneshot timer.
*/
tmrinfo("period=%lu count=%lu\n",
(unsigned long)period, (unsigned long)count);
if (count >= period)
{
/* No time remaining (?) */
ts->tv_sec = 0;
ts->tv_nsec = 0;
}
else
{
/* The total time remaining is the difference. Convert the that
* to units of microseconds.
*
* frequency = ticks / second
* seconds = ticks * frequency
* usecs = (ticks * USEC_PER_SEC) / frequency;
*/
usec = (((uint64_t)(period - count)) * USEC_PER_SEC) /
oneshot->freq;
/* Return the time remaining in the correct form */
sec = usec / USEC_PER_SEC;
nsec = ((usec) - (sec * USEC_PER_SEC)) * NSEC_PER_USEC;
ts->tv_sec = (time_t)sec;
ts->tv_nsec = (unsigned long)nsec;
}
tmrinfo("remaining (%lu, %lu)\n",
(unsigned long)ts->tv_sec, (unsigned long)ts->tv_nsec);
}
return OK;
}
#endif /* CONFIG_PIC32MZ_ONESHOT */
+208
View File
@@ -0,0 +1,208 @@
/****************************************************************************
* arch/mips/src/pic32mz/chip/pic32mz-oneshort.h
*
* Copyright (C) 2019 Abdelatif Guettouche. All rights reserved.
* Author: Abdelatif Guettouche <abdelatif.guettouche@gmail.com>
*
* This file is a part of NuttX:
*
* Copyright (C) 2019 Gregory Nutt. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __ARCH_MIPS_SRC_PIC32MZ_PIC32MZ_ONESHOT_H
#define __ARCH_MIPS_SRC_PIC32MZ_PIC32MZ_ONESHOT_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <time.h>
#include <nuttx/irq.h>
#include "pic32mz-timer.h"
#ifdef CONFIG_PIC32MZ_ONESHOT
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#if !defined(CONFIG_PIC32MZ_ONESHOT_MAXTIMERS) || \
CONFIG_PIC32MZ_ONESHOT_MAXTIMERS < 1
# undef CONFIG_PIC32MZ_ONESHOT_MAXTIMERS
# define CONFIG_PIC32MZ_ONESHOT_MAXTIMERS 1
#endif
/****************************************************************************
* Public Types
****************************************************************************/
/* This describes the callback function that will be invoked when the oneshot
* timer expires. When 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 called
* pic32mz_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 pic32mz_oneshot_s
{
uint8_t chan; /* The timer/counter in use */
#if CONFIG_PIC32MZ_ONESHOT_MAXTIMERS > 1
uint8_t cbndx; /* Timer callback handler index */
#endif
volatile bool running; /* True: the timer is running */
FAR struct pic32mz_timer_dev_s *timer; /* PIC32MZ timer driver */
volatile oneshot_handler_t handler; /* Oneshot expiration callback */
volatile void *arg; /* Callback's argument */
uint32_t freq; /* Timer's frequency */
uint32_t period; /* Timer's period */
uint8_t width; /* Timer's width */
};
/****************************************************************************
* Public Data
****************************************************************************/
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: pic32mz_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 pic32mz_oneshot_initialize(struct pic32mz_oneshot_s *oneshot, int chan,
uint16_t resolution);
/****************************************************************************
* Name: pic32mz_oneshot_max_delay
*
* Description:
* Determine the maximum delay of the one-shot timer (in microseconds)
*
****************************************************************************/
int pic32mz_oneshot_max_delay(struct pic32mz_oneshot_s *oneshot,
uint64_t *usec);
/****************************************************************************
* Name: pic32mz_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
* pic32mz_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 pic32mz_oneshot_start(struct pic32mz_oneshot_s *oneshot,
oneshot_handler_t handler, void *arg,
const struct timespec *ts);
/****************************************************************************
* Name: pic32mz_oneshot_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:
* oneshot Caller allocated instance of the oneshot state structure. This
* structure must have been previously initialized via a call to
* pic32mz_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 pic32mz_oneshot_cancel(struct pic32mz_oneshot_s *oneshot,
struct timespec *ts);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* CONFIG_PIC32MZ_ONESHOT */
#endif /* __ARCH_MIPS_SRC_PIC32MZ_PIC32MZ_ONESHOT_H */
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+167
View File
@@ -0,0 +1,167 @@
/****************************************************************************
* arch/mips/src/pic32mz/chip/pic32mz-timer.h
*
* Copyright (C) 2019 Abdelatif Guettouche. All rights reserved.
* Author: Abdelatif Guettouche <abdelatif.guettouche@gmail.com>
*
* This file is a part of NuttX:
*
* Copyright (C) 2019 Gregory Nutt. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __ARCH_MIPS_SRC_PIC32MZ_PIC32MZ_TIMER_H
#define __ARCH_MIPS_SRC_PIC32MZ_PIC32MZ_TIMER_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/compiler.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Helpers ******************************************************************/
#define PIC32MZ_TIMER_START(d) ((d)->ops->start(d))
#define PIC32MZ_TIMER_STOP(d) ((d)->ops->stop(d))
#define PIC32MZ_TIMER_SETPERIOD(d,p) ((d)->ops->setperiod(d,p))
#define PIC32MZ_TIMER_GETCOUNTER(d) ((d)->ops->getcounter(d))
#define PIC32MZ_TIMER_SETCOUNTER(d,c) ((d)->ops->setcounter(d,c))
#define PIC32MZ_TIMER_GETFREQ(d) ((d)->ops->getfreq(d))
#define PIC32MZ_TIMER_SETFREQ(d,f) ((d)->ops->setfreq(d,f))
#define PIC32MZ_TIMER_GETWIDTH(d) ((d)->ops->getwidth(d))
#define PIC32MZ_TIMER_SETISR(d,hnd,arg) ((d)->ops->setisr(d,hnd,arg))
#define PIC32MZ_TIMER_ACKINT(d) ((d)->ops->ackint(d))
#define PIC32MZ_TIMER_CHECKINT(d) ((d)->ops->checkint(d))
/****************************************************************************
* Public Types
****************************************************************************/
#ifndef __ASSEMBLY__
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/* Timer's Operations */
struct pic32mz_timer_dev_s; /* Forward reference */
struct pic32mz_timer_ops_s
{
/* Timer's methods */
void (*start)(FAR struct pic32mz_timer_dev_s *dev);
void (*stop)(FAR struct pic32mz_timer_dev_s *dev);
void (*setperiod)(FAR struct pic32mz_timer_dev_s *dev, uint32_t p);
uint32_t (*getcounter)(FAR struct pic32mz_timer_dev_s *dev);
void (*setcounter)(FAR struct pic32mz_timer_dev_s *dev, uint32_t c);
uint32_t (*getfreq)(FAR struct pic32mz_timer_dev_s *dev);
bool (*setfreq)(FAR struct pic32mz_timer_dev_s *dev, uint32_t freq);
uint8_t (*getwidth)(FAR struct pic32mz_timer_dev_s *dev);
/* Timer's interrupts */
int (*setisr)(FAR struct pic32mz_timer_dev_s *dev, xcpt_t handler,
void * arg);
void (*ackint)(FAR struct pic32mz_timer_dev_s *dev);
bool (*checkint)(FAR struct pic32mz_timer_dev_s *dev);
};
/* Timer's Device Structure */
struct pic32mz_timer_dev_s
{
FAR struct pic32mz_timer_ops_s *ops;
};
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: pic32mz_timer_init
*
* Description:
* Power-up the timer and get its structure.
*
****************************************************************************/
FAR struct pic32mz_timer_dev_s *pic32mz_timer_init(int timer);
/****************************************************************************
* Name: pic32mz_timer_deinit
*
* Description:
* Power-down the timer and mark it as unused.
*
****************************************************************************/
int pic32mz_timer_deinit(FAR struct pic32mz_timer_dev_s *dev);
/****************************************************************************
* Name: pic32mz_timer_initialize
*
* Description:
* Bind the configuration timer to a timer lower half instance and
* register the timer drivers at 'devpath'
*
* Input Parameters:
* devpath The full path to the timer device.
* This should be of the form /dev/timer0
* timer The timer's number.
*
* Returned Value:
* Zero (OK) is returned on success; A negated errno value is returned
* to indicate the nature of any failure.
*
****************************************************************************/
#ifdef CONFIG_TIMER
int pic32mz_timer_initialize(FAR const char *devpath, int timer);
#endif
#undef EXTERN
#if defined(__cplusplus)
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_MIPS_SRC_PIC32MZ_PIC32MZ_TIMER_H */