SAMA5 oneshot: Some clean-up and correction to the initial implementation

This commit is contained in:
Gregory Nutt 2014-08-09 16:42:04 -06:00
parent 84b86e32be
commit acb05460d0
4 changed files with 64 additions and 57 deletions

View File

@ -52,14 +52,11 @@
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <semaphore.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <arch/board/board.h>
#include <arch/irq.h>
#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);

View File

@ -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 */

View File

@ -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
*

View File

@ -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