source: rtems/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/mcan.c @ c354fac

5
Last change on this file since c354fac was c354fac, checked in by Sebastian Huber <sebastian.huber@…>, on 01/14/16 at 14:48:44

bsp/atsam: Port SAM Software Package to RTEMS

Update #2529.

  • Property mode set to 100644
File size: 40.0 KB
Line 
1/* ---------------------------------------------------------------------------- */
2/*                  Atmel Microcontroller Software Support                      */
3/*                       SAM Software Package License                           */
4/* ---------------------------------------------------------------------------- */
5/* Copyright (c) 2015, Atmel Corporation                                        */
6/*                                                                              */
7/* All rights reserved.                                                         */
8/*                                                                              */
9/* Redistribution and use in source and binary forms, with or without           */
10/* modification, are permitted provided that the following condition is met:    */
11/*                                                                              */
12/* - Redistributions of source code must retain the above copyright notice,     */
13/* this list of conditions and the disclaimer below.                            */
14/*                                                                              */
15/* Atmel's name may not be used to endorse or promote products derived from     */
16/* this software without specific prior written permission.                     */
17/*                                                                              */
18/* DISCLAIMER:  THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR   */
19/* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
20/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE   */
21/* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,      */
22/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
23/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,  */
24/* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    */
25/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING         */
26/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
27/* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                           */
28/* ---------------------------------------------------------------------------- */
29
30/** \file
31 *  Implements functions for Controller Area Network (CAN)
32 *  peripheral operations.
33 */
34/** \addtogroup can_module
35 *@{*/
36
37
38/*----------------------------------------------------------------------------
39 *        Headers
40 *----------------------------------------------------------------------------*/
41#ifndef __rtems__
42#include "board.h"
43#endif /* __rtems__ */
44#include "chip.h"
45#include "mcan_config.h"
46#include <assert.h>
47/*---------------------------------------------------------------------------
48 *      Definitions
49 *---------------------------------------------------------------------------*/
50#define MAILBOX_ADDRESS(address) (0xFFFC & (address))
51
52#define CAN_CLK_FREQ_HZ               MCAN_PROG_CLK_FREQ_HZ
53
54#define MCAN0_TSEG1                   (MCAN0_PROP_SEG + MCAN0_PHASE_SEG1)
55#define MCAN0_TSEG2                   (MCAN0_PHASE_SEG2)
56#define MCAN0_BRP                     ((uint32_t) (((float) CAN_CLK_FREQ_HZ / \
57                                                                           ((float)(MCAN0_TSEG1 + MCAN0_TSEG2 + 3) *\
58                                                                                (float) MCAN0_BIT_RATE_BPS)) - 1))
59#define MCAN0_SJW                     (MCAN0_SYNC_JUMP - 1)
60#define MCAN0_FTSEG1                  (MCAN0_FAST_PROP_SEG + MCAN0_FAST_PHASE_SEG1)
61#define MCAN0_FTSEG2                  (MCAN0_FAST_PHASE_SEG2)
62#define MCAN0_FBRP                    ((uint32_t) (((float) CAN_CLK_FREQ_HZ / \
63                                                                           ((float)(MCAN0_FTSEG1 + MCAN0_FTSEG2 + 3) * \
64                                                                                (float) MCAN0_FAST_BIT_RATE_BPS)) - 1))
65#define MCAN0_FSJW                    (MCAN0_FAST_SYNC_JUMP - 1)
66
67#define MCAN0_STD_FLTS_WRDS           (MCAN0_NMBR_STD_FLTS)
68/* 128 max filters */
69#define MCAN0_EXT_FLTS_WRDS           (MCAN0_NMBR_EXT_FLTS * 2)
70/* 64 max filters */
71#define MCAN0_RX_FIFO0_WRDS           (MCAN0_NMBR_RX_FIFO0_ELMTS * \
72                                                                           ((MCAN0_RX_FIFO0_ELMT_SZ/4) + 2))
73/* 64 elements max */
74#define MCAN0_RX_FIFO1_WRDS           (MCAN0_NMBR_RX_FIFO1_ELMTS *\
75                                                                           ((MCAN0_RX_FIFO1_ELMT_SZ/4) + 2))
76/* 64 elements max */
77#define MCAN0_RX_DED_BUFS_WRDS            (MCAN0_NMBR_RX_DED_BUF_ELMTS * \
78                ((MCAN0_RX_BUF_ELMT_SZ/4) + 2))
79/* 64 elements max */
80#define MCAN0_TX_EVT_FIFO_WRDS        (MCAN0_NMBR_TX_EVT_FIFO_ELMTS * 2)
81/* 32 elements max */
82#define MCAN0_TX_DED_BUF_WRDS         (MCAN0_NMBR_TX_DED_BUF_ELMTS * \
83                                                                           ((MCAN0_TX_BUF_ELMT_SZ/4) + 2))
84/* 32 elements max */
85#define MCAN0_TX_FIFO_Q_WRDS          (MCAN0_NMBR_TX_FIFO_Q_ELMTS *\
86                                                                           ((MCAN0_TX_BUF_ELMT_SZ/4) + 2))
87/* 32 elements max */
88
89#define MCAN1_TSEG1                   (MCAN1_PROP_SEG + MCAN1_PHASE_SEG1)
90#define MCAN1_TSEG2                   (MCAN1_PHASE_SEG2)
91#define MCAN1_BRP                     ((uint32_t) (((float) CAN_CLK_FREQ_HZ / \
92                                                                           ((float)(MCAN1_TSEG1 + MCAN1_TSEG2 + 3) *\
93                                                                                (float) MCAN1_BIT_RATE_BPS)) - 1))
94#define MCAN1_SJW                     (MCAN1_SYNC_JUMP - 1)
95#define MCAN1_FTSEG1                  (MCAN1_FAST_PROP_SEG + MCAN1_FAST_PHASE_SEG1)
96#define MCAN1_FTSEG2                  (MCAN1_FAST_PHASE_SEG2)
97#define MCAN1_FBRP                    ((uint32_t) (((float) CAN_CLK_FREQ_HZ /\
98                                                                           ((float)(MCAN1_FTSEG1 + MCAN1_FTSEG2 + 3) *\
99                                                                                (float) MCAN1_FAST_BIT_RATE_BPS)) - 1))
100#define MCAN1_FSJW                    (MCAN1_FAST_SYNC_JUMP - 1)
101
102#define MCAN1_STD_FLTS_WRDS           (MCAN1_NMBR_STD_FLTS)
103/* 128 max filters */
104#define MCAN1_EXT_FLTS_WRDS           (MCAN1_NMBR_EXT_FLTS * 2)
105/* 64 max filters */
106#define MCAN1_RX_FIFO0_WRDS           (MCAN1_NMBR_RX_FIFO0_ELMTS * \
107                                                                           ((MCAN1_RX_FIFO0_ELMT_SZ/4) + 2))
108/* 64 elements max */
109#define MCAN1_RX_FIFO1_WRDS           (MCAN1_NMBR_RX_FIFO1_ELMTS *\
110                                                                           ((MCAN1_RX_FIFO1_ELMT_SZ/4) + 2))
111/* 64 elements max */
112#define MCAN1_RX_DED_BUFS_WRDS            (MCAN1_NMBR_RX_DED_BUF_ELMTS * \
113                ((MCAN1_RX_BUF_ELMT_SZ/4) + 2))
114/* 64 elements max */
115#define MCAN1_TX_EVT_FIFO_WRDS        (MCAN1_NMBR_TX_EVT_FIFO_ELMTS * 2)
116/* 32 elements max */
117#define MCAN1_TX_DED_BUF_WRDS         (MCAN1_NMBR_TX_DED_BUF_ELMTS * \
118                                                                           ((MCAN1_TX_BUF_ELMT_SZ/4) + 2))
119/* 32 elements max */
120#define MCAN1_TX_FIFO_Q_WRDS          (MCAN1_NMBR_TX_FIFO_Q_ELMTS * \
121                                                                           ((MCAN1_TX_BUF_ELMT_SZ/4) + 2))
122/* 32 elements max */
123
124/* validate CAN0 entries */
125#if (MCAN0_TSEG1 > 63)
126        #error "Invalid CAN0 TSEG1"
127#endif
128#if (MCAN0_TSEG2 > 15)
129        #error "Invalid CAN0 TSEG2"
130#endif
131#if (MCAN0_SJW > 15)
132        #error "Invalid CAN0 SJW"
133#endif
134#if (MCAN0_FTSEG1 > 15)
135        #error "Invalid CAN0 FTSEG1"
136#endif
137#if (MCAN0_FTSEG2 > 7)
138        #error "Invalid CAN0 FTSEG2"
139#endif
140#if (MCAN0_FSJW > 3)
141        #error "Invalid CAN0 FSJW"
142#endif
143
144#if (MCAN0_NMBR_STD_FLTS > 128)
145        #error "Invalid CAN0 # of Standard Filters"
146#endif
147#if (MCAN0_NMBR_EXT_FLTS > 64)
148        #error "Invalid CAN0 # of Extended Filters"
149#endif
150#if (MCAN0_NMBR_RX_FIFO0_ELMTS > 64)
151        #error "Invalid CAN0 # RX FIFO 0 ELEMENTS"
152#endif
153#if (MCAN0_NMBR_RX_FIFO1_ELMTS > 64)
154        #error "Invalid CAN0 # RX FIFO 0 ELEMENTS"
155#endif
156#if (MCAN0_NMBR_RX_DED_BUF_ELMTS > 64)
157        #error "Invalid CAN0 # RX BUFFER ELEMENTS"
158#endif
159#if (MCAN0_NMBR_TX_EVT_FIFO_ELMTS > 32)
160        #error "Invalid CAN0 # TX EVENT FIFO ELEMENTS"
161#endif
162#if ((MCAN0_NMBR_TX_DED_BUF_ELMTS + MCAN0_NMBR_TX_FIFO_Q_ELMTS)  > 32)
163        #error "Invalid CAN0 # TX BUFFER ELEMENTS"
164#endif
165
166#if   (8 == MCAN0_RX_FIFO0_ELMT_SZ)
167        #define MCAN0_RX_FIFO0_DATA_SIZE  (0u)
168#elif (12 == MCAN0_RX_FIFO0_ELMT_SZ)
169        #define MCAN0_RX_FIFO0_DATA_SIZE  (1u)
170#elif (16 == MCAN0_RX_FIFO0_ELMT_SZ)
171        #define MCAN0_RX_FIFO0_DATA_SIZE  (2u)
172#elif (20 == MCAN0_RX_FIFO0_ELMT_SZ)
173        #define MCAN0_RX_FIFO0_DATA_SIZE  (3u)
174#elif (24 == MCAN0_RX_FIFO0_ELMT_SZ)
175        #define MCAN0_RX_FIFO0_DATA_SIZE  (4u)
176#elif (32 == MCAN0_RX_FIFO0_ELMT_SZ)
177        #define MCAN0_RX_FIFO0_DATA_SIZE  (5u)
178#elif (48 == MCAN0_RX_FIFO0_ELMT_SZ)
179        #define MCAN0_RX_FIFO0_DATA_SIZE  (6u)
180#elif (64 == MCAN0_RX_FIFO0_ELMT_SZ)
181        #define MCAN0_RX_FIFO0_DATA_SIZE  (7u)
182#else
183        #error "Invalid CAN0 RX FIFO0 ELEMENT SIZE"
184#endif
185
186#if   (8 == MCAN0_RX_FIFO1_ELMT_SZ)
187        #define MCAN0_RX_FIFO1_DATA_SIZE  (0u)
188#elif (12 == MCAN0_RX_FIFO1_ELMT_SZ)
189        #define MCAN0_RX_FIFO1_DATA_SIZE  (1u)
190#elif (16 == MCAN0_RX_FIFO1_ELMT_SZ)
191        #define MCAN0_RX_FIFO1_DATA_SIZE  (2u)
192#elif (20 == MCAN0_RX_FIFO1_ELMT_SZ)
193        #define MCAN0_RX_FIFO1_DATA_SIZE  (3u)
194#elif (24 == MCAN0_RX_FIFO1_ELMT_SZ)
195        #define MCAN0_RX_FIFO1_DATA_SIZE  (4u)
196#elif (32 == MCAN0_RX_FIFO1_ELMT_SZ)
197        #define MCAN0_RX_FIFO1_DATA_SIZE  (5u)
198#elif (48 == MCAN0_RX_FIFO1_ELMT_SZ)
199        #define MCAN0_RX_FIFO1_DATA_SIZE  (6u)
200#elif (64 == MCAN0_RX_FIFO1_ELMT_SZ)
201        #define MCAN0_RX_FIFO1_DATA_SIZE  (7u)
202#else
203        #error "Invalid CAN0 RX FIFO1 ELEMENT SIZE"
204#endif
205
206#if   (8 == MCAN0_RX_BUF_ELMT_SZ)
207        #define MCAN0_RX_BUF_DATA_SIZE  (0u)
208#elif (12 == MCAN0_RX_BUF_ELMT_SZ)
209        #define MCAN0_RX_BUF_DATA_SIZE  (1u)
210#elif (16 == MCAN0_RX_BUF_ELMT_SZ)
211        #define MCAN0_RX_BUF_DATA_SIZE  (2u)
212#elif (20 == MCAN0_RX_BUF_ELMT_SZ)
213        #define MCAN0_RX_BUF_DATA_SIZE  (3u)
214#elif (24 == MCAN0_RX_BUF_ELMT_SZ)
215        #define MCAN0_RX_BUF_DATA_SIZE  (4u)
216#elif (32 == MCAN0_RX_BUF_ELMT_SZ)
217        #define MCAN0_RX_BUF_DATA_SIZE  (5u)
218#elif (48 == MCAN0_RX_BUF_ELMT_SZ)
219        #define MCAN0_RX_BUF_DATA_SIZE  (6u)
220#elif (64 == MCAN0_RX_BUF_ELMT_SZ)
221        #define MCAN0_RX_BUF_DATA_SIZE  (7u)
222#else
223        #error "Invalid CAN0 RX BUFFER ELEMENT SIZE"
224#endif
225
226#if   (8 == MCAN0_TX_BUF_ELMT_SZ)
227        #define MCAN0_TX_BUF_DATA_SIZE  (0u)
228#elif (12 == MCAN0_TX_BUF_ELMT_SZ)
229        #define MCAN0_TX_BUF_DATA_SIZE  (1u)
230#elif (16 == MCAN0_TX_BUF_ELMT_SZ)
231        #define MCAN0_TX_BUF_DATA_SIZE  (2u)
232#elif (20 == MCAN0_TX_BUF_ELMT_SZ)
233        #define MCAN0_TX_BUF_DATA_SIZE  (3u)
234#elif (24 == MCAN0_TX_BUF_ELMT_SZ)
235        #define MCAN0_TX_BUF_DATA_SIZE  (4u)
236#elif (32 == MCAN0_TX_BUF_ELMT_SZ)
237        #define MCAN0_TX_BUF_DATA_SIZE  (5u)
238#elif (48 == MCAN0_TX_BUF_ELMT_SZ)
239        #define MCAN0_TX_BUF_DATA_SIZE  (6u)
240#elif (64 == MCAN0_TX_BUF_ELMT_SZ)
241        #define MCAN0_TX_BUF_DATA_SIZE  (7u)
242#else
243        #error "Invalid CAN0 TX BUFFER ELEMENT SIZE"
244#endif
245
246/* validate CAN1 entries */
247#if (MCAN1_TSEG1 > 63)
248        #error "Invalid CAN1 TSEG1"
249#endif
250#if (MCAN1_TSEG2 > 15)
251        #error "Invalid CAN1 TSEG2"
252#endif
253#if (MCAN1_SJW > 15)
254        #error "Invalid CAN1 SJW"
255#endif
256#if (MCAN1_FTSEG1 > 15)
257        #error "Invalid CAN1 FTSEG1"
258#endif
259#if (MCAN1_FTSEG2 > 7)
260        #error "Invalid CAN1 FTSEG2"
261#endif
262#if (MCAN1_FSJW > 3)
263        #error "Invalid CAN1 FSJW"
264#endif
265
266#if (MCAN1_NMBR_STD_FLTS > 128)
267        #error "Invalid CAN1 # of Standard Filters"
268#endif
269#if (MCAN1_NMBR_EXT_FLTS > 64)
270        #error "Invalid CAN1 # of Extended Filters"
271#endif
272#if (MCAN1_NMBR_RX_FIFO0_ELMTS > 64)
273        #error "Invalid CAN1 # RX FIFO 0 ELEMENTS"
274#endif
275#if (MCAN1_NMBR_RX_FIFO1_ELMTS > 64)
276        #error "Invalid CAN1 # RX FIFO 0 ELEMENTS"
277#endif
278#if (MCAN1_NMBR_RX_DED_BUF_ELMTS > 64)
279        #error "Invalid CAN1 # RX BUFFER ELEMENTS"
280#endif
281#if (MCAN1_NMBR_TX_EVT_FIFO_ELMTS > 32)
282        #error "Invalid CAN1 # TX EVENT FIFO ELEMENTS"
283#endif
284#if ((MCAN1_NMBR_TX_DED_BUF_ELMTS + MCAN1_NMBR_TX_FIFO_Q_ELMTS)  > 32)
285        #error "Invalid CAN1 # TX BUFFER ELEMENTS"
286#endif
287
288#if   (8 == MCAN1_RX_FIFO0_ELMT_SZ)
289        #define MCAN1_RX_FIFO0_DATA_SIZE  (0u)
290#elif (12 == MCAN1_RX_FIFO0_ELMT_SZ)
291        #define MCAN1_RX_FIFO0_DATA_SIZE  (1u)
292#elif (16 == MCAN1_RX_FIFO0_ELMT_SZ)
293        #define MCAN1_RX_FIFO0_DATA_SIZE  (2u)
294#elif (20 == MCAN1_RX_FIFO0_ELMT_SZ)
295        #define MCAN1_RX_FIFO0_DATA_SIZE  (3u)
296#elif (24 == MCAN1_RX_FIFO0_ELMT_SZ)
297        #define MCAN1_RX_FIFO0_DATA_SIZE  (4u)
298#elif (32 == MCAN1_RX_FIFO0_ELMT_SZ)
299        #define MCAN1_RX_FIFO0_DATA_SIZE  (5u)
300#elif (48 == MCAN1_RX_FIFO0_ELMT_SZ)
301        #define MCAN1_RX_FIFO0_DATA_SIZE  (6u)
302#elif (64 == MCAN1_RX_FIFO0_ELMT_SZ)
303        #define MCAN1_RX_FIFO0_DATA_SIZE  (7u)
304#else
305        #error "Invalid CAN1 RX FIFO0 ELEMENT SIZE"
306#endif
307
308#if   (8 == MCAN1_RX_FIFO1_ELMT_SZ)
309        #define MCAN1_RX_FIFO1_DATA_SIZE  (0u)
310#elif (12 == MCAN1_RX_FIFO1_ELMT_SZ)
311        #define MCAN1_RX_FIFO1_DATA_SIZE  (1u)
312#elif (16 == MCAN1_RX_FIFO1_ELMT_SZ)
313        #define MCAN1_RX_FIFO1_DATA_SIZE  (2u)
314#elif (20 == MCAN1_RX_FIFO1_ELMT_SZ)
315        #define MCAN1_RX_FIFO1_DATA_SIZE  (3u)
316#elif (24 == MCAN1_RX_FIFO1_ELMT_SZ)
317        #define MCAN1_RX_FIFO1_DATA_SIZE  (4u)
318#elif (32 == MCAN1_RX_FIFO1_ELMT_SZ)
319        #define MCAN1_RX_FIFO1_DATA_SIZE  (5u)
320#elif (48 == MCAN1_RX_FIFO1_ELMT_SZ)
321        #define MCAN1_RX_FIFO1_DATA_SIZE  (6u)
322#elif (64 == MCAN1_RX_FIFO1_ELMT_SZ)
323        #define MCAN1_RX_FIFO1_DATA_SIZE  (7u)
324#else
325        #error "Invalid CAN1 RX FIFO1 ELEMENT SIZE"
326#endif
327
328#if   (8 == MCAN1_RX_BUF_ELMT_SZ)
329        #define MCAN1_RX_BUF_DATA_SIZE  (0u)
330#elif (12 == MCAN1_RX_BUF_ELMT_SZ)
331        #define MCAN1_RX_BUF_DATA_SIZE  (1u)
332#elif (16 == MCAN1_RX_BUF_ELMT_SZ)
333        #define MCAN1_RX_BUF_DATA_SIZE  (2u)
334#elif (20 == MCAN1_RX_BUF_ELMT_SZ)
335        #define MCAN1_RX_BUF_DATA_SIZE  (3u)
336#elif (24 == MCAN1_RX_BUF_ELMT_SZ)
337        #define MCAN1_RX_BUF_DATA_SIZE  (4u)
338#elif (32 == MCAN1_RX_BUF_ELMT_SZ)
339        #define MCAN1_RX_BUF_DATA_SIZE  (5u)
340#elif (48 == MCAN1_RX_BUF_ELMT_SZ)
341        #define MCAN1_RX_BUF_DATA_SIZE  (6u)
342#elif (64 == MCAN1_RX_BUF_ELMT_SZ)
343        #define MCAN1_RX_BUF_DATA_SIZE  (7u)
344#else
345        #error "Invalid CAN1 RX BUFFER ELEMENT SIZE"
346#endif
347
348#if   (8 == MCAN1_TX_BUF_ELMT_SZ)
349        #define MCAN1_TX_BUF_DATA_SIZE  (0u)
350#elif (12 == MCAN1_TX_BUF_ELMT_SZ)
351        #define MCAN1_TX_BUF_DATA_SIZE  (1u)
352#elif (16 == MCAN1_TX_BUF_ELMT_SZ)
353        #define MCAN1_TX_BUF_DATA_SIZE  (2u)
354#elif (20 == MCAN1_TX_BUF_ELMT_SZ)
355        #define MCAN1_TX_BUF_DATA_SIZE  (3u)
356#elif (24 == MCAN1_TX_BUF_ELMT_SZ)
357        #define MCAN1_TX_BUF_DATA_SIZE  (4u)
358#elif (32 == MCAN1_TX_BUF_ELMT_SZ)
359        #define MCAN1_TX_BUF_DATA_SIZE  (5u)
360#elif (48 == MCAN1_TX_BUF_ELMT_SZ)
361        #define MCAN1_TX_BUF_DATA_SIZE  (6u)
362#elif (64 == MCAN1_TX_BUF_ELMT_SZ)
363        #define MCAN1_TX_BUF_DATA_SIZE  (7u)
364#else
365        #error "Invalid CAN1 TX BUFFER ELEMENT SIZE"
366#endif
367
368#define CAN_11_BIT_ID_MASK                 (0x7FF)
369#define CAN_29_BIT_ID_MASK                 (0x1FFFFFFF)
370#define ELMT_SIZE_MASK                (0x1F)
371/* max element size is 18 words, fits in 5 bits */
372
373#define BUFFER_XTD_MASK               (0x40000000)
374#define BUFFER_EXT_ID_MASK            (0x1FFFFFFF)
375#define BUFFER_STD_ID_MASK            (0x1FFC0000)
376#define BUFFER_DLC_MASK               (0x000F0000)
377#define BUFFER_RXTS_MASK              (0x0000FFFF)
378
379#define STD_FILT_SFT_MASK             (3U << 30)
380#define STD_FILT_SFT_RANGE            (0U << 30)
381#define STD_FILT_SFT_DUAL             (1U << 30)
382#define STD_FILT_SFT_CLASSIC          (2U << 30)
383#define STD_FILT_SFEC_MASK            (7U << 27)
384#define STD_FILT_SFEC_DISABLE         (0U << 27)
385#define STD_FILT_SFEC_FIFO0           (1U << 27)
386#define STD_FILT_SFEC_FIFO1           (2U << 27)
387#define STD_FILT_SFEC_REJECT          (3U << 27)
388#define STD_FILT_SFEC_PRIORITY        (4U << 27)
389#define STD_FILT_SFEC_PRIORITY_FIFO0  (5U << 27)
390#define STD_FILT_SFEC_PRIORITY_FIFO1  (6U << 27)
391#define STD_FILT_SFEC_BUFFER          (7U << 27)
392#define STD_FILT_SFID1_MASK           (0x03FFU << 16)
393#define STD_FILT_SFID2_MASK           (0x3FFU << 0)
394#define STD_FILT_SFID2_RX_BUFFER      (0U << 9)
395#define STD_FILT_SFID2_DEBUG_A        (1U << 9)
396#define STD_FILT_SFID2_DEBUG_B        (2U << 9)
397#define STD_FILT_SFID2_DEBUG_C        (3U << 9)
398#define STD_FILT_SFID2_BUFFER(nmbr)   (nmbr & 0x3F)
399
400#define EXT_FILT_EFEC_MASK            (7U << 29)
401#define EXT_FILT_EFEC_DISABLE         (0U << 29)
402#define EXT_FILT_EFEC_FIFO0           (1U << 29)
403#define EXT_FILT_EFEC_FIFO1           (2U << 29)
404#define EXT_FILT_EFEC_REJECT          (3U << 29)
405#define EXT_FILT_EFEC_PRIORITY        (4U << 29)
406#define EXT_FILT_EFEC_PRIORITY_FIFO0  (5U << 29)
407#define EXT_FILT_EFEC_PRIORITY_FIFO1  (6U << 29)
408#define EXT_FILT_EFEC_BUFFER          (7U << 29)
409#define EXT_FILT_EFID1_MASK           (0x1FFFFFFF)
410#define EXT_FILT_EFT_MASK             (3U << 30)
411#define EXT_FILT_EFT_RANGE            (0U << 30)
412#define EXT_FILT_EFT_DUAL             (1U << 30)
413#define EXT_FILT_EFT_CLASSIC          (2U << 30)
414#define EXT_FILT_EFT_RANGE_NO_XIDAM   (3U << 30)
415#define EXT_FILT_EFID2_MASK           (0x1FFFFFFF)
416#define EXT_FILT_EFID2_RX_BUFFER      (0U << 9)
417#define EXT_FILT_EFID2_DEBUG_A        (1U << 9)
418#define EXT_FILT_EFID2_DEBUG_B        (2U << 9)
419#define EXT_FILT_EFID2_DEBUG_C        (3U << 9)
420#define EXT_FILT_EFID2_BUFFER(nmbr)   (nmbr & 0x3F)
421
422
423/*---------------------------------------------------------------------------
424 *      Internal variables
425 *---------------------------------------------------------------------------*/
426
427#ifndef __rtems__
428static const Pin pinsMcan0[] =  {PIN_MCAN0_TXD, PIN_MCAN0_RXD };
429static const Pin pinsMcan1[] =  {PIN_MCAN1_TXD, PIN_MCAN1_RXD };
430#endif /* __rtems__ */
431
432static uint32_t can0MsgRam[MCAN0_STD_FLTS_WRDS +
433                                                   MCAN0_EXT_FLTS_WRDS +
434                                                   MCAN0_RX_FIFO0_WRDS +
435                                                   MCAN0_RX_FIFO1_WRDS +
436                                                   MCAN0_RX_DED_BUFS_WRDS +
437                                                   MCAN0_TX_EVT_FIFO_WRDS +
438                                                   MCAN0_TX_DED_BUF_WRDS +
439                                                   MCAN0_TX_FIFO_Q_WRDS];
440
441static uint32_t can1MsgRam[MCAN1_STD_FLTS_WRDS +
442                                                   MCAN1_EXT_FLTS_WRDS +
443                                                   MCAN1_RX_FIFO0_WRDS +
444                                                   MCAN1_RX_FIFO1_WRDS +
445                                                   MCAN1_RX_DED_BUFS_WRDS +
446                                                   MCAN1_TX_EVT_FIFO_WRDS +
447                                                   MCAN1_TX_DED_BUF_WRDS +
448                                                   MCAN1_TX_FIFO_Q_WRDS];
449
450static const uint8_t dlcToMsgLength[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64 };
451
452const MCan_ConfigType mcan0Config = {
453        MCAN0,
454        MCAN_BTP_BRP(MCAN0_BRP) | MCAN_BTP_TSEG1(MCAN0_TSEG1) |
455        MCAN_BTP_TSEG2(MCAN0_TSEG2) | MCAN_BTP_SJW(MCAN0_SJW),
456        MCAN_FBTP_FBRP(MCAN0_FBRP) | MCAN_FBTP_FTSEG1(MCAN0_FTSEG1) |
457        MCAN_FBTP_FTSEG2(MCAN0_FTSEG2) | MCAN_FBTP_FSJW(MCAN0_FSJW),
458        MCAN0_NMBR_STD_FLTS,
459        MCAN0_NMBR_EXT_FLTS,
460        MCAN0_NMBR_RX_FIFO0_ELMTS,
461        MCAN0_NMBR_RX_FIFO1_ELMTS,
462        MCAN0_NMBR_RX_DED_BUF_ELMTS,
463        MCAN0_NMBR_TX_EVT_FIFO_ELMTS,
464        MCAN0_NMBR_TX_DED_BUF_ELMTS,
465        MCAN0_NMBR_TX_FIFO_Q_ELMTS,
466        (MCAN0_RX_FIFO0_DATA_SIZE << 29) | ((MCAN0_RX_FIFO0_ELMT_SZ / 4) + 2),
467        /* element size in WORDS */
468        (MCAN0_RX_FIFO1_DATA_SIZE << 29) | ((MCAN0_RX_FIFO1_ELMT_SZ / 4) + 2),
469        /* element size in WORDS */
470        (MCAN0_RX_BUF_DATA_SIZE << 29) | ((MCAN0_RX_BUF_ELMT_SZ / 4) + 2),
471        /* element size in WORDS */
472        (MCAN0_TX_BUF_DATA_SIZE << 29) | ((MCAN0_TX_BUF_ELMT_SZ / 4) + 2),
473        /* element size in WORDS */
474        {
475                &can0MsgRam[0],
476                &can0MsgRam[MCAN0_STD_FLTS_WRDS],
477                &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS],
478                &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS + MCAN0_RX_FIFO0_WRDS],
479                &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS + MCAN0_RX_FIFO0_WRDS +
480                MCAN0_RX_FIFO1_WRDS],
481                &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS + MCAN0_RX_FIFO0_WRDS +
482                MCAN0_RX_FIFO1_WRDS + MCAN0_RX_DED_BUFS_WRDS],
483                &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS + MCAN0_RX_FIFO0_WRDS +
484                MCAN0_RX_FIFO1_WRDS + MCAN0_RX_DED_BUFS_WRDS + MCAN0_TX_EVT_FIFO_WRDS],
485                &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS + MCAN0_RX_FIFO0_WRDS +
486                MCAN0_RX_FIFO1_WRDS + MCAN0_RX_DED_BUFS_WRDS + MCAN0_TX_EVT_FIFO_WRDS +
487                MCAN0_TX_DED_BUF_WRDS]
488        },
489};
490
491const MCan_ConfigType mcan1Config = {
492        MCAN1,
493        MCAN_BTP_BRP(MCAN1_BRP) | MCAN_BTP_TSEG1(MCAN1_TSEG1) |
494        MCAN_BTP_TSEG2(MCAN1_TSEG2) | MCAN_BTP_SJW(MCAN1_SJW),
495        MCAN_FBTP_FBRP(MCAN1_FBRP) | MCAN_FBTP_FTSEG1(MCAN1_FTSEG1) |
496        MCAN_FBTP_FTSEG2(MCAN1_FTSEG2) | MCAN_FBTP_FSJW(MCAN1_FSJW),
497        MCAN1_NMBR_STD_FLTS,
498        MCAN1_NMBR_EXT_FLTS,
499        MCAN1_NMBR_RX_FIFO0_ELMTS,
500        MCAN1_NMBR_RX_FIFO1_ELMTS,
501        MCAN0_NMBR_RX_DED_BUF_ELMTS,
502        MCAN1_NMBR_TX_EVT_FIFO_ELMTS,
503        MCAN1_NMBR_TX_DED_BUF_ELMTS,
504        MCAN1_NMBR_TX_FIFO_Q_ELMTS,
505        (MCAN1_RX_FIFO0_DATA_SIZE << 29) | ((MCAN1_RX_FIFO0_ELMT_SZ / 4) + 2),
506        /* element size in WORDS */
507        (MCAN1_RX_FIFO1_DATA_SIZE << 29) | ((MCAN1_RX_FIFO1_ELMT_SZ / 4) + 2),
508        /* element size in WORDS */
509        (MCAN1_RX_BUF_DATA_SIZE << 29) | ((MCAN1_RX_BUF_ELMT_SZ / 4) + 2),
510        /* element size in WORDS */
511        (MCAN1_TX_BUF_DATA_SIZE << 29) | ((MCAN1_TX_BUF_ELMT_SZ / 4) + 2),
512        /* element size in WORDS */
513        {
514                &can1MsgRam[0],
515                &can1MsgRam[MCAN1_STD_FLTS_WRDS],
516                &can1MsgRam[MCAN1_STD_FLTS_WRDS + MCAN1_EXT_FLTS_WRDS],
517                &can1MsgRam[MCAN1_STD_FLTS_WRDS + MCAN1_EXT_FLTS_WRDS + MCAN1_RX_FIFO0_WRDS],
518                &can1MsgRam[MCAN1_STD_FLTS_WRDS + MCAN1_EXT_FLTS_WRDS + MCAN1_RX_FIFO0_WRDS
519                + MCAN1_RX_FIFO1_WRDS],
520                &can1MsgRam[MCAN1_STD_FLTS_WRDS + MCAN1_EXT_FLTS_WRDS + MCAN1_RX_FIFO0_WRDS
521                + MCAN1_RX_FIFO1_WRDS + MCAN1_RX_DED_BUFS_WRDS],
522                &can1MsgRam[MCAN1_STD_FLTS_WRDS + MCAN1_EXT_FLTS_WRDS + MCAN1_RX_FIFO0_WRDS
523                + MCAN1_RX_FIFO1_WRDS + MCAN1_RX_DED_BUFS_WRDS + MCAN1_TX_EVT_FIFO_WRDS],
524                &can1MsgRam[MCAN1_STD_FLTS_WRDS + MCAN1_EXT_FLTS_WRDS + MCAN1_RX_FIFO0_WRDS
525                + MCAN1_RX_FIFO1_WRDS + MCAN1_RX_DED_BUFS_WRDS + MCAN1_TX_EVT_FIFO_WRDS
526                + MCAN1_TX_DED_BUF_WRDS]
527        },
528};
529
530
531/*---------------------------------------------------------------------------
532 *      Exported Functions
533 *---------------------------------------------------------------------------*/
534/**
535* \brief Initializes the MCAN hardware for giving peripheral.
536* Default: Mixed mode TX Buffer + FIFO.
537*
538* \param mcanConfig  Pointer to a MCAN instance.
539*/
540void MCAN_Init(const MCan_ConfigType *mcanConfig)
541{
542        Mcan       *mcan = mcanConfig->pMCan;
543        uint32_t    regVal32;
544        uint32_t   *pMsgRam;
545        uint32_t    cntr;
546        IRQn_Type   mCanLine0Irq;
547
548        /* Both MCAN controllers use programmable clock 5 to derive bit rate */
549        // select MCK divided by 1 as programmable clock 5 output
550        PMC->PMC_PCK[5] = PMC_PCK_PRES(MCAN_PROG_CLK_PRESCALER - 1) |
551                                          MCAN_PROG_CLK_SELECT;
552        PMC->PMC_SCER = PMC_SCER_PCK5;
553
554        if (MCAN0 ==  mcan) {
555#ifndef __rtems__
556                PIO_Configure(pinsMcan0, PIO_LISTSIZE(pinsMcan0));
557#endif /* __rtems__ */
558                // Enable MCAN peripheral clock
559                PMC_EnablePeripheral(ID_MCAN0);
560                // Configure Message RAM Base Address
561                regVal32 = MATRIX->CCFG_CAN0 & 0x000001FF;
562                MATRIX->CCFG_CAN0 = regVal32 |
563                                                        ((uint32_t) mcanConfig->msgRam.pStdFilts & 0xFFFF0000);
564                mCanLine0Irq = MCAN0_IRQn;
565        } else if (MCAN1 ==  mcan) {
566#ifndef __rtems__
567                PIO_Configure(pinsMcan1, PIO_LISTSIZE(pinsMcan1));
568#endif /* __rtems__ */
569                // Enable MCAN peripheral clock
570                PMC_EnablePeripheral(ID_MCAN1);
571                // Configure Message RAM Base Address
572                regVal32 = MATRIX->CCFG_SYSIO & 0x0000FFFF;
573                MATRIX->CCFG_SYSIO = regVal32 | ((uint32_t) mcanConfig->msgRam.pStdFilts &
574                                                                                  0xFFFF0000);
575                mCanLine0Irq = MCAN1_IRQn;
576        } else
577                return;
578
579        /* Indicates Initialization state */
580        mcan->MCAN_CCCR = MCAN_CCCR_INIT_ENABLED;
581
582        do { regVal32 = mcan->MCAN_CCCR; }
583        while (0u == (regVal32 & MCAN_CCCR_INIT_ENABLED));
584
585        /* Enable writing to configuration registers */
586        mcan->MCAN_CCCR = MCAN_CCCR_INIT_ENABLED | MCAN_CCCR_CCE_CONFIGURABLE;
587
588        /* Global Filter Configuration: Reject remote frames, reject non-matching frames */
589        mcan->MCAN_GFC = MCAN_GFC_RRFE_REJECT | MCAN_GFC_RRFS_REJECT
590                                         | MCAN_GFC_ANFE(2) | MCAN_GFC_ANFS(2);
591
592        // Extended ID Filter AND mask
593        mcan->MCAN_XIDAM = 0x1FFFFFFF;
594
595        /* Interrupt configuration - leave initialization with all interrupts off */
596        // Disable all interrupts
597        mcan->MCAN_IE =  0;
598        mcan->MCAN_TXBTIE = 0x00000000;
599        // All interrupts directed to Line 0
600        mcan->MCAN_ILS =  0x00000000;
601        // Disable both interrupt LINE 0 & LINE 1
602        mcan->MCAN_ILE = 0x00;
603        // Clear all interrupt flags
604        mcan->MCAN_IR = 0xFFCFFFFF;
605        /* Enable NVIC - but no interrupts will happen since all sources are
606            disabled in MCAN_IE */
607        NVIC_ClearPendingIRQ(mCanLine0Irq);
608        NVIC_EnableIRQ(mCanLine0Irq);
609        NVIC_ClearPendingIRQ((IRQn_Type) (mCanLine0Irq + 1));
610        NVIC_EnableIRQ((IRQn_Type) (mCanLine0Irq + 1));
611
612        /* Configure CAN bit timing */
613        mcan->MCAN_BTP = mcanConfig->bitTiming;
614        mcan->MCAN_FBTP = mcanConfig->fastBitTiming;
615
616        /* Configure message RAM starting addresses & sizes */
617        mcan->MCAN_SIDFC = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pStdFilts)
618                                           | MCAN_SIDFC_LSS(mcanConfig->nmbrStdFilts);
619        mcan->MCAN_XIDFC = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pExtFilts)
620                                           | MCAN_XIDFC_LSE(mcanConfig->nmbrExtFilts);
621        mcan->MCAN_RXF0C = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pRxFifo0)
622                                           | MCAN_RXF0C_F0S(mcanConfig->nmbrFifo0Elmts);
623        // watermark interrupt off, blocking mode
624        mcan->MCAN_RXF1C = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pRxFifo1)
625                                           | MCAN_RXF1C_F1S(mcanConfig->nmbrFifo1Elmts);
626        // watermark interrupt off, blocking mode
627        mcan->MCAN_RXBC = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pRxDedBuf);
628        mcan->MCAN_TXEFC = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pTxEvtFifo)
629                                           | MCAN_TXEFC_EFS(mcanConfig->nmbrTxEvtFifoElmts);
630        // watermark interrupt off
631        mcan->MCAN_TXBC = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pTxDedBuf)
632                                          | MCAN_TXBC_NDTB(mcanConfig->nmbrTxDedBufElmts)
633                                          | MCAN_TXBC_TFQS(mcanConfig->nmbrTxFifoQElmts);
634        mcan->MCAN_RXESC = ((mcanConfig->rxBufElmtSize >> (29 - MCAN_RXESC_RBDS_Pos)) &
635                                                MCAN_RXESC_RBDS_Msk) |
636                                           ((mcanConfig->rxFifo1ElmtSize >> (29 - MCAN_RXESC_F1DS_Pos)) &
637                                                MCAN_RXESC_F1DS_Msk) |
638                                           ((mcanConfig->rxFifo0ElmtSize >> (29 - MCAN_RXESC_F0DS_Pos)) &
639                                                MCAN_RXESC_F0DS_Msk);
640        mcan->MCAN_TXESC = ((mcanConfig->txBufElmtSize >> (29 - MCAN_TXESC_TBDS_Pos)) &
641                                                MCAN_TXESC_TBDS_Msk);
642
643        /* Configure Message Filters */
644        // ...Disable all standard filters
645        pMsgRam = mcanConfig->msgRam.pStdFilts;
646        cntr = mcanConfig->nmbrStdFilts;
647
648        while (cntr > 0) {
649                *pMsgRam++ = STD_FILT_SFEC_DISABLE;
650                cntr--;
651        }
652
653        // ...Disable all extended filters
654        pMsgRam = mcanConfig->msgRam.pExtFilts;
655        cntr = mcanConfig->nmbrExtFilts;
656
657        while (cntr > 0) {
658                *pMsgRam = EXT_FILT_EFEC_DISABLE;
659                pMsgRam = pMsgRam + 2;
660                cntr--;
661        }
662
663        mcan->MCAN_NDAT1 = 0xFFFFFFFF;  // clear new (rx) data flags
664        mcan->MCAN_NDAT2 = 0xFFFFFFFF;  // clear new (rx) data flags
665
666        regVal32 =  mcan->MCAN_CCCR & ~(MCAN_CCCR_CME_Msk | MCAN_CCCR_CMR_Msk);
667        mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CME_ISO11898_1;
668        mcan->MCAN_CCCR = regVal32 | (MCAN_CCCR_CMR_ISO11898_1 |
669                                                                  MCAN_CCCR_CME_ISO11898_1);
670
671        __DSB();
672        __ISB();
673}
674
675/**
676 * \brief Enables a FUTURE switch to FD mode (tx & rx payloads up to 64 bytes)
677 * but transmits WITHOUT bit rate switching
678 * INIT must be set - so this should be called between MCAN_Init() and
679 * MCAN_Enable()
680 * \param mcanConfig  Pointer to a MCAN instance.
681 */
682void MCAN_InitFdEnable(const MCan_ConfigType *mcanConfig)
683{
684        Mcan      *mcan = mcanConfig->pMCan;
685        uint32_t   regVal32;
686
687        regVal32 =  mcan->MCAN_CCCR & ~MCAN_CCCR_CME_Msk;
688        mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CME(1);
689}
690
691/**
692 * \brief Enables a FUTURE switch to FD mode (tx & rx payloads up to 64 bytes) and transmits
693 * WITH bit rate switching
694 * INIT must be set - so this should be called between MCAN_Init() and MCAN_Enable()
695 * \param mcanConfig  Pointer to a MCAN instance.
696 */
697void MCAN_InitFdBitRateSwitchEnable(const MCan_ConfigType *mcanConfig)
698{
699        Mcan      *mcan = mcanConfig->pMCan;
700        uint32_t   regVal32;
701
702        regVal32 =  mcan->MCAN_CCCR & ~MCAN_CCCR_CME_Msk;
703        mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CME(2);
704}
705
706/**
707 * \brief Initializes the MCAN in loop back mode.
708 * INIT must be set - so this should be called between MCAN_Init() and
709 * MCAN_Enable()
710 * \param mcanConfig  Pointer to a MCAN instance.
711 */
712void MCAN_InitLoopback(const MCan_ConfigType *mcanConfig)
713{
714        Mcan *mcan = mcanConfig->pMCan;
715
716        mcan->MCAN_CCCR |= MCAN_CCCR_TEST_ENABLED;
717        //mcan->MCAN_CCCR |= MCAN_CCCR_MON_ENABLED;  // for internal loop back
718        mcan->MCAN_TEST |= MCAN_TEST_LBCK_ENABLED;
719}
720
721/**
722 * \brief Initializes MCAN queue for TX
723 * INIT must be set - so this should be called between MCAN_Init() and
724 * MCAN_Enable()
725 * \param mcanConfig  Pointer to a MCAN instance.
726 */
727void MCAN_InitTxQueue(const MCan_ConfigType *mcanConfig)
728{
729        Mcan *mcan = mcanConfig->pMCan;
730        mcan->MCAN_TXBC |= MCAN_TXBC_TFQM;
731}
732
733/**
734 * \brief Enable MCAN peripheral.
735 * INIT must be set - so this should be called between MCAN_Init()
736 * \param mcanConfig  Pointer to a MCAN instance.
737 */
738void MCAN_Enable(const MCan_ConfigType *mcanConfig)
739{
740        Mcan *mcan = mcanConfig->pMCan;
741        mcan->MCAN_CCCR &= ~MCAN_CCCR_INIT_ENABLED;
742}
743
744/**
745 * \brief Requests switch to Iso11898-1 (standard / classic) mode (tx & rx
746 * payloads up to 8 bytes).
747 * \param mcanConfig  Pointer to a MCAN instance.
748 */
749void MCAN_RequestIso11898_1(const MCan_ConfigType *mcanConfig)
750{
751        Mcan      *mcan = mcanConfig->pMCan;
752        uint32_t   regVal32;
753
754        regVal32 =  mcan->MCAN_CCCR & ~MCAN_CCCR_CMR_Msk;
755        mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CMR_ISO11898_1;
756
757        while ((mcan->MCAN_CCCR & (MCAN_CCCR_FDBS | MCAN_CCCR_FDO)) != 0)
758        { /* wait */ }
759}
760
761/**
762 * \brief Requests switch to FD mode (tx & rx payloads up to 64 bytes) but
763 * transmits WITHOUT bit
764 * rate switching. requested mode should have been enabled at initialization
765 * \param mcanConfig  Pointer to a MCAN instance.
766 */
767void MCAN_RequestFd(const MCan_ConfigType *mcanConfig)
768{
769        Mcan      *mcan = mcanConfig->pMCan;
770        uint32_t   regVal32;
771
772        if ((mcan->MCAN_CCCR & MCAN_CCCR_CME_Msk) == MCAN_CCCR_CME(1)) {
773                regVal32 =  mcan->MCAN_CCCR & ~MCAN_CCCR_CMR_Msk;
774                mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CMR_FD;
775
776                while ((mcan->MCAN_CCCR & MCAN_CCCR_FDO) == 0) { /* wait */ }
777        }
778}
779
780/**
781 * \brief Request switch to FD mode (tx & rx payloads up to 64 bytes) and
782 * transmits WITH bit rate switching.
783 * requested mode should have been enabled at initialization
784 * \param mcanConfig  Pointer to a MCAN instance.
785 */
786void MCAN_RequestFdBitRateSwitch(const MCan_ConfigType *mcanConfig)
787{
788        Mcan      *mcan = mcanConfig->pMCan;
789        uint32_t   regVal32;
790
791        if ((mcan->MCAN_CCCR & MCAN_CCCR_CME_Msk) == MCAN_CCCR_CME(2)) {
792                regVal32 =  mcan->MCAN_CCCR & ~MCAN_CCCR_CMR_Msk;
793                mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CMR_FD_BITRATE_SWITCH;
794
795                while ((mcan->MCAN_CCCR & (MCAN_CCCR_FDBS | MCAN_CCCR_FDO)) !=
796                                (MCAN_CCCR_FDBS | MCAN_CCCR_FDO)) { /* wait */ }
797        }
798}
799
800/**
801 * \brief Switch on loop back mode.
802 * TEST must be set in MCAN_CCCR - e.g. by a prior call to MCAN_InitLoopback()
803 * \param mcanConfig  Pointer to a MCAN instance.
804 */
805void MCAN_LoopbackOn(const MCan_ConfigType *mcanConfig)
806{
807        Mcan *mcan = mcanConfig->pMCan;
808        mcan->MCAN_TEST |= MCAN_TEST_LBCK_ENABLED;
809}
810
811/**
812 * \brief Switch off loop back mode.
813 * \param mcanConfig  Pointer to a MCAN instance.
814 */
815void MCAN_LoopbackOff(const MCan_ConfigType *mcanConfig)
816{
817        Mcan *mcan = mcanConfig->pMCan;
818        mcan->MCAN_TEST &= ~MCAN_TEST_LBCK_ENABLED;
819}
820
821/**
822 * \brief Enable message line and message stored to Dedicated Receive Buffer
823 * Interrupt Line.
824 * \param mcanConfig  Pointer to a MCAN instance.
825 * \param line  Message line.
826 */
827void MCAN_IEnableMessageStoredToRxDedBuffer(const MCan_ConfigType *mcanConfig,
828                MCan_IntrLineType line)
829{
830        Mcan *mcan = mcanConfig->pMCan;
831
832        if (line == CAN_INTR_LINE_0) {
833                mcan->MCAN_ILS &= ~MCAN_ILS_DRXL;
834                mcan->MCAN_ILE |= MCAN_ILE_EINT0;
835        } else  {
836                // Interrupt Line 1
837                mcan->MCAN_ILS |= MCAN_ILS_DRXL;
838                mcan->MCAN_ILE |= MCAN_ILE_EINT1;
839        }
840
841        mcan->MCAN_IR = MCAN_IR_DRX;  // clear previous flag
842        mcan->MCAN_IE |= MCAN_IE_DRXE;  // enable it
843}
844
845/**
846 * \brief Configures a Dedicated TX Buffer.
847 * \param mcanConfig  Pointer to a MCAN instance.
848 * \param buffer  Pointer to buffer.
849 * \param id  Message ID.
850 * \param idType  Type of ID
851 * \param dlc  Type of dlc.
852 */
853uint8_t   *MCAN_ConfigTxDedBuffer(const MCan_ConfigType *mcanConfig,
854                                                                   uint8_t buffer, uint32_t id, MCan_IdType idType, MCan_DlcType dlc)
855{
856        Mcan *mcan = mcanConfig->pMCan;
857        uint32_t *pThisTxBuf = 0;
858
859        if (buffer < mcanConfig->nmbrTxDedBufElmts) {
860                pThisTxBuf = mcanConfig->msgRam.pTxDedBuf + (buffer *
861                                         (mcanConfig->txBufElmtSize & ELMT_SIZE_MASK));
862
863                if (idType == CAN_STD_ID)
864                        *pThisTxBuf++ = ((id << 18) & (CAN_11_BIT_ID_MASK << 18));
865                else
866                        *pThisTxBuf++ = BUFFER_XTD_MASK | (id & CAN_29_BIT_ID_MASK);
867
868                *pThisTxBuf++ = (uint32_t) dlc << 16;
869                /* enable transmit from buffer to set TC interrupt bit in IR, but
870                interrupt will not happen unless TC interrupt is enabled*/
871                mcan->MCAN_TXBTIE = (1 << buffer);
872        }
873
874        return (uint8_t *) pThisTxBuf;  // now it points to the data field
875}
876
877/**
878 * \brief Send Tx buffer.
879 * \param mcanConfig  Pointer to a MCAN instance.
880 * \param buffer  Pointer to buffer.
881 */
882void MCAN_SendTxDedBuffer(const MCan_ConfigType *mcanConfig, uint8_t buffer)
883{
884        Mcan *mcan = mcanConfig->pMCan;
885
886        if (buffer < mcanConfig->nmbrTxDedBufElmts)
887                mcan->MCAN_TXBAR = (1 << buffer);
888}
889
890/**
891 * \brief Adds Message to TX Fifo / Queue
892 * \param mcanConfig  Pointer to a MCAN instance.
893 * \param id  Message ID.
894 * \param idType  Type of ID
895 * \param dlc  Type of dlc.
896 * \param data  Pointer to data.
897 */
898uint32_t MCAN_AddToTxFifoQ(const MCan_ConfigType *mcanConfig,
899                                                        uint32_t id, MCan_IdType idType, MCan_DlcType dlc, uint8_t *data)
900{
901        Mcan *mcan = mcanConfig->pMCan;
902        uint32_t   putIdx = 255;
903        uint32_t *pThisTxBuf = 0;
904        uint8_t   *pTxData;
905        uint8_t    msgLength;
906        uint8_t    cnt;
907
908        // Configured for FifoQ and FifoQ not full?
909        if ((mcanConfig->nmbrTxFifoQElmts > 0) &&
910                ((mcan->MCAN_TXFQS & MCAN_TXFQS_TFQF) == 0)) {
911                putIdx = (mcan->MCAN_TXFQS & MCAN_TXFQS_TFQPI_Msk) >> MCAN_TXFQS_TFQPI_Pos;
912                pThisTxBuf = mcanConfig->msgRam.pTxDedBuf + (putIdx *
913                                         (mcanConfig->txBufElmtSize & ELMT_SIZE_MASK));
914
915                if (idType == CAN_STD_ID)
916                        *pThisTxBuf++ = ((id << 18) & (CAN_11_BIT_ID_MASK << 18));
917                else
918                        *pThisTxBuf++ = BUFFER_XTD_MASK | (id & CAN_29_BIT_ID_MASK);
919
920                *pThisTxBuf++ = (uint32_t) dlc << 16;
921                pTxData = (uint8_t *) pThisTxBuf;
922                msgLength = dlcToMsgLength[dlc];
923
924                for (cnt = 0; cnt < msgLength; cnt++)
925                        *pTxData++ = *data++;
926
927                /* enable transmit from buffer to set TC interrupt bit in IR, but
928                interrupt will not happen unless TC interrupt is enabled */
929                mcan->MCAN_TXBTIE = (1 << putIdx);
930                // request to send
931                mcan->MCAN_TXBAR = (1 << putIdx);
932        }
933
934        return putIdx;  // now it points to the data field
935}
936
937/**
938 * \brief Check if data transmitted from buffer/fifo/queue
939 * \param mcanConfig  Pointer to a MCAN instance.
940 * \param buffer  Pointer to data buffer.
941 */
942uint8_t MCAN_IsBufferTxd(const MCan_ConfigType *mcanConfig, uint8_t buffer)
943{
944        Mcan *mcan = mcanConfig->pMCan;
945
946        return (mcan->MCAN_TXBTO & (1 << buffer));
947}
948
949/**
950 * \brief Configure RX Buffer Filter
951 * ID must match exactly for a RX Buffer Filter
952 * \param mcanConfig  Pointer to a MCAN instance.
953 * \param buffer  Pointer to data buffer.
954 * \param filter  data of filter.
955 * \param idType  Type of ID
956 */
957void MCAN_ConfigRxBufferFilter(const MCan_ConfigType *mcanConfig,
958                                                                uint32_t buffer, uint32_t filter, uint32_t id, MCan_IdType idType)
959{
960        uint32_t *pThisRxFilt = 0;
961
962        if (buffer < mcanConfig->nmbrRxDedBufElmts) {
963                if (idType == CAN_STD_ID) {
964                        if ((filter < mcanConfig->nmbrStdFilts)
965                                && (id <= CAN_11_BIT_ID_MASK)) {
966                                pThisRxFilt = mcanConfig->msgRam.pStdFilts + filter;
967                                // 1 word per filter
968                                *pThisRxFilt = STD_FILT_SFEC_BUFFER | (id << 16) |
969                                                           STD_FILT_SFID2_RX_BUFFER | buffer;
970                        }
971                } else {
972                        // extended ID
973                        if ((filter < mcanConfig->nmbrExtFilts) &&
974                                (id <= CAN_29_BIT_ID_MASK)) {
975                                pThisRxFilt = mcanConfig->msgRam.pExtFilts + (2 * filter);
976                                // 2 words per filter
977                                *pThisRxFilt++ = (uint32_t) EXT_FILT_EFEC_BUFFER | id;
978                                *pThisRxFilt = EXT_FILT_EFID2_RX_BUFFER | buffer;
979                        }
980                }
981        }
982}
983
984/**
985 * \brief Configure Classic Filter
986 * Classic Filters direct accepted messages to a FIFO & include both a ID and
987 * a ID mask
988 * \param mcanConfig  Pointer to a MCAN instance.
989 * \param buffer  Pointer to data buffer.
990 * \param fifo   fifo Number.
991 * \param filter  data of filter.
992 * \param idType  Type of ID
993 * \param mask  Mask to be match
994 */
995void MCAN_ConfigRxClassicFilter(const MCan_ConfigType *mcanConfig,
996                                                                 MCan_FifoType fifo, uint8_t filter, uint32_t id,
997                                                                 MCan_IdType idType, uint32_t mask)
998{
999        uint32_t *pThisRxFilt = 0;
1000        uint32_t   filterTemp;
1001
1002        if (idType == CAN_STD_ID) {
1003                if ((filter < mcanConfig->nmbrStdFilts) && (id <= CAN_11_BIT_ID_MASK)
1004                        && (mask <= CAN_11_BIT_ID_MASK)) {
1005                        pThisRxFilt = mcanConfig->msgRam.pStdFilts + filter;
1006                        // 1 word per filter
1007                        filterTemp = (uint32_t) STD_FILT_SFT_CLASSIC | (id << 16) | mask;
1008
1009                        if (fifo == CAN_FIFO_0)
1010                                *pThisRxFilt = STD_FILT_SFEC_FIFO0 | filterTemp;
1011                        else if (fifo == CAN_FIFO_1)
1012                                *pThisRxFilt = STD_FILT_SFEC_FIFO1 | filterTemp;
1013                }
1014        } else {
1015                // extended ID
1016                if ((filter < mcanConfig->nmbrExtFilts)
1017                        && (id <= CAN_29_BIT_ID_MASK)
1018                        && (mask <= CAN_29_BIT_ID_MASK)) {
1019                        pThisRxFilt = mcanConfig->msgRam.pExtFilts + (2 * filter);
1020
1021                        // 2 words per filter
1022                        if (fifo == CAN_FIFO_0)
1023                                *pThisRxFilt++ = EXT_FILT_EFEC_FIFO0 | id;
1024                        else if (fifo == CAN_FIFO_1)
1025                                *pThisRxFilt++ = EXT_FILT_EFEC_FIFO1 | id;
1026
1027                        *pThisRxFilt = (uint32_t) EXT_FILT_EFT_CLASSIC | mask;
1028                }
1029        }
1030}
1031
1032/**
1033 * \brief check if data received into buffer
1034 * \param mcanConfig  Pointer to a MCAN instance.
1035 * \param buffer  Pointer to data buffer.
1036 */
1037uint8_t MCAN_IsNewDataInRxDedBuffer(const MCan_ConfigType *mcanConfig,
1038                                                                         uint8_t buffer)
1039{
1040        Mcan *mcan = mcanConfig->pMCan;
1041
1042        if (buffer < 32)
1043                return (mcan->MCAN_NDAT1 & (1 << buffer));
1044        else if (buffer < 64)
1045                return (mcan->MCAN_NDAT1 & (1 << (buffer - 32)));
1046        else
1047                return 0;
1048}
1049
1050/**
1051 * \brief Get Rx buffer
1052 * \param mcanConfig  Pointer to a MCAN instance.
1053 * \param buffer  Pointer to data buffer.
1054 * \param pRxMailbox  Pointer to rx Mailbox.
1055 */
1056void MCAN_GetRxDedBuffer(const MCan_ConfigType *mcanConfig,
1057                                                  uint8_t buffer, Mailbox64Type *pRxMailbox)
1058{
1059        Mcan      *mcan = mcanConfig->pMCan;
1060        uint32_t *pThisRxBuf = 0;
1061        uint32_t   tempRy;  // temp copy of RX buffer word
1062        uint32_t   dlc;
1063        uint8_t   *pRxData;
1064        uint8_t    idx;
1065
1066        if (buffer < mcanConfig->nmbrRxDedBufElmts) {
1067                pThisRxBuf = mcanConfig->msgRam.pRxDedBuf
1068                                         + (buffer * (mcanConfig->rxBufElmtSize & ELMT_SIZE_MASK));
1069                tempRy = *pThisRxBuf++;  // word R0 contains ID
1070
1071                if (tempRy & BUFFER_XTD_MASK) {
1072                        // extended ID?
1073                        pRxMailbox->info.id = tempRy & BUFFER_EXT_ID_MASK;
1074                } else {
1075                        // standard ID
1076                        pRxMailbox->info.id = (tempRy & BUFFER_STD_ID_MASK) >> 18;
1077                }
1078
1079                tempRy = *pThisRxBuf++;  // word R1 contains DLC & time stamp
1080                dlc = (tempRy & BUFFER_DLC_MASK) >> 16;
1081                pRxMailbox->info.length = dlcToMsgLength[dlc];
1082                pRxMailbox->info.timestamp = tempRy & BUFFER_RXTS_MASK;
1083                // copy the data from the buffer to the mailbox
1084                pRxData = (uint8_t *) pThisRxBuf;
1085
1086                SCB_CleanDCache_by_Addr((uint32_t *)pRxData, pRxMailbox->info.length);
1087                SCB_CleanDCache_by_Addr((uint32_t *) & (pRxMailbox->data[0]),
1088                                                                pRxMailbox->info.length);
1089
1090                for (idx = 0; idx < pRxMailbox->info.length; idx++)
1091                        pRxMailbox->data[idx] = *pRxData++;
1092
1093                /* clear the new data flag for the buffer */
1094
1095                if (buffer < 32)
1096                        mcan->MCAN_NDAT1 = (1 << buffer);
1097                else
1098                        mcan->MCAN_NDAT1 = (1 << (buffer - 32));
1099
1100        }
1101}
1102
1103/**
1104 * \brief Get from the receive FIFO and place in a application mailbox
1105 * \param mcanConfig  Pointer to a MCAN instance.
1106 * \param fifo  Fifo Number
1107 * \param pRxMailbox  Pointer to rx Mailbox.
1108 * \return: # of fifo entries at the start of the function
1109 *         0 -> FIFO was empty at start
1110 *         1 -> FIFO had 1 entry at start, but is empty at finish
1111 *         2 -> FIFO had 2 entries at start, has 1 entry at finish
1112 */
1113uint32_t MCAN_GetRxFifoBuffer(const MCan_ConfigType *mcanConfig,
1114                                                           MCan_FifoType fifo, Mailbox64Type *pRxMailbox)
1115{
1116        Mcan      *mcan = mcanConfig->pMCan;
1117        uint32_t *pThisRxBuf = 0;
1118        uint32_t   tempRy;  // temp copy of RX buffer word
1119        uint32_t   dlc;
1120        uint8_t   *pRxData;
1121        uint8_t    idx;
1122        uint32_t *fifo_ack_reg;
1123        uint32_t   get_index;
1124        uint32_t   fill_level;
1125        uint32_t   element_size;
1126
1127        // default: fifo empty
1128        fill_level = 0;
1129
1130        if (fifo == CAN_FIFO_0) {
1131                get_index = (mcan->MCAN_RXF0S & MCAN_RXF0S_F0GI_Msk) >> MCAN_RXF0S_F0GI_Pos;
1132                fill_level = (mcan->MCAN_RXF0S & MCAN_RXF0S_F0FL_Msk) >> MCAN_RXF0S_F0FL_Pos;
1133                pThisRxBuf = mcanConfig->msgRam.pRxFifo0;
1134                element_size = mcanConfig->rxFifo0ElmtSize & ELMT_SIZE_MASK;
1135                fifo_ack_reg = (uint32_t *) &mcan->MCAN_RXF0A;
1136        } else if (fifo == CAN_FIFO_1) {
1137                get_index = (mcan->MCAN_RXF1S & MCAN_RXF1S_F1GI_Msk) >> MCAN_RXF1S_F1GI_Pos;
1138                fill_level = (mcan->MCAN_RXF1S & MCAN_RXF1S_F1FL_Msk) >> MCAN_RXF1S_F1FL_Pos;
1139                pThisRxBuf = mcanConfig->msgRam.pRxFifo1;
1140                element_size = mcanConfig->rxFifo1ElmtSize & ELMT_SIZE_MASK;
1141                fifo_ack_reg = (uint32_t *) &mcan->MCAN_RXF1A;
1142        }
1143
1144        if (fill_level > 0) {
1145                pThisRxBuf = pThisRxBuf + (get_index * element_size);
1146                tempRy = *pThisRxBuf++;  // word R0 contains ID
1147
1148                if (tempRy & BUFFER_XTD_MASK) {
1149                        // extended ID?
1150                        pRxMailbox->info.id = tempRy & BUFFER_EXT_ID_MASK;
1151                } else {
1152                        // standard ID
1153                        pRxMailbox->info.id = (tempRy & BUFFER_STD_ID_MASK) >> 18;
1154                }
1155
1156                tempRy = *pThisRxBuf++;  // word R1 contains DLC & timestamps
1157                dlc = (tempRy & BUFFER_DLC_MASK) >> 16;
1158                pRxMailbox->info.length = dlcToMsgLength[dlc];
1159                pRxMailbox->info.timestamp = tempRy & BUFFER_RXTS_MASK;
1160                /* copy the data from the buffer to the mailbox */
1161                pRxData = (uint8_t *) pThisRxBuf;
1162
1163                for (idx = 0; idx < pRxMailbox->info.length; idx++)
1164                        pRxMailbox->data[idx] = *pRxData++;
1165
1166                // acknowledge reading the fifo entry
1167                *fifo_ack_reg = get_index;
1168                /* return entries remaining in FIFO */
1169        }
1170
1171        return (fill_level);
1172}
1173
1174/**@}*/
1175
Note: See TracBrowser for help on using the repository browser.