diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/chdelta.c | 84 | ||||
| -rw-r--r-- | src/chevents.c | 247 | ||||
| -rw-r--r-- | src/chinit.c | 59 | ||||
| -rw-r--r-- | src/chmsg.c | 194 | ||||
| -rw-r--r-- | src/chqueues.c | 478 | ||||
| -rw-r--r-- | src/chschd.c | 205 | ||||
| -rw-r--r-- | src/chsem.c | 376 | ||||
| -rw-r--r-- | src/chserial.c | 195 | ||||
| -rw-r--r-- | src/chsleep.c | 79 | ||||
| -rw-r--r-- | src/chthreads.c | 265 | ||||
| -rw-r--r-- | src/include/ch.h | 97 | ||||
| -rw-r--r-- | src/include/delta.h | 83 | ||||
| -rw-r--r-- | src/include/events.h | 95 | ||||
| -rw-r--r-- | src/include/messages.h | 59 | ||||
| -rw-r--r-- | src/include/queues.h | 172 | ||||
| -rw-r--r-- | src/include/scheduler.h | 81 | ||||
| -rw-r--r-- | src/include/semaphores.h | 82 | ||||
| -rw-r--r-- | src/include/serial.h | 154 | ||||
| -rw-r--r-- | src/include/sleep.h | 43 | ||||
| -rw-r--r-- | src/include/threads.h | 203 | ||||
| -rw-r--r-- | src/templates/chconf.h | 154 | ||||
| -rw-r--r-- | src/templates/chcore.c | 50 | ||||
| -rw-r--r-- | src/templates/chcore.h | 69 | ||||
| -rw-r--r-- | src/templates/chtypes.h | 62 | ||||
| -rw-r--r-- | src/templates/readme.txt | 1 | 
25 files changed, 3587 insertions, 0 deletions
| diff --git a/src/chdelta.c b/src/chdelta.c new file mode 100644 index 000000000..9a4f8b21d --- /dev/null +++ b/src/chdelta.c @@ -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 */
 +
 +/** @} */
 diff --git a/src/chevents.c b/src/chevents.c new file mode 100644 index 000000000..87f990c16 --- /dev/null +++ b/src/chevents.c @@ -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 */
 +
 +/** @} */
 diff --git a/src/chinit.c b/src/chinit.c new file mode 100644 index 000000000..b86626fa6 --- /dev/null +++ b/src/chinit.c @@ -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();
 +}
 +
 +/** @} */
 diff --git a/src/chmsg.c b/src/chmsg.c new file mode 100644 index 000000000..0f71b2216 --- /dev/null +++ b/src/chmsg.c @@ -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 */
 +
 +/** @} */
 diff --git a/src/chqueues.c b/src/chqueues.c new file mode 100644 index 000000000..2cccc3120 --- /dev/null +++ b/src/chqueues.c @@ -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 */
 +
 +/** @} */
 diff --git a/src/chschd.c b/src/chschd.c new file mode 100644 index 000000000..b38fe366f --- /dev/null +++ b/src/chschd.c @@ -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
 +}
 +
 +/** @} */
 diff --git a/src/chsem.c b/src/chsem.c new file mode 100644 index 000000000..1eab23ea4 --- /dev/null +++ b/src/chsem.c @@ -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 */
 +
 +/** @} */
 diff --git a/src/chserial.c b/src/chserial.c new file mode 100644 index 000000000..54c2f9f7e --- /dev/null +++ b/src/chserial.c @@ -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 */
 +
 +/** @} */
 diff --git a/src/chsleep.c b/src/chsleep.c new file mode 100644 index 000000000..9fedd0244 --- /dev/null +++ b/src/chsleep.c @@ -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 */
 +
 +/** @} */
 +
 diff --git a/src/chthreads.c b/src/chthreads.c new file mode 100644 index 000000000..8f7112647 --- /dev/null +++ b/src/chthreads.c @@ -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 */
 +
 +/** @} */
 diff --git a/src/include/ch.h b/src/include/ch.h new file mode 100644 index 000000000..80204bb2d --- /dev/null +++ b/src/include/ch.h @@ -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_ */
 +
 +/** @} */
 diff --git a/src/include/delta.h b/src/include/delta.h new file mode 100644 index 000000000..2ae4d887f --- /dev/null +++ b/src/include/delta.h @@ -0,0 +1,83 @@ +/*
 +    ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
 +
 +    This file is part of ChibiOS/RT.
 +
 +    ChibiOS/RT is free software; you can redistribute it and/or modify
 +    it under the terms of the GNU General Public License as published by
 +    the Free Software Foundation; either version 3 of the License, or
 +    (at your option) any later version.
 +
 +    ChibiOS/RT is distributed in the hope that it will be useful,
 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +    GNU General Public License for more details.
 +
 +    You should have received a copy of the GNU General Public License
 +    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 +*/
 +
 +/**
 + * @addtogroup VirtualTimers
 + * @{
 + */
 +
 +#ifndef _DELTA_H_
 +#define _DELTA_H_
 +
 +#ifdef CH_USE_VIRTUAL_TIMERS
 +
 +/** Virtual Timer callback function.*/
 +typedef void (*t_vtfunc)(void *);
 +
 +typedef struct VirtualTimer VirtualTimer;
 +
 +/**
 + * Virtual Timer descriptor structure.
 + */
 +struct VirtualTimer {
 +    /** Next timer in the delta list.*/
 +    VirtualTimer    *vt_next;
 +    /** Previous timer in the delta list.*/
 +    VirtualTimer    *vt_prev;
 +    /** Time delta before timeout.*/
 +    t_time          vt_dtime;
 +    /** Timer callback function pointer. The pointer is reset to zero after
 +        the callback is invoked.*/
 +    t_vtfunc        vt_func;
 +    /** Timer callback function parameter.*/
 +    void            *vt_par;
 +};
 +
 +/**
 + * Delta List header.
 + * @note The delta list is implemented as a double link bidirectional list in
 + *       order to make the unlink time constant, the reset of a virtual timer
 + *       is often used in the code. An slower implementation using a single
 + *       link list is possible and might be added later with a
 + *       \p CH_OPTIMIZE_SPACE option.
 + */
 +typedef struct {
 +    /** Next timer in the list (the one that will be triggered next).*/
 +    VirtualTimer    *dl_next;
 +    /** Last timer in the list.*/
 +    VirtualTimer    *dl_prev;
 +    /** Not used but it must be set to /p MAXDELTA.*/
 +    t_time          dl_dtime;
 +} DeltaList;
 +
 +
 +extern DeltaList dlist;
 +
 +/*
 + * Virtual Timers APIs.
 + */
 +void chVTInit(void);
 +void chVTSetI(VirtualTimer *vtp, t_time time, t_vtfunc vtfunc, void *par);
 +void chVTResetI(VirtualTimer *vtp);
 +
 +#endif /* CH_USE_VIRTUAL_TIMER */
 +
 +#endif /* _DELTA_H_ */
 +
 +/** @} */
 diff --git a/src/include/events.h b/src/include/events.h new file mode 100644 index 000000000..c5dfe7438 --- /dev/null +++ b/src/include/events.h @@ -0,0 +1,95 @@ +/*
 +    ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
 +
 +    This file is part of ChibiOS/RT.
 +
 +    ChibiOS/RT is free software; you can redistribute it and/or modify
 +    it under the terms of the GNU General Public License as published by
 +    the Free Software Foundation; either version 3 of the License, or
 +    (at your option) any later version.
 +
 +    ChibiOS/RT is distributed in the hope that it will be useful,
 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +    GNU General Public License for more details.
 +
 +    You should have received a copy of the GNU General Public License
 +    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 +*/
 +
 +/**
 + * @addtogroup Events
 + * @{
 + */
 +
 +#ifndef _EVENTS_H_
 +#define _EVENTS_H_
 +
 +#ifdef CH_USE_EVENTS
 +
 +/** All events allowed mask.*/
 +#define ALL_EVENTS -1
 +
 +typedef struct EventListener EventListener;
 +
 +/**
 + * Event Listener structure.
 + */
 +struct EventListener {
 +  /** Next Event Listener registered on the Event Source.*/
 +  EventListener     *el_next;
 +  /** Thread interested in the Event Source.*/
 +  Thread            *el_listener;
 +  /** Event identifier associated by the thread to the Event Source.*/
 +  t_eventid         el_id;
 +};
 +
 +/**
 + * Event Source structure.
 + */
 +typedef struct EventSource {
 +  /** First Event Listener registered on the Event Source.*/
 +  EventListener     *es_next;
 +} EventSource;
 +
 +/** Returns the event mask from the event identifier.*/
 +#define EventMask(eid) (1 << (eid))
 +
 +/**
 + * Initializes an Event Source.
 + * @param esp pointer to the \p EventSource structure
 + * @note Can be called with interrupts disabled or enabled.
 + */
 +#define chEvtInit(esp) \
 +        ((esp)->es_next = (EventListener *)(esp))
 +
 +/**
 + * Verifies if there is at least one \p EventListener registered on the
 + * \p EventSource.
 + * @param esp pointer to the \p EventSource structure
 + * @note Can be called with interrupts disabled or enabled.
 + */
 +#define chEvtIsListening(esp) \
 +  		((esp) != (EventSource *)(esp)->es_next)
 +
 +
 +/** Event Handler callback function.*/
 +typedef void (*t_evhandler)(t_eventid);
 +
 +void chEvtRegister(EventSource *esp, EventListener *elp, t_eventid eid);
 +void chEvtUnregister(EventSource *esp, EventListener *elp);
 +void chEvtClear(t_eventmask mask);
 +void chEvtSend(EventSource *esp);
 +void chEvtSendI(EventSource *esp);
 +t_eventid chEvtWait(t_eventmask ewmask, t_evhandler handlers[]);
 +#ifdef CH_USE_EVENTS_TIMEOUT
 +t_eventid chEvtWaitTimeout(t_eventmask ewmask,
 +                           t_evhandler handlers[],
 +                           t_time time);
 +#endif
 +
 +#endif /* CH_USE_EVENTS */
 +
 +#endif /* _EVENTS_H_ */
 +
 +/** @} */
 diff --git a/src/include/messages.h b/src/include/messages.h new file mode 100644 index 000000000..a6ce409f3 --- /dev/null +++ b/src/include/messages.h @@ -0,0 +1,59 @@ +/*
 +    ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
 +
 +    This file is part of ChibiOS/RT.
 +
 +    ChibiOS/RT is free software; you can redistribute it and/or modify
 +    it under the terms of the GNU General Public License as published by
 +    the Free Software Foundation; either version 3 of the License, or
 +    (at your option) any later version.
 +
 +    ChibiOS/RT is distributed in the hope that it will be useful,
 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +    GNU General Public License for more details.
 +
 +    You should have received a copy of the GNU General Public License
 +    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 +*/
 +
 +/**
 + * @addtogroup Messages
 + * @{
 + */
 +
 +#ifndef _MESSAGES_H_
 +#define _MESSAGES_H_
 +
 +#ifdef CH_USE_MESSAGES
 +
 +/**
 + * Evaluates to TRUE if the thread has pending messages.
 + */
 +#define chMsgIsPendingI(tp) \
 +			((tp)->p_msgqueue.p_next != (Thread *)&(tp)->p_msgqueue)
 +
 +/**
 + * Returns the first message in the queue.
 + */
 +#define chMsgGetI(tp) \
 +			((tp)->p_msgqueue.p_next->p_msg)
 +
 +t_msg chMsgSend(Thread *tp, t_msg msg);
 +t_msg chMsgWait(void);
 +t_msg chMsgGet(void);
 +void chMsgRelease(t_msg msg);
 +
 +#ifdef CH_USE_MESSAGES_EVENT
 +t_msg chMsgSendWithEvent(Thread *tp, t_msg msg, EventSource *esp);
 +#endif
 +
 +#ifdef CH_USE_MESSAGES_TIMEOUT
 +t_msg chMsgSendTimeout(Thread *tp, t_msg msg, t_time time);
 +#endif
 +
 +#endif /* CH_USE_MESSAGES */
 +
 +#endif /* _MESSAGES_H_ */
 +
 +/** @} */
 diff --git a/src/include/queues.h b/src/include/queues.h new file mode 100644 index 000000000..117c6e9e8 --- /dev/null +++ b/src/include/queues.h @@ -0,0 +1,172 @@ +/*
 +    ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
 +
 +    This file is part of ChibiOS/RT.
 +
 +    ChibiOS/RT is free software; you can redistribute it and/or modify
 +    it under the terms of the GNU General Public License as published by
 +    the Free Software Foundation; either version 3 of the License, or
 +    (at your option) any later version.
 +
 +    ChibiOS/RT is distributed in the hope that it will be useful,
 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +    GNU General Public License for more details.
 +
 +    You should have received a copy of the GNU General Public License
 +    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 +*/
 +
 +/**
 + * @addtogroup IOQueues
 + * @{
 + */
 +
 +#ifndef _QUEUES_H_
 +#define _QUEUES_H_
 +
 +/** Queue notification callback type.*/
 +typedef void (*t_qnotify)(void);
 +
 +/** Returned by the queue functions if the operation is successful.*/
 +#define Q_OK        RDY_OK
 +/** Returned by the queue functions if a timeout occurs.*/
 +#define Q_TIMEOUT   RDY_TIMEOUT
 +/** Returned by the queue functions if the queue is reset.*/
 +#define Q_RESET     RDY_RESET
 +/** Returned by the queue functions if the queue is empty.*/
 +#define Q_EMPTY     -3
 +/** Returned by the queue functions if the queue is full.*/
 +#define Q_FULL      -4
 +
 +#ifdef CH_USE_QUEUES
 +/**
 + * I/O queue structure, it is used by both Input and Output Queues,
 + * the difference is on how the semaphore is initialized.
 + */
 +typedef struct {
 +  /** Pointer to the queue buffer.*/
 +  BYTE8             *q_buffer;
 +  /** Pointer to the first location after the buffer.*/
 +  BYTE8             *q_top;
 +  /** Write pointer.*/
 +  BYTE8             *q_wrptr;
 +  /** Read pointer.*/
 +  BYTE8             *q_rdptr;
 +  /** Counter semaphore.*/
 +  Semaphore         q_sem;
 +  /** Data notification callback.*/
 +  t_qnotify         q_notify;
 +} Queue;
 +
 +/** Returns the queue's buffer size.*/
 +#define chQSize(q) \
 +        ((q)->q_top - (q)->q_buffer)
 +
 +/** Returns the used space if used on an Input Queue and the empty space if
 + *  used on an Output Queue.*/
 +#define chQSpace(q) \
 +        ((q)->q_sem.s_cnt)
 +
 +/** Evaluates to TRUE if the specified Input Queue is empty.*/
 +#define chIQIsEmpty(q) \
 +        (chQSpace(q) <= 0)
 +
 +/** Evaluates to TRUE if the specified Input Queue is full.*/
 +#define chIQIsFull(q) \
 +        (chQSpace(q) >= chQSize(q))
 +
 +/** Evaluates to TRUE if the specified Output Queue is empty.*/
 +#define chOQIsEmpty(q) \
 +        (chQSpace(q) >= chQSize(q))
 +
 +/** Evaluates to TRUE if the specified Output Queue is full.*/
 +#define chOQIsFull(q) \
 +        (chQSpace(q) <= 0)
 +
 +/*
 + * Input Queues functions. An Input Queue is usually written into by an
 + * interrupt handler and read from a thread.
 + */
 +void chIQInit(Queue *qp, BYTE8 *buffer, t_size size, t_qnotify inotify);
 +void chIQReset(Queue *qp);
 +t_msg chIQPutI(Queue *qp, BYTE8 b);
 +t_msg chIQGet(Queue *qp);
 +t_size chIQRead(Queue *qp, BYTE8 *buffer, t_size n);
 +#ifdef CH_USE_QUEUES_TIMEOUT
 +t_msg chIQGetTimeout(Queue *qp, t_time time);
 +#endif
 +
 +/*
 + * Output Queues functions. An Output Queue is usually written into by a
 + * thread and read from an interrupt handler.
 + */
 +void chOQInit(Queue *queue, BYTE8 *buffer, t_size size, t_qnotify onotify);
 +void chOQReset(Queue *queue);
 +void chOQPut(Queue *queue, BYTE8 b);
 +t_msg chOQGetI(Queue *queue);
 +t_size chOQWrite(Queue *queue, BYTE8 *buffer, t_size n);
 +#endif  /* CH_USE_QUEUES */
 +
 +#ifdef CH_USE_QUEUES_HALFDUPLEX
 +/**
 + * Half duplex queue structure.
 + */
 +typedef struct {
 +  /** Pointer to the queue buffer.*/
 +  BYTE8             *hdq_buffer;
 +  /** Pointer to the first location after the buffer.*/
 +  BYTE8             *hdq_top;
 +  /** Write pointer.*/
 +  BYTE8             *hdq_wrptr;
 +  /** Read pointer.*/
 +  BYTE8             *hdq_rdptr;
 +  /** Input counter semaphore.*/
 +  Semaphore         hdq_isem;
 +  /** Output counter semaphore.*/
 +  Semaphore         hdq_osem;
 +  /** Input data notification callback.*/
 +  t_qnotify         hdq_inotify;
 +  /** Output data notification callback.*/
 +  t_qnotify         hdq_onotify;
 +} HalfDuplexQueue;
 +
 +/** Returns the queue's buffer size.*/
 +#define chHDQSize(q) \
 +        ((q)->hdq_top - (q)->hdq_buffer)
 +
 +/** Returns the queue space when in transmission mode.*/
 +#define chHDQEmptySpace(q) \
 +        ((q)->hdq_osem.s_cnt)
 +
 +/** Returns the number of the bytes in the queue when in receive mode.*/
 +#define chHDQFilledSpace(q) \
 +        ((q)->hdq_isem.s_cnt)
 +
 +/** Evaluates to TRUE if the queue is in transmit mode.*/
 +#define chHDQIsTransmitting(q) \
 +        (chHDQEmptySpace(q) < chHDQSize(q))
 +
 +/** Evaluates to TRUE if the queue is in receive mode.*/
 +#define chHDQIsReceiving(q) \
 +        (chHDQEmptySpaceQ(q) >= chHDQSize(q))
 +
 +/** Evaluates to TRUE if the receive queue is full.*/
 +#define chHDQIsFullReceive(q) \
 +        (chHDQFilledSpace(q) >= chHDQSize(q))
 +
 +void chHDQInit(HalfDuplexQueue *qp, BYTE8 *buffer, t_size size,
 +               t_qnotify inotify, t_qnotify onotify);
 +t_msg chHDQGetReceive(HalfDuplexQueue *qp);
 +void chHDQPutTransmit(HalfDuplexQueue *qp, BYTE8 b);
 +t_msg chHDQGetTransmitI(HalfDuplexQueue *qp);
 +t_msg chHDQPutReceiveI(HalfDuplexQueue *qp, BYTE8 b);
 +#ifdef CH_USE_QUEUES_TIMEOUT
 +t_msg chHDQGetReceiveTimeout(HalfDuplexQueue *qp, t_time time);
 +#endif
 +
 +#endif /* CH_USE_QUEUES_HALFDUPLEX */
 +
 +#endif /* _QUEUES_H_ */
 +
 +/** @} */
 diff --git a/src/include/scheduler.h b/src/include/scheduler.h new file mode 100644 index 000000000..78fbb4a72 --- /dev/null +++ b/src/include/scheduler.h @@ -0,0 +1,81 @@ +/*
 +    ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
 +
 +    This file is part of ChibiOS/RT.
 +
 +    ChibiOS/RT is free software; you can redistribute it and/or modify
 +    it under the terms of the GNU General Public License as published by
 +    the Free Software Foundation; either version 3 of the License, or
 +    (at your option) any later version.
 +
 +    ChibiOS/RT is distributed in the hope that it will be useful,
 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +    GNU General Public License for more details.
 +
 +    You should have received a copy of the GNU General Public License
 +    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 +*/
 +
 +/**
 + * @addtogroup Scheduler
 + * @{
 + */
 +
 +#ifndef _SCHEDULER_H_
 +#define _SCHEDULER_H_
 +
 +/** Normal \p chSchReadyI() message.*/
 +#define RDY_OK      0
 +/** Returned if the thread was made ready because a timeout.*/
 +#define RDY_TIMEOUT -1
 +/** Returned if the thread was made ready because a reset.*/
 +#define RDY_RESET   -2
 +
 +/**
 + * Ready list header.
 + */
 +typedef struct {
 +  /** Highest priority \p Thread in the list.*/
 +  Thread            *p_next;
 +  /** Lowest priority \p Thread in the list.*/
 +  Thread            *p_prev;
 +  /** Alwas set to \p MAXPRIO.*/
 +  t_prio            p_prio;
 +} ReadyList;
 +
 +/*
 + * Scheduler APIs.
 + */
 +void chSchInit(void);
 +Thread *chSchReadyI(Thread *tp);
 +void chSchGoSleepI(t_tstate newstate);
 +void chSchWakeupI(Thread *tp, t_msg msg);
 +void chSchRescheduleI(void);
 +void chSchDoRescheduleI(void);
 +BOOL chSchRescRequiredI(void);
 +void chSchTimerHandlerI(void);
 +
 +/**
 + * Current thread pointer.
 + * @note Dont use this directly but use the \p chThdSelf()
 + *       instead. Direct use of system global variables is discouraged because
 + *       portability reasons.
 + */
 +#ifdef CH_CURRP_REGISTER_CACHE
 +register Thread *currp asm(CH_CURRP_REGISTER_CACHE);
 +#else
 +extern Thread *currp;
 +#endif
 +
 +/**
 + * System ticks counter.
 + * @note Dont use this directly but use the \p chSysGetTime()
 + *       instead. Direct use of system global variables is discouraged because
 + *       portability reasons.
 + */
 +extern t_time stime;
 +
 +#endif /* _SCHEDULER_H_ */
 +
 +/** @} */
 diff --git a/src/include/semaphores.h b/src/include/semaphores.h new file mode 100644 index 000000000..83d4613de --- /dev/null +++ b/src/include/semaphores.h @@ -0,0 +1,82 @@ +/*
 +    ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
 +
 +    This file is part of ChibiOS/RT.
 +
 +    ChibiOS/RT is free software; you can redistribute it and/or modify
 +    it under the terms of the GNU General Public License as published by
 +    the Free Software Foundation; either version 3 of the License, or
 +    (at your option) any later version.
 +
 +    ChibiOS/RT is distributed in the hope that it will be useful,
 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +    GNU General Public License for more details.
 +
 +    You should have received a copy of the GNU General Public License
 +    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 +*/
 +
 +/**
 + * @addtogroup Semaphores
 + * @{
 + */
 +
 +#ifndef _SEMAPHORES_H_
 +#define _SEMAPHORES_H_
 +
 +#ifdef CH_USE_SEMAPHORES
 +
 +/**
 + * Semaphore structure.
 + */
 +typedef struct {
 +  /** Queue of the threads sleeping on this Semaphore.*/
 +  ThreadsQueue    s_queue;
 +  /** The Semaphore counter.*/
 +  t_semcnt        s_cnt;
 +} Semaphore;
 +
 +void chSemInit(Semaphore *sp, t_semcnt n);
 +void chSemReset(Semaphore *sp, t_semcnt n);
 +void chSemResetI(Semaphore *sp, t_semcnt n);
 +void chSemWait(Semaphore *sp);
 +void chSemWaitS(Semaphore *sp);
 +t_msg chSemWaitTimeout(Semaphore *sp, t_time time);
 +t_msg chSemWaitTimeoutS(Semaphore *sp, t_time time);
 +void chSemSignal(Semaphore *sp);
 +void chSemSignalI(Semaphore *sp);
 +void chSignalWait(Semaphore *sps, Semaphore *spw);
 +
 +#ifdef CH_USE_RT_SEMAPHORES
 +void chSemRaisePrioWait(Semaphore *sp);
 +void chSemLowerPrioSignal(Semaphore *sp);
 +void chSemRaisePrioSignalWait(Semaphore *sps, Semaphore *spw);
 +void chSemLowerPrioSignalWait(Semaphore *sps, Semaphore *spw);
 +#endif
 +
 +/**
 + * Decreases the semaphore counter, this macro can be used when it is ensured
 + * that the counter would not become negative.
 + */
 +#define chSemFastWaitS(sp) \
 +				((sp)->s_cnt--)
 +
 +/**
 + * Increases the semaphore counter, this macro can be used when the counter is
 + * not negative.
 + */
 +#define chSemFastSignalI(sp) \
 +				((sp)->s_cnt++)
 +
 +/**
 + * Returns the semaphore counter current value.
 + */
 +#define chSemGetCounter(sp) \
 +				((sp)->s_cnt)
 +
 +#endif /* CH_USE_SEMAPHORES */
 +
 +#endif /* _SEM_H_ */
 +
 +/** @} */
 diff --git a/src/include/serial.h b/src/include/serial.h new file mode 100644 index 000000000..3d33975b1 --- /dev/null +++ b/src/include/serial.h @@ -0,0 +1,154 @@ +/*
 +    ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
 +
 +    This file is part of ChibiOS/RT.
 +
 +    ChibiOS/RT is free software; you can redistribute it and/or modify
 +    it under the terms of the GNU General Public License as published by
 +    the Free Software Foundation; either version 3 of the License, or
 +    (at your option) any later version.
 +
 +    ChibiOS/RT is distributed in the hope that it will be useful,
 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +    GNU General Public License for more details.
 +
 +    You should have received a copy of the GNU General Public License
 +    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 +*/
 +
 +/**
 + * @addtogroup Serial
 + * @{
 + */
 +
 +#ifndef _SERIAL_H_
 +#define _SERIAL_H_
 +
 +/** No pending conditions.*/
 +#define SD_NO_ERROR               0
 +/** Connection happened.*/
 +#define SD_CONNECTED              1
 +/** Disconnection happened.*/
 +#define SD_DISCONNECTED           2
 +/** Parity error happened.*/
 +#define SD_PARITY_ERROR           4
 +/** Framing error happened.*/
 +#define SD_FRAMING_ERROR          8
 +/** Overflow happened.*/
 +#define SD_OVERRUN_ERROR          16
 +/** Break detected.*/
 +#define SD_BREAK_DETECTED         32
 +
 +/** Serial Driver condition flags type.*/
 +typedef UWORD16 t_dflags;
 +
 +#ifdef CH_USE_SERIAL_FULLDUPLEX
 +
 +/**
 + * Full Duplex Serial Driver main structure.
 + */
 +typedef struct {
 +
 +  /** Input queue. Incoming data can be read from this queue by using the
 +   *  queues APIs.*/
 +  Queue             sd_iqueue;
 +  /** Data Available \p EventSource. This event is generated when some incoming
 +   *  data is inserted in the Input \p Queue.*/
 +  EventSource       sd_ievent;
 +
 +  /** Output queue. Outgoing data can be written to this Output \p Queue by
 +   *   using the queues APIs.*/
 +  Queue             sd_oqueue;
 +  /** Data Transmitted \p EventSource. This event is generated when the
 +   *  Output \p Queue is empty.*/
 +  EventSource       sd_oevent;
 +
 +  /** I/O driver status flags. This field should not be read directly but
 +   *  the \p chFDDGetAndClearFlags() funtion should be used instead.*/
 +  t_dflags          sd_flags;
 +  /** Status Change \p EventSource. This event is generated when a
 +   *  condition flag was changed.*/
 +  EventSource       sd_sevent;
 +} FullDuplexDriver;
 +
 +void chFDDInit(FullDuplexDriver *sd,
 +               BYTE8 *ib, t_size isize, t_qnotify inotify,
 +               BYTE8 *ob, t_size osize, t_qnotify onotify);
 +void chFDDIncomingDataI(FullDuplexDriver *sd, BYTE8 b);
 +t_msg chFDDRequestDataI(FullDuplexDriver *sd);
 +void chFDDAddFlagsI(FullDuplexDriver *sd, t_dflags mask);
 +t_dflags chFDDGetAndClearFlags(FullDuplexDriver *sd);
 +
 +/** @see chIQRead()*/
 +#define chFDDRead(sd, b, n) \
 +        chIQRead(&(sd)->sd_iqueue, b, n)
 +
 +/** @see chOQWrite()*/
 +#define chFDDWrite(sd, b, n) \
 +        chOQWrite(&(sd)->sd_oqueue, b, n)
 +
 +/** @see chIQGet()*/
 +#define chFDDGet(sd) \
 +        chIQGet(&(sd)->sd_iqueue)
 +
 +/** @see chIQGetTimeout()*/
 +#define chFDDGetTimeout(sd, t) \
 +        chIQGetTimeout(&(sd)->sd_iqueue, t)
 +
 +/** @see chOQPut()*/
 +#define chFDDPut(sd, b) \
 +        chOQPut(&(sd)->sd_oqueue, b)
 +
 +#endif /* CH_USE_SERIAL_FULLDUPLEX */
 +
 +#ifdef CH_USE_SERIAL_HALFDUPLEX
 +
 +/**
 + * Full Duplex Serial Driver main structure.
 + */
 +typedef struct {
 +
 +  /** Data queue. Transmit/receive \p HalfDuplexQueue.*/
 +  HalfDuplexQueue   sd_queue;
 +  /** Data Available \p EventSource. This event is generated when some
 +   *  incoming data is inserted in the receive queue.*/
 +  EventSource       sd_ievent;
 +  /** Data Transmitted \p EventSource. This event is generated when the
 +   *  transmission queue is empty and the driver can either transmit more
 +   *  data or enter receive mode.*/
 +  EventSource       sd_oevent;
 +
 +  /** I/O driver status flags. This field should not be read directly but
 +   *  the \p chHDDGetAndClearFlags() funtion should be used
 +   *  instead.*/
 +  t_dflags          sd_flags;
 +  /** Status Change Event Source. This event is generated when a condition
 +   *  flag was changed.*/
 +  EventSource       sd_sevent;
 +} HalfDuplexDriver;
 +
 +void chHDDInit(HalfDuplexDriver *sd, BYTE8 *b, t_size size,
 +              t_qnotify inotify, t_qnotify onotify);
 +void chHDDIncomingDataI(HalfDuplexDriver *sd, BYTE8 b);
 +t_msg chHDDRequestDataI(HalfDuplexDriver *sd);
 +void chHDDAddFlagsI(HalfDuplexDriver *sd, t_dflags mask);
 +t_dflags chHDDGetAndClearFlags(HalfDuplexDriver *sd);
 +
 +/** @see chHDQGetReceive()*/
 +#define chHDDGetReceive(sd) \
 +        chHDQGetReceive(&(sd)->sd_queue)
 +
 +/** @see chHDQGetReceiveTimeout()*/
 +#define chHDDGetReceiveTimeout(sd, t) \
 +        chHDQGetReceiveTimeout(&(sd)->sd_queue, t)
 +
 +/** @see chHDQPutTransmit()*/
 +#define chHDDPutTransmit(sd, b) \
 +        chHDQPutTransmit(&(sd)->sd_queue, b)
 +
 +#endif /* CH_USE_SERIAL_HALFDUPLEX */
 +
 +#endif /* _SERIAL_H_ */
 +
 +/** @} */
 diff --git a/src/include/sleep.h b/src/include/sleep.h new file mode 100644 index 000000000..265500908 --- /dev/null +++ b/src/include/sleep.h @@ -0,0 +1,43 @@ +/*
 +    ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
 +
 +    This file is part of ChibiOS/RT.
 +
 +    ChibiOS/RT is free software; you can redistribute it and/or modify
 +    it under the terms of the GNU General Public License as published by
 +    the Free Software Foundation; either version 3 of the License, or
 +    (at your option) any later version.
 +
 +    ChibiOS/RT is distributed in the hope that it will be useful,
 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +    GNU General Public License for more details.
 +
 +    You should have received a copy of the GNU General Public License
 +    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 +*/
 +
 +/**
 + * @addtogroup Time
 + * @{
 + */
 +
 +#ifndef _SLEEP_H_
 +#define _SLEEP_H_
 +
 +#ifdef CH_USE_SLEEP
 +
 +void chThdSleep(t_time time);
 +
 +#ifdef CH_USE_SYSTEMTIME
 +
 +void chThdSleepUntil(t_time time);
 +t_time chSysGetTime(void);
 +
 +#endif /* CH_USE_SYSTEMTIME */
 +
 +#endif /* CH_USE_SLEEP */
 +
 +#endif /* _SLEEP_H_ */
 +
 +/** @} */
 diff --git a/src/include/threads.h b/src/include/threads.h new file mode 100644 index 000000000..d8937433f --- /dev/null +++ b/src/include/threads.h @@ -0,0 +1,203 @@ +/*
 +    ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
 +
 +    This file is part of ChibiOS/RT.
 +
 +    ChibiOS/RT is free software; you can redistribute it and/or modify
 +    it under the terms of the GNU General Public License as published by
 +    the Free Software Foundation; either version 3 of the License, or
 +    (at your option) any later version.
 +
 +    ChibiOS/RT is distributed in the hope that it will be useful,
 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +    GNU General Public License for more details.
 +
 +    You should have received a copy of the GNU General Public License
 +    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 +*/
 +
 +/**
 + * @addtogroup Threads
 + * @{
 + */
 +
 +#ifndef _THREADS_H_
 +#define _THREADS_H_
 +
 +#define isempty(qp)     ((qp)->p_next == (Thread *)(qp))
 +#define notempty(qp)    ((qp)->p_next != (Thread *)(qp))
 +#define firstprio(qp)   ((qp)->p_next->p_prio)
 +#define lastprio(qp)    ((qp)->p_prev->p_prio)
 +
 +/**
 + * Generic threads queue header and element.
 + */
 +typedef struct {
 +  /** First \p Thread in the queue.*/
 +  Thread            *p_next;
 +  /** Last \p Thread in the queue.*/
 +  Thread            *p_prev;
 +} ThreadsQueue;
 +
 +/**
 + * Structure representing a thread.
 + * @note Not all the listed fields are always needed, by switching off some
 + *       not needed ChibiOS/RT subsystems it is possible to save RAM space by
 + *       shrinking the \p Thread structure.
 + */
 +struct Thread {
 +  /** Next \p Thread in the threads list.*/
 +  Thread            *p_next;
 +  /** Previous \p Thread in the threads list.*/
 +  Thread            *p_prev;
 +  /* End of the fields shared with the ThreadsQueue structure. */
 +  /** The thread priority.*/
 +  t_prio            p_prio;
 +  /* End of the fields shared with the ReadyList structure. */
 +  /** Current thread state.*/
 +  t_tstate          p_state;
 +  /** Mode flags.*/
 +  t_tmode           p_flags;
 +  /*
 +   * The following fields are merged in an union because they are all
 +   * state-specific fields. This trick saves some extra space for each
 +   * thread in the system.
 +   */
 +  union {
 +    /** Thread wakeup code, normally set to \p RDY_OK by the \p chSchReadyI()
 +     * (only while in \p PRCURR or \p PRREADY states).*/
 +    t_msg           p_rdymsg;
 +    /** The thread exit code (only while in \p PREXIT state).*/
 +    t_msg           p_exitcode;
 +#ifdef CH_USE_EVENTS
 +    /** Enabled events mask (only while in \p PRWTEVENT state).*/
 +    t_eventmask     p_ewmask;
 +#endif
 +#ifdef CH_USE_MESSAGES
 +    /** Message (only while in \p PRSNDMSG state).*/
 +    t_msg           p_msg;
 +#endif
 +  };
 +  /** Machine dependent processor context.*/
 +  Context                       p_ctx;
 +  /*
 +   * Start of the optional fields. Note, the null thread may also let its
 +   * stack overwrite the following fields since it never uses semaphores,
 +   * events, messages, exit etc, this can save some space on RAM starved
 +   * systems, be caruful in doing so.
 +   */
 +#ifdef CH_USE_WAITEXIT
 +  /** The queue of the threads waiting for this thread termination.*/
 +  ThreadsQueue      p_waiting;
 +#endif
 +#ifdef CH_USE_EXIT_EVENT
 +  /** The thread termination \p EventSource.*/
 +  EventSource       p_exitesource;
 +#endif
 +#ifdef CH_USE_MESSAGES
 +  ThreadsQueue      p_msgqueue;
 +#endif
 +#ifdef CH_USE_EVENTS
 +  /** Pending events mask.*/
 +  t_eventmask       p_epending;
 +#endif
 +#ifdef CH_USE_RT_SEMAPHORES
 +  /** Priority backup after acquiring a RT semaphore.*/
 +  t_prio            p_bakprio;
 +  /** RT semaphores depth counter.*/
 +  WORD16            p_rtcnt;
 +#endif
 +};
 +
 +/** Thread state: Reserved.*/
 +#define PRFREE      0
 +/** Thread state: Current.*/
 +#define PRCURR      1
 +/** Thread state: Thread in the ready list.*/
 +#define PRREADY     2
 +/** Thread state: Thread created in suspended state.*/
 +#define PRSUSPENDED 3
 +/** Thread state: Waiting on a semaphore.*/
 +#define PRWTSEM     4
 +/** Thread state: Waiting in \p chThdSleep() or \p chThdSleepUntil().*/
 +#define PRSLEEP     5
 +/** Thread state: Waiting in \p chThdWait().*/
 +#define PRWAIT      6
 +/** Thread state: Waiting in \p chEvtWait().*/
 +#define PRWTEVENT   7
 +/** Thread state: Waiting in \p chMsgSend().*/
 +#define PRSNDMSG    8
 +/** Thread state: Waiting in \p chMsgWait().*/
 +#define PRWTMSG     9
 +/** Thread state: After termination.*/
 +#define PREXIT      10
 +
 +/** Thread option: Termination requested flag.*/
 +#define P_TERMINATE 1
 +/** Thread option: Create suspended thread.*/
 +#define P_SUSPENDED 2
 +
 +/** Idle thread priority.*/
 +#define IDLEPRIO    0
 +/** Lowest user priority.*/
 +#define LOWPRIO     1
 +/** Normal user priority.*/
 +#define NORMALPRIO  128
 +/** Highest user priority.*/
 +#define HIGHPRIO    255
 +/** Boosted base priority.*/
 +#define MEPRIO      256
 +/** Absolute priority.*/
 +#define ABSPRIO     512
 +
 +/* Not an API, don't use into the application code.*/
 +void _InitThread(t_prio prio, t_tmode mode, Thread *tp);
 +
 +/** Thread function.*/
 +typedef t_msg (*t_tfunc)(void *);
 +
 +/*
 + * Threads Lists functions.
 + */
 +#ifndef CH_OPTIMIZE_SPEED
 +void enqueue(Thread *tp, ThreadsQueue *tqp);
 +Thread *dequeue(Thread *tp);
 +#else
 +static INLINE Thread *dequeue(Thread *tp) {
 +
 +  tp->p_prev->p_next = tp->p_next;
 +  tp->p_next->p_prev = tp->p_prev;
 +  return tp;
 +}
 +
 +static INLINE void enqueue(Thread *tp, ThreadsQueue *tqp) {
 +
 +  tp->p_next = (Thread *)tqp;
 +  tp->p_prev = tqp->p_prev;
 +  tqp->p_prev->p_next = tp;
 +  tqp->p_prev = tp;
 +}
 +#endif
 +
 +/*
 + * Threads APIs.
 + */
 +#define chThdSelf() currp
 +Thread *chThdCreate(t_prio prio, t_tmode mode, void *workspace,
 +                    t_size wsize, t_tfunc pf, void *arg);
 +void chThdResume(Thread *tp);
 +void chThdTerminate(Thread *tp);
 +BOOL chThdShouldTerminate(void);
 +BOOL chThdTerminated(Thread *tp);
 +void chThdExit(t_msg msg);
 +#ifdef CH_USE_WAITEXIT
 +t_msg chThdWait(Thread *tp);
 +#endif
 +#ifdef CH_USE_EXIT_EVENT
 +EventSource *chThdGetExitEventSource(Thread *tp);
 +#endif
 +
 +#endif  /* _THREADS_H_ */
 +
 +/** @} */
 diff --git a/src/templates/chconf.h b/src/templates/chconf.h new file mode 100644 index 000000000..abb996899 --- /dev/null +++ b/src/templates/chconf.h @@ -0,0 +1,154 @@ +/*
 +    ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
 +
 +    This file is part of ChibiOS/RT.
 +
 +    ChibiOS/RT is free software; you can redistribute it and/or modify
 +    it under the terms of the GNU General Public License as published by
 +    the Free Software Foundation; either version 3 of the License, or
 +    (at your option) any later version.
 +
 +    ChibiOS/RT is distributed in the hope that it will be useful,
 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +    GNU General Public License for more details.
 +
 +    You should have received a copy of the GNU General Public License
 +    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 +*/
 +
 +/**
 + * @addtogroup Config
 + * @{
 + */
 +
 +#ifndef _CHCONF_H_
 +#define _CHCONF_H_
 +
 +/*
 + * NOTE: this is just documentation for doxigen, the real configuration file
 + * is the one into the project directories.
 + */
 +
 +/** Configuration option: if specified then time efficient rather than space
 + *  efficient code is used when two possible implementations exist, note
 + *  that this is not related to the compiler optimization options.*/
 +#define CH_OPTIMIZE_SPEED
 +
 +/** Configuration option: if specified then the Virtual Timers subsystem is
 + *  included in the kernel.*/
 +#define CH_USE_VIRTUAL_TIMERS
 +
 +/** Configuration option: if specified then the System Timer subsystem is
 + *  included in the kernel.*/
 +#define CH_USE_SYSTEMTIME
 +
 +/** Configuration option: if specified then the \p chThdSleep() function is
 + *  included in the kernel.
 + * @note requires \p CH_USE_VIRTUAL_TIMERS.*/
 +#define CH_USE_SLEEP
 +
 +/** Configuration option: if specified then the \p chThdResume()
 + *  function is included in the kernel.*/
 +#define CH_USE_RESUME
 +
 +/** Configuration option: if specified then the \p chThdTerminate()
 + *  and \p chThdShouldTerminate() functions are included in the kernel.*/
 +#define CH_USE_TERMINATE
 +
 +/** Configuration option: if specified then the \p chThdWait() function
 + *  is included in the kernel.*/
 +#define CH_USE_WAITEXIT
 +
 +/** Configuration option: if specified then the Semaphores APIs are included
 + *  in the kernel.*/
 +#define CH_USE_SEMAPHORES
 +
 +/** Configuration option: if specified then the Semaphores with timeout APIs
 + *  are included in the kernel.
 + * @note requires \p CH_USE_SEMAPHORES.
 + * @note requires \p CH_USE_VIRTUAL_TIMERS.*/
 +#define CH_USE_SEMAPHORES_TIMEOUT
 +
 +/** Configuration option: if specified then the Semaphores APIs with priority
 + *  shift are included in the kernel.
 + * @note requires \p CH_USE_SEMAPHORES.*/
 +#define CH_USE_RT_SEMAPHORES
 +
 +/** Configuration option: if specified then the Events APIs are included in
 + *  the kernel.*/
 +#define CH_USE_EVENTS
 +
 +/** Configuration option: if specified then the \p chEvtWaitTimeout()
 + *  function is included in the kernel.
 + * @note requires \p CH_USE_EVENTS.
 + * @note requires \p CH_USE_VIRTUAL_TIMERS.*/
 +#define CH_USE_EVENTS_TIMEOUT
 +
 +/** Configuration option: if specified then the Synchronous Messages APIs are
 + *  included in the kernel.*/
 +#define CH_USE_MESSAGES
 +
 +/** Configuration option: if specified then the \p chMsgSendTimeout()
 + *  function is included in the kernel.
 + * @note requires \p CH_USE_MESSAGES.
 + * @note requires \p CH_USE_VIRTUAL_TIMERS.*/
 +#define CH_USE_MESSAGES_TIMEOUT
 +
 +/** Configuration option: if specified then the \p chMsgSendWithEvent()
 + *  function is included in the kernel.
 + * @note requires \p CH_USE_MESSAGES.
 + * @note requires \p CH_USE_VIRTUAL_TIMERS.*/
 +#define CH_USE_MESSAGES_EVENT
 +
 +/** Configuration option: if specified then the
 + *  \p chThdGetExitEventSource() function is included in the kernel.
 + * @note requires \p CH_USE_MESSAGES.
 + * @note requires \p CH_USE_EVENTS.*/
 +#define CH_USE_EXIT_EVENT
 +
 +/** Configuration option: if specified then the I/O queues APIs are included
 + *  in the kernel.*/
 +#define CH_USE_QUEUES
 +
 +/** Configuration option: if specified then the halfduplex queue APIs are
 + *  included in the kernel.*/
 +#define CH_USE_QUEUES_HALFDUPLEX
 +
 +/** Configuration option: if specified then the I/O queues with timeout
 + *  APIs are included in the kernel.
 + * @note requires \p CH_USE_SEMAPHORES_TIMEOUT.*/
 +#define CH_USE_QUEUES_TIMEOUT
 +
 +/** Configuration option: if specified then the full duplex serial driver APIs
 + *  are included in the kernel.*/
 +#define CH_USE_SERIAL_FULLDUPLEX
 +
 +/** Configuration option: if specified then the half duplex serial driver APIs
 + *  are included in the kernel.*/
 +#define CH_USE_SERIAL_HALFDUPLEX
 +
 +/** Configuration option: Frequency of the system timer that drives the system
 + *  ticks. This also defines the system time unit.*/
 +#define CH_FREQUENCY 100
 +
 +/** Configuration option: This constant is the number of ticks allowed for the
 + *  threads before preemption occurs.*/
 +#define CH_TIME_QUANTUM 10
 +
 +/** Configuration option: Defines a CPU register to be used as storage for the
 + *  global \p currp variable. Caching this variable in a register can greatly
 + *  improve both space and time efficiency of the generated code. Another side
 + *  effect is that one less register has to be saved during the context switch
 + *  resulting in lower RAM usage and faster code.
 + *  @note This option is only useable with the GCC compiler and is only useful
 + *        on processors with many registers like ARM cores.
 + *  @note If this option is enabled then ALL the libraries linked to the
 + *        ChibiOS/RT code <b>must</b> be recompiled with the GCC option \p
 + *        -ffixed-\<reg\>.
 + */
 +#define CH_CURRP_REGISTER_CACHE "reg"
 +
 +#endif  /* _CHCONF_H_ */
 +
 +/** @} */
 diff --git a/src/templates/chcore.c b/src/templates/chcore.c new file mode 100644 index 000000000..29a809378 --- /dev/null +++ b/src/templates/chcore.c @@ -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) {}
 +
 +/** @} */
 diff --git a/src/templates/chcore.h b/src/templates/chcore.h new file mode 100644 index 000000000..895e2b685 --- /dev/null +++ b/src/templates/chcore.h @@ -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_ */
 +
 +/** @} */
 diff --git a/src/templates/chtypes.h b/src/templates/chtypes.h new file mode 100644 index 000000000..0d6547311 --- /dev/null +++ b/src/templates/chtypes.h @@ -0,0 +1,62 @@ +/*
 +    ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
 +
 +    This file is part of ChibiOS/RT.
 +
 +    ChibiOS/RT is free software; you can redistribute it and/or modify
 +    it under the terms of the GNU General Public License as published by
 +    the Free Software Foundation; either version 3 of the License, or
 +    (at your option) any later version.
 +
 +    ChibiOS/RT is distributed in the hope that it will be useful,
 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +    GNU General Public License for more details.
 +
 +    You should have received a copy of the GNU General Public License
 +    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 +*/
 +
 +/**
 + * @addtogroup Core
 + * @{
 + */
 +
 +#ifndef _CHTYPES_H_
 +#define _CHTYPES_H_
 +
 +/*
 + * Generic types often dependant on the compiler.
 + */
 +#define BOOL        char
 +#define BYTE8       unsigned char
 +#define WORD16      short
 +#define UWORD16     unsigned short
 +#define LONG32      int
 +#define ULONG32     unsigned int
 +#define PTR_EQ      int
 +
 +#define INT_REQUIRED_STACK 0
 +
 +typedef BYTE8       t_tmode;
 +typedef BYTE8       t_tstate;
 +typedef WORD16      t_prio;
 +typedef PTR_EQ      t_msg;
 +typedef LONG32      t_eventid;
 +typedef ULONG32     t_eventmask;
 +typedef ULONG32     t_time;
 +typedef LONG32      t_semcnt;
 +typedef ULONG32     t_size;
 +
 +#define MINPRIO     0x8000
 +#define MAXPRIO     0x7fff
 +
 +#define MINDELTA    0
 +#define MAXDELTA    0xffff
 +
 +#define THREAD
 +#define INLINE      inline
 +
 +#endif /* _CHTYPES_H_ */
 +
 +/** @} */
 diff --git a/src/templates/readme.txt b/src/templates/readme.txt new file mode 100644 index 000000000..c7dd925d9 --- /dev/null +++ b/src/templates/readme.txt @@ -0,0 +1 @@ +Files that need to be copied in each project/port directory and configured.
 | 
