aboutsummaryrefslogtreecommitdiffstats
path: root/os/kernel
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2009-08-16 13:07:24 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2009-08-16 13:07:24 +0000
commit1ea7355d85e316aadfd90468b3e808bb3dc95ee9 (patch)
tree7d9c3cd8733553982b9d0a55e1ddff036a6d9b4c /os/kernel
parent51e3bee83961243f5f0ba01537630f5a3d070c36 (diff)
downloadChibiOS-1ea7355d85e316aadfd90468b3e808bb3dc95ee9.tar.gz
ChibiOS-1ea7355d85e316aadfd90468b3e808bb3dc95ee9.tar.bz2
ChibiOS-1ea7355d85e316aadfd90468b3e808bb3dc95ee9.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1073 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/kernel')
-rw-r--r--os/kernel/include/ch.h89
-rw-r--r--os/kernel/include/channels.h292
-rw-r--r--os/kernel/include/condvars.h80
-rw-r--r--os/kernel/include/debug.h149
-rw-r--r--os/kernel/include/events.h145
-rw-r--r--os/kernel/include/heap.h43
-rw-r--r--os/kernel/include/inline.h72
-rw-r--r--os/kernel/include/lists.h92
-rw-r--r--os/kernel/include/mailboxes.h126
-rw-r--r--os/kernel/include/mempools.h82
-rw-r--r--os/kernel/include/messages.h59
-rw-r--r--os/kernel/include/mutexes.h84
-rw-r--r--os/kernel/include/queues.h218
-rw-r--r--os/kernel/include/scheduler.h110
-rw-r--r--os/kernel/include/semaphores.h99
-rw-r--r--os/kernel/include/serial.h217
-rw-r--r--os/kernel/include/sys.h184
-rw-r--r--os/kernel/include/threads.h269
-rw-r--r--os/kernel/include/vt.h125
-rw-r--r--os/kernel/kernel.mk13
-rw-r--r--os/kernel/readme.txt1
-rw-r--r--os/kernel/src/chcond.c227
-rw-r--r--os/kernel/src/chdebug.c81
-rw-r--r--os/kernel/src/chevents.c392
-rw-r--r--os/kernel/src/chheap.c276
-rw-r--r--os/kernel/src/chlists.c111
-rw-r--r--os/kernel/src/chmboxes.c244
-rw-r--r--os/kernel/src/chmempools.c112
-rw-r--r--os/kernel/src/chmsg.c125
-rw-r--r--os/kernel/src/chmtx.c299
-rw-r--r--os/kernel/src/chqueues.c304
-rw-r--r--os/kernel/src/chschd.c242
-rw-r--r--os/kernel/src/chsem.c257
-rw-r--r--os/kernel/src/chserial.c168
-rw-r--r--os/kernel/src/chsys.c129
-rw-r--r--os/kernel/src/chthreads.c381
-rw-r--r--os/kernel/src/chvt.c116
37 files changed, 6013 insertions, 0 deletions
diff --git a/os/kernel/include/ch.h b/os/kernel/include/ch.h
new file mode 100644
index 000000000..0584b167e
--- /dev/null
+++ b/os/kernel/include/ch.h
@@ -0,0 +1,89 @@
+/*
+ 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/>.
+*/
+
+/**
+ * @file ch.h
+ * @brief ChibiOS/RT main include file, it includes everything else.
+ * @addtogroup Kernel
+ * @{
+ */
+
+#ifndef _CH_H_
+#define _CH_H_
+
+/**
+ * ChibiOS/RT identification macro.
+ */
+#define _CHIBIOS_RT_
+
+/**
+ * Kernel version string.
+ */
+#define CH_KERNEL_VERSION "1.3.2unstable"
+
+/**
+ * Kernel version major number.
+ */
+#define CH_KERNEL_MAJOR 1
+
+/**
+ * Kernel version minor number.
+ */
+#define CH_KERNEL_MINOR 3
+
+/**
+ * Kernel version patch number.
+ */
+#define CH_KERNEL_PATCH 2
+
+/*
+ * Common values.
+ */
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE (!FALSE)
+#endif
+
+#include <chconf.h>
+#include <chtypes.h>
+#include "lists.h"
+#include <chcore.h>
+#include "sys.h"
+#include "vt.h"
+#include "scheduler.h"
+#include "semaphores.h"
+#include "mutexes.h"
+#include "condvars.h"
+#include "events.h"
+#include "messages.h"
+#include "mailboxes.h"
+#include "heap.h"
+#include "mempools.h"
+#include "threads.h"
+#include "inline.h"
+#include "queues.h"
+#include "channels.h"
+#include "serial.h"
+#include "debug.h"
+
+#endif /* _CH_H_ */
+
+/** @} */
diff --git a/os/kernel/include/channels.h b/os/kernel/include/channels.h
new file mode 100644
index 000000000..a1c538f62
--- /dev/null
+++ b/os/kernel/include/channels.h
@@ -0,0 +1,292 @@
+/*
+ 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/>.
+*/
+
+/**
+ * @file channels.h
+ * @brief I/O channels
+ * @addtogroup Channels
+ * @{
+ */
+
+#ifndef _CHANNELS_H_
+#define _CHANNELS_H_
+
+/**
+ * @brief @p BaseChannel specific methods.
+ */
+struct _base_channel_methods {
+ /**
+ * @brief Channel output check.
+ * @see chIOPutWouldBlock()
+ */
+ bool_t (*putwouldblock)(void *instance);
+ /**
+ * @brief Channel input check.
+ * @see chIOGetWouldBlock()
+ */
+ bool_t (*getwouldblock)(void *instance);
+ /**
+ * @brief Channel put method with timeout specification.
+ * @see chIOPut()
+ */
+ msg_t (*put)(void *instance, uint8_t b, systime_t timeout);
+ /**
+ * @brief Channel get method with timeout specification.
+ * @see chIOGet()
+ */
+ msg_t (*get)(void *instance, systime_t timeout);
+};
+
+/**
+ * @brief @p BaseChannel specific data.
+ * @note It is empty because @p BaseChannel is only an interface without
+ * implementation.
+ */
+struct _base_channel_data {
+};
+
+/**
+ * @brief @p BaseChannel virtual methods table.
+ */
+struct BaseChannelVMT {
+ /**
+ * @p BaseChannel class specific methods.
+ */
+ struct _base_channel_methods m0;
+};
+
+/**
+ * @brief Base channel class.
+ * @details This class represents a generic, byte-wide, I/O channel.
+ */
+typedef struct {
+ /**
+ * Virtual Methods Table.
+ */
+ const struct BaseChannelVMT *vmt;
+ /**
+ * @p BaseChannel class specific data.
+ */
+ struct _base_channel_data d0;
+} BaseChannel;
+
+/**
+ * @brief Channel output check.
+ * @details This function verifies if a subsequent @p chIOPut() would block.
+ *
+ * @param[in] ip pointer to a @p BaseChannel or derived class
+ * @return The output queue status:
+ * @retval FALSE if the output queue has space and would not block a write
+ * operation.
+ * @retval TRUE if the output queue is full and would block a write operation.
+ */
+#define chIOPutWouldBlock(ip) ((ip)->vmt->m0.putwouldblock(ip))
+
+/**
+ * @brief Channel input check.
+ * @details This function verifies if a subsequent @p chIOGett() would block.
+ *
+ * @param[in] ip pointer to a @p BaseChannel or derived class
+ * @return The input queue status:
+ * @retval FALSE if the input queue contains data and would not block a read
+ * operation.
+ * @retval TRUE if the input queue is empty and would block a read operation.
+ */
+#define chIOGetWouldBlock(ip) ((ip)->vmt->m0.getwouldblock(ip))
+
+/**
+ * @brief Channel blocking byte write.
+ * @details This function writes a byte value to a channel. If the channel
+ * is not ready to accept data then the calling thread is suspended.
+ *
+ * @param[in] ip pointer to a @p BaseChannel or derived class
+ * @param[in] b the byte value to be written to the channel
+ * @return The operation status:
+ * @retval Q_OK if the operation succeeded.
+ * @retval Q_RESET if the channel associated queue (if any) was reset.
+ */
+#define chIOPut(ip, b) ((ip)->vmt->m0.put(ip, b, TIME_INFINITE))
+
+/**
+ * @brief Channel blocking byte write with timeout.
+ * @details This function writes a byte value to a channel. If the channel
+ * is not ready to accept data then the calling thread is suspended.
+ *
+ * @param[in] ip pointer to a @p BaseChannel or derived class
+ * @param[in] b the byte value to be written to the channel
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status:
+ * @retval Q_OK if the operation succeeded.
+ * @retval Q_TIMEOUT if the specified time expired.
+ * @retval Q_RESET if the channel associated queue (if any) was reset.
+ */
+#define chIOPutTimeout(ip, b, timeout) ((ip)->vmt->m0.put(ip, b, timeout))
+
+/**
+ * @brief Channel blocking byte read.
+ * @details This function reads a byte value from a channel. If the data
+ * is not available then the calling thread is suspended.
+ *
+ * @param[in] ip pointer to a @p BaseChannel or derived class
+ * @return A byte value from the queue or:
+ * @retval Q_RESET if the channel associated queue (if any) was reset.
+ */
+#define chIOGet(ip) ((ip)->vmt->m0.get(ip, TIME_INFINITE))
+
+/**
+ * @brief Channel blocking byte read with timeout.
+ * @details This function reads a byte value from a channel. If the data
+ * is not available then the calling thread is suspended.
+ *
+ * @param[in] ip pointer to a @p BaseChannel or derived class
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return A byte value from the queue or:
+ * @retval Q_TIMEOUT if the specified time expired.
+ * @retval Q_RESET if the channel associated queue (if any) was reset.
+ */
+#define chIOGetTimeout(ip, timeout) ((ip)->vmt->m0.get(ip, timeout))
+
+#if CH_USE_EVENTS
+/**
+ * @brief @p BaseAsynchronousChannel specific methods.
+ */
+struct _base_asynchronous_channel_methods {
+ /**
+ * Channel asynchronous write method.
+ * @see chIOWrite()
+ */
+ size_t (*write)(void *instance, uint8_t *buffer, size_t n);
+ /**
+ * Channel asynchronous read method.
+ * @see chIORead()
+ */
+ size_t (*read)(void *instance, uint8_t *buffer, size_t n);
+};
+
+/**
+ * @brief @p BaseAsynchronousChannel specific data.
+ */
+struct _base_asynchronous_channel_data {
+ /**
+ * Data Available @p EventSource. This event is generated when some incoming
+ * data is inserted in the input queue.
+ */
+ EventSource ievent;
+ /**
+ * Data Transmitted @p EventSource. This event is generated when the
+ * output queue is empty.
+ */
+ EventSource oevent;
+};
+
+/**
+ * @brief @p BaseAsynchronousChannel virtual methods table.
+ */
+struct BaseAsynchronousChannelVMT {
+ /**
+ * @p BaseChannel class inherited methods.
+ */
+ struct _base_channel_methods m0;
+ /**
+ * @p BaseAsynchronousChannel class specific methods.
+ */
+ struct _base_asynchronous_channel_methods m1;
+};
+
+/**
+ * @extends BaseChannel
+ *
+ * @brief Base asynchronous channel class.
+ * @details This class extends @p BaseChannel by adding methods for
+ * asynchronous I/O in an event-driven environment.
+ */
+typedef struct {
+ /**
+ * Virtual Methods Table.
+ */
+ const struct BaseAsynchronousChannelVMT *vmt;
+ /**
+ * @p BaseChannel class inherited data.
+ */
+ struct _base_channel_data d0;
+ /**
+ * @p BaseAsynchronousChannel class specific data.
+ */
+ struct _base_asynchronous_channel_data d1;
+} BaseAsynchronousChannel;
+
+/**
+ * @brief Channel non-blocking write.
+ * @details The function writes data from a buffer to a channel. The
+ * transfer is non-blocking and can return zero if the channel is
+ * not read to accept data.
+ *
+ * @param[in] ip pointer to a @p BaseAsynchronousChannel or derived class
+ * @param[out] bp pointer to the buffer where the data is stored
+ * @param[in] n the maximum amount of data to be transferred
+ * @return The number of bytes transferred.
+ */
+#define chIOWrite(ip, bp, n) ((ip)->vmt->m1.write(ip, bp, n))
+
+/**
+ * @brief Channel non-blocking read.
+ * @details The function reads data from a channel into a buffer. The
+ * transfer is non-blocking and can return zero if the channel has
+ * no data immediately available.
+ *
+ * @param[in] ip pointer to a @p BaseAsynchronousChannel or derived class
+ * @param[out] bp pointer to the buffer where the input data is copied
+ * @param[in] n the maximum amount of data to be transferred
+ * @return The number of bytes transferred.
+ */
+#define chIORead(ip, bp, n) ((ip)->vmt->m1.read(ip, bp, n))
+
+/**
+ * @brief Returns the write event source.
+ * @details The write event source is broadcasted when the channel is ready
+ * for write operations. This usually happens when the internal
+ * output queue becomes empty.
+ * @param[in] ip pointer to a @p BaseAsynchronousChannel or derived class
+ * @return A pointer to an @p EventSource object.
+ */
+#define chIOGetWriteEventSource(ip) (&((ip)->vmt->d1.oevent))
+
+/**
+ * @brief Returns the read event source.
+ * @details The read event source is broadcasted when the channel is ready
+ * for read operations. This usually happens when the internal
+ * input queue becomes non-empty.
+ * @param[in] ip pointer to a @p BaseAsynchronousChannel or derived class
+ * @return A pointer to an @p EventSource object.
+ */
+#define chIOGetReadEventSource(ip) (&((ip)->vmt->d1.ievent))
+
+#endif /* CH_USE_EVENTS */
+
+#endif /* _CHANNELS_H_ */
+
+/** @} */
diff --git a/os/kernel/include/condvars.h b/os/kernel/include/condvars.h
new file mode 100644
index 000000000..d68637f21
--- /dev/null
+++ b/os/kernel/include/condvars.h
@@ -0,0 +1,80 @@
+/*
+ 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/>.
+*/
+/*
+ Concepts and parts of this file are contributed by and Copyright (C) 2008
+ of Leon Woestenberg.
+ */
+
+/**
+ * @file condvars.h
+ * @brief Condition Variables macros and structures.
+ * @addtogroup CondVars
+ * @{
+ */
+
+#ifndef _CONDVARS_H_
+#define _CONDVARS_H_
+
+#if CH_USE_CONDVARS && CH_USE_MUTEXES
+
+/**
+ * @brief CondVar structure.
+ */
+typedef struct CondVar {
+ ThreadsQueue c_queue; /**< CondVar threads queue.*/
+} CondVar;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void chCondInit(CondVar *cp);
+ void chCondSignal(CondVar *cp);
+ void chCondSignalI(CondVar *cp);
+ void chCondBroadcast(CondVar *cp);
+ void chCondBroadcastI(CondVar *cp);
+ msg_t chCondWait(CondVar *cp);
+ msg_t chCondWaitS(CondVar *cp);
+#if CH_USE_CONDVARS_TIMEOUT
+ msg_t chCondWaitTimeout(CondVar *cp, systime_t time);
+ msg_t chCondWaitTimeoutS(CondVar *cp, systime_t time);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @brief Data part of a static condition variable initializer.
+ * @details This macro should be used when statically initializing a condition
+ * variable that is part of a bigger structure.
+ */
+#define _CONDVAR_DATA(name) {_THREADSQUEUE_DATA(name.c_queue)}
+
+/**
+ * @brief Static condition variable initializer.
+ * @details Statically initialized condition variables require no explicit
+ * initialization using @p chCondInit().
+ * @param name the name of the condition variable
+ */
+#define CONDVAR_DECL(name) CondVar name = _CONDVAR_DATA(name)
+
+#endif /* CH_USE_CONDVARS && CH_USE_MUTEXES */
+
+#endif /* _CONDVARS_H_ */
+
+/** @} */
diff --git a/os/kernel/include/debug.h b/os/kernel/include/debug.h
new file mode 100644
index 000000000..67a5d65b4
--- /dev/null
+++ b/os/kernel/include/debug.h
@@ -0,0 +1,149 @@
+/*
+ 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/>.
+*/
+
+/**
+ * @file debug.h
+ * @brief Debug macros and structures.
+ * @addtogroup Debug
+ * @{
+ */
+
+#ifndef _DEBUG_H_
+#define _DEBUG_H_
+
+/**
+ * @brief Trace buffer entries.
+ */
+#ifndef TRACE_BUFFER_SIZE
+#define TRACE_BUFFER_SIZE 64
+#endif
+
+/**
+ * @brief Fill value for thread stack area in debug mode.
+ */
+#ifndef STACK_FILL_VALUE
+#define STACK_FILL_VALUE 0x55
+#endif
+
+/**
+ * @brief Fill value for thread area in debug mode.
+ * @note The chosen default value is 0xFF in order to make evident which
+ * thread fields were not initialized when inspecting the memory with
+ * a debugger. A uninitialized field is not an error in itself but it
+ * better to know it.
+ */
+#ifndef THREAD_FILL_VALUE
+#define THREAD_FILL_VALUE 0xFF
+#endif
+
+/**
+ * @brief Trace buffer record.
+ */
+typedef struct {
+ void *cse_wtobjp; /**< Object where going to sleep.*/
+ systime_t cse_time; /**< Time of the switch event.*/
+ uint16_t cse_state: 4; /**< Switched out thread state.*/
+ uint16_t cse_tid: 12; /**< Switched in thdread id.*/
+} CtxSwcEvent;
+
+/**
+ * @brief Trace buffer header.
+ */
+typedef struct {
+ unsigned tb_size; /**< Trace buffer size (records).*/
+ CtxSwcEvent *tb_ptr; /**< Pointer to the ring buffer front.*/
+ CtxSwcEvent tb_buffer[TRACE_BUFFER_SIZE]; /**< Ring buffer.*/
+} TraceBuffer;
+
+#define __QUOTE_THIS(p) #p
+
+#if CH_DBG_ENABLE_CHECKS
+/**
+ * Function parameter check, if the condition check fails then the kernel
+ * panics.
+ * @param c the condition to be verified to be true
+ * @param func the undecorated function name
+ * @note The condition is tested only if the @p CH_DBG_ENABLE_CHECKS switch is
+ * specified in @p chconf.h else the macro does nothing.
+ */
+#define chDbgCheck(c, func) { \
+ if (!(c)) \
+ chDbgPanic(__QUOTE_THIS(func)"(), line "__QUOTE_THIS(__LINE__)); \
+}
+#else /* !CH_DBG_ENABLE_CHECKS */
+#define chDbgCheck(c, func) { \
+ (void)(c), (void)__QUOTE_THIS(func)"(), line "__QUOTE_THIS(__LINE__); \
+}
+#endif /* !CH_DBG_ENABLE_CHECKS */
+
+#if CH_DBG_ENABLE_ASSERTS
+/**
+ * Condition assertion, if the condition check fails then the kernel panics
+ * with the specified message.
+ * @param c the condition to be verified to be true
+ * @param m the text message
+ * @param r a remark string
+ * @note The condition is tested only if the @p CH_DBG_ENABLE_ASSERTS switch is
+ * specified in @p chconf.h else the macro does nothing.
+ * @note The convention for the message is the following:<br>
+ * @<function_name@>(), #@<assert_number@>
+ * @note The remark string is not currently used except for putting a comment
+ * in the code about the assert.
+ */
+#define chDbgAssert(c, m, r) { \
+ if (!(c)) \
+ chDbgPanic(m); \
+}
+#else /* !CH_DBG_ENABLE_ASSERTS */
+#define chDbgAssert(c, m, r) {(void)(c);}
+#endif /* !CH_DBG_ENABLE_ASSERTS */
+
+#if !(CH_DBG_ENABLE_ASSERTS || CH_DBG_ENABLE_CHECKS || CH_DBG_ENABLE_STACK_CHECK)
+/* When the debug features are disabled this function is replaced by an empty
+ * macro.*/
+#define chDbgPanic(msg) {}
+#endif
+
+#if !CH_DBG_ENABLE_TRACE
+/* When the trace feature is disabled this function is replaced by an empty
+ * macro.*/
+#define chDbgTrace(otp, ntp) {}
+#endif
+
+#if !defined(__DOXYGEN__)
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if CH_DBG_ENABLE_TRACE
+ extern TraceBuffer trace_buffer;
+ void trace_init(void);
+ void chDbgTrace(Thread *otp, Thread *ntp);
+#endif
+#if CH_DBG_ENABLE_ASSERTS || CH_DBG_ENABLE_CHECKS || CH_DBG_ENABLE_STACK_CHECK
+ extern char *panic_msg;
+ void chDbgPanic(char *msg);
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif /* !defined(__DOXYGEN__) */
+
+#endif /* _DEBUG_H_ */
+
+/** @} */
diff --git a/os/kernel/include/events.h b/os/kernel/include/events.h
new file mode 100644
index 000000000..c8bf0c6e6
--- /dev/null
+++ b/os/kernel/include/events.h
@@ -0,0 +1,145 @@
+/*
+ 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/>.
+*/
+
+/**
+ * @file events.h
+ * @brief Events macros and structures.
+ * @addtogroup Events
+ * @{
+ */
+
+#ifndef _EVENTS_H_
+#define _EVENTS_H_
+
+#if CH_USE_EVENTS
+
+typedef struct EventListener EventListener;
+
+/**
+ * @brief Event Listener structure.
+ */
+struct EventListener {
+ EventListener *el_next; /**< Next Event Listener registered on
+ the Event Source.*/
+ Thread *el_listener; /**< Thread interested in the Event
+ Source.*/
+ eventmask_t el_mask; /**< Event flags mask associated by the
+ thread to the Event Source.*/
+};
+
+/**
+ * @brief Event Source structure.
+ */
+typedef struct EventSource {
+ EventListener *es_next; /**< First Event Listener registered on
+ the Event Source.*/
+} EventSource;
+
+/**
+ * @brief Data part of a static event source initializer.
+ * @details This macro should be used when statically initializing an event
+ * source that is part of a bigger structure.
+ * @param name the name of the event source variable
+ */
+#define _EVENTSOURCE_DATA(name) {(void *)(&name)}
+
+/**
+ * @brief Static event source initializer.
+ * @details Statically initialized event sources require no explicit
+ * initialization using @p chEvtInit().
+ * @param name the name of the event source variable
+ */
+#define EVENTSOURCE_DECL(name) EventSource name = _EVENTSOURCE_DATA(name)
+
+/** All events allowed mask.*/
+#define ALL_EVENTS -1
+
+/** Returns the event mask from the event identifier.*/
+#define EVENT_MASK(eid) (1 << (eid))
+
+/**
+ * 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 eventid_t type minus one.
+ * @note Multiple Event Listeners can use the same event identifier, the
+ * listener will share the callback function.
+ */
+#define chEvtRegister(esp, elp, eid) chEvtRegisterMask(esp, elp, EVENT_MASK(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 *)(void *)(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) \
+ ((void *)(esp) != (void *)(esp)->es_next)
+
+/** Event Handler callback function.*/
+typedef void (*evhandler_t)(eventid_t);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void chEvtRegisterMask(EventSource *esp, EventListener *elp, eventmask_t emask);
+ void chEvtUnregister(EventSource *esp, EventListener *elp);
+ eventmask_t chEvtClear(eventmask_t mask);
+ eventmask_t chEvtPend(eventmask_t mask);
+ void chEvtSignal(Thread *tp, eventmask_t mask);
+ void chEvtSignalI(Thread *tp, eventmask_t mask);
+ void chEvtBroadcast(EventSource *esp);
+ void chEvtBroadcastI(EventSource *esp);
+ void chEvtDispatch(const evhandler_t handlers[], eventmask_t mask);
+#if CH_OPTIMIZE_SPEED || !CH_USE_EVENTS_TIMEOUT
+ eventmask_t chEvtWaitOne(eventmask_t ewmask);
+ eventmask_t chEvtWaitAny(eventmask_t ewmask);
+ eventmask_t chEvtWaitAll(eventmask_t ewmask);
+#endif
+#if CH_USE_EVENTS_TIMEOUT
+ eventmask_t chEvtWaitOneTimeout(eventmask_t ewmask, systime_t time);
+ eventmask_t chEvtWaitAnyTimeout(eventmask_t ewmask, systime_t time);
+ eventmask_t chEvtWaitAllTimeout(eventmask_t ewmask, systime_t time);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#if !CH_OPTIMIZE_SPEED && CH_USE_EVENTS_TIMEOUT
+#define chEvtWaitOne(ewmask) chEvtWaitOneTimeout(ewmask, TIME_INFINITE)
+#define chEvtWaitAny(ewmask) chEvtWaitAnyTimeout(ewmask, TIME_INFINITE)
+#define chEvtWaitAll(ewmask) chEvtWaitAllTimeout(ewmask, TIME_INFINITE)
+#endif
+
+#endif /* CH_USE_EVENTS */
+
+#endif /* _EVENTS_H_ */
+
+/** @} */
diff --git a/os/kernel/include/heap.h b/os/kernel/include/heap.h
new file mode 100644
index 000000000..4c9571070
--- /dev/null
+++ b/os/kernel/include/heap.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/>.
+*/
+
+/**
+ * @file heap.h
+ * @brief Heap macros and structures.
+ * @addtogroup Heap
+ * @{
+ */
+
+#ifndef _HEAP_H_
+#define _HEAP_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void heap_init(void);
+ void *chHeapAlloc(size_t size);
+ void chHeapFree(void *p);
+ size_t chHeapStatus(size_t *sizep);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HEAP_H_ */
+
+/** @} */
diff --git a/os/kernel/include/inline.h b/os/kernel/include/inline.h
new file mode 100644
index 000000000..42775d5cb
--- /dev/null
+++ b/os/kernel/include/inline.h
@@ -0,0 +1,72 @@
+/*
+ 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/>.
+*/
+
+#ifndef _INLINE_H_
+#define _INLINE_H_
+
+/**
+ * @file inline.h
+ * @brief Kernel inlined functions.
+ */
+
+/*
+ * Inlined functions if CH_OPTIMIZE_SPEED is enabled.
+ * Note: static inlined functions do not duplicate the code in every module
+ * this is true for GCC, not sure about other compilers.
+ */
+#if CH_OPTIMIZE_SPEED
+static INLINE void prio_insert(Thread *tp, ThreadsQueue *tqp) {
+
+ Thread *cp = (Thread *)tqp;
+ do {
+ cp = cp->p_next;
+ } while ((cp != (Thread *)tqp) && (cp->p_prio >= tp->p_prio));
+ tp->p_prev = (tp->p_next = cp)->p_prev;
+ tp->p_prev->p_next = cp->p_prev = tp;
+}
+
+static INLINE void queue_insert(Thread *tp, ThreadsQueue *tqp) {
+
+ tp->p_prev = (tp->p_next = (Thread *)tqp)->p_prev;
+ tp->p_prev->p_next = tqp->p_prev = tp;
+}
+
+static INLINE Thread *fifo_remove(ThreadsQueue *tqp) {
+ Thread *tp = tqp->p_next;
+
+ (tqp->p_next = tp->p_next)->p_prev = (Thread *)tqp;
+ return tp;
+}
+
+static INLINE Thread *lifo_remove(ThreadsQueue *tqp) {
+ Thread *tp = tqp->p_prev;
+
+ (tqp->p_prev = tp->p_prev)->p_next = (Thread *)tqp;
+ return tp;
+}
+
+static INLINE Thread *dequeue(Thread *tp) {
+
+ tp->p_prev->p_next = tp->p_next;
+ tp->p_next->p_prev = tp->p_prev;
+ return tp;
+}
+#endif /* CH_OPTIMIZE_SPEED */
+
+#endif /* _INLINE_H_ */
diff --git a/os/kernel/include/lists.h b/os/kernel/include/lists.h
new file mode 100644
index 000000000..bc3fd7272
--- /dev/null
+++ b/os/kernel/include/lists.h
@@ -0,0 +1,92 @@
+/*
+ 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/>.
+*/
+
+/**
+ * @file lists.h
+ * @brief Thread queues/lists macros and structures.
+ * @addtogroup ThreadLists
+ * @{
+ */
+
+#ifndef _LISTS_H_
+#define _LISTS_H_
+
+typedef struct Thread Thread;
+
+/**
+ * Threads queue initialization.
+ */
+#define queue_init(tqp) ((tqp)->p_next = (tqp)->p_prev = (Thread *)(tqp));
+
+/**
+ * Macro evaluating to @p TRUE if the specified threads queue is empty.
+ */
+#define isempty(p) ((p)->p_next == (Thread *)(p))
+
+/**
+ * Macro evaluating to @p TRUE if the specified threads queue is not empty.
+ */
+#define notempty(p) ((p)->p_next != (Thread *)(p))
+
+/**
+ * @brief Data part of a static threads queue initializer.
+ * @details This macro should be used when statically initializing a threads
+ * queue that is part of a bigger structure.
+ * @param name the name of the threads queue variable
+ */
+#define _THREADSQUEUE_DATA(name) {(Thread *)&name, (Thread *)&name}
+
+/**
+ * @brief Static threads queue initializer.
+ * @details Statically initialized threads queues require no explicit
+ * initialization using @p queue_init().
+ * @param name the name of the threads queue variable
+ */
+#define THREADSQUEUE_DECL(name) ThreadsQueue name = _THREADSQUEUE_DATA(name)
+
+/**
+ * @brief Generic threads bidirectional linked list header and element.
+ * @extends ThreadsList
+ */
+typedef struct {
+ Thread *p_next; /**< First @p Thread in the queue, or
+ @p ThreadQueue when empty.*/
+ Thread *p_prev; /**< Last @p Thread in the queue, or
+ @p ThreadQueue when empty.*/
+} ThreadsQueue;
+
+#if !CH_OPTIMIZE_SPEED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void prio_insert(Thread *tp, ThreadsQueue *tqp);
+ void queue_insert(Thread *tp, ThreadsQueue *tqp);
+ Thread *fifo_remove(ThreadsQueue *tqp);
+ Thread *lifo_remove(ThreadsQueue *tqp);
+ Thread *dequeue(Thread *tp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !CH_OPTIMIZE_SPEED */
+
+#endif /* _LISTS_H_ */
+
+/** @} */
diff --git a/os/kernel/include/mailboxes.h b/os/kernel/include/mailboxes.h
new file mode 100644
index 000000000..075806da8
--- /dev/null
+++ b/os/kernel/include/mailboxes.h
@@ -0,0 +1,126 @@
+/*
+ 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/>.
+*/
+
+/**
+ * @file mailboxes.h
+ * @brief Mailboxes macros and structures.
+ * @addtogroup Mailboxes
+ * @{
+ */
+
+#ifndef _MAILBOXES_H_
+#define _MAILBOXES_H_
+
+#if CH_USE_MAILBOXES
+
+typedef struct {
+ msg_t *mb_buffer; /**< Pointer to the mailbox buffer.*/
+ msg_t *mb_top; /**< Pointer to the first location
+ after the buffer.*/
+ msg_t *mb_wrptr; /**< Write pointer.*/
+ msg_t *mb_rdptr; /**< Read pointer.*/
+ Semaphore mb_fullsem; /**< Full counter @p Semaphore.*/
+ Semaphore mb_emptysem; /**< Empty counter @p Semaphore.*/
+} Mailbox;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void chMBInit(Mailbox *mbp, msg_t *buf, cnt_t n);
+ void chMBReset(Mailbox *mbp);
+ msg_t chMBPost(Mailbox *mbp, msg_t msg, systime_t timeout);
+ msg_t chMBPostS(Mailbox *mbp, msg_t msg, systime_t timeout);
+ msg_t chMBPostAhead(Mailbox *mbp, msg_t msg, systime_t timeout);
+ msg_t chMBPostAheadS(Mailbox *mbp, msg_t msg, systime_t timeout);
+ msg_t chMBFetch(Mailbox *mbp, msg_t *msgp, systime_t timeout);
+ msg_t chMBFetchS(Mailbox *mbp, msg_t *msgp, systime_t timeout);
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * Returns the mailbox buffer size.
+ * @param[in] mbp the pointer to an initialized Mailbox object
+ */
+#define chMBSize(mbp) \
+ ((mbp)->mb_top - (mbp)->mb_buffer)
+
+/**
+ * Returns the free space into the mailbox.
+ * @param[in] mbp the pointer to an initialized Mailbox object
+ * @return The number of empty message slots.
+ * @note Can be invoked in any system state but if invoked out of a locked
+ * state then the returned value may change after reading.
+ * @note The returned value can be less than zero when there are waiting
+ * threads on the internal semaphore.
+ */
+#define chMBGetEmpty(mbp) chSemGetCounterI(&(mbp)->mb_emptysem)
+
+/**
+ * Returns the number of messages into the mailbox.
+ * @param[in] mbp the pointer to an initialized Mailbox object
+ * @return The number of queued messages.
+ * @note Can be invoked in any system state but if invoked out of a locked
+ * state then the returned value may change after reading.
+ * @note The returned value can be less than zero when there are waiting
+ * threads on the internal semaphore.
+ */
+#define chMBGetFull(mbp) chSemGetCounterI(&(mbp)->mb_fullsem)
+
+/**
+ * Returns the next message in the queue without removing it.
+ * @note A message must be waiting in the queue for this function to work or
+ * it would return garbage. The correct way to use this macro is to
+ * use @p chMBGetFull() and then use this macro, all within a lock state.
+ */
+#define chMBPeek(mbp) (*(mbp)->mb_rdptr)
+
+/**
+ * @brief Data part of a static mailbox initializer.
+ * @details This macro should be used when statically initializing a
+ * mailbox that is part of a bigger structure.
+ * @param name the name of the mailbox variable
+ * @param buffer pointer to the mailbox buffer area
+ * @param size size of the mailbox buffer area
+ */
+#define _MAILBOX_DATA(name, buffer, size) { \
+ (msg_t *)(buffer), \
+ (msg_t *)(buffer) + size, \
+ (msg_t *)(buffer), \
+ (msg_t *)(buffer), \
+ _SEMAPHORE_DATA(name.mb_fullsem, 0), \
+ _SEMAPHORE_DATA(name.mb_emptysem, size), \
+}
+
+/**
+ * @brief Static mailbox initializer.
+ * @details Statically initialized mailboxes require no explicit
+ * initialization using @p chMBInit().
+ * @param name the name of the mailbox variable
+ * @param buffer pointer to the mailbox buffer area
+ * @param size size of the mailbox buffer area
+ */
+#define MAILBOX_DECL(name, buffer, size) \
+ Mailbox name = _MAILBOX_DATA(name, buffer, size)
+
+#endif /* CH_USE_MAILBOXES */
+
+#endif /* _MAILBOXES_H_ */
+
+/** @} */
diff --git a/os/kernel/include/mempools.h b/os/kernel/include/mempools.h
new file mode 100644
index 000000000..38e54b3d8
--- /dev/null
+++ b/os/kernel/include/mempools.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/>.
+*/
+
+/**
+ * @file mempools.h
+ * @brief Memory Pools macros and structures.
+ * @addtogroup MemoryPools
+ * @{
+ */
+
+#ifndef _MEMPOOLS_H_
+#define _MEMPOOLS_H_
+
+#if CH_USE_MEMPOOLS
+
+/**
+ * @brief Memory pool free object header.
+ */
+struct pool_header {
+ struct pool_header *ph_next;
+};
+
+/**
+ * @brief Memory pool descriptor.
+ */
+typedef struct {
+ struct pool_header *mp_next; /**< Pointer to the header.*/
+ size_t mp_object_size; /**< Memory pool objects size.*/
+} MemoryPool;
+
+/**
+ * @brief Data part of a static memory pool initializer.
+ * @details This macro should be used when statically initializing a
+ * memory pool that is part of a bigger structure.
+ * @param name the name of the memory pool variable
+ * @param size size of the memory pool contained objects
+ */
+#define _MEMORYPOOL_DATA(name, size) {NULL, size}
+
+/**
+ * @brief Static memory pool initializer.
+ * @details Statically initialized memory pools require no explicit
+ * initialization using @p chPoolInit().
+ * @param name the name of the memory pool variable
+ * @param size size of the memory pool contained objects
+ */
+#define MEMORYPOOL_DECL(name, size) \
+ MemoryPool name = _MEMORYPOOL_DATA(name, size)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void chPoolInit(MemoryPool *mp, size_t size);
+ void *chPoolAllocI(MemoryPool *mp);
+ void *chPoolAlloc(MemoryPool *mp);
+ void chPoolFreeI(MemoryPool *mp, void *objp);
+ void chPoolFree(MemoryPool *mp, void *objp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CH_USE_MEMPOOLS */
+
+#endif /* _MEMPOOLS_H_ */
+
+/** @} */
diff --git a/os/kernel/include/messages.h b/os/kernel/include/messages.h
new file mode 100644
index 000000000..ee1449a82
--- /dev/null
+++ b/os/kernel/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/>.
+*/
+
+/**
+ * @file messages.h
+ * @brief Messages macros and structures.
+ * @addtogroup Messages
+ * @{
+ */
+
+#ifndef _MESSAGES_H_
+#define _MESSAGES_H_
+
+#if 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)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ msg_t chMsgSend(Thread *tp, msg_t msg);
+ msg_t chMsgWait(void);
+ msg_t chMsgGet(void);
+ void chMsgRelease(msg_t msg);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CH_USE_MESSAGES */
+
+#endif /* _MESSAGES_H_ */
+
+/** @} */
diff --git a/os/kernel/include/mutexes.h b/os/kernel/include/mutexes.h
new file mode 100644
index 000000000..6ef6e48f4
--- /dev/null
+++ b/os/kernel/include/mutexes.h
@@ -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/>.
+*/
+
+/**
+ * @file mutexes.h
+ * @brief Mutexes macros and structures.
+ * @addtogroup Mutexes
+ * @{
+ */
+
+#ifndef _MUTEXES_H_
+#define _MUTEXES_H_
+
+#if CH_USE_MUTEXES
+
+/**
+ * @brief Mutex structure.
+ */
+typedef struct Mutex {
+ ThreadsQueue m_queue; /**< Queue of the threads sleeping on
+ this Mutex.*/
+ Thread *m_owner; /**< Owner @p Thread pointer or
+ @p NULL.*/
+ struct Mutex *m_next; /**< Next @p Mutex into an owner-list
+ or @p NULL.*/
+} Mutex;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void chMtxInit(Mutex *mp);
+ void chMtxLock(Mutex *mp);
+ void chMtxLockS(Mutex *mp);
+ bool_t chMtxTryLock(Mutex *mp);
+ bool_t chMtxTryLockS(Mutex *mp);
+ Mutex *chMtxUnlock(void);
+ Mutex *chMtxUnlockS(void);
+ void chMtxUnlockAll(void);
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @brief Data part of a static mutex initializer.
+ * @details This macro should be used when statically initializing a mutex
+ * that is part of a bigger structure.
+ * @param name the name of the mutex variable
+ */
+#define _MUTEX_DATA(name) {_THREADSQUEUE_DATA(name.m_queue), NULL, NULL}
+
+/**
+ * @brief Static mutex initializer.
+ * @details Statically initialized mutexes require no explicit initialization
+ * using @p chMtxInit().
+ * @param name the name of the mutex variable
+ */
+#define MUTEX_DECL(name) Mutex name = _MUTEX_DATA(name)
+
+/**
+ * Returns @p TRUE if the mutex queue contains at least a waiting thread.
+ */
+#define chMtxQueueNotEmptyS(mp) notempty(&(mp)->m_queue)
+
+#endif /* CH_USE_MUTEXES */
+
+#endif /* _MUTEXES_H_ */
+
+/** @} */
diff --git a/os/kernel/include/queues.h b/os/kernel/include/queues.h
new file mode 100644
index 000000000..6bd98b4f1
--- /dev/null
+++ b/os/kernel/include/queues.h
@@ -0,0 +1,218 @@
+/*
+ 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/>.
+*/
+
+/**
+ * @file queues.h I/O
+ * @brief Queues macros and structures.
+ * @addtogroup IOQueues
+ * @{
+ */
+
+#ifndef _QUEUES_H_
+#define _QUEUES_H_
+
+/** Queue notification callback type. */
+typedef void (*qnotify_t)(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
+
+#if CH_USE_QUEUES
+/**
+ * @brief Generic I/O queue structure.
+ * @details This structure represents a generic Input or Output asymmetrical
+ * queue. The queue is asymmetrical because one end is meant to be
+ * accessed from a thread context, and thus can be blocking, the other
+ * end is accessible from interrupt handlers or from within a kernel
+ * lock zone (see <b>I-Locked</b> and <b>S-Locked</b> states in
+ * @ref system_states) and is non-blocking.
+ */
+typedef struct {
+ uint8_t *q_buffer; /**< Pointer to the queue buffer.*/
+ uint8_t *q_top; /**< Pointer to the first location
+ after the buffer.*/
+ uint8_t *q_wrptr; /**< Write pointer.*/
+ uint8_t *q_rdptr; /**< Read pointer.*/
+ Semaphore q_sem; /**< Counter @p Semaphore.*/
+ qnotify_t q_notify; /**< Data notification callback.*/
+} GenericQueue;
+
+/** 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.
+ * @note The returned value can be less than zero when there are waiting
+ * threads on the internal semaphore.
+ */
+#define chQSpace(q) chSemGetCounterI(&(q)->q_sem)
+
+/**
+ * @brief Input queue structure.
+ * @details This structure represents a generic asymmetrical input queue.
+ * Writing in the queue is non-blocking and can be performed from
+ * interrupt handlers or from within a kernel lock zone (see
+ * <b>I-Locked</b> and <b>S-Locked</b> states in @ref system_states).
+ * Reading the queue can be a blocking operation and is supposed to
+ * be performed by a system thread.
+ * @extends GenericQueue
+ */
+typedef GenericQueue InputQueue;
+
+/** Evaluates to @p TRUE if the specified Input Queue is empty. */
+#define chIQIsEmpty(q) (chQSpace(q) <= 0)
+
+/** Evaluates to @p TRUE if the specified Input Queue is full. */
+#define chIQIsFull(q) (chQSpace(q) >= chQSize(q))
+
+/**
+ * @brief Input queue read.
+ * @details This function reads a byte value from an input queue. If the queue
+ * is empty then the calling thread is suspended until a byte arrives
+ * in the queue.
+ *
+ * @param[in] iqp pointer to an @p InputQueue structure
+ * @return A byte value from the queue or:
+ * @retval Q_RESET if the queue was reset.
+ */
+#define chIQGet(iqp) chIQGetTimeout(iqp, TIME_INFINITE)
+
+/**
+ * @brief Data part of a static input queue initializer.
+ * @details This macro should be used when statically initializing an
+ * input queue that is part of a bigger structure.
+ * @param name the name of the input queue variable
+ * @param buffer pointer to the queue buffer area
+ * @param size size of the queue buffer area
+ * @param inotify input notification callback pointer
+ */
+#define _INPUTQUEUE_DATA(name, buffer, size, inotify) { \
+ (uint8_t *)(buffer), \
+ (uint8_t *)(buffer) + size, \
+ (uint8_t *)(buffer), \
+ (uint8_t *)(buffer), \
+ _SEMAPHORE_DATA(name.q_sem, 0), \
+ inotify \
+}
+
+/**
+ * @brief Static input queue initializer.
+ * @details Statically initialized input queues require no explicit
+ * initialization using @p chIQInit().
+ * @param name the name of the input queue variable
+ * @param buffer pointer to the queue buffer area
+ * @param size size of the queue buffer area
+ * @param inotify input notification callback pointer
+ */
+#define INPUTQUEUE_DECL(name, buffer, size, inotify) \
+ InputQueue name = _INPUTQUEUE_DATA(name, buffer, size, inotify)
+
+/**
+ * @brief Output queue structure.
+ * @details This structure represents a generic asymmetrical output queue.
+ * Reading from the queue is non-blocking and can be performed from
+ * interrupt handlers or from within a kernel lock zone (see
+ * <b>I-Locked</b> and <b>S-Locked</b> states in @ref system_states).
+ * Writing the queue can be a blocking operation and is supposed to
+ * be performed by a system thread.
+ * @extends GenericQueue
+ */
+typedef GenericQueue OutputQueue;
+
+/** Evaluates to @p TRUE if the specified Output Queue is empty. */
+#define chOQIsEmpty(q) (chQSpace(q) >= chQSize(q))
+
+/** Evaluates to @p TRUE if the specified Output Queue is full. */
+#define chOQIsFull(q) (chQSpace(q) <= 0)
+
+/**
+ * @brief Output queue write.
+ * @details This function writes a byte value to an output queue. If the queue
+ * is full then the calling thread is suspended until there is space
+ * in the queue.
+ *
+ * @param[in] oqp pointer to an @p OutputQueue structure
+ * @param[in] b the byte value to be written in the queue
+ * @return The operation status:
+ * @retval Q_OK if the operation succeeded.
+ * @retval Q_RESET if the queue was reset.
+ */
+#define chOQPut(oqp, b) chOQPutTimeout(oqp, b, TIME_INFINITE)
+
+/**
+ * @brief Data part of a static output queue initializer.
+ * @details This macro should be used when statically initializing an
+ * output queue that is part of a bigger structure.
+ * @param name the name of the output queue variable.
+ * @param buffer pointer to the queue buffer area
+ * @param size size of the queue buffer area
+ * @param onotify output notification callback pointer
+ */
+#define _OUTPUTQUEUE_DATA(name, buffer, size, onotify) { \
+ (uint8_t *)(buffer), \
+ (uint8_t *)(buffer) + size, \
+ (uint8_t *)(buffer), \
+ (uint8_t *)(buffer), \
+ _SEMAPHORE_DATA(name.q_sem, size), \
+ onotify \
+}
+
+/**
+ * @brief Static output queue initializer.
+ * @details Statically initialized output queues require no explicit
+ * initialization using @p chOQInit().
+ * @param name the name of the output queue variable
+ * @param buffer pointer to the queue buffer area
+ * @param size size of the queue buffer area
+ * @param onotify output notification callback pointer
+ */
+#define OUTPUTQUEUE_DECL(name, buffer, size, onotify) \
+ InputQueue name = _OUTPUTQUEUE_DATA(name, buffer, size, onotify)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void chIQInit(InputQueue *qp, uint8_t *buffer, size_t size, qnotify_t inotify);
+ void chIQResetI(InputQueue *qp);
+ msg_t chIQPutI(InputQueue *qp, uint8_t b);
+ msg_t chIQGetTimeout(InputQueue *qp, systime_t timeout);
+ size_t chIQRead(InputQueue *qp, uint8_t *buffer, size_t n);
+
+ void chOQInit(OutputQueue *queue, uint8_t *buffer, size_t size, qnotify_t onotify);
+ void chOQResetI(OutputQueue *queue);
+ msg_t chOQPutTimeout(OutputQueue *queue, uint8_t b, systime_t timeout);
+ msg_t chOQGetI(OutputQueue *queue);
+ size_t chOQWrite(OutputQueue *queue, uint8_t *buffer, size_t n);
+#ifdef __cplusplus
+}
+#endif
+#endif /* CH_USE_QUEUES */
+
+#endif /* _QUEUES_H_ */
+
+/** @} */
diff --git a/os/kernel/include/scheduler.h b/os/kernel/include/scheduler.h
new file mode 100644
index 000000000..648cb7bc5
--- /dev/null
+++ b/os/kernel/include/scheduler.h
@@ -0,0 +1,110 @@
+/*
+ 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/>.
+*/
+
+/**
+ * @file scheduler.h
+ * @brief Scheduler macros and structures.
+ * @addtogroup Scheduler
+ * @{
+ */
+
+#ifndef _SCHEDULER_H_
+#define _SCHEDULER_H_
+
+/** Default thread wakeup low level message. */
+#define RDY_OK 0
+/** Low level message sent to a thread awakened by a timeout. */
+#define RDY_TIMEOUT -1
+/** Low level message sent to a thread awakened by a reset operation. */
+#define RDY_RESET -2
+
+#define NOPRIO 0 /**< Ready list header priority.*/
+#define IDLEPRIO 1 /**< Idle thread priority.*/
+#define LOWPRIO 2 /**< Lowest user priority.*/
+#define NORMALPRIO 64 /**< Normal user priority.*/
+#define HIGHPRIO 127 /**< Highest user priority.*/
+#define ABSPRIO 255 /**< Greatest possible priority.*/
+
+/**
+ * Zero time specification for some syscalls with a timeout
+ * specification.
+ * @note Not all functions accept @p TIME_IMMEDIATE as timeout parameter,
+ * see the specific function documentation.
+ */
+#define TIME_IMMEDIATE ((systime_t)-1)
+
+/**
+ * Infinite time specification for all the syscalls with a timeout
+ * specification.
+ */
+#define TIME_INFINITE ((systime_t)0)
+
+/** The priority of the first thread on the given ready list. */
+#define firstprio(rlp) ((rlp)->p_next->p_prio)
+
+/**
+ * @brief Ready list header.
+ *
+ * @extends ThreadsQueue
+ */
+typedef struct {
+ Thread *p_next; /**< Next @p Thread in the ready list.*/
+ Thread *p_prev; /**< Previous @p Thread in the ready
+ list.*/
+ /* End of the fields shared with the ThreadsQueue structure. */
+ tprio_t r_prio; /**< This field must be initialized to
+ zero.*/
+ /* End of the fields shared with the Thread structure. */
+#if CH_USE_ROUNDROBIN
+ cnt_t r_preempt; /**< Round robin counter.*/
+#endif
+#ifndef CH_CURRP_REGISTER_CACHE
+ Thread *r_current; /**< The currently running thread.*/
+#endif
+} ReadyList;
+
+extern ReadyList rlist;
+
+/*
+ * Scheduler APIs.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void scheduler_init(void);
+ Thread *chSchReadyI(Thread *tp);
+ void chSchGoSleepS(tstate_t newstate);
+ msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t time);
+ void chSchWakeupS(Thread *tp, msg_t msg);
+ void chSchDoRescheduleI(void);
+ void chSchRescheduleS(void);
+ bool_t chSchRescRequiredI(void);
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef CH_CURRP_REGISTER_CACHE
+register Thread *currp asm(CH_CURRP_REGISTER_CACHE);
+#else
+#define currp rlist.r_current
+#endif
+
+#endif /* _SCHEDULER_H_ */
+
+/** @} */
diff --git a/os/kernel/include/semaphores.h b/os/kernel/include/semaphores.h
new file mode 100644
index 000000000..833fc5cd2
--- /dev/null
+++ b/os/kernel/include/semaphores.h
@@ -0,0 +1,99 @@
+/*
+ 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/>.
+*/
+
+/**
+ * @file semaphores.h
+ * @brief Semaphores macros and structures.
+ * @addtogroup Semaphores
+ * @{
+ */
+
+#ifndef _SEMAPHORES_H_
+#define _SEMAPHORES_H_
+
+#if CH_USE_SEMAPHORES
+
+/**
+ * @brief Semaphore structure.
+ */
+typedef struct Semaphore {
+ ThreadsQueue s_queue; /**< Queue of the threads sleeping on
+ this semaphore.*/
+ cnt_t s_cnt; /**< The semaphore counter.*/
+} Semaphore;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void chSemInit(Semaphore *sp, cnt_t n);
+ void chSemReset(Semaphore *sp, cnt_t n);
+ void chSemResetI(Semaphore *sp, cnt_t n);
+ msg_t chSemWait(Semaphore *sp);
+ msg_t chSemWaitS(Semaphore *sp);
+ msg_t chSemWaitTimeout(Semaphore *sp, systime_t time);
+ msg_t chSemWaitTimeoutS(Semaphore *sp, systime_t time);
+ void chSemSignal(Semaphore *sp);
+ void chSemSignalI(Semaphore *sp);
+#if CH_USE_SEMSW
+ msg_t chSemSignalWait(Semaphore *sps, Semaphore *spw);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @brief Data part of a static semaphore initializer.
+ * @details This macro should be used when statically initializing a semaphore
+ * that is part of a bigger structure.
+ * @param name the name of the semaphore variable
+ * @param n the counter initial value, this value must be non-negative
+ */
+#define _SEMAPHORE_DATA(name, n) {_THREADSQUEUE_DATA(name.s_queue), n}
+
+/**
+ * @brief Static semaphore initializer.
+ * @details Statically initialized semaphores require no explicit initialization
+ * using @p chSemInit().
+ * @param name the name of the semaphore variable
+ * @param n the counter initial value, this value must be non-negative
+ */
+#define SEMAPHORE_DECL(name, n) Semaphore name = _SEMAPHORE_DATA(name, n)
+
+/**
+ * Decreases the semaphore counter, this macro can be used when it is ensured
+ * that the counter would not become negative.
+ */
+#define chSemFastWaitI(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 chSemGetCounterI(sp) ((sp)->s_cnt)
+
+#endif /* CH_USE_SEMAPHORES */
+
+#endif /* _SEMAPHORES_H_ */
+
+/** @} */
diff --git a/os/kernel/include/serial.h b/os/kernel/include/serial.h
new file mode 100644
index 000000000..deaca3d97
--- /dev/null
+++ b/os/kernel/include/serial.h
@@ -0,0 +1,217 @@
+/*
+ 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/>.
+*/
+
+/**
+ * @file serial.h
+ * @brief Serial Drivers macros and structures.
+ * @addtogroup Serial
+ * @{
+ */
+
+#ifndef _SERIAL_H_
+#define _SERIAL_H_
+
+#if CH_USE_SERIAL_FULLDUPLEX
+
+/** 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 uint8_t dflags_t;
+
+/**
+ * @brief @p FullDuplexDriver specific methods.
+ */
+struct _full_duplex_driver_methods {
+};
+
+/**
+ * @brief @p FullDuplexDriver specific data.
+ */
+struct _full_duplex_driver_data {
+ /**
+ * Input queue, incoming data can be read from this input queue by
+ * using the queues APIs.
+ */
+ InputQueue iqueue;
+ /**
+ * Output queue, outgoing data can be written to this output queue by
+ * using the queues APIs.
+ */
+ OutputQueue oqueue;
+ /**
+ * Status Change @p EventSource. This event is generated when one or more
+ * condition flags change.
+ */
+ EventSource sevent;
+ /**
+ * I/O driver status flags.
+ */
+ dflags_t flags;
+};
+
+/**
+ * @brief @p FullDuplexDriver virtual methods table.
+ */
+struct FullDuplexDriverVMT {
+ /**
+ * @p BaseChannel class inherited methods.
+ */
+ struct _base_channel_methods m0;
+ /**
+ * @p BaseAsynchronousChannel class inherited methods.
+ */
+ struct _base_asynchronous_channel_methods m1;
+ /**
+ * @p FullDuplexDriver specific methods.
+ */
+ struct _full_duplex_driver_methods m2;
+};
+
+/**
+ * @extends BaseAsynchronousChannel
+ *
+ * @brief Full duplex serial driver class.
+ * @details This class extends @p GenericSerialDriver by adding physical I/O
+ * queues.
+ */
+typedef struct {
+ /**
+ * Virtual Methods Table.
+ */
+ const struct FullDuplexDriverVMT *vmt;
+ /**
+ * @p BaseChannel class inherited data.
+ */
+ struct _base_channel_data d0;
+ /**
+ * @p BaseAsynchronousChannel class inherited data.
+ */
+ struct _base_asynchronous_channel_data d1;
+ /**
+ * @p FullDuplexDriver specific data.
+ */
+ struct _full_duplex_driver_data d2;
+} FullDuplexDriver;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void chFDDInit(FullDuplexDriver *sd,
+ uint8_t *ib, size_t isize, qnotify_t inotify,
+ uint8_t *ob, size_t osize, qnotify_t onotify);
+ void chFDDIncomingDataI(FullDuplexDriver *sd, uint8_t b);
+ msg_t chFDDRequestDataI(FullDuplexDriver *sd);
+ void chFDDAddFlagsI(FullDuplexDriver *sd, dflags_t mask);
+ dflags_t chFDDGetAndClearFlags(FullDuplexDriver *sd);
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @brief Direct output check on a @p FullDuplexDriver.
+ * @details This function bypasses the indirect access to the channel and
+ * checks directly the output queue. This is faster but cannot
+ * be used to check different channels implementations.
+ * @see chIOPutWouldBlock()
+ */
+#define chFDDPutWouldBlock(sd) chOQIsFull(&(sd)->d2.oqueue)
+
+/**
+ * @brief Direct input check on a @p FullDuplexDriver.
+ * @details This function bypasses the indirect access to the channel and
+ * checks directly the input queue. This is faster but cannot
+ * be used to check different channels implementations.
+ * @see chIOGetWouldBlock()
+ */
+#define chFDDGetWouldBlock(sd) chIQIsEmpty(&(sd)->d2.iqueue)
+
+/**
+ * @brief Direct blocking write to a @p FullDuplexDriver.
+ * @details This function bypasses the indirect access to the channel and
+ * writes directly on the output queue. This is faster but cannot
+ * be used to write to different channels implementations.
+ * @see chIOPut()
+ */
+#define chFDDPut(sd, b) chOQPut(&(sd)->d2.oqueue, b)
+
+/**
+ * @brief Direct blocking write on a @p FullDuplexDriver with timeout
+ * specification.
+ * @details This function bypasses the indirect access to the channel and
+ * writes directly on the output queue. This is faster but cannot
+ * be used to write to different channels implementations.
+ * @see chIOPutTimeout()
+ */
+#define chFDDPutTimeout(sd, b, t) chOQPutTimeout(&(sd)->d2.iqueue, b, t)
+
+/**
+ * @brief Direct blocking read from a @p FullDuplexDriver.
+ * @details This function bypasses the indirect access to the channel and
+ * reads directly from the input queue. This is faster but cannot
+ * be used to read from different channels implementations.
+ * @see chIOGet()
+ */
+#define chFDDGet(sd) chIQGet(&(sd)->d2.iqueue)
+
+/**
+ * @brief Direct blocking read from a @p FullDuplexDriver with timeout
+ * specification.
+ * @details This function bypasses the indirect access to the channel and
+ * reads directly from the input queue. This is faster but cannot
+ * be used to read from different channels implementations.
+ * @see chIOGetTimeout()
+ */
+#define chFDDGetTimeout(sd, t) chIQGetTimeout(&(sd)->d2.iqueue, t)
+
+/**
+ * @brief Direct non-blocking write to a @p FullDuplexDriver.
+ * @details This function bypasses the indirect access to the channel and
+ * writes directly to the output queue. This is faster but cannot
+ * be used to write from different channels implementations.
+ * @see chIOWrite()
+ */
+#define chFDDWrite(sd, b, n) chOQWrite(&(sd)->d2.oqueue, b, n)
+
+/**
+ * @brief Direct non-blocking read on a @p FullDuplexDriver.
+ * @details This function bypasses the indirect access to the channel and
+ * reads directly from the input queue. This is faster but cannot
+ * be used to read from different channels implementations.
+ * @see chIORead()
+ */
+#define chFDDRead(sd, b, n) chIQRead(&(sd)->d2.iqueue, b, n)
+
+#endif /* CH_USE_SERIAL_FULLDUPLEX */
+
+#endif /* _SERIAL_H_ */
+
+/** @} */
diff --git a/os/kernel/include/sys.h b/os/kernel/include/sys.h
new file mode 100644
index 000000000..a84d33da8
--- /dev/null
+++ b/os/kernel/include/sys.h
@@ -0,0 +1,184 @@
+/*
+ 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/>.
+*/
+
+/**
+ * @file sys.h
+ * @brief System related macros and structures.
+ * @addtogroup System
+ * @{
+ */
+
+#ifndef _SYS_H_
+#define _SYS_H_
+
+/**
+ * @brief Halts the system.
+ * @details This function is invoked by the operating system when an
+ * unrecoverable error is detected (as example because a programming error in
+ * the application code that triggers an assertion while in debug mode).
+ */
+#define chSysHalt() port_halt()
+
+/**
+ * @brief Performs a context switch.
+ *
+ * @param otp the thread to be switched out
+ * @param ntp the thread to be switched in
+ */
+#define chSysSwitchI(otp, ntp) port_switch(otp, ntp)
+
+/**
+ * @brief Raises the system interrupt priority mask to the maximum level.
+ * @details All the maskable interrupt sources are disabled regardless their
+ * hardware priority.
+ *
+ * @note The implementation is architecture dependent, it may just disable the
+ * interrupts or be exactly equivalent to @p chSysDisable().
+ * @note Do not invoke this API from within a kernel lock.
+ */
+#define chSysDisable() port_disable()
+
+/**
+ * @brief Raises the system interrupt priority mask to system level.
+ * @details The interrupt sources that should not be able to preempt the kernel
+ * are disabled, interrupt sources with higher priority are still enabled.
+ *
+ * @note The implementation is architecture dependent, it may just disable the
+ * interrupts.
+ * @note Do not invoke this API from within a kernel lock.
+ * @note This API is no replacement for @p chSysLock(), the @p chSysLock()
+ * could do more than just disable the interrupts.
+ */
+#define chSysSuspend() port_suspend()
+
+/**
+ * @brief Lowers the system interrupt priority mask to user level.
+ * @details All the interrupt sources are enabled.
+ *
+ * @note The implementation is architecture dependent, it may just enable the
+ * interrupts.
+ * @note Do not invoke this API from within a kernel lock.
+ * @note This API is no replacement for @p chSysUnlock(), the @p chSysUnlock()
+ * could do more than just enable the interrupts.
+ */
+#define chSysEnable() port_enable()
+
+/**
+ * @brief Enters the kernel lock mode.
+ *
+ * @note The use of kernel lock mode is not recommended in the user code, it is
+ * a better idea to use the semaphores or mutexes instead.
+ * @see CH_USE_NESTED_LOCKS
+ */
+#if CH_USE_NESTED_LOCKS || defined(__DOXYGEN__)
+#if CH_OPTIMIZE_SPEED || defined(__DOXYGEN__)
+#define chSysLock() { \
+ if (currp->p_locks++ == 0) \
+ port_lock(); \
+}
+#endif /* CH_OPTIMIZE_SPEED */
+#else /* !CH_USE_NESTED_LOCKS */
+#define chSysLock() port_lock()
+#endif /* !CH_USE_NESTED_LOCKS */
+
+/**
+ * @brief Leaves the kernel lock mode.
+ *
+ * @note The use of kernel lock mode is not recommended in the user code, it is
+ * a better idea to use the semaphores or mutexes instead.
+ * @see CH_USE_NESTED_LOCKS
+ */
+#if CH_USE_NESTED_LOCKS || defined(__DOXYGEN__)
+#if CH_OPTIMIZE_SPEED || defined(__DOXYGEN__)
+#define chSysUnlock() { \
+ if (--currp->p_locks == 0) \
+ port_unlock(); \
+}
+#endif /* CH_OPTIMIZE_SPEED */
+#else /* !CH_USE_NESTED_LOCKS */
+#define chSysUnlock() port_unlock()
+#endif /* !CH_USE_NESTED_LOCKS */
+
+/**
+ * @brief Enters the kernel lock mode from within an interrupt handler.
+ *
+ * @note This API may do nothing on some architectures, it is required because
+ * on ports that support preemptable interrupt handlers it is required to
+ * raise the interrupt mask to the same level of the system mutual
+ * exclusion zone.<br>
+ * It is good practice to invoke this API before invoking any I-class
+ * syscall from an interrupt handler.
+ * @note This API must be invoked exclusively from interrupt handlers.
+ */
+#define chSysLockFromIsr() port_lock_from_isr()
+
+/**
+ * @brief Leaves the kernel lock mode from within an interrupt handler.
+ *
+ * @note This API may do nothing on some architectures, it is required because
+ * on ports that support preemptable interrupt handlers it is required to
+ * raise the interrupt mask to the same level of the system mutual
+ * exclusion zone.<br>
+ * It is good practice to invoke this API after invoking any I-class
+ * syscall from an interrupt handler.
+ * @note This API must be invoked exclusively from interrupt handlers.
+ */
+#define chSysUnlockFromIsr() port_unlock_from_isr()
+
+/**
+ * @brief IRQ handler enter code.
+ *
+ * @note Usually IRQ handlers functions are also declared naked.
+ * @note On some architectures this macro can be empty.
+ */
+#define CH_IRQ_PROLOGUE() PORT_IRQ_PROLOGUE()
+
+/**
+ * @brief IRQ handler exit code.
+ *
+ * @note Usually IRQ handlers function are also declared naked.
+ * @note This macro usually performs the final reschedulation by using
+ * @p chSchRescRequiredI() and @p chSchDoRescheduleI().
+ */
+#define CH_IRQ_EPILOGUE() PORT_IRQ_EPILOGUE()
+
+/**
+ * @brief Standard IRQ handler declaration.
+ *
+ * @note @p id can be a function name or a vector number depending on the
+ * port implementation.
+ */
+#define CH_IRQ_HANDLER(id) PORT_IRQ_HANDLER(id)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void chSysInit(void);
+ void chSysTimerHandlerI(void);
+#if CH_USE_NESTED_LOCKS && !CH_OPTIMIZE_SPEED
+ void chSysLock(void);
+ void chSysUnlock(void);
+#endif /* CH_USE_NESTED_LOCKS && !CH_OPTIMIZE_SPEED */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_H_ */
+
+/** @} */
diff --git a/os/kernel/include/threads.h b/os/kernel/include/threads.h
new file mode 100644
index 000000000..07e068854
--- /dev/null
+++ b/os/kernel/include/threads.h
@@ -0,0 +1,269 @@
+/*
+ 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/>.
+*/
+
+/**
+ * @file threads.h
+ * @brief Threads macros and structures.
+ * @addtogroup Threads
+ * @{
+ */
+
+#ifndef _THREADS_H_
+#define _THREADS_H_
+
+/**
+ * @brief Structure representing a thread.
+ *
+ * @extends ThreadsQueue
+ * @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 {
+ Thread *p_next; /**< Next @p Thread in the threads
+ list/queue.*/
+ /* End of the fields shared with the ThreadsList structure. */
+ Thread *p_prev; /**< Previous @p Thread in the threads
+ queue.*/
+ /* End of the fields shared with the ThreadsQueue structure. */
+ tprio_t p_prio; /**< Thread priority.*/
+ /* End of the fields shared with the ReadyList structure. */
+ tstate_t p_state; /**< Current thread state.*/
+ tmode_t p_flags; /**< Various flags.*/
+ struct context p_ctx; /**< Processor context.*/
+#if CH_USE_NESTED_LOCKS
+ cnt_t p_locks; /**< Number of nested locks.*/
+#endif
+#if CH_DBG_THREADS_PROFILING
+ volatile systime_t p_time; /**< Consumed time.
+ @note This field can overflow.*/
+#endif
+ /*
+ * The following fields are merged in unions because they are all
+ * state-specific fields. This trick saves some extra space for each
+ * thread in the system.
+ */
+ union {
+ msg_t p_rdymsg; /**< Thread wakeup code.*/
+ msg_t p_exitcode; /**< The thread exit code
+ (@p PREXIT state).*/
+ void *p_wtobjp; /**< Generic kernel object pointer used
+ for opaque access.*/
+#if CH_USE_SEMAPHORES
+ Semaphore *p_wtsemp; /**< Semaphore where the thread is
+ waiting on (@p PRWTSEM state).*/
+#endif
+#if CH_USE_MUTEXES
+ Mutex *p_wtmtxp; /**< Mutex where the thread is waiting
+ on (@p PRWTMTX state).*/
+#endif
+#if CH_USE_CONDVARS
+ CondVar *p_wtcondp; /**< CondVar where the thread is
+ waiting on (@p PRWTCOND state).*/
+#endif
+#if CH_USE_MESSAGES
+ Thread *p_wtthdp; /**< Destination thread for message
+ send @p PRSNDMSG state).*/
+#endif
+#if CH_USE_EVENTS
+ eventmask_t p_ewmask; /**< Enabled events mask (@p PRWTOREVT
+ or @p PRWTANDEVT states).*/
+#endif
+ };
+ /*
+ * Start of the optional fields.
+ */
+#if CH_USE_WAITEXIT
+ Thread *p_waiting; /**< Thread waiting for termination.*/
+#endif
+#if CH_USE_MESSAGES
+ ThreadsQueue p_msgqueue; /**< Message queue.*/
+ msg_t p_msg; /**< The message.*/
+#endif
+#if CH_USE_EVENTS
+ eventmask_t p_epending; /**< Pending events mask.*/
+#endif
+#if CH_USE_MUTEXES
+ Mutex *p_mtxlist; /**< List of the mutexes owned by this
+ thread, @p NULL terminated.*/
+ tprio_t p_realprio; /**< Thread's own, non-inherited,
+ priority.*/
+#endif
+#if CH_USE_DYNAMIC && CH_USE_MEMPOOLS
+ void *p_mpool; /**< Memory Pool where the thread
+ workspace is returned.*/
+#endif
+ /* Extra fields defined in chconf.h */
+ THREAD_EXT_FIELDS
+};
+
+/** Thread state: Ready to run, waiting on the ready list.*/
+#define PRREADY 0
+/** Thread state: Currently running. */
+#define PRCURR 1
+/** Thread state: Thread created in suspended state. */
+#define PRSUSPENDED 2
+/** Thread state: Waiting on a semaphore. */
+#define PRWTSEM 3
+/** Thread state: Waiting on a mutex. */
+#define PRWTMTX 4
+/** Thread state: Waiting in @p chThdSleep() or @p chThdSleepUntil(). */
+#define PRWTCOND 5
+/** Thread state: Waiting in @p chCondWait(). */
+#define PRSLEEP 6
+/** Thread state: Waiting in @p chThdWait(). */
+#define PRWAIT 7
+/** Thread state: Waiting in @p chEvtWaitOneTimeout() or
+ @p chEvtWaitAnyTimeout(). */
+#define PRWTOREVT 8
+/** Thread state: Waiting in @p chEvtWaitAllTimeout(). */
+#define PRWTANDEVT 9
+/** Thread state: Waiting in @p chMsgSend(). */
+#define PRSNDMSG 10
+/** Thread state: Waiting in @p chMsgWait(). */
+#define PRWTMSG 11
+/** Thread state: After termination.*/
+#define PREXIT 12
+
+/*
+ * Various flags into the thread p_flags field.
+ */
+#define P_MEM_MODE_MASK 3 /* Thread memory mode mask. */
+#define P_MEM_MODE_STATIC 0 /* Thread memory mode: static. */
+#define P_MEM_MODE_HEAP 1 /* Thread memory mode: heap. */
+#define P_MEM_MODE_MEMPOOL 2 /* Thread memory mode: mempool. */
+#define P_TERMINATE 4 /* Termination requested. */
+
+/* Not an API, don't use into the application code.*/
+Thread *init_thread(Thread *tp, tprio_t prio);
+
+/** Thread function.*/
+typedef msg_t (*tfunc_t)(void *);
+
+/*
+ * Threads APIs.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+ Thread *chThdInit(void *wsp, size_t size,
+ tprio_t prio, tfunc_t pf, void *arg);
+ Thread *chThdCreateStatic(void *wsp, size_t size,
+ tprio_t prio, tfunc_t pf, void *arg);
+#if CH_USE_DYNAMIC && CH_USE_WAITEXIT && CH_USE_HEAP
+ Thread *chThdCreateFromHeap(size_t size, tprio_t prio,
+ tfunc_t pf, void *arg);
+#endif
+#if CH_USE_DYNAMIC && CH_USE_WAITEXIT && CH_USE_MEMPOOLS
+ Thread *chThdCreateFromMemoryPool(MemoryPool *mp, tprio_t prio,
+ tfunc_t pf, void *arg);
+#endif
+ tprio_t chThdSetPriority(tprio_t newprio);
+ Thread *chThdResume(Thread *tp);
+ void chThdTerminate(Thread *tp);
+ void chThdSleep(systime_t time);
+ void chThdSleepUntil(systime_t time);
+ void chThdExit(msg_t msg);
+#if CH_USE_WAITEXIT
+ msg_t chThdWait(Thread *tp);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/** Returns the pointer to the @p Thread currently in execution.*/
+#define chThdSelf() currp
+
+/** Returns the current thread priority.*/
+#define chThdGetPriority() (currp->p_prio)
+
+/** Returns the pointer to the @p Thread local storage area, if any.*/
+#define chThdLS() (void *)(currp + 1)
+
+/**
+ * Verifies if the specified thread is in the @p PREXIT state.
+ *
+ * @param[in] tp the pointer to the thread
+ * @retval TRUE thread terminated.
+ * @retval FALSE thread not terminated.
+ */
+#define chThdTerminated(tp) ((tp)->p_state == PREXIT)
+
+/**
+ * Verifies if the current thread has a termination request pending.
+ *
+ * @retval TRUE termination request pended.
+ * @retval FALSE termination request not pended.
+ */
+#define chThdShouldTerminate() (currp->p_flags & P_TERMINATE)
+
+/**
+ * Resumes a thread created with @p chThdInit().
+ *
+ * @param[in] tp the pointer to the thread
+ */
+#define chThdResumeI(tp) chSchReadyI(tp)
+
+/**
+ * Suspends the invoking thread for the specified time.
+ *
+ * @param[in] time the delay in system ticks, the special values are handled as
+ * follow:
+ * - @a TIME_INFINITE the thread enters an infinite sleep
+ * state.
+ * - @a TIME_IMMEDIATE this value is accepted but interpreted
+ * as a normal time specification not as an immediate timeout
+ * specification.
+ * .
+ */
+#define chThdSleepS(time) chSchGoSleepTimeoutS(PRSLEEP, time)
+
+/**
+ * Delays the invoking thread for the specified number of seconds.
+ *
+ * @param[in] sec the time in seconds
+ * @note The specified time is rounded up to a value allowed by the real
+ * system clock.
+ * @note The maximum specified value is implementation dependent.
+ */
+#define chThdSleepSeconds(sec) chThdSleep(S2ST(sec))
+
+/**
+ * Delays the invoking thread for the specified number of milliseconds.
+ *
+ * @param[in] msec the time in milliseconds
+ * @note The specified time is rounded up to a value allowed by the real
+ * system clock.
+ * @note The maximum specified value is implementation dependent.
+ */
+#define chThdSleepMilliseconds(msec) chThdSleep(MS2ST(msec))
+
+/**
+ * Delays the invoking thread for the specified number of microseconds.
+ *
+ * @param[in] usec the time in microseconds
+ * @note The specified time is rounded up to a value allowed by the real
+ * system clock.
+ * @note The maximum specified value is implementation dependent.
+ */
+#define chThdSleepMicroseconds(usec) chThdSleep(US2ST(usec))
+
+#endif /* _THREADS_H_ */
+
+/** @} */
diff --git a/os/kernel/include/vt.h b/os/kernel/include/vt.h
new file mode 100644
index 000000000..003cffd45
--- /dev/null
+++ b/os/kernel/include/vt.h
@@ -0,0 +1,125 @@
+/*
+ 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/>.
+*/
+
+/**
+ * @file vt.h
+ * @brief Time macros and structures.
+ * @addtogroup Time
+ * @{
+ */
+
+#ifndef _VT_H_
+#define _VT_H_
+
+/**
+ * Time conversion utility. Converts from seconds to system ticks number.
+ */
+#define S2ST(sec) ((systime_t)((sec) * CH_FREQUENCY))
+
+/**
+ * Time conversion utility. Converts from milliseconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ */
+#define MS2ST(msec) ((systime_t)(((((msec) - 1L) * CH_FREQUENCY) / 1000L) + 1L))
+
+/**
+ * Time conversion utility. Converts from microseconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ */
+#define US2ST(usec) ((systime_t)(((((usec) - 1L) * CH_FREQUENCY) / 1000000L) + 1L))
+
+/** Virtual Timer callback function.*/
+typedef void (*vtfunc_t)(void *);
+
+typedef struct VirtualTimer VirtualTimer;
+
+/**
+ * @brief Virtual Timer descriptor structure.
+ * @extends DeltaList
+ */
+struct VirtualTimer {
+ VirtualTimer *vt_next; /**< Next timer in the delta list.*/
+ VirtualTimer *vt_prev; /**< Previous timer in the delta list.*/
+ systime_t vt_time; /**< Time delta before timeout.*/
+ vtfunc_t vt_func; /**< Timer callback function pointer.
+ The pointer is reset to zero after
+ the callback is invoked.*/
+ void *vt_par; /**< Timer callback function
+ parameter.*/
+};
+
+/**
+ * @brief Virtual timers 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.
+ */
+typedef struct {
+ VirtualTimer *vt_next; /**< Next timer in the delta list (the
+ one that will be triggered next).*/
+ VirtualTimer *vt_prev; /**< Last timer in the delta list.*/
+ systime_t vt_time; /**< Must be initialized to -1.*/
+ volatile systime_t vt_systime; /**< System Time counter.*/
+} VTList;
+
+extern VTList vtlist;
+
+#define chVTDoTickI() { \
+ vtlist.vt_systime++; \
+ if (&vtlist != (VTList *)vtlist.vt_next) { \
+ VirtualTimer *vtp; \
+ \
+ --vtlist.vt_next->vt_time; \
+ while (!(vtp = vtlist.vt_next)->vt_time) { \
+ vtfunc_t fn = vtp->vt_func; \
+ vtp->vt_func = NULL; \
+ (vtp->vt_next->vt_prev = (void *)&vtlist)->vt_next = vtp->vt_next;\
+ fn(vtp->vt_par); \
+ } \
+ } \
+}
+
+/*
+ * Virtual Timers APIs.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void vt_init(void);
+ void chVTSetI(VirtualTimer *vtp, systime_t time, vtfunc_t vtfunc, void *par);
+ void chVTResetI(VirtualTimer *vtp);
+ bool_t chTimeIsWithin(systime_t start, systime_t end);
+#ifdef __cplusplus
+}
+#endif
+
+/** Returns TRUE if the speciified timer is armed.*/
+#define chVTIsArmedI(vtp) ((vtp)->vt_func != NULL)
+
+/**
+ * Returns the number of system ticks since the @p chSysInit() invocation.
+ * @return the system ticks number
+ * @note The counter can reach its maximum and then returns to zero.
+ * @note This function is designed to work with the @p chThdSleepUntil().
+ */
+#define chTimeNow() (vtlist.vt_systime)
+
+#endif /* _VT_H_ */
+
+/** @} */
diff --git a/os/kernel/kernel.mk b/os/kernel/kernel.mk
new file mode 100644
index 000000000..29644a5a9
--- /dev/null
+++ b/os/kernel/kernel.mk
@@ -0,0 +1,13 @@
+# List of all the ChibiOS/RT kernel files, there is no need to remove the files
+# from this list, you can disable parts of the kernel by editing chconf.h.
+KERNSRC = ../../os/kernel/src/chsys.c ../../os/kernel/src/chdebug.c \
+ ../../os/kernel/src/chlists.c ../../os/kernel/src/chvt.c \
+ ../../os/kernel/src/chschd.c ../../os/kernel/src/chthreads.c \
+ ../../os/kernel/src/chsem.c ../../os/kernel/src/chmtx.c \
+ ../../os/kernel/src/chcond.c ../../os/kernel/src/chevents.c \
+ ../../os/kernel/src/chmsg.c ../../os/kernel/src/chmboxes.c \
+ ../../os/kernel/src/chqueues.c ../../os/kernel/src/chheap.c \
+ ../../os/kernel/src/chmempools.c ../../os/kernel/src/chserial.c
+
+# Required include directories
+KERNINC = ../../os/kernel/include
diff --git a/os/kernel/readme.txt b/os/kernel/readme.txt
new file mode 100644
index 000000000..9a15d02f1
--- /dev/null
+++ b/os/kernel/readme.txt
@@ -0,0 +1 @@
+ChibiOS/RT portable kernel code \ No newline at end of file
diff --git a/os/kernel/src/chcond.c b/os/kernel/src/chcond.c
new file mode 100644
index 000000000..ef58f1ddf
--- /dev/null
+++ b/os/kernel/src/chcond.c
@@ -0,0 +1,227 @@
+/*
+ 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/>.
+*/
+/*
+ Concepts and parts of this file are contributed by and Copyright (C) 2008
+ of Leon Woestenberg.
+ */
+
+/**
+ * @file chcond.c
+ * @brief Condition Variables code.
+ * @addtogroup CondVars
+ * @{
+ */
+
+#include <ch.h>
+
+#if CH_USE_CONDVARS && CH_USE_MUTEXES
+
+/**
+ * @brief Initializes s @p CondVar structure.
+ *
+ * @param[out] cp pointer to a @p CondVar structure
+ * @note This function can be invoked from within an interrupt handler even if
+ * it is not an I-Class API because it does not touch any critical kernel
+ * data structure.
+ */
+void chCondInit(CondVar *cp) {
+
+ chDbgCheck(cp != NULL, "chCondInit");
+
+ queue_init(&cp->c_queue);
+}
+
+/**
+ * @brief Signals one thread that is waiting on the condition variable.
+ *
+ * @param[in] cp pointer to the @p CondVar structure
+ */
+void chCondSignal(CondVar *cp) {
+
+ chDbgCheck(cp != NULL, "chCondSignal");
+
+ chSysLock();
+ if (notempty(&cp->c_queue)) /* any thread ? */
+ chSchWakeupS(fifo_remove(&cp->c_queue), RDY_OK);
+ chSysUnlock();
+}
+
+/**
+ * @brief Signals one thread that is waiting on the condition variable.
+ *
+ * @param[in] cp pointer to the @p CondVar structure
+ */
+void chCondSignalI(CondVar *cp) {
+
+ chDbgCheck(cp != NULL, "chCondSignalI");
+
+ if (notempty(&cp->c_queue)) /* any thread ? */
+ chSchReadyI(fifo_remove(&cp->c_queue))->p_rdymsg = RDY_OK;
+}
+
+/**
+ * @brief Signals all threads that are waiting on the condition variable.
+ *
+ * @param[in] cp pointer to the @p CondVar structure
+ */
+void chCondBroadcast(CondVar *cp) {
+
+ chSysLock();
+ chCondBroadcastI(cp);
+ chSchRescheduleS();
+ chSysUnlock();
+}
+
+/**
+ * @brief Signals all threads that are waiting on the condition variable.
+ *
+ * @param[in] cp pointer to the @p CondVar structure
+ */
+void chCondBroadcastI(CondVar *cp) {
+
+ chDbgCheck(cp != NULL, "chCondBroadcastI");
+
+ /* empties the condition variable queue and inserts all the Threads into the
+ * ready list in FIFO order. The wakeup message is set to @p RDY_RESET in
+ * order to make a chCondBroadcast() detectable from a chCondSignal(). */
+ while (cp->c_queue.p_next != (void *)&cp->c_queue)
+ chSchReadyI(fifo_remove(&cp->c_queue))->p_rdymsg = RDY_RESET;
+}
+
+/**
+ * @brief Waits on the condition variable releasing the mutex lock.
+ * @details Releases the mutex, waits on the condition variable, and finally
+ * acquires the mutex again. This is done atomically.
+ *
+ * @param[in] cp pointer to the @p CondVar structure
+ * @return The wakep mode.
+ * @retval RDY_OK if the condvar was signaled using chCondSignal().
+ * @retval RDY_RESET if the condvar was signaled using chCondBroadcast().
+ * @note The thread MUST already have locked the mutex when calling
+ * @p chCondWait().
+ */
+msg_t chCondWait(CondVar *cp) {
+ msg_t msg;
+
+ chSysLock();
+ msg = chCondWaitS(cp);
+ chSysUnlock();
+ return msg;
+}
+
+/**
+ * @brief Waits on the condition variable releasing the mutex lock.
+ * @details Releases the mutex, waits on the condition variable, and finally
+ * acquires the mutex again. This is done atomically.
+ *
+ * @param[in] cp pointer to the @p CondVar structure
+ * @return The wakep mode.
+ * @retval RDY_OK if the condvar was signaled using chCondSignal().
+ * @retval RDY_RESET if the condvar was signaled using chCondBroadcast().
+ * @note The thread MUST already have locked the mutex when calling
+ * @p chCondWaitS().
+ */
+msg_t chCondWaitS(CondVar *cp) {
+ Mutex *mp;
+ msg_t msg;
+
+ chDbgCheck(cp != NULL, "chCondWaitS");
+ chDbgAssert(currp->p_mtxlist != NULL,
+ "chCondWaitS(), #1",
+ "not owning a mutex");
+
+ mp = chMtxUnlockS(); /* unlocks the condvar mutex */
+ prio_insert(currp, &cp->c_queue); /* enters the condvar queue */
+ currp->p_wtcondp = cp; /* needed by the tracer */
+ chSchGoSleepS(PRWTCOND); /* waits on the condvar */
+ msg = currp->p_rdymsg; /* fetches the wakeup message */
+ chMtxLockS(mp); /* atomically relocks the mutex */
+ return msg; /* returns the wakeup message */
+}
+
+#if CH_USE_CONDVARS_TIMEOUT
+/**
+ * @brief Waits on the condition variable releasing the mutex lock.
+ * @details Releases the mutex, waits on the condition variable, and finally
+ * acquires the mutex again. This is done atomically.
+ *
+ * @param[in] cp pointer to the @p CondVar structure
+ * @param[in] time the number of ticks before the operation timeouts,
+ * the special value @p TIME_INFINITE is allowed.
+ * It is not possible to specify zero @p TIME_IMMEDIATE
+ * as timeout specification because it would make no sense
+ * in this function.
+ * @return The wakep mode.
+ * @retval RDY_OK if the condvar was signaled using chCondSignal().
+ * @retval RDY_RESET if the condvar was signaled using chCondBroadcast().
+ * @retval RDY_TIMEOUT if the condvar was not signaled within the specified
+ * timeout.
+ * @note The thread MUST already have locked the mutex when calling
+ * @p chCondWaitTimeout().
+ */
+msg_t chCondWaitTimeout(CondVar *cp, systime_t time) {
+ msg_t msg;
+
+ chSysLock();
+ msg = chCondWaitTimeoutS(cp, time);
+ chSysUnlock();
+ return msg;
+}
+
+/**
+ * @brief Waits on the condition variable releasing the mutex lock.
+ * @details Releases the mutex, waits on the condition variable, and finally
+ * acquires the mutex again. This is done atomically.
+ *
+ * @param[in] cp pointer to the @p CondVar structure
+ * @param[in] time the number of ticks before the operation timeouts,
+ * the special value @p TIME_INFINITE is allowed.
+ * It is not possible to specify zero @p TIME_IMMEDIATE
+ * as timeout specification because it would make no sense
+ * in this function.
+ * @return The wakep mode.
+ * @retval RDY_OK if the condvar was signaled using chCondSignal().
+ * @retval RDY_RESET if the condvar was signaled using chCondBroadcast().
+ * @retval RDY_TIMEOUT if the condvar was not signaled within the specified
+ * timeout.
+ * @note The thread MUST already have locked the mutex when calling
+ * @p chCondWaitTimeoutS().
+ */
+msg_t chCondWaitTimeoutS(CondVar *cp, systime_t time) {
+ Mutex *mp;
+ msg_t msg;
+
+ chDbgCheck(cp != NULL, "chCondWaitTimeoutS");
+ chDbgAssert(currp->p_mtxlist != NULL,
+ "chCondWaitTimeoutS(), #1",
+ "not owning a mutex");
+
+ mp = chMtxUnlockS(); /* unlocks the condvar mutex */
+ prio_insert(currp, &cp->c_queue); /* enters the condvar queue */
+ currp->p_wtcondp = cp; /* needed by the tracer */
+ chSchGoSleepTimeoutS(PRWTCOND, time); /* waits on the condvar */
+ msg = currp->p_rdymsg; /* fetches the wakeup message */
+ chMtxLockS(mp); /* atomically relocks the mutex */
+ return msg; /* returns the wakeup message */
+}
+#endif /* CH_USE_CONDVARS_TIMEOUT */
+
+#endif /* CH_USE_CONDVARS && CH_USE_MUTEXES */
+
+/** @} */
diff --git a/os/kernel/src/chdebug.c b/os/kernel/src/chdebug.c
new file mode 100644
index 000000000..9a8120b29
--- /dev/null
+++ b/os/kernel/src/chdebug.c
@@ -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/>.
+*/
+
+/**
+ * @file chdebug.c
+ * @brief ChibiOS/RT Debug code.
+ * @addtogroup Debug
+ * @{
+ */
+
+#include <ch.h>
+
+#if CH_DBG_ENABLE_TRACE
+/**
+ * @brief Public trace buffer.
+ */
+TraceBuffer trace_buffer;
+
+/**
+ * @brief Trace circular buffer subsystem initialization.
+ */
+void trace_init(void) {
+
+ trace_buffer.tb_size = TRACE_BUFFER_SIZE;
+ trace_buffer.tb_ptr = &trace_buffer.tb_buffer[0];
+}
+
+/**
+ * @brief Inserts in the circular debug trace buffer a context switch record.
+ *
+ * @param[in] otp the thread being switched out
+ * @param[in] ntp the thread to be switched in
+ */
+void chDbgTrace(Thread *otp, Thread *ntp) {
+
+ trace_buffer.tb_ptr->cse_wtobjp = otp->p_wtobjp;
+ trace_buffer.tb_ptr->cse_time = chTimeNow();
+ trace_buffer.tb_ptr->cse_state = otp->p_state;
+ trace_buffer.tb_ptr->cse_tid = (unsigned)ntp >> 4;
+ if (++trace_buffer.tb_ptr >= &trace_buffer.tb_buffer[TRACE_BUFFER_SIZE])
+ trace_buffer.tb_ptr = &trace_buffer.tb_buffer[0];
+}
+#endif /* CH_DBG_ENABLE_TRACE */
+
+#if CH_DBG_ENABLE_ASSERTS || CH_DBG_ENABLE_CHECKS || CH_DBG_ENABLE_STACK_CHECK
+/**
+ * @brief Pointer to the panic message.
+ * @details This pointer is meant to be accessed through the debugger, it is
+ * written once and then the system is halted.
+ */
+char *panic_msg;
+
+/**
+ * @brief Prints a panic message on the console and then halts the system.
+ *
+ * @param[in] msg the pointer to the panic message string
+ */
+void chDbgPanic(char *msg) {
+
+ panic_msg = msg;
+ chSysHalt();
+}
+#endif /* CH_DBG_ENABLE_ASSERTS || CH_DBG_ENABLE_CHECKS || CH_DBG_ENABLE_STACK_CHECK */
+
+/** @} */
diff --git a/os/kernel/src/chevents.c b/os/kernel/src/chevents.c
new file mode 100644
index 000000000..098adce5e
--- /dev/null
+++ b/os/kernel/src/chevents.c
@@ -0,0 +1,392 @@
+/*
+ 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/>.
+*/
+
+/**
+ * @file chevents.c
+ * @brief Events code.
+ * @addtogroup Events
+ * @{
+ */
+#include <ch.h>
+
+#if CH_USE_EVENTS
+/**
+ * @brief Registers an Event Listener on an Event Source.
+ *
+ * @param[in] esp pointer to the @p EventSource structure
+ * @param[in] elp pointer to the @p EventListener structure
+ * @param[in] emask the mask of event flags to be pended to the thread when the
+ * event source is broadcasted
+ * @note Multiple Event Listeners can specify the same bits to be pended.
+ */
+void chEvtRegisterMask(EventSource *esp, EventListener *elp, eventmask_t emask) {
+
+ chDbgCheck((esp != NULL) && (elp != NULL), "chEvtRegisterMask");
+
+ chSysLock();
+ elp->el_next = esp->es_next;
+ esp->es_next = elp;
+ elp->el_listener = currp;
+ elp->el_mask = emask;
+ chSysUnlock();
+}
+
+/**
+ * @brief Unregisters an Event Listener from its Event Source.
+ *
+ * @param[in] esp pointer to the @p EventSource structure
+ * @param[in] 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 it is better to 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;
+
+ chDbgCheck((esp != NULL) && (elp != NULL), "chEvtUnregister");
+
+ 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();
+}
+
+/**
+ * @brief Clears the pending events specified in the mask.
+ *
+ * @param[in] mask the events to be cleared
+ * @return The pending events that were cleared.
+ */
+eventmask_t chEvtClear(eventmask_t mask) {
+ eventmask_t m;
+
+ chSysLock();
+
+ m = currp->p_epending & mask;
+ currp->p_epending &= ~mask;
+
+ chSysUnlock();
+ return m;
+}
+
+/**
+ * @brief Pends a set of event flags on the current thread, this is @b much
+ * faster than using @p chEvtBroadcast() or @p chEvtSignal().
+ *
+ * @param[in] mask the events to be pended
+ * @return The current pending events mask.
+ */
+eventmask_t chEvtPend(eventmask_t mask) {
+
+ chSysLock();
+
+ mask = (currp->p_epending |= mask);
+
+ chSysUnlock();
+ return mask;
+}
+
+/**
+ * @brief Pends a set of event flags on the specified @p Thread.
+ *
+ * @param[in] tp the thread to be signaled
+ * @param[in] mask the event flags set to be pended
+ */
+void chEvtSignal(Thread *tp, eventmask_t mask) {
+
+ chDbgCheck(tp != NULL, "chEvtSignal");
+
+ chSysLock();
+ chEvtSignalI(tp, mask);
+ chSysUnlock();
+}
+
+/**
+ * @brief Pends a set of event flags on the specified @p Thread.
+ *
+ * @param[in] tp the thread to be signaled
+ * @param[in] mask the event flags set to be pended
+ */
+void chEvtSignalI(Thread *tp, eventmask_t mask) {
+
+ chDbgCheck(tp != NULL, "chEvtSignalI");
+
+ tp->p_epending |= mask;
+ /* Test on the AND/OR conditions wait states.*/
+ if (((tp->p_state == PRWTOREVT) && ((tp->p_epending & tp->p_ewmask) != 0)) ||
+ ((tp->p_state == PRWTANDEVT) && ((tp->p_epending & tp->p_ewmask) == tp->p_ewmask)))
+ chSchReadyI(tp)->p_rdymsg = RDY_OK;
+}
+
+/**
+ * @brief Signals all the Event Listeners registered on the specified Event
+ * Source.
+ *
+ * @param[in] esp pointer to the @p EventSource structure
+ */
+void chEvtBroadcast(EventSource *esp) {
+
+ chSysLock();
+ chEvtBroadcastI(esp);
+ chSchRescheduleS();
+ chSysUnlock();
+}
+
+/**
+ * @brief Signals all the Event Listeners registered on the specified Event
+ * Source.
+ *
+ * @param[in] esp pointer to the @p EventSource structure
+ */
+void chEvtBroadcastI(EventSource *esp) {
+ EventListener *elp;
+
+ chDbgCheck(esp != NULL, "chEvtBroadcastI");
+
+ elp = esp->es_next;
+ while (elp != (EventListener *)esp) {
+ chEvtSignalI(elp->el_listener, elp->el_mask);
+ elp = elp->el_next;
+ }
+}
+
+/**
+ * @brief Invokes the event handlers associated with a mask.
+ *
+ * @param[in] mask mask of the events to be dispatched
+ * @param[in] handlers an array of @p evhandler_t. The array must have size
+ * equal to the number of bits in eventmask_t.
+ */
+void chEvtDispatch(const evhandler_t handlers[], eventmask_t mask) {
+ eventid_t eid;
+
+ chDbgCheck(handlers != NULL, "chEvtDispatch");
+
+ eid = 0;
+ while (mask) {
+ if (mask & EVENT_MASK(eid)) {
+ chDbgAssert(handlers[eid] != NULL,
+ "chEvtDispatch(), #1",
+ "null handler");
+ mask &= ~EVENT_MASK(eid);
+ handlers[eid](eid);
+ }
+ eid++;
+ }
+}
+
+#if CH_OPTIMIZE_SPEED || !CH_USE_EVENTS_TIMEOUT || defined(__DOXYGEN__)
+/**
+ * @brief Waits for exactly one of the specified events.
+ * @details The function waits for one event among those specified in
+ * @p ewmask to become pending then the event is cleared and returned.
+ *
+ * @param[in] ewmask mask of the events that the function should wait for,
+ * @p ALL_EVENTS enables all the events
+ * @return The mask of the lowest id served and cleared event.
+ * @note One and only one event is served in the function, the one with the
+ * lowest event id. The function is meant to be invoked into a loop in
+ * order to serve all the pending events.<br>
+ * This means that Event Listeners with a lower event identifier have
+ * an higher priority.
+ */
+eventmask_t chEvtWaitOne(eventmask_t ewmask) {
+ eventmask_t m;
+
+ chSysLock();
+
+ if ((m = (currp->p_epending & ewmask)) == 0) {
+ currp->p_ewmask = ewmask;
+ chSchGoSleepS(PRWTOREVT);
+ m = currp->p_epending & ewmask;
+ }
+ m &= -m;
+ currp->p_epending &= ~m;
+
+ chSysUnlock();
+ return m;
+}
+
+/**
+ * @brief Waits for any of the specified events.
+ * @details The function waits for any event among those specified in
+ * @p ewmask to become pending then the events are cleared and returned.
+ *
+ * @param[in] ewmask mask of the events that the function should wait for,
+ * @p ALL_EVENTS enables all the events
+ * @return The mask of the served and cleared events.
+ */
+eventmask_t chEvtWaitAny(eventmask_t ewmask) {
+ eventmask_t m;
+
+ chSysLock();
+
+ if ((m = (currp->p_epending & ewmask)) == 0) {
+ currp->p_ewmask = ewmask;
+ chSchGoSleepS(PRWTOREVT);
+ m = currp->p_epending & ewmask;
+ }
+ currp->p_epending &= ~m;
+
+ chSysUnlock();
+ return m;
+}
+
+/**
+ * @brief Waits for all the specified events.
+ * @details The function waits for all the events specified in @p ewmask to
+ * become pending then the events are cleared and returned.
+ *
+ * @param[in] ewmask mask of the event ids that the function should wait for
+ * @return The mask of the served and cleared events.
+ */
+eventmask_t chEvtWaitAll(eventmask_t ewmask) {
+
+ chSysLock();
+
+ if ((currp->p_epending & ewmask) != ewmask) {
+ currp->p_ewmask = ewmask;
+ chSchGoSleepS(PRWTANDEVT);
+ }
+ currp->p_epending &= ~ewmask;
+
+ chSysUnlock();
+ return ewmask;
+}
+#endif /* CH_OPTIMIZE_SPEED || !CH_USE_EVENTS_TIMEOUT */
+
+#if CH_USE_EVENTS_TIMEOUT
+/**
+ * @brief Waits for exactly one of the specified events.
+ * @details The function waits for one event among those specified in
+ * @p ewmask to become pending then the event is cleared and returned.
+ *
+ * @param[in] ewmask mask of the events that the function should wait for,
+ * @p ALL_EVENTS enables all the events
+ * @param[in] time the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The mask of the lowest id served and cleared event.
+ * @retval 0 if the specified timeout expired.
+ * @note One and only one event is served in the function, the one with the
+ * lowest event id. The function is meant to be invoked into a loop in
+ * order to serve all the pending events.<br>
+ * This means that Event Listeners with a lower event identifier have
+ * an higher priority.
+ */
+eventmask_t chEvtWaitOneTimeout(eventmask_t ewmask, systime_t time) {
+ eventmask_t m;
+
+ chSysLock();
+
+ if ((m = (currp->p_epending & ewmask)) == 0) {
+ if (TIME_IMMEDIATE == time)
+ return (eventmask_t)0;
+ currp->p_ewmask = ewmask;
+ if (chSchGoSleepTimeoutS(PRWTOREVT, time) < RDY_OK)
+ return (eventmask_t)0;
+ m = currp->p_epending & ewmask;
+ }
+ m &= -m;
+ currp->p_epending &= ~m;
+
+ chSysUnlock();
+ return m;
+}
+
+/**
+ * @brief Waits for any of the specified events.
+ * @details The function waits for any event among those specified in
+ * @p ewmask to become pending then the events are cleared and
+ * returned.
+ *
+ * @param[in] ewmask mask of the events that the function should wait for,
+ * @p ALL_EVENTS enables all the events
+ * @param[in] time the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The mask of the served and cleared events.
+ * @retval 0 if the specified timeout expired.
+ */
+eventmask_t chEvtWaitAnyTimeout(eventmask_t ewmask, systime_t time) {
+ eventmask_t m;
+
+ chSysLock();
+
+ if ((m = (currp->p_epending & ewmask)) == 0) {
+ if (TIME_IMMEDIATE == time)
+ return (eventmask_t)0;
+ currp->p_ewmask = ewmask;
+ if (chSchGoSleepTimeoutS(PRWTOREVT, time) < RDY_OK)
+ return (eventmask_t)0;
+ m = currp->p_epending & ewmask;
+ }
+ currp->p_epending &= ~m;
+
+ chSysUnlock();
+ return m;
+}
+
+/**
+ * @brief Waits for all the specified events.
+ * @details The function waits for all the events specified in @p ewmask to
+ * become pending then the events are cleared and returned.
+ *
+ * @param[in] ewmask mask of the event ids that the function should wait for
+ * @param[in] time the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The mask of the served and cleared events.
+ * @retval 0 if the specified timeout expired.
+ */
+eventmask_t chEvtWaitAllTimeout(eventmask_t ewmask, systime_t time) {
+
+ chSysLock();
+
+ if ((currp->p_epending & ewmask) != ewmask) {
+ if (TIME_IMMEDIATE == time)
+ return (eventmask_t)0;
+ currp->p_ewmask = ewmask;
+ if (chSchGoSleepTimeoutS(PRWTANDEVT, time) < RDY_OK)
+ return (eventmask_t)0;
+ }
+ currp->p_epending &= ~ewmask;
+
+ chSysUnlock();
+ return ewmask;
+}
+#endif /* CH_USE_EVENTS_TIMEOUT */
+
+#endif /* CH_USE_EVENTS */
+
+/** @} */
diff --git a/os/kernel/src/chheap.c b/os/kernel/src/chheap.c
new file mode 100644
index 000000000..82b1ba785
--- /dev/null
+++ b/os/kernel/src/chheap.c
@@ -0,0 +1,276 @@
+/*
+ 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/>.
+*/
+
+/**
+ * @file chheap.c
+ * @brief Heap code.
+ * @addtogroup Heap
+ * @{
+ */
+
+#include <ch.h>
+
+#if CH_USE_HEAP
+
+#if !CH_USE_MALLOC_HEAP
+
+#define MAGIC 0xF5A0
+#define ALIGN_TYPE void *
+#define ALIGN_MASK (sizeof(ALIGN_TYPE) - 1)
+#define ALIGN_SIZE(p) (((size_t)(p) + ALIGN_MASK) & ~ALIGN_MASK)
+
+struct header {
+ union {
+ struct header *h_next;
+ size_t h_magic;
+ };
+ size_t h_size;
+};
+
+static struct {
+ struct header free; /* Guaranteed to be not adjacent to the heap */
+#if CH_USE_MUTEXES
+#define H_LOCK() chMtxLock(&heap.hmtx)
+#define H_UNLOCK() chMtxUnlock()
+ Mutex hmtx;
+#elif CH_USE_SEMAPHORES
+#define H_LOCK() chSemWait(&heap.hsem)
+#define H_UNLOCK() chSemSignal(&heap.hsem)
+ Semaphore hsem;
+#else
+#error "The heap allocator requires mutexes or semaphores to be enabled"
+#endif
+#if CH_HEAP_SIZE > 0
+ union {
+ ALIGN_TYPE alignment;
+ char buffer[ALIGN_SIZE(CH_HEAP_SIZE)];
+ };
+#endif
+} heap;
+
+/**
+ * @brief Initializes the allocator subsystem.
+ *
+ * @note Internal use only.
+ */
+void heap_init(void) {
+ struct header *hp;
+
+#if CH_HEAP_SIZE == 0
+ extern char __heap_base__;
+ extern char __heap_end__;
+
+ hp = (void *)&__heap_base__;
+ hp->h_size = &__heap_end__ - &__heap_base__ - sizeof(struct header);
+#else
+ hp = (void *)&heap.buffer[0];
+ hp->h_size = (&heap.buffer[ALIGN_SIZE(CH_HEAP_SIZE)] - &heap.buffer[0]) -
+ sizeof(struct header);
+#endif
+ hp->h_next = NULL;
+ heap.free.h_next = hp;
+ heap.free.h_size = 0;
+#if CH_USE_MUTEXES
+ chMtxInit(&heap.hmtx);
+#else
+ chSemInit(&heap.hsem, 1);
+#endif
+}
+
+/**
+ * @brief Allocates a block of memory from the heap by using the first-fit
+ * algorithm.
+ * @details The allocated block is guaranteed to be properly aligned for a
+ * pointer data type.
+ *
+ * @param[in] size the size of the block to be allocated. Note that the
+ * allocated block may be a bit bigger than the requested
+ * size for alignment and fragmentation reasons.
+ * @return A pointer to the allocated block.
+ * @retval NULL if the block cannot be allocated.
+ */
+void *chHeapAlloc(size_t size) {
+ struct header *qp, *hp, *fp;
+
+ size = ALIGN_SIZE(size);
+ qp = &heap.free;
+ H_LOCK();
+
+ while (qp->h_next != NULL) {
+ hp = qp->h_next;
+ if (hp->h_size >= size) {
+ if (hp->h_size < size + sizeof(struct header)) {
+ /* Gets the whole block even if it is slightly bigger than the
+ requested size because the fragment would be too small to be
+ useful */
+ qp->h_next = hp->h_next;
+ }
+ else {
+ /* Block bigger enough, must split it */
+ fp = (void *)((char *)(hp) + sizeof(struct header) + size);
+ fp->h_next = hp->h_next;
+ fp->h_size = hp->h_size - sizeof(struct header) - size;
+ qp->h_next = fp;
+ hp->h_size = size;
+ }
+ hp->h_magic = MAGIC;
+
+ H_UNLOCK();
+ return (void *)(hp + 1);
+ }
+ qp = hp;
+ }
+
+ H_UNLOCK();
+ return NULL;
+}
+
+#define LIMIT(p) (struct header *)((char *)(p) + \
+ sizeof(struct header) + \
+ (p)->h_size)
+
+/**
+ * @brief Frees a previously allocated memory block.
+ *
+ * @param[in] p the memory block pointer
+ */
+void chHeapFree(void *p) {
+ struct header *qp, *hp;
+
+ chDbgCheck(p != NULL, "chHeapFree");
+
+ hp = (struct header *)p - 1;
+ chDbgAssert(hp->h_magic == MAGIC,
+ "chHeapFree(), #1",
+ "it is not magic");
+ qp = &heap.free;
+ H_LOCK();
+
+ while (TRUE) {
+
+ chDbgAssert((hp < qp) || (hp >= LIMIT(qp)),
+ "chHeapFree(), #2",
+ "within free block");
+
+ if (((qp == &heap.free) || (hp > qp)) &&
+ ((qp->h_next == NULL) || (hp < qp->h_next))) {
+ /* Insertion after qp */
+ hp->h_next = qp->h_next;
+ qp->h_next = hp;
+ /* Verifies if the newly inserted block should be merged */
+ if (LIMIT(hp) == hp->h_next) {
+ /* Merge with the next block */
+ hp->h_size += hp->h_next->h_size + sizeof(struct header);
+ hp->h_next = hp->h_next->h_next;
+ }
+ if ((LIMIT(qp) == hp)) { /* Cannot happen when qp == &heap.free */
+ /* Merge with the previous block */
+ qp->h_size += hp->h_size + sizeof(struct header);
+ qp->h_next = hp->h_next;
+ }
+
+ H_UNLOCK();
+ return;
+ }
+ qp = qp->h_next;
+ }
+}
+
+/**
+ * @brief Reports the heap status.
+ *
+ * @param[in] sizep pointer to a variable that will receive the total
+ * fragmented free space
+ * @return The number of fragments in the heap.
+ * @note This function is meant to be used in the test suite, it should not be
+ * really useful for the application code.
+ * @note This function is not implemented when the @p CH_USE_MALLOC_HEAP
+ * configuration option is used (it always returns zero).
+ */
+size_t chHeapStatus(size_t *sizep) {
+ struct header *qp;
+ size_t n, sz;
+
+ H_LOCK();
+
+ sz = 0;
+ for (n = 0, qp = &heap.free; qp->h_next; n++, qp = qp->h_next)
+ sz += qp->h_next->h_size;
+ if (sizep)
+ *sizep = sz;
+
+ H_UNLOCK();
+ return n;
+}
+
+#else /* CH_USE_MALLOC_HEAP */
+
+#include <stdlib.h>
+
+#if CH_USE_MUTEXES
+#define H_LOCK() chMtxLock(&hmtx)
+#define H_UNLOCK() chMtxLock(&hmtx)
+static Mutex hmtx;
+#elif CH_USE_SEMAPHORES
+#define H_LOCK() chSemWait(&hsem)
+#define H_UNLOCK() chSemSignal(&hsem)
+static Semaphore hsem;
+#else
+#error "The heap allocator requires mutexes or semaphores to be enabled"
+#endif
+
+void heap_init(void) {
+
+#if CH_USE_MUTEXES
+ chMtxInit(&hmtx);
+#else
+ chSemInit(&hsem, 1);
+#endif
+}
+
+void *chHeapAlloc(size_t size) {
+ void *p;
+
+ H_LOCK();
+ p = malloc(size);
+ H_UNLOCK();
+ return p;
+}
+
+void chHeapFree(void *p) {
+
+ chDbgCheck(p != NULL, "chHeapFree");
+
+ H_LOCK();
+ free(p);
+ H_UNLOCK();
+}
+
+size_t chHeapStatus(size_t *sizep) {
+
+ if (sizep)
+ *sizep = 0;
+ return 0;
+}
+
+#endif /* CH_USE_MALLOC_HEAP */
+
+#endif /* CH_USE_HEAP */
+
+/** @} */
diff --git a/os/kernel/src/chlists.c b/os/kernel/src/chlists.c
new file mode 100644
index 000000000..a2177ca63
--- /dev/null
+++ b/os/kernel/src/chlists.c
@@ -0,0 +1,111 @@
+/*
+ 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/>.
+*/
+
+/**
+ * @file chlists.c
+ * @brief Thread queues/lists code.
+ * @addtogroup ThreadLists
+ * @{
+ */
+#include <ch.h>
+
+#if !CH_OPTIMIZE_SPEED || defined(__DOXYGEN__)
+/**
+ * @brief Inserts a thread into a priority ordered queue.
+ *
+ * @param[in] tp the pointer to the thread to be inserted in the list
+ * @param[in] tqp the pointer to the threads list header
+ * @note The insertion is done by scanning the list from the highest priority
+ * toward the lowest.
+ * @note This function is @b not an API.
+ */
+void prio_insert(Thread *tp, ThreadsQueue *tqp) {
+
+ /* cp iterates over the queue */
+ Thread *cp = (Thread *)tqp;
+ do {
+ /* iterate to next thread in queue */
+ cp = cp->p_next;
+ /* not end of queue? and cp has equal or higher priority than tp? */
+ } while ((cp != (Thread *)tqp) && (cp->p_prio >= tp->p_prio));
+ /* insert before cp, point tp to next and prev in queue */
+ tp->p_prev = (tp->p_next = cp)->p_prev;
+ /* make prev point to tp, and cp point back to tp */
+ tp->p_prev->p_next = cp->p_prev = tp;
+}
+
+/**
+ * @brief Inserts a Thread into a queue.
+ *
+ * @param[in] tp the pointer to the thread to be inserted in the list
+ * @param[in] tqp the pointer to the threads list header
+ * @note This function is @b not an API.
+ */
+void queue_insert(Thread *tp, ThreadsQueue *tqp) {
+
+ tp->p_prev = (tp->p_next = (Thread *)tqp)->p_prev;
+ tp->p_prev->p_next = tqp->p_prev = tp;
+}
+
+/**
+ * @brief Removes the first-out Thread from a queue and returns it.
+ *
+ * @param[in] tqp the pointer to the threads list header
+ * @return The removed thread pointer.
+ * @note This function is @b not an API.
+ */
+Thread *fifo_remove(ThreadsQueue *tqp) {
+ Thread *tp = tqp->p_next;
+
+ (tqp->p_next = tp->p_next)->p_prev = (Thread *)tqp;
+ return tp;
+}
+
+/**
+ * @brief Removes the last-out Thread from a queue and returns it.
+ *
+ * @param[in] tqp the pointer to the threads list header
+ * @return The removed thread pointer.
+ * @note This function is @b not an API.
+ */
+Thread *lifo_remove(ThreadsQueue *tqp) {
+ Thread *tp = tqp->p_next;
+
+ (tqp->p_next = tp->p_next)->p_prev = (Thread *)tqp;
+ return tp;
+}
+
+/**
+ * @brief Removes a Thread from a queue and returns it.
+ * @details The thread is removed from the queue regardless of its relative
+ * position and regardless the used insertion method.
+ *
+ * @param[in] tp the pointer to the thread to be removed from the queue
+ * @return The removed thread pointer.
+ * @note This function is @b not an API.
+ */
+Thread *dequeue(Thread *tp) {
+
+ tp->p_prev->p_next = tp->p_next;
+ tp->p_next->p_prev = tp->p_prev;
+ return tp;
+}
+#endif /* CH_OPTIMIZE_SPEED */
+
+/** @} */
diff --git a/os/kernel/src/chmboxes.c b/os/kernel/src/chmboxes.c
new file mode 100644
index 000000000..8a791a984
--- /dev/null
+++ b/os/kernel/src/chmboxes.c
@@ -0,0 +1,244 @@
+/*
+ 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/>.
+*/
+
+/**
+ * @file chmboxes.c
+ * @brief Mailboxes code.
+ * @addtogroup Mailboxes
+ * @{
+ */
+
+#include <ch.h>
+
+#if CH_USE_MAILBOXES
+/**
+ * @brief Initializes a Mailbox object.
+ *
+ * @param[out] mbp the pointer to the Mailbox structure to be initialized
+ * @param[in] buf the circular messages buffer
+ * @param[in] n the buffer size as number of @p msg_t
+ */
+void chMBInit(Mailbox *mbp, msg_t *buf, cnt_t n) {
+
+ chDbgCheck((mbp != NULL) && (buf != NULL) && (n > 0), "chMBInit");
+
+ mbp->mb_buffer = mbp->mb_wrptr = mbp->mb_rdptr = buf;
+ mbp->mb_top = &buf[n];
+ chSemInit(&mbp->mb_emptysem, n);
+ chSemInit(&mbp->mb_fullsem, 0);
+}
+
+/**
+ * @brief Resets a Mailbox object.
+ * @details All the waiting threads are resumed with status @p RDY_RESET and
+ * the queued messages are lost.
+ *
+ * @param[in] mbp the pointer to an initialized Mailbox object
+ */
+void chMBReset(Mailbox *mbp) {
+
+ chDbgCheck(mbp != NULL, "chMBReset");
+
+ chSysLock();
+ mbp->mb_wrptr = mbp->mb_rdptr = mbp->mb_buffer;
+ chSemResetI(&mbp->mb_emptysem, mbp->mb_top - mbp->mb_buffer);
+ chSemResetI(&mbp->mb_fullsem, 0);
+ chSchRescheduleS();
+ chSysUnlock();
+}
+
+/**
+ * @brief Posts a message into a mailbox.
+ * @details The invoking thread waits until a empty slot in the mailbox becomes
+ * available or the specified time runs out.
+ *
+ * @param[in] mbp the pointer to an initialized Mailbox object
+ * @param[in] msg the message to be posted on the mailbox
+ * @param[in] time the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval RDY_OK if the message was correctly posted.
+ * @retval RDY_RESET if the mailbox was reset while waiting.
+ * @retval RDY_TIMEOUT if the operation timed out.
+ */
+msg_t chMBPost(Mailbox *mbp, msg_t msg, systime_t time) {
+ msg_t rdymsg;
+
+ chSysLock();
+ rdymsg = chMBPostS(mbp, msg, time);
+ chSysUnlock();
+ return rdymsg;
+}
+
+/**
+ * @brief Posts a message into a mailbox.
+ * @details The invoking thread waits until a empty slot in the mailbox becomes
+ * available or the specified time runs out.
+ *
+ * @param[in] mbp the pointer to an initialized Mailbox object
+ * @param[in] msg the message to be posted on the mailbox
+ * @param[in] time the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval RDY_OK if the message was correctly posted.
+ * @retval RDY_RESET if the mailbox was reset while waiting.
+ * @retval RDY_TIMEOUT if the operation timed out.
+ */
+msg_t chMBPostS(Mailbox *mbp, msg_t msg, systime_t time) {
+ msg_t rdymsg;
+
+ chDbgCheck(mbp != NULL, "chMBPostS");
+
+ rdymsg = chSemWaitTimeoutS(&mbp->mb_emptysem, time);
+ if (rdymsg == RDY_OK) {
+ *mbp->mb_wrptr++ = msg;
+ if (mbp->mb_wrptr >= mbp->mb_top)
+ mbp->mb_wrptr = mbp->mb_buffer;
+ chSemSignalI(&mbp->mb_fullsem);
+ chSchRescheduleS();
+ }
+ return rdymsg;
+}
+
+/**
+ * @brief Posts an high priority message into a mailbox.
+ * @details The invoking thread waits until a empty slot in the mailbox becomes
+ * available or the specified time runs out.
+ *
+ * @param[in] mbp the pointer to an initialized Mailbox object
+ * @param[in] msg the message to be posted on the mailbox
+ * @param[in] time the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval RDY_OK if the message was correctly posted.
+ * @retval RDY_RESET if the mailbox was reset while waiting.
+ * @retval RDY_TIMEOUT if the operation timed out.
+ */
+msg_t chMBPostAhead(Mailbox *mbp, msg_t msg, systime_t time) {
+ msg_t rdymsg;
+
+ chSysLock();
+ rdymsg = chMBPostAheadS(mbp, msg, time);
+ chSysUnlock();
+ return rdymsg;
+}
+
+/**
+ * @brief Posts an high priority message into a mailbox.
+ * @details The invoking thread waits until a empty slot in the mailbox becomes
+ * available or the specified time runs out.
+ *
+ * @param[in] mbp the pointer to an initialized Mailbox object
+ * @param[in] msg the message to be posted on the mailbox
+ * @param[in] time the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval RDY_OK if the message was correctly posted.
+ * @retval RDY_RESET if the mailbox was reset while waiting.
+ * @retval RDY_TIMEOUT if the operation timed out.
+ */
+msg_t chMBPostAheadS(Mailbox *mbp, msg_t msg, systime_t time) {
+ msg_t rdymsg;
+
+ chDbgCheck(mbp != NULL, "chMBPostAheadS");
+
+ rdymsg = chSemWaitTimeoutS(&mbp->mb_emptysem, time);
+ if (rdymsg == RDY_OK) {
+ if (--mbp->mb_rdptr < mbp->mb_buffer)
+ mbp->mb_rdptr = mbp->mb_top - 1;
+ *mbp->mb_rdptr = msg;
+ chSemSignalI(&mbp->mb_fullsem);
+ chSchRescheduleS();
+ }
+ return rdymsg;
+}
+
+/**
+ * @brief Retrieves a message from a mailbox.
+ * @details The invoking thread waits until a message is posted in the mailbox
+ * or the specified time runs out.
+ *
+ * @param[in] mbp the pointer to an initialized Mailbox object
+ * @param[out] msgp pointer to a message variable for the received message
+ * @param[in] time the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval RDY_OK if a message was correctly fetched.
+ * @retval RDY_RESET if the mailbox was reset while waiting.
+ * @retval RDY_TIMEOUT if the operation timed out.
+ */
+msg_t chMBFetch(Mailbox *mbp, msg_t *msgp, systime_t time) {
+ msg_t rdymsg;
+
+ chSysLock();
+ rdymsg = chMBFetchS(mbp, msgp, time);
+ chSysUnlock();
+ return rdymsg;
+}
+
+/**
+ * @brief Retrieves a message from a mailbox.
+ * @details The invoking thread waits until a message is posted in the mailbox
+ * or the specified time runs out.
+ *
+ * @param[in] mbp the pointer to an initialized Mailbox object
+ * @param[out] msgp pointer to a message variable for the received message
+ * @param[in] time the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval RDY_OK if a message was correctly fetched.
+ * @retval RDY_RESET if the mailbox was reset while waiting.
+ * @retval RDY_TIMEOUT if the operation timed out.
+ */
+msg_t chMBFetchS(Mailbox *mbp, msg_t *msgp, systime_t time) {
+ msg_t rdymsg;
+
+ chDbgCheck((mbp != NULL) && (msgp != NULL), "chMBFetchS");
+
+ rdymsg = chSemWaitTimeoutS(&mbp->mb_fullsem, time);
+ if (rdymsg == RDY_OK) {
+ *msgp = *mbp->mb_rdptr++;
+ if (mbp->mb_rdptr >= mbp->mb_top)
+ mbp->mb_rdptr = mbp->mb_buffer;
+ chSemSignalI(&mbp->mb_emptysem);
+ chSchRescheduleS();
+ }
+ return rdymsg;
+}
+#endif /* CH_USE_MAILBOXES */
+
+/** @} */
diff --git a/os/kernel/src/chmempools.c b/os/kernel/src/chmempools.c
new file mode 100644
index 000000000..dd6f3d1ba
--- /dev/null
+++ b/os/kernel/src/chmempools.c
@@ -0,0 +1,112 @@
+/*
+ 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/>.
+*/
+
+/**
+ * @file chmempools.c
+ * @brief Memory Pools code.
+ * @addtogroup MemoryPools
+ * @{
+ */
+
+#include <ch.h>
+
+#if CH_USE_MEMPOOLS
+/**
+ * @brief Initializes an empty memory pool.
+ *
+ * @param[out] mp pointer to a @p MemoryPool structure
+ * @param[in] size the size of the objects contained in this memory pool,
+ * the minimum accepted size is the size of a pointer to void
+ */
+void chPoolInit(MemoryPool *mp, size_t size) {
+
+ chDbgCheck((mp != NULL) && (size >= sizeof(void *)), "chPoolInit");
+
+ mp->mp_next = NULL;
+ mp->mp_object_size = size;
+}
+
+/**
+ * @brief Allocates an object from a memory pool.
+ *
+ * @param[in] mp pointer to a @p MemoryPool structure
+ * @return The pointer to the allocated object.
+ * @retval NULL if pool is empty.
+ */
+void *chPoolAllocI(MemoryPool *mp) {
+ void *objp;
+
+ chDbgCheck(mp != NULL, "chPoolAllocI");
+
+ if ((objp = mp->mp_next) != NULL)
+ mp->mp_next = mp->mp_next->ph_next;
+
+ return objp;
+}
+
+/**
+ * @brief Allocates an object from a memory pool.
+ *
+ * @param[in] mp pointer to a @p MemoryPool structure
+ * @return The pointer to the allocated object.
+ * @retval NULL if pool is empty.
+ */
+void *chPoolAlloc(MemoryPool *mp) {
+ void *objp;
+
+ chSysLock();
+ objp = chPoolAllocI(mp);
+ chSysUnlock();
+ return objp;
+}
+
+/**
+ * @brief Releases (or adds) an object into (to) a memory pool.
+ *
+ * @param[in] mp pointer to a @p MemoryPool structure
+ * @param[in] objp the pointer to the object to be released or added
+ * @note the object is assumed to be of the right size for the specified
+ * memory pool.
+ */
+void chPoolFreeI(MemoryPool *mp, void *objp) {
+ struct pool_header *php = objp;
+
+ chDbgCheck((mp != NULL) && (objp != NULL), "chPoolFreeI");
+
+ php->ph_next = mp->mp_next;
+ mp->mp_next = php;
+}
+
+/**
+ * @brief Releases (or adds) an object into (to) a memory pool.
+ *
+ * @param[in] mp pointer to a @p MemoryPool structure
+ * @param[in] objp the pointer to the object to be released or added
+ * @note the object is assumed to be of the right size for the specified
+ * memory pool.
+ */
+void chPoolFree(MemoryPool *mp, void *objp) {
+
+ chSysLock();
+ chPoolFreeI(mp, objp);
+ chSysUnlock();
+}
+#endif /* CH_USE_MEMPOOLS */
+
+/** @} */
diff --git a/os/kernel/src/chmsg.c b/os/kernel/src/chmsg.c
new file mode 100644
index 000000000..393ab8dad
--- /dev/null
+++ b/os/kernel/src/chmsg.c
@@ -0,0 +1,125 @@
+/*
+ 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/>.
+*/
+
+/**
+ * @file chmsg.c
+ * @brief Messages code.
+ * @addtogroup Messages
+ * @{
+ */
+
+#include <ch.h>
+
+#if CH_USE_MESSAGES
+
+#if CH_USE_MESSAGES_PRIORITY
+#define msg_insert(tp, qp) prio_insert(tp, qp)
+#else
+#define msg_insert(tp, qp) queue_insert(tp, qp)
+#endif
+
+/**
+ * @brief Sends a message to the specified thread.
+ * @details The sender is stopped until the receiver executes a
+ * @p chMsgRelease()after receiving the message.
+ *
+ * @param[in] tp the pointer to the thread
+ * @param[in] msg the message
+ * @return The return message from @p chMsgRelease().
+ */
+msg_t chMsgSend(Thread *tp, msg_t msg) {
+
+ chDbgCheck(tp != NULL, "chMsgSend");
+
+ chSysLock();
+ msg_insert(currp, &tp->p_msgqueue);
+ currp->p_msg = msg;
+ currp->p_wtthdp = tp;
+ if (tp->p_state == PRWTMSG)
+ chSchReadyI(tp);
+ chSchGoSleepS(PRSNDMSG);
+ msg = currp->p_rdymsg;
+ chSysUnlock();
+ return msg;
+}
+
+/**
+ * @brief 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.
+ */
+msg_t chMsgWait(void) {
+ msg_t msg;
+
+ chSysLock();
+ if (!chMsgIsPendingI(currp))
+ chSchGoSleepS(PRWTMSG);
+ msg = chMsgGetI(currp);
+ chSysUnlock();
+ return msg;
+}
+
+/**
+ * @brief 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 pointed by 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.
+ */
+msg_t chMsgGet(void) {
+ msg_t msg;
+
+ chSysLock();
+ msg = chMsgIsPendingI(currp) ? chMsgGetI(currp) : (msg_t)NULL;
+ chSysUnlock();
+ return msg;
+}
+
+/**
+ * @brief Releases the thread waiting on top of the messages queue.
+ *
+ * @param[in] 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 only tested in debug mode in order to make this code
+ * as fast as possible.
+ */
+void chMsgRelease(msg_t msg) {
+
+ chSysLock();
+ chDbgAssert(chMsgIsPendingI(currp),
+ "chMsgRelease(), #1",
+ "no message pending");
+ chSchWakeupS(fifo_remove(&currp->p_msgqueue), msg);
+ chSysUnlock();
+}
+
+#endif /* CH_USE_MESSAGES */
+
+/** @} */
diff --git a/os/kernel/src/chmtx.c b/os/kernel/src/chmtx.c
new file mode 100644
index 000000000..5fcb6fd5e
--- /dev/null
+++ b/os/kernel/src/chmtx.c
@@ -0,0 +1,299 @@
+/*
+ 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/>.
+*/
+
+/**
+ * @file chmtx.c
+ * @brief Mutexes code.
+ * @addtogroup Mutexes
+ * @{
+ */
+
+#include <ch.h>
+
+#if CH_USE_MUTEXES
+
+/**
+ * @brief Initializes s @p Mutex structure.
+ *
+ * @param[out] mp pointer to a @p Mutex structure
+ * @note This function can be invoked from within an interrupt handler even if
+ * it is not an I-Class API because it does not touch any critical kernel
+ * data structure.
+ */
+void chMtxInit(Mutex *mp) {
+
+ chDbgCheck(mp != NULL, "chMtxInit");
+
+ queue_init(&mp->m_queue);
+ mp->m_owner = NULL;
+}
+
+/**
+ * @brief Locks the specified mutex.
+ *
+ * @param[in] mp pointer to the @p Mutex structure
+ */
+void chMtxLock(Mutex *mp) {
+
+ chSysLock();
+
+ chMtxLockS(mp);
+
+ chSysUnlock();
+}
+
+/**
+ * @brief Locks the specified mutex.
+ *
+ * @param[in] mp pointer to the @p Mutex structure
+ * @note This function must be called within a @p chSysLock() / @p chSysUnlock()
+ * block.
+ */
+void chMtxLockS(Mutex *mp) {
+
+ chDbgCheck(mp != NULL, "chMtxLockS");
+
+ /* the mutex is already locked? */
+ if (mp->m_owner != NULL) {
+ /*
+ * Priority inheritance protocol; explores the thread-mutex dependencies
+ * boosting the priority of all the affected threads to equal the priority
+ * of the running thread requesting the mutex.
+ */
+ Thread *tp = mp->m_owner;
+ /* { tp is the thread currently owning the mutex } */
+ /* the running thread has higher priority than tp? */
+ while (tp->p_prio < currp->p_prio) {
+ /* make priority of thread tp match the running thread's priority */
+ tp->p_prio = currp->p_prio;
+ /*
+ * The following states need priority queues reordering.
+ */
+ switch (tp->p_state) {
+ /* thread tp is waiting on a mutex? */
+ case PRWTMTX:
+ /* Requeues tp with its new priority on the mutex wait queue. */
+ prio_insert(dequeue(tp), &tp->p_wtmtxp->m_queue);
+ /* boost the owner of this mutex if needed */
+ tp = tp->p_wtmtxp->m_owner;
+ continue;
+#if CH_USE_CONDVARS
+ case PRWTCOND:
+ /* Requeues tp with its new priority on the condvar queue. */
+ prio_insert(dequeue(tp), &tp->p_wtcondp->c_queue);
+ break;
+#endif
+#if CH_USE_SEMAPHORES_PRIORITY
+ case PRWTSEM:
+ /* Requeues tp with its new priority on the semaphore queue. */
+ prio_insert(dequeue(tp), &tp->p_wtsemp->s_queue);
+ break;
+#endif
+#if CH_USE_MESSAGES_PRIORITY
+ case PRSNDMSG:
+ /* Requeues tp with its new priority on the server thread queue. */
+ prio_insert(dequeue(tp), &tp->p_wtthdp->p_msgqueue);
+ break;
+#endif
+ /* thread tp is ready? */
+ case PRREADY:
+ /* Requeue tp with its new priority on the ready list. */
+ chSchReadyI(dequeue(tp));
+ }
+ break;
+ }
+ /* sleep on the mutex */
+ prio_insert(currp, &mp->m_queue);
+ /* thread remembers the mutex where it is waiting on */
+ currp->p_wtmtxp = mp;
+ chSchGoSleepS(PRWTMTX);
+ chDbgAssert(mp->m_owner == NULL, "chMtxLockS(), #1", "still owned");
+ }
+ /*
+ * The mutex is now inserted in the owned mutexes list.
+ */
+ mp->m_owner = currp;
+ mp->m_next = currp->p_mtxlist;
+ currp->p_mtxlist = mp;
+}
+
+/**
+ * @brief Tries to lock a mutex.
+ * @details This function does not have any overhead related to
+ * the priority inheritance mechanism because it does not try to
+ * enter a sleep state on the mutex.
+ *
+ * @param[in] mp pointer to the @p Mutex structure
+ * @retval TRUE if the mutex was successfully acquired
+ * @retval FALSE if the lock attempt failed.
+ */
+bool_t chMtxTryLock(Mutex *mp) {
+ bool_t b;
+
+ chSysLock();
+
+ b = chMtxTryLockS(mp);
+
+ chSysUnlock();
+ return b;
+}
+
+/**
+ * @brief Tries to lock a mutex.
+ * @details This function does not have any overhead related to
+ * the priority inheritance mechanism because it does not try to
+ * enter a sleep state on the mutex.
+ * @param[in] mp pointer to the @p Mutex structure
+ * @retval TRUE if the mutex was successfully acquired
+ * @retval FALSE if the lock attempt failed.
+ * @note This function must be called within a @p chSysLock() / @p chSysUnlock()
+ * block.
+ */
+bool_t chMtxTryLockS(Mutex *mp) {
+
+ chDbgCheck(mp != NULL, "chMtxTryLockS");
+
+ if (mp->m_owner != NULL)
+ return FALSE;
+ mp->m_owner = currp;
+ mp->m_next = currp->p_mtxlist;
+ currp->p_mtxlist = mp;
+ return TRUE;
+}
+
+/**
+ * @brief Unlocks the next owned mutex in reverse lock order.
+ *
+ * @return The pointer to the unlocked mutex.
+ */
+Mutex *chMtxUnlock(void) {
+ Mutex *ump, *mp;
+
+ chSysLock();
+ chDbgAssert(currp->p_mtxlist != NULL,
+ "chMtxUnlock(), #1",
+ "owned mutexes list empty");
+ chDbgAssert(currp->p_mtxlist->m_owner == currp,
+ "chMtxUnlock(), #2",
+ "ownership failure");
+ /* remove the top Mutex from the Threads's owned mutexes list */
+ ump = currp->p_mtxlist;
+ currp->p_mtxlist = ump->m_next;
+ /* mark the Mutex as not owned */
+ ump->m_owner = NULL;
+ /*
+ * If a thread is waiting on the mutex then the hard part begins.
+ */
+ if (chMtxQueueNotEmptyS(ump)) {
+ /* get the highest priority thread waiting for the unlocked mutex */
+ Thread *tp = fifo_remove(&ump->m_queue);
+ /*
+ * Recalculates the optimal thread priority by scanning the owned mutexes list.
+ */
+ tprio_t newprio = currp->p_realprio;
+ /* iterate mp over all the (other) mutexes the current thread still owns */
+ mp = currp->p_mtxlist;
+ while (mp != NULL) {
+ /* mutex mp has a higher priority thread pending? */
+ if (chMtxQueueNotEmptyS(mp) && (mp->m_queue.p_next->p_prio > newprio))
+ /* boost current thread's priority to waiting thread */
+ newprio = mp->m_queue.p_next->p_prio;
+ mp = mp->m_next;
+ }
+ /* (possibly) boost the priority of the current thread */
+ currp->p_prio = newprio;
+ /* awaken the highest priority thread waiting for the unlocked mutex */
+ chSchWakeupS(tp, RDY_OK);
+ }
+ chSysUnlock();
+ return ump;
+}
+
+/**
+ * @brief Unlocks the next owned mutex in reverse lock order.
+ *
+ * @return The pointer to the unlocked mutex.
+ * @note This function must be called within a @p chSysLock() / @p chSysUnlock()
+ * block.
+ * @note This function does not reschedule internally.
+ */
+Mutex *chMtxUnlockS(void) {
+ Mutex *ump, *mp;
+
+ chDbgAssert(currp->p_mtxlist != NULL,
+ "chMtxUnlockS(), #1",
+ "owned mutexes list empty");
+ chDbgAssert(currp->p_mtxlist->m_owner == currp,
+ "chMtxUnlockS(), #2",
+ "ownership failure");
+
+ /*
+ * Removes the top Mutex from the owned mutexes list and marks it as not owned.
+ */
+ ump = currp->p_mtxlist;
+ currp->p_mtxlist = ump->m_next;
+ ump->m_owner = NULL;
+ /*
+ * If a thread is waiting on the mutex then the hard part begins.
+ */
+ if (chMtxQueueNotEmptyS(ump)) {
+ Thread *tp = fifo_remove(&ump->m_queue);
+ /*
+ * Recalculates the optimal thread priority by scanning the owned mutexes list.
+ */
+ tprio_t newprio = currp->p_realprio;
+ mp = currp->p_mtxlist;
+ while (mp != NULL) {
+ if (chMtxQueueNotEmptyS(mp) && (mp->m_queue.p_next->p_prio > newprio))
+ newprio = mp->m_queue.p_next->p_prio;
+ mp = mp->m_next;
+ }
+ currp->p_prio = newprio;
+ chSchReadyI(tp);
+ }
+ return ump;
+}
+
+/**
+ * @brief Unlocks all the mutexes owned by the invoking thread.
+ * @details This function is <b>MUCH MORE</b> efficient than releasing the
+ * mutexes one by one and not just because the call overhead,
+ * this function does not have any overhead related to the priority
+ * inheritance mechanism.
+ */
+void chMtxUnlockAll(void) {
+
+ chSysLock();
+ if (currp->p_mtxlist != NULL) {
+ do {
+ Mutex *mp = currp->p_mtxlist;
+ currp->p_mtxlist = mp->m_next;
+ mp->m_owner = NULL;
+ if (chMtxQueueNotEmptyS(mp))
+ chSchReadyI(fifo_remove(&mp->m_queue));
+ } while (currp->p_mtxlist != NULL);
+ currp->p_prio = currp->p_realprio;
+ chSchRescheduleS();
+ }
+ chSysUnlock();
+}
+
+#endif /* CH_USE_MUTEXES */
+
+/** @} */
diff --git a/os/kernel/src/chqueues.c b/os/kernel/src/chqueues.c
new file mode 100644
index 000000000..a72b83696
--- /dev/null
+++ b/os/kernel/src/chqueues.c
@@ -0,0 +1,304 @@
+/*
+ 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/>.
+*/
+
+/**
+ * @file chqueues.c
+ * @brief I/O Queues code.
+ * @addtogroup IOQueues
+ * @{
+ */
+
+#include <ch.h>
+
+#if CH_USE_QUEUES
+
+/**
+ * @brief Initializes an input queue.
+ * @details A Semaphore is internally initialized and works as a counter of
+ * the bytes contained in the queue.
+ *
+ * @param[out] iqp pointer to an @p InputQueue structure
+ * @param[in] buffer pointer to a memory area allocated as queue buffer
+ * @param[in] size size of the queue buffer
+ * @param[in] inotify pointer to a callback function that is invoked when
+ * some data is read from the queue. The value can be
+ * @p NULL.
+ *
+ * @note The callback is invoked from within the S-Locked system state,
+ * see @ref system_states.
+ */
+void chIQInit(InputQueue *iqp, uint8_t *buffer,
+ size_t size, qnotify_t inotify) {
+
+ iqp->q_buffer = iqp->q_rdptr = iqp->q_wrptr = buffer;
+ iqp->q_top = buffer + size;
+ chSemInit(&iqp->q_sem, 0);
+ iqp->q_notify = inotify;
+}
+
+/**
+ * @brief Resets an input queue.
+ * @details All the data in the input queue is erased and lost, any waiting
+ * thread is resumed with status @p Q_RESET.
+ *
+ * @param[in] iqp pointer to an @p InputQueue structure
+ *
+ * @note A reset operation can be used by a low level driver in order to obtain
+ * immediate attention from the high level layers.
+ */
+void chIQResetI(InputQueue *iqp) {
+
+ iqp->q_rdptr = iqp->q_wrptr = iqp->q_buffer;
+ chSemResetI(&iqp->q_sem, 0);
+}
+
+/**
+ * @brief Input queue write.
+ * @details A byte value is written into the low end of an input queue.
+ *
+ * @param[in] iqp pointer to an @p InputQueue structure
+ * @param[in] b the byte value to be written in the queue
+ * @return The operation status, it can be one of:
+ * @retval Q_OK if the operation has been completed with success.
+ * @retval Q_FULL if the queue is full and the operation cannot be completed.
+ */
+msg_t chIQPutI(InputQueue *iqp, uint8_t b) {
+
+ if (chIQIsFull(iqp))
+ return Q_FULL;
+
+ *iqp->q_wrptr++ = b;
+ if (iqp->q_wrptr >= iqp->q_top)
+ iqp->q_wrptr = iqp->q_buffer;
+ chSemSignalI(&iqp->q_sem);
+ return Q_OK;
+}
+
+/**
+ * @brief Input queue read with timeout.
+ * @details This function reads a byte value from an input queue. If the queue
+ * is empty then the calling thread is suspended until a byte arrives
+ * in the queue or a timeout occurs.
+ *
+ * @param[in] iqp pointer to an @p InputQueue structure
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return A byte value from the queue or:
+ * @retval Q_TIMEOUT if the specified time expired.
+ * @retval Q_RESET if the queue was reset.
+ */
+msg_t chIQGetTimeout(InputQueue *iqp, systime_t timeout) {
+ uint8_t b;
+ msg_t msg;
+
+ chSysLock();
+ if ((msg = chSemWaitTimeoutS(&iqp->q_sem, timeout)) < RDY_OK) {
+ chSysUnlock();
+ return msg;
+ }
+ b = *iqp->q_rdptr++;
+ if (iqp->q_rdptr >= iqp->q_top)
+ iqp->q_rdptr = iqp->q_buffer;
+
+ if (iqp->q_notify)
+ iqp->q_notify();
+
+ chSysUnlock();
+ return b;
+}
+
+/**
+ * @brief Non-blocking read.
+ * @details The function reads data from an input queue into a buffer. The
+ * transfer is non-blocking and can return zero if the queue is
+ * empty.
+ *
+ * @param[in] iqp pointer to an @p InputQueue structure
+ * @param[out] buffer pointer to the buffer where the input data is copied
+ * @param[in] n the maximum amount of data to be transferred
+ * @return The number of bytes transferred.
+ *
+ * @note The function is not atomic, if you need atomicity it is suggested
+ * to use a semaphore or a mutex for mutual exclusion.
+ */
+size_t chIQRead(InputQueue *iqp, uint8_t *buffer, size_t n) {
+ size_t r = 0;
+
+ while (n--) {
+ chSysLock();
+ if (chIQIsEmpty(iqp)) {
+ chSysUnlock();
+ break;
+ }
+ chSemFastWaitI(&iqp->q_sem);
+ *buffer++ = *iqp->q_rdptr++;
+ if (iqp->q_rdptr >= iqp->q_top)
+ iqp->q_rdptr = iqp->q_buffer;
+ chSysUnlock();
+ r++;
+ }
+ if (r && iqp->q_notify) {
+ chSysLock();
+ iqp->q_notify();
+ chSysUnlock();
+ }
+ return r;
+}
+
+/**
+ * @brief Initializes an output queue.
+ * @details A Semaphore is internally initialized and works as a counter of
+ * the free bytes in the queue.
+ *
+ * @param[out] oqp pointer to an @p OutputQueue structure
+ * @param[in] buffer pointer to a memory area allocated as queue buffer
+ * @param[in] size size of the queue buffer
+ * @param[in] onotify pointer to a callback function that is invoked when
+ * some data is written to the queue. The value can be
+ * @p NULL.
+ *
+ * @note The callback is invoked from within the S-Locked system state,
+ * see @ref system_states.
+ */
+void chOQInit(OutputQueue *oqp, uint8_t *buffer,
+ size_t size, qnotify_t onotify) {
+
+ oqp->q_buffer = oqp->q_rdptr = oqp->q_wrptr = buffer;
+ oqp->q_top = buffer + size;
+ chSemInit(&oqp->q_sem, size);
+ oqp->q_notify = onotify;
+}
+
+/**
+ * @brief Resets an output queue.
+ * @details All the data in the output queue is erased and lost, any waiting
+ * thread is resumed with status @p Q_RESET.
+ *
+ * @param[in] oqp pointer to an @p OutputQueue structure
+ *
+ * @note A reset operation can be used by a low level driver in order to obtain
+ * immediate attention from the high level layers.
+ */
+void chOQResetI(OutputQueue *oqp) {
+
+ oqp->q_rdptr = oqp->q_wrptr = oqp->q_buffer;
+ chSemResetI(&oqp->q_sem, (cnt_t)(oqp->q_top - oqp->q_buffer));
+}
+
+/**
+ * @brief Output queue write with timeout.
+ * @details This function writes a byte value to an output queue. If the queue
+ * is full then the calling thread is suspended until there is space
+ * in the queue or a timeout occurs.
+ *
+ * @param[in] oqp pointer to an @p OutputQueue structure
+ * @param[in] b the byte value to be written in the queue
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status:
+ * @retval Q_OK if the operation succeeded.
+ * @retval Q_TIMEOUT if the specified time expired.
+ * @retval Q_RESET if the queue was reset.
+ */
+msg_t chOQPutTimeout(OutputQueue *oqp, uint8_t b, systime_t timeout) {
+ msg_t msg;
+
+ chSysLock();
+ if ((msg = chSemWaitTimeoutS(&oqp->q_sem, timeout)) < RDY_OK) {
+ chSysUnlock();
+ return msg;
+ }
+ *oqp->q_wrptr++ = b;
+ if (oqp->q_wrptr >= oqp->q_top)
+ oqp->q_wrptr = oqp->q_buffer;
+
+ if (oqp->q_notify)
+ oqp->q_notify();
+
+ chSysUnlock();
+ return Q_OK;
+}
+
+/**
+ * @brief Output queue read.
+ * @details A byte value is read from the low end of an output queue.
+ *
+ * @param[in] oqp pointer to an @p OutputQueue structure
+ * @return The byte value from the queue or:
+ * @retval Q_EMPTY if the queue is empty.
+ */
+msg_t chOQGetI(OutputQueue *oqp) {
+ uint8_t b;
+
+ if (chOQIsEmpty(oqp))
+ return Q_EMPTY;
+
+ b = *oqp->q_rdptr++;
+ if (oqp->q_rdptr >= oqp->q_top)
+ oqp->q_rdptr = oqp->q_buffer;
+ chSemSignalI(&oqp->q_sem);
+ return b;
+}
+
+/**
+ * @brief Non-blocking write.
+ * @details The function writes data from a buffer to an output queue. The
+ * transfer is non-blocking and can return zero if the queue is
+ * already full.
+ *
+ * @param[in] oqp pointer to an @p OutputQueue structure
+ * @param[out] buffer pointer to the buffer where the output data is stored
+ * @param[in] n the maximum amount of data to be transferred
+ * @return The number of bytes transferred.
+ *
+ * @note The function is not atomic, if you need atomicity it is suggested
+ * to use a semaphore or a mutex for mutual exclusion.
+ */
+size_t chOQWrite(OutputQueue *oqp, uint8_t *buffer, size_t n) {
+
+ size_t w = 0;
+ while (n--) {
+ chSysLock();
+ if (chOQIsFull(oqp)) {
+ chSysUnlock();
+ break;
+ }
+ chSemFastWaitI(&oqp->q_sem);
+ *oqp->q_wrptr++ = *buffer++;
+ if (oqp->q_wrptr >= oqp->q_top)
+ oqp->q_wrptr = oqp->q_buffer;
+ chSysUnlock();
+ w++;
+ }
+ if (w && oqp->q_notify) {
+ chSysLock();
+ oqp->q_notify();
+ chSysUnlock();
+ }
+ return w;
+}
+#endif /* CH_USE_QUEUES */
+
+/** @} */
diff --git a/os/kernel/src/chschd.c b/os/kernel/src/chschd.c
new file mode 100644
index 000000000..3ba8b29e9
--- /dev/null
+++ b/os/kernel/src/chschd.c
@@ -0,0 +1,242 @@
+/*
+ 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/>.
+*/
+
+/**
+ * @file chschd.c
+ * @brief Scheduler code.
+ * @addtogroup Scheduler
+ * @{
+ */
+
+#include <ch.h>
+
+/** @cond never */
+ReadyList rlist;
+/** @endcond */
+
+/**
+ * @brief Scheduler initialization.
+ *
+ * @note Internally invoked by the @p chSysInit().
+ */
+void scheduler_init(void) {
+
+ queue_init(&rlist);
+ rlist.r_prio = NOPRIO;
+#if CH_USE_ROUNDROBIN
+ rlist.r_preempt = CH_TIME_QUANTUM;
+#endif
+}
+
+/**
+ * @brief Inserts a thread in the Ready List.
+ *
+ * @param[in] tp the Thread to be made ready
+ * @return The Thread pointer.
+ * @note The function does not reschedule, the @p chSchRescheduleS() should
+ * be called soon after.
+ */
+#if CH_OPTIMIZE_SPEED
+/* NOTE: it is inlined in this module only.*/
+INLINE Thread *chSchReadyI(Thread *tp) {
+#else
+Thread *chSchReadyI(Thread *tp) {
+#endif
+ Thread *cp;
+
+ tp->p_state = PRREADY;
+ cp = (Thread *)&rlist;
+ do {
+ cp = cp->p_next;
+ } while (cp->p_prio >= tp->p_prio);
+ /* Insertion on p_prev.*/
+ tp->p_prev = (tp->p_next = cp)->p_prev;
+ tp->p_prev->p_next = cp->p_prev = tp;
+ return tp;
+}
+
+/**
+ * @brief Puts the current thread to sleep into the specified state.
+ * @details The thread goes into a sleeping state. The @ref thread_states are
+ * described into @p threads.h.
+ *
+ * @param[in] newstate the new thread state
+ */
+void chSchGoSleepS(tstate_t newstate) {
+ Thread *otp;
+
+ (otp = currp)->p_state = newstate;
+ (currp = fifo_remove((void *)&rlist))->p_state = PRCURR;
+#if CH_USE_ROUNDROBIN
+ rlist.r_preempt = CH_TIME_QUANTUM;
+#endif
+ chDbgTrace(otp, currp);
+ chSysSwitchI(otp, currp);
+}
+
+/*
+ * Timeout wakeup callback.
+ */
+static void wakeup(void *p) {
+ Thread *tp = (Thread *)p;
+
+#if CH_USE_SEMAPHORES || CH_USE_MUTEXES || CH_USE_CONDVARS
+ switch (tp->p_state) {
+#if CH_USE_SEMAPHORES
+ case PRWTSEM:
+ chSemFastSignalI(tp->p_wtsemp);
+ /* Falls into, intentional. */
+#endif
+#if CH_USE_MUTEXES
+ case PRWTMTX:
+#endif
+#if CH_USE_CONDVARS
+ case PRWTCOND:
+#endif
+ /* States requiring dequeuing. */
+ dequeue(tp);
+ }
+#endif
+ chSchReadyI(tp)->p_rdymsg = RDY_TIMEOUT;
+}
+
+/**
+ * @brief Puts the current thread to sleep into the specified state with
+ * timeout specification.
+ * @details The thread goes into a sleeping state, if it is not awakened
+ * explicitly within the specified timeout then it is forcibly
+ * awakened with a @p RDY_TIMEOUT low level message. The @ref
+ * thread_states are described into @p threads.h.
+ *
+ * @param[in] newstate the new thread state
+ * @param[in] time the number of ticks before the operation timeouts, the
+ * special values are handled as follow:
+ * - @a TIME_INFINITE the thread enters an infinite sleep
+ * state, this is equivalent to invoking @p chSchGoSleepS()
+ * but, of course, less efficient.
+ * - @a TIME_IMMEDIATE this value is accepted but interpreted
+ * as a normal time specification not as an immediate timeout
+ * specification.
+ * .
+ * @return The wakeup message.
+ * @retval RDY_TIMEOUT if a timeout occurs.
+ */
+msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t time) {
+
+ if (TIME_INFINITE != time) {
+ VirtualTimer vt;
+
+ chVTSetI(&vt, time, wakeup, currp);
+ chSchGoSleepS(newstate);
+ if (chVTIsArmedI(&vt))
+ chVTResetI(&vt);
+ }
+ else
+ chSchGoSleepS(newstate);
+ return currp->p_rdymsg;
+}
+
+/**
+ * @brief Wakes up a thread.
+ * @details The thread is inserted into the ready list or immediately made
+ * running depending on its relative priority compared to the current
+ * thread.
+ *
+ * @param[in] ntp the Thread to be made ready
+ * @param[in] msg message to the awakened thread
+ * @note It is equivalent to a @p chSchReadyI() followed by a
+ * @p chSchRescheduleS() but much more efficient.
+ */
+void chSchWakeupS(Thread *ntp, msg_t msg) {
+
+ ntp->p_rdymsg = msg;
+ /* If the waken thread has a not-greater priority than the current
+ * one then it is just inserted in the ready list else it made
+ * running immediately and the invoking thread goes in the ready
+ * list instead.*/
+ if (ntp->p_prio <= currp->p_prio)
+ chSchReadyI(ntp);
+ else {
+ Thread *otp = currp;
+ chSchReadyI(otp);
+ (currp = ntp)->p_state = PRCURR;
+#if CH_USE_ROUNDROBIN
+ rlist.r_preempt = CH_TIME_QUANTUM;
+#endif
+ chDbgTrace(otp, ntp);
+ chSysSwitchI(otp, ntp);
+ }
+}
+
+/**
+ * @brief Switches to the first thread on the runnable queue.
+ *
+ * @note It is intended to be called if @p chSchRescRequiredI() evaluates to
+ * @p TRUE.
+ */
+void chSchDoRescheduleI(void) {
+
+ Thread *otp = currp;
+ /* pick the first thread from the ready queue and makes it current */
+ (currp = fifo_remove((void *)&rlist))->p_state = PRCURR;
+ chSchReadyI(otp);
+#if CH_USE_ROUNDROBIN
+ rlist.r_preempt = CH_TIME_QUANTUM;
+#endif
+ chDbgTrace(otp, currp);
+ chSysSwitchI(otp, currp);
+}
+
+/**
+ * @brief Performs a reschedulation if a higher priority thread is runnable.
+ * @details If a thread with a higher priority than the current thread is in
+ * the ready list then make the higher priority thread running.
+ */
+void chSchRescheduleS(void) {
+ /* first thread in the runnable queue has higher priority than the running
+ * thread? */
+ if (firstprio(&rlist) > currp->p_prio)
+ chSchDoRescheduleI();
+}
+
+/**
+ * @brief Evaluates if a reschedulation is required.
+ * @details The decision is taken by comparing the relative priorities and
+ * depending on the state of the round robin timeout counter.
+ *
+ * @retval TRUE if there is a thread that should go in running state.
+ * @retval FALSE if a reschedulation is not required.
+ */
+bool_t chSchRescRequiredI(void) {
+ tprio_t p1 = firstprio(&rlist);
+ tprio_t p2 = currp->p_prio;
+#if CH_USE_ROUNDROBIN
+ /* If the running thread has not reached its time quantum, reschedule only
+ * if the first thread on the ready queue has a higher priority.
+ * Otherwise, if the running thread has used up its time quantum, reschedule
+ * if the first thread on the ready queue has equal or higher priority.*/
+ return rlist.r_preempt ? p1 > p2 : p1 >= p2;
+#else
+ /* If the round robin feature is not enabled then performs a simpler
+ * comparison.*/
+ return p1 > p2;
+#endif
+}
+
+/** @} */
diff --git a/os/kernel/src/chsem.c b/os/kernel/src/chsem.c
new file mode 100644
index 000000000..9a8570580
--- /dev/null
+++ b/os/kernel/src/chsem.c
@@ -0,0 +1,257 @@
+/*
+ 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/>.
+*/
+
+/**
+ * @file chsem.c
+ * @brief Semaphores code.
+ * @addtogroup Semaphores
+ * @{
+ */
+
+#include <ch.h>
+
+#if CH_USE_SEMAPHORES
+
+#if CH_USE_SEMAPHORES_PRIORITY
+#define sem_insert(tp, qp) prio_insert(tp, qp)
+#else
+#define sem_insert(tp, qp) queue_insert(tp, qp)
+#endif
+
+/**
+ * @brief Initializes a semaphore with the specified counter value.
+ *
+ * @param[out] sp pointer to a @p Semaphore structure
+ * @param[in] n initial value of the semaphore counter. Must be non-negative.
+ * @note This function can be invoked from within an interrupt handler even if
+ * it is not an I-Class API because it does not touch any critical kernel
+ * data structure.
+ */
+void chSemInit(Semaphore *sp, cnt_t n) {
+
+ chDbgCheck((sp != NULL) && (n >= 0), "chSemInit");
+
+ queue_init(&sp->s_queue);
+ sp->s_cnt = n;
+}
+
+/**
+ * @brief Performs a reset operation on the semaphore.
+ *
+ * @param[in] sp pointer to a @p Semaphore structure
+ * @param[in] n the new value of the semaphore counter. The value must be non-negative.
+ * @note The released threads can recognize they were waked up by a reset
+ * instead than a signal because the @p chSemWait() will return
+ * @p RDY_RESET instead of @p RDY_OK.
+ */
+void chSemReset(Semaphore *sp, cnt_t n) {
+
+ chSysLock();
+ chSemResetI(sp, n);
+ chSchRescheduleS();
+ chSysUnlock();
+}
+
+/**
+ * @brief Performs a reset operation on the semaphore.
+ *
+ * @param[in] sp pointer to a @p Semaphore structure
+ * @param[in] n the new value of the semaphore counter. The value must be non-negative.
+ * @note The released threads can recognize they were waked up by a reset
+ * instead than a signal because the @p chSemWait() will return
+ * @p RDY_RESET instead of @p RDY_OK.
+ * @note This function does not reschedule.
+ */
+void chSemResetI(Semaphore *sp, cnt_t n) {
+ cnt_t cnt;
+
+ chDbgCheck((sp != NULL) && (n >= 0), "chSemResetI");
+
+ cnt = sp->s_cnt;
+ sp->s_cnt = n;
+ while (cnt++ < 0)
+ chSchReadyI(lifo_remove(&sp->s_queue))->p_rdymsg = RDY_RESET;
+}
+
+/**
+ * @brief Performs a wait operation on a semaphore.
+ *
+ * @param[in] sp pointer to a @p Semaphore structure
+ * @retval RDY_OK if the semaphore was signaled or not taken.
+ * @retval RDY_RESET if the semaphore was reset using @p chSemReset().
+ */
+msg_t chSemWait(Semaphore *sp) {
+ msg_t msg;
+
+ chSysLock();
+ msg = chSemWaitS(sp);
+ chSysUnlock();
+ return msg;
+}
+
+/**
+ * @brief Performs a wait operation on a semaphore.
+ *
+ * @param[in] sp pointer to a @p Semaphore structure
+ * @retval RDY_OK if the semaphore was signaled or not taken.
+ * @retval RDY_RESET if the semaphore was reset using @p chSemReset().
+ * @note This function must be called with interrupts disabled.
+ * @note This function cannot be called by an interrupt handler.
+ */
+msg_t chSemWaitS(Semaphore *sp) {
+
+ chDbgCheck(sp != NULL, "chSemWaitS");
+
+ if (--sp->s_cnt < 0) {
+ sem_insert(currp, &sp->s_queue);
+ currp->p_wtsemp = sp;
+ chSchGoSleepS(PRWTSEM);
+ return currp->p_rdymsg;
+ }
+ return RDY_OK;
+}
+
+/**
+ * @brief Performs a wait operation on a semaphore with timeout specification.
+ *
+ * @param[in] sp pointer to a @p Semaphore structure
+ * @param[in] time the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @retval RDY_OK if the semaphore was signaled or not taken.
+ * @retval RDY_RESET if the semaphore was reset using @p chSemReset().
+ * @retval RDY_TIMEOUT if the semaphore was not signaled or reset within the
+ * specified timeout.
+ */
+msg_t chSemWaitTimeout(Semaphore *sp, systime_t time) {
+ msg_t msg;
+
+ chSysLock();
+ msg = chSemWaitTimeoutS(sp, time);
+ chSysUnlock();
+ return msg;
+}
+
+/**
+ * @brief Performs a wait operation on a semaphore with timeout specification.
+ *
+ * @param[in] sp pointer to a @p Semaphore structure
+ * @param[in] time the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @retval RDY_OK if the semaphore was signaled or not taken.
+ * @retval RDY_RESET if the semaphore was reset using @p chSemReset().
+ * @retval RDY_TIMEOUT if the semaphore was not signaled or reset within the specified
+ * timeout.
+ */
+msg_t chSemWaitTimeoutS(Semaphore *sp, systime_t time) {
+
+ chDbgCheck(sp != NULL, "chSemWaitTimeoutS");
+
+ if (--sp->s_cnt < 0) {
+ if (TIME_IMMEDIATE == time) {
+ sp->s_cnt++;
+ return RDY_TIMEOUT;
+ }
+ sem_insert(currp, &sp->s_queue);
+ currp->p_wtsemp = sp;
+ return chSchGoSleepTimeoutS(PRWTSEM, time);
+ }
+ return RDY_OK;
+}
+
+/**
+ * @brief Performs a signal operation on a semaphore.
+ *
+ * @param[in] 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) {
+
+ chDbgCheck(sp != NULL, "chSemSignal");
+
+ chSysLock();
+ if (sp->s_cnt++ < 0)
+ chSchWakeupS(fifo_remove(&sp->s_queue), RDY_OK);
+ chSysUnlock();
+}
+
+/**
+ * @brief Performs a signal operation on a semaphore.
+ *
+ * @param[in] 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.
+ * @note This function does not reschedule.
+ */
+void chSemSignalI(Semaphore *sp) {
+
+ chDbgCheck(sp != NULL, "chSemSignalI");
+
+ if (sp->s_cnt++ < 0) {
+ /* NOTE: It is done this way in order to allow a tail call on
+ chSchReadyI().*/
+ Thread *tp = fifo_remove(&sp->s_queue);
+ tp->p_rdymsg = RDY_OK;
+ chSchReadyI(tp);
+ }
+}
+
+#if CH_USE_SEMSW
+/**
+ * @brief Performs atomic signal and wait operations on two semaphores.
+ *
+ * @param[in] sps pointer to a @p Semaphore structure to be signaled
+ * @param[in] spw pointer to a @p Semaphore structure to be wait on
+ * @retval RDY_OK if the semaphore was signaled or not taken.
+ * @retval RDY_RESET if the semaphore was reset using @p chSemReset().
+ * @note The function is available only if the @p CH_USE_SEMSW
+ * option is enabled in @p chconf.h.
+ */
+msg_t chSemSignalWait(Semaphore *sps, Semaphore *spw) {
+ msg_t msg;
+
+ chDbgCheck((sps != NULL) && (spw != NULL), "chSemSignalWait");
+
+ chSysLock();
+ if (sps->s_cnt++ < 0)
+ chSchReadyI(fifo_remove(&sps->s_queue))->p_rdymsg = RDY_OK;
+ if (--spw->s_cnt < 0) {
+ sem_insert(currp, &spw->s_queue);
+ currp->p_wtsemp = spw;
+ chSchGoSleepS(PRWTSEM);
+ msg = currp->p_rdymsg;
+ }
+ else {
+ chSchRescheduleS();
+ msg = RDY_OK;
+ }
+ chSysUnlock();
+ return msg;
+}
+#endif /* CH_USE_SEMSW */
+
+#endif /* CH_USE_SEMAPHORES */
+
+/** @} */
diff --git a/os/kernel/src/chserial.c b/os/kernel/src/chserial.c
new file mode 100644
index 000000000..65179689d
--- /dev/null
+++ b/os/kernel/src/chserial.c
@@ -0,0 +1,168 @@
+/*
+ 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/>.
+*/
+
+/**
+ * @file chserial.c
+ * @brief Serial Drivers code.
+ * @addtogroup Serial
+ * @{
+ */
+
+#include <ch.h>
+
+#if CH_USE_SERIAL_FULLDUPLEX
+
+/*
+ * Interface implementation, the following functions just invoke the equivalent
+ * queue-level function or macro.
+ */
+static bool_t putwouldblock(void *instance) {
+
+ return chOQIsFull(&((FullDuplexDriver *)instance)->d2.oqueue);
+}
+
+static bool_t getwouldblock(void *instance) {
+
+ return chIQIsEmpty(&((FullDuplexDriver *)instance)->d2.iqueue);
+}
+
+static msg_t put(void *instance, uint8_t b, systime_t timeout) {
+
+ return chOQPutTimeout(&((FullDuplexDriver *)instance)->d2.oqueue, b, timeout);
+}
+
+static msg_t get(void *instance, systime_t timeout) {
+
+ return chIQGetTimeout(&((FullDuplexDriver *)instance)->d2.iqueue, timeout);
+}
+
+static size_t write(void *instance, uint8_t *buffer, size_t n) {
+
+ return chOQWrite(&((FullDuplexDriver *)instance)->d2.oqueue, buffer, n);
+}
+
+static size_t read(void *instance, uint8_t *buffer, size_t n) {
+
+ return chIQRead(&((FullDuplexDriver *)instance)->d2.iqueue, buffer, n);
+}
+
+static const struct FullDuplexDriverVMT vmt = {
+ {putwouldblock, getwouldblock, put, get},
+ {write, read},
+ {}
+};
+
+/**
+ * @brief Initializes a generic full duplex driver.
+ * @details The HW dependent part of the initialization has to be performed
+ * outside, usually in the hardware initialization code.
+ *
+ * @param[out] sd pointer to a @p FullDuplexDriver structure
+ * @param[in] ib pointer to a memory area allocated for the Input Queue buffer
+ * @param[in] isize size of the Input Queue buffer
+ * @param[in] inotify pointer to a callback function that is invoked when
+ * some data is read from the Queue. The value can be
+ * @p NULL.
+ * @param[in] ob pointer to a memory area allocated for the Output Queue buffer
+ * @param[in] osize size of the Output Queue buffer
+ * @param[in] 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,
+ uint8_t *ib, size_t isize, qnotify_t inotify,
+ uint8_t *ob, size_t osize, qnotify_t onotify) {
+
+ chDbgCheck((sd != NULL) && (ib != NULL) && (ob != NULL) &&
+ (isize > 0) && (osize > 0), "chFDDInit");
+
+ sd->vmt = &vmt;
+ chEvtInit(&sd->d1.ievent);
+ chEvtInit(&sd->d1.oevent);
+ chEvtInit(&sd->d2.sevent);
+ sd->d2.flags = SD_NO_ERROR;
+ chIQInit(&sd->d2.iqueue, ib, isize, inotify);
+ chOQInit(&sd->d2.oqueue, ob, osize, onotify);
+}
+
+/**
+ * @brief Handles incoming data.
+ * @details This function must be called from the input interrupt service
+ * routine in order to enqueue incoming data and generate the
+ * related events.
+ * @param[in] sd pointer to a @p FullDuplexDriver structure
+ * @param[in] b the byte to be written in the driver's Input Queue
+ */
+void chFDDIncomingDataI(FullDuplexDriver *sd, uint8_t b) {
+
+ if (chIQPutI(&sd->d2.iqueue, b) < Q_OK)
+ chFDDAddFlagsI(sd, SD_OVERRUN_ERROR);
+ else
+ chEvtBroadcastI(&sd->d1.ievent);
+}
+
+/**
+ * @brief Handles outgoing data.
+ * @details Must be called from the output interrupt service routine in order
+ * to get the next byte to be transmitted.
+ *
+ * @param[in] sd pointer to a @p FullDuplexDriver structure
+ * @return The byte value read from the driver's output queue.
+ * @retval Q_EMPTY if the queue is empty (the lower driver usually disables
+ * the interrupt source when this happens).
+ */
+msg_t chFDDRequestDataI(FullDuplexDriver *sd) {
+
+ msg_t b = chOQGetI(&sd->d2.oqueue);
+ if (b < Q_OK)
+ chEvtBroadcastI(&sd->d1.oevent);
+ return b;
+}
+
+/**
+ * @brief Handles communication events/errors.
+ * @details Must be called from the I/O interrupt service routine in order to
+ * notify I/O conditions as errors, signals change etc.
+ *
+ * @param[in] sd pointer to a @p FullDuplexDriver structure
+ * @param[in] mask condition flags to be added to the mask
+ */
+void chFDDAddFlagsI(FullDuplexDriver *sd, dflags_t mask) {
+
+ sd->d2.flags |= mask;
+ chEvtBroadcastI(&sd->d2.sevent);
+}
+
+/**
+ * @brief Returns and clears the errors mask associated to the driver.
+ *
+ * @param[in] sd pointer to a @p FullDuplexDriver structure
+ * @return The condition flags modified since last time this function was
+ * invoked.
+ */
+dflags_t chFDDGetAndClearFlags(FullDuplexDriver *sd) {
+ dflags_t mask;
+
+ mask = sd->d2.flags;
+ sd->d2.flags = SD_NO_ERROR;
+ return mask;
+}
+#endif /* CH_USE_SERIAL_FULLDUPLEX */
+
+/** @} */
diff --git a/os/kernel/src/chsys.c b/os/kernel/src/chsys.c
new file mode 100644
index 000000000..217e2f2da
--- /dev/null
+++ b/os/kernel/src/chsys.c
@@ -0,0 +1,129 @@
+/*
+ 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/>.
+*/
+
+/**
+ * @file chsys.c
+ * @brief System related code.
+ * @addtogroup System
+ * @{
+ */
+
+#include <ch.h>
+
+static WORKING_AREA(idle_thread_wa, IDLE_THREAD_STACK_SIZE);
+
+/**
+ * @brief This function implements the idle thread infinite loop.
+ * @details The function puts the processor in the lowest power mode capable
+ * to serve interrupts.<br>
+ * The priority is internally set to the minimum system value so
+ * that this thread is executed only if there are no other ready
+ * threads in the system.
+ *
+ * @param[in] p the thread parameter, unused in this scenario
+ */
+static void idle_thread(void *p) {
+
+ while (TRUE) {
+ port_wait_for_interrupt();
+ IDLE_LOOP_HOOK();
+ }
+}
+
+/**
+ * @brief ChibiOS/RT initialization.
+ * @details After executing this function the current instructions stream
+ * becomes the main thread.
+ *
+ * @note Interrupts should be still disabled when @p chSysInit() is invoked
+ * and are internally enabled.
+ * @note The main thread is created with priority @p NORMALPRIO.
+ */
+void chSysInit(void) {
+ static Thread mainthread;
+
+ port_init();
+ scheduler_init();
+ vt_init();
+#if CH_USE_HEAP
+ heap_init();
+#endif
+#if CH_DBG_ENABLE_TRACE
+ trace_init();
+#endif
+
+ /*
+ * Now this instructions flow becomes the main thread.
+ */
+ (currp = init_thread(&mainthread, NORMALPRIO))->p_state = PRCURR;
+ chSysEnable();
+
+ /*
+ * This thread has the lowest priority in the system, its role is just to
+ * serve interrupts in its context while keeping the lowest energy saving
+ * mode compatible with the system status.
+ */
+ chThdCreateStatic(idle_thread_wa, sizeof(idle_thread_wa), IDLEPRIO,
+ (tfunc_t)idle_thread, NULL);
+}
+
+/**
+ * @brief Handles time ticks for round robin preemption and timer increments.
+ * @details Decrements the remaining time quantum of the running thread
+ * and preempts it when the quantum is used up. Increments system
+ * time and manages the timers.
+ *
+ * @note The frequency of the timer determines the system tick granularity and,
+ * together with the @p CH_TIME_QUANTUM macro, the round robin interval.
+ */
+void chSysTimerHandlerI(void) {
+
+#if CH_USE_ROUNDROBIN
+ /* running thread has not used up quantum yet? */
+ if (rlist.r_preempt > 0)
+ /* decrement remaining quantum */
+ rlist.r_preempt--;
+#endif
+#if CH_DBG_THREADS_PROFILING
+ currp->p_time++;
+#endif
+ chVTDoTickI();
+}
+
+#if CH_USE_NESTED_LOCKS && !CH_OPTIMIZE_SPEED
+void chSysLock(void) {
+
+ chDbgAssert(currp->p_locks >= 0,
+ "chSysLock(), #1",
+ "negative nesting counter");
+ if (currp->p_locks++ == 0)
+ port_lock();
+}
+
+void chSysUnlock(void) {
+
+ chDbgAssert(currp->p_locks > 0,
+ "chSysUnlock(), #1",
+ "non-positive nesting counter");
+ if (--currp->p_locks == 0)
+ port_unlock();
+}
+#endif /* CH_USE_NESTED_LOCKS && !CH_OPTIMIZE_SPEED */
+
+/** @} */
diff --git a/os/kernel/src/chthreads.c b/os/kernel/src/chthreads.c
new file mode 100644
index 000000000..f8bb3b869
--- /dev/null
+++ b/os/kernel/src/chthreads.c
@@ -0,0 +1,381 @@
+/*
+ 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/>.
+*/
+
+/**
+ * @file chthreads.c
+ * @brief Threads code.
+ * @addtogroup Threads
+ * @{
+ */
+
+#include <ch.h>
+
+/*
+ * Initializes a thread structure.
+ */
+Thread *init_thread(Thread *tp, tprio_t prio) {
+
+ tp->p_flags = P_MEM_MODE_STATIC;
+ tp->p_prio = prio;
+ tp->p_state = PRSUSPENDED;
+#if CH_USE_NESTED_LOCKS
+ tp->p_locks = 0;
+#endif
+#if CH_DBG_THREADS_PROFILING
+ tp->p_time = 0;
+#endif
+#if CH_USE_MUTEXES
+ /* realprio is the thread's own, non-inherited, priority */
+ tp->p_realprio = prio;
+ tp->p_mtxlist = NULL;
+#endif
+#if CH_USE_WAITEXIT
+ tp->p_waiting = NULL;
+#endif
+#if CH_USE_MESSAGES
+ queue_init(&tp->p_msgqueue);
+#endif
+#if CH_USE_EVENTS
+ tp->p_epending = 0;
+#endif
+ THREAD_EXT_INIT(tp);
+ return tp;
+}
+
+#if CH_DBG_FILL_THREADS
+static void memfill(uint8_t *startp, uint8_t *endp, uint8_t v) {
+
+ while (startp < endp)
+ *startp++ = v;
+}
+#endif
+
+/**
+ * @brief Initializes a new thread.
+ * @details The new thread is initialized but not inserted in the ready list,
+ * the initial state is @p PRSUSPENDED.
+ *
+ * @param[out] wsp pointer to a working area dedicated to the thread stack
+ * @param[in] size size of the working area
+ * @param[in] prio the priority level for the new thread
+ * @param[in] pf the thread function
+ * @param[in] 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.
+ * @note This function can be invoked from within an interrupt handler even if
+ * it is not an I-Class API because it does not touch any critical kernel
+ * data structure.
+ */
+Thread *chThdInit(void *wsp, size_t size, tprio_t prio, tfunc_t pf, void *arg) {
+ /* Thread structure is layed out in the lower part of the thread workspace */
+ Thread *tp = wsp;
+
+ chDbgCheck((wsp != NULL) && (size >= THD_WA_SIZE(0)) &&
+ (prio <= HIGHPRIO) && (pf != NULL),
+ "chThdInit");
+#if CH_DBG_FILL_THREADS
+ memfill((uint8_t *)wsp, (uint8_t *)wsp + sizeof(Thread), THREAD_FILL_VALUE);
+ memfill((uint8_t *)wsp + sizeof(Thread),
+ (uint8_t *)wsp + size, STACK_FILL_VALUE);
+#endif
+ SETUP_CONTEXT(wsp, size, pf, arg);
+ return init_thread(tp, prio);
+}
+
+/**
+ * @brief Creates a new thread into a static memory area.
+ *
+ * @param[out] wsp pointer to a working area dedicated to the thread
+ * stack
+ * @param[in] size size of the working area
+ * @param[in] prio the priority level for the new thread
+ * @param[in] pf the thread function
+ * @param[in] 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 *chThdCreateStatic(void *wsp, size_t size,
+ tprio_t prio, tfunc_t pf, void *arg) {
+
+ return chThdResume(chThdInit(wsp, size, prio, pf, arg));
+}
+
+#if CH_USE_DYNAMIC && CH_USE_WAITEXIT && CH_USE_HEAP
+/**
+ * @brief Creates a new thread allocating the memory from the heap.
+ *
+ * @param[in] size size of the working area to be allocated
+ * @param[in] prio the priority level for the new thread
+ * @param[in] pf the thread function
+ * @param[in] 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.
+ * @retval NULL if the memory cannot be allocated.
+ * @note A thread can terminate by calling @p chThdExit() or by simply
+ * returning from its main function.
+ * @note The memory allocated for the thread is not released when the thread
+ * terminates but when a @p chThdWait() is performed.
+ * @note The function is available only if the @p CH_USE_DYNAMIC,
+ * @p CH_USE_HEAP and @p CH_USE_WAITEXIT options are enabled
+ * in @p chconf.h.
+ */
+Thread *chThdCreateFromHeap(size_t size, tprio_t prio, tfunc_t pf, void *arg) {
+ void *wsp;
+ Thread *tp;
+
+ wsp = chHeapAlloc(size);
+ if (wsp == NULL)
+ return NULL;
+ tp = chThdInit(wsp, size, prio, pf, arg);
+ tp->p_flags = P_MEM_MODE_HEAP;
+ return chThdResume(tp);
+}
+#endif /* CH_USE_DYNAMIC && CH_USE_WAITEXIT && CH_USE_HEAP */
+
+#if CH_USE_DYNAMIC && CH_USE_WAITEXIT && CH_USE_MEMPOOLS
+/**
+ * @brief Creates a new thread allocating the memory from the specified Memory
+ * Pool.
+ *
+ * @param[in] mp the memory pool
+ * @param[in] prio the priority level for the new thread
+ * @param[in] pf the thread function
+ * @param[in] 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 or @p NULL if the memory cannot
+ * be allocated.
+ * @retval NULL if the memory pool is empty.
+ * @note A thread can terminate by calling @p chThdExit() or by simply
+ * returning from its main function.
+ * @note The memory allocated for the thread is not released when the thread
+ * terminates but when a @p chThdWait() is performed.
+ * @note The function is available only if the @p CH_USE_DYNAMIC,
+ * @p CH_USE_MEMPOOLS and @p CH_USE_WAITEXIT options are enabled
+ * in @p chconf.h.
+ */
+Thread *chThdCreateFromMemoryPool(MemoryPool *mp, tprio_t prio,
+ tfunc_t pf, void *arg) {
+ void *wsp;
+ Thread *tp;
+
+ chDbgCheck(mp != NULL, "chThdCreateFromMemoryPool");
+
+ wsp = chPoolAlloc(mp);
+ if (wsp == NULL)
+ return NULL;
+ tp = chThdInit(wsp, mp->mp_object_size, prio, pf, arg);
+ tp->p_flags = P_MEM_MODE_MEMPOOL;
+ tp->p_mpool = mp;
+ return chThdResume(tp);
+}
+#endif /* CH_USE_DYNAMIC && CH_USE_WAITEXIT && CH_USE_MEMPOOLS */
+
+/**
+ * @brief Changes the running thread priority level then reschedules if
+ * necessary.
+ *
+ * @param[in] newprio the new priority level of the running thread
+ * @return The old priority level.
+ * @note The function returns the real thread priority regardless of the
+ * current priority that could be higher than the real priority because
+ * the priority inheritance mechanism.
+ */
+tprio_t chThdSetPriority(tprio_t newprio) {
+ tprio_t oldprio;
+
+ chDbgCheck((newprio >= LOWPRIO) && (newprio <= HIGHPRIO),
+ "chThdSetPriority");
+
+ chSysLock();
+#if CH_USE_MUTEXES
+ oldprio = currp->p_realprio;
+ if ((currp->p_prio == currp->p_realprio) || (newprio > currp->p_prio))
+ currp->p_prio = newprio;
+ currp->p_realprio = newprio;
+#else
+ oldprio = currp->p_prio;
+ currp->p_prio = newprio;
+#endif
+ chSchRescheduleS();
+ chSysUnlock();
+ return oldprio;
+}
+
+/**
+ * @brief Resumes a suspended thread.
+ *
+ * @param[in] tp the pointer to the thread
+ * @return The pointer to the thread.
+ * @note This call is supposed to resume threads created with @p chThdInit().
+ * It should not be used on threads suspended using @p chThdSuspend().
+ */
+Thread *chThdResume(Thread *tp) {
+
+ chSysLock();
+ chDbgAssert(tp->p_state == PRSUSPENDED,
+ "chThdResume(), #1",
+ "thread not in PRSUSPENDED state");
+ chSchWakeupS(tp, RDY_OK);
+ chSysUnlock();
+ return tp;
+}
+
+/**
+ * @brief Requests a thread termination.
+ *
+ * @param[in] 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();
+}
+
+/**
+ * @brief Suspends the invoking thread for the specified time.
+ *
+ * @param[in] time the delay in system ticks, the special values are handled as
+ * follow:
+ * - @a TIME_INFINITE the thread enters an infinite sleep
+ * state.
+ * - @a TIME_IMMEDIATE this value is accepted but interpreted
+ * as a normal time specification not as an immediate timeout
+ * specification.
+ * .
+ */
+void chThdSleep(systime_t time) {
+
+ chDbgCheck(time != TIME_INFINITE, "chThdSleep");
+
+ chSysLock();
+ chThdSleepS(time);
+ chSysUnlock();
+}
+
+/**
+ * @brief Suspends the invoking thread until the system time arrives to the
+ * specified value.
+ *
+ * @param[in] time the absolute system time
+ */
+void chThdSleepUntil(systime_t time) {
+
+ chSysLock();
+ if ((time -= chTimeNow()) > 0)
+ chThdSleepS(time);
+ chSysUnlock();
+}
+
+/**
+ * @brief Terminates the current thread by specifying an exit status code.
+ *
+ * @param[in] msg the thread exit code. The code can be retrieved by using
+ * @p chThdWait().
+ */
+void chThdExit(msg_t msg) {
+ Thread *tp = currp;
+
+ chSysLock();
+ tp->p_exitcode = msg;
+ THREAD_EXT_EXIT(tp);
+#if CH_USE_WAITEXIT
+ if (tp->p_waiting != NULL)
+ chSchReadyI(tp->p_waiting);
+#endif
+ chSchGoSleepS(PREXIT);
+}
+
+#if CH_USE_WAITEXIT
+/**
+ * @brief Blocks the execution of the invoking thread until the specified
+ * thread terminates then the exit code is returned.
+ * @details The memory used by the exited thread is handled in different ways
+ * depending on the API that spawned the thread:
+ * - If the thread was spawned by @p chThdCreateStatic() or by
+ * @p chThdInit() then nothing happens and the thread working area
+ * is not released or modified in any way. This is the default,
+ * totally static, behavior.
+ * - If the thread was spawned by @p chThdCreateFromHeap() then
+ * the working area is returned to the system heap.
+ * - If the thread was spawned by @p chThdCreateFromMemoryPool()
+ * then the working area is returned to the owning memory pool.
+ * .
+ * @param[in] tp the thread pointer
+ * @return The exit code from the terminated thread
+ * @note After invoking @p chThdWait() the thread pointer becomes invalid and
+ * must not be used as parameter for further system calls.
+ * @note The function is available only if the @p CH_USE_WAITEXIT
+ * option is enabled in @p chconf.h.
+ * @note Only one thread can be waiting for another thread at any time. You
+ * should imagine the threads as having a reference counter that is set
+ * to one when the thread is created, chThdWait() decreases the reference
+ * and the memory is freed when the counter reaches zero. In the current
+ * implementation there is no real reference counter in the thread
+ * structure but it is a planned extension.
+ */
+msg_t chThdWait(Thread *tp) {
+ msg_t msg;
+
+ chDbgCheck(tp != NULL, "chThdWait");
+
+ chSysLock();
+
+ chDbgAssert(tp != currp, "chThdWait(), #1", "waiting self");
+ chDbgAssert(tp->p_waiting == NULL, "chThdWait(), #2", "some other thread waiting");
+
+ if (tp->p_state != PREXIT) {
+ tp->p_waiting = currp;
+ chSchGoSleepS(PRWAIT);
+ }
+ msg = tp->p_exitcode;
+#if !CH_USE_DYNAMIC
+ chSysUnlock();
+ return msg;
+#else /* CH_USE_DYNAMIC */
+
+ /* Returning memory.*/
+ tmode_t mode = tp->p_flags & P_MEM_MODE_MASK;
+ chSysUnlock();
+
+ switch (mode) {
+#if CH_USE_HEAP
+ case P_MEM_MODE_HEAP:
+ chHeapFree(tp);
+ break;
+#endif
+#if CH_USE_MEMPOOLS
+ case P_MEM_MODE_MEMPOOL:
+ chPoolFree(tp->p_mpool, tp);
+ break;
+#endif
+ }
+ return msg;
+#endif /* CH_USE_DYNAMIC */
+}
+#endif /* CH_USE_WAITEXIT */
+
+/** @} */
diff --git a/os/kernel/src/chvt.c b/os/kernel/src/chvt.c
new file mode 100644
index 000000000..c1d8734ec
--- /dev/null
+++ b/os/kernel/src/chvt.c
@@ -0,0 +1,116 @@
+/*
+ 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/>.
+*/
+
+/**
+ * @file chvt.c
+ * @brief Time and Virtual Timers related code.
+ * @addtogroup Time
+ * @{
+ */
+
+#include <ch.h>
+
+VTList vtlist;
+
+/**
+ * @brief Virtual Timers initialization.
+ *
+ * @note Internal use only.
+ */
+void vt_init(void) {
+
+ vtlist.vt_next = vtlist.vt_prev = (void *)&vtlist;
+ vtlist.vt_time = (systime_t)-1;
+ vtlist.vt_systime = 0;
+}
+
+/**
+ * @brief Enables a virtual timer.
+ *
+ * @param[out] vtp the @p VirtualTimer structure pointer
+ * @param[in] time the number of time ticks, the value @p TIME_INFINITE is not
+ * allowed. The value @p TIME_IMMEDIATE is allowed but
+ * interpreted as a normal time specification not as an
+ * immediate timeout specification.
+ * @param[in] vtfunc the timer callback function. After invoking the callback
+ * the timer is disabled and the structure can be disposed or
+ * reused.
+ * @param[in] par a parameter that will be passed to the callback function
+ * @note The associated function is invoked by an interrupt handler within
+ * the I-Locked state, see @ref system_states.
+ */
+void chVTSetI(VirtualTimer *vtp, systime_t time, vtfunc_t vtfunc, void *par) {
+ VirtualTimer *p;
+
+ chDbgCheck((vtp != NULL) && (vtfunc != NULL) && (time != TIME_INFINITE),
+ "chVTSetI");
+
+ vtp->vt_par = par;
+ vtp->vt_func = vtfunc;
+ p = vtlist.vt_next;
+ while (p->vt_time < time) {
+ time -= p->vt_time;
+ p = p->vt_next;
+ }
+
+ vtp->vt_prev = (vtp->vt_next = p)->vt_prev;
+ vtp->vt_prev->vt_next = p->vt_prev = vtp;
+ vtp->vt_time = time;
+ if (p != (void *)&vtlist)
+ p->vt_time -= time;
+}
+
+/**
+ * @brief Disables a Virtual Timer.
+ *
+ * @param[in] vtp the @p VirtualTimer structure pointer
+ * @note The timer MUST be active when this function is invoked.
+ */
+void chVTResetI(VirtualTimer *vtp) {
+
+ chDbgCheck(vtp != NULL, "chVTResetI");
+ chDbgAssert(vtp->vt_func != NULL,
+ "chVTResetI(), #1",
+ "timer not set or already triggered");
+
+ if (vtp->vt_next != (void *)&vtlist)
+ vtp->vt_next->vt_time += vtp->vt_time;
+ vtp->vt_prev->vt_next = vtp->vt_next;
+ vtp->vt_next->vt_prev = vtp->vt_prev;
+ vtp->vt_func = NULL;
+}
+
+/**
+ * @brief Checks if the current system time is within the specified time window.
+ *
+ * @param[in] start the start of the time window (inclusive)
+ * @param[in] end the end of the time window (non inclusive)
+ * @retval TRUE current time within the specified time window.
+ * @retval FALSE current time not within the specified time window.
+ * @note When start==end then the function returns always true because the
+ * whole time range is specified.
+ */
+bool_t chTimeIsWithin(systime_t start, systime_t end) {
+
+ systime_t time = chTimeNow();
+ return end > start ? (time >= start) && (time < end) :
+ (time >= start) || (time < end);
+}
+
+/** @} */