ChibiOS/RT 2.6.9 CAN Driver

Detailed Description

Generic CAN Driver.

This module implements a generic CAN (Controller Area Network) driver allowing the exchange of information at frame level.

Precondition:
In order to use the CAN driver the HAL_USE_CAN option must be enabled in halconf.h.

Driver State Machine

The driver implements a state machine internally, not all the driver functionalities can be used in any moment,

any transition not explicitly shown in the following diagram has to be considered an error and shall be captured by an assertion (if enabled).

00001 /*
00002     ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
00003
00004     Licensed under the Apache License, Version 2.0 (the "License");
00005     you may not use this file except in compliance with the License.
00006     You may obtain a copy of the License at
00007
00008         http://www.apache.org/licenses/LICENSE-2.0
00009
00010     Unless required by applicable law or agreed to in writing, software
00011     distributed under the License is distributed on an "AS IS" BASIS,
00012     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013     See the License for the specific language governing permissions and
00014     limitations under the License.
00015 */
00016
00017 /**
00018  * @file    templates/can_lld.h
00019  * @brief   CAN Driver subsystem low level driver header template.
00020  *
00021  * @addtogroup CAN
00022  * @{
00023  */
00024
00025 #ifndef _CAN_LLD_H_
00026 #define _CAN_LLD_H_
00027
00028 #if HAL_USE_CAN || defined(__DOXYGEN__)
00029
00030 /*===========================================================================*/
00031 /* Driver constants.                                                         */
00032 /*===========================================================================*/
00033
00034 /**
00035  * @brief   This switch defines whether the driver implementation supports
00036  *          a low power switch mode with automatic an wakeup feature.
00037  */
00038 #define CAN_SUPPORTS_SLEEP          TRUE
00039
00040 /**
00041  * @brief   This implementation supports three transmit mailboxes.
00042  */
00043 #define CAN_TX_MAILBOXES            3
00044
00045 /**
00046  * @brief   This implementation supports two receive mailboxes.
00047  */
00048 #define CAN_RX_MAILBOXES            2
00049
00050 /*===========================================================================*/
00051 /* Driver pre-compile time settings.                                         */
00052 /*===========================================================================*/
00053
00054 /**
00055  * @name    Configuration options
00056  * @{
00057  */
00058 /**
00059  * @brief   CAN1 driver enable switch.
00060  * @details If set to @p TRUE the support for CAN1 is included.
00061  */
00062 #if !defined(PLATFORM_CAN_USE_CAN1) || defined(__DOXYGEN__)
00063 #define PLATFORM_CAN_USE_CAN1               FALSE
00064 #endif
00065 /** @} */
00066
00067 /*===========================================================================*/
00068 /* Derived constants and error checks.                                       */
00069 /*===========================================================================*/
00070
00071 #if CAN_USE_SLEEP_MODE && !CAN_SUPPORTS_SLEEP
00072 #error "CAN sleep mode not supported in this architecture"
00073 #endif
00074
00075 /*===========================================================================*/
00076 /* Driver data structures and types.                                         */
00077 /*===========================================================================*/
00078
00079 /**
00080  * @brief   Type of a transmission mailbox index.
00081  */
00082 typedef uint32_t canmbx_t;
00083
00084 /**
00085  * @brief   CAN transmission frame.
00086  * @note    Accessing the frame data as word16 or word32 is not portable because
00087  *          machine data endianness, it can be still useful for a quick filling.
00088  */
00089 typedef struct {
00090   struct {
00091     uint8_t                 DLC:4;          /**< @brief Data length.        */
00092     uint8_t                 RTR:1;          /**< @brief Frame type.         */
00093     uint8_t                 IDE:1;          /**< @brief Identifier type.    */
00094   };
00095   union {
00096     struct {
00097       uint32_t              SID:11;         /**< @brief Standard identifier.*/
00098     };
00099     struct {
00100       uint32_t              EID:29;         /**< @brief Extended identifier.*/
00101     };
00102   };
00103   union {
00104     uint8_t                 data8[8];       /**< @brief Frame data.         */
00105     uint16_t                data16[4];      /**< @brief Frame data.         */
00106     uint32_t                data32[2];      /**< @brief Frame data.         */
00107   };
00108 } CANTxFrame;
00109
00110 /**
00111  * @brief   CAN received frame.
00112  * @note    Accessing the frame data as word16 or word32 is not portable because
00113  *          machine data endianness, it can be still useful for a quick filling.
00114  */
00115 typedef struct {
00116   struct {
00117     uint8_t                 DLC:4;          /**< @brief Data length.        */
00118     uint8_t                 RTR:1;          /**< @brief Frame type.         */
00119     uint8_t                 IDE:1;          /**< @brief Identifier type.    */
00120   };
00121   union {
00122     struct {
00123       uint32_t              SID:11;         /**< @brief Standard identifier.*/
00124     };
00125     struct {
00126       uint32_t              EID:29;         /**< @brief Extended identifier.*/
00127     };
00128   };
00129   union {
00130     uint8_t                 data8[8];       /**< @brief Frame data.         */
00131     uint16_t                data16[4];      /**< @brief Frame data.         */
00132     uint32_t                data32[2];      /**< @brief Frame data.         */
00133   };
00134 } CANRxFrame;
00135
00136 /**
00137  * @brief   CAN filter.
00138  * @note    Implementations may extend this structure to contain more,
00139  *          architecture dependent, fields.
00140  * @note    It could not be present on some architectures.
00141  */
00142 typedef struct {
00143   uint32_t                  dummy;
00144 } CANFilter;
00145
00146 /**
00147  * @brief   Driver configuration structure.
00148  * @note    Implementations may extend this structure to contain more,
00149  *          architecture dependent, fields.
00150  * @note    It could be empty on some architectures.
00151  */
00152 typedef struct {
00153   uint32_t                  dummy;
00154 } CANConfig;
00155
00156 /**
00157  * @brief   Structure representing an CAN driver.
00158  */
00159 typedef struct {
00160   /**
00161    * @brief   Driver state.
00162    */
00163   canstate_t                state;
00164   /**
00165    * @brief   Current configuration data.
00166    */
00167   const CANConfig           *config;
00168   /**
00169    * @brief   Transmission queue semaphore.
00170    */
00171   Semaphore                 txsem;
00172   /**
00173    * @brief   Receive queue semaphore.
00174    */
00175   Semaphore                 rxsem;
00176   /**
00177    * @brief   One or more frames become available.
00178    * @note    After broadcasting this event it will not be broadcasted again
00179    *          until the received frames queue has been completely emptied. It
00180    *          is <b>not</b> broadcasted for each received frame. It is
00181    *          responsibility of the application to empty the queue by
00182    *          repeatedly invoking @p chReceive() when listening to this event.
00183    *          This behavior minimizes the interrupt served by the system
00184    *          because CAN traffic.
00185    * @note    The flags associated to the listeners will indicate which
00186    *          receive mailboxes become non-empty.
00187    */
00188   EventSource               rxfull_event;
00189   /**
00190    * @brief   One or more transmission mailbox become available.
00191    * @note    The flags associated to the listeners will indicate which
00192    *          transmit mailboxes become empty.
00193    *
00194    */
00195   EventSource               txempty_event;
00196   /**
00197    * @brief   A CAN bus error happened.
00198    * @note    The flags associated to the listeners will indicate the
00199    *          error(s) that have occurred.
00200    */
00201   EventSource               error_event;
00202 #if CAN_USE_SLEEP_MODE || defined (__DOXYGEN__)
00203   /**
00204    * @brief   Entering sleep state event.
00205    */
00206   EventSource               sleep_event;
00207   /**
00208    * @brief   Exiting sleep state event.
00209    */
00210   EventSource               wakeup_event;
00211 #endif /* CAN_USE_SLEEP_MODE */
00212   /* End of the mandatory fields.*/
00213 } CANDriver;
00214
00215 /*===========================================================================*/
00216 /* Driver macros.                                                            */
00217 /*===========================================================================*/
00218
00219 /*===========================================================================*/
00220 /* External declarations.                                                    */
00221 /*===========================================================================*/
00222
00223 #if PLATFORM_CAN_USE_CAN1 && !defined(__DOXYGEN__)
00224 extern CANDriver CAND1;
00225 #endif
00226
00227 #ifdef __cplusplus
00228 extern "C" {
00229 #endif
00230   void can_lld_init(void);
00231   void can_lld_start(CANDriver *canp);
00232   void can_lld_stop(CANDriver *canp);
00233   bool_t can_lld_is_tx_empty(CANDriver *canp,
00234                              canmbx_t mailbox);
00235   void can_lld_transmit(CANDriver *canp,
00236                         canmbx_t mailbox,
00237                         const CANTxFrame *crfp);
00238   bool_t can_lld_is_rx_nonempty(CANDriver *canp,
00239                                 canmbx_t mailbox);
00240   void can_lld_receive(CANDriver *canp,
00241                        canmbx_t mailbox,
00242                        CANRxFrame *ctfp);
00243 #if CAN_USE_SLEEP_MODE
00244   void can_lld_sleep(CANDriver *canp);
00245   void can_lld_wakeup(CANDriver *canp);
00246 #endif /* CAN_USE_SLEEP_MODE */
00247 #ifdef __cplusplus
00248 }
00249 #endif
00250
00251 #endif /* HAL_USE_CAN */
00252
00253 #endif /* _CAN_LLD_H_ */
00254
00255 /** @} */
00001 /*
00002     ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
00003
00004     Licensed under the Apache License, Version 2.0 (the "License");
00005     you may not use this file except in compliance with the License.
00006     You may obtain a copy of the License at
00007
00008         http://www.apache.org/licenses/LICENSE-2.0
00009
00010     Unless required by applicable law or agreed to in writing, software
00011     distributed under the License is distributed on an "AS IS" BASIS,
00012     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013     See the License for the specific language governing permissions and
00014     limitations under the License.
00015 */
00016
00017 /**
00018  * @file    templates/can_lld.c
00019  * @brief   CAN Driver subsystem low level driver source template.
00020  *
00021  * @addtogroup CAN
00022  * @{
00023  */
00024
00025 #include "ch.h"
00026 #include "hal.h"
00027
00028 #if HAL_USE_CAN || defined(__DOXYGEN__)
00029
00030 /*===========================================================================*/
00031 /* Driver local definitions.                                                 */
00032 /*===========================================================================*/
00033
00034 /*===========================================================================*/
00035 /* Driver exported variables.                                                */
00036 /*===========================================================================*/
00037
00038 /**
00039  * @brief   CAN1 driver identifier.
00040  */
00041 #if PLATFORM_CAN_USE_CAN1 || defined(__DOXYGEN__)
00042 CANDriver CAND1;
00043 #endif
00044
00045 /*===========================================================================*/
00046 /* Driver local variables and types.                                         */
00047 /*===========================================================================*/
00048
00049 /*===========================================================================*/
00050 /* Driver local functions.                                                   */
00051 /*===========================================================================*/
00052
00053 /*===========================================================================*/
00054 /* Driver interrupt handlers.                                                */
00055 /*===========================================================================*/
00056
00057 /*===========================================================================*/
00058 /* Driver exported functions.                                                */
00059 /*===========================================================================*/
00060
00061 /**
00062  * @brief   Low level CAN driver initialization.
00063  *
00064  * @notapi
00065  */
00066 void can_lld_init(void) {
00067
00068 #if PLATFORM_CAN_USE_CAN1
00069   /* Driver initialization.*/
00070   canObjectInit(&CAND1);
00071 #endif /* PLATFORM_CAN_USE_CAN1 */
00072 }
00073
00074 /**
00075  * @brief   Configures and activates the CAN peripheral.
00076  *
00077  * @param[in] canp      pointer to the @p CANDriver object
00078  *
00079  * @notapi
00080  */
00081 void can_lld_start(CANDriver *canp) {
00082
00083   if (canp->state == CAN_STOP) {
00084     /* Enables the peripheral.*/
00085 #if PLATFORM_CAN_USE_CAN1
00086     if (&CAND1 == canp) {
00087
00088     }
00089 #endif /* PLATFORM_CAN_USE_CAN1 */
00090   }
00091   /* Configures the peripheral.*/
00092
00093 }
00094
00095 /**
00096  * @brief   Deactivates the CAN peripheral.
00097  *
00098  * @param[in] canp      pointer to the @p CANDriver object
00099  *
00100  * @notapi
00101  */
00102 void can_lld_stop(CANDriver *canp) {
00103
00104   if (canp->state == CAN_READY) {
00105     /* Resets the peripheral.*/
00106
00107     /* Disables the peripheral.*/
00108 #if PLATFORM_CAN_USE_CAN1
00109     if (&CAND1 == canp) {
00110
00111     }
00112 #endif /* PLATFORM_CAN_USE_CAN1 */
00113   }
00114 }
00115
00116 /**
00117  * @brief   Determines whether a frame can be transmitted.
00118  *
00119  * @param[in] canp      pointer to the @p CANDriver object
00120  * @param[in] mailbox   mailbox number, @p CAN_ANY_MAILBOX for any mailbox
00121  *
00122  * @return              The queue space availability.
00123  * @retval FALSE        no space in the transmit queue.
00124  * @retval TRUE         transmit slot available.
00125  *
00126  * @notapi
00127  */
00128 bool_t can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox) {
00129
00130   (void)canp;
00131
00132   switch (mailbox) {
00133   case CAN_ANY_MAILBOX:
00134     return FALSE;
00135   case 1:
00136     return FALSE;
00137   case 2:
00138     return FALSE;
00139   case 3:
00140     return FALSE;
00141   default:
00142     return FALSE;
00143   }
00144 }
00145
00146 /**
00147  * @brief   Inserts a frame into the transmit queue.
00148  *
00149  * @param[in] canp      pointer to the @p CANDriver object
00150  * @param[in] ctfp      pointer to the CAN frame to be transmitted
00151  * @param[in] mailbox   mailbox number,  @p CAN_ANY_MAILBOX for any mailbox
00152  *
00153  * @notapi
00154  */
00155 void can_lld_transmit(CANDriver *canp,
00156                       canmbx_t mailbox,
00157                       const CANTxFrame *ctfp) {
00158
00159   (void)canp;
00160   (void)mailbox;
00161   (void)ctfp;
00162
00163 }
00164
00165 /**
00166  * @brief   Determines whether a frame has been received.
00167  *
00168  * @param[in] canp      pointer to the @p CANDriver object
00169  * @param[in] mailbox   mailbox number, @p CAN_ANY_MAILBOX for any mailbox
00170  *
00171  * @return              The queue space availability.
00172  * @retval FALSE        no space in the transmit queue.
00173  * @retval TRUE         transmit slot available.
00174  *
00175  * @notapi
00176  */
00177 bool_t can_lld_is_rx_nonempty(CANDriver *canp, canmbx_t mailbox) {
00178
00179   (void)canp;
00180   (void)mailbox;
00181
00182   switch (mailbox) {
00183   case CAN_ANY_MAILBOX:
00184     return FALSE;
00185   case 1:
00186     return FALSE;
00187   case 2:
00188     return FALSE;
00189   default:
00190     return FALSE;
00191   }
00192 }
00193
00194 /**
00195  * @brief   Receives a frame from the input queue.
00196  *
00197  * @param[in] canp      pointer to the @p CANDriver object
00198  * @param[in] mailbox   mailbox number, @p CAN_ANY_MAILBOX for any mailbox
00199  * @param[out] crfp     pointer to the buffer where the CAN frame is copied
00200  *
00201  * @notapi
00202  */
00203 void can_lld_receive(CANDriver *canp,
00204                      canmbx_t mailbox,
00205                      CANRxFrame *crfp) {
00206
00207   (void)canp;
00208   (void)mailbox;
00209   (void)crfp;
00210
00211 }
00212
00213 #if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__)
00214 /**
00215  * @brief   Enters the sleep mode.
00216  *
00217  * @param[in] canp      pointer to the @p CANDriver object
00218  *
00219  * @notapi
00220  */
00221 void can_lld_sleep(CANDriver *canp) {
00222
00223   (void)canp;
00224
00225 }
00226
00227 /**
00228  * @brief   Enforces leaving the sleep mode.
00229  *
00230  * @param[in] canp      pointer to the @p CANDriver object
00231  *
00232  * @notapi
00233  */
00234 void can_lld_wakeup(CANDriver *canp) {
00235
00236   (void)canp;
00237
00238 }
00239 #endif /* CAN_USE_SLEEP_MODE */
00240
00241 #endif /* HAL_USE_CAN */
00242
00243 /** @} */
00001 /*
00002     ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
00003                  2011,2012,2013 Giovanni Di Sirio.
00004
00005     This file is part of ChibiOS/RT.
00006
00007     ChibiOS/RT is free software; you can redistribute it and/or modify
00008     it under the terms of the GNU General Public License as published by
00009     the Free Software Foundation; either version 3 of the License, or
00010     (at your option) any later version.
00011
00012     ChibiOS/RT is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015     GNU General Public License for more details.
00016
00017     You should have received a copy of the GNU General Public License
00018     along with this program.  If not, see <http://www.gnu.org/licenses/>.
00019
00020                                       ---
00021
00022     A special exception to the GPL can be applied should you wish to distribute
00023     a combined work that includes ChibiOS/RT, without being obliged to provide
00024     the source code for any proprietary components. See the file exception.txt
00025     for full details of how and when the exception can be applied.
00026 */
00027
00028 /**
00029  * @file    can.h
00030  * @brief   CAN Driver macros and structures.
00031  *
00032  * @addtogroup CAN
00033  * @{
00034  */
00035
00036 #ifndef _CAN_H_
00037 #define _CAN_H_
00038
00039 #if HAL_USE_CAN || defined(__DOXYGEN__)
00040
00041 /*===========================================================================*/
00042 /* Driver constants.                                                         */
00043 /*===========================================================================*/
00044
00045 /**
00046  * @name    CAN status flags
00047  * @{
00048  */
00049 /**
00050  * @brief   Errors rate warning.
00051  */
00052 #define CAN_LIMIT_WARNING           1
00053 /**
00054  * @brief   Errors rate error.
00055  */
00056 #define CAN_LIMIT_ERROR             2
00057 /**
00058  * @brief   Bus off condition reached.
00059  */
00060 #define CAN_BUS_OFF_ERROR           4
00061 /**
00062  * @brief   Framing error of some kind on the CAN bus.
00063  */
00064 #define CAN_FRAMING_ERROR           8
00065 /**
00066  * @brief   Overflow in receive queue.
00067  */
00068 #define CAN_OVERFLOW_ERROR          16
00069 /** @} */
00070
00071 /**
00072  * @brief   Special mailbox identifier.
00073  */
00074 #define CAN_ANY_MAILBOX             0
00075
00076 /*===========================================================================*/
00077 /* Driver pre-compile time settings.                                         */
00078 /*===========================================================================*/
00079
00080 /**
00081  * @name    CAN configuration options
00082  * @{
00083  */
00084 /**
00085  * @brief   Sleep mode related APIs inclusion switch.
00086  * @details This option can only be enabled if the CAN implementation supports
00087  *          the sleep mode, see the macro @p CAN_SUPPORTS_SLEEP exported by
00088  *          the underlying implementation.
00089  */
00090 #if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
00091 #define CAN_USE_SLEEP_MODE          TRUE
00092 #endif
00093 /** @} */
00094
00095 /*===========================================================================*/
00096 /* Derived constants and error checks.                                       */
00097 /*===========================================================================*/
00098
00099 #if !CH_USE_SEMAPHORES || !CH_USE_EVENTS
00100 #error "CAN driver requires CH_USE_SEMAPHORES and CH_USE_EVENTS"
00101 #endif
00102
00103 /*===========================================================================*/
00104 /* Driver data structures and types.                                         */
00105 /*===========================================================================*/
00106
00107 /**
00108  * @brief   Driver state machine possible states.
00109  */
00110 typedef enum {
00111   CAN_UNINIT = 0,                           /**< Not initialized.           */
00112   CAN_STOP = 1,                             /**< Stopped.                   */
00113   CAN_STARTING = 2,                         /**< Starting.                  */
00114   CAN_READY = 3,                            /**< Ready.                     */
00115   CAN_SLEEP = 4                             /**< Sleep state.               */
00116 } canstate_t;
00117
00118 #include "can_lld.h"
00119
00120 /*===========================================================================*/
00121 /* Driver macros.                                                            */
00122 /*===========================================================================*/
00123
00124 /**
00125  * @name    Macro Functions
00126  * @{
00127  */
00128 /**
00129  * @brief   Converts a mailbox index to a bit mask.
00130  */
00131 #define CAN_MAILBOX_TO_MASK(mbx) (1 << ((mbx) - 1))
00132 /** @} */
00133
00134 /*===========================================================================*/
00135 /* External declarations.                                                    */
00136 /*===========================================================================*/
00137
00138 #ifdef __cplusplus
00139 extern "C" {
00140 #endif
00141   void canInit(void);
00142   void canObjectInit(CANDriver *canp);
00143   void canStart(CANDriver *canp, const CANConfig *config);
00144   void canStop(CANDriver *canp);
00145   msg_t canTransmit(CANDriver *canp,
00146                     canmbx_t mailbox,
00147                     const CANTxFrame *ctfp,
00148                     systime_t timeout);
00149   msg_t canReceive(CANDriver *canp,
00150                    canmbx_t mailbox,
00151                    CANRxFrame *crfp,
00152                    systime_t timeout);
00153 #if CAN_USE_SLEEP_MODE
00154   void canSleep(CANDriver *canp);
00155   void canWakeup(CANDriver *canp);
00156 #endif /* CAN_USE_SLEEP_MODE */
00157 #ifdef __cplusplus
00158 }
00159 #endif
00160
00161 #endif /* HAL_USE_CAN */
00162
00163 #endif /* _CAN_H_ */
00164
00165 /** @} */
00001 /*
00002     ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
00003                  2011,2012,2013 Giovanni Di Sirio.
00004
00005     This file is part of ChibiOS/RT.
00006
00007     ChibiOS/RT is free software; you can redistribute it and/or modify
00008     it under the terms of the GNU General Public License as published by
00009     the Free Software Foundation; either version 3 of the License, or
00010     (at your option) any later version.
00011
00012     ChibiOS/RT is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015     GNU General Public License for more details.
00016
00017     You should have received a copy of the GNU General Public License
00018     along with this program.  If not, see <http://www.gnu.org/licenses/>.
00019
00020                                       ---
00021
00022     A special exception to the GPL can be applied should you wish to distribute
00023     a combined work that includes ChibiOS/RT, without being obliged to provide
00024     the source code for any proprietary components. See the file exception.txt
00025     for full details of how and when the exception can be applied.
00026 */
00027
00028 /**
00029  * @file    can.c
00030  * @brief   CAN Driver code.
00031  *
00032  * @addtogroup CAN
00033  * @{
00034  */
00035
00036 #include "ch.h"
00037 #include "hal.h"
00038
00039 #if HAL_USE_CAN || defined(__DOXYGEN__)
00040
00041 /*===========================================================================*/
00042 /* Driver local definitions.                                                 */
00043 /*===========================================================================*/
00044
00045 /*===========================================================================*/
00046 /* Driver exported variables.                                                */
00047 /*===========================================================================*/
00048
00049 /*===========================================================================*/
00050 /* Driver local variables and types.                                         */
00051 /*===========================================================================*/
00052
00053 /*===========================================================================*/
00054 /* Driver local functions.                                                   */
00055 /*===========================================================================*/
00056
00057 /*===========================================================================*/
00058 /* Driver exported functions.                                                */
00059 /*===========================================================================*/
00060
00061 /**
00062  * @brief   CAN Driver initialization.
00063  * @note    This function is implicitly invoked by @p halInit(), there is
00064  *          no need to explicitly initialize the driver.
00065  *
00066  * @init
00067  */
00068 void canInit(void) {
00069
00070   can_lld_init();
00071 }
00072
00073 /**
00074  * @brief   Initializes the standard part of a @p CANDriver structure.
00075  *
00076  * @param[out] canp     pointer to the @p CANDriver object
00077  *
00078  * @init
00079  */
00080 void canObjectInit(CANDriver *canp) {
00081
00082   canp->state    = CAN_STOP;
00083   canp->config   = NULL;
00084   chSemInit(&canp->txsem, 0);
00085   chSemInit(&canp->rxsem, 0);
00086   chEvtInit(&canp->rxfull_event);
00087   chEvtInit(&canp->txempty_event);
00088   chEvtInit(&canp->error_event);
00089 #if CAN_USE_SLEEP_MODE
00090   chEvtInit(&canp->sleep_event);
00091   chEvtInit(&canp->wakeup_event);
00092 #endif /* CAN_USE_SLEEP_MODE */
00093 }
00094
00095 /**
00096  * @brief   Configures and activates the CAN peripheral.
00097  * @note    Activating the CAN bus can be a slow operation this this function
00098  *          is not atomic, it waits internally for the initialization to
00099  *          complete.
00100  *
00101  * @param[in] canp      pointer to the @p CANDriver object
00102  * @param[in] config    pointer to the @p CANConfig object. Depending on
00103  *                      the implementation the value can be @p NULL.
00104  *
00105  * @api
00106  */
00107 void canStart(CANDriver *canp, const CANConfig *config) {
00108
00109   chDbgCheck(canp != NULL, "canStart");
00110
00111   chSysLock();
00112   chDbgAssert((canp->state == CAN_STOP) ||
00113               (canp->state == CAN_STARTING) ||
00114               (canp->state == CAN_READY),
00115               "canStart(), #1", "invalid state");
00116   while (canp->state == CAN_STARTING)
00117     chThdSleepS(1);
00118   if (canp->state == CAN_STOP) {
00119     canp->config = config;
00120     can_lld_start(canp);
00121     canp->state = CAN_READY;
00122   }
00123   chSysUnlock();
00124 }
00125
00126 /**
00127  * @brief   Deactivates the CAN peripheral.
00128  *
00129  * @param[in] canp      pointer to the @p CANDriver object
00130  *
00131  * @api
00132  */
00133 void canStop(CANDriver *canp) {
00134
00135   chDbgCheck(canp != NULL, "canStop");
00136
00137   chSysLock();
00138   chDbgAssert((canp->state == CAN_STOP) || (canp->state == CAN_READY),
00139               "canStop(), #1", "invalid state");
00140   can_lld_stop(canp);
00141   canp->state  = CAN_STOP;
00142   chSemResetI(&canp->rxsem, 0);
00143   chSemResetI(&canp->txsem, 0);
00144   chSchRescheduleS();
00145   chSysUnlock();
00146 }
00147
00148 /**
00149  * @brief   Can frame transmission.
00150  * @details The specified frame is queued for transmission, if the hardware
00151  *          queue is full then the invoking thread is queued.
00152  * @note    Trying to transmit while in sleep mode simply enqueues the thread.
00153  *
00154  * @param[in] canp      pointer to the @p CANDriver object
00155  * @param[in] mailbox   mailbox number, @p CAN_ANY_MAILBOX for any mailbox
00156  * @param[in] ctfp      pointer to the CAN frame to be transmitted
00157  * @param[in] timeout   the number of ticks before the operation timeouts,
00158  *                      the following special values are allowed:
00159  *                      - @a TIME_IMMEDIATE immediate timeout.
00160  *                      - @a TIME_INFINITE no timeout.
00161  *                      .
00162  * @return              The operation result.
00163  * @retval RDY_OK       the frame has been queued for transmission.
00164  * @retval RDY_TIMEOUT  The operation has timed out.
00165  * @retval RDY_RESET    The driver has been stopped while waiting.
00166  *
00167  * @api
00168  */
00169 msg_t canTransmit(CANDriver *canp,
00170                   canmbx_t mailbox,
00171                   const CANTxFrame *ctfp,
00172                   systime_t timeout) {
00173
00174   chDbgCheck((canp != NULL) && (ctfp != NULL) && (mailbox <= CAN_TX_MAILBOXES),
00175              "canTransmit");
00176
00177   chSysLock();
00178   chDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP),
00179               "canTransmit(), #1", "invalid state");
00180   while ((canp->state == CAN_SLEEP) || !can_lld_is_tx_empty(canp, mailbox)) {
00181     msg_t msg = chSemWaitTimeoutS(&canp->txsem, timeout);
00182     if (msg != RDY_OK) {
00183       chSysUnlock();
00184       return msg;
00185     }
00186   }
00187   can_lld_transmit(canp, mailbox, ctfp);
00188   chSysUnlock();
00189   return RDY_OK;
00190 }
00191
00192 /**
00193  * @brief   Can frame receive.
00194  * @details The function waits until a frame is received.
00195  * @note    Trying to receive while in sleep mode simply enqueues the thread.
00196  *
00197  * @param[in] canp      pointer to the @p CANDriver object
00198  * @param[in] mailbox   mailbox number, @p CAN_ANY_MAILBOX for any mailbox
00199  * @param[out] crfp     pointer to the buffer where the CAN frame is copied
00200  * @param[in] timeout   the number of ticks before the operation timeouts,
00201  *                      the following special values are allowed:
00202  *                      - @a TIME_IMMEDIATE immediate timeout (useful in an
00203  *                        event driven scenario where a thread never blocks
00204  *                        for I/O).
00205  *                      - @a TIME_INFINITE no timeout.
00206  *                      .
00207  * @return              The operation result.
00208  * @retval RDY_OK       a frame has been received and placed in the buffer.
00209  * @retval RDY_TIMEOUT  The operation has timed out.
00210  * @retval RDY_RESET    The driver has been stopped while waiting.
00211  *
00212  * @api
00213  */
00214 msg_t canReceive(CANDriver *canp,
00215                  canmbx_t mailbox,
00216                  CANRxFrame *crfp,
00217                  systime_t timeout) {
00218
00219   chDbgCheck((canp != NULL) && (crfp != NULL) && (mailbox <= CAN_RX_MAILBOXES),
00220              "canReceive");
00221
00222   chSysLock();
00223   chDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP),
00224               "canReceive(), #1", "invalid state");
00225   while ((canp->state == CAN_SLEEP) || !can_lld_is_rx_nonempty(canp, mailbox)) {
00226     msg_t msg = chSemWaitTimeoutS(&canp->rxsem, timeout);
00227     if (msg != RDY_OK) {
00228       chSysUnlock();
00229       return msg;
00230     }
00231   }
00232   can_lld_receive(canp, mailbox, crfp);
00233   chSysUnlock();
00234   return RDY_OK;
00235 }
00236
00237 #if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__)
00238 /**
00239  * @brief   Enters the sleep mode.
00240  * @details This function puts the CAN driver in sleep mode and broadcasts
00241  *          the @p sleep_event event source.
00242  * @pre     In order to use this function the option @p CAN_USE_SLEEP_MODE must
00243  *          be enabled and the @p CAN_SUPPORTS_SLEEP mode must be supported
00244  *          by the low level driver.
00245  *
00246  * @param[in] canp      pointer to the @p CANDriver object
00247  *
00248  * @api
00249  */
00250 void canSleep(CANDriver *canp) {
00251
00252   chDbgCheck(canp != NULL, "canSleep");
00253
00254   chSysLock();
00255   chDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP),
00256               "canSleep(), #1", "invalid state");
00257   if (canp->state == CAN_READY) {
00258     can_lld_sleep(canp);
00259     canp->state = CAN_SLEEP;
00260     chEvtBroadcastI(&canp->sleep_event);
00261     chSchRescheduleS();
00262   }
00263   chSysUnlock();
00264 }
00265
00266 /**
00267  * @brief   Enforces leaving the sleep mode.
00268  * @note    The sleep mode is supposed to be usually exited automatically by
00269  *          an hardware event.
00270  *
00271  * @param[in] canp      pointer to the @p CANDriver object
00272  */
00273 void canWakeup(CANDriver *canp) {
00274
00275   chDbgCheck(canp != NULL, "canWakeup");
00276
00277   chSysLock();
00278   chDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP),
00279               "canWakeup(), #1", "invalid state");
00280   if (canp->state == CAN_SLEEP) {
00281     can_lld_wakeup(canp);
00282     canp->state = CAN_READY;
00283     chEvtBroadcastI(&canp->wakeup_event);
00284     chSchRescheduleS();
00285   }
00286   chSysUnlock();
00287 }
00288 #endif /* CAN_USE_SLEEP_MODE */
00289
00290 #endif /* HAL_USE_CAN */
00291
00292 /** @} */

void canInit(void )

CAN Driver initialization.

Note:
This function is implicitly invoked by halInit(), there is no need to explicitly initialize the driver.
Function Class:
Initializer, this function just initializes an object and can be invoked before the kernel is initialized.

Here is the call graph for this function:

void canObjectInit ( CANDriver * canp )

Initializes the standard part of a CANDriver structure.

Function Class:
Initializer, this function just initializes an object and can be invoked before the kernel is initialized.

void canStart ( CANDriver * canp, const CANConfig * config )

Configures and activates the CAN peripheral.

Note:
Activating the CAN bus can be a slow operation this this function is not atomic, it waits internally for the initialization to complete.

Function Class:Normal API, this function can be invoked by regular system threads but not from within a lock zone.

void canStop ( CANDriver * canp )

Deactivates the CAN peripheral.

Function Class:Normal API, this function can be invoked by regular system threads but not from within a lock zone.

msg_t canTransmit ( CANDriver * canp, canmbx_t mailbox, const CANTxFrame * ctfp, systime_t timeout )

Can frame transmission.

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.

Function Class:Normal API, this function can be invoked by regular system threads but not from within a lock zone.

msg_t canReceive ( CANDriver * canp, canmbx_t mailbox, CANRxFrame * crfp, systime_t timeout )

Can frame receive.

The function waits until a frame is received.

Note:
Trying to receive while in sleep mode simply enqueues the thread.

Function Class:Normal API, this function can be invoked by regular system threads but not from within a lock zone.

void canSleep ( CANDriver * canp )

Enters the sleep mode.

This function puts the CAN driver in sleep mode and broadcasts the sleep_event event source.

Precondition:
In order to use this function the option CAN_USE_SLEEP_MODE must be enabled
and the CAN_SUPPORTS_SLEEP mode must be supported by the low level driver.

Function Class:Normal API, this function can be invoked by regular system threads but not from within a lock zone.

void canWakeup ( CANDriver * canp )

Enforces leaving the sleep mode.

Note:
The sleep mode is supposed to be usually exited automatically by an hardware event.
/**
 * This switch defines whether the driver implementation supports
 *          a low power switch mode with automatic an wakeup feature.
 */
#define CAN_SUPPORTS_SLEEP          TRUE

/**
 * This implementation supports three transmit mailboxes.
 */
#define CAN_TX_MAILBOXES            3

/**
 * This implementation supports two receive mailboxes.
 */
#define CAN_RX_MAILBOXES            2

/*===========================================================================*/
/* Driver pre-compile time settings.                                         */
/*===========================================================================*/

/**
 * @name    Configuration options
 * @{
 */
/**
 * CAN1 driver enable switch.
 * @details If set to @p TRUE the support for CAN1 is included.
 */
#if !defined(PLATFORM_CAN_USE_CAN1) || defined(__DOXYGEN__)
#define PLATFORM_CAN_USE_CAN1               FALSE
#endif

/*===========================================================================*/
/* Derived constants and error checks.                                       */
/*===========================================================================*/

#if CAN_USE_SLEEP_MODE && !CAN_SUPPORTS_SLEEP
#error "CAN sleep mode not supported in this architecture"
#endif

/*===========================================================================*/
/* Driver data structures and types.                                         */
/*===========================================================================*/

/**
 * Type of a transmission mailbox index.
 */
typedef uint32_t canmbx_t;

/**
 * CAN transmission frame.
 * @note    Accessing the frame data as word16 or word32 is not portable because
 *          machine data endianness, it can be still useful for a quick filling.
 */
typedef struct
{
  struct
  {
    uint8_t DLC :4; /**< @brief Data length.        */
    uint8_t RTR :1; /**< @brief Frame type.         */
    uint8_t IDE :1; /**< @brief Identifier type.    */
  };
  union
  {
    struct
    {
      uint32_t SID :11; /**< @brief Standard identifier.*/
    };
    struct
    {
      uint32_t EID :29; /**< @brief Extended identifier.*/
    };
  };
  union
  {
    uint8_t data8[ 8 ]; /**< @brief Frame data.         */
    uint16_t data16[ 4 ]; /**< @brief Frame data.         */
    uint32_t data32[ 2 ]; /**< @brief Frame data.         */
  };
} CANTxFrame;

/**
 * CAN received frame.
 * @note    Accessing the frame data as word16 or word32 is not portable because
 *          machine data endianness, it can be still useful for a quick filling.
 */
typedef struct
{
  struct
  {
    uint8_t DLC :4; /**< @brief Data length.        */
    uint8_t RTR :1; /**< @brief Frame type.         */
    uint8_t IDE :1; /**< @brief Identifier type.    */
  };
  union
  {
    struct
    {
      uint32_t SID :11; /**< @brief Standard identifier.*/
    };
    struct
    {
      uint32_t EID :29; /**< @brief Extended identifier.*/
    };
  };
  union
  {
    uint8_t data8[ 8 ]; /**< @brief Frame data.         */
    uint16_t data16[ 4 ]; /**< @brief Frame data.         */
    uint32_t data32[ 2 ]; /**< @brief Frame data.         */
  };
} CANRxFrame;

/**
 * CAN filter.
 * @note    Implementations may extend this structure to contain more,
 *          architecture dependent, fields.
 * @note    It could not be present on some architectures.
 */
typedef struct
{
  uint32_t dummy;
} CANFilter;

/**
 * Driver configuration structure.
 * @note    Implementations may extend this structure to contain more,
 *          architecture dependent, fields.
 * @note    It could be empty on some architectures.
 */
typedef struct
{
  uint32_t dummy;
} CANConfig;

/**
 * Structure representing an CAN driver.
 */
typedef struct
{
  /**
   * Driver state.
   */
  canstate_t state;
  /**
   * Current configuration data.
   */
  const CANConfig *config;
  /**
   * Transmission queue semaphore.
   */
  Semaphore txsem;
  /**
   * Receive queue semaphore.
   */
  Semaphore rxsem;
  /**
   * One or more frames become available.
   * @note    After broadcasting this event it will not be broadcasted again
   *          until the received frames queue has been completely emptied. It
   *          is <b>not</b> broadcasted for each received frame. It is
   *          responsibility of the application to empty the queue by
   *          repeatedly invoking @p chReceive() when listening to this event.
   *          This behavior minimizes the interrupt served by the system
   *          because CAN traffic.
   * @note    The flags associated to the listeners will indicate which
   *          receive mailboxes become non-empty.
   */
  EventSource rxfull_event;
  /**
   * One or more transmission mailbox become available.
   * @note    The flags associated to the listeners will indicate which
   *          transmit mailboxes become empty.
   *
   */
  EventSource txempty_event;
  /**
   * A CAN bus error happened.
   * @note    The flags associated to the listeners will indicate the
   *          error(s) that have occurred.
   */
  EventSource error_event;
  /**
   * Entering sleep state event.
   */
  EventSource sleep_event;
  /**
   * Exiting sleep state event.
   */
  EventSource wakeup_event;
/* End of the mandatory fields.*/
} CANDriver;

extern CANDriver CAND1;
void can_lld_init( void );
void can_lld_start( CANDriver *canp );
void can_lld_stop( CANDriver *canp );
uiknt32_t can_lld_is_tx_empty( CANDriver *canp, canmbx_t mailbox );
void can_lld_transmit( CANDriver *canp, canmbx_t mailbox,
  const CANTxFrame *crfp );
uiknt32_t can_lld_is_rx_nonempty( CANDriver *canp, canmbx_t mailbox );
void can_lld_receive( CANDriver *canp, canmbx_t mailbox, CANRxFrame *ctfp );
void can_lld_sleep( CANDriver *canp );
void can_lld_wakeup( CANDriver *canp );

/**
 * @file    templates/can_lld.c
 * CAN Driver subsystem low level driver source template.
 *
 * @addtogroup CAN
 * @{
 */

/**
 * CAN1 driver identifier.
 */
CANDriver CAND1;

/**
 * Low level CAN driver initialization.
 *
 * @notapi
 */
void can_lld_init( void )
{
  /* Driver initialization.*/
  canObjectInit( &CAND1 );
}

/**
 * Configures and activates the CAN peripheral.
 *
 * @param[in] canp      pointer to the @p CANDriver object
 *
 * @notapi
 */
void can_lld_start( CANDriver *canp )
{
  if ( canp->state == CAN_STOP )
  {
    /* Enables the peripheral.*/
    if ( &CAND1 == canp )
    {
    }
  }
  /* Configures the peripheral.*/

}

/**
 * Deactivates the CAN peripheral.
 *
 * @param[in] canp      pointer to the @p CANDriver object
 *
 * @notapi
 */
void can_lld_stop( CANDriver *canp )
{
  if ( canp->state == CAN_READY )
  {
    /* Resets the peripheral.*/
    /* Disables the peripheral.*/
    if ( &CAND1 == canp )
    {
    }
  }
}

/**
 * Determines whether a frame can be transmitted.
 *
 * @param[in] canp      pointer to the @p CANDriver object
 * @param[in] mailbox   mailbox number, @p CAN_ANY_MAILBOX for any mailbox
 *
 * @return              The queue space availability.
 * @retval FALSE        no space in the transmit queue.
 * @retval TRUE         transmit slot available.
 *
 * @notapi
 */
uiknt32_t can_lld_is_tx_empty( CANDriver *canp, canmbx_t mailbox )
{
  (void) canp;
  switch ( mailbox )
  {
    case CAN_ANY_MAILBOX:
      return FALSE;
    case 1:
      return FALSE;
    case 2:
      return FALSE;
    case 3:
      return FALSE;
    default:
      return FALSE;
  }
}

/**
 * Inserts a frame into the transmit queue.
 *
 * @param[in] canp      pointer to the @p CANDriver object
 * @param[in] ctfp      pointer to the CAN frame to be transmitted
 * @param[in] mailbox   mailbox number,  @p CAN_ANY_MAILBOX for any mailbox
 *
 * @notapi
 */
void can_lld_transmit( CANDriver *canp, canmbx_t mailbox,
  const CANTxFrame *ctfp )
{
  (void) canp;
  (void) mailbox;
  (void) ctfp;

}

/**
 * Determines whether a frame has been received.
 *
 * @param[in] canp      pointer to the @p CANDriver object
 * @param[in] mailbox   mailbox number, @p CAN_ANY_MAILBOX for any mailbox
 *
 * @return              The queue space availability.
 * @retval FALSE        no space in the transmit queue.
 * @retval TRUE         transmit slot available.
 *
 * @notapi
 */
uiknt32_t can_lld_is_rx_nonempty( CANDriver *canp, canmbx_t mailbox )
{
  (void) canp;
  (void) mailbox;

  switch ( mailbox )
  {
    case CAN_ANY_MAILBOX:
      return FALSE;
    case 1:
      return FALSE;
    case 2:
      return FALSE;
    default:
      return FALSE;
  }
}

/**
 * Receives a frame from the input queue.
 *
 * @param[in] canp      pointer to the @p CANDriver object
 * @param[in] mailbox   mailbox number, @p CAN_ANY_MAILBOX for any mailbox
 * @param[out] crfp     pointer to the buffer where the CAN frame is copied
 *
 * @notapi
 */
void can_lld_receive( CANDriver *canp, canmbx_t mailbox, CANRxFrame *crfp )
{
  (void) canp;
  (void) mailbox;
  (void) crfp;
}

/**
 * Enters the sleep mode.
 *
 * @param[in] canp      pointer to the @p CANDriver object
 *
 * @notapi
 */
void can_lld_sleep( CANDriver *canp )
{
  (void) canp;
}

/**
 * Enforces leaving the sleep mode.
 *
 * @param[in] canp      pointer to the @p CANDriver object
 *
 * @notapi
 */
void can_lld_wakeup( CANDriver *canp )
{
  (void) canp;

}

/**
 * @name    CAN status flags
 * @{
 */
/**
 * Errors rate warning.
 */
#define CAN_LIMIT_WARNING           1
/**
 * Errors rate error.
 */
#define CAN_LIMIT_ERROR             2
/**
 * Bus off condition reached.
 */
#define CAN_BUS_OFF_ERROR           4
/**
 * Framing error of some kind on the CAN bus.
 */
#define CAN_FRAMING_ERROR           8
/**
 * Overflow in receive queue.
 */
#define CAN_OVERFLOW_ERROR          16

/**
 * Special mailbox identifier.
 */
#define CAN_ANY_MAILBOX             0

/**
 * @name    CAN configuration options
 * @{
 */
/**
 * Sleep mode related APIs inclusion switch.
 * @details This option can only be enabled if the CAN implementation supports
 *          the sleep mode, see the macro @p CAN_SUPPORTS_SLEEP exported by
 *          the underlying implementation.
 */

#define CAN_USE_SLEEP_MODE          TRUE

/**
 * Driver state machine possible states.
 */
typedef enum
{
  CAN_UNINIT = 0, /**< Not initialized.           */
  CAN_STOP = 1, /**< Stopped.                   */
  CAN_STARTING = 2, /**< Starting.                  */
  CAN_READY = 3, /**< Ready.                     */
  CAN_SLEEP = 4 /**< Sleep state.               */
} canstate_t;

#include "can_lld.h"

/**
 * Converts a mailbox index to a bit mask.
 */
#define CAN_MAILBOX_TO_MASK(mbx) (1 << ((mbx) - 1))

void canInit( void );
void canObjectInit( CANDriver *canp );
void canStart( CANDriver *canp, const CANConfig *config );
void canStop( CANDriver *canp );
msg_t canTransmit( CANDriver *canp, canmbx_t mailbox, const CANTxFrame *ctfp,
  systime_t timeout );
msg_t canReceive( CANDriver *canp, canmbx_t mailbox, CANRxFrame *crfp,
  systime_t timeout );
void canSleep( CANDriver *canp );
void canWakeup( CANDriver *canp );

#include "ch.h"
#include "hal.h"

/**
 * CAN Driver initialization.
 * @note    This function is implicitly invoked by @p halInit(), there is
 *          no need to explicitly initialize the driver.
 *
 * @init
 */
void canInit( void )
{

  can_lld_init( );
}

/**
 * Initializes the standard part of a @p CANDriver structure.
 *
 * @param[out] canp     pointer to the @p CANDriver object
 *
 * @init
 */
void canObjectInit( CANDriver *canp )
{

  canp->state = CAN_STOP;
  canp->config = NULL;
  chSemInit( &canp->txsem, 0 );
  chSemInit( &canp->rxsem, 0 );
  chEvtInit( &canp->rxfull_event );
  chEvtInit( &canp->txempty_event );
  chEvtInit( &canp->error_event );
  chEvtInit( &canp->sleep_event );
  chEvtInit( &canp->wakeup_event );
}

/**
 * Configures and activates the CAN peripheral.
 * @note    Activating the CAN bus can be a slow operation this this function
 *          is not atomic, it waits internally for the initialization to
 *          complete.
 *
 * @param[in] canp      pointer to the @p CANDriver object
 * @param[in] config    pointer to the @p CANConfig object. Depending on
 *                      the implementation the value can be @p NULL.
 *
 * @api
 */
void canStart( CANDriver *canp, const CANConfig *config )
{

  chDbgCheck( canp != NULL, "canStart" );

  chSysLock( );
  chDbgAssert(
    ( canp->state == CAN_STOP ) || ( canp->state == CAN_STARTING )
      || ( canp->state == CAN_READY ), "canStart(), #1", "invalid state" );
  while ( canp->state == CAN_STARTING )
    chThdSleepS( 1 );
  if ( canp->state == CAN_STOP )
  {
    canp->config = config;
    can_lld_start( canp );
    canp->state = CAN_READY;
  }
  chSysUnlock( );
}

/**
 * Deactivates the CAN peripheral.
 *
 * @param[in] canp      pointer to the @p CANDriver object
 *
 * @api
 */
void canStop( CANDriver *canp )
{

  chDbgCheck( canp != NULL, "canStop" );

  chSysLock( );
  chDbgAssert( ( canp->state == CAN_STOP ) || ( canp->state == CAN_READY ),
    "canStop(), #1", "invalid state" );
  can_lld_stop( canp );
  canp->state = CAN_STOP;
  chSemResetI( &canp->rxsem, 0 );
  chSemResetI( &canp->txsem, 0 );
  chSchRescheduleS( );
  chSysUnlock( );
}

/**
 * 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] mailbox   mailbox number, @p CAN_ANY_MAILBOX for any mailbox
 * @param[in] ctfp      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  The operation has timed out.
 * @retval RDY_RESET    The driver has been stopped while waiting.
 *
 * @api
 */
msg_t canTransmit( CANDriver *canp, canmbx_t mailbox, const CANTxFrame *ctfp,
  systime_t timeout )
{

  chDbgCheck(
    ( canp != NULL ) && ( ctfp != NULL ) && ( mailbox <= CAN_TX_MAILBOXES ),
    "canTransmit" );

  chSysLock( );
  chDbgAssert( ( canp->state == CAN_READY ) || ( canp->state == CAN_SLEEP ),
    "canTransmit(), #1", "invalid state" );
  while ( ( canp->state == CAN_SLEEP ) || !can_lld_is_tx_empty( canp, mailbox ) )
  {
    msg_t msg = chSemWaitTimeoutS( &canp->txsem, timeout );
    if ( msg != RDY_OK )
    {
      chSysUnlock( );
      return msg;
    }
  }
  can_lld_transmit( canp, mailbox, ctfp );
  chSysUnlock( );
  return RDY_OK;
}

/**
 * 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[in] mailbox   mailbox number, @p CAN_ANY_MAILBOX for any mailbox
 * @param[out] crfp     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 (useful in an
 *                        event driven scenario where a thread never blocks
 *                        for I/O).
 *                      - @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  The operation has timed out.
 * @retval RDY_RESET    The driver has been stopped while waiting.
 *
 * @api
 */
msg_t canReceive( CANDriver *canp, canmbx_t mailbox, CANRxFrame *crfp,
  systime_t timeout )
{

  chDbgCheck(
    ( canp != NULL ) && ( crfp != NULL ) && ( mailbox <= CAN_RX_MAILBOXES ),
    "canReceive" );

  chSysLock( );
  chDbgAssert( ( canp->state == CAN_READY ) || ( canp->state == CAN_SLEEP ),
    "canReceive(), #1", "invalid state" );
  while ( ( canp->state == CAN_SLEEP )
    || !can_lld_is_rx_nonempty( canp, mailbox ) )
  {
    msg_t msg = chSemWaitTimeoutS( &canp->rxsem, timeout );
    if ( msg != RDY_OK )
    {
      chSysUnlock( );
      return msg;
    }
  }
  can_lld_receive( canp, mailbox, crfp );
  chSysUnlock( );
  return RDY_OK;
}

/**
 * Enters the sleep mode.
 * @details This function puts the CAN driver in sleep mode and broadcasts
 *          the @p sleep_event event source.
 * @pre     In order to use this function the option @p CAN_USE_SLEEP_MODE must
 *          be enabled and the @p CAN_SUPPORTS_SLEEP mode must be supported
 *          by the low level driver.
 *
 * @param[in] canp      pointer to the @p CANDriver object
 *
 * @api
 */
void canSleep( CANDriver *canp )
{

  chDbgCheck( canp != NULL, "canSleep" );

  chSysLock( );
  chDbgAssert( ( canp->state == CAN_READY ) || ( canp->state == CAN_SLEEP ),
    "canSleep(), #1", "invalid state" );
  if ( canp->state == CAN_READY )
  {
    can_lld_sleep( canp );
    canp->state = CAN_SLEEP;
    chEvtBroadcastI( &canp->sleep_event );
    chSchRescheduleS( );
  }
  chSysUnlock( );
}

/**
 * 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->state == CAN_READY ) || ( canp->state == CAN_SLEEP ),
    "canWakeup(), #1", "invalid state" );
  if ( canp->state == CAN_SLEEP )
  {
    can_lld_wakeup( canp );
    canp->state = CAN_READY;
    chEvtBroadcastI( &canp->wakeup_event );
    chSchRescheduleS( );
  }
  chSysUnlock( );
}
时间: 2024-10-17 21:42:10

ChibiOS/RT 2.6.9 CAN Driver的相关文章

ChibiOS/RT 2.6.9 CAN Low Level Driver for STM32

/* ChibiOS - Copyright (C) 2006..2015 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.or

Open Source RTOS

http://www.osrtos.com/ Name License Platforms Description Last updated FreeRTOS Modified GPL MSP430 ARM AVR ColdFire PIC x86 FreeRTOS is a popular real-time operating system for embedded devices, being ported to 31 microcontrollers. It is distributed

A LED AC driver Research: open-loop peak current control type

For some days, I have always wanted to design a LED driver which driving mid-power LEDs, to replace low-power LED tube design that we are using now. Start to do it, now! First of all, a specification: Input Voltage 220 VAC rms Expected LED String Vol

mybatis配置,idea报错:java.sql.SQLException: No suitable driver found for jdbc://localhost:3306/mybatis_test

报错信息: "C:\Program Files\Java\jdk1.8.0_211\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.4\lib\idea_rt.jar=54826:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.4\bin" -Dfile.encoding=UTF-8 -classpath "C

tomcat启动过程报the JDBC Driver has been forcibly unregistered问题的修复过程

最近两天在整理关于flume的总结文档,没有启动过tomcat.昨天晚上部署启动,发现报了如题的错误,全文如下: 严重: The web application [/oa-deploy] registered the JBDC driver [com.microsoft.sqlserver.jdbc.SQLServerDriver] but failed to unregister it when the web application was stopped. To prevent a mem

struts2+hibernate+spring简单整合且java.sql.SQLException: No suitable driver 问题解决

最近上j2ee的课,老师要求整合struts2+hibernate+spring,我自己其实早早地有准备弄的,现在都第9个项目了,无奈自己的思路和头绪把自己带坑了,当然也是经验问题,其实只是用myeclipse进行整合的,本来也没那么多问题,看视频吧居然好多要手打,我不喜欢看不下去放弃了,教程把就是一堆坑,最最让人不解的是明明有一个冲突是需要解决的,但我看到的教程居然都没有提到,还有一个错误居然好多人都好像自动忽略一样,能解决我问题的都是要漫长的找,所以我一定一定要把这个过程记录下来,给第一次搞

fedora25 安装virtualbox5.1 出现提示Kernel driver not installed (rc=-1908) 错误的解决方法

fedora25 安装virtualbox5.1 出现提示Kernel driver not installed (rc=-1908) 错误的解决方法: $ sudo /usr/lib/virtualbox/vboxdrv.sh setup        vboxdrv.sh: Building VirtualBox kernel modules.             vboxdrv.sh: Starting VirtualBox services.

Junit Test With Selenium Driver

Junits 和 Selenium Junits 处理的是unit level 的测试:Selenium 处理的是 functional leve 的测试.虽然它们是完全不同,但仍然可以用Junit 来写 Selenium 测试. 一个完整的例子 import java.util.concurrent.TimeUnit;   import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; im

ZOJ 3794 Greedy Driver spfa

题意: 给定n个点,m条有向边,邮箱容量. 起点在1,终点在n,开始邮箱满油. 下面m行表示起点终点和这条边的耗油量(就是长度) 再下面给出一个数字m表示有P个加油站,可以免费加满油. 下面一行P个数字表示加油站的点标. 再下面一个整数Q 下面Q行 u v 表示在u点有销售站,可以卖掉邮箱里的任意数量的油,每以单位v元. 问跑到终点能获得最多多少元. 先求个每个点的最大剩余油量 f[i], 再把边反向,求每个点距离终点的最短路 dis[i]. 然后枚举一下每个销售点即可,( f[i] - dis