SAMV71 Xplained Ultra Software Package 1.5

mcan.c

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------- */
00002 /*                  Atmel Microcontroller Software Support                      */
00003 /*                       SAM Software Package License                           */
00004 /* ---------------------------------------------------------------------------- */
00005 /* Copyright (c) 2015, Atmel Corporation                                        */
00006 /*                                                                              */
00007 /* All rights reserved.                                                         */
00008 /*                                                                              */
00009 /* Redistribution and use in source and binary forms, with or without           */
00010 /* modification, are permitted provided that the following condition is met:    */
00011 /*                                                                              */
00012 /* - Redistributions of source code must retain the above copyright notice,     */
00013 /* this list of conditions and the disclaimer below.                            */
00014 /*                                                                              */
00015 /* Atmel's name may not be used to endorse or promote products derived from     */
00016 /* this software without specific prior written permission.                     */
00017 /*                                                                              */
00018 /* DISCLAIMER:  THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR   */
00019 /* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
00020 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE   */
00021 /* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,      */
00022 /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
00023 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,  */
00024 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    */
00025 /* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING         */
00026 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
00027 /* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                           */
00028 /* ---------------------------------------------------------------------------- */
00029 
00030 /** \file
00031  *  Implements functions for Controller Area Network (CAN)
00032  *  peripheral operations.
00033  */
00034 /** \addtogroup can_module
00035  *@{*/
00036 
00037 
00038 /*----------------------------------------------------------------------------
00039  *        Headers
00040  *----------------------------------------------------------------------------*/
00041 #include "board.h"
00042 #include "chip.h"
00043 #include "mcan_config.h"
00044 #include <assert.h>
00045 /*---------------------------------------------------------------------------
00046  *      Definitions
00047  *---------------------------------------------------------------------------*/
00048 #define MAILBOX_ADDRESS(address) (0xFFFC & (address))
00049 
00050 #define CAN_CLK_FREQ_HZ               MCAN_PROG_CLK_FREQ_HZ
00051 
00052 #define MCAN0_TSEG1                   (MCAN0_PROP_SEG + MCAN0_PHASE_SEG1)
00053 #define MCAN0_TSEG2                   (MCAN0_PHASE_SEG2)
00054 #define MCAN0_BRP                     ((uint32_t) (((float) CAN_CLK_FREQ_HZ / \
00055                                        ((float)(MCAN0_TSEG1 + MCAN0_TSEG2 + 3) *\
00056                                         (float) MCAN0_BIT_RATE_BPS)) - 1))
00057 #define MCAN0_SJW                     (MCAN0_SYNC_JUMP - 1)
00058 #define MCAN0_FTSEG1                  (MCAN0_FAST_PROP_SEG + MCAN0_FAST_PHASE_SEG1)
00059 #define MCAN0_FTSEG2                  (MCAN0_FAST_PHASE_SEG2)
00060 #define MCAN0_FBRP                    ((uint32_t) (((float) CAN_CLK_FREQ_HZ / \
00061                                        ((float)(MCAN0_FTSEG1 + MCAN0_FTSEG2 + 3) * \
00062                                         (float) MCAN0_FAST_BIT_RATE_BPS)) - 1))
00063 #define MCAN0_FSJW                    (MCAN0_FAST_SYNC_JUMP - 1)
00064 
00065 #define MCAN0_STD_FLTS_WRDS           (MCAN0_NMBR_STD_FLTS)
00066 /* 128 max filters */
00067 #define MCAN0_EXT_FLTS_WRDS           (MCAN0_NMBR_EXT_FLTS * 2)
00068 /* 64 max filters */
00069 #define MCAN0_RX_FIFO0_WRDS           (MCAN0_NMBR_RX_FIFO0_ELMTS * \
00070                                        ((MCAN0_RX_FIFO0_ELMT_SZ/4) + 2))
00071 /* 64 elements max */
00072 #define MCAN0_RX_FIFO1_WRDS           (MCAN0_NMBR_RX_FIFO1_ELMTS *\
00073                                        ((MCAN0_RX_FIFO1_ELMT_SZ/4) + 2))
00074 /* 64 elements max */
00075 #define MCAN0_RX_DED_BUFS_WRDS            (MCAN0_NMBR_RX_DED_BUF_ELMTS * \
00076         ((MCAN0_RX_BUF_ELMT_SZ/4) + 2))
00077 /* 64 elements max */
00078 #define MCAN0_TX_EVT_FIFO_WRDS        (MCAN0_NMBR_TX_EVT_FIFO_ELMTS * 2)
00079 /* 32 elements max */
00080 #define MCAN0_TX_DED_BUF_WRDS         (MCAN0_NMBR_TX_DED_BUF_ELMTS * \
00081                                        ((MCAN0_TX_BUF_ELMT_SZ/4) + 2))
00082 /* 32 elements max */
00083 #define MCAN0_TX_FIFO_Q_WRDS          (MCAN0_NMBR_TX_FIFO_Q_ELMTS *\
00084                                        ((MCAN0_TX_BUF_ELMT_SZ/4) + 2))
00085 /* 32 elements max */
00086 
00087 #define MCAN1_TSEG1                   (MCAN1_PROP_SEG + MCAN1_PHASE_SEG1)
00088 #define MCAN1_TSEG2                   (MCAN1_PHASE_SEG2)
00089 #define MCAN1_BRP                     ((uint32_t) (((float) CAN_CLK_FREQ_HZ / \
00090                                        ((float)(MCAN1_TSEG1 + MCAN1_TSEG2 + 3) *\
00091                                         (float) MCAN1_BIT_RATE_BPS)) - 1))
00092 #define MCAN1_SJW                     (MCAN1_SYNC_JUMP - 1)
00093 #define MCAN1_FTSEG1                  (MCAN1_FAST_PROP_SEG + MCAN1_FAST_PHASE_SEG1)
00094 #define MCAN1_FTSEG2                  (MCAN1_FAST_PHASE_SEG2)
00095 #define MCAN1_FBRP                    ((uint32_t) (((float) CAN_CLK_FREQ_HZ /\
00096                                        ((float)(MCAN1_FTSEG1 + MCAN1_FTSEG2 + 3) *\
00097                                         (float) MCAN1_FAST_BIT_RATE_BPS)) - 1))
00098 #define MCAN1_FSJW                    (MCAN1_FAST_SYNC_JUMP - 1)
00099 
00100 #define MCAN1_STD_FLTS_WRDS           (MCAN1_NMBR_STD_FLTS)
00101 /* 128 max filters */
00102 #define MCAN1_EXT_FLTS_WRDS           (MCAN1_NMBR_EXT_FLTS * 2)
00103 /* 64 max filters */
00104 #define MCAN1_RX_FIFO0_WRDS           (MCAN1_NMBR_RX_FIFO0_ELMTS * \
00105                                        ((MCAN1_RX_FIFO0_ELMT_SZ/4) + 2))
00106 /* 64 elements max */
00107 #define MCAN1_RX_FIFO1_WRDS           (MCAN1_NMBR_RX_FIFO1_ELMTS *\
00108                                        ((MCAN1_RX_FIFO1_ELMT_SZ/4) + 2))
00109 /* 64 elements max */
00110 #define MCAN1_RX_DED_BUFS_WRDS            (MCAN1_NMBR_RX_DED_BUF_ELMTS * \
00111         ((MCAN1_RX_BUF_ELMT_SZ/4) + 2))
00112 /* 64 elements max */
00113 #define MCAN1_TX_EVT_FIFO_WRDS        (MCAN1_NMBR_TX_EVT_FIFO_ELMTS * 2)
00114 /* 32 elements max */
00115 #define MCAN1_TX_DED_BUF_WRDS         (MCAN1_NMBR_TX_DED_BUF_ELMTS * \
00116                                        ((MCAN1_TX_BUF_ELMT_SZ/4) + 2))
00117 /* 32 elements max */
00118 #define MCAN1_TX_FIFO_Q_WRDS          (MCAN1_NMBR_TX_FIFO_Q_ELMTS * \
00119                                        ((MCAN1_TX_BUF_ELMT_SZ/4) + 2))
00120 /* 32 elements max */
00121 
00122 /* validate CAN0 entries */
00123 #if (MCAN0_TSEG1 > 63)
00124     #error "Invalid CAN0 TSEG1"
00125 #endif
00126 #if (MCAN0_TSEG2 > 15)
00127     #error "Invalid CAN0 TSEG2"
00128 #endif
00129 #if (MCAN0_SJW > 15)
00130     #error "Invalid CAN0 SJW"
00131 #endif
00132 #if (MCAN0_FTSEG1 > 15)
00133     #error "Invalid CAN0 FTSEG1"
00134 #endif
00135 #if (MCAN0_FTSEG2 > 7)
00136     #error "Invalid CAN0 FTSEG2"
00137 #endif
00138 #if (MCAN0_FSJW > 3)
00139     #error "Invalid CAN0 FSJW"
00140 #endif
00141 
00142 #if (MCAN0_NMBR_STD_FLTS > 128)
00143     #error "Invalid CAN0 # of Standard Filters"
00144 #endif
00145 #if (MCAN0_NMBR_EXT_FLTS > 64)
00146     #error "Invalid CAN0 # of Extended Filters"
00147 #endif
00148 #if (MCAN0_NMBR_RX_FIFO0_ELMTS > 64)
00149     #error "Invalid CAN0 # RX FIFO 0 ELEMENTS"
00150 #endif
00151 #if (MCAN0_NMBR_RX_FIFO1_ELMTS > 64)
00152     #error "Invalid CAN0 # RX FIFO 0 ELEMENTS"
00153 #endif
00154 #if (MCAN0_NMBR_RX_DED_BUF_ELMTS > 64)
00155     #error "Invalid CAN0 # RX BUFFER ELEMENTS"
00156 #endif
00157 #if (MCAN0_NMBR_TX_EVT_FIFO_ELMTS > 32)
00158     #error "Invalid CAN0 # TX EVENT FIFO ELEMENTS"
00159 #endif
00160 #if ((MCAN0_NMBR_TX_DED_BUF_ELMTS + MCAN0_NMBR_TX_FIFO_Q_ELMTS)  > 32)
00161     #error "Invalid CAN0 # TX BUFFER ELEMENTS"
00162 #endif
00163 
00164 #if   (8 == MCAN0_RX_FIFO0_ELMT_SZ)
00165     #define MCAN0_RX_FIFO0_DATA_SIZE  (0u)
00166 #elif (12 == MCAN0_RX_FIFO0_ELMT_SZ)
00167     #define MCAN0_RX_FIFO0_DATA_SIZE  (1u)
00168 #elif (16 == MCAN0_RX_FIFO0_ELMT_SZ)
00169     #define MCAN0_RX_FIFO0_DATA_SIZE  (2u)
00170 #elif (20 == MCAN0_RX_FIFO0_ELMT_SZ)
00171     #define MCAN0_RX_FIFO0_DATA_SIZE  (3u)
00172 #elif (24 == MCAN0_RX_FIFO0_ELMT_SZ)
00173     #define MCAN0_RX_FIFO0_DATA_SIZE  (4u)
00174 #elif (32 == MCAN0_RX_FIFO0_ELMT_SZ)
00175     #define MCAN0_RX_FIFO0_DATA_SIZE  (5u)
00176 #elif (48 == MCAN0_RX_FIFO0_ELMT_SZ)
00177     #define MCAN0_RX_FIFO0_DATA_SIZE  (6u)
00178 #elif (64 == MCAN0_RX_FIFO0_ELMT_SZ)
00179     #define MCAN0_RX_FIFO0_DATA_SIZE  (7u)
00180 #else
00181     #error "Invalid CAN0 RX FIFO0 ELEMENT SIZE"
00182 #endif
00183 
00184 #if   (8 == MCAN0_RX_FIFO1_ELMT_SZ)
00185     #define MCAN0_RX_FIFO1_DATA_SIZE  (0u)
00186 #elif (12 == MCAN0_RX_FIFO1_ELMT_SZ)
00187     #define MCAN0_RX_FIFO1_DATA_SIZE  (1u)
00188 #elif (16 == MCAN0_RX_FIFO1_ELMT_SZ)
00189     #define MCAN0_RX_FIFO1_DATA_SIZE  (2u)
00190 #elif (20 == MCAN0_RX_FIFO1_ELMT_SZ)
00191     #define MCAN0_RX_FIFO1_DATA_SIZE  (3u)
00192 #elif (24 == MCAN0_RX_FIFO1_ELMT_SZ)
00193     #define MCAN0_RX_FIFO1_DATA_SIZE  (4u)
00194 #elif (32 == MCAN0_RX_FIFO1_ELMT_SZ)
00195     #define MCAN0_RX_FIFO1_DATA_SIZE  (5u)
00196 #elif (48 == MCAN0_RX_FIFO1_ELMT_SZ)
00197     #define MCAN0_RX_FIFO1_DATA_SIZE  (6u)
00198 #elif (64 == MCAN0_RX_FIFO1_ELMT_SZ)
00199     #define MCAN0_RX_FIFO1_DATA_SIZE  (7u)
00200 #else
00201     #error "Invalid CAN0 RX FIFO1 ELEMENT SIZE"
00202 #endif
00203 
00204 #if   (8 == MCAN0_RX_BUF_ELMT_SZ)
00205     #define MCAN0_RX_BUF_DATA_SIZE  (0u)
00206 #elif (12 == MCAN0_RX_BUF_ELMT_SZ)
00207     #define MCAN0_RX_BUF_DATA_SIZE  (1u)
00208 #elif (16 == MCAN0_RX_BUF_ELMT_SZ)
00209     #define MCAN0_RX_BUF_DATA_SIZE  (2u)
00210 #elif (20 == MCAN0_RX_BUF_ELMT_SZ)
00211     #define MCAN0_RX_BUF_DATA_SIZE  (3u)
00212 #elif (24 == MCAN0_RX_BUF_ELMT_SZ)
00213     #define MCAN0_RX_BUF_DATA_SIZE  (4u)
00214 #elif (32 == MCAN0_RX_BUF_ELMT_SZ)
00215     #define MCAN0_RX_BUF_DATA_SIZE  (5u)
00216 #elif (48 == MCAN0_RX_BUF_ELMT_SZ)
00217     #define MCAN0_RX_BUF_DATA_SIZE  (6u)
00218 #elif (64 == MCAN0_RX_BUF_ELMT_SZ)
00219     #define MCAN0_RX_BUF_DATA_SIZE  (7u)
00220 #else
00221     #error "Invalid CAN0 RX BUFFER ELEMENT SIZE"
00222 #endif
00223 
00224 #if   (8 == MCAN0_TX_BUF_ELMT_SZ)
00225     #define MCAN0_TX_BUF_DATA_SIZE  (0u)
00226 #elif (12 == MCAN0_TX_BUF_ELMT_SZ)
00227     #define MCAN0_TX_BUF_DATA_SIZE  (1u)
00228 #elif (16 == MCAN0_TX_BUF_ELMT_SZ)
00229     #define MCAN0_TX_BUF_DATA_SIZE  (2u)
00230 #elif (20 == MCAN0_TX_BUF_ELMT_SZ)
00231     #define MCAN0_TX_BUF_DATA_SIZE  (3u)
00232 #elif (24 == MCAN0_TX_BUF_ELMT_SZ)
00233     #define MCAN0_TX_BUF_DATA_SIZE  (4u)
00234 #elif (32 == MCAN0_TX_BUF_ELMT_SZ)
00235     #define MCAN0_TX_BUF_DATA_SIZE  (5u)
00236 #elif (48 == MCAN0_TX_BUF_ELMT_SZ)
00237     #define MCAN0_TX_BUF_DATA_SIZE  (6u)
00238 #elif (64 == MCAN0_TX_BUF_ELMT_SZ)
00239     #define MCAN0_TX_BUF_DATA_SIZE  (7u)
00240 #else
00241     #error "Invalid CAN0 TX BUFFER ELEMENT SIZE"
00242 #endif
00243 
00244 /* validate CAN1 entries */
00245 #if (MCAN1_TSEG1 > 63)
00246     #error "Invalid CAN1 TSEG1"
00247 #endif
00248 #if (MCAN1_TSEG2 > 15)
00249     #error "Invalid CAN1 TSEG2"
00250 #endif
00251 #if (MCAN1_SJW > 15)
00252     #error "Invalid CAN1 SJW"
00253 #endif
00254 #if (MCAN1_FTSEG1 > 15)
00255     #error "Invalid CAN1 FTSEG1"
00256 #endif
00257 #if (MCAN1_FTSEG2 > 7)
00258     #error "Invalid CAN1 FTSEG2"
00259 #endif
00260 #if (MCAN1_FSJW > 3)
00261     #error "Invalid CAN1 FSJW"
00262 #endif
00263 
00264 #if (MCAN1_NMBR_STD_FLTS > 128)
00265     #error "Invalid CAN1 # of Standard Filters"
00266 #endif
00267 #if (MCAN1_NMBR_EXT_FLTS > 64)
00268     #error "Invalid CAN1 # of Extended Filters"
00269 #endif
00270 #if (MCAN1_NMBR_RX_FIFO0_ELMTS > 64)
00271     #error "Invalid CAN1 # RX FIFO 0 ELEMENTS"
00272 #endif
00273 #if (MCAN1_NMBR_RX_FIFO1_ELMTS > 64)
00274     #error "Invalid CAN1 # RX FIFO 0 ELEMENTS"
00275 #endif
00276 #if (MCAN1_NMBR_RX_DED_BUF_ELMTS > 64)
00277     #error "Invalid CAN1 # RX BUFFER ELEMENTS"
00278 #endif
00279 #if (MCAN1_NMBR_TX_EVT_FIFO_ELMTS > 32)
00280     #error "Invalid CAN1 # TX EVENT FIFO ELEMENTS"
00281 #endif
00282 #if ((MCAN1_NMBR_TX_DED_BUF_ELMTS + MCAN1_NMBR_TX_FIFO_Q_ELMTS)  > 32)
00283     #error "Invalid CAN1 # TX BUFFER ELEMENTS"
00284 #endif
00285 
00286 #if   (8 == MCAN1_RX_FIFO0_ELMT_SZ)
00287     #define MCAN1_RX_FIFO0_DATA_SIZE  (0u)
00288 #elif (12 == MCAN1_RX_FIFO0_ELMT_SZ)
00289     #define MCAN1_RX_FIFO0_DATA_SIZE  (1u)
00290 #elif (16 == MCAN1_RX_FIFO0_ELMT_SZ)
00291     #define MCAN1_RX_FIFO0_DATA_SIZE  (2u)
00292 #elif (20 == MCAN1_RX_FIFO0_ELMT_SZ)
00293     #define MCAN1_RX_FIFO0_DATA_SIZE  (3u)
00294 #elif (24 == MCAN1_RX_FIFO0_ELMT_SZ)
00295     #define MCAN1_RX_FIFO0_DATA_SIZE  (4u)
00296 #elif (32 == MCAN1_RX_FIFO0_ELMT_SZ)
00297     #define MCAN1_RX_FIFO0_DATA_SIZE  (5u)
00298 #elif (48 == MCAN1_RX_FIFO0_ELMT_SZ)
00299     #define MCAN1_RX_FIFO0_DATA_SIZE  (6u)
00300 #elif (64 == MCAN1_RX_FIFO0_ELMT_SZ)
00301     #define MCAN1_RX_FIFO0_DATA_SIZE  (7u)
00302 #else
00303     #error "Invalid CAN1 RX FIFO0 ELEMENT SIZE"
00304 #endif
00305 
00306 #if   (8 == MCAN1_RX_FIFO1_ELMT_SZ)
00307     #define MCAN1_RX_FIFO1_DATA_SIZE  (0u)
00308 #elif (12 == MCAN1_RX_FIFO1_ELMT_SZ)
00309     #define MCAN1_RX_FIFO1_DATA_SIZE  (1u)
00310 #elif (16 == MCAN1_RX_FIFO1_ELMT_SZ)
00311     #define MCAN1_RX_FIFO1_DATA_SIZE  (2u)
00312 #elif (20 == MCAN1_RX_FIFO1_ELMT_SZ)
00313     #define MCAN1_RX_FIFO1_DATA_SIZE  (3u)
00314 #elif (24 == MCAN1_RX_FIFO1_ELMT_SZ)
00315     #define MCAN1_RX_FIFO1_DATA_SIZE  (4u)
00316 #elif (32 == MCAN1_RX_FIFO1_ELMT_SZ)
00317     #define MCAN1_RX_FIFO1_DATA_SIZE  (5u)
00318 #elif (48 == MCAN1_RX_FIFO1_ELMT_SZ)
00319     #define MCAN1_RX_FIFO1_DATA_SIZE  (6u)
00320 #elif (64 == MCAN1_RX_FIFO1_ELMT_SZ)
00321     #define MCAN1_RX_FIFO1_DATA_SIZE  (7u)
00322 #else
00323     #error "Invalid CAN1 RX FIFO1 ELEMENT SIZE"
00324 #endif
00325 
00326 #if   (8 == MCAN1_RX_BUF_ELMT_SZ)
00327     #define MCAN1_RX_BUF_DATA_SIZE  (0u)
00328 #elif (12 == MCAN1_RX_BUF_ELMT_SZ)
00329     #define MCAN1_RX_BUF_DATA_SIZE  (1u)
00330 #elif (16 == MCAN1_RX_BUF_ELMT_SZ)
00331     #define MCAN1_RX_BUF_DATA_SIZE  (2u)
00332 #elif (20 == MCAN1_RX_BUF_ELMT_SZ)
00333     #define MCAN1_RX_BUF_DATA_SIZE  (3u)
00334 #elif (24 == MCAN1_RX_BUF_ELMT_SZ)
00335     #define MCAN1_RX_BUF_DATA_SIZE  (4u)
00336 #elif (32 == MCAN1_RX_BUF_ELMT_SZ)
00337     #define MCAN1_RX_BUF_DATA_SIZE  (5u)
00338 #elif (48 == MCAN1_RX_BUF_ELMT_SZ)
00339     #define MCAN1_RX_BUF_DATA_SIZE  (6u)
00340 #elif (64 == MCAN1_RX_BUF_ELMT_SZ)
00341     #define MCAN1_RX_BUF_DATA_SIZE  (7u)
00342 #else
00343     #error "Invalid CAN1 RX BUFFER ELEMENT SIZE"
00344 #endif
00345 
00346 #if   (8 == MCAN1_TX_BUF_ELMT_SZ)
00347     #define MCAN1_TX_BUF_DATA_SIZE  (0u)
00348 #elif (12 == MCAN1_TX_BUF_ELMT_SZ)
00349     #define MCAN1_TX_BUF_DATA_SIZE  (1u)
00350 #elif (16 == MCAN1_TX_BUF_ELMT_SZ)
00351     #define MCAN1_TX_BUF_DATA_SIZE  (2u)
00352 #elif (20 == MCAN1_TX_BUF_ELMT_SZ)
00353     #define MCAN1_TX_BUF_DATA_SIZE  (3u)
00354 #elif (24 == MCAN1_TX_BUF_ELMT_SZ)
00355     #define MCAN1_TX_BUF_DATA_SIZE  (4u)
00356 #elif (32 == MCAN1_TX_BUF_ELMT_SZ)
00357     #define MCAN1_TX_BUF_DATA_SIZE  (5u)
00358 #elif (48 == MCAN1_TX_BUF_ELMT_SZ)
00359     #define MCAN1_TX_BUF_DATA_SIZE  (6u)
00360 #elif (64 == MCAN1_TX_BUF_ELMT_SZ)
00361     #define MCAN1_TX_BUF_DATA_SIZE  (7u)
00362 #else
00363     #error "Invalid CAN1 TX BUFFER ELEMENT SIZE"
00364 #endif
00365 
00366 #define CAN_11_BIT_ID_MASK                 (0x7FF)
00367 #define CAN_29_BIT_ID_MASK                 (0x1FFFFFFF)
00368 #define ELMT_SIZE_MASK                (0x1F)
00369 /* max element size is 18 words, fits in 5 bits */
00370 
00371 #define BUFFER_XTD_MASK               (0x40000000)
00372 #define BUFFER_EXT_ID_MASK            (0x1FFFFFFF)
00373 #define BUFFER_STD_ID_MASK            (0x1FFC0000)
00374 #define BUFFER_DLC_MASK               (0x000F0000)
00375 #define BUFFER_RXTS_MASK              (0x0000FFFF)
00376 
00377 #define STD_FILT_SFT_MASK             (3U << 30)
00378 #define STD_FILT_SFT_RANGE            (0U << 30)
00379 #define STD_FILT_SFT_DUAL             (1U << 30)
00380 #define STD_FILT_SFT_CLASSIC          (2U << 30)
00381 #define STD_FILT_SFEC_MASK            (7U << 27)
00382 #define STD_FILT_SFEC_DISABLE         (0U << 27)
00383 #define STD_FILT_SFEC_FIFO0           (1U << 27)
00384 #define STD_FILT_SFEC_FIFO1           (2U << 27)
00385 #define STD_FILT_SFEC_REJECT          (3U << 27)
00386 #define STD_FILT_SFEC_PRIORITY        (4U << 27)
00387 #define STD_FILT_SFEC_PRIORITY_FIFO0  (5U << 27)
00388 #define STD_FILT_SFEC_PRIORITY_FIFO1  (6U << 27)
00389 #define STD_FILT_SFEC_BUFFER          (7U << 27)
00390 #define STD_FILT_SFID1_MASK           (0x03FFU << 16)
00391 #define STD_FILT_SFID2_MASK           (0x3FFU << 0)
00392 #define STD_FILT_SFID2_RX_BUFFER      (0U << 9)
00393 #define STD_FILT_SFID2_DEBUG_A        (1U << 9)
00394 #define STD_FILT_SFID2_DEBUG_B        (2U << 9)
00395 #define STD_FILT_SFID2_DEBUG_C        (3U << 9)
00396 #define STD_FILT_SFID2_BUFFER(nmbr)   (nmbr & 0x3F)
00397 
00398 #define EXT_FILT_EFEC_MASK            (7U << 29)
00399 #define EXT_FILT_EFEC_DISABLE         (0U << 29)
00400 #define EXT_FILT_EFEC_FIFO0           (1U << 29)
00401 #define EXT_FILT_EFEC_FIFO1           (2U << 29)
00402 #define EXT_FILT_EFEC_REJECT          (3U << 29)
00403 #define EXT_FILT_EFEC_PRIORITY        (4U << 29)
00404 #define EXT_FILT_EFEC_PRIORITY_FIFO0  (5U << 29)
00405 #define EXT_FILT_EFEC_PRIORITY_FIFO1  (6U << 29)
00406 #define EXT_FILT_EFEC_BUFFER          (7U << 29)
00407 #define EXT_FILT_EFID1_MASK           (0x1FFFFFFF)
00408 #define EXT_FILT_EFT_MASK             (3U << 30)
00409 #define EXT_FILT_EFT_RANGE            (0U << 30)
00410 #define EXT_FILT_EFT_DUAL             (1U << 30)
00411 #define EXT_FILT_EFT_CLASSIC          (2U << 30)
00412 #define EXT_FILT_EFT_RANGE_NO_XIDAM   (3U << 30)
00413 #define EXT_FILT_EFID2_MASK           (0x1FFFFFFF)
00414 #define EXT_FILT_EFID2_RX_BUFFER      (0U << 9)
00415 #define EXT_FILT_EFID2_DEBUG_A        (1U << 9)
00416 #define EXT_FILT_EFID2_DEBUG_B        (2U << 9)
00417 #define EXT_FILT_EFID2_DEBUG_C        (3U << 9)
00418 #define EXT_FILT_EFID2_BUFFER(nmbr)   (nmbr & 0x3F)
00419 
00420 
00421 /*---------------------------------------------------------------------------
00422  *      Internal variables
00423  *---------------------------------------------------------------------------*/
00424 
00425 static const Pin pinsMcan0[] =  {PIN_MCAN0_TXD, PIN_MCAN0_RXD };
00426 static const Pin pinsMcan1[] =  {PIN_MCAN1_TXD, PIN_MCAN1_RXD };
00427 
00428 static uint32_t can0MsgRam[MCAN0_STD_FLTS_WRDS +
00429                            MCAN0_EXT_FLTS_WRDS +
00430                            MCAN0_RX_FIFO0_WRDS +
00431                            MCAN0_RX_FIFO1_WRDS +
00432                            MCAN0_RX_DED_BUFS_WRDS +
00433                            MCAN0_TX_EVT_FIFO_WRDS +
00434                            MCAN0_TX_DED_BUF_WRDS +
00435                            MCAN0_TX_FIFO_Q_WRDS];
00436 
00437 static uint32_t can1MsgRam[MCAN1_STD_FLTS_WRDS +
00438                            MCAN1_EXT_FLTS_WRDS +
00439                            MCAN1_RX_FIFO0_WRDS +
00440                            MCAN1_RX_FIFO1_WRDS +
00441                            MCAN1_RX_DED_BUFS_WRDS +
00442                            MCAN1_TX_EVT_FIFO_WRDS +
00443                            MCAN1_TX_DED_BUF_WRDS +
00444                            MCAN1_TX_FIFO_Q_WRDS];
00445 
00446 static const uint8_t dlcToMsgLength[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64 };
00447 
00448 const MCan_ConfigType mcan0Config = {
00449     MCAN0,
00450     MCAN_BTP_BRP(MCAN0_BRP) | MCAN_BTP_TSEG1(MCAN0_TSEG1) |
00451     MCAN_BTP_TSEG2(MCAN0_TSEG2) | MCAN_BTP_SJW(MCAN0_SJW),
00452     MCAN_FBTP_FBRP(MCAN0_FBRP) | MCAN_FBTP_FTSEG1(MCAN0_FTSEG1) |
00453     MCAN_FBTP_FTSEG2(MCAN0_FTSEG2) | MCAN_FBTP_FSJW(MCAN0_FSJW),
00454     MCAN0_NMBR_STD_FLTS,
00455     MCAN0_NMBR_EXT_FLTS,
00456     MCAN0_NMBR_RX_FIFO0_ELMTS,
00457     MCAN0_NMBR_RX_FIFO1_ELMTS,
00458     MCAN0_NMBR_RX_DED_BUF_ELMTS,
00459     MCAN0_NMBR_TX_EVT_FIFO_ELMTS,
00460     MCAN0_NMBR_TX_DED_BUF_ELMTS,
00461     MCAN0_NMBR_TX_FIFO_Q_ELMTS,
00462     (MCAN0_RX_FIFO0_DATA_SIZE << 29) | ((MCAN0_RX_FIFO0_ELMT_SZ / 4) + 2),
00463     /* element size in WORDS */
00464     (MCAN0_RX_FIFO1_DATA_SIZE << 29) | ((MCAN0_RX_FIFO1_ELMT_SZ / 4) + 2),
00465     /* element size in WORDS */
00466     (MCAN0_RX_BUF_DATA_SIZE << 29) | ((MCAN0_RX_BUF_ELMT_SZ / 4) + 2),
00467     /* element size in WORDS */
00468     (MCAN0_TX_BUF_DATA_SIZE << 29) | ((MCAN0_TX_BUF_ELMT_SZ / 4) + 2),
00469     /* element size in WORDS */
00470     {
00471         &can0MsgRam[0],
00472         &can0MsgRam[MCAN0_STD_FLTS_WRDS],
00473         &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS],
00474         &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS + MCAN0_RX_FIFO0_WRDS],
00475         &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS + MCAN0_RX_FIFO0_WRDS +
00476         MCAN0_RX_FIFO1_WRDS],
00477         &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS + MCAN0_RX_FIFO0_WRDS +
00478         MCAN0_RX_FIFO1_WRDS + MCAN0_RX_DED_BUFS_WRDS],
00479         &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS + MCAN0_RX_FIFO0_WRDS +
00480         MCAN0_RX_FIFO1_WRDS + MCAN0_RX_DED_BUFS_WRDS + MCAN0_TX_EVT_FIFO_WRDS],
00481         &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS + MCAN0_RX_FIFO0_WRDS +
00482         MCAN0_RX_FIFO1_WRDS + MCAN0_RX_DED_BUFS_WRDS + MCAN0_TX_EVT_FIFO_WRDS +
00483         MCAN0_TX_DED_BUF_WRDS]
00484     },
00485 };
00486 
00487 const MCan_ConfigType mcan1Config = {
00488     MCAN1,
00489     MCAN_BTP_BRP(MCAN1_BRP) | MCAN_BTP_TSEG1(MCAN1_TSEG1) |
00490     MCAN_BTP_TSEG2(MCAN1_TSEG2) | MCAN_BTP_SJW(MCAN1_SJW),
00491     MCAN_FBTP_FBRP(MCAN1_FBRP) | MCAN_FBTP_FTSEG1(MCAN1_FTSEG1) |
00492     MCAN_FBTP_FTSEG2(MCAN1_FTSEG2) | MCAN_FBTP_FSJW(MCAN1_FSJW),
00493     MCAN1_NMBR_STD_FLTS,
00494     MCAN1_NMBR_EXT_FLTS,
00495     MCAN1_NMBR_RX_FIFO0_ELMTS,
00496     MCAN1_NMBR_RX_FIFO1_ELMTS,
00497     MCAN0_NMBR_RX_DED_BUF_ELMTS,
00498     MCAN1_NMBR_TX_EVT_FIFO_ELMTS,
00499     MCAN1_NMBR_TX_DED_BUF_ELMTS,
00500     MCAN1_NMBR_TX_FIFO_Q_ELMTS,
00501     (MCAN1_RX_FIFO0_DATA_SIZE << 29) | ((MCAN1_RX_FIFO0_ELMT_SZ / 4) + 2),
00502     /* element size in WORDS */
00503     (MCAN1_RX_FIFO1_DATA_SIZE << 29) | ((MCAN1_RX_FIFO1_ELMT_SZ / 4) + 2),
00504     /* element size in WORDS */
00505     (MCAN1_RX_BUF_DATA_SIZE << 29) | ((MCAN1_RX_BUF_ELMT_SZ / 4) + 2),
00506     /* element size in WORDS */
00507     (MCAN1_TX_BUF_DATA_SIZE << 29) | ((MCAN1_TX_BUF_ELMT_SZ / 4) + 2),
00508     /* element size in WORDS */
00509     {
00510         &can1MsgRam[0],
00511         &can1MsgRam[MCAN1_STD_FLTS_WRDS],
00512         &can1MsgRam[MCAN1_STD_FLTS_WRDS + MCAN1_EXT_FLTS_WRDS],
00513         &can1MsgRam[MCAN1_STD_FLTS_WRDS + MCAN1_EXT_FLTS_WRDS + MCAN1_RX_FIFO0_WRDS],
00514         &can1MsgRam[MCAN1_STD_FLTS_WRDS + MCAN1_EXT_FLTS_WRDS + MCAN1_RX_FIFO0_WRDS
00515         + MCAN1_RX_FIFO1_WRDS],
00516         &can1MsgRam[MCAN1_STD_FLTS_WRDS + MCAN1_EXT_FLTS_WRDS + MCAN1_RX_FIFO0_WRDS
00517         + MCAN1_RX_FIFO1_WRDS + MCAN1_RX_DED_BUFS_WRDS],
00518         &can1MsgRam[MCAN1_STD_FLTS_WRDS + MCAN1_EXT_FLTS_WRDS + MCAN1_RX_FIFO0_WRDS
00519         + MCAN1_RX_FIFO1_WRDS + MCAN1_RX_DED_BUFS_WRDS + MCAN1_TX_EVT_FIFO_WRDS],
00520         &can1MsgRam[MCAN1_STD_FLTS_WRDS + MCAN1_EXT_FLTS_WRDS + MCAN1_RX_FIFO0_WRDS
00521         + MCAN1_RX_FIFO1_WRDS + MCAN1_RX_DED_BUFS_WRDS + MCAN1_TX_EVT_FIFO_WRDS
00522         + MCAN1_TX_DED_BUF_WRDS]
00523     },
00524 };
00525 
00526 
00527 /*---------------------------------------------------------------------------
00528  *      Exported Functions
00529  *---------------------------------------------------------------------------*/
00530 /**
00531 * \brief Initializes the MCAN hardware for giving peripheral.
00532 * Default: Mixed mode TX Buffer + FIFO.
00533 *
00534 * \param mcanConfig  Pointer to a MCAN instance.
00535 */
00536 void MCAN_Init(const MCan_ConfigType *mcanConfig)
00537 {
00538     Mcan       *mcan = mcanConfig->pMCan;
00539     uint32_t    regVal32;
00540     uint32_t   *pMsgRam;
00541     uint32_t    cntr;
00542     IRQn_Type   mCanLine0Irq;
00543 
00544     /* Both MCAN controllers use programmable clock 5 to derive bit rate */
00545     // select MCK divided by 1 as programmable clock 5 output
00546     PMC->PMC_PCK[5] = PMC_PCK_PRES(MCAN_PROG_CLK_PRESCALER - 1) |
00547                       MCAN_PROG_CLK_SELECT;
00548     PMC->PMC_SCER = PMC_SCER_PCK5;
00549 
00550     if (MCAN0 ==  mcan) {
00551         PIO_Configure(pinsMcan0, PIO_LISTSIZE(pinsMcan0));
00552         // Enable MCAN peripheral clock
00553         PMC_EnablePeripheral(ID_MCAN0);
00554         // Configure Message RAM Base Address
00555         regVal32 = MATRIX->CCFG_CAN0 & 0x000001FF;
00556         MATRIX->CCFG_CAN0 = regVal32 |
00557                             ((uint32_t) mcanConfig->msgRam.pStdFilts & 0xFFFF0000);
00558         mCanLine0Irq = MCAN0_IRQn;
00559     } else if (MCAN1 ==  mcan) {
00560         PIO_Configure(pinsMcan1, PIO_LISTSIZE(pinsMcan1));
00561         // Enable MCAN peripheral clock
00562         PMC_EnablePeripheral(ID_MCAN1);
00563         // Configure Message RAM Base Address
00564         regVal32 = MATRIX->CCFG_SYSIO & 0x0000FFFF;
00565         MATRIX->CCFG_SYSIO = regVal32 | ((uint32_t) mcanConfig->msgRam.pStdFilts &
00566                                           0xFFFF0000);
00567         mCanLine0Irq = MCAN1_IRQn;
00568     } else
00569         return;
00570 
00571     /* Indicates Initialization state */
00572     mcan->MCAN_CCCR = MCAN_CCCR_INIT_ENABLED;
00573 
00574     do { regVal32 = mcan->MCAN_CCCR; }
00575     while (0u == (regVal32 & MCAN_CCCR_INIT_ENABLED));
00576 
00577     /* Enable writing to configuration registers */
00578     mcan->MCAN_CCCR = MCAN_CCCR_INIT_ENABLED | MCAN_CCCR_CCE_CONFIGURABLE;
00579 
00580     /* Global Filter Configuration: Reject remote frames, reject non-matching frames */
00581     mcan->MCAN_GFC = MCAN_GFC_RRFE_REJECT | MCAN_GFC_RRFS_REJECT
00582                      | MCAN_GFC_ANFE(2) | MCAN_GFC_ANFS(2);
00583 
00584     // Extended ID Filter AND mask
00585     mcan->MCAN_XIDAM = 0x1FFFFFFF;
00586 
00587     /* Interrupt configuration - leave initialization with all interrupts off */
00588     // Disable all interrupts
00589     mcan->MCAN_IE =  0;
00590     mcan->MCAN_TXBTIE = 0x00000000;
00591     // All interrupts directed to Line 0
00592     mcan->MCAN_ILS =  0x00000000;
00593     // Disable both interrupt LINE 0 & LINE 1
00594     mcan->MCAN_ILE = 0x00;
00595     // Clear all interrupt flags
00596     mcan->MCAN_IR = 0xFFCFFFFF;
00597     /* Enable NVIC - but no interrupts will happen since all sources are
00598         disabled in MCAN_IE */
00599     NVIC_ClearPendingIRQ(mCanLine0Irq);
00600     NVIC_EnableIRQ(mCanLine0Irq);
00601     NVIC_ClearPendingIRQ((IRQn_Type) (mCanLine0Irq + 1));
00602     NVIC_EnableIRQ((IRQn_Type) (mCanLine0Irq + 1));
00603 
00604     /* Configure CAN bit timing */
00605     mcan->MCAN_BTP = mcanConfig->bitTiming;
00606     mcan->MCAN_FBTP = mcanConfig->fastBitTiming;
00607 
00608     /* Configure message RAM starting addresses & sizes */
00609     mcan->MCAN_SIDFC = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pStdFilts)
00610                        | MCAN_SIDFC_LSS(mcanConfig->nmbrStdFilts);
00611     mcan->MCAN_XIDFC = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pExtFilts)
00612                        | MCAN_XIDFC_LSE(mcanConfig->nmbrExtFilts);
00613     mcan->MCAN_RXF0C = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pRxFifo0)
00614                        | MCAN_RXF0C_F0S(mcanConfig->nmbrFifo0Elmts);
00615     // watermark interrupt off, blocking mode
00616     mcan->MCAN_RXF1C = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pRxFifo1)
00617                        | MCAN_RXF1C_F1S(mcanConfig->nmbrFifo1Elmts);
00618     // watermark interrupt off, blocking mode
00619     mcan->MCAN_RXBC = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pRxDedBuf);
00620     mcan->MCAN_TXEFC = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pTxEvtFifo)
00621                        | MCAN_TXEFC_EFS(mcanConfig->nmbrTxEvtFifoElmts);
00622     // watermark interrupt off
00623     mcan->MCAN_TXBC = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pTxDedBuf)
00624                       | MCAN_TXBC_NDTB(mcanConfig->nmbrTxDedBufElmts)
00625                       | MCAN_TXBC_TFQS(mcanConfig->nmbrTxFifoQElmts);
00626     mcan->MCAN_RXESC = ((mcanConfig->rxBufElmtSize >> (29 - MCAN_RXESC_RBDS_Pos)) &
00627                         MCAN_RXESC_RBDS_Msk) |
00628                        ((mcanConfig->rxFifo1ElmtSize >> (29 - MCAN_RXESC_F1DS_Pos)) &
00629                         MCAN_RXESC_F1DS_Msk) |
00630                        ((mcanConfig->rxFifo0ElmtSize >> (29 - MCAN_RXESC_F0DS_Pos)) &
00631                         MCAN_RXESC_F0DS_Msk);
00632     mcan->MCAN_TXESC = ((mcanConfig->txBufElmtSize >> (29 - MCAN_TXESC_TBDS_Pos)) &
00633                         MCAN_TXESC_TBDS_Msk);
00634 
00635     /* Configure Message Filters */
00636     // ...Disable all standard filters
00637     pMsgRam = mcanConfig->msgRam.pStdFilts;
00638     cntr = mcanConfig->nmbrStdFilts;
00639 
00640     while (cntr > 0) {
00641         *pMsgRam++ = STD_FILT_SFEC_DISABLE;
00642         cntr--;
00643     }
00644 
00645     // ...Disable all extended filters
00646     pMsgRam = mcanConfig->msgRam.pExtFilts;
00647     cntr = mcanConfig->nmbrExtFilts;
00648 
00649     while (cntr > 0) {
00650         *pMsgRam = EXT_FILT_EFEC_DISABLE;
00651         pMsgRam = pMsgRam + 2;
00652         cntr--;
00653     }
00654 
00655     mcan->MCAN_NDAT1 = 0xFFFFFFFF;  // clear new (rx) data flags
00656     mcan->MCAN_NDAT2 = 0xFFFFFFFF;  // clear new (rx) data flags
00657 
00658     regVal32 =  mcan->MCAN_CCCR & ~(MCAN_CCCR_CME_Msk | MCAN_CCCR_CMR_Msk);
00659     mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CME_ISO11898_1;
00660     mcan->MCAN_CCCR = regVal32 | (MCAN_CCCR_CMR_ISO11898_1 |
00661                                   MCAN_CCCR_CME_ISO11898_1);
00662 
00663     __DSB();
00664     __ISB();
00665 }
00666 
00667 /**
00668  * \brief Enables a FUTURE switch to FD mode (tx & rx payloads up to 64 bytes)
00669  * but transmits WITHOUT bit rate switching
00670  * INIT must be set - so this should be called between MCAN_Init() and
00671  * MCAN_Enable()
00672  * \param mcanConfig  Pointer to a MCAN instance.
00673  */
00674 void MCAN_InitFdEnable(const MCan_ConfigType *mcanConfig)
00675 {
00676     Mcan      *mcan = mcanConfig->pMCan;
00677     uint32_t   regVal32;
00678 
00679     regVal32 =  mcan->MCAN_CCCR & ~MCAN_CCCR_CME_Msk;
00680     mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CME(1);
00681 }
00682 
00683 /**
00684  * \brief Enables a FUTURE switch to FD mode (tx & rx payloads up to 64 bytes) and transmits
00685  * WITH bit rate switching
00686  * INIT must be set - so this should be called between MCAN_Init() and MCAN_Enable()
00687  * \param mcanConfig  Pointer to a MCAN instance.
00688  */
00689 void MCAN_InitFdBitRateSwitchEnable(const MCan_ConfigType *mcanConfig)
00690 {
00691     Mcan      *mcan = mcanConfig->pMCan;
00692     uint32_t   regVal32;
00693 
00694     regVal32 =  mcan->MCAN_CCCR & ~MCAN_CCCR_CME_Msk;
00695     mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CME(2);
00696 }
00697 
00698 /**
00699  * \brief Initializes the MCAN in loop back mode.
00700  * INIT must be set - so this should be called between MCAN_Init() and
00701  * MCAN_Enable()
00702  * \param mcanConfig  Pointer to a MCAN instance.
00703  */
00704 void MCAN_InitLoopback(const MCan_ConfigType *mcanConfig)
00705 {
00706     Mcan *mcan = mcanConfig->pMCan;
00707 
00708     mcan->MCAN_CCCR |= MCAN_CCCR_TEST_ENABLED;
00709     //mcan->MCAN_CCCR |= MCAN_CCCR_MON_ENABLED;  // for internal loop back
00710     mcan->MCAN_TEST |= MCAN_TEST_LBCK_ENABLED;
00711 }
00712 
00713 /**
00714  * \brief Initializes MCAN queue for TX
00715  * INIT must be set - so this should be called between MCAN_Init() and
00716  * MCAN_Enable()
00717  * \param mcanConfig  Pointer to a MCAN instance.
00718  */
00719 void MCAN_InitTxQueue(const MCan_ConfigType *mcanConfig)
00720 {
00721     Mcan *mcan = mcanConfig->pMCan;
00722     mcan->MCAN_TXBC |= MCAN_TXBC_TFQM;
00723 }
00724 
00725 /**
00726  * \brief Enable MCAN peripheral.
00727  * INIT must be set - so this should be called between MCAN_Init()
00728  * \param mcanConfig  Pointer to a MCAN instance.
00729  */
00730 void MCAN_Enable(const MCan_ConfigType *mcanConfig)
00731 {
00732     Mcan *mcan = mcanConfig->pMCan;
00733     mcan->MCAN_CCCR &= ~MCAN_CCCR_INIT_ENABLED;
00734 }
00735 
00736 /**
00737  * \brief Requests switch to Iso11898-1 (standard / classic) mode (tx & rx
00738  * payloads up to 8 bytes).
00739  * \param mcanConfig  Pointer to a MCAN instance.
00740  */
00741 void MCAN_RequestIso11898_1(const MCan_ConfigType *mcanConfig)
00742 {
00743     Mcan      *mcan = mcanConfig->pMCan;
00744     uint32_t   regVal32;
00745 
00746     regVal32 =  mcan->MCAN_CCCR & ~MCAN_CCCR_CMR_Msk;
00747     mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CMR_ISO11898_1;
00748 
00749     while ((mcan->MCAN_CCCR & (MCAN_CCCR_FDBS | MCAN_CCCR_FDO)) != 0)
00750     { /* wait */ }
00751 }
00752 
00753 /**
00754  * \brief Requests switch to FD mode (tx & rx payloads up to 64 bytes) but
00755  * transmits WITHOUT bit
00756  * rate switching. requested mode should have been enabled at initialization
00757  * \param mcanConfig  Pointer to a MCAN instance.
00758  */
00759 void MCAN_RequestFd(const MCan_ConfigType *mcanConfig)
00760 {
00761     Mcan      *mcan = mcanConfig->pMCan;
00762     uint32_t   regVal32;
00763 
00764     if ((mcan->MCAN_CCCR & MCAN_CCCR_CME_Msk) == MCAN_CCCR_CME(1)) {
00765         regVal32 =  mcan->MCAN_CCCR & ~MCAN_CCCR_CMR_Msk;
00766         mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CMR_FD;
00767 
00768         while ((mcan->MCAN_CCCR & MCAN_CCCR_FDO) == 0) { /* wait */ }
00769     }
00770 }
00771 
00772 /**
00773  * \brief Request switch to FD mode (tx & rx payloads up to 64 bytes) and
00774  * transmits WITH bit rate switching.
00775  * requested mode should have been enabled at initialization
00776  * \param mcanConfig  Pointer to a MCAN instance.
00777  */
00778 void MCAN_RequestFdBitRateSwitch(const MCan_ConfigType *mcanConfig)
00779 {
00780     Mcan      *mcan = mcanConfig->pMCan;
00781     uint32_t   regVal32;
00782 
00783     if ((mcan->MCAN_CCCR & MCAN_CCCR_CME_Msk) == MCAN_CCCR_CME(2)) {
00784         regVal32 =  mcan->MCAN_CCCR & ~MCAN_CCCR_CMR_Msk;
00785         mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CMR_FD_BITRATE_SWITCH;
00786 
00787         while ((mcan->MCAN_CCCR & (MCAN_CCCR_FDBS | MCAN_CCCR_FDO)) !=
00788                 (MCAN_CCCR_FDBS | MCAN_CCCR_FDO)) { /* wait */ }
00789     }
00790 }
00791 
00792 /**
00793  * \brief Switch on loop back mode.
00794  * TEST must be set in MCAN_CCCR - e.g. by a prior call to MCAN_InitLoopback()
00795  * \param mcanConfig  Pointer to a MCAN instance.
00796  */
00797 void MCAN_LoopbackOn(const MCan_ConfigType *mcanConfig)
00798 {
00799     Mcan *mcan = mcanConfig->pMCan;
00800     mcan->MCAN_TEST |= MCAN_TEST_LBCK_ENABLED;
00801 }
00802 
00803 /**
00804  * \brief Switch off loop back mode.
00805  * \param mcanConfig  Pointer to a MCAN instance.
00806  */
00807 void MCAN_LoopbackOff(const MCan_ConfigType *mcanConfig)
00808 {
00809     Mcan *mcan = mcanConfig->pMCan;
00810     mcan->MCAN_TEST &= ~MCAN_TEST_LBCK_ENABLED;
00811 }
00812 
00813 /**
00814  * \brief Enable message line and message stored to Dedicated Receive Buffer
00815  * Interrupt Line.
00816  * \param mcanConfig  Pointer to a MCAN instance.
00817  * \param line  Message line.
00818  */
00819 void MCAN_IEnableMessageStoredToRxDedBuffer(const MCan_ConfigType *mcanConfig,
00820         MCan_IntrLineType line)
00821 {
00822     Mcan *mcan = mcanConfig->pMCan;
00823 
00824     if (line == CAN_INTR_LINE_0) {
00825         mcan->MCAN_ILS &= ~MCAN_ILS_DRXL;
00826         mcan->MCAN_ILE |= MCAN_ILE_EINT0;
00827     } else  {
00828         // Interrupt Line 1
00829         mcan->MCAN_ILS |= MCAN_ILS_DRXL;
00830         mcan->MCAN_ILE |= MCAN_ILE_EINT1;
00831     }
00832 
00833     mcan->MCAN_IR = MCAN_IR_DRX;  // clear previous flag
00834     mcan->MCAN_IE |= MCAN_IE_DRXE;  // enable it
00835 }
00836 
00837 /**
00838  * \brief Configures a Dedicated TX Buffer.
00839  * \param mcanConfig  Pointer to a MCAN instance.
00840  * \param buffer  Pointer to buffer.
00841  * \param id  Message ID.
00842  * \param idType  Type of ID
00843  * \param dlc  Type of dlc.
00844  */
00845 uint8_t   *MCAN_ConfigTxDedBuffer(const MCan_ConfigType *mcanConfig,
00846                                    uint8_t buffer, uint32_t id, MCan_IdType idType, MCan_DlcType dlc)
00847 {
00848     Mcan *mcan = mcanConfig->pMCan;
00849     uint32_t *pThisTxBuf = 0;
00850 
00851     if (buffer < mcanConfig->nmbrTxDedBufElmts) {
00852         pThisTxBuf = mcanConfig->msgRam.pTxDedBuf + (buffer *
00853                      (mcanConfig->txBufElmtSize & ELMT_SIZE_MASK));
00854 
00855         if (idType == CAN_STD_ID)
00856             *pThisTxBuf++ = ((id << 18) & (CAN_11_BIT_ID_MASK << 18));
00857         else
00858             *pThisTxBuf++ = BUFFER_XTD_MASK | (id & CAN_29_BIT_ID_MASK);
00859 
00860         *pThisTxBuf++ = (uint32_t) dlc << 16;
00861         /* enable transmit from buffer to set TC interrupt bit in IR, but
00862         interrupt will not happen unless TC interrupt is enabled*/
00863         mcan->MCAN_TXBTIE = (1 << buffer);
00864     }
00865 
00866     return (uint8_t *) pThisTxBuf;  // now it points to the data field
00867 }
00868 
00869 /**
00870  * \brief Send Tx buffer.
00871  * \param mcanConfig  Pointer to a MCAN instance.
00872  * \param buffer  Pointer to buffer.
00873  */
00874 void MCAN_SendTxDedBuffer(const MCan_ConfigType *mcanConfig, uint8_t buffer)
00875 {
00876     Mcan *mcan = mcanConfig->pMCan;
00877 
00878     if (buffer < mcanConfig->nmbrTxDedBufElmts)
00879         mcan->MCAN_TXBAR = (1 << buffer);
00880 }
00881 
00882 /**
00883  * \brief Adds Message to TX Fifo / Queue
00884  * \param mcanConfig  Pointer to a MCAN instance.
00885  * \param id  Message ID.
00886  * \param idType  Type of ID
00887  * \param dlc  Type of dlc.
00888  * \param data  Pointer to data.
00889  */
00890 uint32_t MCAN_AddToTxFifoQ(const MCan_ConfigType *mcanConfig,
00891                             uint32_t id, MCan_IdType idType, MCan_DlcType dlc, uint8_t *data)
00892 {
00893     Mcan *mcan = mcanConfig->pMCan;
00894     uint32_t   putIdx = 255;
00895     uint32_t *pThisTxBuf = 0;
00896     uint8_t   *pTxData;
00897     uint8_t    msgLength;
00898     uint8_t    cnt;
00899 
00900     // Configured for FifoQ and FifoQ not full?
00901     if ((mcanConfig->nmbrTxFifoQElmts > 0) &&
00902         ((mcan->MCAN_TXFQS & MCAN_TXFQS_TFQF) == 0)) {
00903         putIdx = (mcan->MCAN_TXFQS & MCAN_TXFQS_TFQPI_Msk) >> MCAN_TXFQS_TFQPI_Pos;
00904         pThisTxBuf = mcanConfig->msgRam.pTxDedBuf + (putIdx *
00905                      (mcanConfig->txBufElmtSize & ELMT_SIZE_MASK));
00906 
00907         if (idType == CAN_STD_ID)
00908             *pThisTxBuf++ = ((id << 18) & (CAN_11_BIT_ID_MASK << 18));
00909         else
00910             *pThisTxBuf++ = BUFFER_XTD_MASK | (id & CAN_29_BIT_ID_MASK);
00911 
00912         *pThisTxBuf++ = (uint32_t) dlc << 16;
00913         pTxData = (uint8_t *) pThisTxBuf;
00914         msgLength = dlcToMsgLength[dlc];
00915 
00916         for (cnt = 0; cnt < msgLength; cnt++)
00917             *pTxData++ = *data++;
00918 
00919         /* enable transmit from buffer to set TC interrupt bit in IR, but
00920         interrupt will not happen unless TC interrupt is enabled */
00921         mcan->MCAN_TXBTIE = (1 << putIdx);
00922         // request to send
00923         mcan->MCAN_TXBAR = (1 << putIdx);
00924     }
00925 
00926     return putIdx;  // now it points to the data field
00927 }
00928 
00929 /**
00930  * \brief Check if data transmitted from buffer/fifo/queue
00931  * \param mcanConfig  Pointer to a MCAN instance.
00932  * \param buffer  Pointer to data buffer.
00933  */
00934 uint8_t MCAN_IsBufferTxd(const MCan_ConfigType *mcanConfig, uint8_t buffer)
00935 {
00936     Mcan *mcan = mcanConfig->pMCan;
00937 
00938     return (mcan->MCAN_TXBTO & (1 << buffer));
00939 }
00940 
00941 /**
00942  * \brief Configure RX Buffer Filter
00943  * ID must match exactly for a RX Buffer Filter
00944  * \param mcanConfig  Pointer to a MCAN instance.
00945  * \param buffer  Pointer to data buffer.
00946  * \param filter  data of filter.
00947  * \param idType  Type of ID
00948  */
00949 void MCAN_ConfigRxBufferFilter(const MCan_ConfigType *mcanConfig,
00950                                 uint32_t buffer, uint32_t filter, uint32_t id, MCan_IdType idType)
00951 {
00952     uint32_t *pThisRxFilt = 0;
00953 
00954     if (buffer < mcanConfig->nmbrRxDedBufElmts) {
00955         if (idType == CAN_STD_ID) {
00956             if ((filter < mcanConfig->nmbrStdFilts)
00957                 && (id <= CAN_11_BIT_ID_MASK)) {
00958                 pThisRxFilt = mcanConfig->msgRam.pStdFilts + filter;
00959                 // 1 word per filter
00960                 *pThisRxFilt = STD_FILT_SFEC_BUFFER | (id << 16) |
00961                                STD_FILT_SFID2_RX_BUFFER | buffer;
00962             }
00963         } else {
00964             // extended ID
00965             if ((filter < mcanConfig->nmbrExtFilts) &&
00966                 (id <= CAN_29_BIT_ID_MASK)) {
00967                 pThisRxFilt = mcanConfig->msgRam.pExtFilts + (2 * filter);
00968                 // 2 words per filter
00969                 *pThisRxFilt++ = (uint32_t) EXT_FILT_EFEC_BUFFER | id;
00970                 *pThisRxFilt = EXT_FILT_EFID2_RX_BUFFER | buffer;
00971             }
00972         }
00973     }
00974 }
00975 
00976 /**
00977  * \brief Configure Classic Filter
00978  * Classic Filters direct accepted messages to a FIFO & include both a ID and
00979  * a ID mask
00980  * \param mcanConfig  Pointer to a MCAN instance.
00981  * \param buffer  Pointer to data buffer.
00982  * \param fifo   fifo Number.
00983  * \param filter  data of filter.
00984  * \param idType  Type of ID
00985  * \param mask  Mask to be match
00986  */
00987 void MCAN_ConfigRxClassicFilter(const MCan_ConfigType *mcanConfig,
00988                                  MCan_FifoType fifo, uint8_t filter, uint32_t id,
00989                                  MCan_IdType idType, uint32_t mask)
00990 {
00991     uint32_t *pThisRxFilt = 0;
00992     uint32_t   filterTemp;
00993 
00994     if (idType == CAN_STD_ID) {
00995         if ((filter < mcanConfig->nmbrStdFilts) && (id <= CAN_11_BIT_ID_MASK)
00996             && (mask <= CAN_11_BIT_ID_MASK)) {
00997             pThisRxFilt = mcanConfig->msgRam.pStdFilts + filter;
00998             // 1 word per filter
00999             filterTemp = (uint32_t) STD_FILT_SFT_CLASSIC | (id << 16) | mask;
01000 
01001             if (fifo == CAN_FIFO_0)
01002                 *pThisRxFilt = STD_FILT_SFEC_FIFO0 | filterTemp;
01003             else if (fifo == CAN_FIFO_1)
01004                 *pThisRxFilt = STD_FILT_SFEC_FIFO1 | filterTemp;
01005         }
01006     } else {
01007         // extended ID
01008         if ((filter < mcanConfig->nmbrExtFilts)
01009             && (id <= CAN_29_BIT_ID_MASK)
01010             && (mask <= CAN_29_BIT_ID_MASK)) {
01011             pThisRxFilt = mcanConfig->msgRam.pExtFilts + (2 * filter);
01012 
01013             // 2 words per filter
01014             if (fifo == CAN_FIFO_0)
01015                 *pThisRxFilt++ = EXT_FILT_EFEC_FIFO0 | id;
01016             else if (fifo == CAN_FIFO_1)
01017                 *pThisRxFilt++ = EXT_FILT_EFEC_FIFO1 | id;
01018 
01019             *pThisRxFilt = (uint32_t) EXT_FILT_EFT_CLASSIC | mask;
01020         }
01021     }
01022 }
01023 
01024 /**
01025  * \brief check if data received into buffer
01026  * \param mcanConfig  Pointer to a MCAN instance.
01027  * \param buffer  Pointer to data buffer.
01028  */
01029 uint8_t MCAN_IsNewDataInRxDedBuffer(const MCan_ConfigType *mcanConfig,
01030                                      uint8_t buffer)
01031 {
01032     Mcan *mcan = mcanConfig->pMCan;
01033 
01034     if (buffer < 32)
01035         return (mcan->MCAN_NDAT1 & (1 << buffer));
01036     else if (buffer < 64)
01037         return (mcan->MCAN_NDAT1 & (1 << (buffer - 32)));
01038     else
01039         return 0;
01040 }
01041 
01042 /**
01043  * \brief Get Rx buffer
01044  * \param mcanConfig  Pointer to a MCAN instance.
01045  * \param buffer  Pointer to data buffer.
01046  * \param pRxMailbox  Pointer to rx Mailbox.
01047  */
01048 void MCAN_GetRxDedBuffer(const MCan_ConfigType *mcanConfig,
01049                           uint8_t buffer, Mailbox64Type *pRxMailbox)
01050 {
01051     Mcan      *mcan = mcanConfig->pMCan;
01052     uint32_t *pThisRxBuf = 0;
01053     uint32_t   tempRy;  // temp copy of RX buffer word
01054     uint32_t   dlc;
01055     uint8_t   *pRxData;
01056     uint8_t    idx;
01057 
01058     if (buffer < mcanConfig->nmbrRxDedBufElmts) {
01059         pThisRxBuf = mcanConfig->msgRam.pRxDedBuf
01060                      + (buffer * (mcanConfig->rxBufElmtSize & ELMT_SIZE_MASK));
01061         tempRy = *pThisRxBuf++;  // word R0 contains ID
01062 
01063         if (tempRy & BUFFER_XTD_MASK) {
01064             // extended ID?
01065             pRxMailbox->info.id = tempRy & BUFFER_EXT_ID_MASK;
01066         } else {
01067             // standard ID
01068             pRxMailbox->info.id = (tempRy & BUFFER_STD_ID_MASK) >> 18;
01069         }
01070 
01071         tempRy = *pThisRxBuf++;  // word R1 contains DLC & time stamp
01072         dlc = (tempRy & BUFFER_DLC_MASK) >> 16;
01073         pRxMailbox->info.length = dlcToMsgLength[dlc];
01074         pRxMailbox->info.timestamp = tempRy & BUFFER_RXTS_MASK;
01075         // copy the data from the buffer to the mailbox
01076         pRxData = (uint8_t *) pThisRxBuf;
01077 
01078         SCB_CleanDCache_by_Addr((uint32_t *)pRxData, pRxMailbox->info.length);
01079         SCB_CleanDCache_by_Addr((uint32_t *) & (pRxMailbox->data[0]),
01080                                 pRxMailbox->info.length);
01081 
01082         for (idx = 0; idx < pRxMailbox->info.length; idx++)
01083             pRxMailbox->data[idx] = *pRxData++;
01084 
01085         /* clear the new data flag for the buffer */
01086 
01087         if (buffer < 32)
01088             mcan->MCAN_NDAT1 = (1 << buffer);
01089         else
01090             mcan->MCAN_NDAT1 = (1 << (buffer - 32));
01091 
01092     }
01093 }
01094 
01095 /**
01096  * \brief Get from the receive FIFO and place in a application mailbox
01097  * \param mcanConfig  Pointer to a MCAN instance.
01098  * \param fifo  Fifo Number
01099  * \param pRxMailbox  Pointer to rx Mailbox.
01100  * \return: # of fifo entries at the start of the function
01101  *         0 -> FIFO was empty at start
01102  *         1 -> FIFO had 1 entry at start, but is empty at finish
01103  *         2 -> FIFO had 2 entries at start, has 1 entry at finish
01104  */
01105 uint32_t MCAN_GetRxFifoBuffer(const MCan_ConfigType *mcanConfig,
01106                                MCan_FifoType fifo, Mailbox64Type *pRxMailbox)
01107 {
01108     Mcan      *mcan = mcanConfig->pMCan;
01109     uint32_t *pThisRxBuf = 0;
01110     uint32_t   tempRy;  // temp copy of RX buffer word
01111     uint32_t   dlc;
01112     uint8_t   *pRxData;
01113     uint8_t    idx;
01114     uint32_t *fifo_ack_reg;
01115     uint32_t   get_index;
01116     uint32_t   fill_level;
01117     uint32_t   element_size;
01118 
01119     // default: fifo empty
01120     fill_level = 0;
01121 
01122     if (fifo == CAN_FIFO_0) {
01123         get_index = (mcan->MCAN_RXF0S & MCAN_RXF0S_F0GI_Msk) >> MCAN_RXF0S_F0GI_Pos;
01124         fill_level = (mcan->MCAN_RXF0S & MCAN_RXF0S_F0FL_Msk) >> MCAN_RXF0S_F0FL_Pos;
01125         pThisRxBuf = mcanConfig->msgRam.pRxFifo0;
01126         element_size = mcanConfig->rxFifo0ElmtSize & ELMT_SIZE_MASK;
01127         fifo_ack_reg = (uint32_t *) &mcan->MCAN_RXF0A;
01128     } else if (fifo == CAN_FIFO_1) {
01129         get_index = (mcan->MCAN_RXF1S & MCAN_RXF1S_F1GI_Msk) >> MCAN_RXF1S_F1GI_Pos;
01130         fill_level = (mcan->MCAN_RXF1S & MCAN_RXF1S_F1FL_Msk) >> MCAN_RXF1S_F1FL_Pos;
01131         pThisRxBuf = mcanConfig->msgRam.pRxFifo1;
01132         element_size = mcanConfig->rxFifo1ElmtSize & ELMT_SIZE_MASK;
01133         fifo_ack_reg = (uint32_t *) &mcan->MCAN_RXF1A;
01134     }
01135 
01136     if (fill_level > 0) {
01137         pThisRxBuf = pThisRxBuf + (get_index * element_size);
01138         tempRy = *pThisRxBuf++;  // word R0 contains ID
01139 
01140         if (tempRy & BUFFER_XTD_MASK) {
01141             // extended ID?
01142             pRxMailbox->info.id = tempRy & BUFFER_EXT_ID_MASK;
01143         } else {
01144             // standard ID
01145             pRxMailbox->info.id = (tempRy & BUFFER_STD_ID_MASK) >> 18;
01146         }
01147 
01148         tempRy = *pThisRxBuf++;  // word R1 contains DLC & timestamps
01149         dlc = (tempRy & BUFFER_DLC_MASK) >> 16;
01150         pRxMailbox->info.length = dlcToMsgLength[dlc];
01151         pRxMailbox->info.timestamp = tempRy & BUFFER_RXTS_MASK;
01152         /* copy the data from the buffer to the mailbox */
01153         pRxData = (uint8_t *) pThisRxBuf;
01154 
01155         for (idx = 0; idx < pRxMailbox->info.length; idx++)
01156             pRxMailbox->data[idx] = *pRxData++;
01157 
01158         // acknowledge reading the fifo entry
01159         *fifo_ack_reg = get_index;
01160         /* return entries remaining in FIFO */
01161     }
01162 
01163     return (fill_level);
01164 }
01165 
01166 /**@}*/
01167 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines