1 /** 2 * CAN module object for Linux socketCAN. 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, Martin Wagner 9 * @copyright 2004 - 2015 Janez Paternoster, 2017 - 2020 Neuberger Gebaeudeautomation GmbH 10 * 11 * 12 * This file is part of CANopenNode, an opensource CANopen Stack. 13 * Project home page is <https://github.com/CANopenNode/CANopenNode>. 14 * For more information on CANopen see <http://www.can-cia.org/>. 15 * 16 * Licensed under the Apache License, Version 2.0 (the "License"); 17 * you may not use this file except in compliance with the License. 18 * You may obtain a copy of the License at 19 * 20 * http://www.apache.org/licenses/LICENSE-2.0 21 * 22 * Unless required by applicable law or agreed to in writing, software 23 * distributed under the License is distributed on an "AS IS" BASIS, 24 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 25 * See the License for the specific language governing permissions and 26 * limitations under the License. 27 */ 28 29 30 #ifndef CO_DRIVER_TARGET_H 31 #define CO_DRIVER_TARGET_H 32 33 #ifdef __cplusplus 34 extern "C" { 35 #endif /* __cplusplus */ 36 37 38 /** 39 * @name multi interface support 40 * 41 * Enable this to use interface combining at driver level. This 42 * adds functions to broadcast/selective transmit messages on the 43 * given interfaces as well as combining all received message into 44 * one queue. 45 * 46 * This is not intended to realize interface redundancy!!! 47 */ 48 //#define CO_DRIVER_MULTI_INTERFACE 49 50 /** 51 * @name CAN bus error reporting 52 * 53 * Enable this to add support for socketCAN error detection- and 54 * handling functions inside the driver. This is needed when you have 55 * CANopen with "0" connected nodes as a use case, as this is normally 56 * forbidden in CAN. 57 * 58 * you need to enable error reporting in your kernel driver using 59 * "ip link set canX type can berr-reporting on". Of course, the kernel 60 * driver for your hardware needs this functionallity to be implemented... 61 */ 62 //#define CO_DRIVER_ERROR_REPORTING 63 64 65 #include "CO_driver_base.h" 66 #include "CO_notify_pipe.h" 67 68 #ifdef CO_DRIVER_ERROR_REPORTING 69 #include "CO_error.h" 70 #endif /* CO_DRIVER_ERROR_REPORTING */ 71 72 /** 73 * socketCAN interface object 74 */ 75 typedef struct { 76 const void *CANdriverState; /**< CAN Interface identifier */ 77 char ifName[IFNAMSIZ]; /**< CAN Interface name */ 78 int fd; /**< socketCAN file descriptor */ 79 #ifdef CO_DRIVER_ERROR_REPORTING 80 CO_CANinterfaceErrorhandler_t errorhandler; 81 #endif 82 } CO_CANinterface_t; 83 84 /** 85 * CAN module object. It may be different in different microcontrollers. 86 */ 87 typedef struct{ 88 /** List of can interfaces. From CO_CANmodule_init()/ one per CO_CANmodule_addInterface() call */ 89 CO_CANinterface_t *CANinterfaces; 90 uint32_t CANinterfaceCount; /** interface count */ 91 CO_CANrx_t *rxArray; /**< From CO_CANmodule_init() */ 92 uint16_t rxSize; /**< From CO_CANmodule_init() */ 93 struct can_filter *rxFilter; /**< socketCAN filter list, one per rx buffer */ 94 uint32_t rxDropCount; /**< messages dropped on rx socket queue */ 95 CO_CANtx_t *txArray; /**< From CO_CANmodule_init() */ 96 uint16_t txSize; /**< From CO_CANmodule_init() */ 97 volatile bool_t CANnormal; /**< CAN module is in normal mode */ 98 void *em; /**< Emergency object */ 99 CO_NotifyPipe_t *pipe; /**< Notification Pipe */ 100 int fdEpoll; /**< epoll FD */ 101 int fdTimerRead; /**< timer handle from CANrxWait() */ 102 #ifdef CO_DRIVER_MULTI_INTERFACE 103 /** 104 * Lookup tables Cob ID to rx/tx array index. Only feasible for SFF Messages. 105 */ 106 uint32_t rxIdentToIndex[CO_CAN_MSG_SFF_MAX_COB_ID]; /**< COB ID to index assignment */ 107 uint32_t txIdentToIndex[CO_CAN_MSG_SFF_MAX_COB_ID]; /**< COB ID to index assignment */ 108 #endif /* CO_DRIVER_MULTI_INTERFACE */ 109 }CO_CANmodule_t; 110 111 112 #ifdef CO_DRIVER_MULTI_INTERFACE 113 /** 114 * Initialize CAN module object 115 * 116 * Function must be called in the communication reset section. CAN module must 117 * be in Configuration Mode before. 118 * 119 * @param CANmodule This object will be initialized. 120 * @param CANdriverState unused 121 * @param rxArray Array for handling received CAN messages 122 * @param rxSize Size of the above array. Must be equal to number of receiving CAN objects. 123 * @param txArray Array for handling transmitting CAN messages 124 * @param txSize Size of the above array. Must be equal to number of transmitting CAN objects. 125 * @param CANbitRate not supported in this driver. Needs to be set by OS 126 * 127 * @return #CO_ReturnError_t: CO_ERROR_NO, CO_ERROR_ILLEGAL_ARGUMENT. 128 */ 129 #else 130 /** 131 * Initialize CAN module object and open socketCAN connection. 132 * 133 * Function must be called in the communication reset section. CAN module must 134 * be in Configuration Mode before. 135 * 136 * @param CANmodule This object will be initialized. 137 * @param CANdriverState CAN module interface index (return value if_nametoindex(), NO pointer!). 138 * @param rxArray Array for handling received CAN messages 139 * @param rxSize Size of the above array. Must be equal to number of receiving CAN objects. 140 * @param txArray Array for handling transmitting CAN messages 141 * @param txSize Size of the above array. Must be equal to number of transmitting CAN objects. 142 * @param CANbitRate not supported in this driver. Needs to be set by OS 143 * 144 * @return #CO_ReturnError_t: CO_ERROR_NO, CO_ERROR_ILLEGAL_ARGUMENT or 145 * CO_ERROR_SYSCALL. 146 */ 147 #endif /* CO_DRIVER_MULTI_INTERFACE */ 148 CO_ReturnError_t CO_CANmodule_init( 149 CO_CANmodule_t *CANmodule, 150 void *CANdriverState, 151 CO_CANrx_t rxArray[], 152 uint16_t rxSize, 153 CO_CANtx_t txArray[], 154 uint16_t txSize, 155 uint16_t CANbitRate); 156 157 #ifdef CO_DRIVER_MULTI_INTERFACE 158 159 /** 160 * Add socketCAN interface to can driver 161 * 162 * Function must be called after CO_CANmodule_init. 163 * 164 * @param CANmodule This object will be initialized. 165 * @param CANdriverState CAN module interface index (return value if_nametoindex(), NO pointer!). 166 * @return #CO_ReturnError_t: CO_ERROR_NO, CO_ERROR_ILLEGAL_ARGUMENT, 167 * CO_ERROR_SYSCALL or CO_ERROR_INVALID_STATE. 168 */ 169 CO_ReturnError_t CO_CANmodule_addInterface( 170 CO_CANmodule_t *CANmodule, 171 const void *CANdriverState); 172 173 #endif /* CO_DRIVER_MULTI_INTERFACE */ 174 175 176 /** 177 * Configure CAN message receive buffer. 178 * 179 * Function configures specific CAN receive buffer. It sets CAN identifier 180 * and connects buffer with specific object. Function must be called for each 181 * member in _rxArray_ from CO_CANmodule_t. 182 * 183 * @param CANmodule This object. 184 * @param index Index of the specific buffer in _rxArray_. 185 * @param ident 11-bit standard CAN Identifier. 186 * @param mask 11-bit mask for identifier. Most usually set to 0x7FF. 187 * Received message (rcvMsg) will be accepted if the following 188 * condition is true: (((rcvMsgId ^ ident) & mask) == 0). 189 * @param rtr If true, 'Remote Transmit Request' messages will be accepted. 190 * @param object CANopen object, to which buffer is connected. It will be used as 191 * an argument to pFunct. Its type is (void), pFunct will change its 192 * type back to the correct object type. 193 * @param pFunct Pointer to function, which will be called, if received CAN 194 * message matches the identifier. It must be fast function. 195 * 196 * @return #CO_ReturnError_t: CO_ERROR_NO CO_ERROR_ILLEGAL_ARGUMENT or 197 * CO_ERROR_OUT_OF_MEMORY (not enough masks for configuration). 198 */ 199 CO_ReturnError_t CO_CANrxBufferInit( 200 CO_CANmodule_t *CANmodule, 201 uint16_t index, 202 uint16_t ident, 203 uint16_t mask, 204 bool_t rtr, 205 void *object, 206 void (*pFunct)(void *object, const CO_CANrxMsg_t *message)); 207 208 #ifdef CO_DRIVER_MULTI_INTERFACE 209 210 /** 211 * Check on which interface the last message for one message buffer was received 212 * 213 * It is in the responsibility of the user to check that this information is 214 * useful as some messages can be received at any time on any bus. 215 * 216 * @param CANmodule This object. 217 * @param ident 11-bit standard CAN Identifier. 218 * @param [out] CANdriverStateRx message was received on this interface 219 * @param [out] timestamp message was received at this time (system clock) 220 * 221 * @retval false message has never been received, therefore no base address 222 * and timestamp are available 223 * @retval true base address and timestamp are valid 224 */ 225 bool_t CO_CANrxBuffer_getInterface( 226 CO_CANmodule_t *CANmodule, 227 uint16_t ident, 228 const void **const CANdriverStateRx, 229 struct timespec *timestamp); 230 231 /** 232 * Set which interface should be used for message buffer transmission 233 * 234 * It is in the responsibility of the user to ensure that the correct interface 235 * is used. Some messages need to be transmitted on all interfaces. 236 * 237 * If given interface is unknown or NULL is used, a message is transmitted on 238 * all available interfaces. 239 * 240 * @param CANmodule This object. 241 * @param ident 11-bit standard CAN Identifier. 242 * @param CANdriverStateTx use this interface. NULL = not specified 243 * 244 * @return #CO_ReturnError_t: CO_ERROR_NO or CO_ERROR_ILLEGAL_ARGUMENT. 245 */ 246 CO_ReturnError_t CO_CANtxBuffer_setInterface( 247 CO_CANmodule_t *CANmodule, 248 uint16_t ident, 249 const void *CANdriverStateTx); 250 251 #endif /* CO_DRIVER_MULTI_INTERFACE */ 252 253 254 /** 255 * The same as #CO_CANsend(), but ensures that there is enough space remaining 256 * in the driver for more important messages. 257 * 258 * The default threshold is 50%, or at least 1 message buffer. If sending 259 * would violate those limits, #CO_ERROR_TX_OVERFLOW is returned and the 260 * message will not be sent. 261 * 262 * @param CANmodule This object. 263 * @param buffer Pointer to transmit buffer, returned by CO_CANtxBufferInit(). 264 * Data bytes must be written in buffer before function call. 265 * 266 * @return #CO_ReturnError_t: CO_ERROR_NO, CO_ERROR_TX_OVERFLOW, CO_ERROR_TX_BUSY or 267 * CO_ERROR_TX_PDO_WINDOW (Synchronous TPDO is outside window). 268 */ 269 CO_ReturnError_t CO_CANCheckSend(CO_CANmodule_t *CANmodule, CO_CANtx_t *buffer); 270 271 272 /** 273 * Functions receives CAN messages. It is blocking. 274 * 275 * This function can be used in two ways 276 * - automatic mode (call callback that is set by #CO_CANrxBufferInit() function) 277 * - manual mode (evaluate message filters, return received message) 278 * 279 * Both modes can be combined. 280 * 281 * @param CANmodule This object. 282 * @param fdTimer file descriptor with activated timeout. fd is not read after 283 * expiring! -1 if not used. 284 * @param buffer [out] storage for received message or _NULL_ 285 * @retval >= 0 index of received message in array set by #CO_CANmodule_init() 286 * _rxArray_, copy available in _buffer_ 287 * @retval -1 no message received 288 */ 289 int32_t CO_CANrxWait(CO_CANmodule_t *CANmodule, int fdTimer, CO_CANrxMsg_t *buffer); 290 291 #ifdef __cplusplus 292 } 293 #endif /* __cplusplus */ 294 295 /** @} */ 296 #endif 297