From f9601b68010cffa0254a799e0bf00a695549c373 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 9 Aug 2014 16:42:04 -0600 Subject: [PATCH] SAMA5 oneshot: Some clean-up and correction to the initial implementation --- arch/arm/src/sama5/sam_oneshot.c | 30 +++++++++++------- arch/arm/src/sama5/sam_oneshot.h | 3 +- arch/arm/src/sama5/sam_tc.c | 54 ++++++++++++++++---------------- arch/arm/src/sama5/sam_tc.h | 34 ++++++++++---------- 4 files changed, 64 insertions(+), 57 deletions(-) diff --git a/arch/arm/src/sama5/sam_oneshot.c b/arch/arm/src/sama5/sam_oneshot.c index 509a312656..997e04f048 100644 --- a/arch/arm/src/sama5/sam_oneshot.c +++ b/arch/arm/src/sama5/sam_oneshot.c @@ -52,14 +52,11 @@ #include #include #include -#include -#include #include #include #include -#include -#include +#include #include "sam_oneshot.h" @@ -176,8 +173,9 @@ int sam_oneshot_initialize(struct sam_oneshot_s *oneshot, int chan, return ret; } - tcvdbg("frequency=%lu, divisor=%u, cmr=%08lx\n", - (unsigned long)frequency, oneshot->divisor, (unsigned long)cmr); + tcvdbg("frequency=%lu, divisor=%lu, cmr=%08lx\n", + (unsigned long)frequency, (unsigned long)oneshot->divisor, + (unsigned long)cmr); /* Allocate the timer/counter and select its mode of operation * @@ -190,7 +188,7 @@ int sam_oneshot_initialize(struct sam_oneshot_s *oneshot, int chan, * TC_CMR_EEVT_TIOB - ???? REVISIT * TC_CMR_ENET=0 - External event trigger disabled * TC_CMR_WAVSEL_UPRC - TC_CV is incremented from 0 to the value of RC, - * then automatically reset on a RC Compare + * then automatically reset on a RC Compare * TC_CMR_WAVE - Waveform mode * TC_CMR_ACPA_NONE - RA compare has no effect on TIOA * TC_CMR_ACPC_NONE - RC compare has no effect on TIOA @@ -254,7 +252,7 @@ int sam_oneshot_start(struct sam_oneshot_s *oneshot, oneshot_handler_t handler, uint64_t regval; irqstate_t flags; - tcvdbg("handler=%p arg=%p, ts=(%lu, %lu)\n", + tcvdbg("handler=%p arg=%p, ts=(%lu, %lu)\n", handler, arg, (unsigned long)ts->tv_sec, (unsigned long)ts->tv_nsec); DEBUGASSERT(oneshot && handler && ts); @@ -278,7 +276,7 @@ int sam_oneshot_start(struct sam_oneshot_s *oneshot, oneshot_handler_t handler, tcdbg("usec=%llu regval=%08llx\n", usec, regval); DEBUGASSERT(regval <= UINT32_MAX); - + /* Set up to receive the callback when the interrupt occurs */ (void)sam_tc_attach(oneshot->handle, sam_oneshot_handler, oneshot, @@ -290,6 +288,10 @@ int sam_oneshot_start(struct sam_oneshot_s *oneshot, oneshot_handler_t handler, sam_tc_setregister(oneshot->handle, TC_REGC, regval); + /* Start the counter */ + + sam_tc_start(oneshot->handle); + /* Enable interrupts. We should get the callback when the interrupt * occurs. */ @@ -337,8 +339,14 @@ int sam_oneshot_cancel(struct sam_oneshot_s *oneshot, struct timespec *ts) count = sam_tc_getcounter(oneshot->handle); rc = sam_tc_getregister(oneshot->handle, TC_REGC); - /* Now we can disable the interrupt and stop the clock */ + /* Now we can disable the interrupt and stop the timer. + * + * REVISIT: The assertion is there because I do no not know if the + * counter will be reset when the RC match occurs. The counter + * clock will be disabled, so I am hoping not. + */ + DEBUGASSERT(count > 0 || (sam_tc_getpending(oneshot->handle) & TC_INT_CPCS) == 0); sam_tc_attach(oneshot->handle, NULL, NULL, 0); sam_tc_stop(oneshot->handle); @@ -358,7 +366,7 @@ int sam_oneshot_cancel(struct sam_oneshot_s *oneshot, struct timespec *ts) sec = usec / 1000000; ts->tv_sec = sec; - ts->tv_nsec = ((usec) - (sec * 1000000)) / 1000; + ts->tv_nsec = ((usec) - (sec * 1000000)) * 1000; tcvdbg("remaining (%lu, %lu)\n", (unsigned long)ts->tv_sec, (unsigned long)ts->tv_nsec); diff --git a/arch/arm/src/sama5/sam_oneshot.h b/arch/arm/src/sama5/sam_oneshot.h index 954ea48551..dd3bfdf42e 100644 --- a/arch/arm/src/sama5/sam_oneshot.h +++ b/arch/arm/src/sama5/sam_oneshot.h @@ -119,7 +119,7 @@ extern "C" * ****************************************************************************/ -int sam_oneshot_initialize(struct sam_oneshot_s *oneshot, int tc, +int sam_oneshot_initialize(struct sam_oneshot_s *oneshot, int chan, uint16_t resolution); /**************************************************************************** @@ -173,4 +173,3 @@ int sam_oneshot_cancel(struct sam_oneshot_s *oneshot, struct timespec *ts); #endif /* CONFIG_SAMA5_ONESHOT */ #endif /* __ARCH_ARM_SRC_SAMA5_SAM_ONESHOT_H */ - diff --git a/arch/arm/src/sama5/sam_tc.c b/arch/arm/src/sama5/sam_tc.c index 778b667940..d0495382c2 100644 --- a/arch/arm/src/sama5/sam_tc.c +++ b/arch/arm/src/sama5/sam_tc.c @@ -1204,6 +1204,30 @@ void sam_tc_start(TC_HANDLE handle) sam_regdump(chan, "Started"); } +/**************************************************************************** + * Name: sam_tc_stop + * + * Description: + * Stop TC Channel. Disables the timer clock, stopping the counting. + * + * Input Parameters: + * handle Channel handle previously allocated by sam_tc_allocate() + * + * Returned Value: + * + ****************************************************************************/ + +void sam_tc_stop(TC_HANDLE handle) +{ + struct sam_chan_s *chan = (struct sam_chan_s *)handle; + + tcvdbg("Stopping channel %d inuse=%d\n", chan->chan, chan->inuse); + DEBUGASSERT(chan && chan->inuse); + + sam_chan_putreg(chan, SAM_TC_CCR_OFFSET, TC_CCR_CLKDIS); + sam_regdump(chan, "Stopped"); +} + /**************************************************************************** * Name: sam_tc_attach * @@ -1259,10 +1283,10 @@ tc_handler_t sam_tc_attach(TC_HANDLE handle, tc_handler_t handler, } /**************************************************************************** - * Name: sam_tc_pending + * 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: @@ -1273,37 +1297,13 @@ tc_handler_t sam_tc_attach(TC_HANDLE handle, tc_handler_t handler, * ****************************************************************************/ -uint32_t sam_tc_pending(TC_HANDLE handle) +uint32_t sam_tc_getpending(TC_HANDLE handle) { struct sam_chan_s *chan = (struct sam_chan_s *)handle; DEBUGASSERT(chan); return sam_chan_getreg(chan, SAM_TC_SR_OFFSET); } -/**************************************************************************** - * Name: sam_tc_stop - * - * Description: - * Stop TC Channel. Disables the timer clock, stopping the counting. - * - * Input Parameters: - * handle Channel handle previously allocated by sam_tc_allocate() - * - * Returned Value: - * - ****************************************************************************/ - -void sam_tc_stop(TC_HANDLE handle) -{ - struct sam_chan_s *chan = (struct sam_chan_s *)handle; - - tcvdbg("Stopping channel %d inuse=%d\n", chan->chan, chan->inuse); - DEBUGASSERT(chan && chan->inuse); - - sam_chan_putreg(chan, SAM_TC_CCR_OFFSET, TC_CCR_CLKDIS); - sam_regdump(chan, "Stopped"); -} - /**************************************************************************** * Name: sam_tc_setregister * diff --git a/arch/arm/src/sama5/sam_tc.h b/arch/arm/src/sama5/sam_tc.h index 65f7bbeaed..6aa7cb6534 100644 --- a/arch/arm/src/sama5/sam_tc.h +++ b/arch/arm/src/sama5/sam_tc.h @@ -159,6 +159,21 @@ void sam_tc_free(TC_HANDLE handle); void sam_tc_start(TC_HANDLE handle); +/**************************************************************************** + * Name: sam_tc_stop + * + * Description: + * Stop TC Channel. Disables the timer clock, stopping the counting. + * + * Input Parameters: + * handle Channel handle previously allocated by sam_tc_allocate() + * + * Returned Value: + * + ****************************************************************************/ + +void sam_tc_stop(TC_HANDLE handle); + /**************************************************************************** * Name: sam_tc_attach/sam_tc_detach * @@ -187,7 +202,7 @@ tc_handler_t sam_tc_attach(TC_HANDLE handle, tc_handler_t handler, #define sam_tc_detach(h) sam_tc_attach(h, NULL, NULL, 0) /**************************************************************************** - * Name: sam_tc_pending + * Name: sam_tc_getpending * * Description: * Return the current contents of the interrutp status register, clearing @@ -201,22 +216,7 @@ tc_handler_t sam_tc_attach(TC_HANDLE handle, tc_handler_t handler, * ****************************************************************************/ -uint32_t sam_tc_pending(TC_HANDLE handle); - -/**************************************************************************** - * Name: sam_tc_stop - * - * Description: - * Stop TC Channel. Disables the timer clock, stopping the counting. - * - * Input Parameters: - * handle Channel handle previously allocated by sam_tc_allocate() - * - * Returned Value: - * - ****************************************************************************/ - -void sam_tc_stop(TC_HANDLE handle); +uint32_t sam_tc_getpending(TC_HANDLE handle); /**************************************************************************** * Name: sam_tc_setregister