1 /*
2  * CAN module object for Microchip dsPIC33 or PIC24 microcontroller.
3  *
4  * @file        CO_driver_target.h
5  * @author      Janez Paternoster
6  * @author      Peter Rozsahegyi (EDS)
7  * @author      Jens Nielsen (CAN receive)
8  * @copyright   2004 - 2020 Janez Paternoster
9  *
10  * This file is part of CANopenNode, an opensource CANopen Stack.
11  * Project home page is <https://github.com/CANopenNode/CANopenNode>.
12  * For more information on CANopen see <http://www.can-cia.org/>.
13  *
14  * Licensed under the Apache License, Version 2.0 (the "License");
15  * you may not use this file except in compliance with the License.
16  * You may obtain a copy of the License at
17  *
18  *     http://www.apache.org/licenses/LICENSE-2.0
19  *
20  * Unless required by applicable law or agreed to in writing, software
21  * distributed under the License is distributed on an "AS IS" BASIS,
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23  * See the License for the specific language governing permissions and
24  * limitations under the License.
25  */
26 
27 
28 #ifndef CO_DRIVER_TARGET_H
29 #define CO_DRIVER_TARGET_H
30 
31 
32 #if defined(__dsPIC33F__) || defined(__PIC24H__)
33 #include <p33Fxxxx.h>       /* processor header file */
34 #elif defined(__dsPIC33E__) || defined(__PIC24E__)
35 #include <p33Exxxx.h>       /* processor header file */
36 #endif
37 #include <stddef.h>         /* for 'NULL' */
38 #include <stdint.h>         /* for 'int8_t' to 'uint64_t' */
39 #include <stdbool.h>        /* for 'true' and 'false' */
40 
41 /* Endianness */
42 #define CO_LITTLE_ENDIAN
43 
44 /* CAN message buffer sizes for CAN module 1 and 2. Valid values
45  * are 0, 4, 6, 8, 12, 16. Default is one TX and seven RX messages (FIFO). */
46 #ifndef CO_CAN1msgBuffSize
47     #define CO_CAN1msgBuffSize   8
48 #endif /* CO_CAN1msgBuffSize */
49 #ifndef CO_CAN2msgBuffSize
50     #define CO_CAN2msgBuffSize   0  //CAN module 2 not used by default
51 #endif /* CO_CAN2msgBuffSize */
52 
53 
54 /* Default DMA addresses for CAN modules. */
55 #ifndef CO_CAN1_DMA0
56     #define CO_CAN1_DMA0 ADDR_DMA0
57 #endif /* CO_CAN1_DMA0 */
58 #ifndef CO_CAN1_DMA1
59     #define CO_CAN1_DMA1 ADDR_DMA1
60 #endif /* CO_CAN1_DMA1 */
61 #ifndef CO_CAN2_DMA0
62     #define CO_CAN2_DMA0 ADDR_DMA2
63 #endif /* CO_CAN2_DMA0 */
64 #ifndef CO_CAN2_DMA1
65     #define CO_CAN2_DMA1 ADDR_DMA3
66 #endif /* CO_CAN2_DMA1 */
67 
68 
69 /* Define DMA attribute on supported platforms */
70 #if defined(__dsPIC33F__) || defined(__PIC24H__) || defined(__DMA_BASE)
71     #define __dma  __attribute__((space(dma)))
72 #else
73     #define __dma
74     #if defined(__C30_VERSION__) && !defined(__XC16_VERSION__)
75         #define __builtin_dmaoffset(V)  (uint16_t)V
76     #endif
77 #endif
78 
79 /* Define EDS attribute on supported platforms */
80 #if defined(__HAS_EDS__)
81     #define __eds __attribute__((eds))
82     #if defined(__C30_VERSION__) && !defined(__XC16_VERSION__)
83         #define __builtin_dmapage(V)  (uint16_t)0
84     #endif
85 #else
86     #define __eds
87     #define __eds__
88 #endif
89 
90 
91 /* CAN module base addresses */
92 #define ADDR_CAN1               ((uint16_t)&C1CTRL1)
93 #define ADDR_CAN2               ((uint16_t)&C2CTRL1)
94 
95 /* DMA addresses */
96 #define ADDR_DMA0               ((uint16_t)&DMA0CON)
97 #define ADDR_DMA1               ((uint16_t)&DMA1CON)
98 #define ADDR_DMA2               ((uint16_t)&DMA2CON)
99 #define ADDR_DMA3               ((uint16_t)&DMA3CON)
100 #define ADDR_DMA4               ((uint16_t)&DMA4CON)
101 #define ADDR_DMA5               ((uint16_t)&DMA5CON)
102 #define ADDR_DMA6               ((uint16_t)&DMA6CON)
103 #define ADDR_DMA7               ((uint16_t)&DMA7CON)
104 
105 
106 /* Critical sections */
107 #define CO_LOCK_CAN_SEND()      asm volatile ("disi #0x3FFF")
108 #define CO_UNLOCK_CAN_SEND()    asm volatile ("disi #0x0000")
109 
110 #define CO_LOCK_EMCY()          asm volatile ("disi #0x3FFF")
111 #define CO_UNLOCK_EMCY()        asm volatile ("disi #0x0000")
112 
113 #define CO_LOCK_OD()            asm volatile ("disi #0x3FFF")
114 #define CO_UNLOCK_OD()          asm volatile ("disi #0x0000")
115 
116 #define CO_DISABLE_INTERRUPTS()  asm volatile ("disi #0x3FFF")
117 #define CO_ENABLE_INTERRUPTS()   asm volatile ("disi #0x0000")
118 
119 
120 /* Data types */
121 /* int8_t to uint64_t are defined in stdint.h */
122 typedef unsigned char           bool_t;
123 typedef float                   float32_t;
124 typedef long double             float64_t;
125 typedef char                    char_t;
126 typedef unsigned char           oChar_t;
127 typedef unsigned char           domain_t;
128 
129 
130 /* CAN bit rates
131  *
132  * CAN bit rates are initializers for array of eight CO_CANbitRateData_t
133  * objects.
134  *
135  * Macros are not used by driver itself, they may be used by application with
136  * combination with object CO_CANbitRateData_t.
137  * Application must declare following global variable depending on CO_FCY used:
138  * const CO_CANbitRateData_t  CO_CANbitRateData[8] = {CO_CANbitRateDataInitializers};
139  *
140  * There are initializers for eight objects, which corresponds to following
141  * CAN bit rates (in kbps): 10, 20, 50, 125, 250, 500, 800, 1000.
142  *
143  * CO_FCY is internal instruction cycle clock frequency in kHz units. See
144  * dsPIC33F documentation for more information on FCY.
145  *
146  * Possible values for FCY are (in three groups):
147  *     - Optimal CAN bit timing on all Baud Rates: 8000, 12000, 16000, 24000.
148  *     - Not so optimal CAN bit timing on all Baud Rates: 4000, 32000.
149  *     - not all CANopen Baud Rates possible: 2000, 3000, 5000, 6000, 10000,
150  *       20000, 40000, 48000, 56000, 64000, 70000.
151  *
152  * IMPORTANT: For FCY<=12000 there is unresolved bug; CANCKS configuration
153  *               bit on ECAN does not work, so some baudrates are not possible.
154  */
155 #ifdef CO_FCY
156     /* Macros, which divides K into (SJW + PROP + PhSeg1 + PhSeg2) */
157     #define TQ_x_4    1, 1, 1, 1
158     #define TQ_x_5    1, 1, 2, 1
159     #define TQ_x_6    1, 1, 3, 1
160     #define TQ_x_8    1, 2, 3, 2
161     #define TQ_x_9    1, 2, 4, 2
162     #define TQ_x_10   1, 3, 4, 2
163     #define TQ_x_12   1, 3, 6, 2
164     #define TQ_x_14   1, 4, 7, 2
165     #define TQ_x_15   1, 4, 8, 2  /* good timing */
166     #define TQ_x_16   1, 5, 8, 2  /* good timing */
167     #define TQ_x_17   1, 6, 8, 2  /* good timing */
168     #define TQ_x_18   1, 7, 8, 2  /* good timing */
169     #define TQ_x_19   1, 8, 8, 2  /* good timing */
170     #define TQ_x_20   1, 8, 8, 3  /* good timing */
171     #define TQ_x_21   1, 8, 8, 4
172     #define TQ_x_25   1, 8, 8, 8
173 
174     #if CO_FCY == 2000
175         #define CO_CANbitRateDataInitializers  \
176         {1, 5,   TQ_x_20},   /*CAN=10kbps*/    \
177         {2, 5,   TQ_x_20},   /*CAN=20kbps*/    \
178         {1, 1,   TQ_x_20},   /*CAN=50kbps*/    \
179         {2, 1,   TQ_x_16},   /*CAN=125kbps*/   \
180         {2, 1,   TQ_x_8 },   /*CAN=250kbps*/   \
181         {2, 1,   TQ_x_4 },   /*CAN=500kbps*/   \
182         {2, 1,   TQ_x_4 },   /*Not possible*/  \
183         {2, 1,   TQ_x_4 }    /*Not possible*/
184     #elif CO_FCY == 3000
185         #define CO_CANbitRateDataInitializers  \
186         {2, 15,  TQ_x_20},   /*CAN=10kbps*/    \
187         {1, 5,   TQ_x_15},   /*CAN=20kbps*/    \
188         {1, 2,   TQ_x_15},   /*CAN=50kbps*/    \
189         {1, 1,   TQ_x_12},   /*CAN=125kbps*/   \
190         {2, 1,   TQ_x_12},   /*CAN=250kbps*/   \
191         {2, 1,   TQ_x_6 },   /*CAN=500kbps*/   \
192         {2, 1,   TQ_x_6 },   /*Not possible*/  \
193         {2, 1,   TQ_x_6 }    /*Not possible*/
194     #elif CO_FCY == 4000
195         #define CO_CANbitRateDataInitializers  \
196         {2, 25,  TQ_x_16},   /*CAN=10kbps*/    \
197         {1, 5,   TQ_x_20},   /*CAN=20kbps*/    \
198         {2, 5,   TQ_x_16},   /*CAN=50kbps*/    \
199         {1, 1,   TQ_x_16},   /*CAN=125kbps*/   \
200         {2, 1,   TQ_x_16},   /*CAN=250kbps*/   \
201         {2, 1,   TQ_x_8 },   /*CAN=500kbps*/   \
202         {2, 1,   TQ_x_5 },   /*CAN=800kbps*/   \
203         {2, 1,   TQ_x_4 }    /*CAN=1000kbps*/
204     #elif CO_FCY == 5000
205         #define CO_CANbitRateDataInitializers  \
206         {2, 25,  TQ_x_20},   /*CAN=10kbps*/    \
207         {1, 5,   TQ_x_25},   /*CAN=20kbps*/    \
208         {2, 5,   TQ_x_20},   /*CAN=50kbps*/    \
209         {1, 1,   TQ_x_20},   /*CAN=125kbps*/   \
210         {2, 1,   TQ_x_20},   /*CAN=250kbps*/   \
211         {2, 1,   TQ_x_10},   /*CAN=500kbps*/   \
212         {2, 1,   TQ_x_10},   /*Not possible*/  \
213         {2, 1,   TQ_x_5 }    /*CAN=1000kbps*/
214     #elif CO_FCY == 6000
215         #define CO_CANbitRateDataInitializers  \
216         {1, 20,  TQ_x_15},   /*CAN=10kbps*/    \
217         {1, 10,  TQ_x_15},   /*CAN=20kbps*/    \
218         {1, 4,   TQ_x_15},   /*CAN=50kbps*/    \
219         {2, 3,   TQ_x_16},   /*CAN=125kbps*/   \
220         {1, 1,   TQ_x_12},   /*CAN=250kbps*/   \
221         {2, 1,   TQ_x_12},   /*CAN=500kbps*/   \
222         {2, 1,   TQ_x_12},   /*Not possible*/  \
223         {2, 1,   TQ_x_6 }    /*CAN=1000kbps*/
224     #elif CO_FCY == 8000
225         #define CO_CANbitRateDataInitializers  \
226         {1, 25,  TQ_x_16},   /*CAN=10kbps*/    \
227         {2, 25,  TQ_x_16},   /*CAN=20kbps*/    \
228         {1, 5,   TQ_x_16},   /*CAN=50kbps*/    \
229         {1, 2,   TQ_x_16},   /*CAN=125kbps*/   \
230         {1, 1,   TQ_x_16},   /*CAN=250kbps*/   \
231         {2, 1,   TQ_x_16},   /*CAN=500kbps*/   \
232         {2, 1,   TQ_x_10},   /*CAN=800kbps*/   \
233         {2, 1,   TQ_x_8 }    /*CAN=1000kbps*/
234     #elif CO_FCY == 10000
235         #define CO_CANbitRateDataInitializers  \
236         {1, 25,  TQ_x_20},   /*CAN=10kbps*/    \
237         {2, 25,  TQ_x_20},   /*CAN=20kbps*/    \
238         {1, 5,   TQ_x_20},   /*CAN=50kbps*/    \
239         {2, 5,   TQ_x_16},   /*CAN=125kbps*/   \
240         {1, 1,   TQ_x_20},   /*CAN=250kbps*/   \
241         {2, 1,   TQ_x_20},   /*CAN=500kbps*/   \
242         {2, 1,   TQ_x_20},   /*Not possible*/  \
243         {2, 1,   TQ_x_10}    /*CAN=1000kbps*/
244     #elif CO_FCY == 12000
245         #define CO_CANbitRateDataInitializers  \
246         {2, 63,  TQ_x_19},   /*CAN=10kbps*/    \
247         {1, 20,  TQ_x_15},   /*CAN=20kbps*/    \
248         {2, 15,  TQ_x_16},   /*CAN=50kbps*/    \
249         {1, 3,   TQ_x_16},   /*CAN=125kbps*/   \
250         {2, 3,   TQ_x_16},   /*CAN=250kbps*/   \
251         {1, 1,   TQ_x_12},   /*CAN=500kbps*/   \
252         {2, 1,   TQ_x_15},   /*CAN=800kbps*/   \
253         {2, 1,   TQ_x_12}    /*CAN=1000kbps*/
254     #elif CO_FCY == 16000
255         #define CO_CANbitRateDataInitializers  \
256         {1, 50,  TQ_x_16},   /*CAN=10kbps*/    \
257         {1, 25,  TQ_x_16},   /*CAN=20kbps*/    \
258         {1, 10,  TQ_x_16},   /*CAN=50kbps*/    \
259         {1, 4,   TQ_x_16},   /*CAN=125kbps*/   \
260         {1, 2,   TQ_x_16},   /*CAN=250kbps*/   \
261         {1, 1,   TQ_x_16},   /*CAN=500kbps*/   \
262         {1, 1,   TQ_x_10},   /*CAN=800kbps*/   \
263         {1, 1,   TQ_x_8 }    /*CAN=1000kbps*/
264     #elif CO_FCY == 20000
265         #define CO_CANbitRateDataInitializers  \
266         {1, 50,  TQ_x_20},   /*CAN=10kbps*/    \
267         {1, 25,  TQ_x_20},   /*CAN=20kbps*/    \
268         {1, 10,  TQ_x_20},   /*CAN=50kbps*/    \
269         {1, 5,   TQ_x_16},   /*CAN=125kbps*/   \
270         {1, 2,   TQ_x_20},   /*CAN=250kbps*/   \
271         {1, 1,   TQ_x_20},   /*CAN=500kbps*/   \
272         {1, 1,   TQ_x_20},   /*Not possible*/  \
273         {1, 1,   TQ_x_10}    /*CAN=1000kbps*/
274     #elif CO_FCY == 24000
275         #define CO_CANbitRateDataInitializers  \
276         {1, 63,  TQ_x_19},   /*CAN=10kbps*/    \
277         {1, 40,  TQ_x_15},   /*CAN=20kbps*/    \
278         {1, 15,  TQ_x_16},   /*CAN=50kbps*/    \
279         {1, 6,   TQ_x_16},   /*CAN=125kbps*/   \
280         {1, 3,   TQ_x_16},   /*CAN=250kbps*/   \
281         {1, 2,   TQ_x_12},   /*CAN=500kbps*/   \
282         {1, 1,   TQ_x_15},   /*CAN=800kbps*/   \
283         {1, 1,   TQ_x_12}    /*CAN=1000kbps*/
284     #elif CO_FCY == 32000
285         #define CO_CANbitRateDataInitializers  \
286         {1, 64,  TQ_x_25},   /*CAN=10kbps*/    \
287         {1, 50,  TQ_x_16},   /*CAN=20kbps*/    \
288         {1, 20,  TQ_x_16},   /*CAN=50kbps*/    \
289         {1, 8,   TQ_x_16},   /*CAN=125kbps*/   \
290         {1, 4,   TQ_x_16},   /*CAN=250kbps*/   \
291         {1, 2,   TQ_x_16},   /*CAN=500kbps*/   \
292         {1, 2,   TQ_x_10},   /*CAN=800kbps*/   \
293         {1, 1,   TQ_x_16}    /*CAN=1000kbps*/
294     #elif CO_FCY == 40000
295         #define CO_CANbitRateDataInitializers  \
296         {1, 50,  TQ_x_20},   /*Not possible*/  \
297         {1, 50,  TQ_x_20},   /*CAN=20kbps*/    \
298         {1, 25,  TQ_x_16},   /*CAN=50kbps*/    \
299         {1, 10,  TQ_x_16},   /*CAN=125kbps*/   \
300         {1, 5,   TQ_x_16},   /*CAN=250kbps*/   \
301         {1, 2,   TQ_x_20},   /*CAN=500kbps*/   \
302         {1, 1,   TQ_x_25},   /*CAN=800kbps*/   \
303         {1, 1,   TQ_x_20}    /*CAN=1000kbps*/
304     #elif CO_FCY == 48000
305         #define CO_CANbitRateDataInitializers  \
306         {1, 63,  TQ_x_19},   /*Not possible*/  \
307         {1, 63,  TQ_x_19},   /*CAN=20kbps*/    \
308         {1, 30,  TQ_x_16},   /*CAN=50kbps*/    \
309         {1, 12,  TQ_x_16},   /*CAN=125kbps*/   \
310         {1, 6,   TQ_x_16},   /*CAN=250kbps*/   \
311         {1, 3,   TQ_x_16},   /*CAN=500kbps*/   \
312         {1, 2,   TQ_x_15},   /*CAN=800kbps*/   \
313         {1, 2,   TQ_x_12}    /*CAN=1000kbps*/
314     #elif CO_FCY == 56000
315         #define CO_CANbitRateDataInitializers  \
316         {1, 61,  TQ_x_23},   /*Not possible*/  \
317         {1, 61,  TQ_x_23},   /*CAN=20kbps*/    \
318         {1, 35,  TQ_x_16},   /*CAN=50kbps*/    \
319         {1, 14,  TQ_x_16},   /*CAN=125kbps*/   \
320         {1, 7,   TQ_x_16},   /*CAN=250kbps*/   \
321         {1, 4,   TQ_x_14},   /*CAN=500kbps*/   \
322         {1, 5,   TQ_x_7 },   /*CAN=800kbps*/   \
323         {1, 2,   TQ_x_14}    /*CAN=1000kbps*/
324     #elif CO_FCY == 64000
325         #define CO_CANbitRateDataInitializers  \
326         {1, 64,  TQ_x_25},   /*Not possible*/  \
327         {1, 64,  TQ_x_25},   /*CAN=20kbps*/    \
328         {1, 40,  TQ_x_16},   /*CAN=50kbps*/    \
329         {1, 16,  TQ_x_16},   /*CAN=125kbps*/   \
330         {1, 8,   TQ_x_16},   /*CAN=250kbps*/   \
331         {1, 4,   TQ_x_16},   /*CAN=500kbps*/   \
332         {1, 2,   TQ_x_20},   /*CAN=800kbps*/   \
333         {1, 2,   TQ_x_16}    /*CAN=1000kbps*/
334     #elif CO_FCY == 70000
335         #define CO_CANbitRateDataInitializers  \
336         {1, 64,  TQ_x_25},   /*Not possible*/  \
337         {1, 64,  TQ_x_25},   /*CAN=20kbps*/    \
338         {1, 35,  TQ_x_20},   /*CAN=50kbps*/    \
339         {1, 14,  TQ_x_20},   /*CAN=125kbps*/   \
340         {1, 7,   TQ_x_20},   /*CAN=250kbps*/   \
341         {1, 5,   TQ_x_14},   /*CAN=500kbps*/   \
342         {1, 3,   TQ_x_15},   /*Not working*/   \
343         {1, 2,   TQ_x_17}    /*Not working*/
344     #else
345         #error define_CO_FCY CO_FCY not supported
346     #endif /* CO_FCY == <value> */
347 #endif /* CO_FCY */
348 
349 
350 /* Structure contains timing coefficients for CAN module.
351  *
352  * CAN baud rate is calculated from following equations:
353  * FCAN = FCY * Scale                  - Input frequency to CAN module (MAX 40MHz for dsPIC33F/PIC24H and 70MHz for dsPIC33E/PIC24E)
354  * TQ = 2 * BRP / FCAN                 - Time Quanta
355  * BaudRate = 1 / (TQ * K)             - Can bus Baud Rate
356  * K = SJW + PROP + PhSeg1 + PhSeg2    - Number of Time Quantas
357  */
358 typedef struct{
359     uint8_t   scale;    /* (1 or 2) Scales FCY clock - dsPIC33F and PIC24H specific */
360     uint8_t   BRP;      /* (1...64) Baud Rate Prescaler */
361     uint8_t   SJW;      /* (1...4) SJW time */
362     uint8_t   PROP;     /* (1...8) PROP time */
363     uint8_t   phSeg1;   /* (1...8) Phase Segment 1 time */
364     uint8_t   phSeg2;   /* (1...8) Phase Segment 2 time */
365 }CO_CANbitRateData_t;
366 
367 
368 /* CAN receive message structure as aligned in CAN module.
369  * In dsPIC33F and PIC24H this structure is used for both: transmitting and
370  * receiving to and from CAN module. (Object is ownded by CAN module).
371  */
372 typedef struct{
373     uint16_t    ident;          /* Standard Identifier as aligned in CAN module. 16 bits:
374                                    'UUUSSSSS SSSSSSRE' (U: unused; S: SID; R=SRR; E=IDE). */
375     uint16_t    extIdent;       /* Extended identifier, not used here */
376     uint16_t    DLC      :4;    /* Data length code (bits 0...3) */
377     uint16_t    DLCrest  :12;   /* Not used here (bits 4..15) */
378     uint8_t     data[8];        /* 8 data bytes */
379     uint8_t     dummy;          /* Not used */
380     uint8_t     FILHIT;         /* Filter hit */
381 }CO_CANrxMsg_t;
382 
383 
384 /* Received message object */
385 typedef struct{
386     uint16_t            ident;
387     uint16_t            mask;
388     void               *object;
389     void              (*pFunct)(void *object, const CO_CANrxMsg_t *message);
390 }CO_CANrx_t;
391 
392 
393 /* Transmit message object. */
394 typedef struct{
395     uint16_t            ident;      /* Standard Identifier as aligned in CAN module. 16 bits:
396                                       'SSSSSUUU SSSSSSRE' (U: unused; S: SID; R=SRR; E=IDE). */
397     uint8_t             DLC;
398     uint8_t             data[8];
399     volatile bool_t     bufferFull;
400     volatile bool_t     syncFlag;
401 }CO_CANtx_t;
402 
403 
404 /* CAN module object. */
405 typedef struct{
406     void               *CANdriverState;
407     __eds__ CO_CANrxMsg_t *CANmsgBuff;  /* dsPIC33F specific: CAN message buffer for CAN module */
408     uint8_t             CANmsgBuffSize; /* dsPIC33F specific: Size of the above buffer */
409     CO_CANrx_t         *rxArray;
410     uint16_t            rxSize;
411     CO_CANtx_t         *txArray;
412     uint16_t            txSize;
413     volatile bool_t     CANnormal;
414     volatile bool_t     useCANrxFilters;
415     volatile bool_t     bufferInhibitFlag;
416     volatile bool_t     firstCANtxMessage;
417     volatile uint16_t   CANtxCount;
418     uint16_t            errOld;
419     void               *em;
420 }CO_CANmodule_t;
421 
422 
423 /* CAN interrupt receives and transmits CAN messages.
424  *
425  * Function must be called directly from _C1Interrupt or _C2Interrupt with
426  * high priority.
427  */
428 void CO_CANinterrupt(CO_CANmodule_t *CANmodule);
429 
430 
431 #endif /* CO_DRIVER_TARGET_H */
432