SAMV71 Xplained Ultra Software Package 1.4

mcan.c

Go to the documentation of this file.
00001 /* ----------------------------------------------------------------------------
00002  *         SAM Software Package License 
00003  * ----------------------------------------------------------------------------
00004  * Copyright (c) 2012, Atmel Corporation
00005  *
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *
00011  * - Redistributions of source code must retain the above copyright notice,
00012  * this list of conditions and the disclaimer below.
00013  *
00014  * Atmel's name may not be used to endorse or promote products derived from
00015  * this software without specific prior written permission.
00016  *
00017  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
00020  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00022  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00023  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00024  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00025  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
00026  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  * ----------------------------------------------------------------------------
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             (3 << 30)
00378 #define STD_FILT_SFT_RANGE            (0 << 30)
00379 #define STD_FILT_SFT_DUAL             (1 << 30)
00380 #define STD_FILT_SFT_CLASSIC          (2 << 30)
00381 #define STD_FILT_SFEC_MASK            (7 << 27)
00382 #define STD_FILT_SFEC_DISABLE         (0 << 27)
00383 #define STD_FILT_SFEC_FIFO0           (1 << 27)
00384 #define STD_FILT_SFEC_FIFO1           (2 << 27)
00385 #define STD_FILT_SFEC_REJECT          (3 << 27)
00386 #define STD_FILT_SFEC_PRIORITY        (4 << 27)
00387 #define STD_FILT_SFEC_PRIORITY_FIFO0  (5 << 27)
00388 #define STD_FILT_SFEC_PRIORITY_FIFO1  (6 << 27)
00389 #define STD_FILT_SFEC_BUFFER          (7 << 27)
00390 #define STD_FILT_SFID1_MASK           (0x03FF << 16)
00391 #define STD_FILT_SFID2_MASK           (0x3FF << 0)
00392 #define STD_FILT_SFID2_RX_BUFFER      (0 << 9)
00393 #define STD_FILT_SFID2_DEBUG_A        (1 << 9)
00394 #define STD_FILT_SFID2_DEBUG_B        (2 << 9)
00395 #define STD_FILT_SFID2_DEBUG_C        (3 << 9)
00396 #define STD_FILT_SFID2_BUFFER(nmbr)   (nmbr & 0x3F)
00397 
00398 #define EXT_FILT_EFEC_MASK            (7 << 29)
00399 #define EXT_FILT_EFEC_DISABLE         (0 << 29)
00400 #define EXT_FILT_EFEC_FIFO0           (1 << 29)
00401 #define EXT_FILT_EFEC_FIFO1           (2 << 29)
00402 #define EXT_FILT_EFEC_REJECT          (3 << 29)
00403 #define EXT_FILT_EFEC_PRIORITY        (4 << 29)
00404 #define EXT_FILT_EFEC_PRIORITY_FIFO0  (5 << 29)
00405 #define EXT_FILT_EFEC_PRIORITY_FIFO1  (6 << 29)
00406 #define EXT_FILT_EFEC_BUFFER          (7 << 29)
00407 #define EXT_FILT_EFID1_MASK           (0x1FFFFFFF)
00408 #define EXT_FILT_EFT_MASK             (3 << 30)
00409 #define EXT_FILT_EFT_RANGE            (0 << 30)
00410 #define EXT_FILT_EFT_DUAL             (1 << 30)
00411 #define EXT_FILT_EFT_CLASSIC          (2 << 30)
00412 #define EXT_FILT_EFT_RANGE_NO_XIDAM   (3 << 30)
00413 #define EXT_FILT_EFID2_MASK           (0x1FFFFFFF)
00414 #define EXT_FILT_EFID2_RX_BUFFER      (0 << 9)
00415 #define EXT_FILT_EFID2_DEBUG_A        (1 << 9)
00416 #define EXT_FILT_EFID2_DEBUG_B        (2 << 9)
00417 #define EXT_FILT_EFID2_DEBUG_C        (3 << 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 const MCan_ConfigType mcan0Config =
00447 {
00448     MCAN0,
00449     MCAN_BTP_BRP(MCAN0_BRP) | MCAN_BTP_TSEG1(MCAN0_TSEG1) | 
00450     MCAN_BTP_TSEG2(MCAN0_TSEG2) | MCAN_BTP_SJW(MCAN0_SJW), 
00451     MCAN_FBTP_FBRP(MCAN0_FBRP) | MCAN_FBTP_FTSEG1(MCAN0_FTSEG1) | 
00452     MCAN_FBTP_FTSEG2(MCAN0_FTSEG2) | MCAN_FBTP_FSJW(MCAN0_FSJW), 
00453     MCAN0_NMBR_STD_FLTS,
00454     MCAN0_NMBR_EXT_FLTS,
00455     MCAN0_NMBR_RX_FIFO0_ELMTS,
00456     MCAN0_NMBR_RX_FIFO1_ELMTS,
00457     MCAN0_NMBR_RX_DED_BUF_ELMTS,
00458     MCAN0_NMBR_TX_EVT_FIFO_ELMTS,
00459     MCAN0_NMBR_TX_DED_BUF_ELMTS,
00460     MCAN0_NMBR_TX_FIFO_Q_ELMTS,
00461     (MCAN0_RX_FIFO0_DATA_SIZE << 29) | ((MCAN0_RX_FIFO0_ELMT_SZ/4)+2), 
00462     /* element size in WORDS */
00463     (MCAN0_RX_FIFO1_DATA_SIZE << 29) | ((MCAN0_RX_FIFO1_ELMT_SZ/4)+2), 
00464     /* element size in WORDS */
00465     (MCAN0_RX_BUF_DATA_SIZE << 29) | ((MCAN0_RX_BUF_ELMT_SZ/4)+2), 
00466     /* element size in WORDS */ 
00467     (MCAN0_TX_BUF_DATA_SIZE << 29) | ((MCAN0_TX_BUF_ELMT_SZ/4)+2), 
00468     /* element size in WORDS */
00469     {
00470         &can0MsgRam[0],
00471         &can0MsgRam[MCAN0_STD_FLTS_WRDS],
00472         &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS],
00473         &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS + MCAN0_RX_FIFO0_WRDS],
00474         &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS + MCAN0_RX_FIFO0_WRDS + 
00475         MCAN0_RX_FIFO1_WRDS],
00476         &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS + MCAN0_RX_FIFO0_WRDS + 
00477         MCAN0_RX_FIFO1_WRDS + MCAN0_RX_DED_BUFS_WRDS],
00478         &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS + MCAN0_RX_FIFO0_WRDS + 
00479         MCAN0_RX_FIFO1_WRDS + MCAN0_RX_DED_BUFS_WRDS + MCAN0_TX_EVT_FIFO_WRDS],
00480         &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS + MCAN0_RX_FIFO0_WRDS + 
00481         MCAN0_RX_FIFO1_WRDS + MCAN0_RX_DED_BUFS_WRDS + MCAN0_TX_EVT_FIFO_WRDS + 
00482         MCAN0_TX_DED_BUF_WRDS]    
00483   },
00484 };
00485 
00486 const MCan_ConfigType mcan1Config =
00487 {
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) | MCAN_PROG_CLK_SELECT; 
00547     PMC->PMC_SCER = PMC_SCER_PCK5;
00548     
00549     if( MCAN0 ==  mcan ) {
00550         PIO_Configure(pinsMcan0, PIO_LISTSIZE(pinsMcan0));
00551         // Enable MCAN peripheral clock
00552         PMC_EnablePeripheral( ID_MCAN0 );
00553         // Configure Message RAM Base Address
00554         regVal32 = MATRIX->CCFG_CAN0 & 0x000001FF;
00555         MATRIX->CCFG_CAN0 = regVal32 | 
00556             ( (uint32_t) mcanConfig->msgRam.pStdFilts & 0xFFFF0000 );
00557         mCanLine0Irq = MCAN0_IRQn;
00558     } else if ( MCAN1 ==  mcan ) {
00559         PIO_Configure(pinsMcan1, PIO_LISTSIZE(pinsMcan1));
00560         // Enable MCAN peripheral clock
00561         PMC_EnablePeripheral( ID_MCAN1 );
00562         // Configure Message RAM Base Address
00563         regVal32 = MATRIX->CCFG_SYSIO & 0x0000FFFF;
00564         MATRIX->CCFG_SYSIO = regVal32 | ( (uint32_t) mcanConfig->msgRam.pStdFilts & 0xFFFF0000 );
00565         mCanLine0Irq = MCAN1_IRQn;
00566     } else {
00567         return;
00568     }
00569     
00570     /* Indicates Initialization state */
00571     mcan->MCAN_CCCR = MCAN_CCCR_INIT_ENABLED;
00572     do { regVal32 = mcan->MCAN_CCCR; } 
00573         while(0u == (regVal32 & MCAN_CCCR_INIT_ENABLED));
00574     
00575     /* Enable writing to configuration registers */
00576     mcan->MCAN_CCCR = MCAN_CCCR_INIT_ENABLED | MCAN_CCCR_CCE_CONFIGURABLE;
00577     
00578     /* Global Filter Configuration: Reject remote frames, reject non-matching frames */
00579     mcan->MCAN_GFC = MCAN_GFC_RRFE_REJECT | MCAN_GFC_RRFS_REJECT 
00580         | MCAN_GFC_ANFE(2) | MCAN_GFC_ANFS(2);
00581     
00582     // Extended ID Filter AND mask  
00583     mcan->MCAN_XIDAM = 0x1FFFFFFF; 
00584     
00585     /* Interrupt configuration - leave initialization with all interrupts off */
00586     // Disable all interrupts  
00587     mcan->MCAN_IE =  0;
00588     mcan->MCAN_TXBTIE = 0x00000000;
00589     // All interrupts directed to Line 0
00590     mcan->MCAN_ILS =  0x00000000;
00591     // Disable both interrupt LINE 0 & LINE 1
00592     mcan->MCAN_ILE = 0x00;
00593     // Clear all interrupt flags
00594     mcan->MCAN_IR = 0xFFCFFFFF;
00595     /* Enable NVIC - but no interrupts will happen since all sources are 
00596         disabled in MCAN_IE */
00597     NVIC_ClearPendingIRQ(mCanLine0Irq);
00598     NVIC_EnableIRQ(mCanLine0Irq);
00599     NVIC_ClearPendingIRQ((IRQn_Type) (mCanLine0Irq+1));
00600     NVIC_EnableIRQ((IRQn_Type) (mCanLine0Irq+1));
00601     
00602     /* Configure CAN bit timing */
00603     mcan->MCAN_BTP = mcanConfig->bitTiming;
00604     mcan->MCAN_FBTP = mcanConfig->fastBitTiming;
00605     
00606     /* Configure message RAM starting addresses & sizes */
00607     mcan->MCAN_SIDFC = MAILBOX_ADDRESS( (uint32_t) mcanConfig->msgRam.pStdFilts ) 
00608             | MCAN_SIDFC_LSS(mcanConfig->nmbrStdFilts);
00609     mcan->MCAN_XIDFC = MAILBOX_ADDRESS( (uint32_t) mcanConfig->msgRam.pExtFilts ) 
00610             | MCAN_XIDFC_LSE(mcanConfig->nmbrExtFilts);
00611     mcan->MCAN_RXF0C = MAILBOX_ADDRESS( (uint32_t) mcanConfig->msgRam.pRxFifo0 )
00612             | MCAN_RXF0C_F0S(mcanConfig->nmbrFifo0Elmts);  
00613     // watermark interrupt off, blocking mode
00614     mcan->MCAN_RXF1C = MAILBOX_ADDRESS( (uint32_t) mcanConfig->msgRam.pRxFifo1 ) 
00615             | MCAN_RXF1C_F1S(mcanConfig->nmbrFifo1Elmts);  
00616     // watermark interrupt off, blocking mode 
00617     mcan->MCAN_RXBC = MAILBOX_ADDRESS( (uint32_t) mcanConfig->msgRam.pRxDedBuf ); 
00618     mcan->MCAN_TXEFC = MAILBOX_ADDRESS( (uint32_t) mcanConfig->msgRam.pTxEvtFifo )
00619             | MCAN_TXEFC_EFS(mcanConfig->nmbrTxEvtFifoElmts);  
00620     // watermark interrupt off
00621     mcan->MCAN_TXBC = MAILBOX_ADDRESS( (uint32_t) mcanConfig->msgRam.pTxDedBuf ) 
00622             | MCAN_TXBC_NDTB(mcanConfig->nmbrTxDedBufElmts) 
00623             | MCAN_TXBC_TFQS(mcanConfig->nmbrTxFifoQElmts);
00624     mcan->MCAN_RXESC = ((mcanConfig->rxBufElmtSize >> (29-MCAN_RXESC_RBDS_Pos)) & 
00625                         MCAN_RXESC_RBDS_Msk) |
00626                         ((mcanConfig->rxFifo1ElmtSize >> (29-MCAN_RXESC_F1DS_Pos)) &
00627                         MCAN_RXESC_F1DS_Msk) |
00628                         ((mcanConfig->rxFifo0ElmtSize >> (29-MCAN_RXESC_F0DS_Pos)) &
00629                        MCAN_RXESC_F0DS_Msk);
00630     mcan->MCAN_TXESC = ((mcanConfig->txBufElmtSize >> (29-MCAN_TXESC_TBDS_Pos)) &
00631                 MCAN_TXESC_TBDS_Msk);  
00632     
00633     /* Configure Message Filters */
00634     // ...Disable all standard filters
00635     pMsgRam = mcanConfig->msgRam.pStdFilts;
00636     cntr = mcanConfig->nmbrStdFilts;
00637     while ( cntr > 0 ) {
00638       *pMsgRam++ = STD_FILT_SFEC_DISABLE;
00639       cntr--;
00640     }
00641     // ...Disable all extended filters
00642     pMsgRam = mcanConfig->msgRam.pExtFilts;
00643     cntr = mcanConfig->nmbrExtFilts;
00644     while ( cntr > 0 ) {
00645       *pMsgRam = EXT_FILT_EFEC_DISABLE;
00646       pMsgRam = pMsgRam + 2;
00647       cntr--;
00648     }
00649     
00650     mcan->MCAN_NDAT1 = 0xFFFFFFFF;  // clear new (rx) data flags
00651     mcan->MCAN_NDAT2 = 0xFFFFFFFF;  // clear new (rx) data flags
00652     
00653     regVal32 =  mcan->MCAN_CCCR & ~(MCAN_CCCR_CME_Msk | MCAN_CCCR_CMR_Msk);
00654     mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CME_ISO11898_1;      
00655     mcan->MCAN_CCCR = regVal32 | (MCAN_CCCR_CMR_ISO11898_1 | MCAN_CCCR_CME_ISO11898_1);
00656     
00657     __DSB();
00658     __ISB();
00659 }
00660 
00661 /**
00662  * \brief Enables a FUTURE switch to FD mode (tx & rx payloads up to 64 bytes)  
00663  * but transmits WITHOUT bit rate switching 
00664  * INIT must be set - so this should be called between MCAN_Init() and 
00665  * MCAN_Enable()
00666  * \param mcanConfig  Pointer to a MCAN instance.
00667  */
00668 void MCAN_InitFdEnable( const MCan_ConfigType * mcanConfig )
00669 {
00670     Mcan     * mcan = mcanConfig->pMCan;
00671     uint32_t   regVal32;
00672     
00673     regVal32 =  mcan->MCAN_CCCR & ~MCAN_CCCR_CME_Msk;
00674     mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CME(1);
00675 }
00676 
00677 /**
00678  * \brief Enables a FUTURE switch to FD mode (tx & rx payloads up to 64 bytes) and transmits 
00679  * WITH bit rate switching 
00680  * INIT must be set - so this should be called between MCAN_Init() and MCAN_Enable()
00681  * \param mcanConfig  Pointer to a MCAN instance.
00682  */
00683 void MCAN_InitFdBitRateSwitchEnable( const MCan_ConfigType * mcanConfig )
00684 {
00685     Mcan     * mcan = mcanConfig->pMCan;
00686     uint32_t   regVal32;
00687     
00688     regVal32 =  mcan->MCAN_CCCR & ~MCAN_CCCR_CME_Msk;
00689     mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CME(2);
00690 }
00691 
00692 /**
00693  * \brief Initializes the MCAN in loop back mode.
00694  * INIT must be set - so this should be called between MCAN_Init() and 
00695  * MCAN_Enable()
00696  * \param mcanConfig  Pointer to a MCAN instance.
00697  */
00698 void MCAN_InitLoopback( const MCan_ConfigType * mcanConfig )
00699 {
00700     Mcan * mcan = mcanConfig->pMCan;
00701     
00702     mcan->MCAN_CCCR |= MCAN_CCCR_TEST_ENABLED;
00703     //mcan->MCAN_CCCR |= MCAN_CCCR_MON_ENABLED;  // for internal loop back
00704     mcan->MCAN_TEST |= MCAN_TEST_LBCK_ENABLED;
00705 }
00706 
00707 /**
00708  * \brief Initializes MCAN queue for TX
00709  * INIT must be set - so this should be called between MCAN_Init() and 
00710  * MCAN_Enable()
00711  * \param mcanConfig  Pointer to a MCAN instance.
00712  */
00713 void MCAN_InitTxQueue( const MCan_ConfigType * mcanConfig )
00714 {
00715     Mcan * mcan = mcanConfig->pMCan;
00716     mcan->MCAN_TXBC |= MCAN_TXBC_TFQM;
00717 }
00718 
00719 /**
00720  * \brief Enable MCAN peripheral.
00721  * INIT must be set - so this should be called between MCAN_Init()
00722  * \param mcanConfig  Pointer to a MCAN instance.
00723  */
00724 void MCAN_Enable( const MCan_ConfigType * mcanConfig )
00725 {
00726     Mcan * mcan = mcanConfig->pMCan;
00727     mcan->MCAN_CCCR &= ~MCAN_CCCR_INIT_ENABLED;
00728 }
00729 
00730 /**
00731  * \brief Requests switch to Iso11898-1 (standard / classic) mode (tx & rx 
00732  * payloads up to 8 bytes).
00733  * \param mcanConfig  Pointer to a MCAN instance.
00734  */
00735 void MCAN_RequestIso11898_1( const MCan_ConfigType * mcanConfig )
00736 {
00737     Mcan     * mcan = mcanConfig->pMCan;
00738     uint32_t   regVal32;
00739     
00740     regVal32 =  mcan->MCAN_CCCR & ~MCAN_CCCR_CMR_Msk;
00741     mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CMR_ISO11898_1;      
00742     while ( (mcan->MCAN_CCCR & ( MCAN_CCCR_FDBS | MCAN_CCCR_FDO )) != 0 ) 
00743         { /* wait */ }
00744 }
00745 
00746 /**
00747  * \brief Requests switch to FD mode (tx & rx payloads up to 64 bytes) but 
00748  * transmits WITHOUT bit 
00749  * rate switching. requested mode should have been enabled at initialization
00750  * \param mcanConfig  Pointer to a MCAN instance.
00751  */
00752 void MCAN_RequestFd( const MCan_ConfigType * mcanConfig )
00753 {
00754     Mcan     * mcan = mcanConfig->pMCan;
00755     uint32_t   regVal32;
00756     
00757     if (( mcan->MCAN_CCCR & MCAN_CCCR_CME_Msk ) == MCAN_CCCR_CME(1) ) {
00758         regVal32 =  mcan->MCAN_CCCR & ~MCAN_CCCR_CMR_Msk;
00759         mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CMR_FD; 
00760         while ( (mcan->MCAN_CCCR & MCAN_CCCR_FDO) == 0 ) { /* wait */ }
00761     }
00762 }
00763 
00764 /**
00765  * \brief Request switch to FD mode (tx & rx payloads up to 64 bytes) and 
00766  * transmits WITH bit rate switching.
00767  * requested mode should have been enabled at initialization
00768  * \param mcanConfig  Pointer to a MCAN instance.
00769  */
00770 void MCAN_RequestFdBitRateSwitch( const MCan_ConfigType * mcanConfig )
00771 {
00772     Mcan     * mcan = mcanConfig->pMCan;
00773     uint32_t   regVal32;
00774     
00775     if (( mcan->MCAN_CCCR & MCAN_CCCR_CME_Msk ) == MCAN_CCCR_CME(2) ) {
00776       regVal32 =  mcan->MCAN_CCCR & ~MCAN_CCCR_CMR_Msk;
00777       mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CMR_FD_BITRATE_SWITCH;
00778       while ( (mcan->MCAN_CCCR & ( MCAN_CCCR_FDBS | MCAN_CCCR_FDO )) != 
00779             ( MCAN_CCCR_FDBS | MCAN_CCCR_FDO ) ) { /* wait */ }
00780     }
00781 }
00782 
00783 /**
00784  * \brief Switch on loop back mode.
00785  * TEST must be set in MCAN_CCCR - e.g. by a prior call to MCAN_InitLoopback()
00786  * \param mcanConfig  Pointer to a MCAN instance.
00787  */
00788 void MCAN_LoopbackOn( const MCan_ConfigType * mcanConfig )
00789 {  
00790     Mcan * mcan = mcanConfig->pMCan;
00791     mcan->MCAN_TEST |= MCAN_TEST_LBCK_ENABLED;
00792 }
00793 
00794 /**
00795  * \brief Switch off loop back mode.
00796  * \param mcanConfig  Pointer to a MCAN instance.
00797  */
00798 void MCAN_LoopbackOff( const MCan_ConfigType * mcanConfig )
00799 {  
00800     Mcan * mcan = mcanConfig->pMCan;
00801     mcan->MCAN_TEST &= ~MCAN_TEST_LBCK_ENABLED;
00802 }
00803 
00804 /**
00805  * \brief Enable message line and message stored to Dedicated Receive Buffer 
00806  * Interrupt Line.
00807  * \param mcanConfig  Pointer to a MCAN instance.
00808  * \param line  Message line.
00809  */
00810 void MCAN_IEnableMessageStoredToRxDedBuffer( const MCan_ConfigType * mcanConfig, 
00811         MCan_IntrLineType line )
00812 {
00813     Mcan * mcan = mcanConfig->pMCan;
00814     if ( line == CAN_INTR_LINE_0 ) {
00815         mcan->MCAN_ILS &= ~MCAN_ILS_DRXL;
00816         mcan->MCAN_ILE |= MCAN_ILE_EINT0;
00817     } else  {
00818     // Interrupt Line 1
00819         mcan->MCAN_ILS |= MCAN_ILS_DRXL;
00820         mcan->MCAN_ILE |= MCAN_ILE_EINT1;
00821     }
00822     mcan->MCAN_IR = MCAN_IR_DRX;  // clear previous flag
00823     mcan->MCAN_IE |= MCAN_IE_DRXE;  // enable it
00824 }
00825 
00826 /**
00827  * \brief Configures a Dedicated TX Buffer.
00828  * \param mcanConfig  Pointer to a MCAN instance.
00829  * \param buffer  Pointer to buffer.
00830  * \param id  Message ID.
00831  * \param idType  Type of ID
00832  * \param dlc  Type of dlc.
00833  */
00834 uint8_t  * MCAN_ConfigTxDedBuffer( const MCan_ConfigType * mcanConfig, 
00835         uint8_t buffer, uint32_t id, MCan_IdType idType, MCan_DlcType dlc )
00836 {
00837      Mcan * mcan = mcanConfig->pMCan;
00838      uint32_t * pThisTxBuf = 0;
00839      
00840      if ( buffer < mcanConfig->nmbrTxDedBufElmts ) {
00841         pThisTxBuf = mcanConfig->msgRam.pTxDedBuf + (buffer * 
00842             (mcanConfig->txBufElmtSize & ELMT_SIZE_MASK));
00843         if ( idType == CAN_STD_ID ) 
00844             *pThisTxBuf++ = (( id << 18 ) & ( CAN_11_BIT_ID_MASK << 18 ));
00845        else 
00846             *pThisTxBuf++ = BUFFER_XTD_MASK | ( id & CAN_29_BIT_ID_MASK );
00847         *pThisTxBuf++ = (uint32_t) dlc << 16;
00848         /* enable transmit from buffer to set TC interrupt bit in IR, but 
00849         interrupt will not happen unless TC interrupt is enabled*/
00850         mcan->MCAN_TXBTIE = ( 1 << buffer) ;
00851     }
00852     SCB_CleanInvalidateDCache();
00853     return (uint8_t *) pThisTxBuf;  // now it points to the data field
00854 }
00855 
00856 /**
00857  * \brief Send Tx buffer.
00858  * \param mcanConfig  Pointer to a MCAN instance.
00859  * \param buffer  Pointer to buffer.
00860  */
00861 void MCAN_SendTxDedBuffer( const MCan_ConfigType * mcanConfig, uint8_t buffer )
00862 { 
00863     Mcan * mcan = mcanConfig->pMCan;
00864     
00865     if ( buffer < mcanConfig->nmbrTxDedBufElmts ) {
00866       mcan->MCAN_TXBAR = ( 1 << buffer );
00867     }
00868 }
00869 
00870 /**
00871  * \brief Adds Message to TX Fifo / Queue 
00872  * \param mcanConfig  Pointer to a MCAN instance.
00873  * \param id  Message ID.
00874  * \param idType  Type of ID
00875  * \param dlc  Type of dlc.
00876  * \param data  Pointer to data.
00877  */
00878 uint32_t MCAN_AddToTxFifoQ( const MCan_ConfigType * mcanConfig, 
00879         uint32_t id, MCan_IdType idType, MCan_DlcType dlc, uint8_t * data )
00880 {
00881     Mcan * mcan = mcanConfig->pMCan;
00882     uint32_t   putIdx = 255;
00883     uint32_t * pThisTxBuf = 0;
00884     uint8_t  * pTxData;
00885     uint8_t    cnt;
00886     
00887     // Configured for FifoQ and FifoQ not full?
00888     if (( mcanConfig->nmbrTxFifoQElmts > 0 ) && 
00889             (( mcan->MCAN_TXFQS & MCAN_TXFQS_TFQF ) == 0 )) {
00890         putIdx = ( mcan->MCAN_TXFQS & MCAN_TXFQS_TFQPI_Msk ) >> MCAN_TXFQS_TFQPI_Pos;
00891         pThisTxBuf = mcanConfig->msgRam.pTxDedBuf + (putIdx * 
00892             (mcanConfig->txBufElmtSize & ELMT_SIZE_MASK));
00893         if ( idType == CAN_STD_ID ) 
00894             *pThisTxBuf++ = (( id << 18 ) & ( CAN_11_BIT_ID_MASK << 18 ));
00895         else 
00896             *pThisTxBuf++ = BUFFER_XTD_MASK | ( id & CAN_29_BIT_ID_MASK );
00897         *pThisTxBuf++ = (uint32_t) dlc << 16;
00898         pTxData = (uint8_t *) pThisTxBuf;
00899         for ( cnt = 0; cnt < dlc ; cnt++ ) {
00900             *pTxData++ = *data++;
00901         }
00902         /* enable transmit from buffer to set TC interrupt bit in IR, but
00903         interrupt will not happen unless TC interrupt is enabled */
00904         mcan->MCAN_TXBTIE = ( 1 << putIdx);
00905         // request to send
00906         mcan->MCAN_TXBAR = ( 1 << putIdx );
00907     }
00908     SCB_CleanInvalidateDCache();
00909     return putIdx;  // now it points to the data field
00910 }
00911 
00912 /**
00913  * \brief Check if data transmitted from buffer/fifo/queue
00914  * \param mcanConfig  Pointer to a MCAN instance.
00915  * \param buffer  Pointer to data buffer.
00916  */
00917 uint8_t MCAN_IsBufferTxd( const MCan_ConfigType * mcanConfig, uint8_t buffer )
00918 {
00919     Mcan * mcan = mcanConfig->pMCan;
00920     
00921     return ( mcan->MCAN_TXBTO & ( 1 << buffer ) );
00922 }
00923 
00924 /**
00925  * \brief Configure RX Buffer Filter
00926  * ID must match exactly for a RX Buffer Filter
00927  * \param mcanConfig  Pointer to a MCAN instance.
00928  * \param buffer  Pointer to data buffer.
00929  * \param filter  data of filter.
00930  * \param idType  Type of ID
00931  */
00932 void MCAN_ConfigRxBufferFilter( const MCan_ConfigType * mcanConfig, 
00933         uint32_t buffer, uint32_t filter, uint32_t id, MCan_IdType idType)
00934 { 
00935     uint32_t * pThisRxFilt = 0;
00936     
00937     if ( buffer < mcanConfig->nmbrRxDedBufElmts ) {
00938         if ( idType == CAN_STD_ID ) {
00939             if (( filter < mcanConfig->nmbrStdFilts ) 
00940                     && ( id <= CAN_11_BIT_ID_MASK )) {
00941                 pThisRxFilt = mcanConfig->msgRam.pStdFilts + filter;
00942                 // 1 word per filter
00943                 *pThisRxFilt = STD_FILT_SFEC_BUFFER | (id << 16) |
00944                         STD_FILT_SFID2_RX_BUFFER | buffer;
00945             }
00946         } else {
00947         // extended ID
00948             if (( filter < mcanConfig->nmbrExtFilts ) && 
00949                     ( id <= CAN_29_BIT_ID_MASK )) {
00950                 pThisRxFilt = mcanConfig->msgRam.pExtFilts + (2 * filter);
00951                 // 2 words per filter
00952                 *pThisRxFilt++ = (uint32_t) EXT_FILT_EFEC_BUFFER | id;
00953                 *pThisRxFilt = EXT_FILT_EFID2_RX_BUFFER | buffer;
00954             }
00955         }
00956     }
00957     SCB_CleanInvalidateDCache();
00958 }
00959 
00960 /**
00961  * \brief Configure Classic Filter
00962  * Classic Filters direct accepted messages to a FIFO & include both a ID and
00963  * a ID mask
00964  * \param mcanConfig  Pointer to a MCAN instance.
00965  * \param buffer  Pointer to data buffer.
00966  * \param fifo   fifo Number.
00967  * \param filter  data of filter.
00968  * \param idType  Type of ID
00969  * \param mask  Mask to be match
00970  */
00971 void MCAN_ConfigRxClassicFilter( const MCan_ConfigType * mcanConfig, 
00972         MCan_FifoType fifo, uint8_t filter, uint32_t id, 
00973         MCan_IdType idType, uint32_t mask )
00974 { 
00975     uint32_t * pThisRxFilt = 0;
00976     uint32_t   filterTemp;
00977     
00978     if ( idType == CAN_STD_ID ) {
00979         if (( filter < mcanConfig->nmbrStdFilts ) && ( id <= CAN_11_BIT_ID_MASK ) 
00980                 && ( mask <= CAN_11_BIT_ID_MASK )) {
00981             pThisRxFilt = mcanConfig->msgRam.pStdFilts + filter;  
00982             // 1 word per filter
00983             filterTemp = (uint32_t) STD_FILT_SFT_CLASSIC | (id << 16) | mask;
00984             if ( fifo == CAN_FIFO_0 ) {
00985                 *pThisRxFilt = STD_FILT_SFEC_FIFO0 | filterTemp;
00986             } else if ( fifo == CAN_FIFO_1 ) {
00987                 *pThisRxFilt = STD_FILT_SFEC_FIFO1 | filterTemp;
00988             }
00989         } else { 
00990             // extended ID
00991             if (( filter < mcanConfig->nmbrExtFilts ) 
00992                     && ( id <= CAN_29_BIT_ID_MASK ) 
00993                     && ( mask <= CAN_29_BIT_ID_MASK )) {
00994                 pThisRxFilt = mcanConfig->msgRam.pExtFilts + (2 * filter);
00995                 // 2 words per filter
00996                 if ( fifo == CAN_FIFO_0 ) {
00997                     *pThisRxFilt++ = EXT_FILT_EFEC_FIFO0 | id;
00998                 } else if ( fifo == CAN_FIFO_0 ) {
00999                     *pThisRxFilt++ = EXT_FILT_EFEC_FIFO1 | id;
01000                 }
01001                 *pThisRxFilt = (uint32_t) EXT_FILT_EFT_CLASSIC | mask;
01002             }
01003         }
01004     }
01005     SCB_CleanInvalidateDCache();
01006 }
01007 
01008 /**
01009  * \brief check if data received into buffer
01010  * \param mcanConfig  Pointer to a MCAN instance.
01011  * \param buffer  Pointer to data buffer.
01012  */
01013 uint8_t MCAN_IsNewDataInRxDedBuffer( const MCan_ConfigType * mcanConfig, 
01014                                 uint8_t buffer )
01015 {
01016     Mcan * mcan = mcanConfig->pMCan;
01017     
01018     SCB_CleanInvalidateDCache();
01019     
01020     if ( buffer < 32 ) {
01021       return ( mcan->MCAN_NDAT1 & ( 1 << buffer ));
01022     } else if ( buffer < 64 ) {
01023       return ( mcan->MCAN_NDAT1 & ( 1 << (buffer - 32 )));
01024     }    
01025     else
01026       return 0;
01027 }
01028 
01029 /**
01030  * \brief Get Rx buffer
01031  * \param mcanConfig  Pointer to a MCAN instance.
01032  * \param buffer  Pointer to data buffer.
01033  * \param pRxMailbox  Pointer to rx Mailbox.
01034  */
01035 void MCAN_GetRxDedBuffer( const MCan_ConfigType * mcanConfig, 
01036                     uint8_t buffer, Mailbox64Type * pRxMailbox )
01037 {
01038     Mcan     * mcan = mcanConfig->pMCan;
01039     uint32_t * pThisRxBuf = 0;
01040     uint32_t   tempRy;  // temp copy of RX buffer word
01041     uint8_t  * pRxData;
01042     uint8_t    idx;
01043     
01044     SCB_CleanInvalidateDCache();
01045     
01046     if ( buffer < mcanConfig->nmbrRxDedBufElmts ) {
01047         pThisRxBuf = mcanConfig->msgRam.pRxDedBuf 
01048             + (buffer * (mcanConfig->rxBufElmtSize & ELMT_SIZE_MASK));
01049         tempRy = *pThisRxBuf++;  // word R0 contains ID
01050         if ( tempRy & BUFFER_XTD_MASK ) {
01051             // extended ID?
01052             pRxMailbox->info.id = tempRy & BUFFER_EXT_ID_MASK;
01053         } else {
01054             // standard ID
01055             pRxMailbox->info.id = ( tempRy & BUFFER_STD_ID_MASK) >> 18;
01056         }
01057         tempRy = *pThisRxBuf++;  // word R1 contains DLC & time stamp
01058         pRxMailbox->info.length = (tempRy & BUFFER_DLC_MASK) >> 16;
01059         pRxMailbox->info.timestamp = tempRy & BUFFER_RXTS_MASK;
01060         // copy the data from the buffer to the mailbox
01061         pRxData = (uint8_t *) pThisRxBuf;
01062         for ( idx = 0; idx < pRxMailbox->info.length; idx++ )
01063             pRxMailbox->data[idx] = *pRxData++;
01064         /* clear the new data flag for the buffer */
01065         if ( buffer < 32 ) {
01066             mcan->MCAN_NDAT1 = ( 1 << buffer );
01067         } else {
01068             mcan->MCAN_NDAT1 = ( 1 << (buffer - 32 ));
01069         }
01070     }
01071 }
01072 
01073 /**
01074  * \brief Get from the receive FIFO and place in a application mailbox
01075  * \param mcanConfig  Pointer to a MCAN instance.
01076  * \param fifo  Fifo Number
01077  * \param pRxMailbox  Pointer to rx Mailbox.
01078  * \return: # of fifo entries at the start of the function
01079  *         0 -> FIFO was empty at start
01080  *         1 -> FIFO had 1 entry at start, but is empty at finish
01081  *         2 -> FIFO had 2 entries at start, has 1 entry at finish
01082  */
01083 uint32_t MCAN_GetRxFifoBuffer( const MCan_ConfigType * mcanConfig, 
01084         MCan_FifoType fifo, Mailbox64Type * pRxMailbox )
01085 {
01086     Mcan     * mcan = mcanConfig->pMCan;
01087     uint32_t * pThisRxBuf = 0;
01088     uint32_t   tempRy;  // temp copy of RX buffer word
01089     uint8_t  * pRxData;
01090     uint8_t    idx;
01091     uint32_t * fifo_ack_reg;
01092     uint32_t   get_index;
01093     uint32_t   fill_level;
01094     uint32_t   element_size;
01095     
01096     SCB_CleanInvalidateDCache();
01097     
01098     // default: fifo empty
01099     fill_level = 0; 
01100     
01101     if ( fifo == CAN_FIFO_0 ) {
01102         get_index = ( mcan->MCAN_RXF0S & MCAN_RXF0S_F0GI_Msk ) >> MCAN_RXF0S_F0GI_Pos;
01103         fill_level = ( mcan->MCAN_RXF0S & MCAN_RXF0S_F0FL_Msk ) >> MCAN_RXF0S_F0FL_Pos;
01104         pThisRxBuf = mcanConfig->msgRam.pRxFifo0;
01105         element_size = mcanConfig->rxFifo0ElmtSize & ELMT_SIZE_MASK;
01106         fifo_ack_reg = (uint32_t *) &mcan->MCAN_RXF0A;
01107     } else if ( fifo == CAN_FIFO_1 ) {
01108         get_index = ( mcan->MCAN_RXF1S & MCAN_RXF1S_F1GI_Msk ) >> MCAN_RXF1S_F1GI_Pos;
01109         fill_level = ( mcan->MCAN_RXF1S & MCAN_RXF1S_F1FL_Msk ) >> MCAN_RXF1S_F1FL_Pos;
01110         pThisRxBuf = mcanConfig->msgRam.pRxFifo1;
01111         element_size = mcanConfig->rxFifo1ElmtSize & ELMT_SIZE_MASK;
01112         fifo_ack_reg = (uint32_t *) &mcan->MCAN_RXF1A;
01113     }
01114     
01115     if ( fill_level > 0 ) {
01116         pThisRxBuf = pThisRxBuf + (get_index * element_size);
01117         tempRy = *pThisRxBuf++;  // word R0 contains ID
01118         if ( tempRy & BUFFER_XTD_MASK ) {
01119             // extended ID?
01120             pRxMailbox->info.id = tempRy & BUFFER_EXT_ID_MASK;
01121         } else {
01122             // standard ID
01123             pRxMailbox->info.id = ( tempRy & BUFFER_STD_ID_MASK) >> 18;
01124         }
01125         tempRy = *pThisRxBuf++;  // word R1 contains DLC & timestamps
01126         pRxMailbox->info.length = (tempRy & BUFFER_DLC_MASK) >> 16;
01127         pRxMailbox->info.timestamp = tempRy & BUFFER_RXTS_MASK;
01128         /* copy the data from the buffer to the mailbox */
01129         pRxData = (uint8_t *) pThisRxBuf;
01130         for ( idx = 0; idx < pRxMailbox->info.length; idx++ )
01131             pRxMailbox->data[idx] = *pRxData++;
01132         // acknowledge reading the fifo entry
01133         *fifo_ack_reg = get_index;
01134         /* return entries remaining in FIFO */
01135     }
01136     return ( fill_level );
01137 }
01138 
01139 /**@}*/
01140 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines