This commit is contained in:
Gregory Nutt 2014-08-10 16:09:45 -06:00
parent bedef6a807
commit 8855c1369b
4 changed files with 31 additions and 21 deletions

View File

@ -12,7 +12,7 @@
<h1><big><font color="#3c34ec">
<i>NuttX RTOS Porting Guide</i>
</font></big></h1>
<p>Last Updated: August 8, 2014</p>
<p>Last Updated: August 10, 2014</p>
</td>
</tr>
</table>
@ -2438,7 +2438,7 @@ else
In order to use the Tickless OS, one must provide special support from the platform-specific code. Just as with the default system timer, the platform-specific code must provide the timer resources to support the OS behavior.
Currently these timer resources are only provided by the NuttX simulation. An example implementaion is for the simulation is at <code>nuttx/arch/sim/src/up_tickless.c</code>. These paragraphs will explain how to provide the Tickless OS support to any platform.
Currently these timer resources are only provided on a few platforms. An example implementation is for the simulation is at <code>nuttx/arch/sim/src/up_tickless.c</code>. There is another example for the Atmel SAMA5 at <code>nuttx/arch/arm/src/sama5/sam_tickless.c</code>. These paragraphs will explain how to provide the Tickless OS support to any platform.
<h4><a name="tickconfig">4.3.4.3 Tickless Configuration Options</a></h4>
<ul>
@ -2507,6 +2507,10 @@ config ARCH_SIM
<p>
Note that a platform-specific implementation would probably require two hardware timers: (1) A interval timer to satisfy the requirements of <a href="#uptimerstart"><code>up_timer_start()</code></a> and <a href="#uptimercancel"><code>up_timer_cancel()</code></a>, and a (2) a counter to handle the requirement of <a href="#uptimergettime"><code>up_timer_gettime()</code></a>. Ideally, both timers would run at the rate determined by <code>CONFIG_USEC_PER_TICK</code> (and certainly never slower than that rate).
</p>
<p>
Since timers are a limited resource, the use of two timers could be an issue on some systems.
The job could be done with a single timer if, for example, the single timer were kept in a free-running at all times. Some timer/counters (such as the Atmel SAMA5's timer), for example, have the capability to generate a compare interrupt when the timer matches a comparison value but also to continue counting without stopping. if your hardware supports such counters, one might be able to simply set the comparison count at the value of the free running timer <i>PLUS</i> the desired delay. Then you could have both with a single timer: An interval timer and a free-running counter with the same timer!
</p>
<p>
In addition to these imported interfaces, the RTOS will export the following interfaces for use by the platform-specific interval timer implementation:
</p>

View File

@ -88,17 +88,17 @@
* this interrupt will occur. We will just increment an overflow count.
*
* Input Parameters:
* 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.
* tch - 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.
*
* Returned Value:
* None
*
****************************************************************************/
static void sam_freerun_handler(TC_HANDLE handle, void *arg, uint32_t sr)
static void sam_freerun_handler(TC_HANDLE tch, void *arg, uint32_t sr)
{
struct sam_freerun_s *freerun = (struct sam_freerun_s *)arg;
DEBUGASSERT(freerun && freerun->overflow < UINT16_MAX);
@ -185,8 +185,8 @@ int sam_freerun_initialize(struct sam_freerun_s *freerun, int chan,
TC_CMR_BCPB_NONE | TC_CMR_BCPC_NONE | TC_CMR_BEEVT_NONE |
TC_CMR_BSWTRG_NONE);
freerun->handle = sam_tc_allocate(chan, cmr);
if (!freerun->handle)
freerun->tch = sam_tc_allocate(chan, cmr);
if (!freerun->tch)
{
tcdbg("ERROR: Failed to allocate timer channel %d\n", chan);
return -EBUSY;
@ -202,12 +202,12 @@ 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->handle, sam_freerun_handler, freerun,
(void)sam_tc_attach(freerun->tch, sam_freerun_handler, freerun,
TC_INT_COVFS);
/* Start the counter */
sam_tc_start(freerun->handle);
sam_tc_start(freerun->tch);
return OK;
}
@ -241,13 +241,15 @@ int sam_freerun_counter(struct sam_freerun_s *freerun, struct timespec *ts)
uint32_t sec;
irqstate_t flags;
DEBUGASSERT(freerun && freerun->tch && ts);
/* Temporarily disable the overflow counter */
flags = irqsave();
overflow = freerun->overflow;
counter = sam_tc_getcounter(freerun->handle);
sr = sam_tc_getpending(freerun->handle);
verify = sam_tc_getcounter(freerun->handle);
counter = sam_tc_getcounter(freerun->tch);
sr = sam_tc_getpending(freerun->tch);
verify = sam_tc_getcounter(freerun->tch);
irqrestore(flags);
tcvdbg("counter=%lu (%lu) overflow=%lu, sr=%08lx\n",
@ -307,14 +309,17 @@ int sam_freerun_counter(struct sam_freerun_s *freerun, struct timespec *ts)
int sam_freerun_uninitialize(struct sam_freerun_s *freerun)
{
DEBUGASSERT(freerun && freerun->tch);
/* Now we can disable the timer interrupt and disable the timer. */
sam_tc_attach(freerun->handle, NULL, NULL, 0);
sam_tc_stop(freerun->handle);
sam_tc_attach(freerun->tch, NULL, NULL, 0);
sam_tc_stop(freerun->tch);
/* Free the timer */
sam_tc_free(freerun->handle);
sam_tc_free(freerun->tch);
freerun->tch = NULL;
return OK;
}

View File

@ -69,7 +69,7 @@ struct sam_freerun_s
bool running; /* True: the timer is running */
uint16_t resolution; /* Timer resolution in microseconds */
uint16_t overflow; /* Timer counter overflow */
TC_HANDLE handle; /* Handle returned by sam_tc_initialize() */
TC_HANDLE tch; /* Handle returned by sam_tc_initialize() */
};
/****************************************************************************

View File

@ -80,6 +80,7 @@
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: sam_oneshot_handler
*
@ -121,9 +122,9 @@ static void sam_oneshot_handler(TC_HANDLE tch, void *arg, uint32_t sr)
/* Forward the event, clearing out any vestiges */
oneshot_handler = oneshot->handler;
oneshot_handler = (struct sam_oneshot_s *)oneshot->handler;
oneshot->handler = NULL;
oneshot_arg = oneshot->arg;
oneshot_arg = (void *)oneshot->arg;
oneshot->arg = NULL;
oneshot_handler(oneshot_arg);
@ -368,7 +369,7 @@ int sam_oneshot_cancel(struct sam_oneshot_s *oneshot, struct timespec *ts)
* following logic depends on this fact.
*/
tcvdbg("Canceling...\n");
tcvdbg("Cancelling...\n");
count = sam_tc_getcounter(oneshot->tch);
rc = sam_tc_getregister(oneshot->tch, TC_REGC);