git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@48 35acf78f-673a-0410-8e92-d51de3d6d3f4

master
gdisirio 2007-10-13 06:59:54 +00:00
parent 6264592246
commit 73642ca0cc
13 changed files with 74 additions and 63 deletions

View File

@ -53,7 +53,8 @@ static void ChkIntSources(void) {
if (Com1InInterruptSimCom() || Com2InInterruptSimCom() || if (Com1InInterruptSimCom() || Com2InInterruptSimCom() ||
Com1OutInterruptSimCom() || Com2OutInterruptSimCom() || Com1OutInterruptSimCom() || Com2OutInterruptSimCom() ||
Com1ConnInterruptSimCom() || Com2ConnInterruptSimCom()) { Com1ConnInterruptSimCom() || Com2ConnInterruptSimCom()) {
chSchRescheduleI(); if (chSchRescRequiredI())
chSchDoRescheduleI();
return; return;
} }

View File

@ -76,7 +76,8 @@ static void ChkIntSources(void) {
if (Com1InInterruptSimCom() || Com2InInterruptSimCom() || if (Com1InInterruptSimCom() || Com2InInterruptSimCom() ||
Com1OutInterruptSimCom() || Com2OutInterruptSimCom() || Com1OutInterruptSimCom() || Com2OutInterruptSimCom() ||
Com1ConnInterruptSimCom() || Com2ConnInterruptSimCom()) { Com1ConnInterruptSimCom() || Com2ConnInterruptSimCom()) {
chSchRescheduleI(); if (chSchRescRequiredI())
chSchDoRescheduleI();
return; return;
} }

View File

@ -38,13 +38,21 @@ AVR-AT90CANx-GCC - Port on AVER AT90CAN128, not complete yet.
*** Releases *** *** Releases ***
***************************************************************************** *****************************************************************************
*** 0.3.3 ***
- Modified the chVTSetI(), now for the "time" parameter can have value zero
with meaning "infinite".
This allows all the APIs with timeout parameters to be invoked
with timeout=0 and work with no timeout.
- Fixes in the documentation.
- Renamed some APIs in the "Sch" group to have an S suffix instead of I.
*** 0.3.2 *** *** 0.3.2 ***
- Modified the chSysInit() to give the idle thread absolute priority, the - Modified the chSysInit() to give the idle thread absolute priority, the
priority is then lowered to the minimum value into the chSysPause(). This priority is then lowered to the minimum value into the chSysPause(). This
is done in order to ensure that the initializations performed into the is done in order to ensure that the initializations performed into the
main() procedure are performed before any thread starts. main() procedure are performed before any thread starts.
- Added chThdSetPriority() new API. - Added chThdSetPriority() new API.
- Added a generic events generator timer to the library code. - Added a generic events generator timer modulee to the library code.
- Modified the ARM7-LPC214x-GCC demo to show the use of the event timer. - Modified the ARM7-LPC214x-GCC demo to show the use of the event timer.
- Added the "#ifdef __cplusplus" stuff to the header files. - Added the "#ifdef __cplusplus" stuff to the header files.
- Removed an obsolete definition in ./src/templates/chtypes.h. - Removed an obsolete definition in ./src/templates/chtypes.h.

View File

@ -39,7 +39,8 @@ void chVTInit(void) {
/** /**
* Enables a virtual timer. * Enables a virtual timer.
* @param vtp the \p VirtualTimer structure pointer * @param vtp the \p VirtualTimer structure pointer
* @param time the number of time ticks * @param time the number of time ticks, the value zero is allowed with
* meaning "infinite".
* @param vtfunc the timer callback function. After invoking the callback * @param vtfunc the timer callback function. After invoking the callback
* the timer is disabled and the structure can be disposed or * the timer is disabled and the structure can be disposed or
* reused. * reused.
@ -48,21 +49,23 @@ void chVTInit(void) {
* @note The associated function is invoked by an interrupt handler. * @note The associated function is invoked by an interrupt handler.
*/ */
void chVTSetI(VirtualTimer *vtp, t_time time, t_vtfunc vtfunc, void *par) { void chVTSetI(VirtualTimer *vtp, t_time time, t_vtfunc vtfunc, void *par) {
VirtualTimer *p;
vtp->vt_func = vtfunc; vtp->vt_func = vtfunc;
vtp->vt_par = par; vtp->vt_par = par;
p = dlist.dl_next;
while (p->vt_dtime < time) {
time -= p->vt_dtime;
p = p->vt_next;
}
vtp->vt_prev = (vtp->vt_next = p)->vt_prev; if (time) {
vtp->vt_prev->vt_next = p->vt_prev = vtp; VirtualTimer *p = dlist.dl_next;
vtp->vt_dtime = time; while (p->vt_dtime < time) {
if (p != (VirtualTimer *)&dlist) time -= p->vt_dtime;
p->vt_dtime -= time; p = p->vt_next;
}
vtp->vt_prev = (vtp->vt_next = p)->vt_prev;
vtp->vt_prev->vt_next = p->vt_prev = vtp;
vtp->vt_dtime = time;
if (p != (VirtualTimer *)&dlist)
p->vt_dtime -= time;
}
} }
/** /**

View File

@ -104,7 +104,7 @@ void chEvtSend(EventSource *esp) {
chSchReadyI(tp); chSchReadyI(tp);
elp = elp->el_next; elp = elp->el_next;
} }
chSchRescheduleI(); chSchRescheduleS();
chSysUnlock(); chSysUnlock();
} }
@ -112,7 +112,7 @@ void chEvtSend(EventSource *esp) {
/** /**
* Signals all the Event Listeners registered on the specified Event Source. * Signals all the Event Listeners registered on the specified Event Source.
* @param esp pointer to the \p EventSource structure * @param esp pointer to the \p EventSource structure
* @note This function must be called with interrupts disabled. * @note This function does not reschedule.
*/ */
void chEvtSendI(EventSource *esp) { void chEvtSendI(EventSource *esp) {
EventListener *elp; EventListener *elp;
@ -153,7 +153,7 @@ t_eventid chEvtWait(t_eventmask ewmask,
if ((currp->p_epending & ewmask) == 0) { if ((currp->p_epending & ewmask) == 0) {
currp->p_ewmask = ewmask; currp->p_ewmask = ewmask;
chSchGoSleepI(PRWTEVENT); chSchGoSleepS(PRWTEVENT);
} }
i = 0, m = 1; i = 0, m = 1;
while ((currp->p_epending & ewmask & m) == 0) while ((currp->p_epending & ewmask & m) == 0)
@ -219,7 +219,7 @@ t_eventid chEvtWaitTimeout(t_eventmask ewmask,
chVTSetI(&vt, time, unwait, currp); chVTSetI(&vt, time, unwait, currp);
currp->p_ewmask = ewmask; currp->p_ewmask = ewmask;
chSchGoSleepI(PRWTEVENT); chSchGoSleepS(PRWTEVENT);
if (!vt.vt_func) { if (!vt.vt_func) {
chSysUnlock(); chSysUnlock();

View File

@ -40,7 +40,7 @@ t_msg chMsgSend(Thread *tp, t_msg msg) {
if (tp->p_state == PRWTMSG) if (tp->p_state == PRWTMSG)
chSchReadyI(tp); chSchReadyI(tp);
currp->p_msg = msg; currp->p_msg = msg;
chSchGoSleepI(PRSNDMSG); chSchGoSleepS(PRSNDMSG);
msg = currp->p_rdymsg; msg = currp->p_rdymsg;
chSysUnlock(); chSysUnlock();
@ -71,7 +71,7 @@ t_msg chMsgSendWithEvent(Thread *tp, t_msg msg, EventSource *esp) {
// chSchReadyI(tp); // chSchReadyI(tp);
chEvtSendI(esp); chEvtSendI(esp);
currp->p_msg = msg; currp->p_msg = msg;
chSchGoSleepI(PRSNDMSG); chSchGoSleepS(PRSNDMSG);
msg = currp->p_rdymsg; msg = currp->p_rdymsg;
chSysUnlock(); chSysUnlock();
@ -113,7 +113,7 @@ t_msg chMsgSendTimeout(Thread *tp, t_msg msg, t_time time) {
if (tp->p_state == PRWTMSG) if (tp->p_state == PRWTMSG)
chSchReadyI(tp); chSchReadyI(tp);
currp->p_msg = msg; currp->p_msg = msg;
chSchGoSleepI(PRSNDMSG); chSchGoSleepS(PRSNDMSG);
msg = currp->p_rdymsg; msg = currp->p_rdymsg;
if (vt.vt_func) if (vt.vt_func)
chVTResetI(&vt); chVTResetI(&vt);
@ -138,7 +138,7 @@ t_msg chMsgWait(void) {
chSysLock(); chSysLock();
if (!chMsgIsPendingI(currp)) if (!chMsgIsPendingI(currp))
chSchGoSleepI(PRWTMSG); chSchGoSleepS(PRWTMSG);
msg = chMsgGetI(currp); msg = chMsgGetI(currp);
chSysUnlock(); chSysUnlock();
@ -183,7 +183,7 @@ void chMsgRelease(t_msg msg) {
chSysLock(); chSysLock();
// if (!chMsgIsPendingI(currp) // if (!chMsgIsPendingI(currp)
chSchWakeupI(fifo_remove(&currp->p_msgqueue), msg); chSchWakeupS(fifo_remove(&currp->p_msgqueue), msg);
chSysUnlock(); chSysUnlock();
} }

View File

@ -145,10 +145,10 @@ t_msg chIQGetTimeout(Queue *qp, t_time time) {
* is non-blocking and can return zero if the queue is empty. * is non-blocking and can return zero if the queue is empty.
* @param qp pointer to a \p Queue structure * @param qp pointer to a \p Queue structure
* @param buffer the data buffer * @param buffer the data buffer
* @param n the maxium amount of data to be read * @param n the maximum amount of data to be read
* @return the number of bytes read * @return the number of bytes read
* @note This function is the upper side endpoint of the input queue. * @note This function is the upper side endpoint of the input queue.
* @note The function is not atomical, if you need atomicity it is suggested * @note The function is not atomic, if you need atomicity it is suggested
* to use a semaphore for mutual exclusion. * to use a semaphore for mutual exclusion.
*/ */
t_size chIQRead(Queue *qp, BYTE8 *buffer, t_size n) { t_size chIQRead(Queue *qp, BYTE8 *buffer, t_size n) {
@ -167,9 +167,6 @@ t_size chIQRead(Queue *qp, BYTE8 *buffer, t_size n) {
if (qp->q_rdptr >= qp->q_top) if (qp->q_rdptr >= qp->q_top)
qp->q_rdptr = qp->q_buffer; qp->q_rdptr = qp->q_buffer;
// if (qp->q_notify)
// qp->q_notify();
chSysUnlock(); chSysUnlock();
r++; r++;
} }
@ -264,9 +261,9 @@ t_msg chOQGetI(Queue *qp) {
* is non-blocking and can return zero if the queue is full. * is non-blocking and can return zero if the queue is full.
* @param qp pointer to a \p Queue structure * @param qp pointer to a \p Queue structure
* @param buffer the data buffer * @param buffer the data buffer
* @param n the maxium amount of data to be written * @param n the maximum amount of data to be written
* @note This function is the upper side endpoint of the output queue. * @note This function is the upper side endpoint of the output queue.
* @note The function is not atomical, if you need atomicity it is suggested * @note The function is not atomic, if you need atomicity it is suggested
* to use a semaphore for mutual exclusion. * to use a semaphore for mutual exclusion.
*/ */
t_size chOQWrite(Queue *qp, BYTE8 *buffer, t_size n) { t_size chOQWrite(Queue *qp, BYTE8 *buffer, t_size n) {
@ -285,9 +282,6 @@ t_size chOQWrite(Queue *qp, BYTE8 *buffer, t_size n) {
if (qp->q_wrptr >= qp->q_top) if (qp->q_wrptr >= qp->q_top)
qp->q_wrptr = qp->q_buffer; qp->q_wrptr = qp->q_buffer;
// if (qp->q_notify)
// qp->q_notify();
chSysUnlock(); chSysUnlock();
w++; w++;
} }

View File

@ -98,7 +98,7 @@ static void nextready(void) {
* @note The function must be called in the system mutex zone. * @note The function must be called in the system mutex zone.
* @note The function is not meant to be used in the user code directly. * @note The function is not meant to be used in the user code directly.
*/ */
void chSchGoSleepI(t_tstate newstate) { void chSchGoSleepS(t_tstate newstate) {
currp->p_state = newstate; currp->p_state = newstate;
nextready(); nextready();
@ -115,7 +115,7 @@ void chSchGoSleepI(t_tstate newstate) {
* @note It is equivalent to a \p chSchReadyI() followed by a * @note It is equivalent to a \p chSchReadyI() followed by a
* \p chSchRescheduleI() but much more efficient. * \p chSchRescheduleI() but much more efficient.
*/ */
void chSchWakeupI(Thread *tp, t_msg msg) { void chSchWakeupS(Thread *tp, t_msg msg) {
Thread *ctp = currp; Thread *ctp = currp;
if (tp->p_prio <= ctp->p_prio) if (tp->p_prio <= ctp->p_prio)
@ -134,7 +134,7 @@ void chSchWakeupI(Thread *tp, t_msg msg) {
* ready list then it becomes running. * ready list then it becomes running.
* @note The function must be called in the system mutex zone. * @note The function must be called in the system mutex zone.
*/ */
void chSchRescheduleI(void) { void chSchRescheduleS(void) {
if (isempty(&rlist.r_queue) || firstprio(&rlist.r_queue) <= currp->p_prio) if (isempty(&rlist.r_queue) || firstprio(&rlist.r_queue) <= currp->p_prio)
return; return;

View File

@ -55,7 +55,7 @@ void chSemReset(Semaphore *sp, t_cnt n) {
if (cnt < 0) { if (cnt < 0) {
while (cnt++) while (cnt++)
chSchReadyI(fifo_remove(&sp->s_queue))->p_rdymsg = RDY_RESET; chSchReadyI(fifo_remove(&sp->s_queue))->p_rdymsg = RDY_RESET;
chSchRescheduleI(); chSchRescheduleS();
} }
chSysUnlock(); chSysUnlock();
@ -68,7 +68,7 @@ void chSemReset(Semaphore *sp, t_cnt n) {
* @note The released threads can recognize they were waked up by a reset * @note The released threads can recognize they were waked up by a reset
* instead than a signal because the \p p_rdymsg field is set to * instead than a signal because the \p p_rdymsg field is set to
* \p RDY_RESET. * \p RDY_RESET.
* @note This function must be called with interrupts disabled. * @note This function does not reschedule.
*/ */
void chSemResetI(Semaphore *sp, t_cnt n) { void chSemResetI(Semaphore *sp, t_cnt n) {
t_cnt cnt; t_cnt cnt;
@ -90,7 +90,7 @@ void chSemWait(Semaphore *sp) {
if (--sp->s_cnt < 0) { if (--sp->s_cnt < 0) {
fifo_insert(currp, &sp->s_queue); fifo_insert(currp, &sp->s_queue);
currp->p_semp = sp; currp->p_semp = sp;
chSchGoSleepI(PRWTSEM); chSchGoSleepS(PRWTSEM);
} }
chSysUnlock(); chSysUnlock();
@ -107,7 +107,7 @@ void chSemWaitS(Semaphore *sp) {
if (--sp->s_cnt < 0) { if (--sp->s_cnt < 0) {
fifo_insert(currp, &sp->s_queue); fifo_insert(currp, &sp->s_queue);
currp->p_semp = sp; currp->p_semp = sp;
chSchGoSleepI(PRWTSEM); chSchGoSleepS(PRWTSEM);
} }
} }
@ -137,7 +137,7 @@ t_msg chSemWaitTimeout(Semaphore *sp, t_time time) {
chVTSetI(&vt, time, unwait, currp); chVTSetI(&vt, time, unwait, currp);
fifo_insert(currp, &sp->s_queue); fifo_insert(currp, &sp->s_queue);
currp->p_semp = sp; currp->p_semp = sp;
chSchGoSleepI(PRWTSEM); chSchGoSleepS(PRWTSEM);
msg = currp->p_rdymsg; msg = currp->p_rdymsg;
if (vt.vt_func) if (vt.vt_func)
chVTResetI(&vt); chVTResetI(&vt);
@ -168,7 +168,7 @@ t_msg chSemWaitTimeoutS(Semaphore *sp, t_time time) {
chVTSetI(&vt, time, unwait, currp); chVTSetI(&vt, time, unwait, currp);
fifo_insert(currp, &sp->s_queue); fifo_insert(currp, &sp->s_queue);
currp->p_semp = sp; currp->p_semp = sp;
chSchGoSleepI(PRWTSEM); chSchGoSleepS(PRWTSEM);
if (vt.vt_func) if (vt.vt_func)
chVTResetI(&vt); chVTResetI(&vt);
return currp->p_rdymsg; return currp->p_rdymsg;
@ -188,7 +188,7 @@ void chSemSignal(Semaphore *sp) {
chSysLock(); chSysLock();
if (sp->s_cnt++ < 0) if (sp->s_cnt++ < 0)
chSchWakeupI(fifo_remove(&sp->s_queue), RDY_OK); chSchWakeupS(fifo_remove(&sp->s_queue), RDY_OK);
chSysUnlock(); chSysUnlock();
} }
@ -199,6 +199,7 @@ void chSemSignal(Semaphore *sp) {
* @note This function must be called with interrupts disabled. * @note This function must be called with interrupts disabled.
* @note The function is available only if the \p CH_USE_SEMAPHORES * @note The function is available only if the \p CH_USE_SEMAPHORES
* option is enabled in \p chconf.h. * option is enabled in \p chconf.h.
* @note This function does not reschedule.
*/ */
void chSemSignalI(Semaphore *sp) { void chSemSignalI(Semaphore *sp) {
@ -224,10 +225,10 @@ void chSemSignalWait(Semaphore *sps, Semaphore *spw) {
if (--spw->s_cnt < 0) { if (--spw->s_cnt < 0) {
fifo_insert(currp, &spw->s_queue); fifo_insert(currp, &spw->s_queue);
currp->p_semp = spw; currp->p_semp = spw;
chSchGoSleepI(PRWTSEM); chSchGoSleepS(PRWTSEM);
} }
else else
chSchRescheduleI(); chSchRescheduleS();
chSysUnlock(); chSysUnlock();
} }
@ -265,7 +266,7 @@ void chSemRaisePrioWait(Semaphore *sp) {
if (--sp->s_cnt < 0) { if (--sp->s_cnt < 0) {
prioenq(currp, &sp->s_queue); prioenq(currp, &sp->s_queue);
currp->p_semp = sp; currp->p_semp = sp;
chSchGoSleepI(PRWTSEM); chSchGoSleepS(PRWTSEM);
} }
if (!currp->p_rtcnt++) if (!currp->p_rtcnt++)
@ -288,10 +289,10 @@ void chSemLowerPrioSignal(Semaphore *sp) {
currp->p_prio -= MEPRIO; currp->p_prio -= MEPRIO;
if (sp->s_cnt++ < 0) if (sp->s_cnt++ < 0)
chSchReadyI(fifo_remove(&sp->s_queue)); chSchReadyI(fifo_remove(&sp->s_queue));
chSchRescheduleI(); chSchRescheduleS();
} }
else if (sp->s_cnt++ < 0) else if (sp->s_cnt++ < 0)
chSchWakeupI(fifo_remove(&sp->s_queue), RDY_OK); chSchWakeupS(fifo_remove(&sp->s_queue), RDY_OK);
chSysUnlock(); chSysUnlock();
} }
@ -315,7 +316,7 @@ void chSemRaisePrioSignalWait(Semaphore *sps, Semaphore *spw) {
if (--spw->s_cnt < 0) { if (--spw->s_cnt < 0) {
prioenq(currp, &spw->s_queue); prioenq(currp, &spw->s_queue);
currp->p_semp = spw; currp->p_semp = spw;
chSchGoSleepI(PRWTSEM); chSchGoSleepS(PRWTSEM);
if (!currp->p_rtcnt++) if (!currp->p_rtcnt++)
currp->p_prio += MEPRIO; currp->p_prio += MEPRIO;
@ -324,7 +325,7 @@ void chSemRaisePrioSignalWait(Semaphore *sps, Semaphore *spw) {
if (!currp->p_rtcnt++) if (!currp->p_rtcnt++)
currp->p_prio += MEPRIO; currp->p_prio += MEPRIO;
chSchRescheduleI(); // Really needed ? chSchRescheduleS(); // Really needed ?
} }
chSysUnlock(); chSysUnlock();
@ -351,10 +352,10 @@ void chSemLowerPrioSignalWait(Semaphore *sps, Semaphore *spw) {
if (--spw->s_cnt < 0) { if (--spw->s_cnt < 0) {
fifo_insert(currp, &spw->s_queue); // fifo_insert() because the spw is a normal sem. fifo_insert(currp, &spw->s_queue); // fifo_insert() because the spw is a normal sem.
currp->p_semp = spw; currp->p_semp = spw;
chSchGoSleepI(PRWTSEM); chSchGoSleepS(PRWTSEM);
} }
else else
chSchRescheduleI(); chSchRescheduleS();
chSysUnlock(); chSysUnlock();
} }

View File

@ -35,7 +35,7 @@ void chThdSleep(t_time time) {
chSysLock(); chSysLock();
chVTSetI(&vt, time, (t_vtfunc)chSchReadyI, currp); chVTSetI(&vt, time, (t_vtfunc)chSchReadyI, currp);
chSchGoSleepI(PRSLEEP); chSchGoSleepS(PRSLEEP);
chSysUnlock(); chSysUnlock();
} }
@ -67,7 +67,7 @@ void chThdSleepUntil(t_time time) {
chSysLock(); chSysLock();
chVTSetI(&vt, (t_time)(time - stime), (t_vtfunc)chSchReadyI, currp); chVTSetI(&vt, (t_time)(time - stime), (t_vtfunc)chSchReadyI, currp);
chSchGoSleepI(PRSLEEP); chSchGoSleepS(PRSLEEP);
chSysUnlock(); chSysUnlock();
} }

View File

@ -91,7 +91,7 @@ Thread *chThdCreate(t_prio prio, t_tmode mode, void *workspace,
#endif #endif
chSysLock(); chSysLock();
chSchWakeupI(tp, RDY_OK); chSchWakeupS(tp, RDY_OK);
chSysUnlock(); chSysUnlock();
#ifdef CH_USE_RESUME #ifdef CH_USE_RESUME
@ -116,7 +116,7 @@ void chThdSetPriority(t_prio newprio) {
#else #else
currp->p_prio = newprio; currp->p_prio = newprio;
#endif #endif
chSchRescheduleI(); chSchRescheduleS();
chSysUnlock(); chSysUnlock();
} }
@ -135,7 +135,7 @@ void chThdResume(Thread *tp) {
chSysLock(); chSysLock();
if (tp->p_state == PRSUSPENDED) if (tp->p_state == PRSUSPENDED)
chSchWakeupI(tp, RDY_OK); chSchWakeupS(tp, RDY_OK);
chSysUnlock(); chSysUnlock();
} }
@ -176,7 +176,7 @@ void chThdExit(t_msg msg) {
#ifdef CH_USE_EXIT_EVENT #ifdef CH_USE_EXIT_EVENT
chEvtSendI(&currp->p_exitesource); chEvtSendI(&currp->p_exitesource);
#endif #endif
chSchGoSleepI(PREXIT); chSchGoSleepS(PREXIT);
chSysUnlock(); /* Never executed. */ chSysUnlock(); /* Never executed. */
} }
@ -196,7 +196,7 @@ t_msg chThdWait(Thread *tp) {
if (tp->p_state != PREXIT) { if (tp->p_state != PREXIT) {
list_insert(currp, &tp->p_waiting); list_insert(currp, &tp->p_waiting);
chSchGoSleepI(PRWAIT); chSchGoSleepS(PRWAIT);
} }
chSysUnlock(); chSysUnlock();

View File

@ -81,6 +81,9 @@ extern DeltaList dlist;
} \ } \
} }
/** Infinite time specification.*/
#define TIME_INFINITE 0
/* /*
* Virtual Timers APIs. * Virtual Timers APIs.
*/ */

View File

@ -50,9 +50,9 @@ extern "C" {
#endif #endif
void chSchInit(void); void chSchInit(void);
Thread *chSchReadyI(Thread *tp); Thread *chSchReadyI(Thread *tp);
void chSchGoSleepI(t_tstate newstate); void chSchGoSleepS(t_tstate newstate);
void chSchWakeupI(Thread *tp, t_msg msg); void chSchWakeupS(Thread *tp, t_msg msg);
void chSchRescheduleI(void); void chSchRescheduleS(void);
void chSchDoRescheduleI(void); void chSchDoRescheduleI(void);
BOOL chSchRescRequiredI(void); BOOL chSchRescRequiredI(void);
void chSchTimerHandlerI(void); void chSchTimerHandlerI(void);