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