1 /* 2 * CAN module object for Linux SocketCAN. 3 * 4 * @file CO_driver.h 5 * @author Janez Paternoster 6 * @copyright 2015 - 2020 Janez Paternoster 7 * 8 * This file is part of CANopenNode, an opensource CANopen Stack. 9 * Project home page is <https://github.com/CANopenNode/CANopenNode>. 10 * For more information on CANopen see <http://www.can-cia.org/>. 11 * 12 * Licensed under the Apache License, Version 2.0 (the "License"); 13 * you may not use this file except in compliance with the License. 14 * You may obtain a copy of the License at 15 * 16 * http://www.apache.org/licenses/LICENSE-2.0 17 * 18 * Unless required by applicable law or agreed to in writing, software 19 * distributed under the License is distributed on an "AS IS" BASIS, 20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 * See the License for the specific language governing permissions and 22 * limitations under the License. 23 */ 24 25 26 #ifndef CO_DRIVER_TARGET_H 27 #define CO_DRIVER_TARGET_H 28 29 30 /* For documentation see file drvTemplate/CO_driver.h */ 31 32 33 #include <stddef.h> /* for 'NULL' */ 34 #include <stdint.h> /* for 'int8_t' to 'uint64_t' */ 35 #include <stdbool.h> /* for 'true', 'false' */ 36 #include <unistd.h> 37 #include <endian.h> 38 39 #ifndef CO_SINGLE_THREAD 40 #include <pthread.h> 41 #endif 42 43 #include <linux/can.h> 44 #include <linux/can/raw.h> 45 #include <linux/can/error.h> 46 47 48 /* Endianness */ 49 #ifdef BYTE_ORDER 50 #if BYTE_ORDER == LITTLE_ENDIAN 51 #define CO_LITTLE_ENDIAN 52 #else 53 #define CO_BIG_ENDIAN 54 #endif /* BYTE_ORDER == LITTLE_ENDIAN */ 55 #endif /* BYTE_ORDER */ 56 57 58 /* general configuration */ 59 // #define CO_LOG_CAN_MESSAGES /* Call external function for each received or transmitted CAN message. */ 60 #define CO_SDO_BUFFER_SIZE 889 /* Override default SDO buffer size. */ 61 62 63 /* Critical sections */ 64 #ifdef CO_SINGLE_THREAD 65 #define CO_LOCK_CAN_SEND() 66 #define CO_UNLOCK_CAN_SEND() 67 68 #define CO_LOCK_EMCY() 69 #define CO_UNLOCK_EMCY() 70 71 #define CO_LOCK_OD() 72 #define CO_UNLOCK_OD() 73 74 #define CANrxMemoryBarrier() 75 #else 76 #define CO_LOCK_CAN_SEND() /* not needed */ 77 #define CO_UNLOCK_CAN_SEND() 78 79 extern pthread_mutex_t CO_EMCY_mtx; 80 #define CO_LOCK_EMCY() {if(pthread_mutex_lock(&CO_EMCY_mtx) != 0) CO_errExit("Mutex lock CO_EMCY_mtx failed");} 81 #define CO_UNLOCK_EMCY() {if(pthread_mutex_unlock(&CO_EMCY_mtx) != 0) CO_errExit("Mutex unlock CO_EMCY_mtx failed");} 82 83 extern pthread_mutex_t CO_OD_mtx; 84 #define CO_LOCK_OD() {if(pthread_mutex_lock(&CO_OD_mtx) != 0) CO_errExit("Mutex lock CO_OD_mtx failed");} 85 #define CO_UNLOCK_OD() {if(pthread_mutex_unlock(&CO_OD_mtx) != 0) CO_errExit("Mutex unlock CO_OD_mtx failed");} 86 87 #define CANrxMemoryBarrier() {__sync_synchronize();} 88 #endif /* CO_SINGLE_THREAD */ 89 90 /* Syncronisation functions */ 91 #define IS_CANrxNew(rxNew) ((uintptr_t)rxNew) 92 #define SET_CANrxNew(rxNew) {CANrxMemoryBarrier(); rxNew = (void*)1L;} 93 #define CLEAR_CANrxNew(rxNew) {CANrxMemoryBarrier(); rxNew = (void*)0L;} 94 95 96 /* Data types */ 97 /* int8_t to uint64_t are defined in stdint.h */ 98 typedef _Bool bool_t; 99 typedef float float32_t; 100 typedef double float64_t; 101 typedef char char_t; 102 typedef unsigned char oChar_t; 103 typedef unsigned char domain_t; 104 105 106 /* CAN receive message structure as aligned in CAN module. */ 107 typedef struct{ 108 uint32_t ident; 109 uint8_t DLC; 110 uint8_t data[8] __attribute__((aligned(8))); 111 }CO_CANrxMsg_t; 112 113 114 /* Received message object */ 115 typedef struct{ 116 uint32_t ident; 117 uint32_t mask; 118 void *object; 119 void (*pFunct)(void *object, const CO_CANrxMsg_t *message); 120 }CO_CANrx_t; 121 122 123 /* Transmit message object as aligned in CAN module. */ 124 typedef struct{ 125 uint32_t ident; 126 uint8_t DLC; 127 uint8_t data[8] __attribute__((aligned(8))); 128 volatile bool_t bufferFull; 129 volatile bool_t syncFlag; 130 }CO_CANtx_t; 131 132 133 /* CAN module object. */ 134 typedef struct{ 135 void *CANdriverState; 136 #ifdef CO_LOG_CAN_MESSAGES 137 CO_CANtx_t txRecord; 138 #endif 139 CO_CANrx_t *rxArray; 140 uint16_t rxSize; 141 CO_CANtx_t *txArray; 142 uint16_t txSize; 143 uint16_t wasConfigured;/* Zero only on first run of CO_CANmodule_init */ 144 int fd; /* CAN_RAW socket file descriptor */ 145 struct can_filter *filter; /* array of CAN filters of size rxSize */ 146 volatile bool_t CANnormal; 147 volatile bool_t useCANrxFilters; 148 volatile bool_t bufferInhibitFlag; 149 volatile bool_t firstCANtxMessage; 150 volatile uint8_t error; 151 volatile uint16_t CANtxCount; 152 uint32_t errOld; 153 void *em; 154 }CO_CANmodule_t; 155 156 /* Helper function, must be defined externally. */ 157 void CO_errExit(char* msg); 158 159 160 /* Functions receives CAN messages. It is blocking. 161 * 162 * @param CANmodule This object. 163 */ 164 void CO_CANrxWait(CO_CANmodule_t *CANmodule); 165 166 167 #endif /* CO_DRIVER_TARGET_H */ 168