summaryrefslogtreecommitdiff
path: root/nuttx/arch/arm/src/sam34/sam_tc.c
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-05-05 14:35:37 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-05-05 14:35:37 -0600
commit5bc7fcd3ffc062169be8562afc4d2feaa6425cb0 (patch)
treeae955b30b00e95103c89d5db2d57b8b08c99d21d /nuttx/arch/arm/src/sam34/sam_tc.c
parent28817e379f7a93e4c62df2c3f7e06c3729709015 (diff)
downloadpx4-nuttx-5bc7fcd3ffc062169be8562afc4d2feaa6425cb0.tar.gz
px4-nuttx-5bc7fcd3ffc062169be8562afc4d2feaa6425cb0.tar.bz2
px4-nuttx-5bc7fcd3ffc062169be8562afc4d2feaa6425cb0.zip
Add SAM3/4 RTT driver. From Bob Doiron
Diffstat (limited to 'nuttx/arch/arm/src/sam34/sam_tc.c')
-rw-r--r--nuttx/arch/arm/src/sam34/sam_tc.c47
1 files changed, 23 insertions, 24 deletions
diff --git a/nuttx/arch/arm/src/sam34/sam_tc.c b/nuttx/arch/arm/src/sam34/sam_tc.c
index 27dbd1642..b955d6bb0 100644
--- a/nuttx/arch/arm/src/sam34/sam_tc.c
+++ b/nuttx/arch/arm/src/sam34/sam_tc.c
@@ -106,7 +106,6 @@ struct sam34_lowerhalf_s
uint32_t clkticks; /* actual clock ticks for current interval */
bool started; /* The timer has been started */
uint16_t periphid; /* peripheral id */
- uint16_t debug;
};
/****************************************************************************
@@ -134,7 +133,7 @@ static int sam34_getstatus(FAR struct timer_lowerhalf_s *lower,
FAR struct timer_status_s *status);
static int sam34_settimeout(FAR struct timer_lowerhalf_s *lower,
uint32_t timeout);
-static tccb_t sam34_capture(FAR struct timer_lowerhalf_s *lower,
+static tccb_t sam34_sethandler(FAR struct timer_lowerhalf_s *lower,
tccb_t handler);
static int sam34_ioctl(FAR struct timer_lowerhalf_s *lower, int cmd,
unsigned long arg);
@@ -150,7 +149,7 @@ static const struct timer_ops_s g_tcops =
.stop = sam34_stop,
.getstatus = sam34_getstatus,
.settimeout = sam34_settimeout,
- .capture = sam34_capture,
+ .sethandler = sam34_sethandler,
.ioctl = sam34_ioctl,
};
@@ -267,15 +266,13 @@ static void sam34_putreg(uint32_t val, uint32_t addr)
static int sam34_interrupt(int irq, FAR void *context)
{
FAR struct sam34_lowerhalf_s *priv = &g_tcdevs[irq-SAM_IRQ_TC0];
- uint16_t regval;
tcvdbg("Entry\n");
DEBUGASSERT((irq >= SAM_IRQ_TC0) && (irq <= SAM_IRQ_TC5));
/* Check if the interrupt is really pending */
- regval = sam34_getreg(priv->base + SAM_TC_SR_OFFSET);
- if ((regval & TC_INT_CPCS) != 0)
+ if ((sam34_getreg(priv->base + SAM_TC_SR_OFFSET) & TC_INT_CPCS) != 0)
{
uint32_t timeout;
@@ -283,7 +280,7 @@ static int sam34_interrupt(int irq, FAR void *context)
if (priv->handler && priv->handler(&priv->timeout))
{
- /* Calculate new ticks */
+ /* Calculate new ticks / dither adjustment */
priv->clkticks = ((uint64_t)(priv->adjustment + priv->timeout))*TC_FCLK / 1000000;
@@ -323,7 +320,7 @@ static int sam34_interrupt(int irq, FAR void *context)
static int sam34_start(FAR struct timer_lowerhalf_s *lower)
{
FAR struct sam34_lowerhalf_s *priv = (FAR struct sam34_lowerhalf_s *)lower;
- uint32_t mr_val = 0;
+ uint32_t mr_val;
tcvdbg("Entry\n");
DEBUGASSERT(priv);
@@ -335,13 +332,14 @@ static int sam34_start(FAR struct timer_lowerhalf_s *lower)
sam_enableperiph0(priv->periphid); /* Enable peripheral clock */
sam34_putreg(TC_CCR_CLKDIS, priv->base + SAM_TC_CCR_OFFSET); /* Disable counter */
+ sam34_putreg(0, priv->base + SAM_TC_CV_OFFSET); /* clear counter */
/* TC_CMR_WAVE - waveform mode
* TC_CMR_WAVSEL_UPAUTO - reset on RC compare (interval timer)
* TC_CMR_TCCLKS_TIMERCLOCK5 = SCLK
*/
- mr_val |= (TC_CMR_WAVE + TC_CMR_WAVSEL_UPAUTO + TC_CMR_TCCLKS_TIMERCLOCK5);
+ mr_val = (TC_CMR_WAVE + TC_CMR_WAVSEL_UPAUTO + TC_CMR_TCCLKS_TIMERCLOCK5);
sam34_putreg(mr_val, priv->base + SAM_TC_CMR_OFFSET);
sam34_putreg(priv->clkticks, priv->base + SAM_TC_RC_OFFSET); /* Set interval */
@@ -381,7 +379,7 @@ static int sam34_stop(FAR struct timer_lowerhalf_s *lower)
tcvdbg("Entry\n");
DEBUGASSERT(priv);
- if(!priv->started)
+ if (!priv->started)
{
return -EINVAL;
}
@@ -430,7 +428,7 @@ static int sam34_getstatus(FAR struct timer_lowerhalf_s *lower,
if (priv->handler)
{
- status->flags |= TCFLAGS_CAPTURE;
+ status->flags |= TCFLAGS_HANDLER;
}
/* Return the actual timeout is milliseconds */
@@ -440,7 +438,7 @@ static int sam34_getstatus(FAR struct timer_lowerhalf_s *lower,
/* Get the time remaining until the timer expires (in microseconds) */
elapsed = sam34_getreg(priv->base + SAM_TC_CV_OFFSET);
- status->timeleft = (priv->timeout * elapsed) / (priv->clkticks + 1); /* TODO - check on this +1 */
+ status->timeleft = ((uint64_t)priv->timeout * elapsed) / (priv->clkticks + 1); /* TODO - check on this +1 */
tcvdbg(" flags : %08x\n", status->flags);
tcvdbg(" timeout : %d\n", status->timeout);
@@ -470,6 +468,12 @@ static int sam34_settimeout(FAR struct timer_lowerhalf_s *lower,
FAR struct sam34_lowerhalf_s *priv = (FAR struct sam34_lowerhalf_s *)lower;
DEBUGASSERT(priv);
+
+ if (priv->started)
+ {
+ return -EPERM;
+ }
+
tcvdbg("Entry: timeout=%d\n", timeout);
/* Can this timeout be represented? */
@@ -486,21 +490,17 @@ static int sam34_settimeout(FAR struct timer_lowerhalf_s *lower,
timeout = (1000000ULL * priv->clkticks) / TC_FCLK; /* Truncated timeout */
priv->adjustment = priv->timeout - timeout; /* Truncated time to be added to next interval (dither) */
- tcvdbg("fwdt=%d reload=%d timout=%d, adjustment=%d\n",
- TC_FCLK, reload, priv->timeout, priv->adjustment);
-
- /* Don't commit to MR register until started! */
+ tcvdbg("fclk=%d clkticks=%d timout=%d, adjustment=%d\n",
+ TC_FCLK, priv->clkticks, priv->timeout, priv->adjustment);
return OK;
}
/****************************************************************************
- * Name: sam34_capture
+ * Name: sam34_sethandler
*
* Description:
- * Don't reset on timer timeout; instead, call this user provider
- * timeout handler. NOTE: Providing handler==NULL will restore the reset
- * behavior.
+ * Call this user provided timeout handler.
*
* Input Parameters:
* lower - A pointer the publicly visible representation of the "lower-half"
@@ -511,13 +511,12 @@ static int sam34_settimeout(FAR struct timer_lowerhalf_s *lower,
*
* Returned Values:
* The previous timer expiration function pointer or NULL is there was
- * no previous function pointer, i.e., if the previous behavior was
- * reset-on-expiration (NULL is also returned if an error occurs).
+ * no previous function pointer.
*
****************************************************************************/
-static tccb_t sam34_capture(FAR struct timer_lowerhalf_s *lower,
- tccb_t handler)
+static tccb_t sam34_sethandler(FAR struct timer_lowerhalf_s *lower,
+ tccb_t handler)
{
FAR struct sam34_lowerhalf_s *priv = (FAR struct sam34_lowerhalf_s *)lower;
irqstate_t flags;