From 819c02b8391e3cadcbe814c84c5c5f366ae41e03 Mon Sep 17 00:00:00 2001 From: gdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4> Date: Fri, 23 Jan 2009 16:18:13 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@669 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- docs/ch.txt | 85 ++++++++++++++++++++++++++++++--------------------- docs/src/jitter.dox | 81 ++++++++++++++++++++++++++++++++++++------------ ports/ARM7/port.dox | 4 +-- ports/ARMCM3/port.dox | 4 +-- ports/AVR/port.dox | 4 +-- ports/MSP430/port.dox | 4 +-- 6 files changed, 120 insertions(+), 62 deletions(-) diff --git a/docs/ch.txt b/docs/ch.txt index 416811dc8..aff84eff1 100644 --- a/docs/ch.txt +++ b/docs/ch.txt @@ -104,7 +104,7 @@ * @section system_states System States * When using ChibiOS/RT the system can be in one of the following logical * operating states: - * - <b>Initialization</b>. When the system is in this state all the maskable + * - <b>Init</b>. When the system is in this state all the maskable * interrupt sources are disabled. In this state it is not possible to use * any system API except @p chSysInit(). This state is entered after a * physical reset. @@ -146,7 +146,8 @@ digraph example { rankdir="LR"; node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.75", height="0.75"]; - init [label="Initialization", style="bold"]; + edge [fontname=Helvetica, fontsize=8]; + init [label="Init", style="bold"]; norm [label="Normal", shape=doublecircle]; susp [label="Suspended"]; disab [label="Disabled"]; @@ -155,31 +156,46 @@ slock [label="S-Locked"]; sleep [label="Sleep"]; sri [label="SRI"]; - sfi [label="SFI"]; - init -> norm [label="chSysInit()", fontname=Helvetica, fontsize=8]; - norm -> slock [label="chSysLock()", fontname=Helvetica, fontsize=8, constraint=false]; - slock -> norm [label="chSysUnlock()", fontname=Helvetica, fontsize=8]; - norm -> susp [label="chSysSuspend()", fontname=Helvetica, fontsize=8]; - susp -> disab [label="chSysDisable()", fontname=Helvetica, fontsize=8]; - norm -> disab [label="chSysDisable()", fontname=Helvetica, fontsize=8]; - susp -> norm [label="chSysEnable()", fontname=Helvetica, fontsize=8]; - disab -> norm [label="chSysEnable()", fontname=Helvetica, fontsize=8]; - slock -> ilock [dir="both", label="Context Switch", fontname=Helvetica, fontsize=8]; - norm -> sri [style="dotted", label="Regular IRQ", fontname=Helvetica, fontsize=8]; - norm -> sfi [style="dotted", label="Fast IRQ", fontname=Helvetica, fontsize=8]; - susp -> sfi [style="dotted", label="Fast IRQ", fontname=Helvetica, fontsize=8]; + init -> norm [label="chSysInit()"]; + norm -> slock [label="chSysLock()", constraint=false]; + slock -> norm [label="chSysUnlock()"]; + norm -> susp [label="chSysSuspend()"]; + susp -> disab [label="chSysDisable()"]; + norm -> disab [label="chSysDisable()"]; + susp -> norm [label="chSysEnable()"]; + disab -> norm [label="chSysEnable()"]; + slock -> ilock [label="Context Switch", dir="both"]; + norm -> sri [label="Regular IRQ", style="dotted"]; sri -> norm [label="Regular IRQ return", fontname=Helvetica, fontsize=8]; - sfi -> norm [label="Fast IRQ return", fontname=Helvetica, fontsize=8]; - sfi -> susp [label="Fast IRQ return", fontname=Helvetica, fontsize=8]; - sri -> ilock [label="chSysLockI()", fontname=Helvetica, fontsize=8, constraint=false]; - ilock -> sri [label="chSysUnlockI()", fontname=Helvetica, fontsize=8]; - norm -> sleep [label="Idle Thread", fontname=Helvetica, fontsize=8]; - sleep -> sri [style="dotted", label="Regular IRQ", fontname=Helvetica, fontsize=8]; - sleep -> sfi [style="dotted", label="Fast IRQ", fontname=Helvetica, fontsize=8]; + sri -> ilock [label="chSysLockI()", constraint=false]; + ilock -> sri [label="chSysUnlockI()", fontsize=8]; + norm -> sleep [label="Idle Thread"]; + sleep -> sri [label="Regular IRQ", style="dotted"]; + } + * @enddot + * Note, the <b>SFI</b>, <b>Halted</b> and <b>SNMI</b> states were not shown + * because those are reachable from most states: + * + * @dot + digraph example { + rankdir="LR"; + node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.75", height="0.75"]; + edge [fontname=Helvetica, fontsize=8]; + any1 [label="Any State\nexcept\nDisabled\nand Init"]; + any2 [label="Any State"]; + sfi [label="SFI"]; + halt [label="Halted"]; + SNMI [label="SNMI"]; + any1 -> sfi [style="dotted", label="Fast IRQ"]; + sfi -> any1 [label="Fast IRQ return"]; + any2 -> halt [label="chSysHalt()"]; + any2 -> SNMI [label="Synchronous NMI"]; + any2 -> SNMI [label="Asynchronous NMI", style="dotted"]; + SNMI -> any2 [label="NMI return"]; + halt -> SNMI [label="Asynchronous NMI", style="dotted"]; + SNMI -> halt [label="NMI return"]; } * @enddot - * Note, the Halted and SNMI states can be reached from any state and are not - * shown for simplicity. * * @section scheduling Scheduling * The strategy is very simple the currently ready thread with the highest @@ -197,22 +213,23 @@ digraph example { /*rankdir="LR";*/ node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.75", height="0.75"]; + edge [fontname=Helvetica, fontsize=8]; 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]; + start -> suspend [label="chThdInit()", constraint=false]; + start -> run [label="chThdCreate()"]; + start -> ready [label="chThdCreate()"]; + run -> ready [label="Reschedulation", dir="both"]; + suspend -> run [label="chThdResume()"]; + suspend -> ready [label="chThdResume()"]; + run -> sleep [label="chSchGoSleepS()"]; + sleep -> run [label="chSchWakepS()"]; + sleep -> ready [label="chSchWakepS()"]; + run -> stop [label="chThdExit()"]; } * @enddot * diff --git a/docs/src/jitter.dox b/docs/src/jitter.dox index 4bbedd7b7..1b4220dd4 100644 --- a/docs/src/jitter.dox +++ b/docs/src/jitter.dox @@ -8,15 +8,61 @@ * A good place to start is this * <a href="http://en.wikipedia.org/wiki/Jitter">Wikipedia article</a>. * - * <h2>Jitter Sources</h2> - * Under ChibiOS/RT (or any other similar RTOS) there are several possible - * jitter sources: - * -# Hardware interrupts latency. - * -# Interrupts service time and priority. - * -# Kernel lock zones. - * -# Higher priority threads activity. + * <h2>Interrupt Response Time</h2> + * This is the time from an interrupt event and the execution of the handler + * code. * - * <h2>Jitter mitigation countermeasures</h2> + * @dot + digraph example { + rankdir="LR"; + node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.75", height="0.75"]; + edge [fontname=Helvetica, fontsize=8]; + int [label="Interrupt"]; + busy [label="Busy"]; + served [label="Interrupt\nServed"]; + int -> served [label="Not Busy"]; + int -> busy [label="Not Ready"]; + busy -> busy [label="Still Busy\n(jitter)"]; + busy -> served [label="Finally Ready"]; + * @enddot + * + * <h3>Jitter Sources</h3> + * In this scenario the jitter (busy state) is represented by the sum of: + * - Higher or equal priority interrupt sources execution time combined. + * This time can go from zero to the maximum randomly. This value can be + * guaranteed to be zero only if the interrupt has the highest priority in + * the system. + * - Highest execution time among lower priority sources. This value is zero + * on those architectures (Cortex-M3 as example) where interrupt handlers + * can be preempted by higher priority sources. + * - Longest time in a kernel lock zone that can delay interrupt servicing. + * This value is zero for fast interrupt sources, see @ref system_states. + * + * <h2>Threads Flyback Time</h2> + * This is the time from an event, as example an interrupt, and the execution + * of a thread supposed to handle the event. Imagine the following graph as the + * continuation of the previous one. + * + * @dot + digraph example { + rankdir="LR"; + node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.75", height="0.75"]; + edge [fontname=Helvetica, fontsize=8]; + served [label="Interrupt\nServed"]; + busy [label="Busy"]; + thread [label="Thread\nAwakened"]; + served -> busy [label="Not Highest Priority"]; + busy -> busy [label="Other Threads\n(jitter)"]; + busy -> thread [label="Highest Priority"]; + served -> thread [label="Highest Priority"]; + * @enddot + * + * <h3>Jitter Sources</h3> + * In this scenario all the jitter sources previously discussed are also + * present and there is the added jitter caused by the activity of the + * higher priority threads. + * + * <h2>Jitter Mitigation</h2> * For each of the previously described jitter sources there are possible * mitigation actions. * @@ -26,7 +72,7 @@ * architecture more efficient at interrupt handling, as example, the * ARM Cortex-M3 core present in the STM32 family is very efficient at that. * - * <h3>Interrupts service time and priority</h3> + * <h3>Interrupts service time</h3> * This is the execution time of interrupt handlers, this time includes: * - Fixed handler overhead, as example registers stacking/unstacking. * - Interrupt specific service time, as example, in a serial driver, this is @@ -41,16 +87,8 @@ * An handler should serve the interrupt and wakeup a dedicated thread in order * to handle the bulk of the work.<br> * Another possible mitigation action is to evaluate if a specific interrupt - * handler really need to "speak" with the OS, if the handler uses full + * handler really needs to "speak" with the OS, if the handler uses full * stand-alone code then it is possible to remove the OS related overhead.<br> - * On some architecture it is also possible to give to interrupt sources a - * greater hardware priority than the kernel and not be affected by the - * jitter introduced by OS itself (see next subsection).<br> - * As example, in the ARM port, FIQ sources are not affected by the - * kernel-generated jitter. The Cortex-M3 port is even better thanks to its - * hardware-assisted interrupt architecture allowing handlers preemption, - * late arriving, tail chaining etc. See the notes about the various - * @ref Ports. * * <h3>Kernel lock zones</h3> * The OS kernel protects some critical internal data structure by disabling @@ -67,12 +105,15 @@ * * <h3>Higher priority threads activity</h3> * At thread level the response time is affected by the interrupt-related - * jitter as seen in the previous subsections but also by the activity of the - * higher priority threads and contention on protected resources.<br> + * jitter, as seen in the previous subsections, but also by the activity of + * the higher priority threads and contention on protected resources.<br> * It is possible to improve the system overall response time and reduce jitter * by carefully assigning priorities to the various threads and carefully * designing mutual exclusion zones.<br> * The use of the proper synchronization mechanism (semaphores, mutexes, events, * messages and so on) also helps to improve the overall system performance. + * The use of the Priority Inheritance algorithm implemented in the mutexes + * subsystem can improve the overall response time and reduce jitter but it is + * not a magic wand, a proper system design comes first. */ /** @} */ diff --git a/ports/ARM7/port.dox b/ports/ARM7/port.dox index fce2f9cd7..4efe06089 100644 --- a/ports/ARM7/port.dox +++ b/ports/ARM7/port.dox @@ -20,8 +20,8 @@ * @section ARM7_STATES Mapping of the System States in the ARM7 port * The ChibiOS/RT logical @ref system_states are mapped as follow in the ARM7 * port: - * - <b>Initialization</b>. This state is represented by the startup code and - * the initialization code before @p chSysInit() is executed. It has not a + * - <b>Init</b>. This state is represented by the startup code and the + * initialization code before @p chSysInit() is executed. It has not a * special hardware state associated, usually the CPU goes through several * hardware states during the startup phase. * - <b>Normal</b>. This is the state the system has after executing diff --git a/ports/ARMCM3/port.dox b/ports/ARMCM3/port.dox index 32f52337d..c1776669d 100644 --- a/ports/ARMCM3/port.dox +++ b/ports/ARMCM3/port.dox @@ -7,8 +7,8 @@ * @section ARMCM3_STATES Mapping of the System States in the ARM Cortex-M3 port * The ChibiOS/RT logical @ref system_states are mapped as follow in the ARM * Cortex-M3 port: - * - <b>Initialization</b>. This state is represented by the startup code and - * the initialization code before @p chSysInit() is executed. It has not a + * - <b>Init</b>. This state is represented by the startup code and the + * initialization code before @p chSysInit() is executed. It has not a * special hardware state associated. * - <b>Normal</b>. This is the state the system has after executing * @p chSysInit(). In this state the ARM Cortex-M3 has the BASEPRI register diff --git a/ports/AVR/port.dox b/ports/AVR/port.dox index 8f455f208..817da5a64 100644 --- a/ports/AVR/port.dox +++ b/ports/AVR/port.dox @@ -7,8 +7,8 @@ * @section AVR_STATES Mapping of the System States in the AVR port * The ChibiOS/RT logical @ref system_states are mapped as follow in the AVR * port: - * - <b>Initialization</b>. This state is represented by the startup code and - * the initialization code before @p chSysInit() is executed. It has not a + * - <b>Init</b>. This state is represented by the startup code and the + * initialization code before @p chSysInit() is executed. It has not a * special hardware state associated. * - <b>Normal</b>. This is the state the system has after executing * @p chSysInit(). Interrupts are enabled. diff --git a/ports/MSP430/port.dox b/ports/MSP430/port.dox index 108a44bd8..774098e3d 100644 --- a/ports/MSP430/port.dox +++ b/ports/MSP430/port.dox @@ -7,8 +7,8 @@ * @section MSP430_STATES Mapping of the System States in the MSP430 port * The ChibiOS/RT logical @ref system_states are mapped as follow in the MSP430 * port: - * - <b>Initialization</b>. This state is represented by the startup code and - * the initialization code before @p chSysInit() is executed. It has not a + * - <b>Init</b>. This state is represented by the startup code and the + * initialization code before @p chSysInit() is executed. It has not a * special hardware state associated. * - <b>Normal</b>. This is the state the system has after executing * @p chSysInit(). Interrupts are enabled. -- cgit v1.2.3