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

This commit is contained in:
gdisirio 2007-09-18 12:40:26 +00:00
parent f712427135
commit 30f0bb1d66
25 changed files with 3587 additions and 0 deletions

84
src/chdelta.c Normal file
View File

@ -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 */
/** @} */

247
src/chevents.c Normal file
View File

@ -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 */
/** @} */

59
src/chinit.c Normal file
View File

@ -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();
}
/** @} */

194
src/chmsg.c Normal file
View File

@ -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 */
/** @} */

478
src/chqueues.c Normal file
View File

@ -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 */
/** @} */

205
src/chschd.c Normal file
View File

@ -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
}
/** @} */

376
src/chsem.c Normal file
View File

@ -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 */
/** @} */

195
src/chserial.c Normal file
View File

@ -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 */
/** @} */

79
src/chsleep.c Normal file
View File

@ -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 */
/** @} */

265
src/chthreads.c Normal file
View File

@ -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 */
/** @} */

97
src/include/ch.h Normal file
View File

@ -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_ */
/** @} */

83
src/include/delta.h Normal file
View File

@ -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_ */
/** @} */

95
src/include/events.h Normal file
View File

@ -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_ */
/** @} */

59
src/include/messages.h Normal file
View File

@ -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_ */
/** @} */

172
src/include/queues.h Normal file
View File

@ -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_ */
/** @} */

81
src/include/scheduler.h Normal file
View File

@ -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_ */
/** @} */

82
src/include/semaphores.h Normal file
View File

@ -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_ */
/** @} */

154
src/include/serial.h Normal file
View File

@ -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_ */
/** @} */

43
src/include/sleep.h Normal file
View File

@ -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_ */
/** @} */

203
src/include/threads.h Normal file
View File

@ -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_ */
/** @} */

154
src/templates/chconf.h Normal file
View File

@ -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_ */
/** @} */

50
src/templates/chcore.c Normal file
View File

@ -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) {}
/** @} */

69
src/templates/chcore.h Normal file
View File

@ -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_ */
/** @} */

62
src/templates/chtypes.h Normal file
View File

@ -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_ */
/** @} */

1
src/templates/readme.txt Normal file
View File

@ -0,0 +1 @@
Files that need to be copied in each project/port directory and configured.