aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal/src/can.c
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2009-11-28 12:25:35 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2009-11-28 12:25:35 +0000
commit16178e1c45a76544d34ce63db37932838353637c (patch)
treeb5dbcc988f6d518819b9182f60b8ae6f81bbf61b /os/hal/src/can.c
parent9b10a6c67a38fa040eb62e63190aed0880ead8ec (diff)
downloadChibiOS-16178e1c45a76544d34ce63db37932838353637c.tar.gz
ChibiOS-16178e1c45a76544d34ce63db37932838353637c.tar.bz2
ChibiOS-16178e1c45a76544d34ce63db37932838353637c.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1333 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal/src/can.c')
-rw-r--r--os/hal/src/can.c224
1 files changed, 224 insertions, 0 deletions
diff --git a/os/hal/src/can.c b/os/hal/src/can.c
new file mode 100644
index 000000000..bb3e0d1a5
--- /dev/null
+++ b/os/hal/src/can.c
@@ -0,0 +1,224 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file CAN.c
+ * @brief CAN Driver code.
+ * @addtogroup CAN
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+
+#if CH_HAL_USE_CAN
+
+/**
+ * @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, 0);
+ chSemInit(&canp->can_rxsem, 0);
+ 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[in] canp pointer to the @p CANDriver object
+ * @param[in] cfp 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[in] canp pointer to the @p CANDriver object
+ * @param[out] cfp 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[in] canp 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[in] canp 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 */
+
+#endif /* CH_HAL_USE_CAN */
+
+/** @} */