You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/01/09 09:44:28 UTC

[incubator-nuttx] branch master updated: arch/arm/samv7: rework SAMv7 timer counter implementation

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 1fd51cc  arch/arm/samv7: rework SAMv7 timer counter implementation
1fd51cc is described below

commit 1fd51ccbe244b554386baa78d1922af5dd89d835
Author: Petro Karashchenko <pe...@gmail.com>
AuthorDate: Mon Jan 3 15:01:47 2022 +0200

    arch/arm/samv7: rework SAMv7 timer counter implementation
    
    There are two issues that are addressed with this change:
     - According to SAM E70/S70/V70/V71 Family datasheet the
       timer counter channels are 16-bit so timer counter
       value should be changed from uint32_t to uint16_t
     - The interrupt handling for timer counter channels can
       be simplified
    
    Signed-off-by: Petro Karashchenko <pe...@gmail.com>
---
 arch/arm/src/sam34/sam4cm_freerun.c |   2 +-
 arch/arm/src/sam34/sam4cm_oneshot.c |   4 +-
 arch/arm/src/sam34/sam4cm_tc.c      |   2 +-
 arch/arm/src/sama5/sam_freerun.c    |   2 +-
 arch/arm/src/sama5/sam_oneshot.c    |   4 +-
 arch/arm/src/sama5/sam_tc.c         |   2 +-
 arch/arm/src/samd5e5/sam_freerun.c  |   5 +-
 arch/arm/src/samd5e5/sam_oneshot.c  |   7 +-
 arch/arm/src/samd5e5/sam_tc.c       |   4 +-
 arch/arm/src/samv7/Kconfig          |   6 +-
 arch/arm/src/samv7/sam_freerun.c    |   9 +--
 arch/arm/src/samv7/sam_oneshot.c    |   9 +--
 arch/arm/src/samv7/sam_oneshot.h    |   2 +-
 arch/arm/src/samv7/sam_tc.c         | 148 ++++--------------------------------
 arch/arm/src/samv7/sam_tc.h         |   7 +-
 15 files changed, 45 insertions(+), 168 deletions(-)

diff --git a/arch/arm/src/sam34/sam4cm_freerun.c b/arch/arm/src/sam34/sam4cm_freerun.c
index 5f46155..3c6bff3 100644
--- a/arch/arm/src/sam34/sam4cm_freerun.c
+++ b/arch/arm/src/sam34/sam4cm_freerun.c
@@ -308,7 +308,7 @@ int sam_freerun_uninitialize(struct sam_freerun_s *freerun)
 
   /* Now we can disable the timer interrupt and disable the timer. */
 
-  sam_tc_attach(freerun->tch, NULL, NULL, 0);
+  sam_tc_detach(freerun->tch);
   sam_tc_stop(freerun->tch);
 
   /* Free the timer */
diff --git a/arch/arm/src/sam34/sam4cm_oneshot.c b/arch/arm/src/sam34/sam4cm_oneshot.c
index 431ba4a..cd928fe 100644
--- a/arch/arm/src/sam34/sam4cm_oneshot.c
+++ b/arch/arm/src/sam34/sam4cm_oneshot.c
@@ -99,7 +99,7 @@ static void sam_oneshot_handler(TC_HANDLE tch, void *arg, uint32_t sr)
    * Disable the TC now and disable any further interrupts.
    */
 
-  sam_tc_attach(oneshot->tch, NULL, NULL, 0);
+  sam_tc_detach(oneshot->tch);
   sam_tc_stop(oneshot->tch);
 
   /* The timer is no longer running */
@@ -440,7 +440,7 @@ int sam_oneshot_cancel(struct sam_oneshot_s *oneshot,
 
   /* Now we can disable the interrupt and stop the timer. */
 
-  sam_tc_attach(oneshot->tch, NULL, NULL, 0);
+  sam_tc_detach(oneshot->tch);
   sam_tc_stop(oneshot->tch);
 
   oneshot->running = false;
diff --git a/arch/arm/src/sam34/sam4cm_tc.c b/arch/arm/src/sam34/sam4cm_tc.c
index 39e0056..e16129a 100644
--- a/arch/arm/src/sam34/sam4cm_tc.c
+++ b/arch/arm/src/sam34/sam4cm_tc.c
@@ -921,7 +921,7 @@ void sam_tc_free(TC_HANDLE handle)
    * is stopped and disabled.
    */
 
-  sam_tc_attach(handle, NULL, NULL, 0);
+  sam_tc_detach(handle);
   sam_tc_stop(handle);
 
   /* Mark the channel as available */
diff --git a/arch/arm/src/sama5/sam_freerun.c b/arch/arm/src/sama5/sam_freerun.c
index 901477b..d7072bc 100644
--- a/arch/arm/src/sama5/sam_freerun.c
+++ b/arch/arm/src/sama5/sam_freerun.c
@@ -309,7 +309,7 @@ int sam_freerun_uninitialize(struct sam_freerun_s *freerun)
 
   /* Now we can disable the timer interrupt and disable the timer. */
 
-  sam_tc_attach(freerun->tch, NULL, NULL, 0);
+  sam_tc_detach(freerun->tch);
   sam_tc_stop(freerun->tch);
 
   /* Free the timer */
diff --git a/arch/arm/src/sama5/sam_oneshot.c b/arch/arm/src/sama5/sam_oneshot.c
index d60e381..13e3367 100644
--- a/arch/arm/src/sama5/sam_oneshot.c
+++ b/arch/arm/src/sama5/sam_oneshot.c
@@ -100,7 +100,7 @@ static void sam_oneshot_handler(TC_HANDLE tch, void *arg, uint32_t sr)
    * Disable the TC now and disable any further interrupts.
    */
 
-  sam_tc_attach(oneshot->tch, NULL, NULL, 0);
+  sam_tc_detach(oneshot->tch);
   sam_tc_stop(oneshot->tch);
 
   /* The timer is no longer running */
@@ -451,7 +451,7 @@ int sam_oneshot_cancel(struct sam_oneshot_s *oneshot,
 
   /* Now we can disable the interrupt and stop the timer. */
 
-  sam_tc_attach(oneshot->tch, NULL, NULL, 0);
+  sam_tc_detach(oneshot->tch);
   sam_tc_stop(oneshot->tch);
 
   oneshot->running = false;
diff --git a/arch/arm/src/sama5/sam_tc.c b/arch/arm/src/sama5/sam_tc.c
index 7fe7120..4a1a26a 100644
--- a/arch/arm/src/sama5/sam_tc.c
+++ b/arch/arm/src/sama5/sam_tc.c
@@ -1177,7 +1177,7 @@ void sam_tc_free(TC_HANDLE handle)
    * is stopped and disabled.
    */
 
-  sam_tc_attach(handle, NULL, NULL, 0);
+  sam_tc_detach(handle);
   sam_tc_stop(handle);
 
   /* Mark the channel as available */
diff --git a/arch/arm/src/samd5e5/sam_freerun.c b/arch/arm/src/samd5e5/sam_freerun.c
index 4fc1640..5b42d65 100644
--- a/arch/arm/src/samd5e5/sam_freerun.c
+++ b/arch/arm/src/samd5e5/sam_freerun.c
@@ -121,8 +121,7 @@ int sam_freerun_initialize(struct sam_freerun_s *freerun, int chan,
 
   /* Set up to receive the callback when the counter overflow occurs */
 
-  (void)sam_tc_attach(freerun->tch, sam_freerun_handler,
-                      freerun, TC_INTFLAG_OVF);
+  sam_tc_attach(freerun->tch, sam_freerun_handler, freerun, TC_INTFLAG_OVF);
 
   /* Start the counter */
 
@@ -241,7 +240,7 @@ int sam_freerun_uninitialize(struct sam_freerun_s *freerun)
 
   /* Now we can disable the timer interrupt and disable the timer. */
 
-  sam_tc_attach(freerun->tch, NULL, NULL, 0);
+  sam_tc_detach(freerun->tch);
   sam_tc_stop(freerun->tch);
 
   /* Free the timer */
diff --git a/arch/arm/src/samd5e5/sam_oneshot.c b/arch/arm/src/samd5e5/sam_oneshot.c
index 55c6be2..b5ebf70 100644
--- a/arch/arm/src/samd5e5/sam_oneshot.c
+++ b/arch/arm/src/samd5e5/sam_oneshot.c
@@ -75,7 +75,7 @@ static void sam_oneshot_handler(TC_HANDLE tch, void *arg, uint32_t sr)
    * Disable the TC now and disable any further interrupts.
    */
 
-  sam_tc_attach(oneshot->tch, NULL, NULL, 0);
+  sam_tc_detach(oneshot->tch);
   sam_tc_stop(oneshot->tch);
 
   /* The timer is no longer running */
@@ -250,8 +250,7 @@ int sam_oneshot_start(struct sam_oneshot_s *oneshot,
 
   /* Set up to receive the callback when the interrupt occurs */
 
-  (void)sam_tc_attach(oneshot->tch, sam_oneshot_handler,
-                      oneshot, TC_INTFLAG_MC0);
+  sam_tc_attach(oneshot->tch, sam_oneshot_handler, oneshot, TC_INTFLAG_MC0);
 
   /* Set CC0 so that an event will be triggered when COUNT register
    * counts up to CC0.
@@ -382,7 +381,7 @@ int sam_oneshot_cancel(struct sam_oneshot_s *oneshot,
 
   /* Now we can disable the interrupt and stop the timer. */
 
-  sam_tc_attach(oneshot->tch, NULL, NULL, 0);
+  sam_tc_attach(oneshot->tch);
   sam_tc_stop(oneshot->tch);
 
   oneshot->running = false;
diff --git a/arch/arm/src/samd5e5/sam_tc.c b/arch/arm/src/samd5e5/sam_tc.c
index ad28879..3b5f80f 100644
--- a/arch/arm/src/samd5e5/sam_tc.c
+++ b/arch/arm/src/samd5e5/sam_tc.c
@@ -342,7 +342,7 @@ void tc_bridge_enable(int tc)
 
 static void tc_wait_synchronization(struct sam_tc_dev_s *priv)
 {
-  while ((getreg32(priv->attr->base +  SAM_TC_SYNCBUSY_OFFSET) & 0x7) != 0);
+  while ((getreg32(priv->attr->base + SAM_TC_SYNCBUSY_OFFSET) & 0x7) != 0);
 }
 
 /****************************************************************************
@@ -760,7 +760,7 @@ void sam_tc_free(TC_HANDLE handle)
    * is stopped and disabled.
    */
 
-  sam_tc_attach(handle, NULL, NULL, 0);
+  sam_tc_detach(handle);
   sam_tc_stop(handle);
 
   /* Mark the channel as available */
diff --git a/arch/arm/src/samv7/Kconfig b/arch/arm/src/samv7/Kconfig
index 676b469..604aa91 100644
--- a/arch/arm/src/samv7/Kconfig
+++ b/arch/arm/src/samv7/Kconfig
@@ -670,7 +670,7 @@ config SAMV7_TC2
 	select SAMV7_HAVE_TC
 
 config SAMV7_TC3
-	bool "Timer Counter 3 (ch. 9, 10, 11) (TC2)"
+	bool "Timer Counter 3 (ch. 9, 10, 11) (TC3)"
 	default n
 	select SAMV7_HAVE_TC
 
@@ -1860,7 +1860,7 @@ if SCHED_TICKLESS
 config SAMV7_TICKLESS_ONESHOT
 	int "Tickless one-shot timer channel"
 	default 0
-	range 0 8
+	range 0 11
 	---help---
 		If the Tickless OS feature is enabled, the one clock must be
 		assigned to provided the one-shot timer needed by the OS.
@@ -1868,7 +1868,7 @@ config SAMV7_TICKLESS_ONESHOT
 config SAMV7_TICKLESS_FREERUN
 	int "Tickless free-running timer channel"
 	default 1
-	range 0 8
+	range 0 11
 	---help---
 		If the Tickless OS feature is enabled, the one clock must be
 		assigned to provided the free-running timer needed by the OS.
diff --git a/arch/arm/src/samv7/sam_freerun.c b/arch/arm/src/samv7/sam_freerun.c
index 27a5fa7..b3a026a 100644
--- a/arch/arm/src/samv7/sam_freerun.c
+++ b/arch/arm/src/samv7/sam_freerun.c
@@ -189,8 +189,7 @@ int sam_freerun_initialize(struct sam_freerun_s *freerun, int chan,
 
   /* Set up to receive the callback when the counter overflow occurs */
 
-  sam_tc_attach(freerun->tch, sam_freerun_handler, freerun,
-                TC_INT_COVFS);
+  sam_tc_attach(freerun->tch, sam_freerun_handler, freerun, TC_INT_COVFS);
 
   /* Start the counter */
 
@@ -220,11 +219,11 @@ int sam_freerun_initialize(struct sam_freerun_s *freerun, int chan,
 int sam_freerun_counter(struct sam_freerun_s *freerun, struct timespec *ts)
 {
   uint64_t usec;
-  uint32_t counter;
-  uint32_t verify;
   uint32_t sr;
   uint32_t overflow;
   uint32_t sec;
+  uint16_t counter;
+  uint16_t verify;
   irqstate_t flags;
 
   DEBUGASSERT(freerun && freerun->tch && ts);
@@ -310,7 +309,7 @@ int sam_freerun_uninitialize(struct sam_freerun_s *freerun)
 
   /* Now we can disable the timer interrupt and disable the timer. */
 
-  sam_tc_attach(freerun->tch, NULL, NULL, 0);
+  sam_tc_detach(freerun->tch);
   sam_tc_stop(freerun->tch);
 
   /* Free the timer */
diff --git a/arch/arm/src/samv7/sam_oneshot.c b/arch/arm/src/samv7/sam_oneshot.c
index 6010526..c87dc95 100644
--- a/arch/arm/src/samv7/sam_oneshot.c
+++ b/arch/arm/src/samv7/sam_oneshot.c
@@ -101,7 +101,7 @@ static void sam_oneshot_handler(TC_HANDLE tch, void *arg, uint32_t sr)
    * Disable the TC now and disable any further interrupts.
    */
 
-  sam_tc_attach(oneshot->tch, NULL, NULL, 0);
+  sam_tc_detach(oneshot->tch);
   sam_tc_stop(oneshot->tch);
 
   /* The timer is no longer running */
@@ -321,8 +321,7 @@ int sam_oneshot_start(struct sam_oneshot_s *oneshot,
 
   /* Set up to receive the callback when the interrupt occurs */
 
-  sam_tc_attach(oneshot->tch, sam_oneshot_handler, oneshot,
-                TC_INT_CPCS);
+  sam_tc_attach(oneshot->tch, sam_oneshot_handler, oneshot, TC_INT_CPCS);
 
   /* Set RC so that an event will be triggered when TC_CV register counts
    * up to RC.
@@ -400,8 +399,8 @@ int sam_oneshot_cancel(struct sam_oneshot_s *oneshot,
   uint64_t usec;
   uint64_t sec;
   uint64_t nsec;
-  uint32_t count;
   uint32_t rc;
+  uint16_t count;
 
   /* Was the timer running? */
 
@@ -451,7 +450,7 @@ int sam_oneshot_cancel(struct sam_oneshot_s *oneshot,
 
   /* Now we can disable the interrupt and stop the timer. */
 
-  sam_tc_attach(oneshot->tch, NULL, NULL, 0);
+  sam_tc_detach(oneshot->tch);
   sam_tc_stop(oneshot->tch);
 
   oneshot->running = false;
diff --git a/arch/arm/src/samv7/sam_oneshot.h b/arch/arm/src/samv7/sam_oneshot.h
index 46ca95e..55a604c 100644
--- a/arch/arm/src/samv7/sam_oneshot.h
+++ b/arch/arm/src/samv7/sam_oneshot.h
@@ -68,7 +68,7 @@ struct sam_oneshot_s
   volatile void *arg;                 /* The argument that will accompany
                                        * the callback */
 #ifdef CONFIG_SAMV7_FREERUN
-  volatile uint32_t start_count;      /* Stores the value of the freerun counter,
+  volatile uint16_t start_count;      /* Stores the value of the freerun counter,
                                        * at each start of the oneshot timer. Is necessary
                                        * to find out if the oneshot counter was updated
                                        * correctly at the time of the call to
diff --git a/arch/arm/src/samv7/sam_tc.c b/arch/arm/src/samv7/sam_tc.c
index 5dba6f3..a8c03e1 100644
--- a/arch/arm/src/samv7/sam_tc.c
+++ b/arch/arm/src/samv7/sam_tc.c
@@ -93,7 +93,6 @@ struct sam_chconfig_s
   uintptr_t base;          /* Channel register base address */
   uint8_t pid;             /* Peripheral ID */
   uint8_t irq;             /* IRQ number */
-  xcpt_t handler;          /* Timer interrupt handler */
   gpio_pinset_t clkset;    /* CLK input PIO configuration */
   gpio_pinset_t tioaset;   /* Output A PIO configuration */
   gpio_pinset_t tiobset;   /* Output B PIO configuration */
@@ -108,7 +107,7 @@ struct sam_tcconfig_s
 
   /* Channels */
 
-  struct sam_chconfig_s channel[3];
+  struct sam_chconfig_s channel[SAM_TC_NCHANNELS];
 };
 
 /* This structure describes one timer counter channel */
@@ -135,7 +134,7 @@ struct sam_tc_s
 
   /* Channels */
 
-  struct sam_chan_s channel[3];
+  struct sam_chan_s channel[SAM_TC_NCHANNELS];
 
   /* Debug stuff */
 
@@ -185,31 +184,7 @@ static inline void sam_chan_putreg(struct sam_chan_s *chan,
 
 /* Interrupt Handling *******************************************************/
 
-static int sam_tc_interrupt(struct sam_tc_s *tc, struct sam_chan_s *chan);
-
-#ifdef CONFIG_SAMV7_TC0
-static int sam_tc0_interrupt(int irq, void *context, FAR void *arg);
-static int sam_tc1_interrupt(int irq, void *context, FAR void *arg);
-static int sam_tc2_interrupt(int irq, void *context, FAR void *arg);
-#endif
-
-#ifdef CONFIG_SAMV7_TC1
-static int sam_tc3_interrupt(int irq, void *context, FAR void *arg);
-static int sam_tc4_interrupt(int irq, void *context, FAR void *arg);
-static int sam_tc5_interrupt(int irq, void *context, FAR void *arg);
-#endif
-
-#ifdef CONFIG_SAMV7_TC2
-static int sam_tc6_interrupt(int irq, void *context, FAR void *arg);
-static int sam_tc7_interrupt(int irq, void *context, FAR void *arg);
-static int sam_tc8_interrupt(int irq, void *context, FAR void *arg);
-#endif
-
-#ifdef CONFIG_SAMV7_TC3
-static int sam_tc9_interrupt(int irq, void *context, FAR void *arg);
-static int sam_tc10_interrupt(int irq, void *context, FAR void *arg);
-static int sam_tc11_interrupt(int irq, void *context, FAR void *arg);
-#endif
+static int sam_tc_interrupt(int irq, void *context, FAR void *arg);
 
 /* Initialization ***********************************************************/
 
@@ -235,7 +210,6 @@ static const struct sam_tcconfig_s g_tc012config =
     [0] =
     {
       .base    = SAM_TC012_CHAN_BASE(0),
-      .handler = sam_tc0_interrupt,
       .pid     = SAM_PID_TC0,
       .irq     = SAM_IRQ_TC0,
 
@@ -258,7 +232,6 @@ static const struct sam_tcconfig_s g_tc012config =
     [1] =
     {
       .base    = SAM_TC012_CHAN_BASE(1),
-      .handler = sam_tc1_interrupt,
       .pid     = SAM_PID_TC1,
       .irq     = SAM_IRQ_TC1,
 
@@ -281,7 +254,6 @@ static const struct sam_tcconfig_s g_tc012config =
     [2] =
     {
       .base    = SAM_TC012_CHAN_BASE(2),
-      .handler = sam_tc2_interrupt,
       .pid     = SAM_PID_TC2,
       .irq     = SAM_IRQ_TC2,
 
@@ -315,7 +287,6 @@ static const struct sam_tcconfig_s g_tc345config =
     [0] =
     {
       .base    = SAM_TC345_CHAN_BASE(3),
-      .handler = sam_tc3_interrupt,
       .pid     = SAM_PID_TC3,
       .irq     = SAM_IRQ_TC3,
 
@@ -338,7 +309,6 @@ static const struct sam_tcconfig_s g_tc345config =
     [1] =
     {
       .base    = SAM_TC345_CHAN_BASE(4),
-      .handler = sam_tc4_interrupt,
       .pid     = SAM_PID_TC4,
       .irq     = SAM_IRQ_TC4,
 
@@ -361,7 +331,6 @@ static const struct sam_tcconfig_s g_tc345config =
     [2] =
     {
       .base    = SAM_TC345_CHAN_BASE(5),
-      .handler = sam_tc5_interrupt,
       .pid     = SAM_PID_TC5,
       .irq     = SAM_IRQ_TC5,
 
@@ -395,7 +364,6 @@ static const struct sam_tcconfig_s g_tc678config =
     [0] =
     {
       .base    = SAM_TC678_CHAN_BASE(6),
-      .handler = sam_tc6_interrupt,
       .pid     = SAM_PID_TC6,
       .irq     = SAM_IRQ_TC6,
 
@@ -418,7 +386,6 @@ static const struct sam_tcconfig_s g_tc678config =
     [1] =
     {
       .base    = SAM_TC678_CHAN_BASE(7),
-      .handler = sam_tc7_interrupt,
       .pid     = SAM_PID_TC7,
       .irq     = SAM_IRQ_TC7,
 
@@ -441,7 +408,6 @@ static const struct sam_tcconfig_s g_tc678config =
     [2] =
     {
       .base    = SAM_TC345_CHAN_BASE(8),
-      .handler = sam_tc8_interrupt,
       .pid     = SAM_PID_TC8,
       .irq     = SAM_IRQ_TC8,
 
@@ -475,7 +441,6 @@ static const struct sam_tcconfig_s g_tc901config =
     [0] =
     {
       .base    = SAM_TC901_CHAN_BASE(9),
-      .handler = sam_tc9_interrupt,
       .pid     = SAM_PID_TC9,
       .irq     = SAM_IRQ_TC9,
 
@@ -498,7 +463,6 @@ static const struct sam_tcconfig_s g_tc901config =
     [1] =
     {
       .base    = SAM_TC901_CHAN_BASE(10),
-      .handler = sam_tc10_interrupt,
       .pid     = SAM_PID_TC10,
       .irq     = SAM_IRQ_TC10,
 
@@ -521,7 +485,6 @@ static const struct sam_tcconfig_s g_tc901config =
     [2] =
     {
       .base    = SAM_TC345_CHAN_BASE(11),
-      .handler = sam_tc11_interrupt,
       .pid     = SAM_PID_TC11,
       .irq     = SAM_IRQ_TC11,
 
@@ -840,16 +803,18 @@ static inline void sam_chan_putreg(struct sam_chan_s *chan,
  *  Common timer channel interrupt handling.
  *
  * Input Parameters:
- *   tc   Timer/counter state instance
- *   chan Channel state instance
+ *   irq     The IRQ number that generated the interrupt
+ *   context Architecture specific register save information.
+ *   arg     Pointer to timer counter channel structure
  *
  * Returned Value:
  *   OK on success; a negated errno value on failure
  *
  ****************************************************************************/
 
-static int sam_tc_interrupt(struct sam_tc_s *tc, struct sam_chan_s *chan)
+static int sam_tc_interrupt(int irq, void *context, FAR void *arg)
 {
+  struct sam_chan_s *chan = (struct sam_chan_s *)arg;
   uint32_t sr;
   uint32_t imr;
   uint32_t pending;
@@ -861,7 +826,7 @@ static int sam_tc_interrupt(struct sam_tc_s *tc, struct sam_chan_s *chan)
   pending = sr & imr;
 
   tmrinfo("TC%d Channel %d: pending=%08lx\n",
-          tc->tc, chan->chan, (unsigned long)pending);
+          chan->tc->tc, chan->chan, (unsigned long)pending);
 
   /* Are there any pending interrupts for this channel? */
 
@@ -890,93 +855,6 @@ static int sam_tc_interrupt(struct sam_tc_s *tc, struct sam_chan_s *chan)
 }
 
 /****************************************************************************
- * 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_SAMV7_TC0
-static int sam_tc0_interrupt(int irq, void *context, FAR void *arg)
-{
-  return sam_tc_interrupt(&g_tc012, &g_tc012.channel[0]);
-}
-
-static int sam_tc1_interrupt(int irq, void *context, FAR void *arg)
-{
-  return sam_tc_interrupt(&g_tc012, &g_tc012.channel[1]);
-}
-
-static int sam_tc2_interrupt(int irq, void *context, FAR void *arg)
-{
-  return sam_tc_interrupt(&g_tc012, &g_tc012.channel[2]);
-}
-#endif
-
-#ifdef CONFIG_SAMV7_TC1
-static int sam_tc3_interrupt(int irq, void *context, FAR void *arg)
-{
-  return sam_tc_interrupt(&g_tc345, &g_tc345.channel[0]);
-}
-
-static int sam_tc4_interrupt(int irq, void *context, FAR void *arg)
-{
-  return sam_tc_interrupt(&g_tc345, &g_tc345.channel[1]);
-}
-
-static int sam_tc5_interrupt(int irq, void *context, FAR void *arg)
-{
-  return sam_tc_interrupt(&g_tc345, &g_tc345.channel[2]);
-}
-#endif
-
-#ifdef CONFIG_SAMV7_TC2
-static int sam_tc6_interrupt(int irq, void *context, FAR void *arg)
-{
-  return sam_tc_interrupt(&g_tc678, &g_tc678.channel[0]);
-}
-
-static int sam_tc7_interrupt(int irq, void *context, FAR void *arg)
-{
-  return sam_tc_interrupt(&g_tc678, &g_tc678.channel[1]);
-}
-
-static int sam_tc8_interrupt(int irq, void *context, FAR void *arg)
-{
-  return sam_tc_interrupt(&g_tc678, &g_tc678.channel[2]);
-}
-#endif
-
-#ifdef CONFIG_SAMV7_TC3
-static int sam_tc9_interrupt(int irq, void *context, FAR void *arg)
-{
-  return sam_tc_interrupt(&g_tc901, &g_tc901.channel[0]);
-}
-
-static int sam_tc10_interrupt(int irq, void *context, FAR void *arg)
-{
-  return sam_tc_interrupt(&g_tc901, &g_tc901.channel[1]);
-}
-
-static int sam_tc11_interrupt(int irq, void *context, FAR void *arg)
-{
-  return sam_tc_interrupt(&g_tc901, &g_tc901.channel[2]);
-}
-#endif
-
-/****************************************************************************
  * Initialization
  ****************************************************************************/
 
@@ -1303,7 +1181,7 @@ static inline struct sam_chan_s *sam_tc_initialize(int channel)
 
   /* Attach the timer interrupt handler and enable the timer interrupts */
 
-  irq_attach(chconfig->irq, chconfig->handler, NULL);
+  irq_attach(chconfig->irq, sam_tc_interrupt, chan);
   up_enable_irq(chconfig->irq);
 
   /* Mark the channel "inuse" */
@@ -1402,7 +1280,7 @@ void sam_tc_free(TC_HANDLE handle)
    * is stopped and disabled.
    */
 
-  sam_tc_attach(handle, NULL, NULL, 0);
+  sam_tc_detach(handle);
   sam_tc_stop(handle);
 
   /* Mark the channel as available */
@@ -1435,7 +1313,7 @@ void sam_tc_start(TC_HANDLE handle)
 
   sam_chan_getreg(chan, SAM_TC_SR_OFFSET);
 
-  /* Then enable the timer (by setting the CLKEN bit).  Setting SWTRIG
+  /* Then enable the timer (by setting the CLKEN bit).  Setting SWTRG
    * will also reset the timer counter and starting the timer.
    */
 
@@ -1610,7 +1488,7 @@ uint32_t sam_tc_getregister(TC_HANDLE handle, int regid)
  *
  ****************************************************************************/
 
-uint32_t sam_tc_getcounter(TC_HANDLE handle)
+uint16_t sam_tc_getcounter(TC_HANDLE handle)
 {
   struct sam_chan_s *chan = (struct sam_chan_s *)handle;
   DEBUGASSERT(chan);
diff --git a/arch/arm/src/samv7/sam_tc.h b/arch/arm/src/samv7/sam_tc.h
index 52926b2..d77da1c 100644
--- a/arch/arm/src/samv7/sam_tc.h
+++ b/arch/arm/src/samv7/sam_tc.h
@@ -51,6 +51,9 @@
 #define TC_CHAN6     6  /* TC2 */
 #define TC_CHAN7     7
 #define TC_CHAN8     8
+#define TC_CHAN9     9  /* TC3 */
+#define TC_CHAN10    10
+#define TC_CHAN11    11
 
 /* Register identifier used with sam_tc_setregister */
 
@@ -203,7 +206,7 @@ tc_handler_t sam_tc_attach(TC_HANDLE handle, tc_handler_t handler,
  * Name: sam_tc_getpending
  *
  * Description:
- *   Return the current contents of the interrutp status register, clearing
+ *   Return the current contents of the interrupt status register, clearing
  *   all pending interrupts.
  *
  * Input Parameters:
@@ -265,7 +268,7 @@ uint32_t sam_tc_getregister(TC_HANDLE handle, int regid);
  *
  ****************************************************************************/
 
-uint32_t sam_tc_getcounter(TC_HANDLE handle);
+uint16_t sam_tc_getcounter(TC_HANDLE handle);
 
 /****************************************************************************
  * Name: sam_tc_infreq