git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
f712427135
commit
30f0bb1d66
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup VirtualTimers
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ch.h>
|
||||||
|
|
||||||
|
#ifdef CH_USE_VIRTUAL_TIMERS
|
||||||
|
DeltaList dlist;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Virtual Timers initialization. Internal use only.
|
||||||
|
*/
|
||||||
|
void chVTInit(void) {
|
||||||
|
|
||||||
|
dlist.dl_next = dlist.dl_prev = (VirtualTimer *)&dlist;
|
||||||
|
dlist.dl_dtime = MAXDELTA;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables a virtual timer.
|
||||||
|
* @param vtp the \p VirtualTimer structure pointer
|
||||||
|
* @param time the number of time ticks
|
||||||
|
* @param vtfunc the timer callback function. After invoking the callback
|
||||||
|
* the timer is disabled and the structure can be disposed or
|
||||||
|
* reused.
|
||||||
|
* @param par a parameter that will be passed to the callback function
|
||||||
|
* @note Must be called with the interrupts disabled.
|
||||||
|
* @note The associated function is invoked by an interrupt handler.
|
||||||
|
*/
|
||||||
|
void chVTSetI(VirtualTimer *vtp, t_time time, t_vtfunc vtfunc, void *par) {
|
||||||
|
VirtualTimer *p;
|
||||||
|
|
||||||
|
vtp->vt_func = vtfunc;
|
||||||
|
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;
|
||||||
|
vtp->vt_prev->vt_next = p->vt_prev = vtp;
|
||||||
|
vtp->vt_dtime = time;
|
||||||
|
if (p != (VirtualTimer *)&dlist)
|
||||||
|
p->vt_dtime -= time;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables a Virtual Timer.
|
||||||
|
* @param vtp the \p VirtualTimer structure pointer
|
||||||
|
* @note It must be called with the interrupts disabled.
|
||||||
|
* @note The timer MUST be active when this function is invoked.
|
||||||
|
*/
|
||||||
|
void chVTResetI(VirtualTimer *vtp) {
|
||||||
|
|
||||||
|
if (vtp->vt_next != (VirtualTimer *)&dlist)
|
||||||
|
vtp->vt_next->vt_dtime += vtp->vt_dtime;
|
||||||
|
vtp->vt_prev->vt_next = vtp->vt_next;
|
||||||
|
vtp->vt_next->vt_prev = vtp->vt_prev;
|
||||||
|
vtp->vt_func = 0;
|
||||||
|
}
|
||||||
|
#endif /* CH_USE_VIRTUAL_TIMER */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -0,0 +1,247 @@
|
||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup Events
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#include <ch.h>
|
||||||
|
|
||||||
|
#ifdef CH_USE_EVENTS
|
||||||
|
/**
|
||||||
|
* Registers an Event Listener on an Event Source.
|
||||||
|
* @param esp pointer to the \p EventSource structure
|
||||||
|
* @param elp pointer to the \p EventListener structure
|
||||||
|
* @param eid numeric identifier assigned to the Event Listener. The identifier
|
||||||
|
* is used as index for the event callback function.
|
||||||
|
* The value must range between zero and the size, in bit, of the
|
||||||
|
* \p t_eventid type minus one.
|
||||||
|
* @note Multiple Event Listeners can use the same event identifier, the
|
||||||
|
* listener will share the callback function.
|
||||||
|
*/
|
||||||
|
void chEvtRegister(EventSource *esp, EventListener *elp, t_eventid eid) {
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
elp->el_next = esp->es_next;
|
||||||
|
esp->es_next = elp;
|
||||||
|
elp->el_listener = currp;
|
||||||
|
elp->el_id = eid;
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters an Event Listener from its Event Source.
|
||||||
|
* @param esp pointer to the \p EventSource structure
|
||||||
|
* @param elp pointer to the \p EventListener structure
|
||||||
|
* @note If the event listener is not registered on the specified event source
|
||||||
|
* then the function does nothing.
|
||||||
|
* @note For optimal performance perform the unregister operations in inverse
|
||||||
|
* order of the register operations (elements are found on top of the
|
||||||
|
* list).
|
||||||
|
*/
|
||||||
|
void chEvtUnregister(EventSource *esp, EventListener *elp) {
|
||||||
|
EventListener *p = (EventListener *)esp;
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
while (p->el_next != (EventListener *)esp) {
|
||||||
|
if (p->el_next == elp) {
|
||||||
|
p->el_next = elp->el_next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p = p->el_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the pending events specified in the mask.
|
||||||
|
* @param mask the events to be cleared
|
||||||
|
*/
|
||||||
|
void chEvtClear(t_eventmask mask) {
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
currp->p_epending &= ~mask;
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signals all the Event Listeners registered on the specified Event Source.
|
||||||
|
* @param esp pointer to the \p EventSource structure
|
||||||
|
*/
|
||||||
|
void chEvtSend(EventSource *esp) {
|
||||||
|
EventListener *elp;
|
||||||
|
BOOL flag = FALSE;
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
elp = esp->es_next;
|
||||||
|
while (elp != (EventListener *)esp) {
|
||||||
|
Thread *tp = elp->el_listener;
|
||||||
|
|
||||||
|
tp->p_epending |= EventMask(elp->el_id);
|
||||||
|
if ((tp->p_state == PRWTEVENT) && (tp->p_epending & tp->p_ewmask))
|
||||||
|
chSchReadyI(tp), flag = TRUE;
|
||||||
|
elp = elp->el_next;
|
||||||
|
}
|
||||||
|
if (flag)
|
||||||
|
chSchRescheduleI();
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signals all the Event Listeners registered on the specified Event Source.
|
||||||
|
* @param esp pointer to the \p EventSource structure
|
||||||
|
* @note This function must be called with interrupts disabled.
|
||||||
|
*/
|
||||||
|
void chEvtSendI(EventSource *esp) {
|
||||||
|
EventListener *elp;
|
||||||
|
|
||||||
|
elp = esp->es_next;
|
||||||
|
while (elp != (EventListener *)esp) {
|
||||||
|
Thread *tp = elp->el_listener;
|
||||||
|
|
||||||
|
tp->p_epending |= EventMask(elp->el_id);
|
||||||
|
if ((tp->p_state == PRWTEVENT) && (tp->p_epending & tp->p_ewmask))
|
||||||
|
chSchReadyI(tp);
|
||||||
|
elp = elp->el_next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The function waits for an event and returns the event identifier, if an
|
||||||
|
* event handler is specified then the handler is executed before returning.
|
||||||
|
* @param ewmask mask of the events that should be served by the function,
|
||||||
|
* \p ALL_EVENTS enables all the sources
|
||||||
|
* @param handlers an array of \p t_evhandler. The array must be
|
||||||
|
* have indexes from zero up the higher registered event
|
||||||
|
* identifier. The array can be \p NULL or contain \p NULL
|
||||||
|
* elements (no callbacks specified).
|
||||||
|
* @return the event identifier
|
||||||
|
* @note Only a single event is served in the function, the one with the
|
||||||
|
* lowest event id. The function is meant to be invoked into a loop so
|
||||||
|
* that all events are received and served.<br>
|
||||||
|
* This means that Event Listeners with a lower event identifier have
|
||||||
|
* an higher priority.
|
||||||
|
*/
|
||||||
|
t_eventid chEvtWait(t_eventmask ewmask, t_evhandler handlers[]) {
|
||||||
|
t_eventid i;
|
||||||
|
t_eventmask m;
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
if ((currp->p_epending & ewmask) == 0) {
|
||||||
|
currp->p_ewmask = ewmask;
|
||||||
|
chSchGoSleepI(PRWTEVENT);
|
||||||
|
}
|
||||||
|
i = 0, m = 1;
|
||||||
|
while ((currp->p_epending & ewmask & m) == 0)
|
||||||
|
i += 1, m <<= 1;
|
||||||
|
currp->p_epending &= ~m;
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
|
||||||
|
if (handlers && handlers[i])
|
||||||
|
handlers[i](i);
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CH_USE_EVENTS_TIMEOUT
|
||||||
|
static void unwait(void *p) {
|
||||||
|
|
||||||
|
// Test removed, it should never happen.
|
||||||
|
// if (((Thread *)p)->p_state == PRWTEVENT)
|
||||||
|
chSchReadyI(dequeue(p))->p_rdymsg = RDY_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The function waits for an event or the specified timeout then returns the
|
||||||
|
* event identifier, if an event handler is specified then the handler is
|
||||||
|
* executed before returning.
|
||||||
|
* @param ewmask mask of the events that should be served by the function,
|
||||||
|
* \p ALL_EVENTS enables all the sources
|
||||||
|
* @param handlers an array of \p t_evhandler. The array must be
|
||||||
|
* have indexes from zero up the higher registered event
|
||||||
|
* identifier. The array can be NULL or contain NULL elements
|
||||||
|
* (no callback specified).
|
||||||
|
* @param time the number of ticks before the operation timouts, if set to
|
||||||
|
* zero then the function exits immediatly with \p RDY_TIMEOUT if
|
||||||
|
* there are not serviceable events pending
|
||||||
|
* @return the event identifier or \p RDY_TIMEOUT the specified time expired or
|
||||||
|
* if the timeout was set to zero and no serviceable pending events
|
||||||
|
* were present
|
||||||
|
* @note Only a single event is served in the function, the one with the
|
||||||
|
* lowest event id. The function is meant to be invoked into a loop so
|
||||||
|
* that all events are received and served.<br>
|
||||||
|
* This means that Event Listeners with a lower event identifier have
|
||||||
|
* an higher priority.
|
||||||
|
* @note The function is available only if the \p CH_USE_EVENTS_TIMEOUT
|
||||||
|
* option is enabled in \p chconf.h.
|
||||||
|
*/
|
||||||
|
t_eventid chEvtWaitTimeout(t_eventmask ewmask,
|
||||||
|
t_evhandler handlers[],
|
||||||
|
t_time time) {
|
||||||
|
t_eventid i;
|
||||||
|
t_eventmask m;
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
if ((currp->p_epending & ewmask) == 0) {
|
||||||
|
VirtualTimer vt;
|
||||||
|
|
||||||
|
if (time == 0) {
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
return RDY_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
chVTSetI(&vt, time, unwait, currp);
|
||||||
|
currp->p_ewmask = ewmask;
|
||||||
|
chSchGoSleepI(PRWTEVENT);
|
||||||
|
if (!vt.vt_func) {
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
return RDY_TIMEOUT; // No need to read t_rdymsg value, it is a timeout.
|
||||||
|
}
|
||||||
|
chVTResetI(&vt);
|
||||||
|
}
|
||||||
|
i = 0, m = 1;
|
||||||
|
while ((currp->p_epending & ewmask & m) == 0)
|
||||||
|
i += 1, m <<= 1;
|
||||||
|
currp->p_epending &= ~m;
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
|
||||||
|
if (handlers && handlers[i])
|
||||||
|
handlers[i](i);
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
#endif /*CH_USE_EVENTS_TIMEOUT */
|
||||||
|
|
||||||
|
#endif /* CH_USE_EVENTS */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup Initialization
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ch.h>
|
||||||
|
|
||||||
|
static Thread idlethread;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ChibiOS/RT initialization. After executing this function the current
|
||||||
|
* instructions stream becomes the idle thread. The thread must execute the
|
||||||
|
* first user thread and then go to sleep into the \p chSysPause() where it
|
||||||
|
* will just serve the interrupts while keeping the lowest possible power
|
||||||
|
* mode.<br><br>
|
||||||
|
* @code
|
||||||
|
* chSysInit();
|
||||||
|
* chThdCreate(...); // Starts one or more user threads.
|
||||||
|
* chSysPause();
|
||||||
|
* @endcode
|
||||||
|
* @note Interrupts should be still disabled when \p chSysInit() is invoked and
|
||||||
|
* are internally enabled.
|
||||||
|
*/
|
||||||
|
void chSysInit(void) {
|
||||||
|
|
||||||
|
chSchInit();
|
||||||
|
#ifdef CH_USE_VIRTUAL_TIMERS
|
||||||
|
chVTInit();
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Now this instructions flow becomes the idle thread.
|
||||||
|
*/
|
||||||
|
_InitThread(IDLEPRIO, 0, &idlethread);
|
||||||
|
idlethread.p_state = PRCURR;
|
||||||
|
currp = &idlethread;
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -0,0 +1,194 @@
|
||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup Messages
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#include <ch.h>
|
||||||
|
|
||||||
|
#ifdef CH_USE_MESSAGES
|
||||||
|
/**
|
||||||
|
* Sends a message to the specified thread. The client is stopped until the
|
||||||
|
* server executes a \p chMsgRelease() after receiving the message.
|
||||||
|
*
|
||||||
|
* @param tp the pointer to the thread
|
||||||
|
* @param msg the message, it can be a pointer to a complex structure
|
||||||
|
* @return the return message from \p chMsgRelease()
|
||||||
|
*/
|
||||||
|
t_msg chMsgSend(Thread *tp, t_msg msg) {
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
enqueue(currp, &tp->p_msgqueue);
|
||||||
|
if (tp->p_state == PRWTMSG)
|
||||||
|
chSchReadyI(tp);
|
||||||
|
currp->p_msg = msg;
|
||||||
|
chSchGoSleepI(PRSNDMSG);
|
||||||
|
msg = currp->p_rdymsg;
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CH_USE_MESSAGES_EVENT
|
||||||
|
/**
|
||||||
|
* Sends a message to the specified thread and atomically triggers an event.
|
||||||
|
* The client is stopped until the server executes a \p chMsgRelease()
|
||||||
|
* after receiving the message.
|
||||||
|
*
|
||||||
|
* @param tp the pointer to the thread
|
||||||
|
* @param msg the message, it can be a pointer to a complex structure
|
||||||
|
* @param esp the event source to pulse while sending the message
|
||||||
|
* @return the return message from \p chMsgRelease()
|
||||||
|
* @return the message return status from \p chMsgRelease()
|
||||||
|
* @note This function assumes that the receiving thread is not sleeping into
|
||||||
|
* a \p chMsgWait(). The use case is that the server thread is waiting
|
||||||
|
* for both messages AND events while waiting into \p chEvtWait().
|
||||||
|
*/
|
||||||
|
t_msg chMsgSendWithEvent(Thread *tp, t_msg msg, EventSource *esp) {
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
enqueue(currp, &tp->p_msgqueue);
|
||||||
|
// if (tp->p_state == PRWTMSG)
|
||||||
|
// chSchReadyI(tp);
|
||||||
|
chEvtSendI(esp);
|
||||||
|
currp->p_msg = msg;
|
||||||
|
chSchGoSleepI(PRSNDMSG);
|
||||||
|
msg = currp->p_rdymsg;
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CH_USE_MESSAGES_TIMEOUT
|
||||||
|
static void unsend(void *p) {
|
||||||
|
|
||||||
|
// Test removed, it should never happen.
|
||||||
|
// if (((Thread *)p)->p_state == PRSNDMSG)
|
||||||
|
chSchReadyI(dequeue(p))->p_rdymsg = RDY_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a message to the specified thread with timeout specification. The
|
||||||
|
* sender is stopped until the receiver executes a \p chMsgRelease().
|
||||||
|
*
|
||||||
|
* @param tp the pointer to the thread
|
||||||
|
* @param msg the message. Note that it can be a pointer to a complex
|
||||||
|
* message structure.
|
||||||
|
* @param time the number of ticks before the operation fails
|
||||||
|
* @return the message return status from \p chMsgRelease() or
|
||||||
|
* \p RDY_TIMEOUT the specified time expired.
|
||||||
|
* @note The server thread can also return data into the message structure
|
||||||
|
* if you need messages to be bidirectional, just define the structure
|
||||||
|
* according your needs. If you dont need complicated messages exchange
|
||||||
|
* you may just use the \p chMsgRelease() status code as response
|
||||||
|
* to the message.
|
||||||
|
*/
|
||||||
|
t_msg chMsgSendTimeout(Thread *tp, t_msg msg, t_time time) {
|
||||||
|
VirtualTimer vt;
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
chVTSetI(&vt, time, unsend, currp);
|
||||||
|
enqueue(currp, &tp->p_msgqueue);
|
||||||
|
if (tp->p_state == PRWTMSG)
|
||||||
|
chSchReadyI(tp);
|
||||||
|
currp->p_msg = msg;
|
||||||
|
chSchGoSleepI(PRSNDMSG);
|
||||||
|
msg = currp->p_rdymsg;
|
||||||
|
if (vt.vt_func)
|
||||||
|
chVTResetI(&vt);
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
#endif /* CH_USE_MESSAGES_TIMEOUT */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Suspends the thread and waits for an incoming message.
|
||||||
|
*
|
||||||
|
* @return the pointer to the message structure. Note, it is always the
|
||||||
|
* message associated to the thread on the top of the messages queue.
|
||||||
|
* @note You can assume that the data contained in the message is stable until
|
||||||
|
* you invoke \p chMsgRelease() because the sending thread is
|
||||||
|
* suspended until then. Always remember that the message data is not
|
||||||
|
* copied between the sender and the receiver, just a pointer is passed.
|
||||||
|
*/
|
||||||
|
t_msg chMsgWait(void) {
|
||||||
|
t_msg msg;
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
if (!chMsgIsPendingI(currp))
|
||||||
|
chSchGoSleepI(PRWTMSG);
|
||||||
|
msg = chMsgGetI(currp);
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the next message in the queue.
|
||||||
|
*
|
||||||
|
* @return the pointer to the message structure. Note, it is always the
|
||||||
|
* message associated to the thread on the top of the messages queue.
|
||||||
|
* If the queue is empty then \p NULL is returned.
|
||||||
|
* @note You can assume that the data contained in the message is stable until
|
||||||
|
* you invoke \p chMsgRelease() because the sending thread is
|
||||||
|
* suspended until then. Always remember that the message data is not
|
||||||
|
* copied between the sender and the receiver, just a pointer is passed.
|
||||||
|
*/
|
||||||
|
t_msg chMsgGet(void) {
|
||||||
|
t_msg msg;
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
msg = chMsgIsPendingI(currp) ? chMsgGetI(currp) : NULL;
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Releases the thread waiting on top of the messages queue.
|
||||||
|
*
|
||||||
|
* @param msg the message returned to the message sender
|
||||||
|
* @note You can call this function only if there is a message already in the
|
||||||
|
* queue else the result will be unpredictable (a crash most likely).
|
||||||
|
* Exiting from the \p chMsgWait() ensures you have at least one
|
||||||
|
* message in the queue so it is not a big deal.<br>
|
||||||
|
* The condition is not checked in order to make this code as fast as
|
||||||
|
* possible.
|
||||||
|
*/
|
||||||
|
void chMsgRelease(t_msg msg) {
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
// if (!chMsgIsPendingI(currp)
|
||||||
|
chSchWakeupI(dequeue(currp->p_msgqueue.p_next), msg);
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CH_USE_MESSAGES */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -0,0 +1,478 @@
|
||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup IOQueues
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ch.h>
|
||||||
|
|
||||||
|
#ifdef CH_USE_QUEUES
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes an input queue. A Semaphore is internally initialized
|
||||||
|
* and works as a counter of the bytes contained in the queue.
|
||||||
|
* @param qp pointer to a \p Queue structure
|
||||||
|
* @param buffer pointer to a memory area allocated as queue buffer
|
||||||
|
* @param size size of the queue buffer
|
||||||
|
* @param inotify pointer to a callback function that is invoked when
|
||||||
|
* some data is read from the Queue. The value can be \p NULL.
|
||||||
|
*/
|
||||||
|
void chIQInit(Queue *qp, BYTE8 *buffer, t_size size, t_qnotify inotify) {
|
||||||
|
|
||||||
|
qp->q_buffer = qp->q_rdptr = qp->q_wrptr = buffer;
|
||||||
|
qp->q_top = buffer + size;
|
||||||
|
chSemInit(&qp->q_sem, 0);
|
||||||
|
qp->q_notify = inotify;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets an input queue. All the data is lost and the waiting threads
|
||||||
|
* resumed.
|
||||||
|
* @param qp pointer to a \p Queue structure
|
||||||
|
*/
|
||||||
|
void chIQReset(Queue *qp) {
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
qp->q_rdptr = qp->q_wrptr = qp->q_buffer;
|
||||||
|
chSemResetI(&qp->q_sem, 0);
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts a byte into an input queue.
|
||||||
|
* @param qp pointer to a \p Queue structure
|
||||||
|
* @param b the byte value to be written
|
||||||
|
* @return \p Q_OK if the operation is successful or \p Q_FULL if the queue is
|
||||||
|
* full.
|
||||||
|
* @note This function is the lower side endpoint of the Input Queue.
|
||||||
|
* @note This function must be called with interrupts disabled or from an
|
||||||
|
* interrupt handler.
|
||||||
|
*/
|
||||||
|
t_msg chIQPutI(Queue *qp, BYTE8 b) {
|
||||||
|
|
||||||
|
if (chIQIsFull(qp))
|
||||||
|
return Q_FULL;
|
||||||
|
|
||||||
|
*qp->q_wrptr++ = b;
|
||||||
|
if (qp->q_wrptr >= qp->q_top)
|
||||||
|
qp->q_wrptr = qp->q_buffer;
|
||||||
|
chSemSignalI(&qp->q_sem);
|
||||||
|
return Q_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a byte from the input queue, if the queue is empty then the
|
||||||
|
* calling thread is suspended until a byte arrives in the queue.
|
||||||
|
* @param qp pointer to a \p Queue structure
|
||||||
|
* @return a byte from the queue or \p Q_RESET if the queue was reset
|
||||||
|
*/
|
||||||
|
t_msg chIQGet(Queue *qp) {
|
||||||
|
BYTE8 b;
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
chSemWaitS(&qp->q_sem);
|
||||||
|
if (currp->p_rdymsg < RDY_OK) {
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
return currp->p_rdymsg;
|
||||||
|
}
|
||||||
|
b = *qp->q_rdptr++;
|
||||||
|
if (qp->q_rdptr >= qp->q_top)
|
||||||
|
qp->q_rdptr = qp->q_buffer;
|
||||||
|
|
||||||
|
if (qp->q_notify)
|
||||||
|
qp->q_notify();
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CH_USE_QUEUES_TIMEOUT
|
||||||
|
/**
|
||||||
|
* Gets a byte from the input queue, if the queue is empty then the
|
||||||
|
* calling thread is suspended until a byte arrives in the queue or the
|
||||||
|
* specified time expires.
|
||||||
|
* @param qp pointer to a \p Queue structure
|
||||||
|
* @param time the number of ticks before the operation timouts
|
||||||
|
* @return a byte from the queue, \p Q_TIMEOUT if the specified time expired
|
||||||
|
* or \p Q_RESET if the queue was reset
|
||||||
|
* @note The function is available only if the \p CH_USE_QUEUES_TIMEOUT
|
||||||
|
* option is enabled in \p chconf.h.
|
||||||
|
*/
|
||||||
|
t_msg chIQGetTimeout(Queue *qp, t_time time) {
|
||||||
|
BYTE8 b;
|
||||||
|
t_msg msg;
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
if ((msg = chSemWaitTimeoutS(&qp->q_sem, time)) < RDY_OK)
|
||||||
|
return msg;
|
||||||
|
b = *qp->q_rdptr++;
|
||||||
|
if (qp->q_rdptr >= qp->q_top)
|
||||||
|
qp->q_rdptr = qp->q_buffer;
|
||||||
|
|
||||||
|
if (qp->q_notify)
|
||||||
|
qp->q_notify();
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
#endif /* CH_USE_QUEUES_TIMEOUTS */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads some data from the input queue into the specified buffer. The function
|
||||||
|
* is non-blocking and can return zero if the queue is empty.
|
||||||
|
* @param qp pointer to a \p Queue structure
|
||||||
|
* @param buffer the data buffer
|
||||||
|
* @param n the maxium amount of data to be read
|
||||||
|
* @return the number of bytes read
|
||||||
|
* @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
|
||||||
|
* to use a semaphore for mutual exclusion.
|
||||||
|
*/
|
||||||
|
t_size chIQRead(Queue *qp, BYTE8 *buffer, t_size n) {
|
||||||
|
|
||||||
|
t_size r = 0;
|
||||||
|
while (n--) {
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
if (chIQIsEmpty(qp)) {
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
chSemFastWaitS(&qp->q_sem);
|
||||||
|
*buffer++ = *qp->q_rdptr++;
|
||||||
|
if (qp->q_rdptr >= qp->q_top)
|
||||||
|
qp->q_rdptr = qp->q_buffer;
|
||||||
|
|
||||||
|
// if (qp->q_notify)
|
||||||
|
// qp->q_notify();
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
r++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r && qp->q_notify) {
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
qp->q_notify();
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes an output queue. A Semaphore is internally initialized
|
||||||
|
* and works as a counter of the free bytes in the queue.
|
||||||
|
* @param qp pointer to a \p Queue structure
|
||||||
|
* @param buffer pointer to a memory area allocated as queue buffer
|
||||||
|
* @param size size of the queue buffer
|
||||||
|
* @param onotify pointer to a callback function that is invoked when
|
||||||
|
* some data is written in the Queue. The value can be \p NULL.
|
||||||
|
*/
|
||||||
|
void chOQInit(Queue *qp, BYTE8 *buffer, t_size size, t_qnotify onotify) {
|
||||||
|
|
||||||
|
qp->q_buffer = qp->q_rdptr = qp->q_wrptr = buffer;
|
||||||
|
qp->q_top = buffer + size;
|
||||||
|
chSemInit(&qp->q_sem, size);
|
||||||
|
qp->q_notify = onotify;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets an Output Queue. All the data is lost and the waiting threads
|
||||||
|
* resumed.
|
||||||
|
* @param qp pointer to a \p Queue structure
|
||||||
|
*/
|
||||||
|
void chOQReset(Queue *qp) {
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
qp->q_rdptr = qp->q_wrptr = qp->q_buffer;
|
||||||
|
chSemResetI(&qp->q_sem, (t_semcnt)(qp->q_top - qp->q_buffer));
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts a byte in the output queue, if the queue is full then the thread
|
||||||
|
* is suspended until the queue has free space available.
|
||||||
|
* @param qp pointer to a \p Queue structure
|
||||||
|
* @param b the byte value to be written
|
||||||
|
*/
|
||||||
|
void chOQPut(Queue *qp, BYTE8 b) {
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
chSemWaitS(&qp->q_sem);
|
||||||
|
*qp->q_wrptr++ = b;
|
||||||
|
if (qp->q_wrptr >= qp->q_top)
|
||||||
|
qp->q_wrptr = qp->q_buffer;
|
||||||
|
|
||||||
|
if (qp->q_notify)
|
||||||
|
qp->q_notify();
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a byte from an output queue.
|
||||||
|
* @param qp pointer to a \p Queue structure
|
||||||
|
* @return the byte value or \p Q_EMPTY if the queue is empty
|
||||||
|
* @note This function is the lower side endpoint of the output queue.
|
||||||
|
* @note This function must be called with interrupts disabled or from an
|
||||||
|
* interrupt handler.
|
||||||
|
*/
|
||||||
|
t_msg chOQGetI(Queue *qp) {
|
||||||
|
BYTE8 b;
|
||||||
|
|
||||||
|
if (chOQIsEmpty(qp))
|
||||||
|
return Q_EMPTY;
|
||||||
|
|
||||||
|
b = *qp->q_rdptr++;
|
||||||
|
if (qp->q_rdptr >= qp->q_top)
|
||||||
|
qp->q_rdptr = qp->q_buffer;
|
||||||
|
chSemSignalI(&qp->q_sem);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes some data from the specified buffer into the queue. The function
|
||||||
|
* is non-blocking and can return zero if the queue is full.
|
||||||
|
* @param qp pointer to a \p Queue structure
|
||||||
|
* @param buffer the data buffer
|
||||||
|
* @param n the maxium amount of data to be written
|
||||||
|
* @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
|
||||||
|
* to use a semaphore for mutual exclusion.
|
||||||
|
*/
|
||||||
|
t_size chOQWrite(Queue *qp, BYTE8 *buffer, t_size n) {
|
||||||
|
|
||||||
|
t_size w = 0;
|
||||||
|
while (n--) {
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
if (chOQIsFull(qp)) {
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
chSemFastWaitS(&qp->q_sem);
|
||||||
|
*qp->q_wrptr++ = *buffer++;
|
||||||
|
if (qp->q_wrptr >= qp->q_top)
|
||||||
|
qp->q_wrptr = qp->q_buffer;
|
||||||
|
|
||||||
|
// if (qp->q_notify)
|
||||||
|
// qp->q_notify();
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
w++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (w && qp->q_notify) {
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
qp->q_notify();
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
#endif /* CH_USE_QUEUES */
|
||||||
|
|
||||||
|
#ifdef CH_USE_QUEUES_HALFDUPLEX
|
||||||
|
/**
|
||||||
|
* Initializes an half duplex queue.
|
||||||
|
* @param qp pointer to the \p HalfDuplexQueue structure
|
||||||
|
* @param buffer pointer to a memory area allocated as buffer for the queue
|
||||||
|
* @param size the size of the queue buffer
|
||||||
|
* @param inotify pointer to a callback function that is invoked when
|
||||||
|
* some data is read from the queue. The value can be \p NULL.
|
||||||
|
* @param onotify pointer to a callback function that is invoked when
|
||||||
|
* some data is written to the queue. The value can be \p NULL.
|
||||||
|
*/
|
||||||
|
void chHDQInit(HalfDuplexQueue *qp, BYTE8 *buffer, t_size size,
|
||||||
|
t_qnotify inotify, t_qnotify onotify) {
|
||||||
|
|
||||||
|
qp->hdq_buffer = qp->hdq_rdptr = qp->hdq_wrptr = buffer;
|
||||||
|
qp->hdq_top = buffer + size;
|
||||||
|
chSemInit(&qp->hdq_isem, 0);
|
||||||
|
chSemInit(&qp->hdq_osem, size);
|
||||||
|
qp->hdq_inotify = inotify;
|
||||||
|
qp->hdq_onotify = onotify;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a byte from the receive queue, if the queue is empty or is in
|
||||||
|
* transmission mode then the invoking thread is suspended.
|
||||||
|
* @param qp pointer to a \p HalfDuplexQueue structure
|
||||||
|
* @return the byte value
|
||||||
|
*/
|
||||||
|
t_msg chHDQGetReceive(HalfDuplexQueue *qp) {
|
||||||
|
BYTE8 b;
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
chSemWaitS(&qp->hdq_isem);
|
||||||
|
if (currp->p_rdymsg < RDY_OK) {
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
return currp->p_rdymsg;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* NOTE: The semaphore can be signaled only if the queue is in
|
||||||
|
* receive mode.
|
||||||
|
*/
|
||||||
|
b = *qp->hdq_rdptr++;
|
||||||
|
if (qp->hdq_rdptr >= qp->hdq_top)
|
||||||
|
qp->hdq_rdptr = qp->hdq_buffer;
|
||||||
|
|
||||||
|
if (qp->hdq_inotify)
|
||||||
|
qp->hdq_inotify();
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CH_USE_QUEUES_TIMEOUT
|
||||||
|
/**
|
||||||
|
* Reads a byte from the receive queue, if the queue is empty or is in
|
||||||
|
* transmission mode then the invoking thread is suspended.
|
||||||
|
* @param qp pointer to a \p HalfDuplexQueue structure
|
||||||
|
* @param time the number of ticks before the operation timouts
|
||||||
|
* @return the byte value or \p Q_TIMEOUT if a timeout occurs
|
||||||
|
* @note The function is available only if the \p CH_USE_QUEUES_TIMEOUT
|
||||||
|
* option is enabled in \p chconf.h.
|
||||||
|
*/
|
||||||
|
t_msg chHDQGetReceiveTimeout(HalfDuplexQueue *qp, t_time time) {
|
||||||
|
BYTE8 b;
|
||||||
|
t_msg msg;
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
if ((msg = chSemWaitTimeoutS(&qp->hdq_isem, time)) < RDY_OK) {
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* NOTE: The semaphore can be signaled only if the queue is in
|
||||||
|
* receive mode.
|
||||||
|
*/
|
||||||
|
b = *qp->hdq_rdptr++;
|
||||||
|
if (qp->hdq_rdptr >= qp->hdq_top)
|
||||||
|
qp->hdq_rdptr = qp->hdq_buffer;
|
||||||
|
|
||||||
|
if (qp->hdq_inotify)
|
||||||
|
qp->hdq_inotify();
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a byte into the transmit queue. If the buffer contains unread
|
||||||
|
* input data then the the buffer is cleared and the queue goes in
|
||||||
|
* transmission mode.
|
||||||
|
* @param qp pointer to a \p HalfDuplexQueue structure
|
||||||
|
* @param b the byte value to be written
|
||||||
|
*/
|
||||||
|
void chHDQPutTransmit(HalfDuplexQueue *qp, BYTE8 b) {
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Transmission mode requires that all the unread data must be destroyed.
|
||||||
|
*/
|
||||||
|
if (qp->hdq_isem.s_cnt > 0) {
|
||||||
|
qp->hdq_isem.s_cnt = 0;
|
||||||
|
qp->hdq_rdptr = qp->hdq_wrptr = qp->hdq_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Goes in transmission mode.
|
||||||
|
*/
|
||||||
|
chSemWaitS(&qp->hdq_osem);
|
||||||
|
*qp->hdq_wrptr++ = b;
|
||||||
|
if (qp->hdq_wrptr >= qp->hdq_top)
|
||||||
|
qp->hdq_wrptr = qp->hdq_buffer;
|
||||||
|
|
||||||
|
if (qp->hdq_onotify)
|
||||||
|
qp->hdq_onotify();
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a byte from the transmit queue.
|
||||||
|
* @param qp pointer to a \p HalfDuplexQueue structure
|
||||||
|
* @return the byte value or \p Q_EMPTY if the transmit queue is empty (not in
|
||||||
|
* transmission mode)
|
||||||
|
* @note This function must be called with interrupts disabled or from an
|
||||||
|
* interrupt handler.
|
||||||
|
*/
|
||||||
|
t_msg chHDQGetTransmitI(HalfDuplexQueue *qp) {
|
||||||
|
BYTE8 b;
|
||||||
|
|
||||||
|
if (!chHDQIsTransmitting(qp))
|
||||||
|
return Q_EMPTY;
|
||||||
|
|
||||||
|
b = *qp->hdq_rdptr++;
|
||||||
|
if (qp->hdq_rdptr >= qp->hdq_top)
|
||||||
|
qp->hdq_rdptr = qp->hdq_buffer;
|
||||||
|
chSemSignalI(&qp->hdq_osem);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a byte into the receive queue. If the queue is in transmission mode
|
||||||
|
* then the byte is lost.
|
||||||
|
* @param qp pointer to a \p HalfDuplexQueue structure
|
||||||
|
* @param b the byte value to be written
|
||||||
|
* @return \p Q_OK if the operation is successful or \p Q_FULL if the driver
|
||||||
|
* is in transmit mode or the receive queue is full.
|
||||||
|
* @note This function must be called with interrupts disabled or from an
|
||||||
|
* interrupt handler.
|
||||||
|
*/
|
||||||
|
t_msg chHDQPutReceiveI(HalfDuplexQueue *qp, BYTE8 b) {
|
||||||
|
|
||||||
|
if (chHDQIsTransmitting(qp))
|
||||||
|
return Q_FULL;
|
||||||
|
|
||||||
|
if (chHDQIsFullReceive(qp))
|
||||||
|
return Q_FULL;
|
||||||
|
|
||||||
|
*qp->hdq_wrptr++ = b;
|
||||||
|
if (qp->hdq_wrptr >= qp->hdq_top)
|
||||||
|
qp->hdq_wrptr = qp->hdq_buffer;
|
||||||
|
chSemSignalI(&qp->hdq_isem);
|
||||||
|
return Q_OK;
|
||||||
|
}
|
||||||
|
#endif /* CH_USE_QUEUES_HALFDUPLEX */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -0,0 +1,205 @@
|
||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup Scheduler
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ch.h>
|
||||||
|
|
||||||
|
/** @cond never*/
|
||||||
|
|
||||||
|
static ReadyList rlist;
|
||||||
|
|
||||||
|
#ifndef CH_CURRP_REGISTER_CACHE
|
||||||
|
Thread *currp;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static UWORD16 preempt;
|
||||||
|
#ifdef CH_USE_SYSTEMTIME
|
||||||
|
t_time stime;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** @endcond */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scheduler initialization.
|
||||||
|
* @note Internally invoked by the \p chSysInit().
|
||||||
|
*/
|
||||||
|
void chSchInit(void) {
|
||||||
|
|
||||||
|
rlist.p_next = rlist.p_prev = (Thread *)&rlist;
|
||||||
|
rlist.p_prio = MAXPRIO;
|
||||||
|
preempt = CH_TIME_QUANTUM;
|
||||||
|
#ifdef CH_USE_SYSTEMTIME
|
||||||
|
stime = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts a thread in the Ready List.
|
||||||
|
* @param tp the Thread to be made ready
|
||||||
|
* @return the Thread pointer
|
||||||
|
* @note The function must be called in the system mutex zone.
|
||||||
|
* @note The function does not reschedule, the \p chSchRescheduleI() should
|
||||||
|
* be called soon after.
|
||||||
|
* @note The function is not meant to be used in the user code directly.
|
||||||
|
*/
|
||||||
|
Thread *chSchReadyI(Thread *tp) {
|
||||||
|
Thread *cp;
|
||||||
|
t_prio prio = tp->p_prio;
|
||||||
|
|
||||||
|
tp->p_state = PRREADY;
|
||||||
|
tp->p_rdymsg = RDY_OK;
|
||||||
|
cp = rlist.p_next;
|
||||||
|
while (cp->p_prio < prio)
|
||||||
|
cp = cp->p_next;
|
||||||
|
tp->p_prev = (tp->p_next = cp)->p_prev;
|
||||||
|
tp->p_prev->p_next = cp->p_prev = tp;
|
||||||
|
return tp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Switches to the next thread in the ready list, the ready list is assumed
|
||||||
|
* to contain at least a thread.
|
||||||
|
*/
|
||||||
|
static void nextready(void) {
|
||||||
|
Thread *otp = currp;
|
||||||
|
|
||||||
|
(currp = dequeue(rlist.p_prev))->p_state = PRCURR;
|
||||||
|
preempt = CH_TIME_QUANTUM;
|
||||||
|
chSysSwitchI(&otp->p_ctx, &currp->p_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Puts the current thread to sleep into the specified state, the next highest
|
||||||
|
* priority thread becomes running. The threads states are described into
|
||||||
|
* \p threads.h
|
||||||
|
* @param newstate the new thread state
|
||||||
|
* @return the wakeup message
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
|
void chSchGoSleepI(t_tstate newstate) {
|
||||||
|
|
||||||
|
currp->p_state = newstate;
|
||||||
|
nextready();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wakeups a thread, the thread is inserted into the ready list or made
|
||||||
|
* running directly depending on its relative priority compared to the current
|
||||||
|
* thread.
|
||||||
|
* @param tp the Thread to be made ready
|
||||||
|
* @param msg wakeup message to the awakened thread
|
||||||
|
* @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 It is equivalent to a \p chSchReadyI() followed by a
|
||||||
|
* \p chSchRescheduleI() but much more efficient.
|
||||||
|
*/
|
||||||
|
void chSchWakeupI(Thread *tp, t_msg msg) {
|
||||||
|
Thread *ctp = currp;
|
||||||
|
|
||||||
|
if (tp->p_prio <= ctp->p_prio)
|
||||||
|
chSchReadyI(tp)->p_rdymsg = msg;
|
||||||
|
else {
|
||||||
|
chSchReadyI(ctp);
|
||||||
|
(currp = tp)->p_state = PRCURR;
|
||||||
|
tp->p_rdymsg = msg;
|
||||||
|
preempt = CH_TIME_QUANTUM;
|
||||||
|
chSysSwitchI(&ctp->p_ctx, &tp->p_ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If a thread with an higher priority than the current thread is in the
|
||||||
|
* ready list then it becomes running.
|
||||||
|
* @note The function must be called in the system mutex zone.
|
||||||
|
*/
|
||||||
|
void chSchRescheduleI(void) {
|
||||||
|
|
||||||
|
if (isempty(&rlist) || lastprio(&rlist) <= currp->p_prio)
|
||||||
|
return;
|
||||||
|
|
||||||
|
chSchDoRescheduleI();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a reschedulation. It is meant to be called if
|
||||||
|
* \p chSchRescRequired() evaluates to \p TRUE.
|
||||||
|
*/
|
||||||
|
void chSchDoRescheduleI(void) {
|
||||||
|
|
||||||
|
chSchReadyI(currp);
|
||||||
|
nextready();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates if a reschedulation is required.
|
||||||
|
* @return \p TRUE if there is a thread that should go in running state
|
||||||
|
* immediatly else \p FALSE.
|
||||||
|
*/
|
||||||
|
BOOL chSchRescRequiredI(void) {
|
||||||
|
|
||||||
|
if (isempty(&rlist))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (preempt) {
|
||||||
|
if (lastprio(&rlist) <= currp->p_prio)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else { /* Time quantum elapsed. */
|
||||||
|
if (lastprio(&rlist) < currp->p_prio)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Preemption routine, this function must be called into an interrupt
|
||||||
|
* handler invoked by a system timer.
|
||||||
|
* The frequency of the timer determines the system tick granularity and,
|
||||||
|
* together with the \p CH_TIME_QUANTUM macro, the round robin interval.
|
||||||
|
*/
|
||||||
|
void chSchTimerHandlerI(void) {
|
||||||
|
|
||||||
|
if (preempt)
|
||||||
|
preempt--;
|
||||||
|
|
||||||
|
#ifdef CH_USE_SYSTEMTIME
|
||||||
|
stime++;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CH_USE_VIRTUAL_TIMERS
|
||||||
|
if (&dlist != (DeltaList *)dlist.dl_next) {
|
||||||
|
VirtualTimer *vtp;
|
||||||
|
|
||||||
|
--dlist.dl_next->vt_dtime;
|
||||||
|
while (!(vtp = dlist.dl_next)->vt_dtime) {
|
||||||
|
vtp->vt_prev->vt_next = vtp->vt_next;
|
||||||
|
vtp->vt_next->vt_prev = vtp->vt_prev;
|
||||||
|
vtp->vt_func(vtp->vt_par);
|
||||||
|
vtp->vt_func = 0; // Required, flags the timer as triggered.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -0,0 +1,376 @@
|
||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup Semaphores
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ch.h>
|
||||||
|
|
||||||
|
#ifdef CH_USE_SEMAPHORES
|
||||||
|
/**
|
||||||
|
* Initializes a semaphore with the specified counter value.
|
||||||
|
* @param sp pointer to a \p Semaphore structure
|
||||||
|
* @param n initial value of the semaphore counter. Must be non-negative.
|
||||||
|
* @note Can be called with interrupts disabled or enabled.
|
||||||
|
*/
|
||||||
|
void chSemInit(Semaphore *sp, t_semcnt n) {
|
||||||
|
|
||||||
|
sp->s_cnt = n;
|
||||||
|
sp->s_queue.p_next = sp->s_queue.p_prev = (Thread *)&sp->s_queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a reset operation on the semaphore.
|
||||||
|
* @param sp pointer to a \p Semaphore structure
|
||||||
|
* @param n the new value of the semaphore counter. Must be non-negative.
|
||||||
|
* @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
|
||||||
|
* \p RDY_RESET.
|
||||||
|
*/
|
||||||
|
void chSemReset(Semaphore *sp, t_semcnt n) {
|
||||||
|
t_semcnt cnt;
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
cnt = sp->s_cnt;
|
||||||
|
sp->s_cnt = n;
|
||||||
|
if (cnt < 0) {
|
||||||
|
while (cnt++)
|
||||||
|
chSchReadyI(dequeue(sp->s_queue.p_next))->p_rdymsg = RDY_RESET;
|
||||||
|
chSchRescheduleI();
|
||||||
|
}
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a reset operation on the semaphore.
|
||||||
|
* @param sp pointer to a \p Semaphore structure
|
||||||
|
* @param n the new value of the semaphore counter. Must be non-negative.
|
||||||
|
* @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
|
||||||
|
* \p RDY_RESET.
|
||||||
|
* @note This function must be called with interrupts disabled.
|
||||||
|
*/
|
||||||
|
void chSemResetI(Semaphore *sp, t_semcnt n) {
|
||||||
|
t_semcnt cnt;
|
||||||
|
|
||||||
|
cnt = sp->s_cnt;
|
||||||
|
sp->s_cnt = n;
|
||||||
|
while (cnt++ < 0)
|
||||||
|
chSchReadyI(dequeue(sp->s_queue.p_next))->p_rdymsg = RDY_RESET;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a wait operation on a semaphore.
|
||||||
|
* @param sp pointer to a \p Semaphore structure
|
||||||
|
*/
|
||||||
|
void chSemWait(Semaphore *sp) {
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
if (--sp->s_cnt < 0) {
|
||||||
|
enqueue(currp, &sp->s_queue);
|
||||||
|
chSchGoSleepI(PRWTSEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a wait operation on a semaphore.
|
||||||
|
* @param sp pointer to a \p Semaphore structure
|
||||||
|
* @note This function must be called with interrupts disabled.
|
||||||
|
* @note This function cannot be called by an interrupt handler.
|
||||||
|
*/
|
||||||
|
void chSemWaitS(Semaphore *sp) {
|
||||||
|
|
||||||
|
if (--sp->s_cnt < 0) {
|
||||||
|
enqueue(currp, &sp->s_queue);
|
||||||
|
chSchGoSleepI(PRWTSEM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CH_USE_SEMAPHORES_TIMEOUT
|
||||||
|
static void unwait(void *p) {
|
||||||
|
|
||||||
|
// Test removed, it should never happen.
|
||||||
|
// if (((Thread *)p)->p_state == PRWTSEM)
|
||||||
|
chSchReadyI(dequeue(p))->p_rdymsg = RDY_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a wait operation on a semaphore with timeout specification.
|
||||||
|
* @param sp pointer to a \p Semaphore structure
|
||||||
|
* @param time the number of ticks before the operation fails
|
||||||
|
* @return the function can return \p RDY_OK. \p RDY_TIMEOUT or \p RDY_RESET.
|
||||||
|
*/
|
||||||
|
t_msg chSemWaitTimeout(Semaphore *sp, t_time time) {
|
||||||
|
t_msg msg;
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
if (--sp->s_cnt < 0) {
|
||||||
|
VirtualTimer vt;
|
||||||
|
|
||||||
|
chVTSetI(&vt, time, unwait, currp);
|
||||||
|
enqueue(currp, &sp->s_queue);
|
||||||
|
chSchGoSleepI(PRWTSEM);
|
||||||
|
msg = currp->p_rdymsg; // Note, got value *before* invoking CH_LEAVE_SYSTEM().
|
||||||
|
if (!vt.vt_func) {
|
||||||
|
sp->s_cnt++;
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
chVTResetI(&vt);
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
return RDY_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a wait operation on a semaphore with timeout specification.
|
||||||
|
* @param sp pointer to a \p Semaphore structure
|
||||||
|
* @param time the number of ticks before the operation fails
|
||||||
|
* @return the function can return \p RDY_OK. \p RDY_TIMEOUT or \p RDY_RESET.
|
||||||
|
* @note This function must be called with interrupts disabled.
|
||||||
|
* @note This function cannot be called by an interrupt handler.
|
||||||
|
* @note The function is available only if the \p CH_USE_SEMAPHORES_TIMEOUT
|
||||||
|
* option is enabled in \p chconf.h.
|
||||||
|
*/
|
||||||
|
t_msg chSemWaitTimeoutS(Semaphore *sp, t_time time) {
|
||||||
|
|
||||||
|
if (--sp->s_cnt < 0) {
|
||||||
|
VirtualTimer vt;
|
||||||
|
|
||||||
|
chVTSetI(&vt, time, unwait, currp);
|
||||||
|
enqueue(currp, &sp->s_queue);
|
||||||
|
chSchGoSleepI(PRWTSEM);
|
||||||
|
if (!vt.vt_func) {
|
||||||
|
sp->s_cnt++;
|
||||||
|
return currp->p_rdymsg;
|
||||||
|
}
|
||||||
|
chVTResetI(&vt);
|
||||||
|
return currp->p_rdymsg;
|
||||||
|
}
|
||||||
|
return RDY_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CH_USE_SEMAPHORES_TIMEOUT */
|
||||||
|
/**
|
||||||
|
* Performs a signal operation on a semaphore.
|
||||||
|
* @param sp pointer to a \p Semaphore structure
|
||||||
|
* @note The function is available only if the \p CH_USE_SEMAPHORES
|
||||||
|
* option is enabled in \p chconf.h.
|
||||||
|
*/
|
||||||
|
void chSemSignal(Semaphore *sp) {
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
if (sp->s_cnt++ < 0)
|
||||||
|
chSchWakeupI(dequeue(sp->s_queue.p_next), RDY_OK);
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a signal operation on a semaphore.
|
||||||
|
* @param sp pointer to a \p Semaphore structure
|
||||||
|
* @note This function must be called with interrupts disabled.
|
||||||
|
* @note The function is available only if the \p CH_USE_SEMAPHORES
|
||||||
|
* option is enabled in \p chconf.h.
|
||||||
|
*/
|
||||||
|
void chSemSignalI(Semaphore *sp) {
|
||||||
|
|
||||||
|
if (sp->s_cnt++ < 0)
|
||||||
|
chSchReadyI(dequeue(sp->s_queue.p_next));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs atomic signal and wait operations on two semaphores.
|
||||||
|
* @param sps pointer to a \p Semaphore structure to be signaled
|
||||||
|
* @param spw pointer to a \p Semaphore structure to be wait on
|
||||||
|
* @note The function is available only if the \p CH_USE_SEMAPHORES
|
||||||
|
* option is enabled in \p chconf.h.
|
||||||
|
*/
|
||||||
|
void chSemSignalWait(Semaphore *sps, Semaphore *spw) {
|
||||||
|
BOOL flag;
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
if (sps->s_cnt++ < 0)
|
||||||
|
chSchReadyI(dequeue(sps->s_queue.p_next)), flag = TRUE;
|
||||||
|
else
|
||||||
|
flag = FALSE;
|
||||||
|
|
||||||
|
if (--spw->s_cnt < 0) {
|
||||||
|
enqueue(currp, &spw->s_queue);
|
||||||
|
chSchGoSleepI(PRWTSEM);
|
||||||
|
}
|
||||||
|
else if (flag)
|
||||||
|
chSchRescheduleI();
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CH_USE_RT_SEMAPHORES
|
||||||
|
/*
|
||||||
|
* Inserts a thread into a list ordering it by priority.
|
||||||
|
* @param tp the pointer to the thread to be inserted in the list
|
||||||
|
* @param tqp the pointer to the threads list header
|
||||||
|
* @note Usually you dont need to use this function in the user code unless
|
||||||
|
* you want to create some custom threads synchronization mechanism.
|
||||||
|
*/
|
||||||
|
static void prioenq(Thread *tp, ThreadsQueue *tqp) {
|
||||||
|
Thread *p;
|
||||||
|
|
||||||
|
p = tqp->p_next;
|
||||||
|
while ((p != (Thread *)tqp) && (p->p_prio >= tp->p_prio))
|
||||||
|
p = p->p_next;
|
||||||
|
tp->p_next = p;
|
||||||
|
tp->p_prev = tqp->p_prev;
|
||||||
|
p->p_prev->p_next = tp;
|
||||||
|
p->p_prev = tp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a wait operation on a semaphore with priority boost.
|
||||||
|
* @param sp pointer to a \p Semaphore structure
|
||||||
|
* @note The function is available only if the \p CH_USE_RT_SEMAPHORES
|
||||||
|
* option is enabled in \p chconf.h.
|
||||||
|
*/
|
||||||
|
void chSemRaisePrioWait(Semaphore *sp) {
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
if (--sp->s_cnt < 0) {
|
||||||
|
prioenq(currp, &sp->s_queue);
|
||||||
|
chSchGoSleepI(PRWTSEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!currp->p_rtcnt++)
|
||||||
|
currp->p_prio += MEPRIO;
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a signal operation on a semaphore with return to normal priority.
|
||||||
|
* @param sp pointer to a \p Semaphore structure
|
||||||
|
* @note The function is available only if the \p CH_USE_RT_SEMAPHORES
|
||||||
|
* option is enabled in \p chconf.h.
|
||||||
|
*/
|
||||||
|
void chSemLowerPrioSignal(Semaphore *sp) {
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
if (!--currp->p_rtcnt) {
|
||||||
|
currp->p_prio = currp->p_bakprio;
|
||||||
|
if (sp->s_cnt++ < 0)
|
||||||
|
chSchReadyI(dequeue(sp->s_queue.p_next));
|
||||||
|
chSchRescheduleI();
|
||||||
|
}
|
||||||
|
else if (sp->s_cnt++ < 0)
|
||||||
|
chSchWakeupI(dequeue(sp->s_queue.p_next), RDY_OK);
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs atomic signal and wait operations on two semaphores with priority
|
||||||
|
* boost.
|
||||||
|
* @param sps pointer to a \p Semaphore structure to be signaled
|
||||||
|
* @param spw pointer to a \p Semaphore structure to be wait on
|
||||||
|
* @note The function is available only if the \p CH_USE_RT_SEMAPHORES
|
||||||
|
* option is enabled in \p chconf.h.
|
||||||
|
*/
|
||||||
|
void chSemRaisePrioSignalWait(Semaphore *sps, Semaphore *spw) {
|
||||||
|
BOOL flag;
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
if (sps->s_cnt++ < 0)
|
||||||
|
chSchReadyI(dequeue(sps->s_queue.p_next)), flag = TRUE;
|
||||||
|
else
|
||||||
|
flag = FALSE;
|
||||||
|
|
||||||
|
if (--spw->s_cnt < 0) {
|
||||||
|
prioenq(currp, &spw->s_queue);
|
||||||
|
chSchGoSleepI(PRWTSEM);
|
||||||
|
|
||||||
|
if (!currp->p_rtcnt++)
|
||||||
|
currp->p_prio += MEPRIO;
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!currp->p_rtcnt++) {
|
||||||
|
currp->p_bakprio = currp->p_prio;
|
||||||
|
currp->p_prio += MEPRIO;
|
||||||
|
flag = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( flag)
|
||||||
|
chSchRescheduleI();
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs atomic signal and wait operations on two semaphores with return
|
||||||
|
* to normal priority.
|
||||||
|
* @param sps pointer to a \p Semaphore structure to be signaled
|
||||||
|
* @param spw pointer to a \p Semaphore structure to be wait on
|
||||||
|
* @note The function is available only if the \p CH_USE_RT_SEMAPHORES
|
||||||
|
* option is enabled in \p chconf.h.
|
||||||
|
*/
|
||||||
|
void chSemLowerPrioSignalWait(Semaphore *sps, Semaphore *spw) {
|
||||||
|
BOOL flag = FALSE;
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
if (!--currp->p_rtcnt)
|
||||||
|
currp->p_prio = currp->p_bakprio, flag = TRUE;
|
||||||
|
|
||||||
|
if (sps->s_cnt++ < 0)
|
||||||
|
chSchReadyI(dequeue(sps->s_queue.p_next)), flag = TRUE;
|
||||||
|
|
||||||
|
if (--spw->s_cnt < 0) {
|
||||||
|
enqueue(currp, &spw->s_queue); // enqueue() because the spw is a normal sem.
|
||||||
|
chSchGoSleepI(PRWTSEM);
|
||||||
|
}
|
||||||
|
else if (flag)
|
||||||
|
chSchRescheduleI();
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CH_USE_RT_SEMAPHORES */
|
||||||
|
|
||||||
|
#endif /* CH_USE_SEMAPHORES */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -0,0 +1,195 @@
|
||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup Serial
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ch.h>
|
||||||
|
|
||||||
|
#ifdef CH_USE_SERIAL_FULLDUPLEX
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a generic full duplex driver. The HW dependent part of the
|
||||||
|
* initialization has to be performed outside, usually in the hardware
|
||||||
|
* initialization code.
|
||||||
|
* @param sd pointer to a \p FullDuplexDriver structure
|
||||||
|
* @param ib pointer to a memory area allocated for the Input Queue buffer
|
||||||
|
* @param isize size of the Input Queue buffer
|
||||||
|
* @param inotify pointer to a callback function that is invoked when
|
||||||
|
* some data is read from the Queue. The value can be \p NULL.
|
||||||
|
* @param ob pointer to a memory area allocated for the Output Queue buffer
|
||||||
|
* @param osize size of the Output Queue buffer
|
||||||
|
* @param onotify pointer to a callback function that is invoked when
|
||||||
|
* some data is written in the Queue. The value can be \p NULL.
|
||||||
|
*/
|
||||||
|
void chFDDInit(FullDuplexDriver *sd,
|
||||||
|
BYTE8 *ib, t_size isize, t_qnotify inotify,
|
||||||
|
BYTE8 *ob, t_size osize, t_qnotify onotify) {
|
||||||
|
|
||||||
|
chIQInit(&sd->sd_iqueue, ib, isize, inotify);
|
||||||
|
chEvtInit(&sd->sd_ievent);
|
||||||
|
chOQInit(&sd->sd_oqueue, ob, osize, onotify);
|
||||||
|
chEvtInit(&sd->sd_oevent);
|
||||||
|
chEvtInit(&sd->sd_sevent);
|
||||||
|
sd->sd_flags = SD_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function must be called from the input interrupt service routine in
|
||||||
|
* order to enqueue incoming data and generate the related events.
|
||||||
|
* @param sd pointer to a \p FullDuplexDriver structure
|
||||||
|
* @param b the byte to be written in the driver's Input Queue
|
||||||
|
*/
|
||||||
|
void chFDDIncomingDataI(FullDuplexDriver *sd, BYTE8 b) {
|
||||||
|
|
||||||
|
if (chIQPutI(&sd->sd_iqueue, b) < Q_OK)
|
||||||
|
chFDDAddFlagsI(sd, SD_OVERRUN_ERROR);
|
||||||
|
else
|
||||||
|
chEvtSendI(&sd->sd_ievent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Must be called from the output interrupt service routine in order to get
|
||||||
|
* the next byte to be transmitted.
|
||||||
|
*
|
||||||
|
* @param sd pointer to a \p FullDuplexDriver structure
|
||||||
|
* @return the byte read from the driver's Output Queue or \p Q_EMPTY if the
|
||||||
|
* queue is empty (the lower driver usually disables the interrupt
|
||||||
|
* source when this happens).
|
||||||
|
*/
|
||||||
|
t_msg chFDDRequestDataI(FullDuplexDriver *sd) {
|
||||||
|
|
||||||
|
t_msg b = chOQGetI(&sd->sd_oqueue);
|
||||||
|
if (b < Q_OK)
|
||||||
|
chEvtSendI(&sd->sd_oevent);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Must be called from the I/O interrupt service routine in order to
|
||||||
|
* notify I/O conditions as errors, signals change etc.
|
||||||
|
* @param sd pointer to a \p FullDuplexDriver structure
|
||||||
|
* @param mask condition flags to be added to the mask
|
||||||
|
*/
|
||||||
|
void chFDDAddFlagsI(FullDuplexDriver *sd, t_dflags mask) {
|
||||||
|
|
||||||
|
sd->sd_flags |= mask;
|
||||||
|
chEvtSendI(&sd->sd_sevent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function returns and clears the errors mask associated to the driver.
|
||||||
|
* @param sd pointer to a \p FullDuplexDriver structure
|
||||||
|
* @return the condition flags modified since last time this function was
|
||||||
|
* invoked
|
||||||
|
*/
|
||||||
|
t_dflags chFDDGetAndClearFlags(FullDuplexDriver *sd) {
|
||||||
|
t_dflags mask;
|
||||||
|
|
||||||
|
mask = sd->sd_flags;
|
||||||
|
sd->sd_flags = SD_NO_ERROR;
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CH_USE_SERIAL_FULLDUPLEX */
|
||||||
|
|
||||||
|
#ifdef CH_USE_SERIAL_HALFDUPLEX
|
||||||
|
/**
|
||||||
|
* Initializes a generic half duplex driver. The HW dependent part of the
|
||||||
|
* initialization has to be performed outside, usually in the hardware
|
||||||
|
* initialization code.
|
||||||
|
* @param sd pointer to a \p HalfDuplexDriver structure
|
||||||
|
* @param b pointer to a memory area allocated for the queue buffer
|
||||||
|
* @param size the buffer size
|
||||||
|
* @param inotify pointer to a callback function that is invoked when
|
||||||
|
* some data is read from the queue. The value can be \p NULL.
|
||||||
|
* @param onotify pointer to a callback function that is invoked when
|
||||||
|
* some data is written in the queue. The value can be \p NULL.
|
||||||
|
*/
|
||||||
|
void chHDDInit(HalfDuplexDriver *sd, BYTE8 *b, t_size size,
|
||||||
|
t_qnotify inotify, t_qnotify onotify) {
|
||||||
|
|
||||||
|
chHDQInit(&sd->sd_queue, b, size, inotify, onotify);
|
||||||
|
chEvtInit(&sd->sd_ievent);
|
||||||
|
chEvtInit(&sd->sd_oevent);
|
||||||
|
chEvtInit(&sd->sd_sevent);
|
||||||
|
sd->sd_flags = SD_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function must be called from the input interrupt service routine in
|
||||||
|
* order to enqueue incoming data and generate the related events.
|
||||||
|
* @param sd pointer to a \p FullDuplexDriver structure
|
||||||
|
* @param b the byte to be written in the driver's Input Queue
|
||||||
|
*/
|
||||||
|
void chHDDIncomingDataI(HalfDuplexDriver *sd, BYTE8 b) {
|
||||||
|
|
||||||
|
if (chHDQPutReceiveI(&sd->sd_queue, b) < Q_OK)
|
||||||
|
chHDDAddFlagsI(sd, SD_OVERRUN_ERROR);
|
||||||
|
else
|
||||||
|
chEvtSendI(&sd->sd_ievent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Must be called from the output interrupt service routine in order to get
|
||||||
|
* the next byte to be transmitted.
|
||||||
|
*
|
||||||
|
* @param sd pointer to a \p HalfDuplexDriver structure
|
||||||
|
* @return the byte read from the driver's Output Queue or \p Q_EMPTY if the
|
||||||
|
* queue is empty (the lower driver usually disables the interrupt
|
||||||
|
* source when this happens).
|
||||||
|
*/
|
||||||
|
t_msg chHDDRequestDataI(HalfDuplexDriver *sd) {
|
||||||
|
|
||||||
|
t_msg b = chHDQGetTransmitI(&sd->sd_queue);
|
||||||
|
if (b < Q_OK)
|
||||||
|
chEvtSendI(&sd->sd_oevent);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Must be called from the I/O interrupt service routine in order to
|
||||||
|
* notify I/O conditions as errors, signals change etc.
|
||||||
|
* @param sd pointer to a \p HalfDuplexDriver structure
|
||||||
|
* @param mask condition flags to be added to the mask
|
||||||
|
*/
|
||||||
|
void chHDDAddFlagsI(HalfDuplexDriver *sd, t_dflags mask) {
|
||||||
|
|
||||||
|
sd->sd_flags |= mask;
|
||||||
|
chEvtSendI(&sd->sd_sevent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function returns and clears the errors mask associated to the driver.
|
||||||
|
* @param sd pointer to a \p HalfDuplexDriver structure
|
||||||
|
* @return the condition flags modified since last time this function was
|
||||||
|
* invoked
|
||||||
|
*/
|
||||||
|
t_dflags chHDDGetAndClearFlags(HalfDuplexDriver *sd) {
|
||||||
|
t_dflags mask;
|
||||||
|
|
||||||
|
mask = sd->sd_flags;
|
||||||
|
sd->sd_flags = SD_NO_ERROR;
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
#endif /* CH_USE_SERIAL_HALFDUPLEX */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup Time
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ch.h>
|
||||||
|
|
||||||
|
#ifdef CH_USE_SLEEP
|
||||||
|
/**
|
||||||
|
* Suspends the invoking thread for the specified time.
|
||||||
|
* @param time the system ticks number
|
||||||
|
*/
|
||||||
|
void chThdSleep(t_time time) {
|
||||||
|
VirtualTimer vt;
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
chVTSetI(&vt, time, (t_vtfunc)chSchReadyI, currp);
|
||||||
|
chSchGoSleepI(PRSLEEP);
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CH_USE_SYSTEMTIME
|
||||||
|
/**
|
||||||
|
* Returns the number of system ticks since the \p chSysInit() invocation.
|
||||||
|
* @return the system ticks number
|
||||||
|
* @note The counter can reach its maximum and return to zero.
|
||||||
|
* @note This function is designed to work with the \p chThdSleepUntil().
|
||||||
|
* @note The function is available only if the \p CH_USE_SYSTEMTIME
|
||||||
|
* option is enabled in \p chconf.h.
|
||||||
|
*/
|
||||||
|
t_time chSysGetTime(void) {
|
||||||
|
|
||||||
|
return stime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Suspends the invoking thread until the system time arrives to the specified
|
||||||
|
* value.
|
||||||
|
* @param time the system time
|
||||||
|
* @note The function is available only if the \p CH_USE_SYSTEMTIME
|
||||||
|
* option is enabled in \p chconf.h.
|
||||||
|
*/
|
||||||
|
void chThdSleepUntil(t_time time) {
|
||||||
|
VirtualTimer t;
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
chVTSetI(&t, (t_time)(time - stime), (t_vtfunc)chSchReadyI, currp);
|
||||||
|
chSchGoSleepI(PRSLEEP);
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
#endif /* CH_USE_SYSTEMTIME */
|
||||||
|
|
||||||
|
#endif /* CH_USE_SLEEP */
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
|
@ -0,0 +1,265 @@
|
||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup Threads
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ch.h>
|
||||||
|
|
||||||
|
#ifndef CH_OPTIMIZE_SPEED
|
||||||
|
/*
|
||||||
|
* Removes a Thread from a list and returns it.
|
||||||
|
* @param tp the pointer to the thread to be removed from the list
|
||||||
|
* @return the removed thread pointer
|
||||||
|
*/
|
||||||
|
Thread *dequeue(Thread *tp) {
|
||||||
|
|
||||||
|
tp->p_prev->p_next = tp->p_next;
|
||||||
|
tp->p_next->p_prev = tp->p_prev;
|
||||||
|
return tp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Inserts a thread into a bi-directional list in FIFO order.
|
||||||
|
* @param tp the pointer to the thread to be inserted in the list
|
||||||
|
* @param tqp the pointer to the threads list header
|
||||||
|
*/
|
||||||
|
void enqueue(Thread *tp, ThreadsQueue *tqp) {
|
||||||
|
|
||||||
|
tp->p_next = (Thread *)tqp;
|
||||||
|
tp->p_prev = tqp->p_prev;
|
||||||
|
tqp->p_prev->p_next = tp;
|
||||||
|
tqp->p_prev = tp;
|
||||||
|
}
|
||||||
|
#endif /* CH_OPTIMIZE_SPEED */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initializes a thread structure.
|
||||||
|
*/
|
||||||
|
void _InitThread(t_prio prio, t_tmode mode, Thread *tp) {
|
||||||
|
|
||||||
|
tp->p_flags = mode;
|
||||||
|
tp->p_prio = prio;
|
||||||
|
tp->p_rdymsg = RDY_OK;
|
||||||
|
#ifdef CH_USE_RT_SEMAPHORES
|
||||||
|
tp->p_rtcnt = 0;
|
||||||
|
tp->p_bakprio = prio;
|
||||||
|
#endif
|
||||||
|
#ifdef CH_USE_WAITEXIT
|
||||||
|
tp->p_waiting.p_next = (Thread *)&tp->p_waiting;
|
||||||
|
tp->p_waiting.p_prev = (Thread *)&tp->p_waiting;
|
||||||
|
#endif
|
||||||
|
#ifdef CH_USE_MESSAGES
|
||||||
|
tp->p_msgqueue.p_next = (Thread *)&tp->p_msgqueue;
|
||||||
|
tp->p_msgqueue.p_prev = (Thread *)&tp->p_msgqueue;
|
||||||
|
#endif
|
||||||
|
#ifdef CH_USE_EVENTS
|
||||||
|
tp->p_epending = 0;
|
||||||
|
#endif
|
||||||
|
#ifdef CH_USE_EXIT_EVENT
|
||||||
|
chEvtInit(&tp->p_exitesource);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new thread.
|
||||||
|
* @param prio the priority level for the new thread. Usually the threads are
|
||||||
|
* created with priority \p NORMALPRIO (128), priorities
|
||||||
|
* can range from \p LOWPRIO (1) to \p HIGHPRIO
|
||||||
|
* (255).
|
||||||
|
* @param mode the creation option flags for the thread. The following options
|
||||||
|
* can be OR'ed in this parameter:<br>
|
||||||
|
* <ul>
|
||||||
|
* <li>\p P_SUSPENDED, the thread is created in the
|
||||||
|
* \p PRSUSPENDED state and a subsequent call to
|
||||||
|
* \p chThdResume() will make it ready for
|
||||||
|
* execution.</li>
|
||||||
|
* <li>\p P_TERMINATED, this flag is usually set
|
||||||
|
* by the \p chThdTerminate() function and it is not
|
||||||
|
* normally used as parameter for this function. The
|
||||||
|
* result would be to create a thread with a termination
|
||||||
|
* request already pending.</li>
|
||||||
|
* </ul>
|
||||||
|
* @param workspace pointer to a working area dedicated to the thread stack
|
||||||
|
* @param wsize size of the working area.
|
||||||
|
* @param pf the thread function. Returning from this function automatically
|
||||||
|
* terminates the thread.
|
||||||
|
* @param arg an argument passed to the thread function. It can be \p NULL.
|
||||||
|
* @return the pointer to the \p Thread structure allocated for the
|
||||||
|
* thread into the working space area.
|
||||||
|
* @note A thread can terminate by calling \p chThdExit() or by simply
|
||||||
|
* returning from its main function.
|
||||||
|
*/
|
||||||
|
Thread *chThdCreate(t_prio prio, t_tmode mode, void *workspace,
|
||||||
|
t_size wsize, t_tfunc pf, void *arg) {
|
||||||
|
Thread *tp = workspace;
|
||||||
|
|
||||||
|
_InitThread(prio, mode, tp);
|
||||||
|
SETUP_CONTEXT(workspace, wsize, pf, arg);
|
||||||
|
#ifdef CH_USE_RESUME
|
||||||
|
if (tp->p_flags & P_SUSPENDED)
|
||||||
|
tp->p_state = PRSUSPENDED;
|
||||||
|
else {
|
||||||
|
#endif
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
chSchWakeupI(tp, RDY_OK);
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
#ifdef CH_USE_RESUME
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return tp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies if the specified thread is in the \p PREXIT state.
|
||||||
|
* @param tp the pointer to the thread
|
||||||
|
* @return \p TRUE if the thread is ended else \p FALSE. \p TRUE ensures that
|
||||||
|
* a subsequent call to \p chThdWait() would not block.
|
||||||
|
*/
|
||||||
|
BOOL chThdTerminated(Thread *tp) {
|
||||||
|
|
||||||
|
return tp->p_state == PREXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CH_USE_RESUME
|
||||||
|
/**
|
||||||
|
* Resumes a thread created with the \p P_SUSPENDED option.
|
||||||
|
* @param tp the pointer to the thread
|
||||||
|
* @note The function has no effect on threads in any other state than
|
||||||
|
* \p PRSUSPENDED.
|
||||||
|
* @note The function is available only if the \p CH_USE_RESUME
|
||||||
|
* option is enabled in \p chconf.h.
|
||||||
|
*/
|
||||||
|
void chThdResume(Thread *tp) {
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
if (tp->p_state == PRSUSPENDED)
|
||||||
|
chSchWakeupI(tp, RDY_OK);
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CH_USE_TERMINATE
|
||||||
|
/**
|
||||||
|
* Requests a thread termination.
|
||||||
|
* @param tp the pointer to the thread
|
||||||
|
* @note The thread is not termitated but a termination request is added to
|
||||||
|
* its \p p_flags field. The thread can read this status by
|
||||||
|
* invoking \p chThdShouldTerminate() and then terminate cleanly.
|
||||||
|
*/
|
||||||
|
void chThdTerminate(Thread *tp) {
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
tp->p_flags |= P_TERMINATE;
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies if the current thread has a termination request pending.
|
||||||
|
* @return \p TRUE if the termination was requested. The thread should terminate
|
||||||
|
* as soon it is ready to do so.
|
||||||
|
*/
|
||||||
|
BOOL chThdShouldTerminate(void) {
|
||||||
|
|
||||||
|
return currp->p_flags & P_TERMINATE ? TRUE : FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Terminates the current thread by specifying an exit status code.
|
||||||
|
* @param msg the thread exit code. The code can be retrieved by using
|
||||||
|
* \p chThdWait().
|
||||||
|
*/
|
||||||
|
void chThdExit(t_msg msg) {
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
currp->p_exitcode = msg; /* Post mortem info. */
|
||||||
|
#ifdef CH_USE_WAITEXIT
|
||||||
|
while (notempty(&currp->p_waiting))
|
||||||
|
chSchReadyI(dequeue(currp->p_waiting.p_next));
|
||||||
|
#endif
|
||||||
|
#ifdef CH_USE_EXIT_EVENT
|
||||||
|
chEvtSendI(&currp->p_exitesource);
|
||||||
|
#endif
|
||||||
|
chSchGoSleepI(PREXIT);
|
||||||
|
|
||||||
|
chSysUnlock(); /* Never executed. */
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CH_USE_WAITEXIT
|
||||||
|
/**
|
||||||
|
* Blocks the execution of the invoking thread until the specified thread
|
||||||
|
* terminates then the exit code is returned.
|
||||||
|
* @param tp the pointer to the thread
|
||||||
|
* @return the exit code
|
||||||
|
* @note The function is available only if the \p CH_USE_WAITEXIT
|
||||||
|
* option is enabled in \p chconf.h.
|
||||||
|
*/
|
||||||
|
t_msg chThdWait(Thread *tp) {
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
if (tp->p_state != PREXIT) {
|
||||||
|
enqueue(currp, &tp->p_waiting);
|
||||||
|
chSchGoSleepI(PRWAIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
return tp->p_exitcode;
|
||||||
|
}
|
||||||
|
#endif /* CH_USE_WAITEXIT */
|
||||||
|
|
||||||
|
#ifdef CH_USE_EXIT_EVENT
|
||||||
|
/**
|
||||||
|
* Returns the exit event source for the specified thread. The source is
|
||||||
|
* signaled when the thread terminates.
|
||||||
|
* @param tp the pointer to the thread
|
||||||
|
* @note When registering on a thread termination make sure the thread
|
||||||
|
* is still alive, if you do that after the thread termination
|
||||||
|
* then you would miss the event. There are two ways to ensure
|
||||||
|
* this:<br>
|
||||||
|
* <ul>
|
||||||
|
* <li>Create the thread suspended, register on the event source
|
||||||
|
* and then resume the thread (recommended).</li>
|
||||||
|
* <li>Create the thread with a lower priority then register on it.
|
||||||
|
* This does not work if the hardware is capable of multiple
|
||||||
|
* physical threads.</li>
|
||||||
|
* </ul>
|
||||||
|
* @note You dont need to unregister from a terminated thread because
|
||||||
|
* the event source becomes inactive.
|
||||||
|
* @note The function is available only if the \p CH_USE_EXIT_EVENT
|
||||||
|
* option is enabled in \p chconf.h.
|
||||||
|
*/
|
||||||
|
EventSource *chThdGetExitEventSource(Thread *tp) {
|
||||||
|
|
||||||
|
return &tp->p_exitesource;
|
||||||
|
}
|
||||||
|
#endif /* CH_USE_EXIT_EVENT */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup Initialization
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CH_H_
|
||||||
|
#define _CH_H_
|
||||||
|
|
||||||
|
typedef struct Thread Thread;
|
||||||
|
|
||||||
|
#ifndef __DOXIGEN__
|
||||||
|
#ifndef _CHCONF_H_
|
||||||
|
#include <chconf.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _CHTYPES_H_
|
||||||
|
#include <chtypes.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _CHCORE_H_
|
||||||
|
#include <chcore.h>
|
||||||
|
#endif
|
||||||
|
#endif /* __DOXIGEN__ */
|
||||||
|
|
||||||
|
#ifndef _DELTA_H_
|
||||||
|
#include "delta.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _SCHEDULER_H_
|
||||||
|
#include "scheduler.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _EVENTS_H_
|
||||||
|
#include "events.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _MESSAGES_H_
|
||||||
|
#include "messages.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _THREADS_H_
|
||||||
|
#include "threads.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _SLEEP_H_
|
||||||
|
#include "sleep.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _SEMAPHORES_H_
|
||||||
|
#include "semaphores.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _QUEUES_H_
|
||||||
|
#include "queues.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _SERIAL_H_
|
||||||
|
#include "serial.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Common values.
|
||||||
|
*/
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE 0
|
||||||
|
#endif
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE 1
|
||||||
|
#endif
|
||||||
|
#ifndef NULL
|
||||||
|
#define NULL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void chSysInit(void);
|
||||||
|
|
||||||
|
#endif /* _CH_H_ */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup VirtualTimers
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _DELTA_H_
|
||||||
|
#define _DELTA_H_
|
||||||
|
|
||||||
|
#ifdef CH_USE_VIRTUAL_TIMERS
|
||||||
|
|
||||||
|
/** Virtual Timer callback function.*/
|
||||||
|
typedef void (*t_vtfunc)(void *);
|
||||||
|
|
||||||
|
typedef struct VirtualTimer VirtualTimer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Virtual Timer descriptor structure.
|
||||||
|
*/
|
||||||
|
struct VirtualTimer {
|
||||||
|
/** Next timer in the delta list.*/
|
||||||
|
VirtualTimer *vt_next;
|
||||||
|
/** Previous timer in the delta list.*/
|
||||||
|
VirtualTimer *vt_prev;
|
||||||
|
/** Time delta before timeout.*/
|
||||||
|
t_time vt_dtime;
|
||||||
|
/** Timer callback function pointer. The pointer is reset to zero after
|
||||||
|
the callback is invoked.*/
|
||||||
|
t_vtfunc vt_func;
|
||||||
|
/** Timer callback function parameter.*/
|
||||||
|
void *vt_par;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delta List header.
|
||||||
|
* @note The delta list is implemented as a double link bidirectional list in
|
||||||
|
* order to make the unlink time constant, the reset of a virtual timer
|
||||||
|
* is often used in the code. An slower implementation using a single
|
||||||
|
* link list is possible and might be added later with a
|
||||||
|
* \p CH_OPTIMIZE_SPACE option.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
/** Next timer in the list (the one that will be triggered next).*/
|
||||||
|
VirtualTimer *dl_next;
|
||||||
|
/** Last timer in the list.*/
|
||||||
|
VirtualTimer *dl_prev;
|
||||||
|
/** Not used but it must be set to /p MAXDELTA.*/
|
||||||
|
t_time dl_dtime;
|
||||||
|
} DeltaList;
|
||||||
|
|
||||||
|
|
||||||
|
extern DeltaList dlist;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Virtual Timers APIs.
|
||||||
|
*/
|
||||||
|
void chVTInit(void);
|
||||||
|
void chVTSetI(VirtualTimer *vtp, t_time time, t_vtfunc vtfunc, void *par);
|
||||||
|
void chVTResetI(VirtualTimer *vtp);
|
||||||
|
|
||||||
|
#endif /* CH_USE_VIRTUAL_TIMER */
|
||||||
|
|
||||||
|
#endif /* _DELTA_H_ */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup Events
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _EVENTS_H_
|
||||||
|
#define _EVENTS_H_
|
||||||
|
|
||||||
|
#ifdef CH_USE_EVENTS
|
||||||
|
|
||||||
|
/** All events allowed mask.*/
|
||||||
|
#define ALL_EVENTS -1
|
||||||
|
|
||||||
|
typedef struct EventListener EventListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event Listener structure.
|
||||||
|
*/
|
||||||
|
struct EventListener {
|
||||||
|
/** Next Event Listener registered on the Event Source.*/
|
||||||
|
EventListener *el_next;
|
||||||
|
/** Thread interested in the Event Source.*/
|
||||||
|
Thread *el_listener;
|
||||||
|
/** Event identifier associated by the thread to the Event Source.*/
|
||||||
|
t_eventid el_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event Source structure.
|
||||||
|
*/
|
||||||
|
typedef struct EventSource {
|
||||||
|
/** First Event Listener registered on the Event Source.*/
|
||||||
|
EventListener *es_next;
|
||||||
|
} EventSource;
|
||||||
|
|
||||||
|
/** Returns the event mask from the event identifier.*/
|
||||||
|
#define EventMask(eid) (1 << (eid))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes an Event Source.
|
||||||
|
* @param esp pointer to the \p EventSource structure
|
||||||
|
* @note Can be called with interrupts disabled or enabled.
|
||||||
|
*/
|
||||||
|
#define chEvtInit(esp) \
|
||||||
|
((esp)->es_next = (EventListener *)(esp))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies if there is at least one \p EventListener registered on the
|
||||||
|
* \p EventSource.
|
||||||
|
* @param esp pointer to the \p EventSource structure
|
||||||
|
* @note Can be called with interrupts disabled or enabled.
|
||||||
|
*/
|
||||||
|
#define chEvtIsListening(esp) \
|
||||||
|
((esp) != (EventSource *)(esp)->es_next)
|
||||||
|
|
||||||
|
|
||||||
|
/** Event Handler callback function.*/
|
||||||
|
typedef void (*t_evhandler)(t_eventid);
|
||||||
|
|
||||||
|
void chEvtRegister(EventSource *esp, EventListener *elp, t_eventid eid);
|
||||||
|
void chEvtUnregister(EventSource *esp, EventListener *elp);
|
||||||
|
void chEvtClear(t_eventmask mask);
|
||||||
|
void chEvtSend(EventSource *esp);
|
||||||
|
void chEvtSendI(EventSource *esp);
|
||||||
|
t_eventid chEvtWait(t_eventmask ewmask, t_evhandler handlers[]);
|
||||||
|
#ifdef CH_USE_EVENTS_TIMEOUT
|
||||||
|
t_eventid chEvtWaitTimeout(t_eventmask ewmask,
|
||||||
|
t_evhandler handlers[],
|
||||||
|
t_time time);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* CH_USE_EVENTS */
|
||||||
|
|
||||||
|
#endif /* _EVENTS_H_ */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup Messages
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _MESSAGES_H_
|
||||||
|
#define _MESSAGES_H_
|
||||||
|
|
||||||
|
#ifdef CH_USE_MESSAGES
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates to TRUE if the thread has pending messages.
|
||||||
|
*/
|
||||||
|
#define chMsgIsPendingI(tp) \
|
||||||
|
((tp)->p_msgqueue.p_next != (Thread *)&(tp)->p_msgqueue)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the first message in the queue.
|
||||||
|
*/
|
||||||
|
#define chMsgGetI(tp) \
|
||||||
|
((tp)->p_msgqueue.p_next->p_msg)
|
||||||
|
|
||||||
|
t_msg chMsgSend(Thread *tp, t_msg msg);
|
||||||
|
t_msg chMsgWait(void);
|
||||||
|
t_msg chMsgGet(void);
|
||||||
|
void chMsgRelease(t_msg msg);
|
||||||
|
|
||||||
|
#ifdef CH_USE_MESSAGES_EVENT
|
||||||
|
t_msg chMsgSendWithEvent(Thread *tp, t_msg msg, EventSource *esp);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CH_USE_MESSAGES_TIMEOUT
|
||||||
|
t_msg chMsgSendTimeout(Thread *tp, t_msg msg, t_time time);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* CH_USE_MESSAGES */
|
||||||
|
|
||||||
|
#endif /* _MESSAGES_H_ */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -0,0 +1,172 @@
|
||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup IOQueues
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _QUEUES_H_
|
||||||
|
#define _QUEUES_H_
|
||||||
|
|
||||||
|
/** Queue notification callback type.*/
|
||||||
|
typedef void (*t_qnotify)(void);
|
||||||
|
|
||||||
|
/** Returned by the queue functions if the operation is successful.*/
|
||||||
|
#define Q_OK RDY_OK
|
||||||
|
/** Returned by the queue functions if a timeout occurs.*/
|
||||||
|
#define Q_TIMEOUT RDY_TIMEOUT
|
||||||
|
/** Returned by the queue functions if the queue is reset.*/
|
||||||
|
#define Q_RESET RDY_RESET
|
||||||
|
/** Returned by the queue functions if the queue is empty.*/
|
||||||
|
#define Q_EMPTY -3
|
||||||
|
/** Returned by the queue functions if the queue is full.*/
|
||||||
|
#define Q_FULL -4
|
||||||
|
|
||||||
|
#ifdef CH_USE_QUEUES
|
||||||
|
/**
|
||||||
|
* I/O queue structure, it is used by both Input and Output Queues,
|
||||||
|
* the difference is on how the semaphore is initialized.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
/** Pointer to the queue buffer.*/
|
||||||
|
BYTE8 *q_buffer;
|
||||||
|
/** Pointer to the first location after the buffer.*/
|
||||||
|
BYTE8 *q_top;
|
||||||
|
/** Write pointer.*/
|
||||||
|
BYTE8 *q_wrptr;
|
||||||
|
/** Read pointer.*/
|
||||||
|
BYTE8 *q_rdptr;
|
||||||
|
/** Counter semaphore.*/
|
||||||
|
Semaphore q_sem;
|
||||||
|
/** Data notification callback.*/
|
||||||
|
t_qnotify q_notify;
|
||||||
|
} Queue;
|
||||||
|
|
||||||
|
/** Returns the queue's buffer size.*/
|
||||||
|
#define chQSize(q) \
|
||||||
|
((q)->q_top - (q)->q_buffer)
|
||||||
|
|
||||||
|
/** Returns the used space if used on an Input Queue and the empty space if
|
||||||
|
* used on an Output Queue.*/
|
||||||
|
#define chQSpace(q) \
|
||||||
|
((q)->q_sem.s_cnt)
|
||||||
|
|
||||||
|
/** Evaluates to TRUE if the specified Input Queue is empty.*/
|
||||||
|
#define chIQIsEmpty(q) \
|
||||||
|
(chQSpace(q) <= 0)
|
||||||
|
|
||||||
|
/** Evaluates to TRUE if the specified Input Queue is full.*/
|
||||||
|
#define chIQIsFull(q) \
|
||||||
|
(chQSpace(q) >= chQSize(q))
|
||||||
|
|
||||||
|
/** Evaluates to TRUE if the specified Output Queue is empty.*/
|
||||||
|
#define chOQIsEmpty(q) \
|
||||||
|
(chQSpace(q) >= chQSize(q))
|
||||||
|
|
||||||
|
/** Evaluates to TRUE if the specified Output Queue is full.*/
|
||||||
|
#define chOQIsFull(q) \
|
||||||
|
(chQSpace(q) <= 0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Input Queues functions. An Input Queue is usually written into by an
|
||||||
|
* interrupt handler and read from a thread.
|
||||||
|
*/
|
||||||
|
void chIQInit(Queue *qp, BYTE8 *buffer, t_size size, t_qnotify inotify);
|
||||||
|
void chIQReset(Queue *qp);
|
||||||
|
t_msg chIQPutI(Queue *qp, BYTE8 b);
|
||||||
|
t_msg chIQGet(Queue *qp);
|
||||||
|
t_size chIQRead(Queue *qp, BYTE8 *buffer, t_size n);
|
||||||
|
#ifdef CH_USE_QUEUES_TIMEOUT
|
||||||
|
t_msg chIQGetTimeout(Queue *qp, t_time time);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Output Queues functions. An Output Queue is usually written into by a
|
||||||
|
* thread and read from an interrupt handler.
|
||||||
|
*/
|
||||||
|
void chOQInit(Queue *queue, BYTE8 *buffer, t_size size, t_qnotify onotify);
|
||||||
|
void chOQReset(Queue *queue);
|
||||||
|
void chOQPut(Queue *queue, BYTE8 b);
|
||||||
|
t_msg chOQGetI(Queue *queue);
|
||||||
|
t_size chOQWrite(Queue *queue, BYTE8 *buffer, t_size n);
|
||||||
|
#endif /* CH_USE_QUEUES */
|
||||||
|
|
||||||
|
#ifdef CH_USE_QUEUES_HALFDUPLEX
|
||||||
|
/**
|
||||||
|
* Half duplex queue structure.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
/** Pointer to the queue buffer.*/
|
||||||
|
BYTE8 *hdq_buffer;
|
||||||
|
/** Pointer to the first location after the buffer.*/
|
||||||
|
BYTE8 *hdq_top;
|
||||||
|
/** Write pointer.*/
|
||||||
|
BYTE8 *hdq_wrptr;
|
||||||
|
/** Read pointer.*/
|
||||||
|
BYTE8 *hdq_rdptr;
|
||||||
|
/** Input counter semaphore.*/
|
||||||
|
Semaphore hdq_isem;
|
||||||
|
/** Output counter semaphore.*/
|
||||||
|
Semaphore hdq_osem;
|
||||||
|
/** Input data notification callback.*/
|
||||||
|
t_qnotify hdq_inotify;
|
||||||
|
/** Output data notification callback.*/
|
||||||
|
t_qnotify hdq_onotify;
|
||||||
|
} HalfDuplexQueue;
|
||||||
|
|
||||||
|
/** Returns the queue's buffer size.*/
|
||||||
|
#define chHDQSize(q) \
|
||||||
|
((q)->hdq_top - (q)->hdq_buffer)
|
||||||
|
|
||||||
|
/** Returns the queue space when in transmission mode.*/
|
||||||
|
#define chHDQEmptySpace(q) \
|
||||||
|
((q)->hdq_osem.s_cnt)
|
||||||
|
|
||||||
|
/** Returns the number of the bytes in the queue when in receive mode.*/
|
||||||
|
#define chHDQFilledSpace(q) \
|
||||||
|
((q)->hdq_isem.s_cnt)
|
||||||
|
|
||||||
|
/** Evaluates to TRUE if the queue is in transmit mode.*/
|
||||||
|
#define chHDQIsTransmitting(q) \
|
||||||
|
(chHDQEmptySpace(q) < chHDQSize(q))
|
||||||
|
|
||||||
|
/** Evaluates to TRUE if the queue is in receive mode.*/
|
||||||
|
#define chHDQIsReceiving(q) \
|
||||||
|
(chHDQEmptySpaceQ(q) >= chHDQSize(q))
|
||||||
|
|
||||||
|
/** Evaluates to TRUE if the receive queue is full.*/
|
||||||
|
#define chHDQIsFullReceive(q) \
|
||||||
|
(chHDQFilledSpace(q) >= chHDQSize(q))
|
||||||
|
|
||||||
|
void chHDQInit(HalfDuplexQueue *qp, BYTE8 *buffer, t_size size,
|
||||||
|
t_qnotify inotify, t_qnotify onotify);
|
||||||
|
t_msg chHDQGetReceive(HalfDuplexQueue *qp);
|
||||||
|
void chHDQPutTransmit(HalfDuplexQueue *qp, BYTE8 b);
|
||||||
|
t_msg chHDQGetTransmitI(HalfDuplexQueue *qp);
|
||||||
|
t_msg chHDQPutReceiveI(HalfDuplexQueue *qp, BYTE8 b);
|
||||||
|
#ifdef CH_USE_QUEUES_TIMEOUT
|
||||||
|
t_msg chHDQGetReceiveTimeout(HalfDuplexQueue *qp, t_time time);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* CH_USE_QUEUES_HALFDUPLEX */
|
||||||
|
|
||||||
|
#endif /* _QUEUES_H_ */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup Scheduler
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SCHEDULER_H_
|
||||||
|
#define _SCHEDULER_H_
|
||||||
|
|
||||||
|
/** Normal \p chSchReadyI() message.*/
|
||||||
|
#define RDY_OK 0
|
||||||
|
/** Returned if the thread was made ready because a timeout.*/
|
||||||
|
#define RDY_TIMEOUT -1
|
||||||
|
/** Returned if the thread was made ready because a reset.*/
|
||||||
|
#define RDY_RESET -2
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ready list header.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
/** Highest priority \p Thread in the list.*/
|
||||||
|
Thread *p_next;
|
||||||
|
/** Lowest priority \p Thread in the list.*/
|
||||||
|
Thread *p_prev;
|
||||||
|
/** Alwas set to \p MAXPRIO.*/
|
||||||
|
t_prio p_prio;
|
||||||
|
} ReadyList;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scheduler APIs.
|
||||||
|
*/
|
||||||
|
void chSchInit(void);
|
||||||
|
Thread *chSchReadyI(Thread *tp);
|
||||||
|
void chSchGoSleepI(t_tstate newstate);
|
||||||
|
void chSchWakeupI(Thread *tp, t_msg msg);
|
||||||
|
void chSchRescheduleI(void);
|
||||||
|
void chSchDoRescheduleI(void);
|
||||||
|
BOOL chSchRescRequiredI(void);
|
||||||
|
void chSchTimerHandlerI(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current thread pointer.
|
||||||
|
* @note Dont use this directly but use the \p chThdSelf()
|
||||||
|
* instead. Direct use of system global variables is discouraged because
|
||||||
|
* portability reasons.
|
||||||
|
*/
|
||||||
|
#ifdef CH_CURRP_REGISTER_CACHE
|
||||||
|
register Thread *currp asm(CH_CURRP_REGISTER_CACHE);
|
||||||
|
#else
|
||||||
|
extern Thread *currp;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* System ticks counter.
|
||||||
|
* @note Dont use this directly but use the \p chSysGetTime()
|
||||||
|
* instead. Direct use of system global variables is discouraged because
|
||||||
|
* portability reasons.
|
||||||
|
*/
|
||||||
|
extern t_time stime;
|
||||||
|
|
||||||
|
#endif /* _SCHEDULER_H_ */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup Semaphores
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SEMAPHORES_H_
|
||||||
|
#define _SEMAPHORES_H_
|
||||||
|
|
||||||
|
#ifdef CH_USE_SEMAPHORES
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Semaphore structure.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
/** Queue of the threads sleeping on this Semaphore.*/
|
||||||
|
ThreadsQueue s_queue;
|
||||||
|
/** The Semaphore counter.*/
|
||||||
|
t_semcnt s_cnt;
|
||||||
|
} Semaphore;
|
||||||
|
|
||||||
|
void chSemInit(Semaphore *sp, t_semcnt n);
|
||||||
|
void chSemReset(Semaphore *sp, t_semcnt n);
|
||||||
|
void chSemResetI(Semaphore *sp, t_semcnt n);
|
||||||
|
void chSemWait(Semaphore *sp);
|
||||||
|
void chSemWaitS(Semaphore *sp);
|
||||||
|
t_msg chSemWaitTimeout(Semaphore *sp, t_time time);
|
||||||
|
t_msg chSemWaitTimeoutS(Semaphore *sp, t_time time);
|
||||||
|
void chSemSignal(Semaphore *sp);
|
||||||
|
void chSemSignalI(Semaphore *sp);
|
||||||
|
void chSignalWait(Semaphore *sps, Semaphore *spw);
|
||||||
|
|
||||||
|
#ifdef CH_USE_RT_SEMAPHORES
|
||||||
|
void chSemRaisePrioWait(Semaphore *sp);
|
||||||
|
void chSemLowerPrioSignal(Semaphore *sp);
|
||||||
|
void chSemRaisePrioSignalWait(Semaphore *sps, Semaphore *spw);
|
||||||
|
void chSemLowerPrioSignalWait(Semaphore *sps, Semaphore *spw);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decreases the semaphore counter, this macro can be used when it is ensured
|
||||||
|
* that the counter would not become negative.
|
||||||
|
*/
|
||||||
|
#define chSemFastWaitS(sp) \
|
||||||
|
((sp)->s_cnt--)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increases the semaphore counter, this macro can be used when the counter is
|
||||||
|
* not negative.
|
||||||
|
*/
|
||||||
|
#define chSemFastSignalI(sp) \
|
||||||
|
((sp)->s_cnt++)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the semaphore counter current value.
|
||||||
|
*/
|
||||||
|
#define chSemGetCounter(sp) \
|
||||||
|
((sp)->s_cnt)
|
||||||
|
|
||||||
|
#endif /* CH_USE_SEMAPHORES */
|
||||||
|
|
||||||
|
#endif /* _SEM_H_ */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -0,0 +1,154 @@
|
||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup Serial
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SERIAL_H_
|
||||||
|
#define _SERIAL_H_
|
||||||
|
|
||||||
|
/** No pending conditions.*/
|
||||||
|
#define SD_NO_ERROR 0
|
||||||
|
/** Connection happened.*/
|
||||||
|
#define SD_CONNECTED 1
|
||||||
|
/** Disconnection happened.*/
|
||||||
|
#define SD_DISCONNECTED 2
|
||||||
|
/** Parity error happened.*/
|
||||||
|
#define SD_PARITY_ERROR 4
|
||||||
|
/** Framing error happened.*/
|
||||||
|
#define SD_FRAMING_ERROR 8
|
||||||
|
/** Overflow happened.*/
|
||||||
|
#define SD_OVERRUN_ERROR 16
|
||||||
|
/** Break detected.*/
|
||||||
|
#define SD_BREAK_DETECTED 32
|
||||||
|
|
||||||
|
/** Serial Driver condition flags type.*/
|
||||||
|
typedef UWORD16 t_dflags;
|
||||||
|
|
||||||
|
#ifdef CH_USE_SERIAL_FULLDUPLEX
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Full Duplex Serial Driver main structure.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
|
||||||
|
/** Input queue. Incoming data can be read from this queue by using the
|
||||||
|
* queues APIs.*/
|
||||||
|
Queue sd_iqueue;
|
||||||
|
/** Data Available \p EventSource. This event is generated when some incoming
|
||||||
|
* data is inserted in the Input \p Queue.*/
|
||||||
|
EventSource sd_ievent;
|
||||||
|
|
||||||
|
/** Output queue. Outgoing data can be written to this Output \p Queue by
|
||||||
|
* using the queues APIs.*/
|
||||||
|
Queue sd_oqueue;
|
||||||
|
/** Data Transmitted \p EventSource. This event is generated when the
|
||||||
|
* Output \p Queue is empty.*/
|
||||||
|
EventSource sd_oevent;
|
||||||
|
|
||||||
|
/** I/O driver status flags. This field should not be read directly but
|
||||||
|
* the \p chFDDGetAndClearFlags() funtion should be used instead.*/
|
||||||
|
t_dflags sd_flags;
|
||||||
|
/** Status Change \p EventSource. This event is generated when a
|
||||||
|
* condition flag was changed.*/
|
||||||
|
EventSource sd_sevent;
|
||||||
|
} FullDuplexDriver;
|
||||||
|
|
||||||
|
void chFDDInit(FullDuplexDriver *sd,
|
||||||
|
BYTE8 *ib, t_size isize, t_qnotify inotify,
|
||||||
|
BYTE8 *ob, t_size osize, t_qnotify onotify);
|
||||||
|
void chFDDIncomingDataI(FullDuplexDriver *sd, BYTE8 b);
|
||||||
|
t_msg chFDDRequestDataI(FullDuplexDriver *sd);
|
||||||
|
void chFDDAddFlagsI(FullDuplexDriver *sd, t_dflags mask);
|
||||||
|
t_dflags chFDDGetAndClearFlags(FullDuplexDriver *sd);
|
||||||
|
|
||||||
|
/** @see chIQRead()*/
|
||||||
|
#define chFDDRead(sd, b, n) \
|
||||||
|
chIQRead(&(sd)->sd_iqueue, b, n)
|
||||||
|
|
||||||
|
/** @see chOQWrite()*/
|
||||||
|
#define chFDDWrite(sd, b, n) \
|
||||||
|
chOQWrite(&(sd)->sd_oqueue, b, n)
|
||||||
|
|
||||||
|
/** @see chIQGet()*/
|
||||||
|
#define chFDDGet(sd) \
|
||||||
|
chIQGet(&(sd)->sd_iqueue)
|
||||||
|
|
||||||
|
/** @see chIQGetTimeout()*/
|
||||||
|
#define chFDDGetTimeout(sd, t) \
|
||||||
|
chIQGetTimeout(&(sd)->sd_iqueue, t)
|
||||||
|
|
||||||
|
/** @see chOQPut()*/
|
||||||
|
#define chFDDPut(sd, b) \
|
||||||
|
chOQPut(&(sd)->sd_oqueue, b)
|
||||||
|
|
||||||
|
#endif /* CH_USE_SERIAL_FULLDUPLEX */
|
||||||
|
|
||||||
|
#ifdef CH_USE_SERIAL_HALFDUPLEX
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Full Duplex Serial Driver main structure.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
|
||||||
|
/** Data queue. Transmit/receive \p HalfDuplexQueue.*/
|
||||||
|
HalfDuplexQueue sd_queue;
|
||||||
|
/** Data Available \p EventSource. This event is generated when some
|
||||||
|
* incoming data is inserted in the receive queue.*/
|
||||||
|
EventSource sd_ievent;
|
||||||
|
/** Data Transmitted \p EventSource. This event is generated when the
|
||||||
|
* transmission queue is empty and the driver can either transmit more
|
||||||
|
* data or enter receive mode.*/
|
||||||
|
EventSource sd_oevent;
|
||||||
|
|
||||||
|
/** I/O driver status flags. This field should not be read directly but
|
||||||
|
* the \p chHDDGetAndClearFlags() funtion should be used
|
||||||
|
* instead.*/
|
||||||
|
t_dflags sd_flags;
|
||||||
|
/** Status Change Event Source. This event is generated when a condition
|
||||||
|
* flag was changed.*/
|
||||||
|
EventSource sd_sevent;
|
||||||
|
} HalfDuplexDriver;
|
||||||
|
|
||||||
|
void chHDDInit(HalfDuplexDriver *sd, BYTE8 *b, t_size size,
|
||||||
|
t_qnotify inotify, t_qnotify onotify);
|
||||||
|
void chHDDIncomingDataI(HalfDuplexDriver *sd, BYTE8 b);
|
||||||
|
t_msg chHDDRequestDataI(HalfDuplexDriver *sd);
|
||||||
|
void chHDDAddFlagsI(HalfDuplexDriver *sd, t_dflags mask);
|
||||||
|
t_dflags chHDDGetAndClearFlags(HalfDuplexDriver *sd);
|
||||||
|
|
||||||
|
/** @see chHDQGetReceive()*/
|
||||||
|
#define chHDDGetReceive(sd) \
|
||||||
|
chHDQGetReceive(&(sd)->sd_queue)
|
||||||
|
|
||||||
|
/** @see chHDQGetReceiveTimeout()*/
|
||||||
|
#define chHDDGetReceiveTimeout(sd, t) \
|
||||||
|
chHDQGetReceiveTimeout(&(sd)->sd_queue, t)
|
||||||
|
|
||||||
|
/** @see chHDQPutTransmit()*/
|
||||||
|
#define chHDDPutTransmit(sd, b) \
|
||||||
|
chHDQPutTransmit(&(sd)->sd_queue, b)
|
||||||
|
|
||||||
|
#endif /* CH_USE_SERIAL_HALFDUPLEX */
|
||||||
|
|
||||||
|
#endif /* _SERIAL_H_ */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup Time
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SLEEP_H_
|
||||||
|
#define _SLEEP_H_
|
||||||
|
|
||||||
|
#ifdef CH_USE_SLEEP
|
||||||
|
|
||||||
|
void chThdSleep(t_time time);
|
||||||
|
|
||||||
|
#ifdef CH_USE_SYSTEMTIME
|
||||||
|
|
||||||
|
void chThdSleepUntil(t_time time);
|
||||||
|
t_time chSysGetTime(void);
|
||||||
|
|
||||||
|
#endif /* CH_USE_SYSTEMTIME */
|
||||||
|
|
||||||
|
#endif /* CH_USE_SLEEP */
|
||||||
|
|
||||||
|
#endif /* _SLEEP_H_ */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -0,0 +1,203 @@
|
||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup Threads
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _THREADS_H_
|
||||||
|
#define _THREADS_H_
|
||||||
|
|
||||||
|
#define isempty(qp) ((qp)->p_next == (Thread *)(qp))
|
||||||
|
#define notempty(qp) ((qp)->p_next != (Thread *)(qp))
|
||||||
|
#define firstprio(qp) ((qp)->p_next->p_prio)
|
||||||
|
#define lastprio(qp) ((qp)->p_prev->p_prio)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic threads queue header and element.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
/** First \p Thread in the queue.*/
|
||||||
|
Thread *p_next;
|
||||||
|
/** Last \p Thread in the queue.*/
|
||||||
|
Thread *p_prev;
|
||||||
|
} ThreadsQueue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Structure representing a thread.
|
||||||
|
* @note Not all the listed fields are always needed, by switching off some
|
||||||
|
* not needed ChibiOS/RT subsystems it is possible to save RAM space by
|
||||||
|
* shrinking the \p Thread structure.
|
||||||
|
*/
|
||||||
|
struct Thread {
|
||||||
|
/** Next \p Thread in the threads list.*/
|
||||||
|
Thread *p_next;
|
||||||
|
/** Previous \p Thread in the threads list.*/
|
||||||
|
Thread *p_prev;
|
||||||
|
/* End of the fields shared with the ThreadsQueue structure. */
|
||||||
|
/** The thread priority.*/
|
||||||
|
t_prio p_prio;
|
||||||
|
/* End of the fields shared with the ReadyList structure. */
|
||||||
|
/** Current thread state.*/
|
||||||
|
t_tstate p_state;
|
||||||
|
/** Mode flags.*/
|
||||||
|
t_tmode p_flags;
|
||||||
|
/*
|
||||||
|
* The following fields are merged in an union because they are all
|
||||||
|
* state-specific fields. This trick saves some extra space for each
|
||||||
|
* thread in the system.
|
||||||
|
*/
|
||||||
|
union {
|
||||||
|
/** Thread wakeup code, normally set to \p RDY_OK by the \p chSchReadyI()
|
||||||
|
* (only while in \p PRCURR or \p PRREADY states).*/
|
||||||
|
t_msg p_rdymsg;
|
||||||
|
/** The thread exit code (only while in \p PREXIT state).*/
|
||||||
|
t_msg p_exitcode;
|
||||||
|
#ifdef CH_USE_EVENTS
|
||||||
|
/** Enabled events mask (only while in \p PRWTEVENT state).*/
|
||||||
|
t_eventmask p_ewmask;
|
||||||
|
#endif
|
||||||
|
#ifdef CH_USE_MESSAGES
|
||||||
|
/** Message (only while in \p PRSNDMSG state).*/
|
||||||
|
t_msg p_msg;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
/** Machine dependent processor context.*/
|
||||||
|
Context p_ctx;
|
||||||
|
/*
|
||||||
|
* Start of the optional fields. Note, the null thread may also let its
|
||||||
|
* stack overwrite the following fields since it never uses semaphores,
|
||||||
|
* events, messages, exit etc, this can save some space on RAM starved
|
||||||
|
* systems, be caruful in doing so.
|
||||||
|
*/
|
||||||
|
#ifdef CH_USE_WAITEXIT
|
||||||
|
/** The queue of the threads waiting for this thread termination.*/
|
||||||
|
ThreadsQueue p_waiting;
|
||||||
|
#endif
|
||||||
|
#ifdef CH_USE_EXIT_EVENT
|
||||||
|
/** The thread termination \p EventSource.*/
|
||||||
|
EventSource p_exitesource;
|
||||||
|
#endif
|
||||||
|
#ifdef CH_USE_MESSAGES
|
||||||
|
ThreadsQueue p_msgqueue;
|
||||||
|
#endif
|
||||||
|
#ifdef CH_USE_EVENTS
|
||||||
|
/** Pending events mask.*/
|
||||||
|
t_eventmask p_epending;
|
||||||
|
#endif
|
||||||
|
#ifdef CH_USE_RT_SEMAPHORES
|
||||||
|
/** Priority backup after acquiring a RT semaphore.*/
|
||||||
|
t_prio p_bakprio;
|
||||||
|
/** RT semaphores depth counter.*/
|
||||||
|
WORD16 p_rtcnt;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Thread state: Reserved.*/
|
||||||
|
#define PRFREE 0
|
||||||
|
/** Thread state: Current.*/
|
||||||
|
#define PRCURR 1
|
||||||
|
/** Thread state: Thread in the ready list.*/
|
||||||
|
#define PRREADY 2
|
||||||
|
/** Thread state: Thread created in suspended state.*/
|
||||||
|
#define PRSUSPENDED 3
|
||||||
|
/** Thread state: Waiting on a semaphore.*/
|
||||||
|
#define PRWTSEM 4
|
||||||
|
/** Thread state: Waiting in \p chThdSleep() or \p chThdSleepUntil().*/
|
||||||
|
#define PRSLEEP 5
|
||||||
|
/** Thread state: Waiting in \p chThdWait().*/
|
||||||
|
#define PRWAIT 6
|
||||||
|
/** Thread state: Waiting in \p chEvtWait().*/
|
||||||
|
#define PRWTEVENT 7
|
||||||
|
/** Thread state: Waiting in \p chMsgSend().*/
|
||||||
|
#define PRSNDMSG 8
|
||||||
|
/** Thread state: Waiting in \p chMsgWait().*/
|
||||||
|
#define PRWTMSG 9
|
||||||
|
/** Thread state: After termination.*/
|
||||||
|
#define PREXIT 10
|
||||||
|
|
||||||
|
/** Thread option: Termination requested flag.*/
|
||||||
|
#define P_TERMINATE 1
|
||||||
|
/** Thread option: Create suspended thread.*/
|
||||||
|
#define P_SUSPENDED 2
|
||||||
|
|
||||||
|
/** Idle thread priority.*/
|
||||||
|
#define IDLEPRIO 0
|
||||||
|
/** Lowest user priority.*/
|
||||||
|
#define LOWPRIO 1
|
||||||
|
/** Normal user priority.*/
|
||||||
|
#define NORMALPRIO 128
|
||||||
|
/** Highest user priority.*/
|
||||||
|
#define HIGHPRIO 255
|
||||||
|
/** Boosted base priority.*/
|
||||||
|
#define MEPRIO 256
|
||||||
|
/** Absolute priority.*/
|
||||||
|
#define ABSPRIO 512
|
||||||
|
|
||||||
|
/* Not an API, don't use into the application code.*/
|
||||||
|
void _InitThread(t_prio prio, t_tmode mode, Thread *tp);
|
||||||
|
|
||||||
|
/** Thread function.*/
|
||||||
|
typedef t_msg (*t_tfunc)(void *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Threads Lists functions.
|
||||||
|
*/
|
||||||
|
#ifndef CH_OPTIMIZE_SPEED
|
||||||
|
void enqueue(Thread *tp, ThreadsQueue *tqp);
|
||||||
|
Thread *dequeue(Thread *tp);
|
||||||
|
#else
|
||||||
|
static INLINE Thread *dequeue(Thread *tp) {
|
||||||
|
|
||||||
|
tp->p_prev->p_next = tp->p_next;
|
||||||
|
tp->p_next->p_prev = tp->p_prev;
|
||||||
|
return tp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE void enqueue(Thread *tp, ThreadsQueue *tqp) {
|
||||||
|
|
||||||
|
tp->p_next = (Thread *)tqp;
|
||||||
|
tp->p_prev = tqp->p_prev;
|
||||||
|
tqp->p_prev->p_next = tp;
|
||||||
|
tqp->p_prev = tp;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Threads APIs.
|
||||||
|
*/
|
||||||
|
#define chThdSelf() currp
|
||||||
|
Thread *chThdCreate(t_prio prio, t_tmode mode, void *workspace,
|
||||||
|
t_size wsize, t_tfunc pf, void *arg);
|
||||||
|
void chThdResume(Thread *tp);
|
||||||
|
void chThdTerminate(Thread *tp);
|
||||||
|
BOOL chThdShouldTerminate(void);
|
||||||
|
BOOL chThdTerminated(Thread *tp);
|
||||||
|
void chThdExit(t_msg msg);
|
||||||
|
#ifdef CH_USE_WAITEXIT
|
||||||
|
t_msg chThdWait(Thread *tp);
|
||||||
|
#endif
|
||||||
|
#ifdef CH_USE_EXIT_EVENT
|
||||||
|
EventSource *chThdGetExitEventSource(Thread *tp);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _THREADS_H_ */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -0,0 +1,154 @@
|
||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup Config
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CHCONF_H_
|
||||||
|
#define _CHCONF_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: this is just documentation for doxigen, the real configuration file
|
||||||
|
* is the one into the project directories.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Configuration option: if specified then time efficient rather than space
|
||||||
|
* efficient code is used when two possible implementations exist, note
|
||||||
|
* that this is not related to the compiler optimization options.*/
|
||||||
|
#define CH_OPTIMIZE_SPEED
|
||||||
|
|
||||||
|
/** Configuration option: if specified then the Virtual Timers subsystem is
|
||||||
|
* included in the kernel.*/
|
||||||
|
#define CH_USE_VIRTUAL_TIMERS
|
||||||
|
|
||||||
|
/** Configuration option: if specified then the System Timer subsystem is
|
||||||
|
* included in the kernel.*/
|
||||||
|
#define CH_USE_SYSTEMTIME
|
||||||
|
|
||||||
|
/** Configuration option: if specified then the \p chThdSleep() function is
|
||||||
|
* included in the kernel.
|
||||||
|
* @note requires \p CH_USE_VIRTUAL_TIMERS.*/
|
||||||
|
#define CH_USE_SLEEP
|
||||||
|
|
||||||
|
/** Configuration option: if specified then the \p chThdResume()
|
||||||
|
* function is included in the kernel.*/
|
||||||
|
#define CH_USE_RESUME
|
||||||
|
|
||||||
|
/** Configuration option: if specified then the \p chThdTerminate()
|
||||||
|
* and \p chThdShouldTerminate() functions are included in the kernel.*/
|
||||||
|
#define CH_USE_TERMINATE
|
||||||
|
|
||||||
|
/** Configuration option: if specified then the \p chThdWait() function
|
||||||
|
* is included in the kernel.*/
|
||||||
|
#define CH_USE_WAITEXIT
|
||||||
|
|
||||||
|
/** Configuration option: if specified then the Semaphores APIs are included
|
||||||
|
* in the kernel.*/
|
||||||
|
#define CH_USE_SEMAPHORES
|
||||||
|
|
||||||
|
/** Configuration option: if specified then the Semaphores with timeout APIs
|
||||||
|
* are included in the kernel.
|
||||||
|
* @note requires \p CH_USE_SEMAPHORES.
|
||||||
|
* @note requires \p CH_USE_VIRTUAL_TIMERS.*/
|
||||||
|
#define CH_USE_SEMAPHORES_TIMEOUT
|
||||||
|
|
||||||
|
/** Configuration option: if specified then the Semaphores APIs with priority
|
||||||
|
* shift are included in the kernel.
|
||||||
|
* @note requires \p CH_USE_SEMAPHORES.*/
|
||||||
|
#define CH_USE_RT_SEMAPHORES
|
||||||
|
|
||||||
|
/** Configuration option: if specified then the Events APIs are included in
|
||||||
|
* the kernel.*/
|
||||||
|
#define CH_USE_EVENTS
|
||||||
|
|
||||||
|
/** Configuration option: if specified then the \p chEvtWaitTimeout()
|
||||||
|
* function is included in the kernel.
|
||||||
|
* @note requires \p CH_USE_EVENTS.
|
||||||
|
* @note requires \p CH_USE_VIRTUAL_TIMERS.*/
|
||||||
|
#define CH_USE_EVENTS_TIMEOUT
|
||||||
|
|
||||||
|
/** Configuration option: if specified then the Synchronous Messages APIs are
|
||||||
|
* included in the kernel.*/
|
||||||
|
#define CH_USE_MESSAGES
|
||||||
|
|
||||||
|
/** Configuration option: if specified then the \p chMsgSendTimeout()
|
||||||
|
* function is included in the kernel.
|
||||||
|
* @note requires \p CH_USE_MESSAGES.
|
||||||
|
* @note requires \p CH_USE_VIRTUAL_TIMERS.*/
|
||||||
|
#define CH_USE_MESSAGES_TIMEOUT
|
||||||
|
|
||||||
|
/** Configuration option: if specified then the \p chMsgSendWithEvent()
|
||||||
|
* function is included in the kernel.
|
||||||
|
* @note requires \p CH_USE_MESSAGES.
|
||||||
|
* @note requires \p CH_USE_VIRTUAL_TIMERS.*/
|
||||||
|
#define CH_USE_MESSAGES_EVENT
|
||||||
|
|
||||||
|
/** Configuration option: if specified then the
|
||||||
|
* \p chThdGetExitEventSource() function is included in the kernel.
|
||||||
|
* @note requires \p CH_USE_MESSAGES.
|
||||||
|
* @note requires \p CH_USE_EVENTS.*/
|
||||||
|
#define CH_USE_EXIT_EVENT
|
||||||
|
|
||||||
|
/** Configuration option: if specified then the I/O queues APIs are included
|
||||||
|
* in the kernel.*/
|
||||||
|
#define CH_USE_QUEUES
|
||||||
|
|
||||||
|
/** Configuration option: if specified then the halfduplex queue APIs are
|
||||||
|
* included in the kernel.*/
|
||||||
|
#define CH_USE_QUEUES_HALFDUPLEX
|
||||||
|
|
||||||
|
/** Configuration option: if specified then the I/O queues with timeout
|
||||||
|
* APIs are included in the kernel.
|
||||||
|
* @note requires \p CH_USE_SEMAPHORES_TIMEOUT.*/
|
||||||
|
#define CH_USE_QUEUES_TIMEOUT
|
||||||
|
|
||||||
|
/** Configuration option: if specified then the full duplex serial driver APIs
|
||||||
|
* are included in the kernel.*/
|
||||||
|
#define CH_USE_SERIAL_FULLDUPLEX
|
||||||
|
|
||||||
|
/** Configuration option: if specified then the half duplex serial driver APIs
|
||||||
|
* are included in the kernel.*/
|
||||||
|
#define CH_USE_SERIAL_HALFDUPLEX
|
||||||
|
|
||||||
|
/** Configuration option: Frequency of the system timer that drives the system
|
||||||
|
* ticks. This also defines the system time unit.*/
|
||||||
|
#define CH_FREQUENCY 100
|
||||||
|
|
||||||
|
/** Configuration option: This constant is the number of ticks allowed for the
|
||||||
|
* threads before preemption occurs.*/
|
||||||
|
#define CH_TIME_QUANTUM 10
|
||||||
|
|
||||||
|
/** Configuration option: Defines a CPU register to be used as storage for the
|
||||||
|
* global \p currp variable. Caching this variable in a register can greatly
|
||||||
|
* improve both space and time efficiency of the generated code. Another side
|
||||||
|
* effect is that one less register has to be saved during the context switch
|
||||||
|
* resulting in lower RAM usage and faster code.
|
||||||
|
* @note This option is only useable with the GCC compiler and is only useful
|
||||||
|
* on processors with many registers like ARM cores.
|
||||||
|
* @note If this option is enabled then ALL the libraries linked to the
|
||||||
|
* ChibiOS/RT code <b>must</b> be recompiled with the GCC option \p
|
||||||
|
* -ffixed-\<reg\>.
|
||||||
|
*/
|
||||||
|
#define CH_CURRP_REGISTER_CACHE "reg"
|
||||||
|
|
||||||
|
#endif /* _CHCONF_H_ */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup Core
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ch.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is just a template, it contains the function prototypes and the
|
||||||
|
* doxigen documentation. The implementation of the following functions is
|
||||||
|
* architecture/compiler specific.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function implements the idle thread infinite loop. The function should
|
||||||
|
* put the processor in the lowest power mode capable to serve interrupts.
|
||||||
|
*/
|
||||||
|
void chSysPause(void) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abonormal system termination handler. Invoked by the ChobiOS/RT when an
|
||||||
|
* abnormal unrecoverable condition is met.
|
||||||
|
*/
|
||||||
|
void chSysHalt(void) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context switch.
|
||||||
|
*/
|
||||||
|
void chSysSwitchI(struct ctxswc **oldp, struct ctxswc *new) {}
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup Core
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CHCORE_H_
|
||||||
|
#define _CHCORE_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stack saved context.
|
||||||
|
*/
|
||||||
|
struct stackregs {
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Platform dependent part of the \p chThdCreate() API.
|
||||||
|
*/
|
||||||
|
#define SETUP_CONTEXT(workspace, wsize, pf, arg) \
|
||||||
|
{ \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enters the ChobiOS/RT system mutual exclusion zone, the implementation is
|
||||||
|
* architecture dependent, on single core systems usually this function
|
||||||
|
* just disables the interrupts.
|
||||||
|
* @note The code in the system mutual exclusion zone must be as light and
|
||||||
|
* fast as possible, the system performance is affected by this.
|
||||||
|
* @note The use of system mutual exclusion zones are not recommended in
|
||||||
|
* the user code, it is a better idea to use the Semaphores instead.
|
||||||
|
*/
|
||||||
|
#define chSysLock()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Leaves the ChobiOS/RT system mutual exclusion zone, the implementation is
|
||||||
|
* architecture dependent, on single core systems usually this function
|
||||||
|
* just enables the interrupts.
|
||||||
|
* @note The code in the system mutual exclusion zone must be as light and
|
||||||
|
* fast as possible, the system performance is affected by this.
|
||||||
|
* @note The use of system mutual exclusion zones are not recommended in
|
||||||
|
* the user code, it is a better idea to use the Semaphores instead.
|
||||||
|
*/
|
||||||
|
#define chSysUnlock()
|
||||||
|
|
||||||
|
void chSysHalt(void);
|
||||||
|
void chSysPause(void);
|
||||||
|
void chSysSwitchI(struct ctxswc **oldp, struct ctxswc *new);
|
||||||
|
|
||||||
|
#endif /* _CHCORE_H_ */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup Core
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CHTYPES_H_
|
||||||
|
#define _CHTYPES_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generic types often dependant on the compiler.
|
||||||
|
*/
|
||||||
|
#define BOOL char
|
||||||
|
#define BYTE8 unsigned char
|
||||||
|
#define WORD16 short
|
||||||
|
#define UWORD16 unsigned short
|
||||||
|
#define LONG32 int
|
||||||
|
#define ULONG32 unsigned int
|
||||||
|
#define PTR_EQ int
|
||||||
|
|
||||||
|
#define INT_REQUIRED_STACK 0
|
||||||
|
|
||||||
|
typedef BYTE8 t_tmode;
|
||||||
|
typedef BYTE8 t_tstate;
|
||||||
|
typedef WORD16 t_prio;
|
||||||
|
typedef PTR_EQ t_msg;
|
||||||
|
typedef LONG32 t_eventid;
|
||||||
|
typedef ULONG32 t_eventmask;
|
||||||
|
typedef ULONG32 t_time;
|
||||||
|
typedef LONG32 t_semcnt;
|
||||||
|
typedef ULONG32 t_size;
|
||||||
|
|
||||||
|
#define MINPRIO 0x8000
|
||||||
|
#define MAXPRIO 0x7fff
|
||||||
|
|
||||||
|
#define MINDELTA 0
|
||||||
|
#define MAXDELTA 0xffff
|
||||||
|
|
||||||
|
#define THREAD
|
||||||
|
#define INLINE inline
|
||||||
|
|
||||||
|
#endif /* _CHTYPES_H_ */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -0,0 +1 @@
|
||||||
|
Files that need to be copied in each project/port directory and configured.
|
Loading…
Reference in New Issue