diff --git a/os/io/can.c b/os/io/can.c
new file mode 100644
index 000000000..3dd0c99c3
--- /dev/null
+++ b/os/io/can.c
@@ -0,0 +1,220 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file CAN.c
+ * @brief CAN Driver code.
+ * @addtogroup CAN
+ * @{
+ */
+
+#include
+#include
+
+/**
+ * @brief CAN Driver initialization.
+ */
+void canInit(void) {
+
+ can_lld_init();
+}
+
+/**
+ * @brief Initializes the standard part of a @p CANDriver structure.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ */
+void canObjectInit(CANDriver *canp) {
+
+ canp->can_state = CAN_STOP;
+ canp->can_config = NULL;
+ chSemInit(&canp->can_txsem);
+ chSemInit(&canp->can_rxsem);
+ chEvtInit(&canp->can_rxfull_event);
+ chEvtInit(&canp->can_txempty_event);
+#if CAN_USE_SLEEP_MODE
+ chEvtInit(&canp->can_sleep_event);
+ chEvtInit(&canp->can_wakeup_event);
+#endif /* CAN_USE_SLEEP_MODE */
+}
+
+/**
+ * @brief Configures and activates the CAN peripheral.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ * @param[in] config pointer to the @p CANConfig object
+ */
+void canStart(CANDriver *canp, const CANConfig *config) {
+
+ chDbgCheck((canp != NULL) && (config != NULL), "canStart");
+
+ chSysLock();
+ chDbgAssert((canp->can_state == CAN_STOP) || (canp->can_state == CAN_READY),
+ "canStart(), #1",
+ "invalid state");
+ canp->can_config = config;
+ can_lld_start(canp);
+ canp->can_state = CAN_READY;
+ chSysUnlock();
+}
+
+/**
+ * @brief Deactivates the CAN peripheral.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ */
+void canStop(CANDriver *canp) {
+
+ chDbgCheck(canp != NULL, "canStop");
+
+ chSysLock();
+ chDbgAssert((canp->can_state == CAN_STOP) || (canp->can_state == CAN_READY),
+ "canStop(), #1",
+ "invalid state");
+ can_lld_stop(canp);
+ canp->can_state = CAN_STOP;
+ chSysUnlock();
+}
+
+/**
+ * @brief Can frame transmission.
+ * @details The specified frame is queued for transmission, if the hardware
+ * queue is full then the invoking thread is queued.
+ * @note Trying to transmit while in sleep mode simply enqueues the thread.
+ *
+ * @param canp[in] pointer to the @p CANDriver object
+ * @param cfp[in] pointer to the CAN frame to be transmitted
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation result.
+ * @retval RDY_OK the frame has been queued for transmission.
+ * @retval RDY_TIMEOUT operation not finished within the specified time.
+ * @retval RDY_RESET driver stopped while waiting.
+ */
+msg_t canTransmit(CANDriver *canp, const CANFrame *cfp, systime_t timeout) {
+ msg_t msg;
+
+ chDbgCheck((canp != NULL) && (cfp != NULL), "canTransmit");
+
+ chSysLock();
+ chDbgAssert((canp->can_state == CAN_READY) || (canp->can_state == CAN_SLEEP),
+ "canTransmit(), #1",
+ "invalid state");
+ if ((canp->can_state == CAN_SLEEP) || !can_lld_can_transmit(canp)) {
+ msg = chSemWaitTimeoutS(&canp->can_txsem, timeout);
+ if (msg != RDY_OK) {
+ chSysUnlock();
+ return msg;
+ }
+ }
+ msg = can_lld_transmit(canp, cfp);
+ chSysUnlock();
+ return msg;
+}
+
+/**
+ * @brief Can frame receive.
+ * @details The function waits until a frame is received.
+ * @note Trying to receive while in sleep mode simply enqueues the thread.
+ *
+ * @param canp[in] pointer to the @p CANDriver object
+ * @param cfp[out] pointer to the buffer where the CAN frame is copied
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation result.
+ * @retval RDY_OK a frame has been received and placed in the buffer.
+ * @retval RDY_TIMEOUT operation not finished within the specified time.
+ * @retval RDY_RESET driver stopped while waiting.
+ */
+msg_t canReceive(CANDriver *canp, CANFrame *cfp, systime_t timeout) {
+ msg_t msg;
+
+ chDbgCheck((canp != NULL) && (cfp != NULL), "canReceive");
+
+ chSysLock();
+ chDbgAssert((canp->can_state == CAN_READY) || (canp->can_state == CAN_SLEEP),
+ "canReceive(), #1",
+ "invalid state");
+ if ((canp->can_state == CAN_SLEEP) || !can_lld_can_receive(canp)) {
+ msg = chSemWaitTimeoutS(&canp->can_rxsem, timeout);
+ if (msg != RDY_OK) {
+ chSysUnlock();
+ return msg;
+ }
+ }
+ msg = can_lld_receive(canp, cfp);
+ chSysUnlock();
+ return msg;
+}
+
+#if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__)
+/**
+ * @brief Enters the sleep mode.
+ *
+ * @param canp[in] pointer to the @p CANDriver object
+ */
+void canSleep(CANDriver *canp) {
+
+ chDbgCheck(canp != NULL, "canSleep");
+
+ chSysLock();
+ chDbgAssert((canp->can_state == CAN_READY) || (canp->can_state == CAN_SLEEP),
+ "canSleep(), #1",
+ "invalid state");
+ if (canp->can_state = CAN_READY) {
+ can_lld_sleep(canp);
+ canp->can_state = CAN_SLEEP;
+ chEvtBroadcastI(&canp->can_sleep_event);
+ chSchRescheduleS();
+ }
+ chSysUnlock();
+}
+
+/**
+ * @brief Enforces leaving the sleep mode.
+ * @note The sleep mode is supposed to be usually exited automatically by an
+ * hardware event.
+ *
+ * @param canp[in] pointer to the @p CANDriver object
+ */
+void canWakeup(CANDriver *canp) {
+
+ chDbgCheck(canp != NULL, "canWakeup");
+
+ chSysLock();
+ chDbgAssert((canp->can_state == CAN_READY) || (canp->can_state == CAN_SLEEP),
+ "canWakeup(), #1",
+ "invalid state");
+ if (canp->can_state = CAN_SLEEP) {
+ can_lld_wakeup(canp);
+ canp->can_state = CAN_READY;
+ chEvtBroadcastI(&canp->can_wakeup_event);
+ chSchRescheduleS();
+ }
+ chSysUnlock();
+}
+#endif /* CAN_USE_SLEEP_MODE */
+
+/** @} */
diff --git a/os/io/can.h b/os/io/can.h
new file mode 100644
index 000000000..9d9462f86
--- /dev/null
+++ b/os/io/can.h
@@ -0,0 +1,61 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file can.h
+ * @brief CAN Driver macros and structures.
+ * @addtogroup CAN
+ * @{
+ */
+
+#ifndef _CAN_H_
+#define _CAN_H_
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ CAN_UNINIT = 0, /**< @brief Not initialized. */
+ CAN_STOP = 1, /**< @brief Stopped. */
+ CAN_READY = 2, /**< @brief Ready. */
+ CAN_SLEEP = 3 /**< @brief Sleep state. */
+} canstate_t;
+
+#include "can_lld.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void canInit(void);
+ void canObjectInit(CANDriver *canp);
+ void canStart(CANDriver *canp, const CANConfig *config);
+ void canStop(CANDriver *canp);
+ msg_t canTransmit(CANDriver *canp, const CANFrame *cfp, systime_t timeout);
+ msg_t canReceive(CANDriver *canp, CANFrame *cfp, systime_t timeout);
+#if CAN_USE_SLEEP_MODE
+ void canSleep(CANDriver *canp);
+ void canWakeup(CANDriver *canp);
+#endif /* CAN_USE_SLEEP_MODE */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CAN_H_ */
+
+/** @} */
diff --git a/os/io/templates/can_lld.c b/os/io/templates/can_lld.c
new file mode 100644
index 000000000..4fc0ae7d0
--- /dev/null
+++ b/os/io/templates/can_lld.c
@@ -0,0 +1,155 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file templates/can_lld.c
+ * @brief CAN Driver subsystem low level driver source template
+ * @addtogroup CAN_LLD
+ * @{
+ */
+
+#include
+#include
+
+/*===========================================================================*/
+/* Low Level Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Low Level Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Low Level Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Low Level Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Low Level Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level CAN driver initialization.
+ */
+void can_lld_init(void) {
+
+}
+
+/**
+ * @brief Configures and activates the CAN peripheral.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ */
+void can_lld_start(CANDriver *canp) {
+
+ if (canp->can_state == CAN_STOP) {
+ /* Clock activation.*/
+ }
+ /* Configuration.*/
+}
+
+/**
+ * @brief Deactivates the CAN peripheral.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ */
+void can_lld_stop(CANDriver *canp) {
+
+}
+
+/**
+ * @brief Determines whether a frame can be transmitted.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ *
+ * @return The queue space availability.
+ * @retval FALSE no space in the transmit queue.
+ * @retval TRUE transmit slot available.
+ */
+bool_t can_lld_can_transmit(CANDriver *canp) {
+
+ return false;
+}
+
+/**
+ * @brief Inserts a frame into the transmit queue.
+ *
+ * @param canp[in] pointer to the @p CANDriver object
+ * @param cfp[in] pointer to the CAN frame to be transmitted
+ *
+ * @return The operation status.
+ * @retval RDY_OK frame transmitted.
+ */
+msg_t can_lld_transmit(CANDriver *canp, const CANFrame *cfp) {
+
+ return RDY_OK;
+}
+
+/**
+ * @brief Determines whether a frame has been received.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ *
+ * @return The queue space availability.
+ * @retval FALSE no space in the transmit queue.
+ * @retval TRUE transmit slot available.
+ */
+bool_t can_lld_can_receive(CANDriver *canp) {
+
+ return false;
+}
+
+/**
+ * @brief Receives a frame from the input queue.
+ *
+ * @param canp[in] pointer to the @p CANDriver object
+ * @param cfp[out] pointer to the buffer where the CAN frame is copied
+ *
+ * @return The operation status.
+ * @retval RDY_OK frame received.
+ */
+msg_t can_lld_receive(CANDriver *canp, CANFrame *cfp) {
+
+ return RDY_OK;
+}
+
+#if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__)
+/**
+ * @brief Enters the sleep mode.
+ *
+ * @param canp[in] pointer to the @p CANDriver object
+ */
+void can_lld_sleep(CANDriver *canp) {
+
+}
+
+/**
+ * @brief Enforces leaving the sleep mode.
+ *
+ * @param canp[in] pointer to the @p CANDriver object
+ */
+void can_lld_wakeup(CANDriver *canp) {
+
+}
+#endif /* CAN_USE_SLEEP_MODE */
+
+/** @} */
diff --git a/os/io/templates/can_lld.h b/os/io/templates/can_lld.h
new file mode 100644
index 000000000..fcd8631a9
--- /dev/null
+++ b/os/io/templates/can_lld.h
@@ -0,0 +1,134 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file templates/can_lld.h
+ * @brief CAN Driver subsystem low level driver header template
+ * @addtogroup CAN_LLD
+ * @{
+ */
+
+#ifndef _CAN_LLD_H_
+#define _CAN_LLD_H_
+
+/**
+ * @brief This switch defines whether the driver implementation supports
+ * a low power switch mode with automatic an wakeup feature.
+ */
+#define CAN_SUPPORTS_SLEEP TRUE
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Sleep mode related APIs inclusion switch.
+ * @note This switch is enforced to @p FALSE if the driver implementation
+ * does not support the sleep mode.
+ */
+#if CAN_SUPPORTS_SLEEP || defined(__DOXYGEN__)
+#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
+#define CAN_USE_SLEEP_MODE TRUE
+#endif
+#else /* !CAN_SUPPORTS_SLEEP */
+#define CAN_USE_SLEEP_MODE FALSE
+#endif /* !CAN_SUPPORTS_SLEEP */
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Driver configuration structure.
+ * @note It could be empty on some architectures.
+ */
+typedef struct {
+
+} CANConfig;
+
+/**
+ * @brief Structure representing an CAN driver.
+ */
+typedef struct {
+ /**
+ * @brief Driver state.
+ */
+ canstate_t can_state;
+ /**
+ * @brief Current configuration data.
+ */
+ const CANConfig *can_config;
+ /**
+ * @brief Transmission queue semaphore.
+ */
+ Semaphore can_txsem;
+ /**
+ * @brief Receive queue semaphore.
+ */
+ Semaphore can_rxsem;
+ /**
+ * @brief One or more frames become available.
+ */
+ EventSource can_rxfull_event;
+ /**
+ * @brief One or more transmission slots become available.
+ */
+ EventSource can_txempty_event;
+#if CAN_USE_SLEEP_MODE || defined __DOXYGEN__)
+ /**
+ * @brief Entering sleep state event.
+ */
+ EventSource can_sleep_event;
+ /**
+ * @brief Exiting sleep state event.
+ */
+ EventSource can_wakeup_event;
+#endif /* CAN_USE_SLEEP_MODE */
+ /* End of the mandatory fields.*/
+} CANDriver;
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void can_lld_init(void);
+ void can_lld_start(CANDriver *canp);
+ void can_lld_stop(CANDriver *canp);
+ bool_t can_lld_can_transmit(CANDriver *canp);
+ msg_t can_lld_transmit(CANDriver *canp, const CANFrame *cfp);
+ bool_t can_lld_can_receive(CANDriver *canp);
+ msg_t can_lld_receive(CANDriver *canp, CANFrame *cfp);
+#if CAN_USE_SLEEP_MODE
+ void can_lld_sleep(CANDriver *canp);
+ void can_lld_wakeup(CANDriver *canp);
+#endif /* CAN_USE_SLEEP_MODE */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CAN_LLD_H_ */
+
+/** @} */