git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@655 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
12721da8ad
commit
22fe505a81
24
docs/ch.txt
24
docs/ch.txt
|
@ -192,7 +192,28 @@
|
|||
*
|
||||
* @section thread_states Threads States
|
||||
* The image shows how threads can change their state in ChibiOS/RT.<br>
|
||||
* @image html states.png
|
||||
* @dot
|
||||
digraph example {
|
||||
/*rankdir="LR";*/
|
||||
node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.75", height="0.75"];
|
||||
start [label="Start", style="bold"];
|
||||
run [label="Running"];
|
||||
ready [label="Ready"];
|
||||
suspend [label="Suspended"];
|
||||
sleep [label="Sleeping"];
|
||||
stop [label="Stop", style="bold"];
|
||||
start -> suspend [label="chThdInit()", fontname=Helvetica, fontsize=8, constraint=false];
|
||||
start -> run [label="chThdCreate()", fontname=Helvetica, fontsize=8];
|
||||
start -> ready [label="chThdCreate()", fontname=Helvetica, fontsize=8];
|
||||
run -> ready [dir="both", label="Reschedulation", fontname=Helvetica, fontsize=8];
|
||||
suspend -> run [label="chThdResume()", fontname=Helvetica, fontsize=8];
|
||||
suspend -> ready [label="chThdResume()", fontname=Helvetica, fontsize=8];
|
||||
run -> sleep [label="chSchGoSleepS()", fontname=Helvetica, fontsize=8];
|
||||
sleep -> run [label="chSchWakepS()", fontname=Helvetica, fontsize=8];
|
||||
sleep -> ready [label="chSchWakepS()", fontname=Helvetica, fontsize=8];
|
||||
run -> stop [label="chThdExit()", fontname=Helvetica, fontsize=8];
|
||||
}
|
||||
* @enddot
|
||||
*
|
||||
* @section priority Priority Levels
|
||||
* Priorities in ChibiOS/RT are a contiguous numerical range but the initial
|
||||
|
@ -246,6 +267,7 @@
|
|||
* - @subpage article_atomic
|
||||
* - @subpage article_saveram
|
||||
* - @subpage article_interrupts
|
||||
* - @subpage article_timing
|
||||
*/
|
||||
/** @} */
|
||||
|
||||
|
|
|
@ -12,17 +12,13 @@
|
|||
|
||||
chSemSignalI(&sem1);
|
||||
chSemSignalI(&sem2);
|
||||
if (tp != NULL) {
|
||||
chThdResumeI(tp);
|
||||
tp = NULL;
|
||||
}
|
||||
chSchRescheduleS();
|
||||
|
||||
chSysUnlock();
|
||||
* @endcode
|
||||
* The above example performs a signal operation on two semaphores, optionally
|
||||
* resumes a thread, and performs a final reschedulation. The three operations
|
||||
* are performed atomically.<br>
|
||||
* The above example performs a signal operation on two semaphores and
|
||||
* performs a final reschedulation. The two operations are performed
|
||||
* atomically.<br>
|
||||
* An hypotetical @p chSemSignalSignalWait() operation could be implemented as
|
||||
* follow:
|
||||
* @code
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* @page article_timing Reliable timings using Threads
|
||||
* @{
|
||||
* One common task is to have threads do something at regular, scheduled,
|
||||
* intervals.
|
||||
* An obvious solution is to write something like this:
|
||||
* @code
|
||||
msg_t my_thread(void *param) {
|
||||
|
||||
while (TRUE) {
|
||||
do_something();
|
||||
chThdSleepMilliseconds(1000); /* Fixed interval */
|
||||
}
|
||||
}
|
||||
* @endcode
|
||||
* This example works well assuming that @p do_something() execution time is
|
||||
* well below the system tick period and that @p my_thread() is not preempted
|
||||
* by other threads inserting long intervals.<br>
|
||||
* If the above conditions are not satisfied you may have @p do_something()
|
||||
* executed at irregular intevals, as example:<br><br>
|
||||
* T0...T0+1000...T0+2002...T0+3002...T0+4005...etc.<br><br>
|
||||
* Also note that the error increases over time and this kind of behavior can
|
||||
* lead anomalies really hard to debug.
|
||||
* <h2>A better solution</h2>
|
||||
* It is possible to rewrite the above code using absolute deadlines rather
|
||||
* than fixed intervals:
|
||||
* @code
|
||||
msg_t my_thread(void *param) {
|
||||
|
||||
systick_t time = chSysGetTime(); /* T0 */
|
||||
while (TRUE) {
|
||||
time += MS2ST(1000); /* Next deadline */
|
||||
do_something();
|
||||
chThdSleepUntil(time);
|
||||
}
|
||||
}
|
||||
* @endcode
|
||||
* Using this code @p do_something() will always be executed at an absolute
|
||||
* deadline time and the error will not accumulate over time regardless of
|
||||
* the execution time and delays inserted by other threads.
|
||||
*/
|
||||
/** @} */
|
|
@ -105,8 +105,10 @@ static void wakeup(void *p) {
|
|||
/* Falls into, intentional. */
|
||||
#endif
|
||||
case PRWTCOND:
|
||||
chSchReadyI(dequeue(tp))->p_rdymsg = RDY_TIMEOUT;
|
||||
break;
|
||||
case PRWTMTX:
|
||||
/* States requiring dequeuing. */
|
||||
dequeue(tp);
|
||||
/* Falls into, intentional. */
|
||||
default:
|
||||
chSchReadyI(tp)->p_rdymsg = RDY_TIMEOUT;
|
||||
}
|
||||
|
|
|
@ -214,26 +214,6 @@ void chThdSetPriority(tprio_t newprio) {
|
|||
chSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Suspends the invoking thread.
|
||||
*
|
||||
* @param tpp pointer to a @p Thread pointer, the @p Thread pointer is set
|
||||
* to point to the suspended process before it enters the
|
||||
* @p PRSUSPENDED state. The variable pointed by this parameter
|
||||
* must be set to @p NULL on entry.
|
||||
* @note The resume operation is meant to be executed into an interrupt or timer
|
||||
* handler. The handler is also responsible to clear the variable pointed
|
||||
* by @p tpp after invoking @p chThdResumeI().
|
||||
*/
|
||||
void chThdSuspend(Thread **tpp) {
|
||||
|
||||
chSysLock();
|
||||
chDbgAssert(*tpp == NULL, "chthreads.c, chThdSuspend()");
|
||||
*tpp = currp;
|
||||
chSchGoSleepS(PRSUSPENDED);
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resumes a suspended thread.
|
||||
*
|
||||
|
|
|
@ -183,7 +183,6 @@ extern "C" {
|
|||
#endif
|
||||
void chThdSetPriority(tprio_t newprio);
|
||||
Thread *chThdResume(Thread *tp);
|
||||
void chThdSuspend(Thread **tpp);
|
||||
void chThdTerminate(Thread *tp);
|
||||
void chThdSleep(systime_t time);
|
||||
void chThdSleepUntil(systime_t time);
|
||||
|
|
|
@ -94,7 +94,6 @@ static void sem2_execute(void) {
|
|||
test_assert(isempty(&sem1.s_queue), "queue not empty");
|
||||
test_assert(&sem1.s_cnt != 0, "counter not zero");
|
||||
}
|
||||
test_assert(chSemGetCounter(&sem1) == 0, "non zero counter");
|
||||
test_assert_sequence("ABCDE");
|
||||
test_assert_time_window(target_time, target_time + ALLOWED_DELAY);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue