1 /** 2 * CAN module object for generic microcontroller. 3 * 4 * This file is a template for other microcontrollers. 5 * 6 * @file CO_driver_target.h 7 * @ingroup CO_driver 8 * @author Janez Paternoster 9 * @copyright 2004 - 2020 Janez Paternoster 10 * 11 * This file is part of CANopenNode, an opensource CANopen Stack. 12 * Project home page is <https://github.com/CANopenNode/CANopenNode>. 13 * For more information on CANopen see <http://www.can-cia.org/>. 14 * 15 * Licensed under the Apache License, Version 2.0 (the "License"); 16 * you may not use this file except in compliance with the License. 17 * You may obtain a copy of the License at 18 * 19 * http://www.apache.org/licenses/LICENSE-2.0 20 * 21 * Unless required by applicable law or agreed to in writing, software 22 * distributed under the License is distributed on an "AS IS" BASIS, 23 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 24 * See the License for the specific language governing permissions and 25 * limitations under the License. 26 */ 27 28 29 #ifndef CO_DRIVER_TARGET_H 30 #define CO_DRIVER_TARGET_H 31 32 #ifdef __cplusplus 33 extern "C" { 34 #endif 35 36 /* Include processor header file */ 37 #include <stddef.h> /* for 'NULL' */ 38 #include <stdint.h> /* for 'int8_t' to 'uint64_t' */ 39 #include <stdbool.h> /* for 'true', 'false' */ 40 41 42 /** 43 * Endianness. 44 * 45 * Depending on processor or compiler architecture, one of the two macros must 46 * be defined: CO_LITTLE_ENDIAN or CO_BIG_ENDIAN. CANopen itself is little endian. 47 */ 48 #define CO_LITTLE_ENDIAN 49 50 51 /** 52 * @defgroup CO_driver Driver 53 * @ingroup CO_CANopen 54 * @{ 55 * 56 * Microcontroller specific code for CANopenNode. 57 * 58 * This file contains type definitions, functions and macros for: 59 * - Basic data types. 60 * - Receive and transmit buffers for CANopen messages. 61 * - Interaction with CAN module on the microcontroller. 62 * - CAN receive and transmit interrupts. 63 * 64 * This file is not only a CAN driver. There are no classic CAN queues for CAN 65 * messages. This file provides direct connection with other CANopen 66 * objects. It tries to provide fast responses and tries to avoid unnecessary 67 * calculations and memory consumptions. 68 * 69 * CO_CANmodule_t contains an array of _Received message objects_ (of type 70 * CO_CANrx_t) and an array of _Transmit message objects_ (of type CO_CANtx_t). 71 * Each CANopen communication object owns one member in one of the arrays. 72 * For example Heartbeat producer generates one CANopen transmitting object, 73 * so it has reserved one member in CO_CANtx_t array. 74 * SYNC module may produce sync or consume sync, so it has reserved one member 75 * in CO_CANtx_t and one member in CO_CANrx_t array. 76 * 77 * ###Reception of CAN messages. 78 * Before CAN messages can be received, each member in CO_CANrx_t must be 79 * initialized. CO_CANrxBufferInit() is called by CANopen module, which 80 * uses specific member. For example @ref CO_HBconsumer uses multiple members 81 * in CO_CANrx_t array. (It monitors multiple heartbeat messages from remote 82 * nodes.) It must call CO_CANrxBufferInit() multiple times. 83 * 84 * Main arguments to the CO_CANrxBufferInit() function are CAN identifier 85 * and a pointer to callback function. Those two arguments (and some others) 86 * are copied to the member of the CO_CANrx_t array. 87 * 88 * Callback function is a function, specified by specific CANopen module 89 * (for example by @ref CO_HBconsumer). Each CANopen module defines own 90 * callback function. Callback function will process the received CAN message. 91 * It will copy the necessary data from CAN message to proper place. It may 92 * also trigger additional task, which will further process the received message. 93 * Callback function must be fast and must only make the necessary calculations 94 * and copying. 95 * 96 * Received CAN messages are processed by CAN receive interrupt function. 97 * After CAN message is received, function first tries to find matching CAN 98 * identifier from CO_CANrx_t array. If found, then a corresponding callback 99 * function is called. 100 * 101 * Callback function accepts two parameters: 102 * - object is pointer to object registered by CO_CANrxBufferInit(). 103 * - msg is pointer to CAN message of type CO_CANrxMsg_t. 104 * 105 * Callback function must return #CO_ReturnError_t: CO_ERROR_NO, 106 * CO_ERROR_RX_OVERFLOW, CO_ERROR_RX_PDO_OVERFLOW, CO_ERROR_RX_MSG_LENGTH or 107 * CO_ERROR_RX_PDO_LENGTH. 108 * 109 * 110 * ###Transmission of CAN messages. 111 * Before CAN messages can be transmitted, each member in CO_CANtx_t must be 112 * initialized. CO_CANtxBufferInit() is called by CANopen module, which 113 * uses specific member. For example Heartbeat producer must initialize it's 114 * member in CO_CANtx_t array. 115 * 116 * CO_CANtxBufferInit() returns a pointer of type CO_CANtx_t, which contains buffer 117 * where CAN message data can be written. CAN message is send with calling 118 * CO_CANsend() function. If at that moment CAN transmit buffer inside 119 * microcontroller's CAN module is free, message is copied directly to CAN module. 120 * Otherwise CO_CANsend() function sets _bufferFull_ flag to true. Message will be 121 * then sent by CAN TX interrupt as soon as CAN module is freed. Until message is 122 * not copied to CAN module, its contents must not change. There may be multiple 123 * _bufferFull_ flags in CO_CANtx_t array set to true. In that case messages with 124 * lower index inside array will be sent first. 125 */ 126 127 128 /** 129 * @name Critical sections 130 * CANopenNode is designed to run in different threads, as described in README. 131 * Threads are implemented differently in different systems. In microcontrollers 132 * threads are interrupts with different priorities, for example. 133 * It is necessary to protect sections, where different threads access to the 134 * same resource. In simple systems interrupts or scheduler may be temporary 135 * disabled between access to the shared resource. Otherwise mutexes or 136 * semaphores can be used. 137 * 138 * ####Reentrant functions. 139 * Functions CO_CANsend() from C_driver.h, CO_errorReport() from CO_Emergency.h 140 * and CO_errorReset() from CO_Emergency.h may be called from different threads. 141 * Critical sections must be protected. Eather by disabling scheduler or 142 * interrupts or by mutexes or semaphores. 143 * 144 * ####Object Dictionary variables. 145 * In general, there are two threads, which accesses OD variables: mainline and 146 * timer. CANopenNode initialization and SDO server runs in mainline. PDOs runs 147 * in faster timer thread. Processing of PDOs must not be interrupted by 148 * mainline. Mainline thread must protect sections, which accesses the same OD 149 * variables as timer thread. This care must also take the application. Note 150 * that not all variables are allowed to be mapped to PDOs, so they may not need 151 * to be protected. SDO server protects sections with access to OD variables. 152 * 153 * ####CAN receive thread. 154 * It partially processes received CAN data and puts them into appropriate 155 * objects. Objects are later processed. It does not need protection of 156 * critical sections. There is one circumstance, where CANrx should be disabled: 157 * After presence of SYNC message on CANopen bus, CANrx should be temporary 158 * disabled until all receive PDOs are processed. See also CO_SYNC.h file and 159 * CO_SYNC_initCallback() function. 160 * @{ 161 */ 162 #define CO_LOCK_CAN_SEND() /**< Lock critical section in CO_CANsend() */ 163 #define CO_UNLOCK_CAN_SEND()/**< Unlock critical section in CO_CANsend() */ 164 165 #define CO_LOCK_EMCY() /**< Lock critical section in CO_errorReport() or CO_errorReset() */ 166 #define CO_UNLOCK_EMCY() /**< Unlock critical section in CO_errorReport() or CO_errorReset() */ 167 168 #define CO_LOCK_OD() /**< Lock critical section when accessing Object Dictionary */ 169 #define CO_UNLOCK_OD() /**< Unock critical section when accessing Object Dictionary */ 170 /** @} */ 171 172 /** 173 * @name Synchronization functions 174 * synchronization for message buffer for communication between CAN receive and 175 * message processing threads. 176 * 177 * If receive function runs inside IRQ, no further synchronization is needed. 178 * Otherwise, some kind of synchronization has to be included. The following 179 * example uses GCC builtin memory barrier __sync_synchronize(). A comprehensive 180 * list can be found here: https://gist.github.com/leo-yuriev/ba186a6bf5cf3a27bae7 181 * \code{.c} 182 #define CANrxMemoryBarrier() __sync_synchronize() 183 * \endcode 184 * @{ 185 */ 186 /** Memory barrier */ 187 #define CANrxMemoryBarrier() 188 /** Check if new message has arrived */ 189 #define IS_CANrxNew(rxNew) ((uintptr_t)rxNew) 190 /** Set new message flag */ 191 #define SET_CANrxNew(rxNew) {CANrxMemoryBarrier(); rxNew = (void*)1L;} 192 /** Clear new message flag */ 193 #define CLEAR_CANrxNew(rxNew) {CANrxMemoryBarrier(); rxNew = (void*)0L;} 194 /** @} */ 195 196 /** 197 * @defgroup CO_dataTypes Data types 198 * @{ 199 * 200 * According to Misra C 201 */ 202 /* int8_t to uint64_t are defined in stdint.h */ 203 typedef unsigned char bool_t; /**< bool_t */ 204 typedef float float32_t; /**< float32_t */ 205 typedef long double float64_t; /**< float64_t */ 206 typedef char char_t; /**< char_t */ 207 typedef unsigned char oChar_t; /**< oChar_t */ 208 typedef unsigned char domain_t; /**< domain_t */ 209 /** @} */ 210 211 212 /** 213 * CAN receive message structure as aligned in CAN module. It is different in 214 * different microcontrollers. It usually contains other variables. 215 */ 216 typedef struct{ 217 /** CAN identifier. It must be read through CO_CANrxMsg_readIdent() function. */ 218 uint32_t ident; 219 uint8_t DLC ; /**< Length of CAN message */ 220 uint8_t data[8]; /**< 8 data bytes */ 221 }CO_CANrxMsg_t; 222 223 224 /** 225 * Received message object 226 */ 227 typedef struct{ 228 uint16_t ident; /**< Standard CAN Identifier (bits 0..10) + RTR (bit 11) */ 229 uint16_t mask; /**< Standard Identifier mask with same alignment as ident */ 230 void *object; /**< From CO_CANrxBufferInit() */ 231 void (*pFunct)(void *object, const CO_CANrxMsg_t *message); /**< From CO_CANrxBufferInit() */ 232 }CO_CANrx_t; 233 234 235 /** 236 * Transmit message object. 237 */ 238 typedef struct{ 239 uint32_t ident; /**< CAN identifier as aligned in CAN module */ 240 uint8_t DLC ; /**< Length of CAN message. (DLC may also be part of ident) */ 241 uint8_t data[8]; /**< 8 data bytes */ 242 volatile bool_t bufferFull; /**< True if previous message is still in buffer */ 243 /** Synchronous PDO messages has this flag set. It prevents them to be sent outside the synchronous window */ 244 volatile bool_t syncFlag; 245 }CO_CANtx_t; 246 247 248 /** 249 * CAN module object. It may be different in different microcontrollers. 250 */ 251 typedef struct{ 252 void *CANdriverState; /**< From CO_CANmodule_init() */ 253 CO_CANrx_t *rxArray; /**< From CO_CANmodule_init() */ 254 uint16_t rxSize; /**< From CO_CANmodule_init() */ 255 CO_CANtx_t *txArray; /**< From CO_CANmodule_init() */ 256 uint16_t txSize; /**< From CO_CANmodule_init() */ 257 volatile bool_t CANnormal; /**< CAN module is in normal mode */ 258 /** Value different than zero indicates, that CAN module hardware filters 259 * are used for CAN reception. If there is not enough hardware filters, 260 * they won't be used. In this case will be *all* received CAN messages 261 * processed by software. */ 262 volatile bool_t useCANrxFilters; 263 /** If flag is true, then message in transmitt buffer is synchronous PDO 264 * message, which will be aborted, if CO_clearPendingSyncPDOs() function 265 * will be called by application. This may be necessary if Synchronous 266 * window time was expired. */ 267 volatile bool_t bufferInhibitFlag; 268 /** Equal to 1, when the first transmitted message (bootup message) is in CAN TX buffers */ 269 volatile bool_t firstCANtxMessage; 270 /** Number of messages in transmit buffer, which are waiting to be copied to the CAN module */ 271 volatile uint16_t CANtxCount; 272 uint32_t errOld; /**< Previous state of CAN errors */ 273 void *em; /**< Emergency object */ 274 }CO_CANmodule_t; 275 276 277 /** 278 * Receives and transmits CAN messages. 279 * 280 * Function must be called directly from high priority CAN interrupt. 281 * 282 * @param CANmodule This object. 283 */ 284 void CO_CANinterrupt(CO_CANmodule_t *CANmodule); 285 286 #ifdef __cplusplus 287 } 288 #endif /* __cplusplus */ 289 290 /** @} */ 291 #endif /* CO_DRIVER_TARGET_H */ 292