1 /* 2 * CAN module object for Microchip PIC32MX microcontroller. 3 * 4 * @file CO_driver_target.h 5 * @author Janez Paternoster 6 * @copyright 2004 - 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 #include <p32xxxx.h> /* processor header file */ 31 #include <stddef.h> /* for 'NULL' */ 32 #include <stdint.h> /* for 'int8_t' to 'uint64_t' */ 33 #include <stdbool.h> /* for 'true', 'false' */ 34 35 /* Endianness */ 36 #define CO_LITTLE_ENDIAN 37 38 /* CAN module base address */ 39 #define ADDR_CAN1 0 40 #define ADDR_CAN2 (_CAN2_BASE_ADDRESS - _CAN1_BASE_ADDRESS) 41 42 43 /* Translate a kernel virtual address in KSEG0 or KSEG1 to a real 44 * physical address and back. */ 45 typedef unsigned long CO_paddr_t; /* a physical address */ 46 typedef unsigned long CO_vaddr_t; /* a virtual address */ 47 #define CO_KVA_TO_PA(v) ((CO_paddr_t)(v) & 0x1fffffff) 48 #define CO_PA_TO_KVA0(pa) ((void *) ((pa) | 0x80000000)) 49 #define CO_PA_TO_KVA1(pa) ((void *) ((pa) | 0xa0000000)) 50 51 52 /* Critical sections */ 53 extern unsigned int CO_interruptStatus; 54 #define CO_LOCK_CAN_SEND() CO_interruptStatus = __builtin_disable_interrupts() 55 #define CO_UNLOCK_CAN_SEND() if(CO_interruptStatus & 0x00000001) {__builtin_enable_interrupts();} 56 57 #define CO_LOCK_EMCY() CO_interruptStatus = __builtin_disable_interrupts() 58 #define CO_UNLOCK_EMCY() if(CO_interruptStatus & 0x00000001) {__builtin_enable_interrupts();} 59 60 #define CO_LOCK_OD() CO_interruptStatus = __builtin_disable_interrupts() 61 #define CO_UNLOCK_OD() if(CO_interruptStatus & 0x00000001) {__builtin_enable_interrupts();} 62 63 64 /* Data types */ 65 /* int8_t to uint64_t are defined in stdint.h */ 66 typedef unsigned char bool_t; 67 typedef float float32_t; 68 typedef long double float64_t; 69 typedef char char_t; 70 typedef unsigned char oChar_t; 71 typedef unsigned char domain_t; 72 73 74 /* CAN bit rates 75 * 76 * CAN bit rates are initializers for array of eight CO_CANbitRateData_t 77 * objects. 78 * 79 * Macros are not used by driver itself, they may be used by application with 80 * combination with object CO_CANbitRateData_t. 81 * Application must declare following global variable depending on CO_FSYS used: 82 * const CO_CANbitRateData_t CO_CANbitRateData[8] = {CO_CANbitRateDataInitializers}; 83 * 84 * There are initializers for eight objects, which corresponds to following 85 * CAN bit rates (in kbps): 10, 20, 50, 125, 250, 500, 800, 1000. 86 * 87 * CO_FSYS is internal instruction cycle clock frequency in kHz units. See 88 * PIC32MX documentation for more information on FSYS. 89 * 90 * Available values for FSYS: 91 * kbps = | 10 | 20 | 50 | 125 | 250 | 500 | 800 | 1000 92 * -------+----+----+----+-----+-----+-----+-----+----- 93 * 4 Mhz | O | O | O | O | p | - | - | - 94 * 8 Mhz | O | O | O | O | O | p | - | - 95 * 12 Mhz | O | O | O | O | p | p | - | - 96 * 16 Mhz | O | O | O | O | O | O | p | p 97 * 20 Mhz | O | O | O | O | O | O | - | p 98 * 24 Mhz | O | O | O | O | O | p | O | p 99 * 32 Mhz | p | O | O | O | O | O | p | O 100 * 36 Mhz | - | O | O | O | O | O | - | O 101 * 40 Mhz | - | O | O | O | O | O | p | O 102 * 48 Mhz | - | O | O | O | O | O | O | p 103 * 56 Mhz | - | p | O | O | O | p | (p) | p 104 * 64 Mhz | - | p | O | O | O | O | O | O 105 * 72 Mhz | - | - | O | O | O | O | O | O 106 * 80 Mhz | - | - | O | O | O | O | p | O 107 * ---------------------------------------------------- 108 * (O=optimal; p=possible; -=not possible) 109 */ 110 #ifdef CO_FSYS 111 /* Macros, which divides K into (SJW + PROP + PhSeg1 + PhSeg2) */ 112 #define TQ_x_7 1, 2, 3, 1 113 #define TQ_x_8 1, 2, 3, 2 114 #define TQ_x_9 1, 2, 4, 2 115 #define TQ_x_10 1, 3, 4, 2 116 #define TQ_x_12 1, 3, 6, 2 117 #define TQ_x_14 1, 4, 7, 2 118 #define TQ_x_15 1, 4, 8, 2 /* good timing */ 119 #define TQ_x_16 1, 5, 8, 2 /* good timing */ 120 #define TQ_x_17 1, 6, 8, 2 /* good timing */ 121 #define TQ_x_18 1, 7, 8, 2 /* good timing */ 122 #define TQ_x_19 1, 8, 8, 2 /* good timing */ 123 #define TQ_x_20 1, 8, 8, 3 /* good timing */ 124 #define TQ_x_21 1, 8, 8, 4 125 #define TQ_x_22 1, 8, 8, 5 126 #define TQ_x_23 1, 8, 8, 6 127 #define TQ_x_24 1, 8, 8, 7 128 #define TQ_x_25 1, 8, 8, 8 129 130 #if CO_FSYS == 4000 131 #define CO_CANbitRateDataInitializers \ 132 {10, TQ_x_20}, /*CAN=10kbps*/ \ 133 {5, TQ_x_20}, /*CAN=20kbps*/ \ 134 {2, TQ_x_20}, /*CAN=50kbps*/ \ 135 {1, TQ_x_16}, /*CAN=125kbps*/ \ 136 {1, TQ_x_8 }, /*CAN=250kbps*/ \ 137 {1, TQ_x_8 }, /*Not possible*/ \ 138 {1, TQ_x_8 }, /*Not possible*/ \ 139 {1, TQ_x_8 } /*Not possible*/ 140 #elif CO_FSYS == 8000 141 #define CO_CANbitRateDataInitializers \ 142 {25, TQ_x_16}, /*CAN=10kbps*/ \ 143 {10, TQ_x_20}, /*CAN=20kbps*/ \ 144 {5, TQ_x_16}, /*CAN=50kbps*/ \ 145 {2, TQ_x_16}, /*CAN=125kbps*/ \ 146 {1, TQ_x_16}, /*CAN=250kbps*/ \ 147 {1, TQ_x_8 }, /*CAN=500kbps*/ \ 148 {1, TQ_x_8 }, /*Not possible*/ \ 149 {1, TQ_x_8 } /*Not possible*/ 150 #elif CO_FSYS == 12000 151 #define CO_CANbitRateDataInitializers \ 152 {40, TQ_x_15}, /*CAN=10kbps*/ \ 153 {20, TQ_x_15}, /*CAN=20kbps*/ \ 154 {8, TQ_x_15}, /*CAN=50kbps*/ \ 155 {3, TQ_x_16}, /*CAN=125kbps*/ \ 156 {2, TQ_x_12}, /*CAN=250kbps*/ \ 157 {1, TQ_x_12}, /*CAN=500kbps*/ \ 158 {1, TQ_x_12}, /*Not possible*/ \ 159 {1, TQ_x_12} /*Not possible*/ 160 #elif CO_FSYS == 16000 161 #define CO_CANbitRateDataInitializers \ 162 {50, TQ_x_16}, /*CAN=10kbps*/ \ 163 {25, TQ_x_16}, /*CAN=20kbps*/ \ 164 {10, TQ_x_16}, /*CAN=50kbps*/ \ 165 {4, TQ_x_16}, /*CAN=125kbps*/ \ 166 {2, TQ_x_16}, /*CAN=250kbps*/ \ 167 {1, TQ_x_16}, /*CAN=500kbps*/ \ 168 {1, TQ_x_10}, /*CAN=800kbps*/ \ 169 {1, TQ_x_8 } /*CAN=1000kbps*/ 170 #elif CO_FSYS == 20000 171 #define CO_CANbitRateDataInitializers \ 172 {50, TQ_x_20}, /*CAN=10kbps*/ \ 173 {25, TQ_x_20}, /*CAN=20kbps*/ \ 174 {10, TQ_x_20}, /*CAN=50kbps*/ \ 175 {5, TQ_x_16}, /*CAN=125kbps*/ \ 176 {2, TQ_x_20}, /*CAN=250kbps*/ \ 177 {1, TQ_x_20}, /*CAN=500kbps*/ \ 178 {1, TQ_x_20}, /*Not possible*/ \ 179 {1, TQ_x_10} /*CAN=1000kbps*/ 180 #elif CO_FSYS == 24000 181 #define CO_CANbitRateDataInitializers \ 182 {63, TQ_x_19}, /*CAN=10kbps*/ \ 183 {40, TQ_x_15}, /*CAN=20kbps*/ \ 184 {15, TQ_x_16}, /*CAN=50kbps*/ \ 185 {6, TQ_x_16}, /*CAN=125kbps*/ \ 186 {3, TQ_x_16}, /*CAN=250kbps*/ \ 187 {2, TQ_x_12}, /*CAN=500kbps*/ \ 188 {1, TQ_x_15}, /*CAN=800kbps*/ \ 189 {1, TQ_x_12} /*CAN=1000kbps*/ 190 #elif CO_FSYS == 32000 191 #define CO_CANbitRateDataInitializers \ 192 {64, TQ_x_25}, /*CAN=10kbps*/ \ 193 {50, TQ_x_16}, /*CAN=20kbps*/ \ 194 {20, TQ_x_16}, /*CAN=50kbps*/ \ 195 {8, TQ_x_16}, /*CAN=125kbps*/ \ 196 {4, TQ_x_16}, /*CAN=250kbps*/ \ 197 {2, TQ_x_16}, /*CAN=500kbps*/ \ 198 {2, TQ_x_10}, /*CAN=800kbps*/ \ 199 {1, TQ_x_16} /*CAN=1000kbps*/ 200 #elif CO_FSYS == 36000 201 #define CO_CANbitRateDataInitializers \ 202 {50, TQ_x_18}, /*CAN=10kbps*/ \ 203 {50, TQ_x_18}, /*CAN=20kbps*/ \ 204 {20, TQ_x_18}, /*CAN=50kbps*/ \ 205 {8, TQ_x_18}, /*CAN=125kbps*/ \ 206 {4, TQ_x_18}, /*CAN=250kbps*/ \ 207 {2, TQ_x_18}, /*CAN=500kbps*/ \ 208 {2, TQ_x_18}, /*Not possible*/ \ 209 {1, TQ_x_18} /*CAN=1000kbps*/ 210 #elif CO_FSYS == 40000 211 #define CO_CANbitRateDataInitializers \ 212 {50, TQ_x_20}, /*Not possible*/ \ 213 {50, TQ_x_20}, /*CAN=20kbps*/ \ 214 {25, TQ_x_16}, /*CAN=50kbps*/ \ 215 {10, TQ_x_16}, /*CAN=125kbps*/ \ 216 {5, TQ_x_16}, /*CAN=250kbps*/ \ 217 {2, TQ_x_20}, /*CAN=500kbps*/ \ 218 {1, TQ_x_25}, /*CAN=800kbps*/ \ 219 {1, TQ_x_20} /*CAN=1000kbps*/ 220 #elif CO_FSYS == 48000 221 #define CO_CANbitRateDataInitializers \ 222 {63, TQ_x_19}, /*Not possible*/ \ 223 {63, TQ_x_19}, /*CAN=20kbps*/ \ 224 {30, TQ_x_16}, /*CAN=50kbps*/ \ 225 {12, TQ_x_16}, /*CAN=125kbps*/ \ 226 {6, TQ_x_16}, /*CAN=250kbps*/ \ 227 {3, TQ_x_16}, /*CAN=500kbps*/ \ 228 {2, TQ_x_15}, /*CAN=800kbps*/ \ 229 {2, TQ_x_12} /*CAN=1000kbps*/ 230 #elif CO_FSYS == 56000 231 #define CO_CANbitRateDataInitializers \ 232 {61, TQ_x_23}, /*Not possible*/ \ 233 {61, TQ_x_23}, /*CAN=20kbps*/ \ 234 {35, TQ_x_16}, /*CAN=50kbps*/ \ 235 {14, TQ_x_16}, /*CAN=125kbps*/ \ 236 {7, TQ_x_16}, /*CAN=250kbps*/ \ 237 {4, TQ_x_14}, /*CAN=500kbps*/ \ 238 {5, TQ_x_7 }, /*CAN=800kbps*/ \ 239 {2, TQ_x_14} /*CAN=1000kbps*/ 240 #elif CO_FSYS == 64000 241 #define CO_CANbitRateDataInitializers \ 242 {64, TQ_x_25}, /*Not possible*/ \ 243 {64, TQ_x_25}, /*CAN=20kbps*/ \ 244 {40, TQ_x_16}, /*CAN=50kbps*/ \ 245 {16, TQ_x_16}, /*CAN=125kbps*/ \ 246 {8, TQ_x_16}, /*CAN=250kbps*/ \ 247 {4, TQ_x_16}, /*CAN=500kbps*/ \ 248 {2, TQ_x_20}, /*CAN=800kbps*/ \ 249 {2, TQ_x_16} /*CAN=1000kbps*/ 250 #elif CO_FSYS == 72000 251 #define CO_CANbitRateDataInitializers \ 252 {40, TQ_x_18}, /*Not possible*/ \ 253 {40, TQ_x_18}, /*Not possible*/ \ 254 {40, TQ_x_18}, /*CAN=50kbps*/ \ 255 {16, TQ_x_18}, /*CAN=125kbps*/ \ 256 {8, TQ_x_18}, /*CAN=250kbps*/ \ 257 {4, TQ_x_18}, /*CAN=500kbps*/ \ 258 {3, TQ_x_15}, /*CAN=800kbps*/ \ 259 {2, TQ_x_18} /*CAN=1000kbps*/ 260 #elif CO_FSYS == 80000 261 #define CO_CANbitRateDataInitializers \ 262 {40, TQ_x_20}, /*Not possible*/ \ 263 {40, TQ_x_20}, /*Not possible*/ \ 264 {40, TQ_x_20}, /*CAN=50kbps*/ \ 265 {16, TQ_x_20}, /*CAN=125kbps*/ \ 266 {8, TQ_x_20}, /*CAN=250kbps*/ \ 267 {4, TQ_x_20}, /*CAN=500kbps*/ \ 268 {2, TQ_x_25}, /*CAN=800kbps*/ \ 269 {2, TQ_x_20} /*CAN=1000kbps*/ 270 #else 271 #error define_CO_FSYS CO_FSYS not supported 272 #endif 273 #endif 274 275 276 /* Structure contains timing coefficients for CAN module. 277 * 278 * CAN baud rate is calculated from following equations: 279 * Fsys - System clock (MAX 80MHz for PIC32MX) 280 * TQ = 2 * BRP / Fsys - Time Quanta 281 * BaudRate = 1 / (TQ * K) - Can bus Baud Rate 282 * K = SJW + PROP + PhSeg1 + PhSeg2 - Number of Time Quantas 283 */ 284 typedef struct{ 285 uint8_t BRP; /* (1...64) Baud Rate Prescaler */ 286 uint8_t SJW; /* (1...4) SJW time */ 287 uint8_t PROP; /* (1...8) PROP time */ 288 uint8_t phSeg1; /* (1...8) Phase Segment 1 time */ 289 uint8_t phSeg2; /* (1...8) Phase Segment 2 time */ 290 }CO_CANbitRateData_t; 291 292 293 /* CAN receive message structure as aligned in CAN module. */ 294 typedef struct{ 295 unsigned ident :11; /* Standard Identifier */ 296 unsigned FILHIT :5; /* Filter hit, see PIC32MX documentation */ 297 unsigned CMSGTS :16; /* CAN message timestamp, see PIC32MX documentation */ 298 unsigned DLC :4; /* Data length code (bits 0...3) */ 299 unsigned :5; 300 unsigned RTR :1; /* Remote Transmission Request bit */ 301 unsigned :22; 302 uint8_t data[8]; /* 8 data bytes */ 303 }CO_CANrxMsg_t; 304 305 306 /* Received message object */ 307 typedef struct{ 308 uint16_t ident; 309 uint16_t mask; 310 void *object; 311 void (*pFunct)(void *object, const CO_CANrxMsg_t *message); 312 }CO_CANrx_t; 313 314 315 /* Transmit message object. */ 316 typedef struct{ 317 uint32_t CMSGSID; /* Equal to register in transmit message buffer. Includes standard Identifier */ 318 uint32_t CMSGEID; /* Equal to register in transmit message buffer. Includes data length code and RTR */ 319 uint8_t data[8]; 320 volatile bool_t bufferFull; 321 volatile bool_t syncFlag; 322 }CO_CANtx_t; 323 324 325 /* CAN module object. */ 326 typedef struct{ 327 void *CANdriverState; 328 CO_CANrxMsg_t CANmsgBuff[33]; /* PIC32 specific: CAN message buffer for CAN module. 32 buffers for receive, 1 buffer for transmit */ 329 uint8_t CANmsgBuffSize; /* PIC32 specific: Size of the above buffer == 33. Take care initial value! */ 330 CO_CANrx_t *rxArray; 331 uint16_t rxSize; 332 CO_CANtx_t *txArray; 333 uint16_t txSize; 334 volatile bool_t CANnormal; 335 volatile bool_t useCANrxFilters; 336 volatile bool_t bufferInhibitFlag; 337 volatile bool_t firstCANtxMessage; 338 volatile uint16_t CANtxCount; 339 uint32_t errOld; 340 void *em; 341 }CO_CANmodule_t; 342 343 344 /* CAN interrupt receives and transmits CAN messages. 345 * 346 * Function must be called directly from _C1Interrupt or _C2Interrupt with 347 * high priority. 348 */ 349 void CO_CANinterrupt(CO_CANmodule_t *CANmodule); 350 351 352 #endif /* CO_DRIVER_TARGET_H */ 353