aboutsummaryrefslogtreecommitdiffstats
path: root/os/various
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2013-06-15 15:58:20 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2013-06-15 15:58:20 +0000
commit7c68ef157d009f9932ac47ba21ba5d74e321623f (patch)
tree6c2442ca44cd090656ec3059ffb959f3d747e18d /os/various
parent076746af63d317f8e96766b9137a65679f60463f (diff)
parente0d850113610f3efa0c0ac4946901f683e5e7332 (diff)
downloadChibiOS-7c68ef157d009f9932ac47ba21ba5d74e321623f.tar.gz
ChibiOS-7c68ef157d009f9932ac47ba21ba5d74e321623f.tar.bz2
ChibiOS-7c68ef157d009f9932ac47ba21ba5d74e321623f.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@5854 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/various')
-rw-r--r--os/various/chprintf.c263
-rw-r--r--os/various/chprintf.h45
-rw-r--r--os/various/chrtclib.c359
-rw-r--r--os/various/chrtclib.h55
-rw-r--r--os/various/cpp_wrappers/ch.cpp866
-rw-r--r--os/various/cpp_wrappers/ch.hpp2282
-rw-r--r--os/various/cpp_wrappers/kernel.mk4
-rw-r--r--os/various/devices_lib/accel/lis302dl.c119
-rw-r--r--os/various/devices_lib/accel/lis302dl.dox30
-rw-r--r--os/various/devices_lib/accel/lis302dl.h93
-rw-r--r--os/various/devices_lib/lcd/lcd3310.c310
-rw-r--r--os/various/devices_lib/lcd/lcd3310.h94
-rw-r--r--os/various/evtimer.c64
-rw-r--r--os/various/evtimer.h68
-rw-r--r--os/various/fatfs_bindings/fatfs.mk7
-rw-r--r--os/various/fatfs_bindings/fatfs_diskio.c254
-rw-r--r--os/various/fatfs_bindings/fatfs_syscall.c84
-rw-r--r--os/various/fatfs_bindings/readme.txt6
-rw-r--r--os/various/lwip_bindings/arch/cc.h72
-rw-r--r--os/various/lwip_bindings/arch/perf.h57
-rw-r--r--os/various/lwip_bindings/arch/sys_arch.c235
-rw-r--r--os/various/lwip_bindings/arch/sys_arch.h68
-rw-r--r--os/various/lwip_bindings/lwip.mk54
-rw-r--r--os/various/lwip_bindings/lwipthread.c303
-rw-r--r--os/various/lwip_bindings/lwipthread.h131
-rw-r--r--os/various/lwip_bindings/readme.txt6
-rw-r--r--os/various/memstreams.c113
-rw-r--r--os/various/memstreams.h94
-rw-r--r--os/various/shell.c286
-rw-r--r--os/various/shell.h83
-rw-r--r--os/various/syscalls.c172
-rw-r--r--os/various/usb_msc.c299
-rw-r--r--os/various/usb_msc.h163
-rw-r--r--os/various/various.dox93
34 files changed, 7232 insertions, 0 deletions
diff --git a/os/various/chprintf.c b/os/various/chprintf.c
new file mode 100644
index 000000000..d712b98ab
--- /dev/null
+++ b/os/various/chprintf.c
@@ -0,0 +1,263 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ Concepts and parts of this file have been contributed by Fabio Utzig.
+ */
+
+/**
+ * @file chprintf.c
+ * @brief Mini printf-like functionality.
+ *
+ * @addtogroup chprintf
+ * @{
+ */
+
+#include <stdarg.h>
+
+#include "ch.h"
+#include "chprintf.h"
+
+#define MAX_FILLER 11
+#define FLOAT_PRECISION 100000
+
+static char *long_to_string_with_divisor(char *p,
+ long num,
+ unsigned radix,
+ long divisor) {
+ int i;
+ char *q;
+ long l, ll;
+
+ l = num;
+ if (divisor == 0) {
+ ll = num;
+ } else {
+ ll = divisor;
+ }
+
+ q = p + MAX_FILLER;
+ do {
+ i = (int)(l % radix);
+ i += '0';
+ if (i > '9')
+ i += 'A' - '0' - 10;
+ *--q = i;
+ l /= radix;
+ } while ((ll /= radix) != 0);
+
+ i = (int)(p + MAX_FILLER - q);
+ do
+ *p++ = *q++;
+ while (--i);
+
+ return p;
+}
+
+static char *ltoa(char *p, long num, unsigned radix) {
+
+ return long_to_string_with_divisor(p, num, radix, 0);
+}
+
+#if CHPRINTF_USE_FLOAT
+static char *ftoa(char *p, double num) {
+ long l;
+ unsigned long precision = FLOAT_PRECISION;
+
+ l = num;
+ p = long_to_string_with_divisor(p, l, 10, 0);
+ *p++ = '.';
+ l = (num - l) * precision;
+ return long_to_string_with_divisor(p, l, 10, precision / 10);
+}
+#endif
+
+/**
+ * @brief System formatted output function.
+ * @details This function implements a minimal @p printf() like functionality
+ * with output on a @p BaseSequentialStream.
+ * The general parameters format is: %[-][width|*][.precision|*][l|L]p.
+ * The following parameter types (p) are supported:
+ * - <b>x</b> hexadecimal integer.
+ * - <b>X</b> hexadecimal long.
+ * - <b>o</b> octal integer.
+ * - <b>O</b> octal long.
+ * - <b>d</b> decimal signed integer.
+ * - <b>D</b> decimal signed long.
+ * - <b>u</b> decimal unsigned integer.
+ * - <b>U</b> decimal unsigned long.
+ * - <b>c</b> character.
+ * - <b>s</b> string.
+ * .
+ *
+ * @param[in] chp pointer to a @p BaseSequentialStream implementing object
+ * @param[in] fmt formatting string
+ */
+void chprintf(BaseSequentialStream *chp, const char *fmt, ...) {
+ va_list ap;
+ char *p, *s, c, filler;
+ int i, precision, width;
+ bool_t is_long, left_align;
+ long l;
+#if CHPRINTF_USE_FLOAT
+ float f;
+ char tmpbuf[2*MAX_FILLER + 1];
+#else
+ char tmpbuf[MAX_FILLER + 1];
+#endif
+
+ va_start(ap, fmt);
+ while (TRUE) {
+ c = *fmt++;
+ if (c == 0) {
+ va_end(ap);
+ return;
+ }
+ if (c != '%') {
+ chSequentialStreamPut(chp, (uint8_t)c);
+ continue;
+ }
+ p = tmpbuf;
+ s = tmpbuf;
+ left_align = FALSE;
+ if (*fmt == '-') {
+ fmt++;
+ left_align = TRUE;
+ }
+ filler = ' ';
+ if ((*fmt == '.') || (*fmt == '0')) {
+ fmt++;
+ filler = '0';
+ }
+ width = 0;
+ while (TRUE) {
+ c = *fmt++;
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c == '*')
+ c = va_arg(ap, int);
+ else
+ break;
+ width = width * 10 + c;
+ }
+ precision = 0;
+ if (c == '.') {
+ while (TRUE) {
+ c = *fmt++;
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c == '*')
+ c = va_arg(ap, int);
+ else
+ break;
+ precision *= 10;
+ precision += c;
+ }
+ }
+ /* Long modifier.*/
+ if (c == 'l' || c == 'L') {
+ is_long = TRUE;
+ if (*fmt)
+ c = *fmt++;
+ }
+ else
+ is_long = (c >= 'A') && (c <= 'Z');
+
+ /* Command decoding.*/
+ switch (c) {
+ case 'c':
+ filler = ' ';
+ *p++ = va_arg(ap, int);
+ break;
+ case 's':
+ filler = ' ';
+ if ((s = va_arg(ap, char *)) == 0)
+ s = "(null)";
+ if (precision == 0)
+ precision = 32767;
+ for (p = s; *p && (--precision >= 0); p++)
+ ;
+ break;
+ case 'D':
+ case 'd':
+ case 'I':
+ case 'i':
+ if (is_long)
+ l = va_arg(ap, long);
+ else
+ l = va_arg(ap, int);
+ if (l < 0) {
+ *p++ = '-';
+ l = -l;
+ }
+ p = ltoa(p, l, 10);
+ break;
+#if CHPRINTF_USE_FLOAT
+ case 'f':
+ f = (float) va_arg(ap, double);
+ if (f < 0) {
+ *p++ = '-';
+ f = -f;
+ }
+ p = ftoa(p, f);
+ break;
+#endif
+ case 'X':
+ case 'x':
+ c = 16;
+ goto unsigned_common;
+ case 'U':
+ case 'u':
+ c = 10;
+ goto unsigned_common;
+ case 'O':
+ case 'o':
+ c = 8;
+unsigned_common:
+ if (is_long)
+ l = va_arg(ap, unsigned long);
+ else
+ l = va_arg(ap, unsigned int);
+ p = ltoa(p, l, c);
+ break;
+ default:
+ *p++ = c;
+ break;
+ }
+ i = (int)(p - s);
+ if ((width -= i) < 0)
+ width = 0;
+ if (left_align == FALSE)
+ width = -width;
+ if (width < 0) {
+ if (*s == '-' && filler == '0') {
+ chSequentialStreamPut(chp, (uint8_t)*s++);
+ i--;
+ }
+ do
+ chSequentialStreamPut(chp, (uint8_t)filler);
+ while (++width != 0);
+ }
+ while (--i >= 0)
+ chSequentialStreamPut(chp, (uint8_t)*s++);
+
+ while (width) {
+ chSequentialStreamPut(chp, (uint8_t)filler);
+ width--;
+ }
+ }
+}
+
+/** @} */
diff --git a/os/various/chprintf.h b/os/various/chprintf.h
new file mode 100644
index 000000000..1d758f680
--- /dev/null
+++ b/os/various/chprintf.h
@@ -0,0 +1,45 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file chprintf.h
+ * @brief Mini printf-like functionality.
+ *
+ * @addtogroup chprintf
+ * @{
+ */
+
+#ifndef _CHPRINTF_H_
+#define _CHPRINTF_H_
+
+/**
+ * @brief Float type support.
+ */
+#if !defined(CHPRINTF_USE_FLOAT) || defined(__DOXYGEN__)
+#define CHPRINTF_USE_FLOAT FALSE
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void chprintf(BaseSequentialStream *chp, const char *fmt, ...);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CHPRINTF_H_ */
+
+/** @} */
diff --git a/os/various/chrtclib.c b/os/various/chrtclib.c
new file mode 100644
index 000000000..f8a6a86ff
--- /dev/null
+++ b/os/various/chrtclib.c
@@ -0,0 +1,359 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ Concepts and parts of this file have been contributed by Uladzimir Pylinsky
+ aka barthess.
+ */
+
+/**
+ * @file chrtclib.c
+ * @brief RTC time conversion utilities code.
+ *
+ * @addtogroup chrtclib
+ * @{
+ */
+
+#include <time.h>
+
+#include "ch.h"
+#include "hal.h"
+
+#include "chrtclib.h"
+
+#if (defined(STM32F4XX) || defined(STM32F2XX) || defined(STM32L1XX) || \
+ defined(STM32F30X) || defined(STM32F37X) || \
+ defined(STM32F1XX) || defined(STM32F10X_MD) || defined(STM32F10X_LD) || \
+ defined(STM32F10X_HD) || defined(LPC122X) || defined(__DOXYGEN__))
+#if STM32_RTC_IS_CALENDAR
+/**
+ * @brief Converts from STM32 BCD to canonicalized time format.
+ *
+ * @param[out] timp pointer to a @p tm structure as defined in time.h
+ * @param[in] timespec pointer to a @p RTCTime structure
+ *
+ * @notapi
+ */
+static void stm32_rtc_bcd2tm(struct tm *timp, RTCTime *timespec) {
+ uint32_t tv_time = timespec->tv_time;
+ uint32_t tv_date = timespec->tv_date;
+
+#if CH_DBG_ENABLE_CHECKS
+ timp->tm_isdst = 0;
+ timp->tm_wday = 0;
+ timp->tm_mday = 0;
+ timp->tm_yday = 0;
+ timp->tm_mon = 0;
+ timp->tm_year = 0;
+ timp->tm_sec = 0;
+ timp->tm_min = 0;
+ timp->tm_hour = 0;
+#endif
+
+ timp->tm_isdst = -1;
+
+ timp->tm_wday = (tv_date & RTC_DR_WDU) >> RTC_DR_WDU_OFFSET;
+ if (timp->tm_wday == 7)
+ timp->tm_wday = 0;
+
+ timp->tm_mday = (tv_date & RTC_DR_DU) >> RTC_DR_DU_OFFSET;
+ timp->tm_mday += ((tv_date & RTC_DR_DT) >> RTC_DR_DT_OFFSET) * 10;
+
+ timp->tm_mon = (tv_date & RTC_DR_MU) >> RTC_DR_MU_OFFSET;
+ timp->tm_mon += ((tv_date & RTC_DR_MT) >> RTC_DR_MT_OFFSET) * 10;
+ timp->tm_mon -= 1;
+
+ timp->tm_year = (tv_date & RTC_DR_YU) >> RTC_DR_YU_OFFSET;
+ timp->tm_year += ((tv_date & RTC_DR_YT) >> RTC_DR_YT_OFFSET) * 10;
+ timp->tm_year += 2000 - 1900;
+
+ timp->tm_sec = (tv_time & RTC_TR_SU) >> RTC_TR_SU_OFFSET;
+ timp->tm_sec += ((tv_time & RTC_TR_ST) >> RTC_TR_ST_OFFSET) * 10;
+
+ timp->tm_min = (tv_time & RTC_TR_MNU) >> RTC_TR_MNU_OFFSET;
+ timp->tm_min += ((tv_time & RTC_TR_MNT) >> RTC_TR_MNT_OFFSET) * 10;
+
+ timp->tm_hour = (tv_time & RTC_TR_HU) >> RTC_TR_HU_OFFSET;
+ timp->tm_hour += ((tv_time & RTC_TR_HT) >> RTC_TR_HT_OFFSET) * 10;
+ timp->tm_hour += 12 * ((tv_time & RTC_TR_PM) >> RTC_TR_PM_OFFSET);
+}
+
+/**
+ * @brief Converts from canonicalized to STM32 BCD time format.
+ *
+ * @param[in] timp pointer to a @p tm structure as defined in time.h
+ * @param[out] timespec pointer to a @p RTCTime structure
+ *
+ * @notapi
+ */
+static void stm32_rtc_tm2bcd(struct tm *timp, RTCTime *timespec) {
+ uint32_t v = 0;
+
+ timespec->tv_date = 0;
+ timespec->tv_time = 0;
+
+ v = timp->tm_year - 100;
+ timespec->tv_date |= ((v / 10) << RTC_DR_YT_OFFSET) & RTC_DR_YT;
+ timespec->tv_date |= (v % 10) << RTC_DR_YU_OFFSET;
+
+ if (timp->tm_wday == 0)
+ v = 7;
+ else
+ v = timp->tm_wday;
+ timespec->tv_date |= (v << RTC_DR_WDU_OFFSET) & RTC_DR_WDU;
+
+ v = timp->tm_mon + 1;
+ timespec->tv_date |= ((v / 10) << RTC_DR_MT_OFFSET) & RTC_DR_MT;
+ timespec->tv_date |= (v % 10) << RTC_DR_MU_OFFSET;
+
+ v = timp->tm_mday;
+ timespec->tv_date |= ((v / 10) << RTC_DR_DT_OFFSET) & RTC_DR_DT;
+ timespec->tv_date |= (v % 10) << RTC_DR_DU_OFFSET;
+
+ v = timp->tm_hour;
+ timespec->tv_time |= ((v / 10) << RTC_TR_HT_OFFSET) & RTC_TR_HT;
+ timespec->tv_time |= (v % 10) << RTC_TR_HU_OFFSET;
+
+ v = timp->tm_min;
+ timespec->tv_time |= ((v / 10) << RTC_TR_MNT_OFFSET) & RTC_TR_MNT;
+ timespec->tv_time |= (v % 10) << RTC_TR_MNU_OFFSET;
+
+ v = timp->tm_sec;
+ timespec->tv_time |= ((v / 10) << RTC_TR_ST_OFFSET) & RTC_TR_ST;
+ timespec->tv_time |= (v % 10) << RTC_TR_SU_OFFSET;
+}
+
+/**
+ * @brief Gets raw time from RTC and converts it to canonicalized format.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[out] timp pointer to a @p tm structure as defined in time.h
+ *
+ * @api
+ */
+void rtcGetTimeTm(RTCDriver *rtcp, struct tm *timp) {
+#if STM32_RTC_HAS_SUBSECONDS
+ RTCTime timespec = {0,0,FALSE,0};
+#else
+ RTCTime timespec = {0,0,FALSE};
+#endif
+
+ rtcGetTime(rtcp, &timespec);
+ stm32_rtc_bcd2tm(timp, &timespec);
+}
+
+/**
+ * @brief Sets RTC time.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[out] timp pointer to a @p tm structure as defined in time.h
+ *
+ * @api
+ */
+void rtcSetTimeTm(RTCDriver *rtcp, struct tm *timp) {
+#if STM32_RTC_HAS_SUBSECONDS
+ RTCTime timespec = {0,0,FALSE,0};
+#else
+ RTCTime timespec = {0,0,FALSE};
+#endif
+
+ stm32_rtc_tm2bcd(timp, &timespec);
+ rtcSetTime(rtcp, &timespec);
+}
+
+/**
+ * @brief Gets raw time from RTC and converts it to unix format.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @return Unix time value in seconds.
+ *
+ * @api
+ */
+time_t rtcGetTimeUnixSec(RTCDriver *rtcp) {
+#if STM32_RTC_HAS_SUBSECONDS
+ RTCTime timespec = {0,0,FALSE,0};
+#else
+ RTCTime timespec = {0,0,FALSE};
+#endif
+ struct tm timp;
+
+ rtcGetTime(rtcp, &timespec);
+ stm32_rtc_bcd2tm(&timp, &timespec);
+
+ return mktime(&timp);
+}
+
+/**
+ * @brief Sets RTC time.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[in] tv_sec time specification
+ * @return Unix time value in seconds.
+ *
+ * @api
+ */
+void rtcSetTimeUnixSec(RTCDriver *rtcp, time_t tv_sec) {
+#if STM32_RTC_HAS_SUBSECONDS
+ RTCTime timespec = {0,0,FALSE,0};
+#else
+ RTCTime timespec = {0,0,FALSE};
+#endif
+ struct tm timp;
+
+ localtime_r(&tv_sec, &timp);
+ stm32_rtc_tm2bcd(&timp, &timespec);
+ rtcSetTime(rtcp, &timespec);
+}
+
+/**
+ * @brief Gets raw time from RTC and converts it to unix format.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @return Unix time value in microseconds.
+ *
+ * @api
+ */
+uint64_t rtcGetTimeUnixUsec(RTCDriver *rtcp) {
+#if STM32_RTC_HAS_SUBSECONDS
+ uint64_t result = 0;
+ RTCTime timespec = {0,0,FALSE,0};
+ struct tm timp;
+
+ rtcGetTime(rtcp, &timespec);
+ stm32_rtc_bcd2tm(&timp, &timespec);
+
+ result = (uint64_t)mktime(&timp) * 1000000;
+ return result + timespec.tv_msec * 1000;
+#else
+ return (uint64_t)rtcGetTimeUnixSec(rtcp) * 1000000;
+#endif
+}
+
+#else /* STM32_RTC_IS_CALENDAR */
+/**
+ * @brief Gets raw time from RTC and converts it to canonicalized format.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[out] timp pointer to a @p tm structure as defined in time.h
+ *
+ * @api
+ */
+void rtcGetTimeTm(RTCDriver *rtcp, struct tm *timp) {
+ RTCTime timespec = {0};
+
+ rtcGetTime(rtcp, &timespec);
+ localtime_r((time_t *)&(timespec.tv_sec), timp);
+}
+
+/**
+ * @brief Sets RTC time.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[out] timp pointer to a @p tm structure as defined in time.h
+ *
+ * @api
+ */
+void rtcSetTimeTm(RTCDriver *rtcp, struct tm *timp) {
+ RTCTime timespec = {0};
+
+ timespec.tv_sec = mktime(timp);
+#if !defined(LPC122X)
+ timespec.tv_msec = 0;
+#endif
+ rtcSetTime(rtcp, &timespec);
+}
+
+/**
+ * @brief Gets raw time from RTC and converts it to unix format.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @return Unix time value in seconds.
+ *
+ * @api
+ */
+time_t rtcGetTimeUnixSec(RTCDriver *rtcp) {
+ RTCTime timespec = {0};
+
+ rtcGetTime(rtcp, &timespec);
+ return timespec.tv_sec;
+}
+
+/**
+ * @brief Sets RTC time.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[in] tv_sec time specification
+ * @return Unix time value in seconds.
+ *
+ * @api
+ */
+void rtcSetTimeUnixSec(RTCDriver *rtcp, time_t tv_sec) {
+ RTCTime timespec = {0};
+
+ timespec.tv_sec = tv_sec;
+#if !defined(LPC122X)
+ timespec.tv_msec = 0;
+#endif
+ rtcSetTime(rtcp, &timespec);
+}
+
+/**
+ * @brief Gets raw time from RTC and converts it to unix format.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @return Unix time value in microseconds.
+ *
+ * @api
+ */
+uint64_t rtcGetTimeUnixUsec(RTCDriver *rtcp) {
+#if STM32_RTC_HAS_SUBSECONDS
+ uint64_t result = 0;
+ RTCTime timespec = {0,0};
+
+ rtcGetTime(rtcp, &timespec);
+ result = (uint64_t)timespec.tv_sec * 1000000;
+ return result + timespec.tv_msec * 1000;
+#else
+ return (uint64_t)rtcGetTimeUnixSec(rtcp) * 1000000;
+#endif
+}
+
+/**
+ * @brief Get current time in format suitable for usage in FatFS.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @return FAT time value.
+ *
+ * @api
+ */
+uint32_t rtcGetTimeFatFromCounter(RTCDriver *rtcp) {
+ uint32_t fattime;
+ struct tm timp;
+
+ rtcGetTimeTm(rtcp, &timp);
+
+ fattime = (timp.tm_sec) >> 1;
+ fattime |= (timp.tm_min) << 5;
+ fattime |= (timp.tm_hour) << 11;
+ fattime |= (timp.tm_mday) << 16;
+ fattime |= (timp.tm_mon + 1) << 21;
+ fattime |= (timp.tm_year - 80) << 25;
+
+ return fattime;
+}
+#endif /* STM32_RTC_IS_CALENDAR */
+#endif /* (defined(STM32F4XX) || defined(STM32F2XX) || defined(STM32L1XX) || defined(STM32F1XX)) */
+
+/** @} */
diff --git a/os/various/chrtclib.h b/os/various/chrtclib.h
new file mode 100644
index 000000000..895abc1a7
--- /dev/null
+++ b/os/various/chrtclib.h
@@ -0,0 +1,55 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ Concepts and parts of this file have been contributed by Uladzimir Pylinsky
+ aka barthess.
+ */
+
+/**
+ * @file chrtclib.h
+ * @brief RTC time conversion utilities header.
+ *
+ * @addtogroup chrtclib
+ * @{
+ */
+
+#ifndef CHRTCLIB_H_
+#define CHRTCLIB_H_
+
+#include <time.h>
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if !STM32_RTC_IS_CALENDAR
+ uint32_t rtcGetTimeFat(RTCDriver *rtcp);
+#endif
+ void rtcGetTimeTm(RTCDriver *rtcp, struct tm *timp);
+ void rtcSetTimeTm(RTCDriver *rtcp, struct tm *timp);
+ time_t rtcGetTimeUnixSec(RTCDriver *rtcp);
+ uint64_t rtcGetTimeUnixUsec(RTCDriver *rtcp);
+ void rtcSetTimeUnixSec(RTCDriver *rtcp, time_t tv_sec);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CHRTCLIB_H_ */
+
+/** @} */
diff --git a/os/various/cpp_wrappers/ch.cpp b/os/various/cpp_wrappers/ch.cpp
new file mode 100644
index 000000000..5f2621a61
--- /dev/null
+++ b/os/various/cpp_wrappers/ch.cpp
@@ -0,0 +1,866 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/**
+ * @file ch.cpp
+ * @brief C++ wrapper code.
+ *
+ * @addtogroup cpp_library
+ * @{
+ */
+
+#include "ch.hpp"
+
+namespace chibios_rt {
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::System *
+ *------------------------------------------------------------------------*/
+ void System::init(void) {
+
+ chSysInit();
+ }
+
+ void System::lock(void) {
+
+ chSysLock();
+ }
+
+ void System::unlock(void) {
+
+ chSysUnlock();
+ }
+
+ void System::lockFromIsr(void) {
+
+ chSysLockFromIsr();
+ }
+
+ void System::unlockFromIsr(void) {
+
+ chSysUnlockFromIsr();
+ }
+
+ systime_t System::getTime(void) {
+
+ return chTimeNow();
+ }
+
+ bool System::isTimeWithin(systime_t start, systime_t end) {
+
+ return (bool)chTimeIsWithin(start, end);
+ }
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::Core *
+ *------------------------------------------------------------------------*/
+ void *Core::alloc(size_t size) {
+
+ return chCoreAlloc(size);
+ }
+
+ void *Core::allocI(size_t size) {
+
+ return chCoreAllocI(size);
+ }
+
+ size_t Core::getStatus(void) {
+
+ return chCoreStatus();
+ }
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::Timer *
+ *------------------------------------------------------------------------*/
+ void Timer::setI(systime_t time, vtfunc_t vtfunc, void *par) {
+
+ chVTSetI(&timer_ref, time, vtfunc, par);
+ }
+
+ void Timer::resetI() {
+
+ if (chVTIsArmedI(&timer_ref))
+ chVTResetI(&timer_ref);
+ }
+
+ bool Timer::isArmedI(void) {
+
+ return (bool)chVTIsArmedI(&timer_ref);
+ }
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::ThreadReference *
+ *------------------------------------------------------------------------*/
+
+ void ThreadReference::stop(void) {
+
+ chDbgPanic("invoked unimplemented method stop()");
+ }
+
+ msg_t ThreadReference::suspend(void) {
+ msg_t msg;
+
+ chSysLock();
+
+ chDbgAssert(thread_ref != NULL,
+ "ThreadReference, #1",
+ "already referenced");
+
+ thread_ref = chThdSelf();
+ chSchGoSleepS(THD_STATE_SUSPENDED);
+ msg = thread_ref->p_u.rdymsg;
+
+ chSysUnlock();
+ return msg;
+ }
+
+ msg_t ThreadReference::suspendS(void) {
+
+ chDbgAssert(thread_ref == NULL,
+ "ThreadReference, #2",
+ "already referenced");
+
+ thread_ref = chThdSelf();
+ chSchGoSleepS(THD_STATE_SUSPENDED);
+ return thread_ref->p_u.rdymsg;
+ }
+
+ void ThreadReference::resume(msg_t msg) {
+
+ chSysLock()
+
+ chDbgAssert(thread_ref != NULL,
+ "ThreadReference, #3",
+ "not referenced");
+
+ if (thread_ref) {
+ Thread *tp = thread_ref;
+ thread_ref = NULL;
+ chSchWakeupS(tp, msg);
+ }
+
+ chSysUnlock();
+ }
+
+ void ThreadReference::resumeI(msg_t msg) {
+
+ chDbgAssert(thread_ref != NULL,
+ "ThreadReference, #4",
+ "not referenced");
+
+ if (thread_ref) {
+ Thread *tp = thread_ref;
+ thread_ref = NULL;
+ tp->p_msg = msg;
+ chSchReadyI(tp);
+ }
+ }
+
+ void ThreadReference::requestTerminate(void) {
+
+ chDbgAssert(thread_ref != NULL,
+ "ThreadReference, #5",
+ "not referenced");
+
+ chThdTerminate(thread_ref);
+ }
+
+#if CH_USE_WAITEXIT
+ msg_t ThreadReference::wait(void) {
+
+ chDbgAssert(thread_ref != NULL,
+ "ThreadReference, #6",
+ "not referenced");
+
+ msg_t msg = chThdWait(thread_ref);
+ thread_ref = NULL;
+ return msg;
+ }
+#endif /* CH_USE_WAITEXIT */
+
+#if CH_USE_MESSAGES
+ msg_t ThreadReference::sendMessage(msg_t msg) {
+
+ chDbgAssert(thread_ref != NULL,
+ "ThreadReference, #7",
+ "not referenced");
+
+ return chMsgSend(thread_ref, msg);
+ }
+
+ bool ThreadReference::isPendingMessage(void) {
+
+ chDbgAssert(thread_ref != NULL,
+ "ThreadReference, #7",
+ "not referenced");
+
+ return (bool)chMsgIsPendingI(thread_ref);
+ }
+
+ msg_t ThreadReference::getMessage(void) {
+
+ chDbgAssert(thread_ref != NULL,
+ "ThreadReference, #8",
+ "not referenced");
+
+ return chMsgGet(thread_ref);
+ }
+
+ void ThreadReference::releaseMessage(msg_t msg) {
+
+ chDbgAssert(thread_ref != NULL,
+ "ThreadReference, #9",
+ "not referenced");
+
+ chMsgRelease(thread_ref, msg);
+ }
+#endif /* CH_USE_MESSAGES */
+
+#if CH_USE_EVENTS
+ void ThreadReference::signalEvents(eventmask_t mask) {
+
+ chDbgAssert(thread_ref != NULL,
+ "ThreadReference, #10",
+ "not referenced");
+
+ chEvtSignal(thread_ref, mask);
+ }
+
+ void ThreadReference::signalEventsI(eventmask_t mask) {
+
+ chDbgAssert(thread_ref != NULL,
+ "ThreadReference, #11",
+ "not referenced");
+
+ chEvtSignalI(thread_ref, mask);
+ }
+#endif /* CH_USE_EVENTS */
+
+#if CH_USE_DYNAMIC
+#endif /* CH_USE_DYNAMIC */
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::BaseThread *
+ *------------------------------------------------------------------------*/
+ BaseThread::BaseThread() : ThreadReference(NULL) {
+
+ }
+
+ msg_t BaseThread::main(void) {
+
+ return 0;
+ }
+
+ ThreadReference BaseThread::start(tprio_t prio) {
+
+ (void)prio;
+
+ return *this;
+ };
+
+ msg_t _thd_start(void *arg) {
+
+ return ((BaseThread *)arg)->main();
+ }
+
+ void BaseThread::setName(const char *tname) {
+
+ chRegSetThreadName(tname);
+ }
+
+ tprio_t BaseThread::setPriority(tprio_t newprio) {
+
+ return chThdSetPriority(newprio);
+ }
+
+ void BaseThread::exit(msg_t msg) {
+
+ chThdExit(msg);
+ }
+
+ void BaseThread::exitS(msg_t msg) {
+
+ chThdExitS(msg);
+ }
+
+ bool BaseThread::shouldTerminate(void) {
+
+ return (bool)chThdShouldTerminate();
+ }
+
+ void BaseThread::sleep(systime_t interval){
+
+ chThdSleep(interval);
+ }
+
+ void BaseThread::sleepUntil(systime_t time) {
+
+ chThdSleepUntil(time);
+ }
+
+ void BaseThread::yield(void) {
+
+ chThdYield();
+ }
+
+#if CH_USE_MESSAGES
+ ThreadReference BaseThread::waitMessage(void) {
+
+ ThreadReference tr(chMsgWait());
+ return tr;
+ }
+#endif /* CH_USE_MESSAGES */
+
+#if CH_USE_EVENTS
+ eventmask_t BaseThread::getAndClearEvents(eventmask_t mask) {
+
+ return chEvtGetAndClearEvents(mask);
+ }
+
+ eventmask_t BaseThread::addEvents(eventmask_t mask) {
+
+ return chEvtAddEvents(mask);
+ }
+
+ eventmask_t BaseThread::waitOneEvent(eventmask_t ewmask) {
+
+ return chEvtWaitOne(ewmask);
+ }
+
+ eventmask_t BaseThread::waitAnyEvent(eventmask_t ewmask) {
+
+ return chEvtWaitAny(ewmask);
+ }
+
+ eventmask_t BaseThread::waitAllEvents(eventmask_t ewmask) {
+
+ return chEvtWaitAll(ewmask);
+ }
+
+#if CH_USE_EVENTS_TIMEOUT
+ eventmask_t BaseThread::waitOneEventTimeout(eventmask_t ewmask,
+ systime_t time) {
+
+ return chEvtWaitOneTimeout(ewmask, time);
+ }
+
+ eventmask_t BaseThread::waitAnyEventTimeout(eventmask_t ewmask,
+ systime_t time) {
+
+ return chEvtWaitAnyTimeout(ewmask, time);
+ }
+
+ eventmask_t BaseThread::waitAllEventsTimeout(eventmask_t ewmask,
+ systime_t time) {
+
+ return chEvtWaitAllTimeout(ewmask, time);
+ }
+#endif /* CH_USE_EVENTS_TIMEOUT */
+
+ void BaseThread::dispatchEvents(const evhandler_t handlers[],
+ eventmask_t mask) {
+
+ chEvtDispatch(handlers, mask);
+ }
+#endif /* CH_USE_EVENTS */
+
+#if CH_USE_MUTEXES
+ void BaseThread::unlockMutex(void) {
+
+ chMtxUnlock();
+ }
+
+ void BaseThread::unlockMutexS(void) {
+
+ chMtxUnlockS();
+ }
+
+ void BaseThread::unlockAllMutexes(void) {
+
+ chMtxUnlockAll();
+ }
+#endif /* CH_USE_MUTEXES */
+
+#if CH_USE_SEMAPHORES
+ /*------------------------------------------------------------------------*
+ * chibios_rt::CounterSemaphore *
+ *------------------------------------------------------------------------*/
+ CounterSemaphore::CounterSemaphore(cnt_t n) {
+
+ chSemInit(&sem, n);
+ }
+
+ void CounterSemaphore::reset(cnt_t n) {
+
+ chSemReset(&sem, n);
+ }
+
+ void CounterSemaphore::resetI(cnt_t n) {
+
+ chSemResetI(&sem, n);
+ }
+
+ msg_t CounterSemaphore::wait(void) {
+
+ return chSemWait(&sem);
+ }
+
+ msg_t CounterSemaphore::waitS(void) {
+
+ return chSemWaitS(&sem);
+ }
+
+ msg_t CounterSemaphore::waitTimeout(systime_t time) {
+
+ return chSemWaitTimeout(&sem, time);
+ }
+
+ msg_t CounterSemaphore::waitTimeoutS(systime_t time) {
+
+ return chSemWaitTimeoutS(&sem, time);
+ }
+
+ void CounterSemaphore::signal(void) {
+
+ chSemSignal(&sem);
+ }
+
+ void CounterSemaphore::signalI(void) {
+
+ chSemSignalI(&sem);
+ }
+
+ void CounterSemaphore::addCounterI(cnt_t n) {
+
+ chSemAddCounterI(&sem, n);
+ }
+
+ cnt_t CounterSemaphore::getCounterI(void) {
+
+ return chSemGetCounterI(&sem);
+ }
+
+#if CH_USE_SEMSW
+ msg_t CounterSemaphore::signalWait(CounterSemaphore *ssem,
+ CounterSemaphore *wsem) {
+
+ return chSemSignalWait(&ssem->sem, &wsem->sem);
+ }
+#endif /* CH_USE_SEMSW */
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::BinarySemaphore *
+ *------------------------------------------------------------------------*/
+ BinarySemaphore::BinarySemaphore(bool taken) {
+
+ chBSemInit(&bsem, (bool_t)taken);
+ }
+
+ msg_t BinarySemaphore::wait(void) {
+
+ return chBSemWait(&bsem);
+ }
+
+ msg_t BinarySemaphore::waitS(void) {
+
+ return chBSemWaitS(&bsem);
+ }
+
+ msg_t BinarySemaphore::waitTimeout(systime_t time) {
+
+ return chBSemWaitTimeout(&bsem, time);
+ }
+
+ msg_t BinarySemaphore::waitTimeoutS(systime_t time) {
+
+ return chBSemWaitTimeoutS(&bsem, time);
+ }
+
+ void BinarySemaphore::reset(bool taken) {
+
+ chBSemReset(&bsem, (bool_t)taken);
+ }
+
+ void BinarySemaphore::resetI(bool taken) {
+
+ chBSemResetI(&bsem, (bool_t)taken);
+ }
+
+ void BinarySemaphore::signal(void) {
+
+ chBSemSignal(&bsem);
+ }
+
+ void BinarySemaphore::signalI(void) {
+
+ chBSemSignalI(&bsem);
+ }
+
+ bool BinarySemaphore::getStateI(void) {
+
+ return (bool)chBSemGetStateI(&bsem);
+ }
+#endif /* CH_USE_SEMAPHORES */
+
+#if CH_USE_MUTEXES
+ /*------------------------------------------------------------------------*
+ * chibios_rt::Mutex *
+ *------------------------------------------------------------------------*/
+ Mutex::Mutex(void) {
+
+ chMtxInit(&mutex);
+ }
+
+ bool Mutex::tryLock(void) {
+
+ return chMtxTryLock(&mutex);
+ }
+
+ bool Mutex::tryLockS(void) {
+
+ return chMtxTryLockS(&mutex);
+ }
+
+ void Mutex::lock(void) {
+
+ chMtxLock(&mutex);
+ }
+
+ void Mutex::lockS(void) {
+
+ chMtxLockS(&mutex);
+ }
+
+#if CH_USE_CONDVARS
+ /*------------------------------------------------------------------------*
+ * chibios_rt::CondVar *
+ *------------------------------------------------------------------------*/
+ CondVar::CondVar(void) {
+
+ chCondInit(&condvar);
+ }
+
+ void CondVar::signal(void) {
+
+ chCondSignal(&condvar);
+ }
+
+ void CondVar::signalI(void) {
+
+ chCondSignalI(&condvar);
+ }
+
+ void CondVar::broadcast(void) {
+
+ chCondBroadcast(&condvar);
+ }
+
+ void CondVar::broadcastI(void) {
+
+ chCondBroadcastI(&condvar);
+ }
+
+ msg_t CondVar::wait(void) {
+
+ return chCondWait(&condvar);
+ }
+
+ msg_t CondVar::waitS(void) {
+
+ return chCondWaitS(&condvar);
+ }
+
+#if CH_USE_CONDVARS_TIMEOUT
+ msg_t CondVar::waitTimeout(systime_t time) {
+
+ return chCondWaitTimeout(&condvar, time);
+ }
+#endif /* CH_USE_CONDVARS_TIMEOUT */
+#endif /* CH_USE_CONDVARS */
+#endif /* CH_USE_MUTEXES */
+
+#if CH_USE_EVENTS
+ /*------------------------------------------------------------------------*
+ * chibios_rt::EvtListener *
+ *------------------------------------------------------------------------*/
+ flagsmask_t EvtListener::getAndClearFlags(void) {
+
+ return chEvtGetAndClearFlags(&ev_listener);
+ }
+
+ flagsmask_t EvtListener::getAndClearFlagsI(void) {
+
+ return chEvtGetAndClearFlagsI(&ev_listener);
+ }
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::EvtSource *
+ *------------------------------------------------------------------------*/
+ EvtSource::EvtSource(void) {
+
+ chEvtInit(&ev_source);
+ }
+
+ void EvtSource::registerOne(chibios_rt::EvtListener *elp,
+ eventid_t eid) {
+
+ chEvtRegister(&ev_source, &elp->ev_listener, eid);
+ }
+
+ void EvtSource::registerMask(chibios_rt::EvtListener *elp,
+ eventmask_t emask) {
+
+ chEvtRegisterMask(&ev_source, &elp->ev_listener, emask);
+ }
+
+ void EvtSource::unregister(chibios_rt::EvtListener *elp) {
+
+ chEvtUnregister(&ev_source, &elp->ev_listener);
+ }
+
+ void EvtSource::broadcastFlags(flagsmask_t flags) {
+
+ chEvtBroadcastFlags(&ev_source, flags);
+ }
+
+ void EvtSource::broadcastFlagsI(flagsmask_t flags) {
+
+ chEvtBroadcastFlagsI(&ev_source, flags);
+ }
+#endif /* CH_USE_EVENTS */
+
+#if CH_USE_QUEUES
+ /*------------------------------------------------------------------------*
+ * chibios_rt::InQueue *
+ *------------------------------------------------------------------------*/
+ InQueue::InQueue(uint8_t *bp, size_t size, qnotify_t infy, void *link) {
+
+ chIQInit(&iq, bp, size, infy, link);
+ }
+
+ size_t InQueue::getFullI(void) {
+
+ return chIQGetFullI(&iq);
+ }
+
+ size_t InQueue::getEmptyI(void) {
+
+ return chIQGetEmptyI(&iq);
+ }
+
+ bool InQueue::isEmptyI(void) {
+
+ return (bool)chIQIsEmptyI(&iq);
+ }
+
+ bool InQueue::isFullI(void) {
+
+ return (bool)chIQIsFullI(&iq);
+ }
+
+ void InQueue::resetI(void) {
+
+ chIQResetI(&iq);
+ }
+
+ msg_t InQueue::putI(uint8_t b) {
+
+ return chIQPutI(&iq, b);
+ }
+
+ msg_t InQueue::get() {
+
+ return chIQGet(&iq);
+ }
+
+ msg_t InQueue::getTimeout(systime_t time) {
+
+ return chIQGetTimeout(&iq, time);
+ }
+
+ size_t InQueue::readTimeout(uint8_t *bp, size_t n, systime_t time) {
+
+ return chIQReadTimeout(&iq, bp, n, time);
+ }
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::OutQueue *
+ *------------------------------------------------------------------------*/
+ OutQueue::OutQueue(uint8_t *bp, size_t size, qnotify_t onfy, void *link) {
+
+ chOQInit(&oq, bp, size, onfy, link);
+ }
+
+ size_t OutQueue::getFullI(void) {
+
+ return chOQGetFullI(&oq);
+ }
+
+ size_t OutQueue::getEmptyI(void) {
+
+ return chOQGetEmptyI(&oq);
+ }
+
+ bool OutQueue::isEmptyI(void) {
+
+ return (bool)chOQIsEmptyI(&oq);
+ }
+
+ bool OutQueue::isFullI(void) {
+
+ return (bool)chOQIsFullI(&oq);
+ }
+
+ void OutQueue::resetI(void) {
+
+ chOQResetI(&oq);
+ }
+
+ msg_t OutQueue::put(uint8_t b) {
+
+ return chOQPut(&oq, b);
+ }
+
+ msg_t OutQueue::putTimeout(uint8_t b, systime_t time) {
+
+ return chOQPutTimeout(&oq, b, time);
+ }
+
+ msg_t OutQueue::getI(void) {
+
+ return chOQGetI(&oq);
+ }
+
+ size_t OutQueue::writeTimeout(const uint8_t *bp, size_t n,
+ systime_t time) {
+
+ return chOQWriteTimeout(&oq, bp, n, time);
+ }
+#endif /* CH_USE_QUEUES */
+
+#if CH_USE_MAILBOXES
+ /*------------------------------------------------------------------------*
+ * chibios_rt::Mailbox *
+ *------------------------------------------------------------------------*/
+ Mailbox::Mailbox(msg_t *buf, cnt_t n) {
+
+ chMBInit(&mb, buf, n);
+ }
+
+ void Mailbox::reset(void) {
+
+ chMBReset(&mb);
+ }
+
+ msg_t Mailbox::post(msg_t msg, systime_t time) {
+
+ return chMBPost(&mb, msg, time);
+ }
+
+ msg_t Mailbox::postS(msg_t msg, systime_t time) {
+
+ return chMBPostS(&mb, msg, time);
+ }
+
+ msg_t Mailbox::postI(msg_t msg) {
+
+ return chMBPostI(&mb, msg);
+ }
+
+ msg_t Mailbox::postAhead(msg_t msg, systime_t time) {
+
+ return chMBPostAhead(&mb, msg, time);
+ }
+
+ msg_t Mailbox::postAheadS(msg_t msg, systime_t time) {
+
+ return chMBPostAheadS(&mb, msg, time);
+ }
+
+ msg_t Mailbox::postAheadI(msg_t msg) {
+
+ return chMBPostAheadI(&mb, msg);
+ }
+
+ msg_t Mailbox::fetch(msg_t *msgp, systime_t time) {
+
+ return chMBFetch(&mb, msgp, time);
+ }
+
+ msg_t Mailbox::fetchS(msg_t *msgp, systime_t time) {
+
+ return chMBFetchS(&mb, msgp, time);
+ }
+
+ msg_t Mailbox::fetchI(msg_t *msgp) {
+
+ return chMBFetchI(&mb, msgp);
+ }
+
+ cnt_t Mailbox::getFreeCountI(void) {
+
+ return chMBGetFreeCountI(&mb);
+ }
+
+ cnt_t Mailbox::getUsedCountI(void) {
+
+ return chMBGetUsedCountI(&mb);
+ }
+#endif /* CH_USE_MAILBOXES */
+
+#if CH_USE_MEMPOOLS
+ /*------------------------------------------------------------------------*
+ * chibios_rt::MemoryPool *
+ *------------------------------------------------------------------------*/
+ MemoryPool::MemoryPool(size_t size, memgetfunc_t provider) {
+
+ chPoolInit(&pool, size, provider);
+ }
+
+ MemoryPool::MemoryPool(size_t size, memgetfunc_t provider, void* p, size_t n) {
+
+ chPoolInit(&pool, size, provider);
+ chPoolLoadArray(&pool, p, n);
+ }
+
+
+ void MemoryPool::loadArray(void *p, size_t n) {
+
+ chPoolLoadArray(&pool, p, n);
+ }
+
+ void *MemoryPool::allocI(void) {
+
+ return chPoolAllocI(&pool);
+ }
+
+ void *MemoryPool::alloc(void) {
+
+ return chPoolAlloc(&pool);
+ }
+
+ void MemoryPool::free(void *objp) {
+
+ chPoolFree(&pool, objp);
+ }
+
+ void MemoryPool::freeI(void *objp) {
+
+ chPoolFreeI(&pool, objp);
+ }
+#endif /* CH_USE_MEMPOOLS */
+}
+
+/** @} */
diff --git a/os/various/cpp_wrappers/ch.hpp b/os/various/cpp_wrappers/ch.hpp
new file mode 100644
index 000000000..2bc70b55b
--- /dev/null
+++ b/os/various/cpp_wrappers/ch.hpp
@@ -0,0 +1,2282 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ch.hpp
+ * @brief C++ wrapper classes and definitions.
+ *
+ * @addtogroup cpp_library
+ * @{
+ */
+
+#include <ch.h>
+
+#ifndef _CH_HPP_
+#define _CH_HPP_
+
+/**
+ * @brief ChibiOS kernel-related classes and interfaces.
+ */
+namespace chibios_rt {
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::System *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Class encapsulating the base system functionalities.
+ */
+ class System {
+ public:
+ /**
+ * @brief ChibiOS/RT initialization.
+ * @details After executing this function the current instructions stream
+ * becomes the main thread.
+ * @pre Interrupts must be still disabled when @p chSysInit() is invoked
+ * and are internally enabled.
+ * @post The main thread is created with priority @p NORMALPRIO.
+ * @note This function has special, architecture-dependent, requirements,
+ * see the notes into the various port reference manuals.
+ *
+ * @special
+ */
+ static void init(void);
+
+ /**
+ * @brief Enters the kernel lock mode.
+ *
+ * @special
+ */
+ static void lock(void);
+
+ /**
+ * @brief Leaves the kernel lock mode.
+ *
+ * @special
+ */
+ static void unlock(void);
+
+ /**
+ * @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.
+ *
+ * @special
+ */
+ static void lockFromIsr(void);
+
+ /**
+ * @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.
+ *
+ * @special
+ */
+ static void unlockFromIsr(void);
+
+
+ /**
+ * @brief Returns the system time as system ticks.
+ * @note The system tick time interval is implementation dependent.
+ *
+ * @return The system time.
+ *
+ * @api
+ */
+ static systime_t getTime(void);
+
+ /**
+ * @brief Checks if the current system time is within the specified time
+ * window.
+ * @note When start==end then the function returns always true because the
+ * whole time range is specified.
+ *
+ * @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.
+ *
+ * @api
+ */
+ static bool isTimeWithin(systime_t start, systime_t end);
+ };
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::System *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Class encapsulating the base system functionalities.
+ */
+ class Core {
+ public:
+
+ /**
+ * @brief Allocates a memory block.
+ * @details The size of the returned block is aligned to the alignment
+ * type so it is not possible to allocate less
+ * than <code>MEM_ALIGN_SIZE</code>.
+ *
+ * @param[in] size the size of the block to be allocated
+ * @return A pointer to the allocated memory block.
+ * @retval NULL allocation failed, core memory exhausted.
+ *
+ * @api
+ */
+ static void *alloc(size_t size);
+
+ /**
+ * @brief Allocates a memory block.
+ * @details The size of the returned block is aligned to the alignment
+ * type so it is not possible to allocate less than
+ * <code>MEM_ALIGN_SIZE</code>.
+ *
+ * @param[in] size the size of the block to be allocated.
+ * @return A pointer to the allocated memory block.
+ * @retval NULL allocation failed, core memory exhausted.
+ *
+ * @iclass
+ */
+ static void *allocI(size_t size);
+
+ /**
+ * @brief Core memory status.
+ *
+ * @return The size, in bytes, of the free core memory.
+ *
+ * @api
+ */
+ static size_t getStatus(void);
+ };
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::Timer *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Timer class.
+ */
+ class Timer {
+ public:
+ /**
+ * @brief Embedded @p VirtualTimer structure.
+ */
+ ::VirtualTimer timer_ref;
+
+ /**
+ * @brief Enables a virtual timer.
+ * @note The associated function is invoked from interrupt context.
+ *
+ * @param[in] time the number of ticks before the operation timeouts,
+ * the special values are handled as follow:
+ * - @a TIME_INFINITE is allowed but interpreted as a
+ * normal time specification.
+ * - @a TIME_IMMEDIATE this value is not allowed.
+ * .
+ * @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
+ *
+ * @iclass
+ */
+ void setI(systime_t time, vtfunc_t vtfunc, void *par);
+
+ /**
+ * @brief Resets the timer, if armed.
+ *
+ * @iclass
+ */
+ void resetI();
+
+ /**
+ * @brief Returns the timer status.
+ *
+ * @retval TRUE The timer is armed.
+ * @retval FALSE The timer already fired its callback.
+ *
+ * @iclass
+ */
+ bool isArmedI(void);
+ };
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::ThreadReference *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Thread reference class.
+ * @details This class encapsulates a reference to a system thread. All
+ * operations involving another thread are performed through
+ * an object of this type.
+ */
+ class ThreadReference {
+ public:
+ /**
+ * @brief Pointer to the system thread.
+ */
+ ::Thread *thread_ref;
+
+ /**
+ * @brief Thread reference constructor.
+ *
+ * @param[in] tp the target thread. This parameter can be
+ * @p NULL if the thread is not known at
+ * creation time.
+ *
+ * @init
+ */
+ ThreadReference(Thread *tp) : thread_ref(tp) {
+
+ };
+
+ /**
+ * @brief Stops the thread.
+ * @note The implementation is left to descendant classes and is
+ * optional.
+ */
+ virtual void stop(void);
+
+ /**
+ * @brief Suspends the current thread on the reference.
+ * @details The suspended thread becomes the referenced thread. It is
+ * possible to use this method only if the thread reference
+ * was set to @p NULL.
+ *
+ * @return The incoming message.
+ *
+ * @api
+ */
+ msg_t suspend(void);
+
+ /**
+ * @brief Suspends the current thread on the reference.
+ * @details The suspended thread becomes the referenced thread. It is
+ * possible to use this method only if the thread reference
+ * was set to @p NULL.
+ *
+ * @return The incoming message.
+ *
+ * @sclass
+ */
+ msg_t suspendS(void);
+
+ /**
+ * @brief Resumes the currently referenced thread, if any.
+ *
+ * @param[in] msg the wakeup message
+ *
+ * @api
+ */
+ void resume(msg_t msg);
+
+ /**
+ * @brief Resumes the currently referenced thread, if any.
+ *
+ * @param[in] msg the wakeup message
+ *
+ * @iclass
+ */
+ void resumeI(msg_t msg);
+
+ /**
+ * @brief Requests a thread termination.
+ * @pre The target thread must be written to invoke periodically
+ * @p chThdShouldTerminate() and terminate cleanly if it returns
+ * @p TRUE.
+ * @post The specified thread will terminate after detecting the
+ * termination condition.
+ *
+ * @api
+ */
+ void requestTerminate(void);
+
+#if CH_USE_WAITEXIT || defined(__DOXYGEN__)
+ /**
+ * @brief Blocks the execution of the invoking thread until the specified
+ * thread terminates then the exit code is returned.
+ * @details This function waits for the specified thread to terminate then
+ * decrements its reference counter, if the counter reaches zero
+ * then the thread working area is returned to the proper
+ * allocator.<br>
+ * 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 chThdCreateI() 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.
+ * .
+ * @pre The configuration option @p CH_USE_WAITEXIT must be enabled in
+ * order to use this function.
+ * @post Enabling @p chThdWait() requires 2-4 (depending on the
+ * architecture) extra bytes in the @p Thread structure.
+ * @post After invoking @p chThdWait() the thread pointer becomes
+ * invalid and must not be used as parameter for further system
+ * calls.
+ * @note If @p CH_USE_DYNAMIC is not specified this function just waits
+ * for the thread termination, no memory allocators are involved.
+ *
+ * @return The exit code from the terminated thread.
+ *
+ * @api
+ */
+ msg_t wait(void);
+#endif /* CH_USE_WAITEXIT */
+
+#if CH_USE_MESSAGES || defined(__DOXYGEN__)
+ /**
+ * @brief Sends a message to the thread and returns the answer.
+ *
+ * @param[in] msg the sent message
+ * @return The returned message.
+ *
+ * @api
+ */
+ msg_t sendMessage(msg_t msg);
+
+ /**
+ * @brief Returns true if there is at least one message in queue.
+ *
+ * @retval true A message is waiting in queue.
+ * @retval false A message is not waiting in queue.
+ *
+ * @api
+ */
+ bool isPendingMessage(void);
+
+ /**
+ * @brief Returns an enqueued message or @p NULL.
+ *
+ * @return The incoming message.
+ *
+ * @api
+ */
+ msg_t getMessage(void);
+
+ /**
+ * @brief Releases the next message in queue with a reply.
+ *
+ * @param[in] msg the answer message
+ *
+ * @api
+ */
+ void releaseMessage(msg_t msg);
+#endif /* CH_USE_MESSAGES */
+
+#if CH_USE_EVENTS || defined(__DOXYGEN__)
+ /**
+ * @brief Adds a set of event flags directly to specified @p Thread.
+ *
+ * @param[in] mask the event flags set to be ORed
+ *
+ * @api
+ */
+ void signalEvents(eventmask_t mask);
+
+ /**
+ * @brief Adds a set of event flags directly to specified @p Thread.
+ *
+ * @param[in] mask the event flags set to be ORed
+ *
+ * @iclass
+ */
+ void signalEventsI(eventmask_t mask);
+#endif /* CH_USE_EVENTS */
+
+#if CH_USE_DYNAMIC || defined(__DOXYGEN__)
+#endif /* CH_USE_DYNAMIC */
+ };
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::BaseThread *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Abstract base class for a ChibiOS/RT thread.
+ * @details The thread body is the virtual function @p Main().
+ */
+ class BaseThread : public ThreadReference {
+ public:
+ /**
+ * @brief BaseThread constructor.
+ *
+ * @init
+ */
+ BaseThread(void);
+
+ /**
+ * @brief Thread body function.
+ *
+ * @return The exit message.
+ *
+ * @api
+ */
+ virtual msg_t main(void);
+
+ /**
+ * @brief Creates and starts a system thread.
+ *
+ * @param[in] prio thread priority
+ * @return A reference to the created thread with
+ * reference counter set to one.
+ *
+ * @api
+ */
+ virtual ThreadReference start(tprio_t prio);
+
+ /**
+ * @brief Sets the current thread name.
+ * @pre This function only stores the pointer to the name if the option
+ * @p CH_USE_REGISTRY is enabled else no action is performed.
+ *
+ * @param[in] tname thread name as a zero terminated string
+ *
+ * @api
+ */
+ static void setName(const char *tname);
+
+ /**
+ * @brief Changes the running thread priority level then reschedules if
+ * necessary.
+ * @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.
+ *
+ * @param[in] newprio the new priority level of the running thread
+ * @return The old priority level.
+ *
+ * @api
+ */
+ static tprio_t setPriority(tprio_t newprio);
+
+ /**
+ * @brief Terminates the current thread.
+ * @details The thread goes in the @p THD_STATE_FINAL state holding the
+ * specified exit status code, other threads can retrieve the
+ * exit status code by invoking the function @p chThdWait().
+ * @post Eventual code after this function will never be executed,
+ * this function never returns. The compiler has no way to
+ * know this so do not assume that the compiler would remove
+ * the dead code.
+ *
+ * @param[in] msg thread exit code
+ *
+ * @api
+ */
+ static void exit(msg_t msg);
+
+ /**
+ * @brief Terminates the current thread.
+ * @details The thread goes in the @p THD_STATE_FINAL state holding the
+ * specified exit status code, other threads can retrieve the
+ * exit status code by invoking the function @p chThdWait().
+ * @post Eventual code after this function will never be executed,
+ * this function never returns. The compiler has no way to
+ * know this so do not assume that the compiler would remove
+ * the dead code.
+ *
+ * @param[in] msg thread exit code
+ *
+ * @sclass
+ */
+ static void exitS(msg_t msg);
+
+ /**
+ * @brief Verifies if the current thread has a termination request
+ * pending.
+ * @note Can be invoked in any context.
+ *
+ * @retval TRUE termination request pending.
+ * @retval FALSE termination request not pending.
+ *
+ * @special
+ */
+ static bool shouldTerminate(void);
+
+ /**
+ * @brief Suspends the invoking thread for the specified time.
+ *
+ * @param[in] interval 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 not allowed.
+ * .
+ *
+ * @api
+ */
+ static void sleep(systime_t interval);
+
+ /**
+ * @brief Suspends the invoking thread until the system time arrives to
+ * the specified value.
+ *
+ * @param[in] time absolute system time
+ *
+ * @api
+ */
+ static void sleepUntil(systime_t time);
+
+ /**
+ * @brief Yields the time slot.
+ * @details Yields the CPU control to the next thread in the ready list
+ * with equal priority, if any.
+ *
+ * @api
+ */
+ static void yield(void);
+
+#if CH_USE_MESSAGES || defined(__DOXYGEN__)
+ /**
+ * @brief Waits for a message.
+ *
+ * @return The sender thread.
+ *
+ * @api
+ */
+ static ThreadReference waitMessage(void);
+#endif /* CH_USE_MESSAGES */
+
+#if CH_USE_EVENTS || defined(__DOXYGEN__)
+ /**
+ * @brief Clears the pending events specified in the mask.
+ *
+ * @param[in] mask the events to be cleared
+ * @return The pending events that were cleared.
+ *
+ * @api
+ */
+ static eventmask_t getAndClearEvents(eventmask_t mask);
+
+ /**
+ * @brief Adds (OR) 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 event flags to be added
+ * @return The current pending events mask.
+ *
+ * @api
+ */
+ static eventmask_t addEvents(eventmask_t mask);
+
+ /**
+ * @brief Waits for a single event.
+ * @details A pending event among those specified in @p ewmask is selected,
+ * cleared and its mask returned.
+ * @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.
+ *
+ * @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.
+ *
+ * @api
+ */
+ static eventmask_t waitOneEvent(eventmask_t ewmask);
+
+ /**
+ * @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.
+ *
+ * @api
+ */
+ static eventmask_t waitAnyEvent(eventmask_t ewmask);
+
+ /**
+ * @brief Waits for all the specified event flags then clears them.
+ * @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.
+ *
+ * @api
+ */
+ static eventmask_t waitAllEvents(eventmask_t ewmask);
+
+#if CH_USE_EVENTS_TIMEOUT || defined(__DOXYGEN__)
+ /**
+ * @brief Waits for a single event.
+ * @details A pending event among those specified in @p ewmask is selected,
+ * cleared and its mask returned.
+ * @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.
+ *
+ * @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
+ * timouts
+ * @return The mask of the lowest id served and cleared
+ * event.
+ * @retval 0 if the specified timeout expired.
+ *
+ * @api
+ */
+ static eventmask_t waitOneEventTimeout(eventmask_t ewmask,
+ systime_t time);
+
+ /**
+ * @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
+ * timouts
+ * @return The mask of the served and cleared events.
+ * @retval 0 if the specified timeout expired.
+ *
+ * @api
+ */
+ static eventmask_t waitAnyEventTimeout(eventmask_t ewmask,
+ systime_t time);
+
+ /**
+ * @brief Waits for all the specified event flags then clears them.
+ * @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
+ * timouts
+ * @return The mask of the served and cleared events.
+ * @retval 0 if the specified timeout expired.
+ *
+ * @api
+ */
+ static eventmask_t waitAllEventsTimeout(eventmask_t ewmask,
+ systime_t time);
+#endif /* CH_USE_EVENTS_TIMEOUT */
+
+ /**
+ * @brief Invokes the event handlers associated to an event flags mask.
+ *
+ * @param[in] mask mask of the event flags 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.
+ *
+ * @api
+ */
+ static void dispatchEvents(const evhandler_t handlers[],
+ eventmask_t mask);
+#endif /* CH_USE_EVENTS */
+
+#if CH_USE_MUTEXES || defined(__DOXYGEN__)
+ /**
+ * @brief Unlocks the next owned mutex in reverse lock order.
+ * @pre The invoking thread <b>must</b> have at least one owned mutex.
+ * @post The mutex is unlocked and removed from the per-thread stack of
+ * owned mutexes.
+ *
+ * @return A pointer to the unlocked mutex.
+ *
+ * @api
+ */
+ static void unlockMutex(void);
+
+ /**
+ * @brief Unlocks the next owned mutex in reverse lock order.
+ * @pre The invoking thread <b>must</b> have at least one owned mutex.
+ * @post The mutex is unlocked and removed from the per-thread stack of
+ * owned mutexes.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel.
+ *
+ * @return A pointer to the unlocked mutex.
+ *
+ * @sclass
+ */
+ static void unlockMutexS(void);
+
+ /**
+ * @brief Unlocks all the mutexes owned by the invoking thread.
+ * @post The stack of owned mutexes is emptied and all the found
+ * mutexes are unlocked.
+ * @note 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.
+ *
+ * @api
+ */
+ static void unlockAllMutexes(void);
+#endif /* CH_USE_MUTEXES */
+ };
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::BaseStaticThread *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Static threads template class.
+ * @details This class introduces static working area allocation.
+ *
+ * @param N the working area size for the thread class
+ */
+ template <int N>
+ class BaseStaticThread : public BaseThread {
+ protected:
+ WORKING_AREA(wa, N);
+
+ public:
+ /**
+ * @brief Thread constructor.
+ * @details The thread object is initialized but the thread is not
+ * started here.
+ *
+ * @init
+ */
+ BaseStaticThread(void) : BaseThread() {
+
+ }
+
+ /**
+ * @brief Creates and starts a system thread.
+ *
+ * @param[in] prio thread priority
+ * @return A reference to the created thread with
+ * reference counter set to one.
+ *
+ * @api
+ */
+ virtual ThreadReference start(tprio_t prio) {
+ msg_t _thd_start(void *arg);
+
+ thread_ref = chThdCreateStatic(wa, sizeof(wa), prio, _thd_start, this);
+ return *this;
+ }
+ };
+
+#if CH_USE_SEMAPHORES || defined(__DOXYGEN__)
+ /*------------------------------------------------------------------------*
+ * chibios_rt::CounterSemaphore *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Class encapsulating a semaphore.
+ */
+ class CounterSemaphore {
+ public:
+ /**
+ * @brief Embedded @p ::Semaphore structure.
+ */
+ ::Semaphore sem;
+
+ /**
+ * @brief CounterSemaphore constructor.
+ * @details The embedded @p ::Semaphore structure is initialized.
+ *
+ * @param[in] n the semaphore counter value, must be greater
+ * or equal to zero
+ *
+ * @init
+ */
+ CounterSemaphore(cnt_t n);
+
+ /**
+ * @brief Performs a reset operation on the semaphore.
+ * @post After invoking this function all the threads waiting on the
+ * semaphore, if any, are released and the semaphore counter is
+ * set to the specified, non negative, value.
+ * @note The released threads can recognize they were waked up by a
+ * reset rather than a signal because the @p chSemWait() will
+ * return @p RDY_RESET instead of @p RDY_OK.
+ *
+ * @param[in] n the new value of the semaphore counter. The value
+ * must be non-negative.
+ *
+ * @api
+ */
+ void reset(cnt_t n);
+
+ /**
+ * @brief Performs a reset operation on the semaphore.
+ * @post After invoking this function all the threads waiting on the
+ * semaphore, if any, are released and the semaphore counter is
+ * set to the specified, non negative, value.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note
+ * that interrupt handlers always reschedule on exit so an
+ * explicit reschedule must not be performed in ISRs.
+ * @note The released threads can recognize they were waked up by a
+ * reset rather than a signal because the @p chSemWait() will
+ * return @p RDY_RESET instead of @p RDY_OK.
+ *
+ * @param[in] n the new value of the semaphore counter. The value
+ * must be non-negative.
+ *
+ * @iclass
+ */
+ void resetI(cnt_t n);
+
+ /**
+ * @brief Performs a wait operation on a semaphore.
+ *
+ * @return A message specifying how the invoking thread has
+ * been released from the semaphore.
+ * @retval RDY_OK if the thread has not stopped on the semaphore or
+ * the semaphore has been signaled.
+ * @retval RDY_RESET if the semaphore has been reset using
+ * @p chSemReset().
+ *
+ * @api
+ */
+ msg_t wait(void);
+
+ /**
+ * @brief Performs a wait operation on a semaphore.
+ *
+ * @return A message specifying how the invoking thread has
+ * been released from the semaphore.
+ * @retval RDY_OK if the thread has not stopped on the semaphore or
+ * the semaphore has been signaled.
+ * @retval RDY_RESET if the semaphore has been reset using
+ * @p chSemReset().
+ *
+ * @sclass
+ */
+ msg_t waitS(void);
+
+ /**
+ * @brief Performs a wait operation on a semaphore with timeout
+ * specification.
+ *
+ * @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 A message specifying how the invoking thread has
+ * been released from the semaphore.
+ * @retval RDY_OK if the thread has not stopped on the semaphore or
+ * the semaphore has been signaled.
+ * @retval RDY_RESET if the semaphore has been reset using
+ * @p chSemReset().
+ * @retval RDY_TIMEOUT if the semaphore has not been signaled or reset
+ * within the specified timeout.
+ *
+ * @api
+ */
+ msg_t waitTimeout(systime_t time);
+
+ /**
+ * @brief Performs a wait operation on a semaphore with timeout
+ * specification.
+ *
+ * @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 A message specifying how the invoking thread has
+ * been released from the semaphore.
+ * @retval RDY_OK if the thread has not stopped on the semaphore or
+ * the semaphore has been signaled.
+ * @retval RDY_RESET if the semaphore has been reset using
+ * @p chSemReset().
+ * @retval RDY_TIMEOUT if the semaphore has not been signaled or reset
+ * within the specified timeout.
+ *
+ * @sclass
+ */
+ msg_t waitTimeoutS(systime_t time);
+
+ /**
+ * @brief Performs a signal operation on a semaphore.
+ *
+ * @api
+ */
+ void signal(void);
+
+ /**
+ * @brief Performs a signal operation on a semaphore.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note
+ * that interrupt handlers always reschedule on exit so an
+ * explicit reschedule must not be performed in ISRs.
+ *
+ * @iclass
+ */
+ void signalI(void);
+
+ /**
+ * @brief Adds the specified value to the semaphore counter.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note
+ * that interrupt handlers always reschedule on exit so an explicit
+ * reschedule must not be performed in ISRs.
+ *
+ * @param[in] n value to be added to the semaphore counter. The
+ * value must be positive.
+ *
+ * @iclass
+ */
+ void addCounterI(cnt_t n);
+
+ /**
+ * @brief Returns the semaphore counter value.
+ *
+ * @return The semaphore counter value.
+ *
+ * @iclass
+ */
+ cnt_t getCounterI(void);
+
+#if CH_USE_SEMSW || defined(__DOXYGEN__)
+ /**
+ * @brief Atomic signal and wait operations.
+ *
+ * @param[in] ssem @p Semaphore object to be signaled
+ * @param[in] wsem @p Semaphore object to wait on
+ * @return A message specifying how the invoking thread
+ * has been released from the semaphore.
+ * @retval RDY_OK if the thread has not stopped on the semaphore
+ * or the semaphore has been signaled.
+ * @retval RDY_RESET if the semaphore has been reset using
+ * @p chSemReset().
+ *
+ * @api
+ */
+ static msg_t signalWait(CounterSemaphore *ssem,
+ CounterSemaphore *wsem);
+#endif /* CH_USE_SEMSW */
+ };
+ /*------------------------------------------------------------------------*
+ * chibios_rt::BinarySemaphore *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Class encapsulating a binary semaphore.
+ */
+ class BinarySemaphore {
+ public:
+ /**
+ * @brief Embedded @p ::Semaphore structure.
+ */
+ ::BinarySemaphore bsem;
+
+ /**
+ * @brief BinarySemaphore constructor.
+ * @details The embedded @p ::BinarySemaphore structure is initialized.
+ *
+ * @param[in] taken initial state of the binary semaphore:
+ * - @a false, the initial state is not taken.
+ * - @a true, the initial state is taken.
+ * .
+ *
+ * @init
+ */
+ BinarySemaphore(bool taken);
+
+ /**
+ * @brief Wait operation on the binary semaphore.
+ *
+ * @return A message specifying how the invoking thread has
+ * been released from the semaphore.
+ * @retval RDY_OK if the binary semaphore has been successfully
+ * taken.
+ * @retval RDY_RESET if the binary semaphore has been reset using
+ * @p bsemReset().
+ *
+ * @api
+ */
+ msg_t wait(void);
+
+ /**
+ * @brief Wait operation on the binary semaphore.
+ *
+ * @return A message specifying how the invoking thread has
+ * been released from the semaphore.
+ * @retval RDY_OK if the binary semaphore has been successfully
+ * taken.
+ * @retval RDY_RESET if the binary semaphore has been reset using
+ * @p bsemReset().
+ *
+ * @sclass
+ */
+ msg_t waitS(void);
+
+ /**
+ * @brief Wait operation on the binary semaphore.
+ *
+ * @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 A message specifying how the invoking thread has
+ * been released from the semaphore.
+ * @retval RDY_OK if the binary semaphore has been successfully
+ * taken.
+ * @retval RDY_RESET if the binary semaphore has been reset using
+ * @p bsemReset().
+ * @retval RDY_TIMEOUT if the binary semaphore has not been signaled
+ * or reset within the specified timeout.
+ *
+ * @api
+ */
+ msg_t waitTimeout(systime_t time);
+
+ /**
+ * @brief Wait operation on the binary semaphore.
+ *
+ * @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 A message specifying how the invoking thread has
+ * been released from the semaphore.
+ * @retval RDY_OK if the binary semaphore has been successfully
+ * taken.
+ * @retval RDY_RESET if the binary semaphore has been reset using
+ * @p bsemReset().
+ * @retval RDY_TIMEOUT if the binary semaphore has not been signaled
+ * or reset within the specified timeout.
+ *
+ * @sclass
+ */
+ msg_t waitTimeoutS(systime_t time);
+
+ /**
+ * @brief Reset operation on the binary semaphore.
+ * @note The released threads can recognize they were waked up by a
+ * reset rather than a signal because the @p bsemWait() will
+ * return @p RDY_RESET instead of @p RDY_OK.
+ *
+ * @param[in] taken new state of the binary semaphore
+ * - @a FALSE, the new state is not taken.
+ * - @a TRUE, the new state is taken.
+ * .
+ *
+ * @api
+ */
+ void reset(bool taken);
+
+ /**
+ * @brief Reset operation on the binary semaphore.
+ * @note The released threads can recognize they were waked up by a
+ * reset rather than a signal because the @p bsemWait() will
+ * return @p RDY_RESET instead of @p RDY_OK.
+ * @note This function does not reschedule.
+ *
+ * @param[in] taken new state of the binary semaphore
+ * - @a FALSE, the new state is not taken.
+ * - @a TRUE, the new state is taken.
+ * .
+ *
+ * @iclass
+ */
+ void resetI(bool taken);
+
+ /**
+ * @brief Performs a signal operation on a binary semaphore.
+ *
+ * @api
+ */
+ void signal(void);
+
+ /**
+ * @brief Performs a signal operation on a binary semaphore.
+ * @note This function does not reschedule.
+ *
+ * @iclass
+ */
+ void signalI(void);
+
+ /**
+ * @brief Returns the binary semaphore current state.
+ *
+ * @return The binary semaphore current state.
+ * @retval false if the binary semaphore is not taken.
+ * @retval true if the binary semaphore is taken.
+ *
+ * @iclass
+ */
+ bool getStateI(void);
+};
+#endif /* CH_USE_SEMAPHORES */
+
+#if CH_USE_MUTEXES || defined(__DOXYGEN__)
+ /*------------------------------------------------------------------------*
+ * chibios_rt::Mutex *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Class encapsulating a mutex.
+ */
+ class Mutex {
+ public:
+ /**
+ * @brief Embedded @p ::Mutex structure.
+ */
+ ::Mutex mutex;
+
+ /**
+ * @brief Mutex object constructor.
+ * @details The embedded @p ::Mutex structure is initialized.
+ *
+ * @init
+ */
+ Mutex(void);
+
+ /**
+ * @brief Tries to lock a mutex.
+ * @details This function attempts to lock a mutex, if the mutex is already
+ * locked by another thread then the function exits without
+ * waiting.
+ * @post The mutex is locked and inserted in the per-thread stack of
+ * owned mutexes.
+ * @note This function does not have any overhead related to the
+ * priority inheritance mechanism because it does not try to
+ * enter a sleep state.
+ *
+ * @return The operation status.
+ * @retval TRUE if the mutex has been successfully acquired
+ * @retval FALSE if the lock attempt failed.
+ *
+ * @api
+ */
+ bool tryLock(void);
+
+ /**
+ * @brief Tries to lock a mutex.
+ * @details This function attempts to lock a mutex, if the mutex is already
+ * taken by another thread then the function exits without
+ * waiting.
+ * @post The mutex is locked and inserted in the per-thread stack of
+ * owned mutexes.
+ * @note This function does not have any overhead related to the
+ * priority inheritance mechanism because it does not try to
+ * enter a sleep state.
+ *
+ * @return The operation status.
+ * @retval TRUE if the mutex has been successfully acquired
+ * @retval FALSE if the lock attempt failed.
+ *
+ * @sclass
+ */
+ bool tryLockS(void);
+
+ /**
+ * @brief Locks the specified mutex.
+ * @post The mutex is locked and inserted in the per-thread stack of
+ * owned mutexes.
+ *
+ * @api
+ */
+ void lock(void);
+
+ /**
+ * @brief Locks the specified mutex.
+ * @post The mutex is locked and inserted in the per-thread stack of
+ * owned mutexes.
+ *
+ * @sclass
+ */
+ void lockS(void);
+ };
+
+#if CH_USE_CONDVARS || defined(__DOXYGEN__)
+ /*------------------------------------------------------------------------*
+ * chibios_rt::CondVar *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Class encapsulating a conditional variable.
+ */
+ class CondVar {
+ public:
+ /**
+ * @brief Embedded @p ::CondVar structure.
+ */
+ ::CondVar condvar;
+
+ /**
+ * @brief CondVar object constructor.
+ * @details The embedded @p ::CondVar structure is initialized.
+ *
+ * @init
+ */
+ CondVar(void);
+
+ /**
+ * @brief Signals one thread that is waiting on the condition variable.
+ *
+ * @api
+ */
+ void signal(void);
+
+ /**
+ * @brief Signals one thread that is waiting on the condition variable.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note
+ * that interrupt handlers always reschedule on exit so an
+ * explicit reschedule must not be performed in ISRs.
+ *
+ * @iclass
+ */
+ void signalI(void);
+
+ /**
+ * @brief Signals all threads that are waiting on the condition variable.
+ *
+ * @api
+ */
+ void broadcast(void);
+
+ /**
+ * @brief Signals all threads that are waiting on the condition variable.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note
+ * that interrupt handlers always reschedule on exit so an
+ * explicit reschedule must not be performed in ISRs.
+ *
+ * @iclass
+ */
+ void broadcastI(void);
+
+ /**
+ * @brief Waits on the condition variable releasing the mutex lock.
+ * @details Releases the currently owned mutex, waits on the condition
+ * variable, and finally acquires the mutex again. All the
+ * sequence is performed atomically.
+ * @pre The invoking thread <b>must</b> have at least one owned mutex.
+ *
+ * @return A message specifying how the invoking thread has
+ * been released from the condition variable.
+ * @retval RDY_OK if the condvar has been signaled using
+ * @p chCondSignal().
+ * @retval RDY_RESET if the condvar has been signaled using
+ * @p chCondBroadcast().
+ *
+ * @api
+ */
+ msg_t wait(void);
+
+ /**
+ * @brief Waits on the condition variable releasing the mutex lock.
+ * @details Releases the currently owned mutex, waits on the condition
+ * variable, and finally acquires the mutex again. All the
+ * sequence is performed atomically.
+ * @pre The invoking thread <b>must</b> have at least one owned mutex.
+ *
+ * @return A message specifying how the invoking thread has
+ * been released from the condition variable.
+ * @retval RDY_OK if the condvar has been signaled using
+ * @p chCondSignal().
+ * @retval RDY_RESET if the condvar has been signaled using
+ * @p chCondBroadcast().
+ *
+ * @sclass
+ */
+ msg_t waitS(void);
+
+#if CH_USE_CONDVARS_TIMEOUT || defined(__DOXYGEN__)
+ /**
+ * @brief Waits on the CondVar while releasing the controlling mutex.
+ *
+ * @param[in] time the number of ticks before the operation fails
+ * @return The wakep mode.
+ * @retval RDY_OK if the condvar was signaled using
+ * @p chCondSignal().
+ * @retval RDY_RESET if the condvar was signaled using
+ * @p chCondBroadcast().
+ * @retval RDY_TIMEOUT if the condvar was not signaled within the
+ * specified timeout.
+ *
+ * @api
+ */
+ msg_t waitTimeout(systime_t time);
+#endif /* CH_USE_CONDVARS_TIMEOUT */
+ };
+#endif /* CH_USE_CONDVARS */
+#endif /* CH_USE_MUTEXES */
+
+#if CH_USE_EVENTS || defined(__DOXYGEN__)
+ /*------------------------------------------------------------------------*
+ * chibios_rt::EvtListener *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Class encapsulating an event listener.
+ */
+ class EvtListener {
+ public:
+ /**
+ * @brief Embedded @p ::EventListener structure.
+ */
+ struct ::EventListener ev_listener;
+
+ /**
+ * @brief Returns the pending flags from the listener and clears them.
+ *
+ * @return The flags added to the listener by the
+ * associated event source.
+ *
+ * @api
+ */
+ flagsmask_t getAndClearFlags(void);
+
+ /**
+ * @brief Returns the flags associated to an @p EventListener.
+ * @details The flags are returned and the @p EventListener flags mask is
+ * cleared.
+ *
+ * @return The flags added to the listener by the associated
+ * event source.
+ *
+ * @iclass
+ */
+ flagsmask_t getAndClearFlagsI(void);
+ };
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::EvtSource *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Class encapsulating an event source.
+ */
+ class EvtSource {
+ public:
+ /**
+ * @brief Embedded @p ::EventSource structure.
+ */
+ struct ::EventSource ev_source;
+
+ /**
+ * @brief EvtSource object constructor.
+ * @details The embedded @p ::EventSource structure is initialized.
+ *
+ * @init
+ */
+ EvtSource(void);
+
+ /**
+ * @brief Registers a listener on the event source.
+ *
+ * @param[in] elp pointer to the @p EvtListener object
+ * @param[in] eid numeric identifier assigned to the Event
+ * Listener
+ *
+ * @api
+ */
+ void registerOne(chibios_rt::EvtListener *elp, eventid_t eid);
+
+ /**
+ * @brief Registers an Event Listener on an Event Source.
+ * @note Multiple Event Listeners can specify the same bits to be added.
+ *
+ * @param[in] elp pointer to the @p EvtListener object
+ * @param[in] emask the mask of event flags to be pended to the
+ * thread when the event source is broadcasted
+ *
+ * @api
+ */
+ void registerMask(chibios_rt::EvtListener *elp, eventmask_t emask);
+
+ /**
+ * @brief Unregisters a listener.
+ * @details The specified listeners is no more signaled by the event
+ * source.
+ *
+ * @param[in] elp the listener to be unregistered
+ *
+ * @api
+ */
+ void unregister(chibios_rt::EvtListener *elp);
+
+ /**
+ * @brief Broadcasts on an event source.
+ * @details All the listeners registered on the event source are signaled
+ * and the flags are added to the listener's flags mask.
+ *
+ * @param[in] flags the flags set to be added to the listener
+ * flags mask
+ *
+ * @api
+ */
+ void broadcastFlags(flagsmask_t flags);
+
+ /**
+ * @brief Broadcasts on an event source.
+ * @details All the listeners registered on the event source are signaled
+ * and the flags are added to the listener's flags mask.
+ *
+ * @param[in] flags the flags set to be added to the listener
+ * flags mask
+ *
+ * @iclass
+ */
+ void broadcastFlagsI(flagsmask_t flags);
+ };
+#endif /* CH_USE_EVENTS */
+
+#if CH_USE_QUEUES || defined(__DOXYGEN__)
+ /*------------------------------------------------------------------------*
+ * chibios_rt::InQueue *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Class encapsulating an input queue.
+ */
+ class InQueue {
+ private:
+ /**
+ * @brief Embedded @p ::InputQueue structure.
+ */
+ ::InputQueue iq;
+
+ public:
+ /**
+ * @brief InQueue constructor.
+ *
+ * @param[in] bp pointer to a memory area allocated as queue buffer
+ * @param[in] size size of the queue buffer
+ * @param[in] infy pointer to a callback function that is invoked when
+ * data is read from the queue. The value can be
+ * @p NULL.
+ * @param[in] link application defined pointer
+ *
+ * @init
+ */
+ InQueue(uint8_t *bp, size_t size, qnotify_t infy, void *link);
+
+ /**
+ * @brief Returns the filled space into an input queue.
+ *
+ * @return The number of full bytes in the queue.
+ * @retval 0 if the queue is empty.
+ *
+ * @iclass
+ */
+ size_t getFullI(void);
+
+ /**
+ * @brief Returns the empty space into an input queue.
+ *
+ * @return The number of empty bytes in the queue.
+ * @retval 0 if the queue is full.
+ *
+ * @iclass
+ */
+ size_t getEmptyI(void);
+
+ /**
+ * @brief Evaluates to @p TRUE if the specified input queue is empty.
+ *
+ * @return The queue status.
+ * @retval false if the queue is not empty.
+ * @retval true if the queue is empty.
+ *
+ * @iclass
+ */
+ bool isEmptyI(void);
+
+ /**
+ * @brief Evaluates to @p TRUE if the specified input queue is full.
+ *
+ * @return The queue status.
+ * @retval FALSE if the queue is not full.
+ * @retval TRUE if the queue is full.
+ *
+ * @iclass
+ */
+ bool isFullI(void);
+
+ /**
+ * @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.
+ * @note A reset operation can be used by a low level driver in order to
+ * obtain immediate attention from the high level layers.
+ * @iclass
+ */
+ void resetI(void);
+
+ /**
+ * @brief Input queue write.
+ * @details A byte value is written into the low end of an input queue.
+ *
+ * @param[in] b the byte value to be written in the queue
+ * @return The operation status.
+ * @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.
+ *
+ * @iclass
+ */
+ msg_t putI(uint8_t b);
+
+ /**
+ * @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.
+ *
+ * @return A byte value from the queue.
+ * @retval Q_RESET if the queue has been reset.
+ *
+ * @api
+ */
+ msg_t get();
+
+ /**
+ * @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.
+ * @note The callback is invoked before reading the character from the
+ * buffer or before entering the state @p THD_STATE_WTQUEUE.
+ *
+ * @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 A byte value from the queue.
+ * @retval Q_TIMEOUT if the specified time expired.
+ * @retval Q_RESET if the queue has been reset.
+ *
+ * @api
+ */
+ msg_t getTimeout(systime_t time);
+
+ /**
+ * @brief Input queue read with timeout.
+ * @details The function reads data from an input queue into a buffer. The
+ * operation completes when the specified amount of data has been
+ * transferred or after the specified timeout or if the queue has
+ * been reset.
+ * @note The function is not atomic, if you need atomicity it is
+ * suggested to use a semaphore or a mutex for mutual exclusion.
+ * @note The callback is invoked before reading each character from the
+ * buffer or before entering the state @p THD_STATE_WTQUEUE.
+ *
+ * @param[out] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred, the
+ * value 0 is reserved
+ * @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 number of bytes effectively transferred.
+ *
+ * @api
+ */
+ size_t readTimeout(uint8_t *bp, size_t n, systime_t time);
+ };
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::InQueueBuffer *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Template class encapsulating an input queue and its buffer.
+ *
+ * @param N size of the input queue
+ */
+ template <int N>
+ class InQueueBuffer : public InQueue {
+ private:
+ uint8_t iq_buf[N];
+
+ public:
+ /**
+ * @brief InQueueBuffer constructor.
+ *
+ * @param[in] infy input notify callback function
+ * @param[in] link parameter to be passed to the callback
+ *
+ * @init
+ */
+ InQueueBuffer(qnotify_t infy, void *link) : InQueue(iq_buf, N,
+ infy, link) {
+ }
+ };
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::OutQueue *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Class encapsulating an output queue.
+ */
+ class OutQueue {
+ private:
+ /**
+ * @brief Embedded @p ::OutputQueue structure.
+ */
+ ::OutputQueue oq;
+
+ public:
+ /**
+ * @brief OutQueue constructor.
+ *
+ * @param[in] bp pointer to a memory area allocated as queue buffer
+ * @param[in] size size of the queue buffer
+ * @param[in] onfy pointer to a callback function that is invoked when
+ * data is written to the queue. The value can be
+ * @p NULL.
+ * @param[in] link application defined pointer
+ *
+ * @init
+ */
+ OutQueue(uint8_t *bp, size_t size, qnotify_t onfy, void *link);
+
+ /**
+ * @brief Returns the filled space into an output queue.
+ *
+ * @return The number of full bytes in the queue.
+ * @retval 0 if the queue is empty.
+ *
+ * @iclass
+ */
+ size_t getFullI(void);
+
+ /**
+ * @brief Returns the empty space into an output queue.
+ *
+ * @return The number of empty bytes in the queue.
+ * @retval 0 if the queue is full.
+ *
+ * @iclass
+ */
+ size_t getEmptyI(void);
+
+ /**
+ * @brief Evaluates to @p TRUE if the specified output queue is empty.
+ *
+ * @return The queue status.
+ * @retval false if the queue is not empty.
+ * @retval true if the queue is empty.
+ *
+ * @iclass
+ */
+ bool isEmptyI(void);
+
+ /**
+ * @brief Evaluates to @p TRUE if the specified output queue is full.
+ *
+ * @return The queue status.
+ * @retval FALSE if the queue is not full.
+ * @retval TRUE if the queue is full.
+ *
+ * @iclass
+ */
+ bool isFullI(void);
+
+ /**
+ * @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.
+ * @note A reset operation can be used by a low level driver in order
+ * to obtain immediate attention from the high level layers.
+ *
+ * @iclass
+ */
+ void resetI(void);
+
+ /**
+ * @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] 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 has been reset.
+ *
+ * @api
+ */
+ msg_t put(uint8_t b);
+
+ /**
+ * @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.
+ * @note The callback is invoked after writing the character into the
+ * buffer.
+ *
+ * @param[in] b the byte value to be written in the queue
+ * @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 Q_OK if the operation succeeded.
+ * @retval Q_TIMEOUT if the specified time expired.
+ * @retval Q_RESET if the queue has been reset.
+ *
+ * @api
+ */
+ msg_t putTimeout(uint8_t b, systime_t time);
+
+ /**
+ * @brief Output queue read.
+ * @details A byte value is read from the low end of an output queue.
+ *
+ * @return The byte value from the queue.
+ * @retval Q_EMPTY if the queue is empty.
+ *
+ * @iclass
+ */
+ msg_t getI(void);
+
+ /**
+ * @brief Output queue write with timeout.
+ * @details The function writes data from a buffer to an output queue. The
+ * operation completes when the specified amount of data has been
+ * transferred or after the specified timeout or if the queue has
+ * been reset.
+ * @note The function is not atomic, if you need atomicity it is
+ * suggested to use a semaphore or a mutex for mutual exclusion.
+ * @note The callback is invoked after writing each character into the
+ * buffer.
+ *
+ * @param[out] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred, the
+ * value 0 is reserved
+ * @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 number of bytes effectively transferred.
+ *
+ * @api
+ */
+ size_t writeTimeout(const uint8_t *bp, size_t n, systime_t time);
+};
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::OutQueueBuffer *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Template class encapsulating an output queue and its buffer.
+ *
+ * @param N size of the output queue
+ */
+ template <int N>
+ class OutQueueBuffer : public OutQueue {
+ private:
+ uint8_t oq_buf[N];
+
+ public:
+ /**
+ * @brief OutQueueBuffer constructor.
+ *
+ * @param[in] onfy output notify callback function
+ * @param[in] link parameter to be passed to the callback
+ *
+ * @init
+ */
+ OutQueueBuffer(qnotify_t onfy, void *link) : OutQueue(oq_buf, N,
+ onfy, link) {
+ }
+ };
+#endif /* CH_USE_QUEUES */
+
+#if CH_USE_MAILBOXES || defined(__DOXYGEN__)
+ /*------------------------------------------------------------------------*
+ * chibios_rt::Mailbox *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Class encapsulating a mailbox.
+ */
+ class Mailbox {
+ public:
+ /**
+ * @brief Embedded @p ::Mailbox structure.
+ */
+ ::Mailbox mb;
+
+ /**
+ * @brief Mailbox constructor.
+ * @details The embedded @p ::Mailbox structure is initialized.
+ *
+ * @param[in] buf pointer to the messages buffer as an array of
+ * @p msg_t
+ * @param[in] n number of elements in the buffer array
+ *
+ * @init
+ */
+ Mailbox(msg_t *buf, cnt_t n);
+
+ /**
+ * @brief Resets a Mailbox object.
+ * @details All the waiting threads are resumed with status @p RDY_RESET
+ * and the queued messages are lost.
+ *
+ * @api
+ */
+ void reset(void);
+
+ /**
+ * @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] 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 a message has been correctly posted.
+ * @retval RDY_RESET if the mailbox has been reset while waiting.
+ * @retval RDY_TIMEOUT if the operation has timed out.
+ *
+ * @api
+ */
+ msg_t post(msg_t msg, systime_t time);
+
+ /**
+ * @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] 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 a message has been correctly posted.
+ * @retval RDY_RESET if the mailbox has been reset while waiting.
+ * @retval RDY_TIMEOUT if the operation has timed out.
+ *
+ * @sclass
+ */
+ msg_t postS(msg_t msg, systime_t time);
+
+ /**
+ * @brief Posts a message into a mailbox.
+ * @details This variant is non-blocking, the function returns a timeout
+ * condition if the queue is full.
+ *
+ * @param[in] msg the message to be posted on the mailbox
+ * @return The operation status.
+ * @retval RDY_OK if a message has been correctly posted.
+ * @retval RDY_TIMEOUT if the mailbox is full and the message cannot be
+ * posted.
+ *
+ * @iclass
+ */
+ msg_t postI(msg_t msg);
+
+ /**
+ * @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] 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 a message has been correctly posted.
+ * @retval RDY_RESET if the mailbox has been reset while waiting.
+ * @retval RDY_TIMEOUT if the operation has timed out.
+ *
+ * @api
+ */
+ msg_t postAhead(msg_t msg, systime_t time);
+
+ /**
+ * @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] 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 a message has been correctly posted.
+ * @retval RDY_RESET if the mailbox has been reset while waiting.
+ * @retval RDY_TIMEOUT if the operation has timed out.
+ *
+ * @sclass
+ */
+ msg_t postAheadS(msg_t msg, systime_t time);
+
+ /**
+ * @brief Posts an high priority message into a mailbox.
+ * @details This variant is non-blocking, the function returns a timeout
+ * condition if the queue is full.
+ *
+ * @param[in] msg the message to be posted on the mailbox
+ * @return The operation status.
+ * @retval RDY_OK if a message has been correctly posted.
+ * @retval RDY_TIMEOUT if the mailbox is full and the message cannot be
+ * posted.
+ *
+ * @iclass
+ */
+ msg_t postAheadI(msg_t msg);
+
+ /**
+ * @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[out] msgp pointer to a message variable for the received
+ * @param[in] time message 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 has been correctly fetched.
+ * @retval RDY_RESET if the mailbox has been reset while waiting.
+ * @retval RDY_TIMEOUT if the operation has timed out.
+ *
+ * @api
+ */
+ msg_t fetch(msg_t *msgp, systime_t time);
+
+ /**
+ * @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[out] msgp pointer to a message variable for the received
+ * @param[in] time message 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 has been correctly fetched.
+ * @retval RDY_RESET if the mailbox has been reset while waiting.
+ * @retval RDY_TIMEOUT if the operation has timed out.
+ *
+ * @sclass
+ */
+ msg_t fetchS(msg_t *msgp, systime_t time);
+
+ /**
+ * @brief Retrieves a message from a mailbox.
+ * @details This variant is non-blocking, the function returns a timeout
+ * condition if the queue is empty.
+ *
+ * @param[out] msgp pointer to a message variable for the received
+ * message
+ * @return The operation status.
+ * @retval RDY_OK if a message has been correctly fetched.
+ * @retval RDY_TIMEOUT if the mailbox is empty and a message cannot be
+ * fetched.
+ *
+ * @iclass
+ */
+ msg_t fetchI(msg_t *msgp);
+
+ /**
+ * @brief Returns the number of free message slots into a mailbox.
+ * @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.
+ *
+ * @return The number of empty message slots.
+ *
+ * @iclass
+ */
+ cnt_t getFreeCountI(void);
+
+ /**
+ * @brief Returns the number of used message slots into a mailbox.
+ * @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.
+ *
+ * @return The number of queued messages.
+ *
+ * @iclass
+ */
+ cnt_t getUsedCountI(void);
+ };
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::MailboxBuffer *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Template class encapsulating a mailbox and its messages buffer.
+ *
+ * @param N size of the mailbox
+ */
+ template <int N>
+ class MailboxBuffer : public Mailbox {
+ private:
+ msg_t mb_buf[N];
+
+ public:
+ /**
+ * @brief BufferMailbox constructor.
+ *
+ * @init
+ */
+ MailboxBuffer(void) : Mailbox(mb_buf,
+ (cnt_t)(sizeof mb_buf / sizeof (msg_t))) {
+ }
+ };
+#endif /* CH_USE_MAILBOXES */
+
+#if CH_USE_MEMPOOLS || defined(__DOXYGEN__)
+ /*------------------------------------------------------------------------*
+ * chibios_rt::MemoryPool *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Class encapsulating a mailbox.
+ */
+ class MemoryPool {
+ public:
+ /**
+ * @brief Embedded @p ::MemoryPool structure.
+ */
+ ::MemoryPool pool;
+
+ /**
+ * @brief MemoryPool constructor.
+ *
+ * @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.
+ * @param[in] provider memory provider function for the memory pool or
+ * @p NULL if the pool is not allowed to grow
+ * automatically
+ *
+ * @init
+ */
+ MemoryPool(size_t size, memgetfunc_t provider);
+
+ /**
+ * @brief MemoryPool constructor.
+ *
+ * @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.
+ * @param[in] provider memory provider function for the memory pool or
+ * @p NULL if the pool is not allowed to grow
+ * automatically
+ * @param[in] p pointer to the array first element
+ * @param[in] n number of elements in the array
+ *
+ * @init
+ */
+ MemoryPool(size_t size, memgetfunc_t provider, void* p, size_t n);
+
+ /**
+ * @brief Loads a memory pool with an array of static objects.
+ * @pre The memory pool must be already been initialized.
+ * @pre The array elements must be of the right size for the specified
+ * memory pool.
+ * @post The memory pool contains the elements of the input array.
+ *
+ * @param[in] p pointer to the array first element
+ * @param[in] n number of elements in the array
+ *
+ * @api
+ */
+ void loadArray(void *p, size_t n);
+
+ /**
+ * @brief Allocates an object from a memory pool.
+ * @pre The memory pool must be already been initialized.
+ *
+ * @return The pointer to the allocated object.
+ * @retval NULL if pool is empty.
+ *
+ * @iclass
+ */
+ void *allocI(void);
+
+ /**
+ * @brief Allocates an object from a memory pool.
+ * @pre The memory pool must be already been initialized.
+ *
+ * @return The pointer to the allocated object.
+ * @retval NULL if pool is empty.
+ *
+ * @api
+ */
+ void *alloc(void);
+
+ /**
+ * @brief Releases an object into a memory pool.
+ * @pre The memory pool must be already been initialized.
+ * @pre The freed object must be of the right size for the specified
+ * memory pool.
+ * @pre The object must be properly aligned to contain a pointer to
+ * void.
+ *
+ * @param[in] objp the pointer to the object to be released
+ *
+ * @iclass
+ */
+ void free(void *objp);
+
+ /**
+ * @brief Adds an object to a memory pool.
+ * @pre The memory pool must be already been initialized.
+ * @pre The added object must be of the right size for the specified
+ * memory pool.
+ * @pre The added object must be memory aligned to the size of
+ * @p stkalign_t type.
+ * @note This function is just an alias for @p chPoolFree() and has been
+ * added for clarity.
+ *
+ * @param[in] objp the pointer to the object to be added
+ *
+ * @iclass
+ */
+ void freeI(void *objp);
+ };
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::ObjectsPool *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Template class encapsulating a memory pool and its elements.
+ */
+ template<class T, size_t N>
+ class ObjectsPool : public MemoryPool {
+ private:
+ /* The buffer is declared as an array of pointers to void for two
+ reasons:
+ 1) The objects must be properly aligned to hold a pointer as
+ first field.
+ 2) There is no need to invoke constructors for object that are
+ into the pool.*/
+ void *pool_buf[(N * sizeof (T)) / sizeof (void *)];
+
+ public:
+ /**
+ * @brief ObjectsPool constructor.
+ *
+ * @init
+ */
+ ObjectsPool(void) : MemoryPool(sizeof (T), NULL) {
+
+ loadArray(pool_buf, N);
+ }
+ };
+#endif /* CH_USE_MEMPOOLS */
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::BaseSequentialStreamInterface *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Interface of a ::BaseSequentialStream.
+ * @note You can cast a ::BaseSequentialStream to this interface and use
+ * it, the memory layout is the same.
+ */
+ class BaseSequentialStreamInterface {
+ public:
+ /**
+ * @brief Sequential Stream write.
+ * @details The function writes data from a buffer to a stream.
+ *
+ * @param[in] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred
+ * @return The number of bytes transferred. The return value
+ * can be less than the specified number of bytes if
+ * an end-of-file condition has been met.
+ *
+ * @api
+ */
+ virtual size_t write(const uint8_t *bp, size_t n) = 0;
+
+ /**
+ * @brief Sequential Stream read.
+ * @details The function reads data from a stream into a buffer.
+ *
+ * @param[out] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred
+ * @return The number of bytes transferred. The return value
+ * can be less than the specified number of bytes if
+ * an end-of-file condition has been met.
+ *
+ * @api
+ */
+ virtual size_t read(uint8_t *bp, size_t n) = 0;
+
+ /**
+ * @brief Sequential Stream 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] 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 an end-of-file condition has been met.
+ *
+ * @api
+ */
+ virtual msg_t put(uint8_t b) = 0;
+
+ /**
+ * @brief Sequential Stream 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.
+ *
+ * @return A byte value from the queue.
+ * @retval Q_RESET if an end-of-file condition has been met.
+ *
+ * @api
+ */
+ virtual msg_t get(void) = 0;
+ };
+}
+
+#endif /* _CH_HPP_ */
+
+/** @} */
diff --git a/os/various/cpp_wrappers/kernel.mk b/os/various/cpp_wrappers/kernel.mk
new file mode 100644
index 000000000..6cd787658
--- /dev/null
+++ b/os/various/cpp_wrappers/kernel.mk
@@ -0,0 +1,4 @@
+# C++ wrapper files.
+CHCPPSRC = ${CHIBIOS}/os/various/cpp_wrappers/ch.cpp
+
+CHCPPINC = ${CHIBIOS}/os/various/cpp_wrappers
diff --git a/os/various/devices_lib/accel/lis302dl.c b/os/various/devices_lib/accel/lis302dl.c
new file mode 100644
index 000000000..14e2a0ad1
--- /dev/null
+++ b/os/various/devices_lib/accel/lis302dl.c
@@ -0,0 +1,119 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file lis302dl.c
+ * @brief LIS302DL MEMS interface module through SPI code.
+ *
+ * @addtogroup lis302dl
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "lis302dl.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+static uint8_t txbuf[2];
+static uint8_t rxbuf[2];
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Reads a register value.
+ * @pre The SPI interface must be initialized and the driver started.
+ *
+ * @param[in] spip pointer to the SPI initerface
+ * @param[in] reg register number
+ * @return The register value.
+ */
+uint8_t lis302dlReadRegister(SPIDriver *spip, uint8_t reg) {
+
+ spiSelect(spip);
+ txbuf[0] = 0x80 | reg;
+ txbuf[1] = 0xff;
+ spiExchange(spip, 2, txbuf, rxbuf);
+ spiUnselect(spip);
+ return rxbuf[1];
+}
+
+/**
+ * @brief Writes a value into a register.
+ * @pre The SPI interface must be initialized and the driver started.
+ *
+ * @param[in] spip pointer to the SPI initerface
+ * @param[in] reg register number
+ * @param[in] value the value to be written
+ */
+void lis302dlWriteRegister(SPIDriver *spip, uint8_t reg, uint8_t value) {
+
+ switch (reg) {
+ default:
+ /* Reserved register must not be written, according to the datasheet
+ this could permanently damage the device.*/
+ chDbgAssert(FALSE, "lis302dlWriteRegister(), #1", "reserved register");
+ case LIS302DL_WHO_AM_I:
+ case LIS302DL_HP_FILTER_RESET:
+ case LIS302DL_STATUS_REG:
+ case LIS302DL_OUTX:
+ case LIS302DL_OUTY:
+ case LIS302DL_OUTZ:
+ case LIS302DL_FF_WU_SRC1:
+ case LIS302DL_FF_WU_SRC2:
+ case LIS302DL_CLICK_SRC:
+ /* Read only registers cannot be written, the command is ignored.*/
+ return;
+ case LIS302DL_CTRL_REG1:
+ case LIS302DL_CTRL_REG2:
+ case LIS302DL_CTRL_REG3:
+ case LIS302DL_FF_WU_CFG1:
+ case LIS302DL_FF_WU_THS1:
+ case LIS302DL_FF_WU_DURATION1:
+ case LIS302DL_FF_WU_CFG2:
+ case LIS302DL_FF_WU_THS2:
+ case LIS302DL_FF_WU_DURATION2:
+ case LIS302DL_CLICK_CFG:
+ case LIS302DL_CLICK_THSY_X:
+ case LIS302DL_CLICK_THSZ:
+ case LIS302DL_CLICK_TIMELIMIT:
+ case LIS302DL_CLICK_LATENCY:
+ case LIS302DL_CLICK_WINDOW:
+ spiSelect(spip);
+ txbuf[0] = reg;
+ txbuf[1] = value;
+ spiSend(spip, 2, txbuf);
+ spiUnselect(spip);
+ }
+}
+
+/** @} */
diff --git a/os/various/devices_lib/accel/lis302dl.dox b/os/various/devices_lib/accel/lis302dl.dox
new file mode 100644
index 000000000..02f51606a
--- /dev/null
+++ b/os/various/devices_lib/accel/lis302dl.dox
@@ -0,0 +1,30 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
+ 2011,2012,2013 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/>.
+*/
+
+/**
+ * @defgroup lis302dl Interface module for LIS302DL MEMS
+ *
+ * @brief Interface module for LIS302DL MEMS.
+ * @details This module implements a generic interface for the LIS302DL
+ * STMicroelectronics MEMS device. The communication is performed
+ * through a standard SPI driver.
+ *
+ * @ingroup accel
+ */
diff --git a/os/various/devices_lib/accel/lis302dl.h b/os/various/devices_lib/accel/lis302dl.h
new file mode 100644
index 000000000..0c6637a0d
--- /dev/null
+++ b/os/various/devices_lib/accel/lis302dl.h
@@ -0,0 +1,93 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file lis302dl.h
+ * @brief LIS302DL MEMS interface module through SPI header.
+ *
+ * @addtogroup lis302dl
+ * @{
+ */
+
+#ifndef _LIS302DL_H_
+#define _LIS302DL_H_
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name LIS302DL register names
+ * @{
+ */
+#define LIS302DL_WHO_AM_I 0x0F
+#define LIS302DL_CTRL_REG1 0x20
+#define LIS302DL_CTRL_REG2 0x21
+#define LIS302DL_CTRL_REG3 0x22
+#define LIS302DL_HP_FILTER_RESET 0x23
+#define LIS302DL_STATUS_REG 0x27
+#define LIS302DL_OUTX 0x29
+#define LIS302DL_OUTY 0x2B
+#define LIS302DL_OUTZ 0x2D
+#define LIS302DL_FF_WU_CFG1 0x30
+#define LIS302DL_FF_WU_SRC1 0x31
+#define LIS302DL_FF_WU_THS1 0x32
+#define LIS302DL_FF_WU_DURATION1 0x33
+#define LIS302DL_FF_WU_CFG2 0x34
+#define LIS302DL_FF_WU_SRC2 0x35
+#define LIS302DL_FF_WU_THS2 0x36
+#define LIS302DL_FF_WU_DURATION2 0x37
+#define LIS302DL_CLICK_CFG 0x38
+#define LIS302DL_CLICK_SRC 0x39
+#define LIS302DL_CLICK_THSY_X 0x3B
+#define LIS302DL_CLICK_THSZ 0x3C
+#define LIS302DL_CLICK_TIMELIMIT 0x3D
+#define LIS302DL_CLICK_LATENCY 0x3E
+#define LIS302DL_CLICK_WINDOW 0x3F
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ uint8_t lis302dlReadRegister(SPIDriver *spip, uint8_t reg);
+ void lis302dlWriteRegister(SPIDriver *spip, uint8_t reg, uint8_t value);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIS302DL_H_ */
+
+/** @} */
diff --git a/os/various/devices_lib/lcd/lcd3310.c b/os/various/devices_lib/lcd/lcd3310.c
new file mode 100644
index 000000000..86fee541b
--- /dev/null
+++ b/os/various/devices_lib/lcd/lcd3310.c
@@ -0,0 +1,310 @@
+/*
+ Copyright (C) 2013 Marcin Jokel
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file lcd3310.c
+ * @brief Nokia 3310 LCD interface module through SPI code.
+ *
+ * @addtogroup lcd3310
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "lcd3310.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+const uint8_t Fonts8x5 [][LCD3310_FONT_X_SIZE] =
+{
+ { 0x00, 0x00, 0x00, 0x00, 0x00 }, /* space */
+ { 0x00, 0x00, 0x2f, 0x00, 0x00 }, /* ! */
+ { 0x00, 0x07, 0x00, 0x07, 0x00 }, /* " */
+ { 0x14, 0x7f, 0x14, 0x7f, 0x14 }, /* # */
+ { 0x24, 0x2a, 0x7f, 0x2a, 0x12 }, /* $ */
+ { 0xc4, 0xc8, 0x10, 0x26, 0x46 }, /* % */
+ { 0x36, 0x49, 0x55, 0x22, 0x50 }, /* & */
+ { 0x00, 0x05, 0x03, 0x00, 0x00 }, /* ' */
+ { 0x00, 0x1c, 0x22, 0x41, 0x00 }, /* ( */
+ { 0x00, 0x41, 0x22, 0x1c, 0x00 }, /* ) */
+ { 0x14, 0x08, 0x3E, 0x08, 0x14 }, /* * */
+ { 0x08, 0x08, 0x3E, 0x08, 0x08 }, /* + */
+ { 0x00, 0x00, 0x50, 0x30, 0x00 }, /* , */
+ { 0x10, 0x10, 0x10, 0x10, 0x10 }, /* - */
+ { 0x00, 0x60, 0x60, 0x00, 0x00 }, /* . */
+ { 0x20, 0x10, 0x08, 0x04, 0x02 }, /* / */
+ { 0x3E, 0x51, 0x49, 0x45, 0x3E }, /* 0 */
+ { 0x00, 0x42, 0x7F, 0x40, 0x00 }, /* 1 */
+ { 0x42, 0x61, 0x51, 0x49, 0x46 }, /* 2 */
+ { 0x21, 0x41, 0x45, 0x4B, 0x31 }, /* 3 */
+ { 0x18, 0x14, 0x12, 0x7F, 0x10 }, /* 4 */
+ { 0x27, 0x45, 0x45, 0x45, 0x39 }, /* 5 */
+ { 0x3C, 0x4A, 0x49, 0x49, 0x30 }, /* 6 */
+ { 0x01, 0x71, 0x09, 0x05, 0x03 }, /* 7 */
+ { 0x36, 0x49, 0x49, 0x49, 0x36 }, /* 8 */
+ { 0x06, 0x49, 0x49, 0x29, 0x1E }, /* 9 */
+ { 0x00, 0x36, 0x36, 0x00, 0x00 }, /* : */
+ { 0x00, 0x56, 0x36, 0x00, 0x00 }, /* ; */
+ { 0x08, 0x14, 0x22, 0x41, 0x00 }, /* < */
+ { 0x14, 0x14, 0x14, 0x14, 0x14 }, /* = */
+ { 0x00, 0x41, 0x22, 0x14, 0x08 }, /* > */
+ { 0x02, 0x01, 0x51, 0x09, 0x06 }, /* ? */
+ { 0x32, 0x49, 0x59, 0x51, 0x3E }, /* @ */
+ { 0x7E, 0x11, 0x11, 0x11, 0x7E }, /* A */
+ { 0x7F, 0x49, 0x49, 0x49, 0x36 }, /* B */
+ { 0x3E, 0x41, 0x41, 0x41, 0x22 }, /* C */
+ { 0x7F, 0x41, 0x41, 0x22, 0x1C }, /* D */
+ { 0x7F, 0x49, 0x49, 0x49, 0x41 }, /* E */
+ { 0x7F, 0x09, 0x09, 0x09, 0x01 }, /* F */
+ { 0x3E, 0x41, 0x49, 0x49, 0x7A }, /* G */
+ { 0x7F, 0x08, 0x08, 0x08, 0x7F }, /* H */
+ { 0x00, 0x41, 0x7F, 0x41, 0x00 }, /* I */
+ { 0x20, 0x40, 0x41, 0x3F, 0x01 }, /* J */
+ { 0x7F, 0x08, 0x14, 0x22, 0x41 }, /* K */
+ { 0x7F, 0x40, 0x40, 0x40, 0x40 }, /* L */
+ { 0x7F, 0x02, 0x0C, 0x02, 0x7F }, /* M */
+ { 0x7F, 0x04, 0x08, 0x10, 0x7F }, /* N */
+ { 0x3E, 0x41, 0x41, 0x41, 0x3E }, /* O */
+ { 0x7F, 0x09, 0x09, 0x09, 0x06 }, /* P */
+ { 0x3E, 0x41, 0x51, 0x21, 0x5E }, /* Q */
+ { 0x7F, 0x09, 0x19, 0x29, 0x46 }, /* R */
+ { 0x46, 0x49, 0x49, 0x49, 0x31 }, /* S */
+ { 0x01, 0x01, 0x7F, 0x01, 0x01 }, /* T */
+ { 0x3F, 0x40, 0x40, 0x40, 0x3F }, /* U */
+ { 0x1F, 0x20, 0x40, 0x20, 0x1F }, /* V */
+ { 0x3F, 0x40, 0x38, 0x40, 0x3F }, /* W */
+ { 0x63, 0x14, 0x08, 0x14, 0x63 }, /* X */
+ { 0x07, 0x08, 0x70, 0x08, 0x07 }, /* Y */
+ { 0x61, 0x51, 0x49, 0x45, 0x43 }, /* Z */
+ { 0x00, 0x7F, 0x41, 0x41, 0x00 }, /* [ */
+ { 0x55, 0x2A, 0x55, 0x2A, 0x55 }, /* \ */
+ { 0x00, 0x41, 0x41, 0x7F, 0x00 }, /* ] */
+ { 0x04, 0x02, 0x01, 0x02, 0x04 }, /* ^ */
+ { 0x40, 0x40, 0x40, 0x40, 0x40 }, /* _ */
+ { 0x00, 0x01, 0x02, 0x04, 0x00 }, /* ' */
+ { 0x20, 0x54, 0x54, 0x54, 0x78 }, /* a */
+ { 0x7F, 0x48, 0x44, 0x44, 0x38 }, /* b */
+ { 0x38, 0x44, 0x44, 0x44, 0x20 }, /* c */
+ { 0x38, 0x44, 0x44, 0x48, 0x7F }, /* d */
+ { 0x38, 0x54, 0x54, 0x54, 0x18 }, /* e */
+ { 0x08, 0x7E, 0x09, 0x01, 0x02 }, /* f */
+ { 0x0C, 0x52, 0x52, 0x52, 0x3E }, /* g */
+ { 0x7F, 0x08, 0x04, 0x04, 0x78 }, /* h */
+ { 0x00, 0x44, 0x7D, 0x40, 0x00 }, /* i */
+ { 0x20, 0x40, 0x44, 0x3D, 0x00 }, /* j */
+ { 0x7F, 0x10, 0x28, 0x44, 0x00 }, /* k */
+ { 0x00, 0x41, 0x7F, 0x40, 0x00 }, /* l */
+ { 0x7C, 0x04, 0x18, 0x04, 0x78 }, /* m */
+ { 0x7C, 0x08, 0x04, 0x04, 0x78 }, /* n */
+ { 0x38, 0x44, 0x44, 0x44, 0x38 }, /* o */
+ { 0x7C, 0x14, 0x14, 0x14, 0x08 }, /* p */
+ { 0x08, 0x14, 0x14, 0x18, 0x7C }, /* q */
+ { 0x7C, 0x08, 0x04, 0x04, 0x08 }, /* r */
+ { 0x48, 0x54, 0x54, 0x54, 0x20 }, /* s */
+ { 0x04, 0x3F, 0x44, 0x40, 0x20 }, /* t */
+ { 0x3C, 0x40, 0x40, 0x20, 0x7C }, /* u */
+ { 0x1C, 0x20, 0x40, 0x20, 0x1C }, /* v */
+ { 0x3C, 0x40, 0x30, 0x40, 0x3C }, /* w */
+ { 0x44, 0x28, 0x10, 0x28, 0x44 }, /* x */
+ { 0x0C, 0x50, 0x50, 0x50, 0x3C }, /* y */
+ { 0x44, 0x64, 0x54, 0x4C, 0x44 }, /* z */
+ { 0x00, 0x08, 0x36, 0x41, 0x00 }, /* { */
+ { 0x00, 0x00, 0x7F, 0x00, 0x00 }, /* | */
+ { 0x00, 0x41, 0x36, 0x08, 0x00 }, /* } */
+};
+
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief LCD driver initialization.
+ * @pre The SPI interface must be initialized and the driver started.
+ *
+ * @param[in] spip pointer to the SPI interface
+ *
+ */
+void lcd3310Init(SPIDriver *spip) {
+
+ /* Reset LCD */
+ palClearPad(LCD3310_RES_PORT, LCD3310_RES_PIN);
+ chThdSleepMilliseconds(15);
+ palSetPad(LCD3310_RES_PORT, LCD3310_RES_PIN);
+ chThdSleepMilliseconds(15);
+
+ /* Send configuration commands to LCD */
+ lcd3310WriteByte(spip, 0x21, LCD3310_SEND_CMD); /* LCD extended commands */
+ lcd3310WriteByte(spip, 0xC8, LCD3310_SEND_CMD); /* Set LCD Vop (Contrast) */
+ lcd3310WriteByte(spip, 0x05, LCD3310_SEND_CMD); /* Set start line S6 to 1 TLS8204 */
+ lcd3310WriteByte(spip, 0x40, LCD3310_SEND_CMD); /* Set start line S[5:0] to 0x00 TLS8204 */
+ lcd3310WriteByte(spip, 0x12, LCD3310_SEND_CMD); /* LCD bias mode 1:68. */
+ lcd3310WriteByte(spip, 0x20, LCD3310_SEND_CMD); /* LCD standard Commands, horizontal addressing mode. */
+ lcd3310WriteByte(spip, 0x08, LCD3310_SEND_CMD); /* LCD blank */
+ lcd3310WriteByte(spip, 0x0C, LCD3310_SEND_CMD); /* LCD in normal mode. */
+
+ lcd3310Clear(spip); /* Clear LCD */
+}
+
+/**
+ * @brief Write byte to LCD driver.
+ * @pre The LCD driver must be initialized.
+ *
+ * @param[in] spip pointer to the SPI interface
+ * @param[in] data data to write
+ * @param[in] cd select between command or data
+ */
+void lcd3310WriteByte(SPIDriver *spip, uint8_t data, uint8_t cd) {
+
+ spiSelect(spip);
+
+ if(cd == LCD3310_SEND_DATA) {
+ palSetPad(LCD3310_DC_PORT, LCD3310_DC_PIN);
+ }
+ else {
+ palClearPad(LCD3310_DC_PORT, LCD3310_DC_PIN);
+ }
+
+ spiSend(spip, 1, &data); // change to normal spi send
+ spiUnselect(spip);
+}
+
+/**
+ * @brief Clear LCD
+ * @pre The LCD driver must be initialized.
+ *
+ * @param[in] spip pointer to the SPI interface
+ */
+void lcd3310Clear(SPIDriver *spip) { // ok
+
+ uint32_t i, j;
+
+ for (i = 0; i < LCD3310_Y_RES/LCD3310_FONT_Y_SIZE; i++) {
+ lcd3310SetPosXY(spip, 0, i);
+ for (j = 0; j < LCD3310_X_RES; j++)
+ lcd3310WriteByte(spip, 0x00, LCD3310_SEND_DATA);
+ }
+
+}
+
+/**
+ * @brief Set position
+ * @pre The LCD driver must be initialized.
+ *
+ * @param[in] spip pointer to the SPI interface
+ * @param[in] x column address in LCD DDRAM, 0 to 83
+ * @param[in] y page address in LCD DDRAM, 0 to 5
+ */
+void lcd3310SetPosXY(SPIDriver *spip, uint8_t x, uint8_t y) {
+
+ if (y > LCD3310_Y_RES/LCD3310_FONT_Y_SIZE) return;
+ if (x > LCD3310_X_RES) return;
+
+ lcd3310WriteByte(spip, 0x80 | x, LCD3310_SEND_CMD); /* Set x position */
+ lcd3310WriteByte(spip, 0x40 | y, LCD3310_SEND_CMD); /* Set y position */
+
+}
+
+/**
+ * @brief Write char
+ * @pre The LCD driver must be initialized.
+ *
+ * @param[in] spip pointer to the SPI interface
+ * @param[in] ch char
+ */
+void lcd3310WriteChar(SPIDriver *spip, uint8_t ch) {
+
+ uint8_t i;
+
+ for ( i = 0; i < LCD3310_FONT_X_SIZE; i++ ){
+ lcd3310WriteByte(spip, Fonts8x5[ch - 32][i], LCD3310_SEND_DATA);
+ }
+
+}
+
+/**
+ * @brief Set LCD contrast.
+ * @pre The LCD driver must be initialized.
+ *
+ * @param[in] spip pointer to the SPI interface
+ * @param[in] contrast LCD contrast value
+ */
+void lcd3310Contrast (SPIDriver *spip, uint8_t contrast) {
+
+ lcd3310WriteByte(spip, 0x21, LCD3310_SEND_CMD); /* LCD Extended Commands */
+ lcd3310WriteByte(spip, 0x80 | contrast, LCD3310_SEND_CMD); /* Set LCD Vop (Contrast) */
+ lcd3310WriteByte(spip, 0x20, LCD3310_SEND_CMD); /* LCD Standard Commands, horizontal addressing mode */
+}
+
+
+/**
+ * @brief Write text
+ * @pre The LCD driver must be initialized.
+ *
+ * @param[in] spip pointer to the SPI interface
+ * @param[in] strp pointer to text
+ */
+void lcd3310WriteText(SPIDriver *spip, const uint8_t * strp) {
+
+ while ( *strp ) {
+ lcd3310WriteChar(spip, *strp);
+ strp++;
+ }
+}
+
+/**
+ * @brief Rotate text
+ * @pre The LCD driver must be initialized.
+ *
+ * @param[in] spip pointer to the SPI interface
+ * @param[in] strp pointer to text
+ * @param[in] offset text offset
+ */
+void lcd3310RotateText(SPIDriver *spip, const uint8_t * strp, uint8_t offset) {
+
+ uint8_t i;
+ uint8_t n;
+ uint8_t m;
+
+ for(n = 0; strp[n] != '\0'; n++); /* Count number of char */
+
+ if (offset >= n)
+ return;
+
+ for (i = 0; i < LCD3310_X_RES/LCD3310_FONT_X_SIZE; i++) {
+ m = i + offset;
+ if ( m < n)
+ lcd3310WriteChar(spip, strp[m]);
+ else
+ lcd3310WriteChar(spip, strp[m - n]);
+ }
+}
+
+/** @} */
diff --git a/os/various/devices_lib/lcd/lcd3310.h b/os/various/devices_lib/lcd/lcd3310.h
new file mode 100644
index 000000000..b3bf90660
--- /dev/null
+++ b/os/various/devices_lib/lcd/lcd3310.h
@@ -0,0 +1,94 @@
+/*
+ Copyright (C) 2013 Marcin Jokel
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file lcd3310.h
+ * @brief Nokia 3310 LCD interface module through SPI code.
+ *
+ * @addtogroup lcd3310
+ * @{
+ */
+
+#ifndef _LCD3310_H_
+#define _LCD3310_H_
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+#define LCD3310_X_RES 84
+#define LCD3310_Y_RES 48
+
+#define LCD3310_FONT_X_SIZE 5
+#define LCD3310_FONT_Y_SIZE 8
+
+#define LCD3310_SEND_CMD 0
+#define LCD3310_SEND_DATA 1
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !defined(LCD3310_RES_PIN)
+#error "LCD3310_RES_PIN not defined!!!"
+#endif
+
+#if !defined(LCD3310_RES_PORT)
+#error "LCD3310_RES_PORT not defined!!!"
+#endif
+
+#if !defined(LCD3310_DC_PIN)
+#error "LCD3310_DC_PIN not defined!!!"
+#endif
+
+#if!defined(LCD3310_DC_PORT)
+#error "LCD3310_DC_PORT not defined!!!"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void lcd3310Init(SPIDriver *spip);
+ void lcd3310WriteByte(SPIDriver *spip, uint8_t data, uint8_t cd);
+ void lcd3310Contrast(SPIDriver *spip, uint8_t contrast);
+ void lcd3310Clear(SPIDriver *spip);
+ void lcd3310SetPosXY(SPIDriver *spip, uint8_t x, uint8_t y);
+ void lcd3310WriteChar (SPIDriver *spip, uint8_t ch);
+ void lcd3310WriteText(SPIDriver *spip, const uint8_t * strp);
+ void lcd3310RotateText(SPIDriver *spip, const uint8_t * strp, uint8_t offset);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LCD3310_H_ */
+
+/** @} */
diff --git a/os/various/evtimer.c b/os/various/evtimer.c
new file mode 100644
index 000000000..a077529da
--- /dev/null
+++ b/os/various/evtimer.c
@@ -0,0 +1,64 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file evtimer.c
+ * @brief Events Generator Timer code.
+ *
+ * @addtogroup event_timer
+ * @{
+ */
+
+#include "ch.h"
+#include "evtimer.h"
+
+static void tmrcb(void *p) {
+ EvTimer *etp = p;
+
+ chSysLockFromIsr();
+ chEvtBroadcastI(&etp->et_es);
+ chVTSetI(&etp->et_vt, etp->et_interval, tmrcb, etp);
+ chSysUnlockFromIsr();
+}
+
+/**
+ * @brief Starts the timer
+ * @details If the timer was already running then the function has no effect.
+ *
+ * @param etp pointer to an initialized @p EvTimer structure.
+ */
+void evtStart(EvTimer *etp) {
+
+ chSysLock();
+
+ if (!chVTIsArmedI(&etp->et_vt))
+ chVTSetI(&etp->et_vt, etp->et_interval, tmrcb, etp);
+
+ chSysUnlock();
+}
+
+/**
+ * @brief Stops the timer.
+ * @details If the timer was already stopped then the function has no effect.
+ *
+ * @param etp pointer to an initialized @p EvTimer structure.
+ */
+void evtStop(EvTimer *etp) {
+
+ chVTReset(&etp->et_vt);
+}
+
+/** @} */
diff --git a/os/various/evtimer.h b/os/various/evtimer.h
new file mode 100644
index 000000000..613c688a6
--- /dev/null
+++ b/os/various/evtimer.h
@@ -0,0 +1,68 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file evtimer.h
+ * @brief Events Generator Timer structures and macros.
+ *
+ * @addtogroup event_timer
+ * @{
+ */
+
+#ifndef _EVTIMER_H_
+#define _EVTIMER_H_
+
+
+/*
+ * Module dependencies check.
+ */
+#if !CH_USE_EVENTS
+#error "Event Timers require CH_USE_EVENTS"
+#endif
+
+/**
+ * @brief Event timer structure.
+ */
+typedef struct {
+ VirtualTimer et_vt;
+ EventSource et_es;
+ systime_t et_interval;
+} EvTimer;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void evtStart(EvTimer *etp);
+ void evtStop(EvTimer *etp);
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @brief Initializes an @p EvTimer structure.
+ *
+ * @param etp the EvTimer structure to be initialized
+ * @param time the interval in system ticks
+ */
+#define evtInit(etp, time) { \
+ chEvtInit(&(etp)->et_es); \
+ (etp)->et_vt.vt_func = NULL; \
+ (etp)->et_interval = (time); \
+}
+
+#endif /* _EVTIMER_H_ */
+
+/** @} */
diff --git a/os/various/fatfs_bindings/fatfs.mk b/os/various/fatfs_bindings/fatfs.mk
new file mode 100644
index 000000000..682091e00
--- /dev/null
+++ b/os/various/fatfs_bindings/fatfs.mk
@@ -0,0 +1,7 @@
+# FATFS files.
+FATFSSRC = ${CHIBIOS}/os/various/fatfs_bindings/fatfs_diskio.c \
+ ${CHIBIOS}/os/various/fatfs_bindings/fatfs_syscall.c \
+ ${CHIBIOS}/ext/fatfs/src/ff.c \
+ ${CHIBIOS}/ext/fatfs/src/option/ccsbcs.c
+
+FATFSINC = ${CHIBIOS}/ext/fatfs/src
diff --git a/os/various/fatfs_bindings/fatfs_diskio.c b/os/various/fatfs_bindings/fatfs_diskio.c
new file mode 100644
index 000000000..c724fa5f9
--- /dev/null
+++ b/os/various/fatfs_bindings/fatfs_diskio.c
@@ -0,0 +1,254 @@
+/*-----------------------------------------------------------------------*/
+/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2007 */
+/*-----------------------------------------------------------------------*/
+/* This is a stub disk I/O module that acts as front end of the existing */
+/* disk I/O modules and attach it to FatFs module with common interface. */
+/*-----------------------------------------------------------------------*/
+
+#include "ch.h"
+#include "hal.h"
+#include "ffconf.h"
+#include "diskio.h"
+
+#if HAL_USE_MMC_SPI && HAL_USE_SDC
+#error "cannot specify both MMC_SPI and SDC drivers"
+#endif
+
+#if HAL_USE_MMC_SPI
+extern MMCDriver MMCD1;
+#elif HAL_USE_SDC
+extern SDCDriver SDCD1;
+#else
+#error "MMC_SPI or SDC driver must be specified"
+#endif
+
+#if HAL_USE_RTC
+#include "chrtclib.h"
+extern RTCDriver RTCD1;
+#endif
+
+/*-----------------------------------------------------------------------*/
+/* Correspondence between physical drive number and physical drive. */
+
+#define MMC 0
+#define SDC 0
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Inidialize a Drive */
+
+DSTATUS disk_initialize (
+ BYTE drv /* Physical drive nmuber (0..) */
+)
+{
+ DSTATUS stat;
+
+ switch (drv) {
+#if HAL_USE_MMC_SPI
+ case MMC:
+ stat = 0;
+ /* It is initialized externally, just reads the status.*/
+ if (blkGetDriverState(&MMCD1) != BLK_READY)
+ stat |= STA_NOINIT;
+ if (mmcIsWriteProtected(&MMCD1))
+ stat |= STA_PROTECT;
+ return stat;
+#else
+ case SDC:
+ stat = 0;
+ /* It is initialized externally, just reads the status.*/
+ if (blkGetDriverState(&SDCD1) != BLK_READY)
+ stat |= STA_NOINIT;
+ if (sdcIsWriteProtected(&SDCD1))
+ stat |= STA_PROTECT;
+ return stat;
+#endif
+ }
+ return STA_NODISK;
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Return Disk Status */
+
+DSTATUS disk_status (
+ BYTE drv /* Physical drive nmuber (0..) */
+)
+{
+ DSTATUS stat;
+
+ switch (drv) {
+#if HAL_USE_MMC_SPI
+ case MMC:
+ stat = 0;
+ /* It is initialized externally, just reads the status.*/
+ if (blkGetDriverState(&MMCD1) != BLK_READY)
+ stat |= STA_NOINIT;
+ if (mmcIsWriteProtected(&MMCD1))
+ stat |= STA_PROTECT;
+ return stat;
+#else
+ case SDC:
+ stat = 0;
+ /* It is initialized externally, just reads the status.*/
+ if (blkGetDriverState(&SDCD1) != BLK_READY)
+ stat |= STA_NOINIT;
+ if (sdcIsWriteProtected(&SDCD1))
+ stat |= STA_PROTECT;
+ return stat;
+#endif
+ }
+ return STA_NODISK;
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Read Sector(s) */
+
+DRESULT disk_read (
+ BYTE drv, /* Physical drive nmuber (0..) */
+ BYTE *buff, /* Data buffer to store read data */
+ DWORD sector, /* Sector address (LBA) */
+ BYTE count /* Number of sectors to read (1..255) */
+)
+{
+ switch (drv) {
+#if HAL_USE_MMC_SPI
+ case MMC:
+ if (blkGetDriverState(&MMCD1) != BLK_READY)
+ return RES_NOTRDY;
+ if (mmcStartSequentialRead(&MMCD1, sector))
+ return RES_ERROR;
+ while (count > 0) {
+ if (mmcSequentialRead(&MMCD1, buff))
+ return RES_ERROR;
+ buff += MMCSD_BLOCK_SIZE;
+ count--;
+ }
+ if (mmcStopSequentialRead(&MMCD1))
+ return RES_ERROR;
+ return RES_OK;
+#else
+ case SDC:
+ if (blkGetDriverState(&SDCD1) != BLK_READY)
+ return RES_NOTRDY;
+ if (sdcRead(&SDCD1, sector, buff, count))
+ return RES_ERROR;
+ return RES_OK;
+#endif
+ }
+ return RES_PARERR;
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Write Sector(s) */
+
+#if _READONLY == 0
+DRESULT disk_write (
+ BYTE drv, /* Physical drive nmuber (0..) */
+ const BYTE *buff, /* Data to be written */
+ DWORD sector, /* Sector address (LBA) */
+ BYTE count /* Number of sectors to write (1..255) */
+)
+{
+ switch (drv) {
+#if HAL_USE_MMC_SPI
+ case MMC:
+ if (blkGetDriverState(&MMCD1) != BLK_READY)
+ return RES_NOTRDY;
+ if (mmcIsWriteProtected(&MMCD1))
+ return RES_WRPRT;
+ if (mmcStartSequentialWrite(&MMCD1, sector))
+ return RES_ERROR;
+ while (count > 0) {
+ if (mmcSequentialWrite(&MMCD1, buff))
+ return RES_ERROR;
+ buff += MMCSD_BLOCK_SIZE;
+ count--;
+ }
+ if (mmcStopSequentialWrite(&MMCD1))
+ return RES_ERROR;
+ return RES_OK;
+#else
+ case SDC:
+ if (blkGetDriverState(&SDCD1) != BLK_READY)
+ return RES_NOTRDY;
+ if (sdcWrite(&SDCD1, sector, buff, count))
+ return RES_ERROR;
+ return RES_OK;
+#endif
+ }
+ return RES_PARERR;
+}
+#endif /* _READONLY */
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Miscellaneous Functions */
+
+DRESULT disk_ioctl (
+ BYTE drv, /* Physical drive nmuber (0..) */
+ BYTE ctrl, /* Control code */
+ void *buff /* Buffer to send/receive control data */
+)
+{
+ switch (drv) {
+#if HAL_USE_MMC_SPI
+ case MMC:
+ switch (ctrl) {
+ case CTRL_SYNC:
+ return RES_OK;
+ case GET_SECTOR_SIZE:
+ *((WORD *)buff) = MMCSD_BLOCK_SIZE;
+ return RES_OK;
+#if _USE_ERASE
+ case CTRL_ERASE_SECTOR:
+ mmcErase(&MMCD1, *((DWORD *)buff), *((DWORD *)buff + 1));
+ return RES_OK;
+#endif
+ default:
+ return RES_PARERR;
+ }
+#else
+ case SDC:
+ switch (ctrl) {
+ case CTRL_SYNC:
+ return RES_OK;
+ case GET_SECTOR_COUNT:
+ *((DWORD *)buff) = mmcsdGetCardCapacity(&SDCD1);
+ return RES_OK;
+ case GET_SECTOR_SIZE:
+ *((WORD *)buff) = MMCSD_BLOCK_SIZE;
+ return RES_OK;
+ case GET_BLOCK_SIZE:
+ *((DWORD *)buff) = 256; /* 512b blocks in one erase block */
+ return RES_OK;
+#if _USE_ERASE
+ case CTRL_ERASE_SECTOR:
+ sdcErase(&SDCD1, *((DWORD *)buff), *((DWORD *)buff + 1));
+ return RES_OK;
+#endif
+ default:
+ return RES_PARERR;
+ }
+#endif
+ }
+ return RES_PARERR;
+}
+
+DWORD get_fattime(void) {
+#if HAL_USE_RTC
+ return rtcGetTimeFat(&RTCD1);
+#else
+ return ((uint32_t)0 | (1 << 16)) | (1 << 21); /* wrong but valid time */
+#endif
+}
+
+
+
diff --git a/os/various/fatfs_bindings/fatfs_syscall.c b/os/various/fatfs_bindings/fatfs_syscall.c
new file mode 100644
index 000000000..a42cbcffb
--- /dev/null
+++ b/os/various/fatfs_bindings/fatfs_syscall.c
@@ -0,0 +1,84 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*------------------------------------------------------------------------*/
+/* Sample code of OS dependent controls for FatFs R0.08b */
+/* (C)ChaN, 2011 */
+/*------------------------------------------------------------------------*/
+
+#include "ch.h"
+#include "ff.h"
+
+#if _FS_REENTRANT
+/*------------------------------------------------------------------------*/
+/* Static array of Synchronization Objects */
+/*------------------------------------------------------------------------*/
+static Semaphore ff_sem[_VOLUMES];
+
+/*------------------------------------------------------------------------*/
+/* Create a Synchronization Object */
+/*------------------------------------------------------------------------*/
+int ff_cre_syncobj(BYTE vol, _SYNC_t *sobj) {
+
+ *sobj = &ff_sem[vol];
+ chSemInit(*sobj, 1);
+ return TRUE;
+}
+
+/*------------------------------------------------------------------------*/
+/* Delete a Synchronization Object */
+/*------------------------------------------------------------------------*/
+int ff_del_syncobj(_SYNC_t sobj) {
+
+ chSemReset(sobj, 0);
+ return TRUE;
+}
+
+/*------------------------------------------------------------------------*/
+/* Request Grant to Access the Volume */
+/*------------------------------------------------------------------------*/
+int ff_req_grant(_SYNC_t sobj) {
+
+ msg_t msg = chSemWaitTimeout(sobj, (systime_t)_FS_TIMEOUT);
+ return msg == RDY_OK;
+}
+
+/*------------------------------------------------------------------------*/
+/* Release Grant to Access the Volume */
+/*------------------------------------------------------------------------*/
+void ff_rel_grant(_SYNC_t sobj) {
+
+ chSemSignal(sobj);
+}
+#endif /* _FS_REENTRANT */
+
+#if _USE_LFN == 3 /* LFN with a working buffer on the heap */
+/*------------------------------------------------------------------------*/
+/* Allocate a memory block */
+/*------------------------------------------------------------------------*/
+void *ff_memalloc(UINT size) {
+
+ return chHeapAlloc(NULL, size);
+}
+
+/*------------------------------------------------------------------------*/
+/* Free a memory block */
+/*------------------------------------------------------------------------*/
+void ff_memfree(void *mblock) {
+
+ chHeapFree(mblock);
+}
+#endif /* _USE_LFN == 3 */
diff --git a/os/various/fatfs_bindings/readme.txt b/os/various/fatfs_bindings/readme.txt
new file mode 100644
index 000000000..8735cce54
--- /dev/null
+++ b/os/various/fatfs_bindings/readme.txt
@@ -0,0 +1,6 @@
+This directory contains the ChibiOS/RT "official" bindings with the FatFS
+library by ChaN: http://elm-chan.org
+
+In order to use FatFS within ChibiOS/RT project, unzip FatFS under
+./ext/fatfs then include $(CHIBIOS)/os/various/fatfs_bindings/fatfs.mk
+in your makefile.
diff --git a/os/various/lwip_bindings/arch/cc.h b/os/various/lwip_bindings/arch/cc.h
new file mode 100644
index 000000000..87e900272
--- /dev/null
+++ b/os/various/lwip_bindings/arch/cc.h
@@ -0,0 +1,72 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ * **** This file incorporates work covered by the following copyright and ****
+ * **** permission notice: ****
+ *
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#ifndef __CC_H__
+#define __CC_H__
+
+#include <ch.h>
+
+typedef uint8_t u8_t;
+typedef int8_t s8_t;
+typedef uint16_t u16_t;
+typedef int16_t s16_t;
+typedef uint32_t u32_t;
+typedef int32_t s32_t;
+typedef uint32_t mem_ptr_t;
+
+#define LWIP_PLATFORM_DIAG(x)
+#define LWIP_PLATFORM_ASSERT(x) { \
+ chSysHalt(); \
+}
+
+#define BYTE_ORDER LITTLE_ENDIAN
+#define LWIP_PROVIDE_ERRNO
+
+#endif /* __CC_H__ */
diff --git a/os/various/lwip_bindings/arch/perf.h b/os/various/lwip_bindings/arch/perf.h
new file mode 100644
index 000000000..81ef4673b
--- /dev/null
+++ b/os/various/lwip_bindings/arch/perf.h
@@ -0,0 +1,57 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ * **** This file incorporates work covered by the following copyright and ****
+ * **** permission notice: ****
+ *
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#ifndef __PERF_H__
+#define __PERF_H__
+
+#define PERF_START
+#define PERF_STOP(x)
+
+#endif /* __PERF_H__ */
diff --git a/os/various/lwip_bindings/arch/sys_arch.c b/os/various/lwip_bindings/arch/sys_arch.c
new file mode 100644
index 000000000..57ed14124
--- /dev/null
+++ b/os/various/lwip_bindings/arch/sys_arch.c
@@ -0,0 +1,235 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ * **** This file incorporates work covered by the following copyright and ****
+ * **** permission notice: ****
+ *
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+
+// see http://lwip.wikia.com/wiki/Porting_for_an_OS for instructions
+
+#include "ch.h"
+
+#include "lwip/opt.h"
+#include "lwip/mem.h"
+#include "lwip/sys.h"
+#include "lwip/stats.h"
+
+#include "arch/cc.h"
+#include "arch/sys_arch.h"
+
+void sys_init(void) {
+
+}
+
+err_t sys_sem_new(sys_sem_t *sem, u8_t count) {
+
+ *sem = chHeapAlloc(NULL, sizeof(Semaphore));
+ if (*sem == 0) {
+ SYS_STATS_INC(sem.err);
+ return ERR_MEM;
+ }
+ else {
+ chSemInit(*sem, (cnt_t)count);
+ SYS_STATS_INC_USED(sem);
+ return ERR_OK;
+ }
+}
+
+void sys_sem_free(sys_sem_t *sem) {
+
+ chHeapFree(*sem);
+ *sem = SYS_SEM_NULL;
+ SYS_STATS_DEC(sem.used);
+}
+
+void sys_sem_signal(sys_sem_t *sem) {
+
+ chSemSignal(*sem);
+}
+
+/* CHIBIOS FIX: specific variant of this call to be called from within
+ a lock.*/
+void sys_sem_signal_S(sys_sem_t *sem) {
+
+ chSemSignalI(*sem);
+ chSchRescheduleS();
+}
+
+u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) {
+ systime_t time, tmo;
+
+ chSysLock();
+ tmo = timeout > 0 ? (systime_t)timeout : TIME_INFINITE;
+ time = chTimeNow();
+ if (chSemWaitTimeoutS(*sem, tmo) != RDY_OK)
+ time = SYS_ARCH_TIMEOUT;
+ else
+ time = chTimeNow() - time;
+ chSysUnlock();
+ return time;
+}
+
+int sys_sem_valid(sys_sem_t *sem) {
+ return *sem != SYS_SEM_NULL;
+}
+
+// typically called within lwIP after freeing a semaphore
+// to make sure the pointer is not left pointing to invalid data
+void sys_sem_set_invalid(sys_sem_t *sem) {
+ *sem = SYS_SEM_NULL;
+}
+
+err_t sys_mbox_new(sys_mbox_t *mbox, int size) {
+
+ *mbox = chHeapAlloc(NULL, sizeof(Mailbox) + sizeof(msg_t) * size);
+ if (*mbox == 0) {
+ SYS_STATS_INC(mbox.err);
+ return ERR_MEM;
+ }
+ else {
+ chMBInit(*mbox, (void *)(((uint8_t *)*mbox) + sizeof(Mailbox)), size);
+ SYS_STATS_INC(mbox.used);
+ return ERR_OK;
+ }
+}
+
+void sys_mbox_free(sys_mbox_t *mbox) {
+
+ if (chMBGetUsedCountI(*mbox) != 0) {
+ // If there are messages still present in the mailbox when the mailbox
+ // is deallocated, it is an indication of a programming error in lwIP
+ // and the developer should be notified.
+ SYS_STATS_INC(mbox.err);
+ chMBReset(*mbox);
+ }
+ chHeapFree(*mbox);
+ *mbox = SYS_MBOX_NULL;
+ SYS_STATS_DEC(mbox.used);
+}
+
+void sys_mbox_post(sys_mbox_t *mbox, void *msg) {
+
+ chMBPost(*mbox, (msg_t)msg, TIME_INFINITE);
+}
+
+err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) {
+
+ if (chMBPost(*mbox, (msg_t)msg, TIME_IMMEDIATE) == RDY_TIMEOUT) {
+ SYS_STATS_INC(mbox.err);
+ return ERR_MEM;
+ }
+ return ERR_OK;
+}
+
+u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) {
+ systime_t time, tmo;
+
+ chSysLock();
+ tmo = timeout > 0 ? (systime_t)timeout : TIME_INFINITE;
+ time = chTimeNow();
+ if (chMBFetchS(*mbox, (msg_t *)msg, tmo) != RDY_OK)
+ time = SYS_ARCH_TIMEOUT;
+ else
+ time = chTimeNow() - time;
+ chSysUnlock();
+ return time;
+}
+
+u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) {
+
+ if (chMBFetch(*mbox, (msg_t *)msg, TIME_IMMEDIATE) == RDY_TIMEOUT)
+ return SYS_MBOX_EMPTY;
+ return 0;
+}
+
+int sys_mbox_valid(sys_mbox_t *mbox) {
+ return *mbox != SYS_MBOX_NULL;
+}
+
+// typically called within lwIP after freeing an mbox
+// to make sure the pointer is not left pointing to invalid data
+void sys_mbox_set_invalid(sys_mbox_t *mbox) {
+ *mbox = SYS_MBOX_NULL;
+}
+
+sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread,
+ void *arg, int stacksize, int prio) {
+
+ size_t wsz;
+ void *wsp;
+
+ (void)name;
+ wsz = THD_WA_SIZE(stacksize);
+ wsp = chCoreAlloc(wsz);
+ if (wsp == NULL)
+ return NULL;
+ return (sys_thread_t)chThdCreateStatic(wsp, wsz, prio, (tfunc_t)thread, arg);
+}
+
+sys_prot_t sys_arch_protect(void) {
+
+ chSysLock();
+ return 0;
+}
+
+void sys_arch_unprotect(sys_prot_t pval) {
+
+ (void)pval;
+ chSysUnlock();
+}
+
+u32_t sys_now(void) {
+
+#if CH_FREQUENCY == 1000
+ return (u32_t)chTimeNow();
+#elif (CH_FREQUENCY / 1000) >= 1 && (CH_FREQUENCY % 1000) == 0
+ return ((u32_t)chTimeNow() - 1) / (CH_FREQUENCY / 1000) + 1;
+#elif (1000 / CH_FREQUENCY) >= 1 && (1000 % CH_FREQUENCY) == 0
+ return ((u32_t)chTimeNow() - 1) * (1000 / CH_FREQUENCY) + 1;
+#else
+ return (u32_t)(((u64_t)(chTimeNow() - 1) * 1000) / CH_FREQUENCY) + 1;
+#endif
+}
diff --git a/os/various/lwip_bindings/arch/sys_arch.h b/os/various/lwip_bindings/arch/sys_arch.h
new file mode 100644
index 000000000..6c10607f7
--- /dev/null
+++ b/os/various/lwip_bindings/arch/sys_arch.h
@@ -0,0 +1,68 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ * **** This file incorporates work covered by the following copyright and ****
+ * **** permission notice: ****
+ *
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#include <ch.h>
+
+#ifndef __SYS_ARCH_H__
+#define __SYS_ARCH_H__
+
+typedef Semaphore * sys_sem_t;
+typedef Mailbox * sys_mbox_t;
+typedef Thread * sys_thread_t;
+typedef int sys_prot_t;
+
+#define SYS_MBOX_NULL (Mailbox *)0
+#define SYS_THREAD_NULL (Thread *)0
+#define SYS_SEM_NULL (Semaphore *)0
+
+/* let sys.h use binary semaphores for mutexes */
+#define LWIP_COMPAT_MUTEX 1
+
+#endif /* __SYS_ARCH_H__ */
diff --git a/os/various/lwip_bindings/lwip.mk b/os/various/lwip_bindings/lwip.mk
new file mode 100644
index 000000000..afaaf1454
--- /dev/null
+++ b/os/various/lwip_bindings/lwip.mk
@@ -0,0 +1,54 @@
+# List of the required lwIP files.
+LWIP = ${CHIBIOS}/ext/lwip
+
+LWBINDSRC = \
+ $(CHIBIOS)/os/various/lwip_bindings/lwipthread.c \
+ $(CHIBIOS)/os/various/lwip_bindings/arch/sys_arch.c
+
+LWNETIFSRC = \
+ ${LWIP}/src/netif/etharp.c
+
+LWCORESRC = \
+ ${LWIP}/src/core/dhcp.c \
+ ${LWIP}/src/core/dns.c \
+ ${LWIP}/src/core/init.c \
+ ${LWIP}/src/core/mem.c \
+ ${LWIP}/src/core/memp.c \
+ ${LWIP}/src/core/netif.c \
+ ${LWIP}/src/core/pbuf.c \
+ ${LWIP}/src/core/raw.c \
+ ${LWIP}/src/core/stats.c \
+ ${LWIP}/src/core/sys.c \
+ ${LWIP}/src/core/tcp.c \
+ ${LWIP}/src/core/tcp_in.c \
+ ${LWIP}/src/core/tcp_out.c \
+ ${LWIP}/src/core/udp.c
+
+LWIPV4SRC = \
+ ${LWIP}/src/core/ipv4/autoip.c \
+ ${LWIP}/src/core/ipv4/icmp.c \
+ ${LWIP}/src/core/ipv4/igmp.c \
+ ${LWIP}/src/core/ipv4/inet.c \
+ ${LWIP}/src/core/ipv4/inet_chksum.c \
+ ${LWIP}/src/core/ipv4/ip.c \
+ ${LWIP}/src/core/ipv4/ip_addr.c \
+ ${LWIP}/src/core/ipv4/ip_frag.c \
+ ${LWIP}/src/core/def.c \
+ ${LWIP}/src/core/timers.c
+
+LWAPISRC = \
+ ${LWIP}/src/api/api_lib.c \
+ ${LWIP}/src/api/api_msg.c \
+ ${LWIP}/src/api/err.c \
+ ${LWIP}/src/api/netbuf.c \
+ ${LWIP}/src/api/netdb.c \
+ ${LWIP}/src/api/netifapi.c \
+ ${LWIP}/src/api/sockets.c \
+ ${LWIP}/src/api/tcpip.c
+
+LWSRC = $(LWBINDSRC) $(LWNETIFSRC) $(LWCORESRC) $(LWIPV4SRC) $(LWAPISRC)
+
+LWINC = \
+ $(CHIBIOS)/os/various/lwip_bindings \
+ ${LWIP}/src/include \
+ ${LWIP}/src/include/ipv4
diff --git a/os/various/lwip_bindings/lwipthread.c b/os/various/lwip_bindings/lwipthread.c
new file mode 100644
index 000000000..38ef8cfd2
--- /dev/null
+++ b/os/various/lwip_bindings/lwipthread.c
@@ -0,0 +1,303 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ * **** This file incorporates work covered by the following copyright and ****
+ * **** permission notice: ****
+ *
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+
+/**
+ * @file lwipthread.c
+ * @brief LWIP wrapper thread code.
+ * @addtogroup LWIP_THREAD
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "evtimer.h"
+
+#include "lwipthread.h"
+
+#include "lwip/opt.h"
+
+#include "lwip/def.h"
+#include "lwip/mem.h"
+#include "lwip/pbuf.h"
+#include "lwip/sys.h"
+#include <lwip/stats.h>
+#include <lwip/snmp.h>
+#include <lwip/tcpip.h>
+#include "netif/etharp.h"
+#include "netif/ppp_oe.h"
+
+#define PERIODIC_TIMER_ID 1
+#define FRAME_RECEIVED_ID 2
+
+/**
+ * Stack area for the LWIP-MAC thread.
+ */
+WORKING_AREA(wa_lwip_thread, LWIP_THREAD_STACK_SIZE);
+
+/*
+ * Initialization.
+ */
+static void low_level_init(struct netif *netif) {
+ /* set MAC hardware address length */
+ netif->hwaddr_len = ETHARP_HWADDR_LEN;
+
+ /* maximum transfer unit */
+ netif->mtu = 1500;
+
+ /* device capabilities */
+ /* don't set NETIF_FLAG_ETHARP if this device is not an Ethernet one */
+ netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
+
+ /* Do whatever else is needed to initialize interface. */
+}
+
+/*
+ * Transmits a frame.
+ */
+static err_t low_level_output(struct netif *netif, struct pbuf *p) {
+ struct pbuf *q;
+ MACTransmitDescriptor td;
+
+ (void)netif;
+ if (macWaitTransmitDescriptor(&ETHD1, &td, MS2ST(LWIP_SEND_TIMEOUT)) != RDY_OK)
+ return ERR_TIMEOUT;
+
+#if ETH_PAD_SIZE
+ pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
+#endif
+
+ /* Iterates through the pbuf chain. */
+ for(q = p; q != NULL; q = q->next)
+ macWriteTransmitDescriptor(&td, (uint8_t *)q->payload, (size_t)q->len);
+ macReleaseTransmitDescriptor(&td);
+
+#if ETH_PAD_SIZE
+ pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
+#endif
+
+ LINK_STATS_INC(link.xmit);
+
+ return ERR_OK;
+}
+
+/*
+ * Receives a frame.
+ */
+static struct pbuf *low_level_input(struct netif *netif) {
+ MACReceiveDescriptor rd;
+ struct pbuf *p, *q;
+ u16_t len;
+
+ (void)netif;
+ if (macWaitReceiveDescriptor(&ETHD1, &rd, TIME_IMMEDIATE) == RDY_OK) {
+ len = (u16_t)rd.size;
+
+#if ETH_PAD_SIZE
+ len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
+#endif
+
+ /* We allocate a pbuf chain of pbufs from the pool. */
+ p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
+
+ if (p != NULL) {
+
+#if ETH_PAD_SIZE
+ pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
+#endif
+
+ /* Iterates through the pbuf chain. */
+ for(q = p; q != NULL; q = q->next)
+ macReadReceiveDescriptor(&rd, (uint8_t *)q->payload, (size_t)q->len);
+ macReleaseReceiveDescriptor(&rd);
+
+#if ETH_PAD_SIZE
+ pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
+#endif
+
+ LINK_STATS_INC(link.recv);
+ }
+ else {
+ macReleaseReceiveDescriptor(&rd);
+ LINK_STATS_INC(link.memerr);
+ LINK_STATS_INC(link.drop);
+ }
+ return p;
+ }
+ return NULL;
+}
+
+/*
+ * Initialization.
+ */
+static err_t ethernetif_init(struct netif *netif) {
+#if LWIP_NETIF_HOSTNAME
+ /* Initialize interface hostname */
+ netif->hostname = "lwip";
+#endif /* LWIP_NETIF_HOSTNAME */
+
+ /*
+ * Initialize the snmp variables and counters inside the struct netif.
+ * The last argument should be replaced with your link speed, in units
+ * of bits per second.
+ */
+ NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LWIP_LINK_SPEED);
+
+ netif->state = NULL;
+ netif->name[0] = LWIP_IFNAME0;
+ netif->name[1] = LWIP_IFNAME1;
+ /* We directly use etharp_output() here to save a function call.
+ * You can instead declare your own function an call etharp_output()
+ * from it if you have to do some checks before sending (e.g. if link
+ * is available...) */
+ netif->output = etharp_output;
+ netif->linkoutput = low_level_output;
+
+ /* initialize the hardware */
+ low_level_init(netif);
+
+ return ERR_OK;
+}
+
+/**
+ * @brief LWIP handling thread.
+ *
+ * @param[in] p pointer to a @p lwipthread_opts structure or @p NULL
+ * @return The function does not return.
+ */
+msg_t lwip_thread(void *p) {
+ EvTimer evt;
+ EventListener el0, el1;
+ struct ip_addr ip, gateway, netmask;
+ static struct netif thisif;
+ static const MACConfig mac_config = {thisif.hwaddr};
+
+ chRegSetThreadName("lwipthread");
+
+ /* Initializes the thing.*/
+ tcpip_init(NULL, NULL);
+
+ /* TCP/IP parameters, runtime or compile time.*/
+ if (p) {
+ struct lwipthread_opts *opts = p;
+ unsigned i;
+
+ for (i = 0; i < 6; i++)
+ thisif.hwaddr[i] = opts->macaddress[i];
+ ip.addr = opts->address;
+ gateway.addr = opts->gateway;
+ netmask.addr = opts->netmask;
+ }
+ else {
+ thisif.hwaddr[0] = LWIP_ETHADDR_0;
+ thisif.hwaddr[1] = LWIP_ETHADDR_1;
+ thisif.hwaddr[2] = LWIP_ETHADDR_2;
+ thisif.hwaddr[3] = LWIP_ETHADDR_3;
+ thisif.hwaddr[4] = LWIP_ETHADDR_4;
+ thisif.hwaddr[5] = LWIP_ETHADDR_5;
+ LWIP_IPADDR(&ip);
+ LWIP_GATEWAY(&gateway);
+ LWIP_NETMASK(&netmask);
+ }
+ macStart(&ETHD1, &mac_config);
+ netif_add(&thisif, &ip, &netmask, &gateway, NULL, ethernetif_init, tcpip_input);
+
+ netif_set_default(&thisif);
+ netif_set_up(&thisif);
+
+ /* Setup event sources.*/
+ evtInit(&evt, LWIP_LINK_POLL_INTERVAL);
+ evtStart(&evt);
+ chEvtRegisterMask(&evt.et_es, &el0, PERIODIC_TIMER_ID);
+ chEvtRegisterMask(macGetReceiveEventSource(&ETHD1), &el1, FRAME_RECEIVED_ID);
+ chEvtAddEvents(PERIODIC_TIMER_ID | FRAME_RECEIVED_ID);
+
+ /* Goes to the final priority after initialization.*/
+ chThdSetPriority(LWIP_THREAD_PRIORITY);
+
+ while (TRUE) {
+ eventmask_t mask = chEvtWaitAny(ALL_EVENTS);
+ if (mask & PERIODIC_TIMER_ID) {
+ bool_t current_link_status = macPollLinkStatus(&ETHD1);
+ if (current_link_status != netif_is_link_up(&thisif)) {
+ if (current_link_status)
+ tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_up,
+ &thisif, 0);
+ else
+ tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_down,
+ &thisif, 0);
+ }
+ }
+ if (mask & FRAME_RECEIVED_ID) {
+ struct pbuf *p;
+ while ((p = low_level_input(&thisif)) != NULL) {
+ struct eth_hdr *ethhdr = p->payload;
+ switch (htons(ethhdr->type)) {
+ /* IP or ARP packet? */
+ case ETHTYPE_IP:
+ case ETHTYPE_ARP:
+#if PPPOE_SUPPORT
+ /* PPPoE packet? */
+ case ETHTYPE_PPPOEDISC:
+ case ETHTYPE_PPPOE:
+#endif /* PPPOE_SUPPORT */
+ /* full packet send to tcpip_thread to process */
+ if (thisif.input(p, &thisif) == ERR_OK)
+ break;
+ LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
+ default:
+ pbuf_free(p);
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+/** @} */
diff --git a/os/various/lwip_bindings/lwipthread.h b/os/various/lwip_bindings/lwipthread.h
new file mode 100644
index 000000000..fe4de2870
--- /dev/null
+++ b/os/various/lwip_bindings/lwipthread.h
@@ -0,0 +1,131 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file lwipthread.h
+ * @brief LWIP wrapper thread macros and structures.
+ * @addtogroup LWIP_THREAD
+ * @{
+ */
+
+#ifndef _LWIPTHREAD_H_
+#define _LWIPTHREAD_H_
+
+#include <lwip/opt.h>
+
+/** @brief MAC thread priority.*/
+#ifndef LWIP_THREAD_PRIORITY
+#define LWIP_THREAD_PRIORITY LOWPRIO
+#endif
+
+/** @brief MAC thread stack size. */
+#if !defined(LWIP_THREAD_STACK_SIZE) || defined(__DOXYGEN__)
+#define LWIP_THREAD_STACK_SIZE 512
+#endif
+
+/** @brief Link poll interval. */
+#if !defined(LWIP_LINK_POLL_INTERVAL) || defined(__DOXYGEN__)
+#define LWIP_LINK_POLL_INTERVAL S2ST(5)
+#endif
+
+/** @brief IP Address. */
+#if !defined(LWIP_IPADDR) || defined(__DOXYGEN__)
+#define LWIP_IPADDR(p) IP4_ADDR(p, 192, 168, 1, 20)
+#endif
+
+/** @brief IP Gateway. */
+#if !defined(LWIP_GATEWAY) || defined(__DOXYGEN__)
+#define LWIP_GATEWAY(p) IP4_ADDR(p, 192, 168, 1, 1)
+#endif
+
+/** @brief IP netmask. */
+#if !defined(LWIP_NETMASK) || defined(__DOXYGEN__)
+#define LWIP_NETMASK(p) IP4_ADDR(p, 255, 255, 255, 0)
+#endif
+
+/** @brief Transmission timeout. */
+#if !defined(LWIP_SEND_TIMEOUT) || defined(__DOXYGEN__)
+#define LWIP_SEND_TIMEOUT 50
+#endif
+
+/** @brief Link speed. */
+#if !defined(LWIP_LINK_SPEED) || defined(__DOXYGEN__)
+#define LWIP_LINK_SPEED 100000000
+#endif
+
+/** @brief MAC Address byte 0. */
+#if !defined(LWIP_ETHADDR_0) || defined(__DOXYGEN__)
+#define LWIP_ETHADDR_0 0xC2
+#endif
+
+/** @brief MAC Address byte 1. */
+#if !defined(LWIP_ETHADDR_1) || defined(__DOXYGEN__)
+#define LWIP_ETHADDR_1 0xAF
+#endif
+
+/** @brief MAC Address byte 2. */
+#if !defined(LWIP_ETHADDR_2) || defined(__DOXYGEN__)
+#define LWIP_ETHADDR_2 0x51
+#endif
+
+/** @brief MAC Address byte 3. */
+#if !defined(LWIP_ETHADDR_3) || defined(__DOXYGEN__)
+#define LWIP_ETHADDR_3 0x03
+#endif
+
+/** @brief MAC Address byte 4. */
+#if !defined(LWIP_ETHADDR_4) || defined(__DOXYGEN__)
+#define LWIP_ETHADDR_4 0xCF
+#endif
+
+/** @brief MAC Address byte 5. */
+#if !defined(LWIP_ETHADDR_5) || defined(__DOXYGEN__)
+#define LWIP_ETHADDR_5 0x46
+#endif
+
+/** @brief Interface name byte 0. */
+#if !defined(LWIP_IFNAME0) || defined(__DOXYGEN__)
+#define LWIP_IFNAME0 'm'
+#endif
+
+/** @brief Interface name byte 1. */
+#if !defined(LWIP_IFNAME1) || defined(__DOXYGEN__)
+#define LWIP_IFNAME1 's'
+#endif
+
+/**
+ * @brief Runtime TCP/IP settings.
+ */
+struct lwipthread_opts {
+ uint8_t *macaddress;
+ uint32_t address;
+ uint32_t netmask;
+ uint32_t gateway;
+};
+
+extern WORKING_AREA(wa_lwip_thread, LWIP_THREAD_STACK_SIZE);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ msg_t lwip_thread(void *p);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LWIPTHREAD_H_ */
+
+/** @} */
diff --git a/os/various/lwip_bindings/readme.txt b/os/various/lwip_bindings/readme.txt
new file mode 100644
index 000000000..8a7a89e8c
--- /dev/null
+++ b/os/various/lwip_bindings/readme.txt
@@ -0,0 +1,6 @@
+This directory contains the ChibiOS/RT "official" bindings with the lwIP
+TCP/IP stack: http://savannah.nongnu.org/projects/lwip
+
+In order to use FatFS within ChibiOS/RT project, unzip FatFS under
+./ext/lwip-1.4.0 then include $(CHIBIOS)/os/various/lwip_bindings/lwip.mk
+in your makefile.
diff --git a/os/various/memstreams.c b/os/various/memstreams.c
new file mode 100644
index 000000000..11dd5b8ac
--- /dev/null
+++ b/os/various/memstreams.c
@@ -0,0 +1,113 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file memstreams.c
+ * @brief Memory streams code.
+ *
+ * @addtogroup memory_streams
+ * @{
+ */
+
+#include <string.h>
+
+#include "ch.h"
+#include "memstreams.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static size_t writes(void *ip, const uint8_t *bp, size_t n) {
+ MemoryStream *msp = ip;
+
+ if (msp->size - msp->eos < n)
+ n = msp->size - msp->eos;
+ memcpy(msp->buffer + msp->eos, bp, n);
+ msp->eos += n;
+ return n;
+}
+
+static size_t reads(void *ip, uint8_t *bp, size_t n) {
+ MemoryStream *msp = ip;
+
+ if (msp->eos - msp->offset < n)
+ n = msp->eos - msp->offset;
+ memcpy(bp, msp->buffer + msp->offset, n);
+ msp->offset += n;
+ return n;
+}
+
+static msg_t put(void *ip, uint8_t b) {
+ MemoryStream *msp = ip;
+
+ if (msp->size - msp->eos <= 0)
+ return RDY_RESET;
+ *(msp->buffer + msp->eos) = b;
+ msp->eos += 1;
+ return RDY_OK;
+}
+
+static msg_t get(void *ip) {
+ uint8_t b;
+ MemoryStream *msp = ip;
+
+ if (msp->eos - msp->offset <= 0)
+ return RDY_RESET;
+ b = *(msp->buffer + msp->offset);
+ msp->offset += 1;
+ return b;
+}
+
+static const struct MemStreamVMT vmt = {writes, reads, put, get};
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Memory stream object initialization.
+ *
+ * @param[out] msp pointer to the @p MemoryStream object to be initialized
+ * @param[in] buffer pointer to the memory buffer for the memory stream
+ * @param[in] size total size of the memory stream buffer
+ * @param[in] eos initial End Of Stream offset. Normally you need to
+ * put this to zero for RAM buffers or equal to @p size
+ * for ROM streams.
+ */
+void msObjectInit(MemoryStream *msp, uint8_t *buffer,
+ size_t size, size_t eos) {
+
+ msp->vmt = &vmt;
+ msp->buffer = buffer;
+ msp->size = size;
+ msp->eos = eos;
+ msp->offset = 0;
+}
+
+/** @} */
diff --git a/os/various/memstreams.h b/os/various/memstreams.h
new file mode 100644
index 000000000..3daa8ee92
--- /dev/null
+++ b/os/various/memstreams.h
@@ -0,0 +1,94 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file memstreams.h
+ * @brief Memory streams structures and macros.
+
+ * @addtogroup memory_streams
+ * @{
+ */
+
+#ifndef _MEMSTREAMS_H_
+#define _MEMSTREAMS_H_
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief @p RamStream specific data.
+ */
+#define _memory_stream_data \
+ _base_sequential_stream_data \
+ /* Pointer to the stream buffer.*/ \
+ uint8_t *buffer; \
+ /* Size of the stream.*/ \
+ size_t size; \
+ /* Current end of stream.*/ \
+ size_t eos; \
+ /* Current read offset.*/ \
+ size_t offset;
+
+/**
+ * @brief @p MemStream virtual methods table.
+ */
+struct MemStreamVMT {
+ _base_sequential_stream_methods
+};
+
+/**
+ * @extends BaseSequentialStream
+ *
+ * @brief Memory stream object.
+ */
+typedef struct {
+ /** @brief Virtual Methods Table.*/
+ const struct MemStreamVMT *vmt;
+ _memory_stream_data
+} MemoryStream;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void msObjectInit(MemoryStream *msp, uint8_t *buffer, size_t size, size_t eos);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MEMSTREAMS_H_ */
+
+/** @} */
diff --git a/os/various/shell.c b/os/various/shell.c
new file mode 100644
index 000000000..abdfc0b86
--- /dev/null
+++ b/os/various/shell.c
@@ -0,0 +1,286 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file shell.c
+ * @brief Simple CLI shell code.
+ *
+ * @addtogroup SHELL
+ * @{
+ */
+
+#include <string.h>
+
+#include "ch.h"
+#include "hal.h"
+#include "shell.h"
+#include "chprintf.h"
+
+/**
+ * @brief Shell termination event source.
+ */
+EventSource shell_terminated;
+
+static char *_strtok(char *str, const char *delim, char **saveptr) {
+ char *token;
+ if (str)
+ *saveptr = str;
+ token = *saveptr;
+
+ if (!token)
+ return NULL;
+
+ token += strspn(token, delim);
+ *saveptr = strpbrk(token, delim);
+ if (*saveptr)
+ *(*saveptr)++ = '\0';
+
+ return *token ? token : NULL;
+}
+
+static void usage(BaseSequentialStream *chp, char *p) {
+
+ chprintf(chp, "Usage: %s\r\n", p);
+}
+
+static void list_commands(BaseSequentialStream *chp, const ShellCommand *scp) {
+
+ while (scp->sc_name != NULL) {
+ chprintf(chp, "%s ", scp->sc_name);
+ scp++;
+ }
+}
+
+static void cmd_info(BaseSequentialStream *chp, int argc, char *argv[]) {
+
+ (void)argv;
+ if (argc > 0) {
+ usage(chp, "info");
+ return;
+ }
+
+ chprintf(chp, "Kernel: %s\r\n", CH_KERNEL_VERSION);
+#ifdef CH_COMPILER_NAME
+ chprintf(chp, "Compiler: %s\r\n", CH_COMPILER_NAME);
+#endif
+ chprintf(chp, "Architecture: %s\r\n", CH_ARCHITECTURE_NAME);
+#ifdef CH_CORE_VARIANT_NAME
+ chprintf(chp, "Core Variant: %s\r\n", CH_CORE_VARIANT_NAME);
+#endif
+#ifdef CH_PORT_INFO
+ chprintf(chp, "Port Info: %s\r\n", CH_PORT_INFO);
+#endif
+#ifdef PLATFORM_NAME
+ chprintf(chp, "Platform: %s\r\n", PLATFORM_NAME);
+#endif
+#ifdef BOARD_NAME
+ chprintf(chp, "Board: %s\r\n", BOARD_NAME);
+#endif
+#ifdef __DATE__
+#ifdef __TIME__
+ chprintf(chp, "Build time: %s%s%s\r\n", __DATE__, " - ", __TIME__);
+#endif
+#endif
+}
+
+static void cmd_systime(BaseSequentialStream *chp, int argc, char *argv[]) {
+
+ (void)argv;
+ if (argc > 0) {
+ usage(chp, "systime");
+ return;
+ }
+ chprintf(chp, "%lu\r\n", (unsigned long)chTimeNow());
+}
+
+/**
+ * @brief Array of the default commands.
+ */
+static ShellCommand local_commands[] = {
+ {"info", cmd_info},
+ {"systime", cmd_systime},
+ {NULL, NULL}
+};
+
+static bool_t cmdexec(const ShellCommand *scp, BaseSequentialStream *chp,
+ char *name, int argc, char *argv[]) {
+
+ while (scp->sc_name != NULL) {
+ if (strcasecmp(scp->sc_name, name) == 0) {
+ scp->sc_function(chp, argc, argv);
+ return FALSE;
+ }
+ scp++;
+ }
+ return TRUE;
+}
+
+/**
+ * @brief Shell thread function.
+ *
+ * @param[in] p pointer to a @p BaseSequentialStream object
+ * @return Termination reason.
+ * @retval RDY_OK terminated by command.
+ * @retval RDY_RESET terminated by reset condition on the I/O channel.
+ */
+static msg_t shell_thread(void *p) {
+ int n;
+ msg_t msg = RDY_OK;
+ BaseSequentialStream *chp = ((ShellConfig *)p)->sc_channel;
+ const ShellCommand *scp = ((ShellConfig *)p)->sc_commands;
+ char *lp, *cmd, *tokp, line[SHELL_MAX_LINE_LENGTH];
+ char *args[SHELL_MAX_ARGUMENTS + 1];
+
+ chRegSetThreadName("shell");
+ chprintf(chp, "\r\nChibiOS/RT Shell\r\n");
+ while (TRUE) {
+ chprintf(chp, "ch> ");
+ if (shellGetLine(chp, line, sizeof(line))) {
+ chprintf(chp, "\r\nlogout");
+ break;
+ }
+ lp = _strtok(line, " \t", &tokp);
+ cmd = lp;
+ n = 0;
+ while ((lp = _strtok(NULL, " \t", &tokp)) != NULL) {
+ if (n >= SHELL_MAX_ARGUMENTS) {
+ chprintf(chp, "too many arguments\r\n");
+ cmd = NULL;
+ break;
+ }
+ args[n++] = lp;
+ }
+ args[n] = NULL;
+ if (cmd != NULL) {
+ if (strcasecmp(cmd, "exit") == 0) {
+ if (n > 0) {
+ usage(chp, "exit");
+ continue;
+ }
+ break;
+ }
+ else if (strcasecmp(cmd, "help") == 0) {
+ if (n > 0) {
+ usage(chp, "help");
+ continue;
+ }
+ chprintf(chp, "Commands: help exit ");
+ list_commands(chp, local_commands);
+ if (scp != NULL)
+ list_commands(chp, scp);
+ chprintf(chp, "\r\n");
+ }
+ else if (cmdexec(local_commands, chp, cmd, n, args) &&
+ ((scp == NULL) || cmdexec(scp, chp, cmd, n, args))) {
+ chprintf(chp, "%s", cmd);
+ chprintf(chp, " ?\r\n");
+ }
+ }
+ }
+ /* Atomically broadcasting the event source and terminating the thread,
+ there is not a chSysUnlock() because the thread terminates upon return.*/
+ chSysLock();
+ chEvtBroadcastI(&shell_terminated);
+ chThdExitS(msg);
+ return 0; /* Never executed.*/
+}
+
+/**
+ * @brief Shell manager initialization.
+ */
+void shellInit(void) {
+
+ chEvtInit(&shell_terminated);
+}
+
+/**
+ * @brief Spawns a new shell.
+ * @pre @p CH_USE_MALLOC_HEAP and @p CH_USE_DYNAMIC must be enabled.
+ *
+ * @param[in] scp pointer to a @p ShellConfig object
+ * @param[in] size size of the shell working area to be allocated
+ * @param[in] prio priority level for the new shell
+ * @return A pointer to the shell thread.
+ * @retval NULL thread creation failed because memory allocation.
+ */
+#if CH_USE_HEAP && CH_USE_DYNAMIC
+Thread *shellCreate(const ShellConfig *scp, size_t size, tprio_t prio) {
+
+ return chThdCreateFromHeap(NULL, size, prio, shell_thread, (void *)scp);
+}
+#endif
+
+/**
+ * @brief Create statically allocated shell thread.
+ *
+ * @param[in] scp pointer to a @p ShellConfig object
+ * @param[in] wsp pointer to a working area dedicated to the shell thread stack
+ * @param[in] size size of the shell working area
+ * @param[in] prio priority level for the new shell
+ * @return A pointer to the shell thread.
+ */
+Thread *shellCreateStatic(const ShellConfig *scp, void *wsp,
+ size_t size, tprio_t prio) {
+
+ return chThdCreateStatic(wsp, size, prio, shell_thread, (void *)scp);
+}
+
+/**
+ * @brief Reads a whole line from the input channel.
+ *
+ * @param[in] chp pointer to a @p BaseSequentialStream object
+ * @param[in] line pointer to the line buffer
+ * @param[in] size buffer maximum length
+ * @return The operation status.
+ * @retval TRUE the channel was reset or CTRL-D pressed.
+ * @retval FALSE operation successful.
+ */
+bool_t shellGetLine(BaseSequentialStream *chp, char *line, unsigned size) {
+ char *p = line;
+
+ while (TRUE) {
+ char c;
+
+ if (chSequentialStreamRead(chp, (uint8_t *)&c, 1) == 0)
+ return TRUE;
+ if (c == 4) {
+ chprintf(chp, "^D");
+ return TRUE;
+ }
+ if (c == 8) {
+ if (p != line) {
+ chSequentialStreamPut(chp, c);
+ chSequentialStreamPut(chp, 0x20);
+ chSequentialStreamPut(chp, c);
+ p--;
+ }
+ continue;
+ }
+ if (c == '\r') {
+ chprintf(chp, "\r\n");
+ *p = 0;
+ return FALSE;
+ }
+ if (c < 0x20)
+ continue;
+ if (p < line + size - 1) {
+ chSequentialStreamPut(chp, c);
+ *p++ = (char)c;
+ }
+ }
+}
+
+/** @} */
diff --git a/os/various/shell.h b/os/various/shell.h
new file mode 100644
index 000000000..384a6a200
--- /dev/null
+++ b/os/various/shell.h
@@ -0,0 +1,83 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file shell.h
+ * @brief Simple CLI shell header.
+ *
+ * @addtogroup SHELL
+ * @{
+ */
+
+#ifndef _SHELL_H_
+#define _SHELL_H_
+
+/**
+ * @brief Shell maximum input line length.
+ */
+#if !defined(SHELL_MAX_LINE_LENGTH) || defined(__DOXYGEN__)
+#define SHELL_MAX_LINE_LENGTH 64
+#endif
+
+/**
+ * @brief Shell maximum arguments per command.
+ */
+#if !defined(SHELL_MAX_ARGUMENTS) || defined(__DOXYGEN__)
+#define SHELL_MAX_ARGUMENTS 4
+#endif
+
+/**
+ * @brief Command handler function type.
+ */
+typedef void (*shellcmd_t)(BaseSequentialStream *chp, int argc, char *argv[]);
+
+/**
+ * @brief Custom command entry type.
+ */
+typedef struct {
+ const char *sc_name; /**< @brief Command name. */
+ shellcmd_t sc_function; /**< @brief Command function. */
+} ShellCommand;
+
+/**
+ * @brief Shell descriptor type.
+ */
+typedef struct {
+ BaseSequentialStream *sc_channel; /**< @brief I/O channel associated
+ to the shell. */
+ const ShellCommand *sc_commands; /**< @brief Shell extra commands
+ table. */
+} ShellConfig;
+
+#if !defined(__DOXYGEN__)
+extern EventSource shell_terminated;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void shellInit(void);
+ Thread *shellCreate(const ShellConfig *scp, size_t size, tprio_t prio);
+ Thread *shellCreateStatic(const ShellConfig *scp, void *wsp,
+ size_t size, tprio_t prio);
+ bool_t shellGetLine(BaseSequentialStream *chp, char *line, unsigned size);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SHELL_H_ */
+
+/** @} */
diff --git a/os/various/syscalls.c b/os/various/syscalls.c
new file mode 100644
index 000000000..fd2449b40
--- /dev/null
+++ b/os/various/syscalls.c
@@ -0,0 +1,172 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+* **** This file incorporates work covered by the following copyright and ****
+* **** permission notice: ****
+*
+* Copyright (c) 2009 by Michael Fischer. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* 1. Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* 3. Neither the name of the author nor the names of its contributors may
+* be used to endorse or promote products derived from this software
+* without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+* THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+* SUCH DAMAGE.
+*
+****************************************************************************
+* History:
+*
+* 28.03.09 mifi First Version, based on the original syscall.c from
+* newlib version 1.17.0
+* 17.08.09 gdisirio Modified the file for use under ChibiOS/RT
+* 15.11.09 gdisirio Added read and write handling
+****************************************************************************/
+
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "ch.h"
+#if defined(STDOUT_SD) || defined(STDIN_SD)
+#include "hal.h"
+#endif
+
+/***************************************************************************/
+
+int _read_r(struct _reent *r, int file, char * ptr, int len)
+{
+ (void)r;
+#if defined(STDIN_SD)
+ if (!len || (file != 0)) {
+ __errno_r(r) = EINVAL;
+ return -1;
+ }
+ len = sdRead(&STDIN_SD, (uint8_t *)ptr, (size_t)len);
+ return len;
+#else
+ (void)file;
+ (void)ptr;
+ (void)len;
+ __errno_r(r) = EINVAL;
+ return -1;
+#endif
+}
+
+/***************************************************************************/
+
+int _lseek_r(struct _reent *r, int file, int ptr, int dir)
+{
+ (void)r;
+ (void)file;
+ (void)ptr;
+ (void)dir;
+
+ return 0;
+}
+
+/***************************************************************************/
+
+int _write_r(struct _reent *r, int file, char * ptr, int len)
+{
+ (void)r;
+ (void)file;
+ (void)ptr;
+#if defined(STDOUT_SD)
+ if (file != 1) {
+ __errno_r(r) = EINVAL;
+ return -1;
+ }
+ sdWrite(&STDOUT_SD, (uint8_t *)ptr, (size_t)len);
+#endif
+ return len;
+}
+
+/***************************************************************************/
+
+int _close_r(struct _reent *r, int file)
+{
+ (void)r;
+ (void)file;
+
+ return 0;
+}
+
+/***************************************************************************/
+
+caddr_t _sbrk_r(struct _reent *r, int incr)
+{
+#if CH_USE_MEMCORE
+ void *p;
+
+ chDbgCheck(incr > 0, "_sbrk_r");
+
+ (void)r;
+ p = chCoreAlloc((size_t)incr);
+ if (p == NULL) {
+ __errno_r(r) = ENOMEM;
+ return (caddr_t)-1;
+ }
+ return (caddr_t)p;
+#else
+ __errno_r(r) = ENOMEM;
+ return (caddr_t)-1;
+#endif
+}
+
+/***************************************************************************/
+
+int _fstat_r(struct _reent *r, int file, struct stat * st)
+{
+ (void)r;
+ (void)file;
+
+ memset(st, 0, sizeof(*st));
+ st->st_mode = S_IFCHR;
+ return 0;
+}
+
+/***************************************************************************/
+
+int _isatty_r(struct _reent *r, int fd)
+{
+ (void)r;
+ (void)fd;
+
+ return 1;
+}
+
+/*** EOF ***/
diff --git a/os/various/usb_msc.c b/os/various/usb_msc.c
new file mode 100644
index 000000000..61f4202d3
--- /dev/null
+++ b/os/various/usb_msc.c
@@ -0,0 +1,299 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*-*
+ * @file usb_msc.c
+ * @brief USB Mass Storage Class code.
+ *
+ * @addtogroup USB_MSC
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+
+#include "usb_msc.h"
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/**
+ * @brief Zero-filled constant buffer.
+ */
+static const uint8_t zerobuf[4] = {0, 0, 0, 0};
+
+/**
+ * @brief Answer to the INQUIRY command.
+ */
+static const uint8_t scsi_inquiry_data[] = {
+ 0x00, /* Direct Access Device. */
+ 0x80, /* RMB = 1: Removable Medium. */
+ 0x02, /* ISO, ECMA, ANSI = 2. */
+ 0x00, /* UFI response format. */
+
+ 36 - 4, /* Additional Length. */
+ 0x00,
+ 0x00,
+ 0x00,
+ /* Vendor Identification */
+ 'C', 'h', 'i', 'b', 'i', 'O', 'S', ' ',
+ /* Product Identification */
+ 'S', 'D', ' ', 'F', 'l', 'a', 's', 'h',
+ ' ', 'D', 'i', 's', 'k', ' ', ' ', ' ',
+ /* Product Revision Level */
+ '1', '.', '0', ' '
+};
+
+/**
+ * @brief Generic buffer.
+ */
+uint8_t buf[16];
+
+/*===========================================================================*/
+/* MMC interface code. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* SCSI emulation code. */
+/*===========================================================================*/
+
+static uint8_t scsi_read_format_capacities(uint32_t *nblocks,
+ uint32_t *secsize) {
+
+ *nblocks = 1024;
+ *secsize = 512;
+ return 3; /* No Media.*/
+}
+
+/*===========================================================================*/
+/* Mass Storage Class related code. */
+/*===========================================================================*/
+
+/**
+ * @brief MSC state machine current state.
+ */
+static mscstate_t msc_state;
+
+/**
+ * @brief Received CBW.
+ */
+static msccbw_t CBW;
+
+/**
+ * @brief CSW to be transmitted.
+ */
+static msccsw_t CSW;
+
+/**
+ * @brief MSC state machine initialization.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ */
+static void msc_reset(USBDriver *usbp) {
+
+ msc_state = MSC_IDLE;
+ chSysLockFromIsr();
+ usbStartReceiveI(usbp, MSC_DATA_OUT_EP, (uint8_t *)&CBW, sizeof CBW);
+ chSysUnlockFromIsr();
+}
+
+static void msc_transmit(USBDriver *usbp, const uint8_t *p, size_t n) {
+
+ if (n > CBW.dCBWDataTransferLength)
+ n = CBW.dCBWDataTransferLength;
+ CSW.dCSWDataResidue = CBW.dCBWDataTransferLength - (uint32_t)n;
+ chSysLockFromIsr();
+ usbStartTransmitI(usbp, MSC_DATA_IN_EP, p, n);
+ chSysUnlockFromIsr();
+}
+
+static void msc_sendstatus(USBDriver *usbp) {
+
+ msc_state = MSC_SENDING_CSW;
+ chSysLockFromIsr();
+ usbStartTransmitI(usbp, MSC_DATA_IN_EP, (uint8_t *)&CSW, sizeof CSW);
+ chSysUnlockFromIsr();
+}
+
+static bool_t msc_decode(USBDriver *usbp) {
+ uint32_t nblocks, secsize;
+
+ switch (CBW.CBWCB[0]) {
+ case SCSI_REQUEST_SENSE:
+ break;
+ case SCSI_INQUIRY:
+ msc_transmit(usbp, (uint8_t *)&scsi_inquiry_data,
+ sizeof scsi_inquiry_data);
+ CSW.bCSWStatus = MSC_CSW_STATUS_PASSED;
+ break;
+ case SCSI_READ_FORMAT_CAPACITIES:
+ buf[8] = scsi_read_format_capacities(&nblocks, &secsize);
+ buf[0] = buf[1] = buf[2] = 0;
+ buf[3] = 8;
+ buf[4] = (uint8_t)(nblocks >> 24);
+ buf[5] = (uint8_t)(nblocks >> 16);
+ buf[6] = (uint8_t)(nblocks >> 8);
+ buf[7] = (uint8_t)(nblocks >> 0);
+ buf[9] = (uint8_t)(secsize >> 16);
+ buf[10] = (uint8_t)(secsize >> 8);
+ buf[11] = (uint8_t)(secsize >> 0);
+ msc_transmit(usbp, buf, 12);
+ CSW.bCSWStatus = MSC_CSW_STATUS_PASSED;
+ break;
+ default:
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Default requests hook.
+ * @details The application must use this function as callback for the
+ * messages hook.
+ * The following requests are emulated:
+ * - MSC_GET_MAX_LUN_COMMAND.
+ * - MSC_MASS_STORAGE_RESET_COMMAND.
+ * .
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @return The hook status.
+ * @retval TRUE Message handled internally.
+ * @retval FALSE Message not handled.
+ */
+bool_t mscRequestsHook(USBDriver *usbp) {
+
+ if ((usbp->setup[0] & (USB_RTYPE_TYPE_MASK | USB_RTYPE_RECIPIENT_MASK)) ==
+ (USB_RTYPE_TYPE_CLASS | USB_RTYPE_RECIPIENT_INTERFACE)) {
+ switch (usbp->setup[1]) {
+ case MSC_GET_MAX_LUN_COMMAND:
+ usbSetupTransfer(usbp, (uint8_t *)zerobuf, 1, NULL);
+ return TRUE;
+ case MSC_MASS_STORAGE_RESET_COMMAND:
+ msc_reset(usbp);
+ usbSetupTransfer(usbp, NULL, 0, NULL);
+ return TRUE;
+ default:
+ return FALSE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * @brief Default data transmitted callback.
+ * @details The application must use this function as callback for the IN
+ * data endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ */
+void mscDataTransmitted(USBDriver *usbp, usbep_t ep) {
+
+ switch (msc_state) {
+ case MSC_DATA_IN:
+ CSW.dCSWSignature = MSC_CSW_SIGNATURE;
+ CSW.dCSWTag = CBW.dCBWTag;
+ chSysLockFromIsr();
+ usbStartTransmitI(usbp, ep, (uint8_t *)&CSW, sizeof CSW);
+ chSysUnlockFromIsr();
+ msc_state = MSC_SENDING_CSW;
+ break;
+ case MSC_SENDING_CSW:
+ chSysLockFromIsr();
+ usbStartReceiveI(usbp, MSC_DATA_OUT_EP, (uint8_t *)&CBW, sizeof CBW);
+ chSysUnlockFromIsr();
+ msc_state = MSC_IDLE;
+ break;
+ default:
+ ;
+ }
+}
+
+/**
+ * @brief Default data received callback.
+ * @details The application must use this function as callback for the OUT
+ * data endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ */
+void mscDataReceived(USBDriver *usbp, usbep_t ep) {
+ size_t n;
+
+ n = usbGetReceiveTransactionSizeI(usbp, ep);
+ switch (msc_state) {
+ case MSC_IDLE:
+ if ((n != sizeof(msccbw_t)) || (CBW.dCBWSignature != MSC_CBW_SIGNATURE))
+ goto stall_out; /* 6.6.1 */
+
+ /* Decoding SCSI command.*/
+ if (msc_decode(usbp)) {
+ if (CBW.dCBWDataTransferLength == 0) {
+ CSW.bCSWStatus = MSC_CSW_STATUS_FAILED;
+ CSW.dCSWDataResidue = 0;
+ msc_sendstatus(usbp);
+ return;
+ }
+ goto stall_both;
+ }
+
+ /* Commands with zero transfer length, 5.1.*/
+ if (CBW.dCBWDataTransferLength == 0) {
+ msc_sendstatus(usbp);
+ return;
+ }
+
+ /* Transfer direction.*/
+ if (CBW.bmCBWFlags & 0x80) {
+ /* IN, Device to Host.*/
+ msc_state = MSC_DATA_IN;
+ }
+ else {
+ /* OUT, Host to Device.*/
+ msc_state = MSC_DATA_OUT;
+ }
+ break;
+ case MSC_DATA_OUT:
+ break;
+ default:
+ ;
+ }
+ return;
+stall_out:
+ msc_state = MSC_ERROR;
+ chSysLockFromIsr();
+ usbStallReceiveI(usbp, ep);
+ chSysUnlockFromIsr();
+ return;
+stall_both:
+ msc_state = MSC_ERROR;
+ chSysLockFromIsr();
+ usbStallTransmitI(usbp, ep);
+ usbStallReceiveI(usbp, ep);
+ chSysUnlockFromIsr();
+ return;
+}
+
+/** @} */
diff --git a/os/various/usb_msc.h b/os/various/usb_msc.h
new file mode 100644
index 000000000..5e5a80c1f
--- /dev/null
+++ b/os/various/usb_msc.h
@@ -0,0 +1,163 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*-*
+ * @file usb_msc.h
+ * @brief USB Mass Storage Class header.
+ *
+ * @addtogroup USB_MSC
+ * @{
+ */
+
+#ifndef _USB_MSC_H_
+#define _USB_MSC_H_
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+#define MSC_CBW_SIGNATURE 0x43425355
+#define MSC_CSW_SIGNATURE 0x53425355
+
+#define MSC_GET_MAX_LUN_COMMAND 0xFE
+#define MSC_MASS_STORAGE_RESET_COMMAND 0xFF
+
+#define MSC_CSW_STATUS_PASSED 0
+#define MSC_CSW_STATUS_FAILED 1
+#define MSC_CSW_STATUS_PHASE_ERROR 2
+
+
+#define SCSI_FORMAT_UNIT 0x04
+#define SCSI_INQUIRY 0x12
+#define SCSI_MODE_SELECT6 0x15
+#define SCSI_MODE_SELECT10 0x55
+#define SCSI_MODE_SENSE6 0x1A
+#define SCSI_MODE_SENSE10 0x5A
+#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1E
+#define SCSI_READ6 0x08
+#define SCSI_READ10 0x28
+#define SCSI_READ12 0xA8
+#define SCSI_READ16 0x88
+
+#define SCSI_READ_CAPACITY10 0x25
+#define SCSI_READ_CAPACITY16 0x9E
+
+#define SCSI_REQUEST_SENSE 0x03
+#define SCSI_START_STOP_UNIT 0x1B
+#define SCSI_TEST_UNIT_READY 0x00
+#define SCSI_WRITE6 0x0A
+#define SCSI_WRITE10 0x2A
+#define SCSI_WRITE12 0xAA
+#define SCSI_WRITE16 0x8A
+
+#define SCSI_VERIFY10 0x2F
+#define SCSI_VERIFY12 0xAF
+#define SCSI_VERIFY16 0x8F
+
+#define SCSI_SEND_DIAGNOSTIC 0x1D
+#define SCSI_READ_FORMAT_CAPACITIES 0x23
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Endpoint number for bulk IN.
+ */
+#if !defined(MSC_DATA_IN_EP) || defined(__DOXYGEN__)
+#define MSC_DATA_IN_EP 1
+#endif
+
+/**
+ * @brief Endpoint number for bulk OUT.
+ */
+#if !defined(MSC_DATA_OUT_EP) || defined(__DOXYGEN__)
+#define MSC_DATA_OUT_EP 2
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of the MSC possible states.
+ */
+typedef enum {
+ MSC_IDLE = 0,
+ MSC_DATA_OUT,
+ MSC_DATA_IN,
+ MSC_SENDING_CSW,
+ MSC_ERROR
+} mscstate_t;
+
+/**
+ * @brief CBW structure.
+ */
+struct CBW {
+ uint32_t dCBWSignature;
+ uint32_t dCBWTag;
+ uint32_t dCBWDataTransferLength;
+ uint8_t bmCBWFlags;
+ uint8_t bCBWLUN;
+ uint8_t bCBWCBLength;
+ uint8_t CBWCB[16];
+};
+
+/**
+ * @brief CSW structure.
+ */
+struct CSW {
+ uint32_t dCSWSignature;
+ uint32_t dCSWTag;
+ uint32_t dCSWDataResidue;
+ uint8_t bCSWStatus;
+};
+
+/**
+ * @brief Type of a CBW structure.
+ */
+typedef struct CBW msccbw_t;
+
+/**
+ * @brief Type of a CSW structure.
+ */
+typedef struct CSW msccsw_t;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ bool_t mscRequestsHook(USBDriver *usbp);
+ void mscDataTransmitted(USBDriver *usbp, usbep_t ep);
+ void mscDataReceived(USBDriver *usbp, usbep_t ep);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _USB_MSC_H_ */
+
+/** @} */
diff --git a/os/various/various.dox b/os/various/various.dox
new file mode 100644
index 000000000..57c37829c
--- /dev/null
+++ b/os/various/various.dox
@@ -0,0 +1,93 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
+ 2011,2012,2013 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/>.
+*/
+
+/**
+ * @defgroup various Various
+ *
+ * @brief Utilities Library.
+ * @details This is a collection of useful library code that is not part of
+ * the base kernel services.
+ * <h2>Notes</h2>
+ * The library code does not follow the same naming convention of the
+ * system APIs in order to make very clear that it is not "core" code.<br>
+ * The main difference is that library code is not formally tested in the
+ * test suite but through usage in the various demo applications.
+ */
+
+/**
+ * @defgroup cpp_library C++ Wrapper
+ *
+ * @brief C++ wrapper module.
+ * @details This module allows to use the ChibiOS/RT functionalities
+ * from C++ as classes and objects rather the traditional "C" APIs.
+ *
+ * @ingroup various
+ */
+
+/**
+ * @defgroup memory_streams Memory Streams
+ *
+ * @brief Memory Streams.
+ * @details This module allows to use a memory area (RAM or ROM) using a
+ * @ref data_streams interface.
+ *
+ * @ingroup various
+ */
+
+/**
+ * @defgroup event_timer Periodic Events Timer
+ *
+ * @brief Periodic Event Timer.
+ * @details This timer generates an event at regular intervals. The
+ * listening threads can use the event to perform time related
+ * activities. Multiple threads can listen to the same timer.
+ *
+ * @ingroup various
+ */
+
+/**
+ * @defgroup SHELL Command Shell
+ *
+ * @brief Small extendible command line shell.
+ * @details This module implements a generic extendible command line interface.
+ * The CLI just requires an I/O channel (@p BaseChannel), more
+ * commands can be added to the shell using the configuration
+ * structure.
+ *
+ * @ingroup various
+ */
+
+/**
+ * @defgroup chrtclib RTC time conversion utilities
+ *
+ * @brief RTC time conversion utilities.
+ *
+ * @ingroup various
+ */
+
+/**
+ * @defgroup chprintf System formatted print
+ *
+ * @brief System formatted print service.
+ * @details This module implements printf()-like function able to send data
+ * to any module implementing a @p BaseSequentialStream interface.
+ *
+ * @ingroup various
+ */