summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-08-09 10:30:45 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-08-09 10:30:45 -0600
commit108b276b1235811d4200efef8a53b2cfcb8346ea (patch)
tree37cf0bb77270ba4be721a45c2cbe59f48433249d
parent4ed36015adda181f0662f18ad43b7600543b2464 (diff)
downloadnuttx-108b276b1235811d4200efef8a53b2cfcb8346ea.tar.gz
nuttx-108b276b1235811d4200efef8a53b2cfcb8346ea.tar.bz2
nuttx-108b276b1235811d4200efef8a53b2cfcb8346ea.zip
SAMA5 T/C: Can now handle non-constant BOARD_MCK_FREQUENCY. Also now supports methods to attach user interrupt handlers
-rw-r--r--nuttx/arch/arm/src/sama5/chip/sam_pmc.h1
-rw-r--r--nuttx/arch/arm/src/sama5/sam_tc.c415
-rw-r--r--nuttx/arch/arm/src/sama5/sam_tc.h50
-rw-r--r--nuttx/include/nuttx/watchdog.h11
4 files changed, 407 insertions, 70 deletions
diff --git a/nuttx/arch/arm/src/sama5/chip/sam_pmc.h b/nuttx/arch/arm/src/sama5/chip/sam_pmc.h
index 222149d7c..19940593d 100644
--- a/nuttx/arch/arm/src/sama5/chip/sam_pmc.h
+++ b/nuttx/arch/arm/src/sama5/chip/sam_pmc.h
@@ -423,6 +423,7 @@
# define SAMA5_HAVE_PMC_PCR_DIV 1 /* Supports conditional compilation */
# define PMC_PCR_DIV_SHIFT (16) /* Bits 16-17: Divisor Value */
# define PMC_PCR_DIV_MASK (3 << PMC_PCR_DIV_SHIFT)
+# define PMC_PCR_DIV(n) ((uint32_t)(n) << PMC_PCR_DIV_SHIFT)
# define PMC_PCR_DIV1 (0 << PMC_PCR_DIV_SHIFT) /* Peripheral clock is MCK */
# define PMC_PCR_DIV2 (1 << PMC_PCR_DIV_SHIFT) /* Peripheral clock is MCK/2 */
# define PMC_PCR_DIV4 (2 << PMC_PCR_DIV_SHIFT) /* Peripheral clock is MCK/4 */
diff --git a/nuttx/arch/arm/src/sama5/sam_tc.c b/nuttx/arch/arm/src/sama5/sam_tc.c
index 8f3865c86..c4a89aef7 100644
--- a/nuttx/arch/arm/src/sama5/sam_tc.c
+++ b/nuttx/arch/arm/src/sama5/sam_tc.c
@@ -58,6 +58,7 @@
#include <errno.h>
#include <debug.h>
+#include <nuttx/arch.h>
#include <arch/board/board.h>
#include "up_arch.h"
@@ -74,24 +75,6 @@
* Pre-processor Definitions
****************************************************************************/
-/* Clocking */
-
-#if BOARD_MCK_FREQUENCY <= SAM_TC_MAXPERCLK
-# define TC_FREQUENCY BOARD_MCK_FREQUENCY
-# define TC_PCR_DIV PMC_PCR_DIV1
-#elif (BOARD_MCK_FREQUENCY >> 1) <= SAM_TC_MAXPERCLK
-# define TC_FREQUENCY (BOARD_MCK_FREQUENCY >> 1)
-# define TC_PCR_DIV PMC_PCR_DIV2
-#elif (BOARD_MCK_FREQUENCY >> 2) <= SAM_TC_MAXPERCLK
-# define TC_FREQUENCY (BOARD_MCK_FREQUENCY >> 2)
-# define TC_PCR_DIV PMC_PCR_DIV4
-#elif (BOARD_MCK_FREQUENCY >> 3) <= SAM_TC_MAXPERCLK
-# define TC_FREQUENCY (BOARD_MCK_FREQUENCY >> 3)
-# define TC_PCR_DIV PMC_PCR_DIV8
-#else
-# error Cannot realize TC input frequency
-#endif
-
/* Timer debug is enabled if any timer client is enabled */
#ifndef CONFIG_DEBUG
@@ -146,17 +129,19 @@ struct sam_chan_s
{
struct sam_tc_s *tc; /* Parent timer/counter */
uintptr_t base; /* Channel register base address */
+ tc_handler_t handler; /* Attached interrupt handler */
+ void *arg; /* Interrupt handler argument */
uint8_t chan; /* Channel number (0, 1, or 2 OR 3, 4, or 5) */
bool inuse; /* True: channel is in use */
};
-/* This structure describes on timer/counter */
+/* This structure describes one timer/counter */
struct sam_tc_s
{
sem_t exclsem; /* Assures mutually exclusive access to TC */
uintptr_t base; /* Register base address */
- uint8_t pid; /* Peripheral ID */
+ uint8_t pid; /* Peripheral ID/irq number */
uint8_t tc; /* Timer/channel number (0 or 1) */
bool initialized; /* True: Timer data has been initialized */
@@ -202,8 +187,26 @@ static inline uint32_t sam_chan_getreg(struct sam_chan_s *chan,
static inline void sam_chan_putreg(struct sam_chan_s *chan,
unsigned int offset, uint32_t regval);
+/* Interrupt Handling *******************************************************/
+
+static int sam_tc_interrupt(struct sam_tc_s *tc);
+#ifdef CONFIG_SAMA5_TC0
+static int sam_tc012_interrupt(int irq, void *context);
+#endif
+#ifdef CONFIG_SAMA5_TC1
+static int sam_tc345_interrupt(int irq, void *context);
+#endif
+#ifdef CONFIG_SAMA5_TC2
+static int sam_tc678_interrupt(int irq, void *context);
+#endif
+
/* Initialization ***********************************************************/
+#ifdef SAMA5_HAVE_PMC_PCR_DIV
+static int sam_tc_mckdivider(uint32_t mck);
+#endif
+static int sam_tc_freqdiv(uint32_t ftc, int ndx);
+static uint32_t sam_tc_divfreq(uint32_t ftc, int ndx);
static inline struct sam_chan_s *sam_tc_initialize(int channel);
/****************************************************************************
@@ -437,28 +440,17 @@ static struct sam_tc_s g_tc678;
/* TC frequency data. This table provides the frequency for each selection of TCCLK */
-#define TC_NDIVIDERS 5
-
-/* This is the list of divider values */
-
-static const uint16_t g_divider[TC_NDIVIDERS] =
-{
- 2, /* TIMER_CLOCK1 -> div2 */
- 8, /* TIMER_CLOCK2 -> div8 */
- 32, /* TIMER_CLOCK3 -> div32 */
- 128, /* TIMER_CLOCK4 -> div128 */
- TC_FREQUENCY / 32768 /* TIMER_CLOCK5 -> slow clock (not really a divider) */
-};
+#define TC_NDIVIDERS 4
+#define TC_NDIVOPTIONS 5
-/* This is the list of divided down frequencies */
+/* This is the list of divider values: divider = (1 << value) */
-static const uint32_t g_divfreq[TC_NDIVIDERS] =
+static const uint8_t g_log2divider[TC_NDIVIDERS] =
{
- TC_FREQUENCY / 2, /* TIMER_CLOCK1 -> div2 */
- TC_FREQUENCY / 8, /* TIMER_CLOCK2 -> div8 */
- TC_FREQUENCY / 32, /* TIMER_CLOCK3 -> div32 */
- TC_FREQUENCY / 128, /* TIMER_CLOCK4 -> div128 */
- 32768 /* TIMER_CLOCK5 -> slow clock */
+ 1, /* TIMER_CLOCK1 -> div2 */
+ 3, /* TIMER_CLOCK2 -> div8 */
+ 5, /* TIMER_CLOCK3 -> div32 */
+ 7 /* TIMER_CLOCK4 -> div128 */
};
/* TC register lookup used by sam_tc_setregister */
@@ -700,9 +692,217 @@ static inline void sam_chan_putreg(struct sam_chan_s *chan, unsigned int offset,
}
/****************************************************************************
+ * Interrupt Handling
+ ****************************************************************************/
+/****************************************************************************
+ * Name: sam_tc_interrupt
+ *
+ * Description:
+ * Common timer channel interrupt handling.
+ *
+ * Input Parameters:
+ * tc Timer status instance
+ *
+ * Returned Value:
+ * A pointer to the initialized timer channel structure associated with tc
+ * and channel. NULL is returned on any failure.
+ *
+ * On successful return, the caller holds the tc exclusive access semaphore.
+ *
+ ****************************************************************************/
+
+static int sam_tc_interrupt(struct sam_tc_s *tc)
+{
+ struct sam_chan_s *chan;
+ uint32_t sr;
+ uint32_t imr;
+ uint32_t pending;
+ int i;
+
+ /* Process interrupts on each channel */
+
+ for (i = 0; i < 3; i++)
+ {
+ /* Get the handy channel reference */
+
+ chan = &tc->channel[i];
+
+ /* Get the interrupt status for this channel */
+
+ sr = sam_chan_getreg(chan, SAM_TC_SR_OFFSET);
+ imr = sam_chan_getreg(chan, SAM_TC_IMR_OFFSET);
+ pending = sr & imr;
+
+ /* Are there any pending interrupts for this channel? */
+
+ if (pending)
+ {
+ /* Yes... if we have pending interrupts then interrupts must be
+ * enabled and we must have a handler attached.
+ */
+
+ DEBUGASSERT(chan->handler);
+ if (chan->handler)
+ {
+ /* Execute the callback */
+
+ chan->handler(chan, chan->arg, sr);
+ }
+ else
+ {
+ /* Should never happen */
+
+ sam_chan_putreg(chan, SAM_TC_IDR_OFFSET, TC_INT_ALL);
+ }
+ }
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: sam_tcABC_interrupt
+ *
+ * Description:
+ * Timer block interrupt handlers
+ *
+ * Input Parameters:
+ * chan TC channel structure
+ * sr The status register value that generated the interrupt
+ *
+ * Returned Value:
+ * A pointer to the initialized timer channel structure associated with tc
+ * and channel. NULL is returned on any failure.
+ *
+ * On successful return, the caller holds the tc exclusive access semaphore.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SAMA5_TC0
+static int sam_tc012_interrupt(int irq, void *context)
+{
+ return sam_tc_interrupt(&g_tc012);
+}
+#endif
+
+#ifdef CONFIG_SAMA5_TC1
+static int sam_tc345_interrupt(int irq, void *context)
+{
+ return sam_tc_interrupt(&g_tc345);
+}
+#endif
+
+#ifdef CONFIG_SAMA5_TC2
+static int sam_tc678_interrupt(int irq, void *context)
+{
+ return sam_tc_interrupt(&g_tc678);
+}
+#endif
+
+/****************************************************************************
* Initialization
****************************************************************************/
/****************************************************************************
+ * Name: sam_tc_mckdivider
+ *
+ * Description:
+ * Return the TC clock input divider value. One of n=0..3 corresponding
+ * to divider values of {1, 2, 4, 8}.
+ *
+ * NOTE: The SAMA5D4 has no clock input divider
+ *
+ * Input Parameters:
+ * mck - The MCK frequency to be divider.
+ *
+ * Returned Value:
+ * Log2 of the TC clock divider.
+ *
+ ****************************************************************************/
+
+#ifdef SAMA5_HAVE_PMC_PCR_DIV
+static int sam_tc_mckdivider(uint32_t mck)
+{
+ if (mck <= SAM_TC_MAXPERCLK)
+ {
+ return 0;
+ }
+ else if ((mck >> 1) <= SAM_TC_MAXPERCLK)
+ {
+ return 1;
+ }
+ else if ((mck >> 2) <= SAM_TC_MAXPERCLK)
+ {
+ return 2;
+ }
+ else /* if ((mck >> 3) <= SAM_TC_MAXPERCLK) */
+ {
+ DEBUGASSERT((mck >> 3) <= SAM_TC_MAXPERCLK);
+ return 3;
+ }
+}
+#endif
+
+/****************************************************************************
+ * Name: sam_tc_freqdiv
+ *
+ * Description:
+ * Given the TC input frequency (Ftc) and a divider index, return the value of
+ * the Ftc divider.
+ *
+ * Input Parameters:
+ * ftc - TC input frequency
+ * ndx - Divider index
+ *
+ * Returned Value:
+ * The ftc input divider value
+ *
+ ****************************************************************************/
+
+static int sam_tc_freqdiv(uint32_t ftc, int ndx)
+{
+ /* The final option is to use the SLOW clock */
+
+ if (ndx >= TC_NDIVIDERS)
+ {
+ return ftc / BOARD_SLOWCLK_FREQUENCY;
+ }
+ else
+ {
+ return 1 << g_log2divider[ndx];
+ }
+}
+
+/****************************************************************************
+ * Name: sam_tc_divfreq
+ *
+ * Description:
+ * Given the TC input frequency (Ftc) and a divider index, return the value of
+ * the divided frequency
+ *
+ * Input Parameters:
+ * ftc - TC input frequency
+ * ndx - Divider index
+ *
+ * Returned Value:
+ * The divided frequency value
+ *
+ ****************************************************************************/
+
+static uint32_t sam_tc_divfreq(uint32_t ftc, int ndx)
+{
+ /* The final option is to use the SLOW clock */
+
+ if (ndx >= TC_NDIVIDERS)
+ {
+ return BOARD_SLOWCLK_FREQUENCY;
+ }
+ else
+ {
+ return ftc >> g_log2divider[ndx];
+ }
+}
+
+/****************************************************************************
* Name: sam_tc_initialize
*
* Description:
@@ -724,11 +924,12 @@ static inline void sam_chan_putreg(struct sam_chan_s *chan, unsigned int offset,
static inline struct sam_chan_s *sam_tc_initialize(int channel)
{
- FAR struct sam_tc_s *tc;
- FAR const struct sam_tcconfig_s *tcconfig;
- FAR struct sam_chan_s *chan;
- FAR const struct sam_chconfig_s *chconfig;
+ struct sam_tc_s *tc;
+ const struct sam_tcconfig_s *tcconfig;
+ struct sam_chan_s *chan;
+ const struct sam_chconfig_s *chconfig;
irqstate_t flags;
+ xcpt_t handler;
uint32_t regval;
uint8_t ch;
int i;
@@ -742,6 +943,7 @@ static inline struct sam_chan_s *sam_tc_initialize(int channel)
{
tc = &g_tc012;
tcconfig = &g_tc012config;
+ handler = sam_tc012_interrupt;
}
else
#endif
@@ -750,6 +952,7 @@ static inline struct sam_chan_s *sam_tc_initialize(int channel)
{
tc = &g_tc345;
tcconfig = &g_tc345config;
+ handler = sam_tc345_interrupt;
}
else
#endif
@@ -758,6 +961,7 @@ static inline struct sam_chan_s *sam_tc_initialize(int channel)
{
tc = &g_tc678;
tcconfig = &g_tc678config;
+ handler = sam_tc678_interrupt;
}
else
#endif
@@ -820,17 +1024,34 @@ static inline struct sam_chan_s *sam_tc_initialize(int channel)
sam_configpio(chconfig->tiobset);
}
+
+ /* Disable and clear all channel interrupts */
+
+ sam_chan_putreg(chan, SAM_TC_IDR_OFFSET, TC_INT_ALL);
+ (void)sam_chan_getreg(chan, SAM_TC_SR_OFFSET);
}
/* Set the maximum TC peripheral clock frequency */
- regval = PMC_PCR_PID(tcconfig->pid) | PMC_PCR_CMD | TC_PCR_DIV | PMC_PCR_EN;
+ regval = PMC_PCR_PID(tcconfig->pid) | PMC_PCR_CMD | PMC_PCR_EN;
+
+#ifdef SAMA5_HAVE_PMC_PCR_DIV
+ /* Set the MCK divider (if any) */
+
+ regval |= PMC_PCR_DIV(sam_tc_mckdivider(BOARD_MCK_FREQUENCY));
+#endif
+
putreg32(regval, SAM_PMC_PCR);
/* Enable clocking to the timer counter */
sam_enableperiph0(tcconfig->pid);
+ /* Attach the timer interrupt handler and enable the timer interrupts */
+
+ (void)irq_attach(tc->pid, handler);
+ up_enable_irq(tc->pid);
+
/* Now the channel is initialized */
tc->initialized = true;
@@ -981,6 +1202,60 @@ void sam_tc_start(TC_HANDLE handle)
}
/****************************************************************************
+ * Name: sam_tc_attach
+ *
+ * Description:
+ * Attach or detach an interrupt handler to the timer interrupt. The
+ * interrupt is detached if the handler argument is NULL.
+ *
+ * Input Parameters:
+ * handle The handle that represents the timer state
+ * handler The interrupt handler that will be invoked when the interrupt
+ * condition occurs
+ * arg An opaque argument that will be provided when the interrupt
+ * handler callback is executed.
+ * mask The value of the timer interrupt mask register that defines
+ * which interrupts should be disabled.
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+tc_handler_t sam_tc_attach(TC_HANDLE handle, tc_handler_t handler,
+ void *arg, uint32_t mask)
+{
+ struct sam_chan_s *chan = (struct sam_chan_s *)handle;
+ tc_handler_t oldhandler;
+ irqstate_t flags;
+
+ DEBUGASSERT(chan);
+
+ /* Remember the old interrupt handler and set the new handler */
+
+ flags = irqsave();
+ oldhandler = handler;
+ chan->handler = handler;
+
+ /* Don't enable interrupt if we are detaching no matter what the caller
+ * says.
+ */
+
+ if (!handler)
+ {
+ arg = NULL;
+ mask = 0;
+ }
+
+ /* Now enable interrupt as requested */
+
+ sam_chan_putreg(chan, SAM_TC_IDR_OFFSET, TC_INT_ALL & ~mask);
+ sam_chan_putreg(chan, SAM_TC_IER_OFFSET, TC_INT_ALL & mask);
+ irqrestore(flags);
+
+ return oldhandler;
+}
+
+/****************************************************************************
* Name: sam_tc_stop
*
* Description:
@@ -1009,9 +1284,9 @@ void sam_tc_stop(TC_HANDLE handle)
*
* Description:
* Set TC_RA, TC_RB, or TC_RB using the provided divisor. The actual
- * setting in the register will be the TC input frequency divided by
+ * setting in the register will be the TC input frequency (Ftc) divided by
* the provided divider (which should derive from the divider returned
- * by sam_tc_divider).
+ * by sam_tc_divisor).
*
* Input Parameters:
* handle Channel handle previously allocated by sam_tc_allocate()
@@ -1024,13 +1299,15 @@ void sam_tc_stop(TC_HANDLE handle)
void sam_tc_setregister(TC_HANDLE handle, int reg, unsigned int div)
{
struct sam_chan_s *chan = (struct sam_chan_s *)handle;
+ uint32_t frequency;
uint32_t regval;
DEBUGASSERT(reg < TC_NREGISTERS);
- regval = TC_FREQUENCY / div;
+ frequency = sam_tc_frequency();
+ regval = frequency / div;
tcvdbg("Channel %d: Set register %d to %d / %d = %d\n",
- chan->chan, reg, TC_FREQUENCY, div, (unsigned int)regval);
+ chan->chan, reg, frequency, div, (unsigned int)regval);
sam_chan_putreg(chan, g_regoffset[reg], regval);
sam_regdump(chan, "Set register");
@@ -1040,8 +1317,9 @@ void sam_tc_setregister(TC_HANDLE handle, int reg, unsigned int div)
* Name: sam_tc_frequency
*
* Description:
- * Return the timer input frequency, that is, the MCK frequency divided
- * down so that the timer/counter is driven within its maximum frequency.
+ * Return the timer input frequency (Ftc), that is, the MCK frequency
+ * divided down so that the timer/counter is driven within its maximum
+ * frequency.
*
* Input Parameters:
* None
@@ -1053,7 +1331,13 @@ void sam_tc_setregister(TC_HANDLE handle, int reg, unsigned int div)
uint32_t sam_tc_frequency(void)
{
- return TC_FREQUENCY;
+#ifdef SAMA5_HAVE_PMC_PCR_DIV
+ uint32_t mck = BOARD_MCK_FREQUENCY;
+ int shift = sam_tc_mckdivider(mck);
+ return mck >> shift;
+#else
+ return BOARD_MCK_FREQUENCY;
+#endif
}
/****************************************************************************
@@ -1066,7 +1350,7 @@ uint32_t sam_tc_frequency(void)
* (Ftc / (div * 65536)) <= freq <= (Ftc / dev)
*
* where:
- * freq - the desitred frequency
+ * freq - the desired frequency
* Ftc - The timer/counter input frequency
* div - With DIV being the highest possible value.
*
@@ -1083,15 +1367,19 @@ uint32_t sam_tc_frequency(void)
int sam_tc_divisor(uint32_t frequency, uint32_t *div, uint32_t *tcclks)
{
+ uint32_t ftc = sam_tc_frequency();
int ndx = 0;
tcvdbg("frequency=%d\n", frequency);
- /* Satisfy lower bound */
+ /* Satisfy lower bound. That is, the value of the divider such that:
+ *
+ * frequency >= tc_input_frequency / divider.
+ */
- while (frequency < (g_divfreq[ndx] >> 16))
+ while (frequency < (sam_tc_divfreq(ftc, ndx) >> 16))
{
- if (++ndx > TC_NDIVIDERS)
+ if (++ndx > TC_NDIVOPTIONS)
{
/* If no divisor can be found, return -ERANGE */
@@ -1100,11 +1388,15 @@ int sam_tc_divisor(uint32_t frequency, uint32_t *div, uint32_t *tcclks)
}
}
- /* Try to maximize DIV while still satisfying upper bound */
+ /* Try to maximize DIV while still satisfying upper bound. That the
+ * value of the divider such that:
+ *
+ * frequency < tc_input_frequency / divider.
+ */
- for (; ndx < (TC_NDIVIDERS-1); ndx++)
+ for (; ndx < (TC_NDIVOPTIONS-1); ndx++)
{
- if (frequency > g_divfreq[ndx + 1])
+ if (frequency > sam_tc_divfreq(ftc, ndx + 1))
{
break;
}
@@ -1114,11 +1406,12 @@ int sam_tc_divisor(uint32_t frequency, uint32_t *div, uint32_t *tcclks)
if (div)
{
- tcvdbg("return div=%d\n", g_divider[ndx]);
- *div = g_divider[ndx];
+ uint32_t value = sam_tc_freqdiv(ftc, ndx);
+ tcvdbg("return div=%lu\n", (unsigned long)value);
+ *div = value;
}
- /* REturn the TCCLKS selection */
+ /* Return the TCCLKS selection */
if (tcclks)
{
diff --git a/nuttx/arch/arm/src/sama5/sam_tc.h b/nuttx/arch/arm/src/sama5/sam_tc.h
index 50585f7a1..b767158ef 100644
--- a/nuttx/arch/arm/src/sama5/sam_tc.h
+++ b/nuttx/arch/arm/src/sama5/sam_tc.h
@@ -55,12 +55,15 @@
/* The timer/counter and channel arguments to sam_tc_allocate() */
-#define TC_CHAN0 0
+#define TC_CHAN0 0 /* TC0 */
#define TC_CHAN1 1
#define TC_CHAN2 2
-#define TC_CHAN3 3
+#define TC_CHAN3 3 /* TC1 */
#define TC_CHAN4 4
#define TC_CHAN5 5
+#define TC_CHAN6 6 /* TC2 */
+#define TC_CHAN7 7
+#define TC_CHAN8 8
/* Register identifier used with sam_tc_setregister */
@@ -71,9 +74,21 @@
/****************************************************************************
* Public Types
****************************************************************************/
+/* An opaque handle used to represent a timer channel */
typedef void *TC_HANDLE;
+/* Timer interrupt callback. When a timer interrup expires, the client will
+ * receive:
+ *
+ * handle - The handle that represents the timer state
+ * arg - An opaque argument provided when the interrupt was registered
+ * sr - The value of the timer interrupt status register at the time
+ * that the interrupt occurred.
+ */
+
+typedef void (*tc_handler_t)(TC_HANDLE handle, void *arg, uint32_t sr);
+
/****************************************************************************
* Public Data
****************************************************************************/
@@ -145,6 +160,33 @@ void sam_tc_free(TC_HANDLE handle);
void sam_tc_start(TC_HANDLE handle);
/****************************************************************************
+ * Name: sam_tc_attach/sam_tc_detach
+ *
+ * Description:
+ * Attach or detach an interrupt handler to the timer interrupt. The
+ * interrupt is detached if the handler argument is NULL.
+ *
+ * Input Parameters:
+ * handle The handle that represents the timer state
+ * handler The interrupt handler that will be invoked when the interrupt
+ * condition occurs
+ * arg An opaque argument that will be provided when the interrupt
+ * handler callback is executed. Ignored if handler is NULL.
+ * mask The value of the timer interrupt mask register that defines
+ * which interrupts should be disabled. Ignored if handler is
+ * NULL.
+ *
+ * Returned Value:
+ * The address of the previous handler, if any.
+ *
+ ****************************************************************************/
+
+tc_handler_t sam_tc_attach(TC_HANDLE handle, tc_handler_t handler,
+ void *arg, uint32_t mask);
+
+#define sam_tc_detach(h) sam_tc_attach(h, NULL, NULL, 0)
+
+/****************************************************************************
* Name: sam_tc_stop
*
* Description:
@@ -166,7 +208,7 @@ void sam_tc_stop(TC_HANDLE handle);
* Set TC_RA, TC_RB, or TC_RB using the provided divisor. The actual
* setting in the register will be the TC input frequency divided by
* the provided divider (which should derive from the divider returned
- * by sam_tc_divider).
+ * by sam_tc_divisor).
*
*
* Input Parameters:
@@ -206,7 +248,7 @@ uint32_t sam_tc_frequency(void);
* (Ftc / (div * 65536)) <= freq <= (Ftc / dev)
*
* where:
- * freq - the desitred frequency
+ * freq - the desired frequency
* Ftc - The timer/counter input frequency
* div - With DIV being the highest possible value.
*
diff --git a/nuttx/include/nuttx/watchdog.h b/nuttx/include/nuttx/watchdog.h
index fd92ac7ad..2daa38142 100644
--- a/nuttx/include/nuttx/watchdog.h
+++ b/nuttx/include/nuttx/watchdog.h
@@ -197,7 +197,8 @@ struct watchdog_lowerhalf_s
#ifdef __cplusplus
#define EXTERN extern "C"
-extern "C" {
+extern "C"
+{
#else
#define EXTERN extern
#endif
@@ -235,8 +236,8 @@ extern "C" {
*
****************************************************************************/
-EXTERN FAR void *watchdog_register(FAR const char *path,
- FAR struct watchdog_lowerhalf_s *lower);
+FAR void *watchdog_register(FAR const char *path,
+ FAR struct watchdog_lowerhalf_s *lower);
/****************************************************************************
* Name: watchdog_unregister
@@ -253,7 +254,7 @@ EXTERN FAR void *watchdog_register(FAR const char *path,
*
****************************************************************************/
-EXTERN void watchdog_unregister(FAR void *handle);
+void watchdog_unregister(FAR void *handle);
/****************************************************************************
* Platform-Independent "Lower-Half" Watchdog Driver Interfaces
@@ -282,7 +283,7 @@ EXTERN void watchdog_unregister(FAR void *handle);
*
****************************************************************************/
-EXTERN int up_wdginitialize(void);
+int up_wdginitialize(void);
#undef EXTERN
#ifdef __cplusplus