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

5
Last change on this file since e1eeb883 was e1eeb883, checked in by Sebastian Huber <sebastian.huber@…>, on Jan 12, 2016 at 2:34:31 PM

bsp/atsam: Import SAM Software Package

Import selected files of the "SAM V71 / V70 / E70 / S70 Software
Package" obtained from the "SAMV71-XULT GNU Software Package 1.5".

Converted files via dos2unix before import.

Update #2529.

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