summaryrefslogtreecommitdiffstats
path: root/bsps/arm/atsam/contrib/libraries/libchip/source/mcan.c
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/arm/atsam/contrib/libraries/libchip/source/mcan.c')
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/mcan.c1175
1 files changed, 1175 insertions, 0 deletions
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/mcan.c b/bsps/arm/atsam/contrib/libraries/libchip/source/mcan.c
new file mode 100644
index 0000000000..e91f73e871
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/mcan.c
@@ -0,0 +1,1175 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR */
+/* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE */
+/* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, */
+/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
+/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
+/* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */
+/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
+/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
+/* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+/* ---------------------------------------------------------------------------- */
+
+/** \file
+ * Implements functions for Controller Area Network (CAN)
+ * peripheral operations.
+ */
+/** \addtogroup can_module
+ *@{*/
+
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+#ifndef __rtems__
+#include "board.h"
+#endif /* __rtems__ */
+#include "chip.h"
+#include "mcan_config.h"
+#include <assert.h>
+/*---------------------------------------------------------------------------
+ * Definitions
+ *---------------------------------------------------------------------------*/
+#define MAILBOX_ADDRESS(address) (0xFFFC & (address))
+
+#define CAN_CLK_FREQ_HZ MCAN_PROG_CLK_FREQ_HZ
+
+#define MCAN0_TSEG1 (MCAN0_PROP_SEG + MCAN0_PHASE_SEG1)
+#define MCAN0_TSEG2 (MCAN0_PHASE_SEG2)
+#define MCAN0_BRP ((uint32_t) (((float) CAN_CLK_FREQ_HZ / \
+ ((float)(MCAN0_TSEG1 + MCAN0_TSEG2 + 3) *\
+ (float) MCAN0_BIT_RATE_BPS)) - 1))
+#define MCAN0_SJW (MCAN0_SYNC_JUMP - 1)
+#define MCAN0_FTSEG1 (MCAN0_FAST_PROP_SEG + MCAN0_FAST_PHASE_SEG1)
+#define MCAN0_FTSEG2 (MCAN0_FAST_PHASE_SEG2)
+#define MCAN0_FBRP ((uint32_t) (((float) CAN_CLK_FREQ_HZ / \
+ ((float)(MCAN0_FTSEG1 + MCAN0_FTSEG2 + 3) * \
+ (float) MCAN0_FAST_BIT_RATE_BPS)) - 1))
+#define MCAN0_FSJW (MCAN0_FAST_SYNC_JUMP - 1)
+
+#define MCAN0_STD_FLTS_WRDS (MCAN0_NMBR_STD_FLTS)
+/* 128 max filters */
+#define MCAN0_EXT_FLTS_WRDS (MCAN0_NMBR_EXT_FLTS * 2)
+/* 64 max filters */
+#define MCAN0_RX_FIFO0_WRDS (MCAN0_NMBR_RX_FIFO0_ELMTS * \
+ ((MCAN0_RX_FIFO0_ELMT_SZ/4) + 2))
+/* 64 elements max */
+#define MCAN0_RX_FIFO1_WRDS (MCAN0_NMBR_RX_FIFO1_ELMTS *\
+ ((MCAN0_RX_FIFO1_ELMT_SZ/4) + 2))
+/* 64 elements max */
+#define MCAN0_RX_DED_BUFS_WRDS (MCAN0_NMBR_RX_DED_BUF_ELMTS * \
+ ((MCAN0_RX_BUF_ELMT_SZ/4) + 2))
+/* 64 elements max */
+#define MCAN0_TX_EVT_FIFO_WRDS (MCAN0_NMBR_TX_EVT_FIFO_ELMTS * 2)
+/* 32 elements max */
+#define MCAN0_TX_DED_BUF_WRDS (MCAN0_NMBR_TX_DED_BUF_ELMTS * \
+ ((MCAN0_TX_BUF_ELMT_SZ/4) + 2))
+/* 32 elements max */
+#define MCAN0_TX_FIFO_Q_WRDS (MCAN0_NMBR_TX_FIFO_Q_ELMTS *\
+ ((MCAN0_TX_BUF_ELMT_SZ/4) + 2))
+/* 32 elements max */
+
+#define MCAN1_TSEG1 (MCAN1_PROP_SEG + MCAN1_PHASE_SEG1)
+#define MCAN1_TSEG2 (MCAN1_PHASE_SEG2)
+#define MCAN1_BRP ((uint32_t) (((float) CAN_CLK_FREQ_HZ / \
+ ((float)(MCAN1_TSEG1 + MCAN1_TSEG2 + 3) *\
+ (float) MCAN1_BIT_RATE_BPS)) - 1))
+#define MCAN1_SJW (MCAN1_SYNC_JUMP - 1)
+#define MCAN1_FTSEG1 (MCAN1_FAST_PROP_SEG + MCAN1_FAST_PHASE_SEG1)
+#define MCAN1_FTSEG2 (MCAN1_FAST_PHASE_SEG2)
+#define MCAN1_FBRP ((uint32_t) (((float) CAN_CLK_FREQ_HZ /\
+ ((float)(MCAN1_FTSEG1 + MCAN1_FTSEG2 + 3) *\
+ (float) MCAN1_FAST_BIT_RATE_BPS)) - 1))
+#define MCAN1_FSJW (MCAN1_FAST_SYNC_JUMP - 1)
+
+#define MCAN1_STD_FLTS_WRDS (MCAN1_NMBR_STD_FLTS)
+/* 128 max filters */
+#define MCAN1_EXT_FLTS_WRDS (MCAN1_NMBR_EXT_FLTS * 2)
+/* 64 max filters */
+#define MCAN1_RX_FIFO0_WRDS (MCAN1_NMBR_RX_FIFO0_ELMTS * \
+ ((MCAN1_RX_FIFO0_ELMT_SZ/4) + 2))
+/* 64 elements max */
+#define MCAN1_RX_FIFO1_WRDS (MCAN1_NMBR_RX_FIFO1_ELMTS *\
+ ((MCAN1_RX_FIFO1_ELMT_SZ/4) + 2))
+/* 64 elements max */
+#define MCAN1_RX_DED_BUFS_WRDS (MCAN1_NMBR_RX_DED_BUF_ELMTS * \
+ ((MCAN1_RX_BUF_ELMT_SZ/4) + 2))
+/* 64 elements max */
+#define MCAN1_TX_EVT_FIFO_WRDS (MCAN1_NMBR_TX_EVT_FIFO_ELMTS * 2)
+/* 32 elements max */
+#define MCAN1_TX_DED_BUF_WRDS (MCAN1_NMBR_TX_DED_BUF_ELMTS * \
+ ((MCAN1_TX_BUF_ELMT_SZ/4) + 2))
+/* 32 elements max */
+#define MCAN1_TX_FIFO_Q_WRDS (MCAN1_NMBR_TX_FIFO_Q_ELMTS * \
+ ((MCAN1_TX_BUF_ELMT_SZ/4) + 2))
+/* 32 elements max */
+
+/* validate CAN0 entries */
+#if (MCAN0_TSEG1 > 63)
+ #error "Invalid CAN0 TSEG1"
+#endif
+#if (MCAN0_TSEG2 > 15)
+ #error "Invalid CAN0 TSEG2"
+#endif
+#if (MCAN0_SJW > 15)
+ #error "Invalid CAN0 SJW"
+#endif
+#if (MCAN0_FTSEG1 > 15)
+ #error "Invalid CAN0 FTSEG1"
+#endif
+#if (MCAN0_FTSEG2 > 7)
+ #error "Invalid CAN0 FTSEG2"
+#endif
+#if (MCAN0_FSJW > 3)
+ #error "Invalid CAN0 FSJW"
+#endif
+
+#if (MCAN0_NMBR_STD_FLTS > 128)
+ #error "Invalid CAN0 # of Standard Filters"
+#endif
+#if (MCAN0_NMBR_EXT_FLTS > 64)
+ #error "Invalid CAN0 # of Extended Filters"
+#endif
+#if (MCAN0_NMBR_RX_FIFO0_ELMTS > 64)
+ #error "Invalid CAN0 # RX FIFO 0 ELEMENTS"
+#endif
+#if (MCAN0_NMBR_RX_FIFO1_ELMTS > 64)
+ #error "Invalid CAN0 # RX FIFO 0 ELEMENTS"
+#endif
+#if (MCAN0_NMBR_RX_DED_BUF_ELMTS > 64)
+ #error "Invalid CAN0 # RX BUFFER ELEMENTS"
+#endif
+#if (MCAN0_NMBR_TX_EVT_FIFO_ELMTS > 32)
+ #error "Invalid CAN0 # TX EVENT FIFO ELEMENTS"
+#endif
+#if ((MCAN0_NMBR_TX_DED_BUF_ELMTS + MCAN0_NMBR_TX_FIFO_Q_ELMTS) > 32)
+ #error "Invalid CAN0 # TX BUFFER ELEMENTS"
+#endif
+
+#if (8 == MCAN0_RX_FIFO0_ELMT_SZ)
+ #define MCAN0_RX_FIFO0_DATA_SIZE (0u)
+#elif (12 == MCAN0_RX_FIFO0_ELMT_SZ)
+ #define MCAN0_RX_FIFO0_DATA_SIZE (1u)
+#elif (16 == MCAN0_RX_FIFO0_ELMT_SZ)
+ #define MCAN0_RX_FIFO0_DATA_SIZE (2u)
+#elif (20 == MCAN0_RX_FIFO0_ELMT_SZ)
+ #define MCAN0_RX_FIFO0_DATA_SIZE (3u)
+#elif (24 == MCAN0_RX_FIFO0_ELMT_SZ)
+ #define MCAN0_RX_FIFO0_DATA_SIZE (4u)
+#elif (32 == MCAN0_RX_FIFO0_ELMT_SZ)
+ #define MCAN0_RX_FIFO0_DATA_SIZE (5u)
+#elif (48 == MCAN0_RX_FIFO0_ELMT_SZ)
+ #define MCAN0_RX_FIFO0_DATA_SIZE (6u)
+#elif (64 == MCAN0_RX_FIFO0_ELMT_SZ)
+ #define MCAN0_RX_FIFO0_DATA_SIZE (7u)
+#else
+ #error "Invalid CAN0 RX FIFO0 ELEMENT SIZE"
+#endif
+
+#if (8 == MCAN0_RX_FIFO1_ELMT_SZ)
+ #define MCAN0_RX_FIFO1_DATA_SIZE (0u)
+#elif (12 == MCAN0_RX_FIFO1_ELMT_SZ)
+ #define MCAN0_RX_FIFO1_DATA_SIZE (1u)
+#elif (16 == MCAN0_RX_FIFO1_ELMT_SZ)
+ #define MCAN0_RX_FIFO1_DATA_SIZE (2u)
+#elif (20 == MCAN0_RX_FIFO1_ELMT_SZ)
+ #define MCAN0_RX_FIFO1_DATA_SIZE (3u)
+#elif (24 == MCAN0_RX_FIFO1_ELMT_SZ)
+ #define MCAN0_RX_FIFO1_DATA_SIZE (4u)
+#elif (32 == MCAN0_RX_FIFO1_ELMT_SZ)
+ #define MCAN0_RX_FIFO1_DATA_SIZE (5u)
+#elif (48 == MCAN0_RX_FIFO1_ELMT_SZ)
+ #define MCAN0_RX_FIFO1_DATA_SIZE (6u)
+#elif (64 == MCAN0_RX_FIFO1_ELMT_SZ)
+ #define MCAN0_RX_FIFO1_DATA_SIZE (7u)
+#else
+ #error "Invalid CAN0 RX FIFO1 ELEMENT SIZE"
+#endif
+
+#if (8 == MCAN0_RX_BUF_ELMT_SZ)
+ #define MCAN0_RX_BUF_DATA_SIZE (0u)
+#elif (12 == MCAN0_RX_BUF_ELMT_SZ)
+ #define MCAN0_RX_BUF_DATA_SIZE (1u)
+#elif (16 == MCAN0_RX_BUF_ELMT_SZ)
+ #define MCAN0_RX_BUF_DATA_SIZE (2u)
+#elif (20 == MCAN0_RX_BUF_ELMT_SZ)
+ #define MCAN0_RX_BUF_DATA_SIZE (3u)
+#elif (24 == MCAN0_RX_BUF_ELMT_SZ)
+ #define MCAN0_RX_BUF_DATA_SIZE (4u)
+#elif (32 == MCAN0_RX_BUF_ELMT_SZ)
+ #define MCAN0_RX_BUF_DATA_SIZE (5u)
+#elif (48 == MCAN0_RX_BUF_ELMT_SZ)
+ #define MCAN0_RX_BUF_DATA_SIZE (6u)
+#elif (64 == MCAN0_RX_BUF_ELMT_SZ)
+ #define MCAN0_RX_BUF_DATA_SIZE (7u)
+#else
+ #error "Invalid CAN0 RX BUFFER ELEMENT SIZE"
+#endif
+
+#if (8 == MCAN0_TX_BUF_ELMT_SZ)
+ #define MCAN0_TX_BUF_DATA_SIZE (0u)
+#elif (12 == MCAN0_TX_BUF_ELMT_SZ)
+ #define MCAN0_TX_BUF_DATA_SIZE (1u)
+#elif (16 == MCAN0_TX_BUF_ELMT_SZ)
+ #define MCAN0_TX_BUF_DATA_SIZE (2u)
+#elif (20 == MCAN0_TX_BUF_ELMT_SZ)
+ #define MCAN0_TX_BUF_DATA_SIZE (3u)
+#elif (24 == MCAN0_TX_BUF_ELMT_SZ)
+ #define MCAN0_TX_BUF_DATA_SIZE (4u)
+#elif (32 == MCAN0_TX_BUF_ELMT_SZ)
+ #define MCAN0_TX_BUF_DATA_SIZE (5u)
+#elif (48 == MCAN0_TX_BUF_ELMT_SZ)
+ #define MCAN0_TX_BUF_DATA_SIZE (6u)
+#elif (64 == MCAN0_TX_BUF_ELMT_SZ)
+ #define MCAN0_TX_BUF_DATA_SIZE (7u)
+#else
+ #error "Invalid CAN0 TX BUFFER ELEMENT SIZE"
+#endif
+
+/* validate CAN1 entries */
+#if (MCAN1_TSEG1 > 63)
+ #error "Invalid CAN1 TSEG1"
+#endif
+#if (MCAN1_TSEG2 > 15)
+ #error "Invalid CAN1 TSEG2"
+#endif
+#if (MCAN1_SJW > 15)
+ #error "Invalid CAN1 SJW"
+#endif
+#if (MCAN1_FTSEG1 > 15)
+ #error "Invalid CAN1 FTSEG1"
+#endif
+#if (MCAN1_FTSEG2 > 7)
+ #error "Invalid CAN1 FTSEG2"
+#endif
+#if (MCAN1_FSJW > 3)
+ #error "Invalid CAN1 FSJW"
+#endif
+
+#if (MCAN1_NMBR_STD_FLTS > 128)
+ #error "Invalid CAN1 # of Standard Filters"
+#endif
+#if (MCAN1_NMBR_EXT_FLTS > 64)
+ #error "Invalid CAN1 # of Extended Filters"
+#endif
+#if (MCAN1_NMBR_RX_FIFO0_ELMTS > 64)
+ #error "Invalid CAN1 # RX FIFO 0 ELEMENTS"
+#endif
+#if (MCAN1_NMBR_RX_FIFO1_ELMTS > 64)
+ #error "Invalid CAN1 # RX FIFO 0 ELEMENTS"
+#endif
+#if (MCAN1_NMBR_RX_DED_BUF_ELMTS > 64)
+ #error "Invalid CAN1 # RX BUFFER ELEMENTS"
+#endif
+#if (MCAN1_NMBR_TX_EVT_FIFO_ELMTS > 32)
+ #error "Invalid CAN1 # TX EVENT FIFO ELEMENTS"
+#endif
+#if ((MCAN1_NMBR_TX_DED_BUF_ELMTS + MCAN1_NMBR_TX_FIFO_Q_ELMTS) > 32)
+ #error "Invalid CAN1 # TX BUFFER ELEMENTS"
+#endif
+
+#if (8 == MCAN1_RX_FIFO0_ELMT_SZ)
+ #define MCAN1_RX_FIFO0_DATA_SIZE (0u)
+#elif (12 == MCAN1_RX_FIFO0_ELMT_SZ)
+ #define MCAN1_RX_FIFO0_DATA_SIZE (1u)
+#elif (16 == MCAN1_RX_FIFO0_ELMT_SZ)
+ #define MCAN1_RX_FIFO0_DATA_SIZE (2u)
+#elif (20 == MCAN1_RX_FIFO0_ELMT_SZ)
+ #define MCAN1_RX_FIFO0_DATA_SIZE (3u)
+#elif (24 == MCAN1_RX_FIFO0_ELMT_SZ)
+ #define MCAN1_RX_FIFO0_DATA_SIZE (4u)
+#elif (32 == MCAN1_RX_FIFO0_ELMT_SZ)
+ #define MCAN1_RX_FIFO0_DATA_SIZE (5u)
+#elif (48 == MCAN1_RX_FIFO0_ELMT_SZ)
+ #define MCAN1_RX_FIFO0_DATA_SIZE (6u)
+#elif (64 == MCAN1_RX_FIFO0_ELMT_SZ)
+ #define MCAN1_RX_FIFO0_DATA_SIZE (7u)
+#else
+ #error "Invalid CAN1 RX FIFO0 ELEMENT SIZE"
+#endif
+
+#if (8 == MCAN1_RX_FIFO1_ELMT_SZ)
+ #define MCAN1_RX_FIFO1_DATA_SIZE (0u)
+#elif (12 == MCAN1_RX_FIFO1_ELMT_SZ)
+ #define MCAN1_RX_FIFO1_DATA_SIZE (1u)
+#elif (16 == MCAN1_RX_FIFO1_ELMT_SZ)
+ #define MCAN1_RX_FIFO1_DATA_SIZE (2u)
+#elif (20 == MCAN1_RX_FIFO1_ELMT_SZ)
+ #define MCAN1_RX_FIFO1_DATA_SIZE (3u)
+#elif (24 == MCAN1_RX_FIFO1_ELMT_SZ)
+ #define MCAN1_RX_FIFO1_DATA_SIZE (4u)
+#elif (32 == MCAN1_RX_FIFO1_ELMT_SZ)
+ #define MCAN1_RX_FIFO1_DATA_SIZE (5u)
+#elif (48 == MCAN1_RX_FIFO1_ELMT_SZ)
+ #define MCAN1_RX_FIFO1_DATA_SIZE (6u)
+#elif (64 == MCAN1_RX_FIFO1_ELMT_SZ)
+ #define MCAN1_RX_FIFO1_DATA_SIZE (7u)
+#else
+ #error "Invalid CAN1 RX FIFO1 ELEMENT SIZE"
+#endif
+
+#if (8 == MCAN1_RX_BUF_ELMT_SZ)
+ #define MCAN1_RX_BUF_DATA_SIZE (0u)
+#elif (12 == MCAN1_RX_BUF_ELMT_SZ)
+ #define MCAN1_RX_BUF_DATA_SIZE (1u)
+#elif (16 == MCAN1_RX_BUF_ELMT_SZ)
+ #define MCAN1_RX_BUF_DATA_SIZE (2u)
+#elif (20 == MCAN1_RX_BUF_ELMT_SZ)
+ #define MCAN1_RX_BUF_DATA_SIZE (3u)
+#elif (24 == MCAN1_RX_BUF_ELMT_SZ)
+ #define MCAN1_RX_BUF_DATA_SIZE (4u)
+#elif (32 == MCAN1_RX_BUF_ELMT_SZ)
+ #define MCAN1_RX_BUF_DATA_SIZE (5u)
+#elif (48 == MCAN1_RX_BUF_ELMT_SZ)
+ #define MCAN1_RX_BUF_DATA_SIZE (6u)
+#elif (64 == MCAN1_RX_BUF_ELMT_SZ)
+ #define MCAN1_RX_BUF_DATA_SIZE (7u)
+#else
+ #error "Invalid CAN1 RX BUFFER ELEMENT SIZE"
+#endif
+
+#if (8 == MCAN1_TX_BUF_ELMT_SZ)
+ #define MCAN1_TX_BUF_DATA_SIZE (0u)
+#elif (12 == MCAN1_TX_BUF_ELMT_SZ)
+ #define MCAN1_TX_BUF_DATA_SIZE (1u)
+#elif (16 == MCAN1_TX_BUF_ELMT_SZ)
+ #define MCAN1_TX_BUF_DATA_SIZE (2u)
+#elif (20 == MCAN1_TX_BUF_ELMT_SZ)
+ #define MCAN1_TX_BUF_DATA_SIZE (3u)
+#elif (24 == MCAN1_TX_BUF_ELMT_SZ)
+ #define MCAN1_TX_BUF_DATA_SIZE (4u)
+#elif (32 == MCAN1_TX_BUF_ELMT_SZ)
+ #define MCAN1_TX_BUF_DATA_SIZE (5u)
+#elif (48 == MCAN1_TX_BUF_ELMT_SZ)
+ #define MCAN1_TX_BUF_DATA_SIZE (6u)
+#elif (64 == MCAN1_TX_BUF_ELMT_SZ)
+ #define MCAN1_TX_BUF_DATA_SIZE (7u)
+#else
+ #error "Invalid CAN1 TX BUFFER ELEMENT SIZE"
+#endif
+
+#define CAN_11_BIT_ID_MASK (0x7FF)
+#define CAN_29_BIT_ID_MASK (0x1FFFFFFF)
+#define ELMT_SIZE_MASK (0x1F)
+/* max element size is 18 words, fits in 5 bits */
+
+#define BUFFER_XTD_MASK (0x40000000)
+#define BUFFER_EXT_ID_MASK (0x1FFFFFFF)
+#define BUFFER_STD_ID_MASK (0x1FFC0000)
+#define BUFFER_DLC_MASK (0x000F0000)
+#define BUFFER_RXTS_MASK (0x0000FFFF)
+
+#define STD_FILT_SFT_MASK (3U << 30)
+#define STD_FILT_SFT_RANGE (0U << 30)
+#define STD_FILT_SFT_DUAL (1U << 30)
+#define STD_FILT_SFT_CLASSIC (2U << 30)
+#define STD_FILT_SFEC_MASK (7U << 27)
+#define STD_FILT_SFEC_DISABLE (0U << 27)
+#define STD_FILT_SFEC_FIFO0 (1U << 27)
+#define STD_FILT_SFEC_FIFO1 (2U << 27)
+#define STD_FILT_SFEC_REJECT (3U << 27)
+#define STD_FILT_SFEC_PRIORITY (4U << 27)
+#define STD_FILT_SFEC_PRIORITY_FIFO0 (5U << 27)
+#define STD_FILT_SFEC_PRIORITY_FIFO1 (6U << 27)
+#define STD_FILT_SFEC_BUFFER (7U << 27)
+#define STD_FILT_SFID1_MASK (0x03FFU << 16)
+#define STD_FILT_SFID2_MASK (0x3FFU << 0)
+#define STD_FILT_SFID2_RX_BUFFER (0U << 9)
+#define STD_FILT_SFID2_DEBUG_A (1U << 9)
+#define STD_FILT_SFID2_DEBUG_B (2U << 9)
+#define STD_FILT_SFID2_DEBUG_C (3U << 9)
+#define STD_FILT_SFID2_BUFFER(nmbr) (nmbr & 0x3F)
+
+#define EXT_FILT_EFEC_MASK (7U << 29)
+#define EXT_FILT_EFEC_DISABLE (0U << 29)
+#define EXT_FILT_EFEC_FIFO0 (1U << 29)
+#define EXT_FILT_EFEC_FIFO1 (2U << 29)
+#define EXT_FILT_EFEC_REJECT (3U << 29)
+#define EXT_FILT_EFEC_PRIORITY (4U << 29)
+#define EXT_FILT_EFEC_PRIORITY_FIFO0 (5U << 29)
+#define EXT_FILT_EFEC_PRIORITY_FIFO1 (6U << 29)
+#define EXT_FILT_EFEC_BUFFER (7U << 29)
+#define EXT_FILT_EFID1_MASK (0x1FFFFFFF)
+#define EXT_FILT_EFT_MASK (3U << 30)
+#define EXT_FILT_EFT_RANGE (0U << 30)
+#define EXT_FILT_EFT_DUAL (1U << 30)
+#define EXT_FILT_EFT_CLASSIC (2U << 30)
+#define EXT_FILT_EFT_RANGE_NO_XIDAM (3U << 30)
+#define EXT_FILT_EFID2_MASK (0x1FFFFFFF)
+#define EXT_FILT_EFID2_RX_BUFFER (0U << 9)
+#define EXT_FILT_EFID2_DEBUG_A (1U << 9)
+#define EXT_FILT_EFID2_DEBUG_B (2U << 9)
+#define EXT_FILT_EFID2_DEBUG_C (3U << 9)
+#define EXT_FILT_EFID2_BUFFER(nmbr) (nmbr & 0x3F)
+
+
+/*---------------------------------------------------------------------------
+ * Internal variables
+ *---------------------------------------------------------------------------*/
+
+#ifndef __rtems__
+static const Pin pinsMcan0[] = {PIN_MCAN0_TXD, PIN_MCAN0_RXD };
+static const Pin pinsMcan1[] = {PIN_MCAN1_TXD, PIN_MCAN1_RXD };
+#endif /* __rtems__ */
+
+static uint32_t can0MsgRam[MCAN0_STD_FLTS_WRDS +
+ MCAN0_EXT_FLTS_WRDS +
+ MCAN0_RX_FIFO0_WRDS +
+ MCAN0_RX_FIFO1_WRDS +
+ MCAN0_RX_DED_BUFS_WRDS +
+ MCAN0_TX_EVT_FIFO_WRDS +
+ MCAN0_TX_DED_BUF_WRDS +
+ MCAN0_TX_FIFO_Q_WRDS];
+
+static uint32_t can1MsgRam[MCAN1_STD_FLTS_WRDS +
+ MCAN1_EXT_FLTS_WRDS +
+ MCAN1_RX_FIFO0_WRDS +
+ MCAN1_RX_FIFO1_WRDS +
+ MCAN1_RX_DED_BUFS_WRDS +
+ MCAN1_TX_EVT_FIFO_WRDS +
+ MCAN1_TX_DED_BUF_WRDS +
+ MCAN1_TX_FIFO_Q_WRDS];
+
+static const uint8_t dlcToMsgLength[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64 };
+
+const MCan_ConfigType mcan0Config = {
+ MCAN0,
+ MCAN_BTP_BRP(MCAN0_BRP) | MCAN_BTP_TSEG1(MCAN0_TSEG1) |
+ MCAN_BTP_TSEG2(MCAN0_TSEG2) | MCAN_BTP_SJW(MCAN0_SJW),
+ MCAN_FBTP_FBRP(MCAN0_FBRP) | MCAN_FBTP_FTSEG1(MCAN0_FTSEG1) |
+ MCAN_FBTP_FTSEG2(MCAN0_FTSEG2) | MCAN_FBTP_FSJW(MCAN0_FSJW),
+ MCAN0_NMBR_STD_FLTS,
+ MCAN0_NMBR_EXT_FLTS,
+ MCAN0_NMBR_RX_FIFO0_ELMTS,
+ MCAN0_NMBR_RX_FIFO1_ELMTS,
+ MCAN0_NMBR_RX_DED_BUF_ELMTS,
+ MCAN0_NMBR_TX_EVT_FIFO_ELMTS,
+ MCAN0_NMBR_TX_DED_BUF_ELMTS,
+ MCAN0_NMBR_TX_FIFO_Q_ELMTS,
+ (MCAN0_RX_FIFO0_DATA_SIZE << 29) | ((MCAN0_RX_FIFO0_ELMT_SZ / 4) + 2),
+ /* element size in WORDS */
+ (MCAN0_RX_FIFO1_DATA_SIZE << 29) | ((MCAN0_RX_FIFO1_ELMT_SZ / 4) + 2),
+ /* element size in WORDS */
+ (MCAN0_RX_BUF_DATA_SIZE << 29) | ((MCAN0_RX_BUF_ELMT_SZ / 4) + 2),
+ /* element size in WORDS */
+ (MCAN0_TX_BUF_DATA_SIZE << 29) | ((MCAN0_TX_BUF_ELMT_SZ / 4) + 2),
+ /* element size in WORDS */
+ {
+ &can0MsgRam[0],
+ &can0MsgRam[MCAN0_STD_FLTS_WRDS],
+ &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS],
+ &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS + MCAN0_RX_FIFO0_WRDS],
+ &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS + MCAN0_RX_FIFO0_WRDS +
+ MCAN0_RX_FIFO1_WRDS],
+ &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS + MCAN0_RX_FIFO0_WRDS +
+ MCAN0_RX_FIFO1_WRDS + MCAN0_RX_DED_BUFS_WRDS],
+ &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS + MCAN0_RX_FIFO0_WRDS +
+ MCAN0_RX_FIFO1_WRDS + MCAN0_RX_DED_BUFS_WRDS + MCAN0_TX_EVT_FIFO_WRDS],
+ &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS + MCAN0_RX_FIFO0_WRDS +
+ MCAN0_RX_FIFO1_WRDS + MCAN0_RX_DED_BUFS_WRDS + MCAN0_TX_EVT_FIFO_WRDS +
+ MCAN0_TX_DED_BUF_WRDS]
+ },
+};
+
+const MCan_ConfigType mcan1Config = {
+ MCAN1,
+ MCAN_BTP_BRP(MCAN1_BRP) | MCAN_BTP_TSEG1(MCAN1_TSEG1) |
+ MCAN_BTP_TSEG2(MCAN1_TSEG2) | MCAN_BTP_SJW(MCAN1_SJW),
+ MCAN_FBTP_FBRP(MCAN1_FBRP) | MCAN_FBTP_FTSEG1(MCAN1_FTSEG1) |
+ MCAN_FBTP_FTSEG2(MCAN1_FTSEG2) | MCAN_FBTP_FSJW(MCAN1_FSJW),
+ MCAN1_NMBR_STD_FLTS,
+ MCAN1_NMBR_EXT_FLTS,
+ MCAN1_NMBR_RX_FIFO0_ELMTS,
+ MCAN1_NMBR_RX_FIFO1_ELMTS,
+ MCAN0_NMBR_RX_DED_BUF_ELMTS,
+ MCAN1_NMBR_TX_EVT_FIFO_ELMTS,
+ MCAN1_NMBR_TX_DED_BUF_ELMTS,
+ MCAN1_NMBR_TX_FIFO_Q_ELMTS,
+ (MCAN1_RX_FIFO0_DATA_SIZE << 29) | ((MCAN1_RX_FIFO0_ELMT_SZ / 4) + 2),
+ /* element size in WORDS */
+ (MCAN1_RX_FIFO1_DATA_SIZE << 29) | ((MCAN1_RX_FIFO1_ELMT_SZ / 4) + 2),
+ /* element size in WORDS */
+ (MCAN1_RX_BUF_DATA_SIZE << 29) | ((MCAN1_RX_BUF_ELMT_SZ / 4) + 2),
+ /* element size in WORDS */
+ (MCAN1_TX_BUF_DATA_SIZE << 29) | ((MCAN1_TX_BUF_ELMT_SZ / 4) + 2),
+ /* element size in WORDS */
+ {
+ &can1MsgRam[0],
+ &can1MsgRam[MCAN1_STD_FLTS_WRDS],
+ &can1MsgRam[MCAN1_STD_FLTS_WRDS + MCAN1_EXT_FLTS_WRDS],
+ &can1MsgRam[MCAN1_STD_FLTS_WRDS + MCAN1_EXT_FLTS_WRDS + MCAN1_RX_FIFO0_WRDS],
+ &can1MsgRam[MCAN1_STD_FLTS_WRDS + MCAN1_EXT_FLTS_WRDS + MCAN1_RX_FIFO0_WRDS
+ + MCAN1_RX_FIFO1_WRDS],
+ &can1MsgRam[MCAN1_STD_FLTS_WRDS + MCAN1_EXT_FLTS_WRDS + MCAN1_RX_FIFO0_WRDS
+ + MCAN1_RX_FIFO1_WRDS + MCAN1_RX_DED_BUFS_WRDS],
+ &can1MsgRam[MCAN1_STD_FLTS_WRDS + MCAN1_EXT_FLTS_WRDS + MCAN1_RX_FIFO0_WRDS
+ + MCAN1_RX_FIFO1_WRDS + MCAN1_RX_DED_BUFS_WRDS + MCAN1_TX_EVT_FIFO_WRDS],
+ &can1MsgRam[MCAN1_STD_FLTS_WRDS + MCAN1_EXT_FLTS_WRDS + MCAN1_RX_FIFO0_WRDS
+ + MCAN1_RX_FIFO1_WRDS + MCAN1_RX_DED_BUFS_WRDS + MCAN1_TX_EVT_FIFO_WRDS
+ + MCAN1_TX_DED_BUF_WRDS]
+ },
+};
+
+
+/*---------------------------------------------------------------------------
+ * Exported Functions
+ *---------------------------------------------------------------------------*/
+/**
+* \brief Initializes the MCAN hardware for giving peripheral.
+* Default: Mixed mode TX Buffer + FIFO.
+*
+* \param mcanConfig Pointer to a MCAN instance.
+*/
+void MCAN_Init(const MCan_ConfigType *mcanConfig)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ uint32_t regVal32;
+ uint32_t *pMsgRam;
+ uint32_t cntr;
+ IRQn_Type mCanLine0Irq;
+
+ /* Both MCAN controllers use programmable clock 5 to derive bit rate */
+ // select MCK divided by 1 as programmable clock 5 output
+ PMC->PMC_PCK[5] = PMC_PCK_PRES(MCAN_PROG_CLK_PRESCALER - 1) |
+ MCAN_PROG_CLK_SELECT;
+ PMC->PMC_SCER = PMC_SCER_PCK5;
+
+ if (MCAN0 == mcan) {
+#ifndef __rtems__
+ PIO_Configure(pinsMcan0, PIO_LISTSIZE(pinsMcan0));
+#endif /* __rtems__ */
+ // Enable MCAN peripheral clock
+ PMC_EnablePeripheral(ID_MCAN0);
+ // Configure Message RAM Base Address
+ regVal32 = MATRIX->CCFG_CAN0 & 0x000001FF;
+ MATRIX->CCFG_CAN0 = regVal32 |
+ ((uint32_t) mcanConfig->msgRam.pStdFilts & 0xFFFF0000);
+ mCanLine0Irq = MCAN0_IRQn;
+ } else if (MCAN1 == mcan) {
+#ifndef __rtems__
+ PIO_Configure(pinsMcan1, PIO_LISTSIZE(pinsMcan1));
+#endif /* __rtems__ */
+ // Enable MCAN peripheral clock
+ PMC_EnablePeripheral(ID_MCAN1);
+ // Configure Message RAM Base Address
+ regVal32 = MATRIX->CCFG_SYSIO & 0x0000FFFF;
+ MATRIX->CCFG_SYSIO = regVal32 | ((uint32_t) mcanConfig->msgRam.pStdFilts &
+ 0xFFFF0000);
+ mCanLine0Irq = MCAN1_IRQn;
+ } else
+ return;
+
+ /* Indicates Initialization state */
+ mcan->MCAN_CCCR = MCAN_CCCR_INIT_ENABLED;
+
+ do { regVal32 = mcan->MCAN_CCCR; }
+ while (0u == (regVal32 & MCAN_CCCR_INIT_ENABLED));
+
+ /* Enable writing to configuration registers */
+ mcan->MCAN_CCCR = MCAN_CCCR_INIT_ENABLED | MCAN_CCCR_CCE_CONFIGURABLE;
+
+ /* Global Filter Configuration: Reject remote frames, reject non-matching frames */
+ mcan->MCAN_GFC = MCAN_GFC_RRFE_REJECT | MCAN_GFC_RRFS_REJECT
+ | MCAN_GFC_ANFE(2) | MCAN_GFC_ANFS(2);
+
+ // Extended ID Filter AND mask
+ mcan->MCAN_XIDAM = 0x1FFFFFFF;
+
+ /* Interrupt configuration - leave initialization with all interrupts off */
+ // Disable all interrupts
+ mcan->MCAN_IE = 0;
+ mcan->MCAN_TXBTIE = 0x00000000;
+ // All interrupts directed to Line 0
+ mcan->MCAN_ILS = 0x00000000;
+ // Disable both interrupt LINE 0 & LINE 1
+ mcan->MCAN_ILE = 0x00;
+ // Clear all interrupt flags
+ mcan->MCAN_IR = 0xFFCFFFFF;
+ /* Enable NVIC - but no interrupts will happen since all sources are
+ disabled in MCAN_IE */
+ NVIC_ClearPendingIRQ(mCanLine0Irq);
+ NVIC_EnableIRQ(mCanLine0Irq);
+ NVIC_ClearPendingIRQ((IRQn_Type) (mCanLine0Irq + 1));
+ NVIC_EnableIRQ((IRQn_Type) (mCanLine0Irq + 1));
+
+ /* Configure CAN bit timing */
+ mcan->MCAN_BTP = mcanConfig->bitTiming;
+ mcan->MCAN_FBTP = mcanConfig->fastBitTiming;
+
+ /* Configure message RAM starting addresses & sizes */
+ mcan->MCAN_SIDFC = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pStdFilts)
+ | MCAN_SIDFC_LSS(mcanConfig->nmbrStdFilts);
+ mcan->MCAN_XIDFC = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pExtFilts)
+ | MCAN_XIDFC_LSE(mcanConfig->nmbrExtFilts);
+ mcan->MCAN_RXF0C = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pRxFifo0)
+ | MCAN_RXF0C_F0S(mcanConfig->nmbrFifo0Elmts);
+ // watermark interrupt off, blocking mode
+ mcan->MCAN_RXF1C = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pRxFifo1)
+ | MCAN_RXF1C_F1S(mcanConfig->nmbrFifo1Elmts);
+ // watermark interrupt off, blocking mode
+ mcan->MCAN_RXBC = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pRxDedBuf);
+ mcan->MCAN_TXEFC = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pTxEvtFifo)
+ | MCAN_TXEFC_EFS(mcanConfig->nmbrTxEvtFifoElmts);
+ // watermark interrupt off
+ mcan->MCAN_TXBC = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pTxDedBuf)
+ | MCAN_TXBC_NDTB(mcanConfig->nmbrTxDedBufElmts)
+ | MCAN_TXBC_TFQS(mcanConfig->nmbrTxFifoQElmts);
+ mcan->MCAN_RXESC = ((mcanConfig->rxBufElmtSize >> (29 - MCAN_RXESC_RBDS_Pos)) &
+ MCAN_RXESC_RBDS_Msk) |
+ ((mcanConfig->rxFifo1ElmtSize >> (29 - MCAN_RXESC_F1DS_Pos)) &
+ MCAN_RXESC_F1DS_Msk) |
+ ((mcanConfig->rxFifo0ElmtSize >> (29 - MCAN_RXESC_F0DS_Pos)) &
+ MCAN_RXESC_F0DS_Msk);
+ mcan->MCAN_TXESC = ((mcanConfig->txBufElmtSize >> (29 - MCAN_TXESC_TBDS_Pos)) &
+ MCAN_TXESC_TBDS_Msk);
+
+ /* Configure Message Filters */
+ // ...Disable all standard filters
+ pMsgRam = mcanConfig->msgRam.pStdFilts;
+ cntr = mcanConfig->nmbrStdFilts;
+
+ while (cntr > 0) {
+ *pMsgRam++ = STD_FILT_SFEC_DISABLE;
+ cntr--;
+ }
+
+ // ...Disable all extended filters
+ pMsgRam = mcanConfig->msgRam.pExtFilts;
+ cntr = mcanConfig->nmbrExtFilts;
+
+ while (cntr > 0) {
+ *pMsgRam = EXT_FILT_EFEC_DISABLE;
+ pMsgRam = pMsgRam + 2;
+ cntr--;
+ }
+
+ mcan->MCAN_NDAT1 = 0xFFFFFFFF; // clear new (rx) data flags
+ mcan->MCAN_NDAT2 = 0xFFFFFFFF; // clear new (rx) data flags
+
+ regVal32 = mcan->MCAN_CCCR & ~(MCAN_CCCR_CME_Msk | MCAN_CCCR_CMR_Msk);
+ mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CME_ISO11898_1;
+ mcan->MCAN_CCCR = regVal32 | (MCAN_CCCR_CMR_ISO11898_1 |
+ MCAN_CCCR_CME_ISO11898_1);
+
+ __DSB();
+ __ISB();
+}
+
+/**
+ * \brief Enables a FUTURE switch to FD mode (tx & rx payloads up to 64 bytes)
+ * but transmits WITHOUT bit rate switching
+ * INIT must be set - so this should be called between MCAN_Init() and
+ * MCAN_Enable()
+ * \param mcanConfig Pointer to a MCAN instance.
+ */
+void MCAN_InitFdEnable(const MCan_ConfigType *mcanConfig)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ uint32_t regVal32;
+
+ regVal32 = mcan->MCAN_CCCR & ~MCAN_CCCR_CME_Msk;
+ mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CME(1);
+}
+
+/**
+ * \brief Enables a FUTURE switch to FD mode (tx & rx payloads up to 64 bytes) and transmits
+ * WITH bit rate switching
+ * INIT must be set - so this should be called between MCAN_Init() and MCAN_Enable()
+ * \param mcanConfig Pointer to a MCAN instance.
+ */
+void MCAN_InitFdBitRateSwitchEnable(const MCan_ConfigType *mcanConfig)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ uint32_t regVal32;
+
+ regVal32 = mcan->MCAN_CCCR & ~MCAN_CCCR_CME_Msk;
+ mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CME(2);
+}
+
+/**
+ * \brief Initializes the MCAN in loop back mode.
+ * INIT must be set - so this should be called between MCAN_Init() and
+ * MCAN_Enable()
+ * \param mcanConfig Pointer to a MCAN instance.
+ */
+void MCAN_InitLoopback(const MCan_ConfigType *mcanConfig)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+
+ mcan->MCAN_CCCR |= MCAN_CCCR_TEST_ENABLED;
+ //mcan->MCAN_CCCR |= MCAN_CCCR_MON_ENABLED; // for internal loop back
+ mcan->MCAN_TEST |= MCAN_TEST_LBCK_ENABLED;
+}
+
+/**
+ * \brief Initializes MCAN queue for TX
+ * INIT must be set - so this should be called between MCAN_Init() and
+ * MCAN_Enable()
+ * \param mcanConfig Pointer to a MCAN instance.
+ */
+void MCAN_InitTxQueue(const MCan_ConfigType *mcanConfig)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ mcan->MCAN_TXBC |= MCAN_TXBC_TFQM;
+}
+
+/**
+ * \brief Enable MCAN peripheral.
+ * INIT must be set - so this should be called between MCAN_Init()
+ * \param mcanConfig Pointer to a MCAN instance.
+ */
+void MCAN_Enable(const MCan_ConfigType *mcanConfig)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ mcan->MCAN_CCCR &= ~MCAN_CCCR_INIT_ENABLED;
+}
+
+/**
+ * \brief Requests switch to Iso11898-1 (standard / classic) mode (tx & rx
+ * payloads up to 8 bytes).
+ * \param mcanConfig Pointer to a MCAN instance.
+ */
+void MCAN_RequestIso11898_1(const MCan_ConfigType *mcanConfig)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ uint32_t regVal32;
+
+ regVal32 = mcan->MCAN_CCCR & ~MCAN_CCCR_CMR_Msk;
+ mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CMR_ISO11898_1;
+
+ while ((mcan->MCAN_CCCR & (MCAN_CCCR_FDBS | MCAN_CCCR_FDO)) != 0)
+ { /* wait */ }
+}
+
+/**
+ * \brief Requests switch to FD mode (tx & rx payloads up to 64 bytes) but
+ * transmits WITHOUT bit
+ * rate switching. requested mode should have been enabled at initialization
+ * \param mcanConfig Pointer to a MCAN instance.
+ */
+void MCAN_RequestFd(const MCan_ConfigType *mcanConfig)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ uint32_t regVal32;
+
+ if ((mcan->MCAN_CCCR & MCAN_CCCR_CME_Msk) == MCAN_CCCR_CME(1)) {
+ regVal32 = mcan->MCAN_CCCR & ~MCAN_CCCR_CMR_Msk;
+ mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CMR_FD;
+
+ while ((mcan->MCAN_CCCR & MCAN_CCCR_FDO) == 0) { /* wait */ }
+ }
+}
+
+/**
+ * \brief Request switch to FD mode (tx & rx payloads up to 64 bytes) and
+ * transmits WITH bit rate switching.
+ * requested mode should have been enabled at initialization
+ * \param mcanConfig Pointer to a MCAN instance.
+ */
+void MCAN_RequestFdBitRateSwitch(const MCan_ConfigType *mcanConfig)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ uint32_t regVal32;
+
+ if ((mcan->MCAN_CCCR & MCAN_CCCR_CME_Msk) == MCAN_CCCR_CME(2)) {
+ regVal32 = mcan->MCAN_CCCR & ~MCAN_CCCR_CMR_Msk;
+ mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CMR_FD_BITRATE_SWITCH;
+
+ while ((mcan->MCAN_CCCR & (MCAN_CCCR_FDBS | MCAN_CCCR_FDO)) !=
+ (MCAN_CCCR_FDBS | MCAN_CCCR_FDO)) { /* wait */ }
+ }
+}
+
+/**
+ * \brief Switch on loop back mode.
+ * TEST must be set in MCAN_CCCR - e.g. by a prior call to MCAN_InitLoopback()
+ * \param mcanConfig Pointer to a MCAN instance.
+ */
+void MCAN_LoopbackOn(const MCan_ConfigType *mcanConfig)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ mcan->MCAN_TEST |= MCAN_TEST_LBCK_ENABLED;
+}
+
+/**
+ * \brief Switch off loop back mode.
+ * \param mcanConfig Pointer to a MCAN instance.
+ */
+void MCAN_LoopbackOff(const MCan_ConfigType *mcanConfig)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ mcan->MCAN_TEST &= ~MCAN_TEST_LBCK_ENABLED;
+}
+
+/**
+ * \brief Enable message line and message stored to Dedicated Receive Buffer
+ * Interrupt Line.
+ * \param mcanConfig Pointer to a MCAN instance.
+ * \param line Message line.
+ */
+void MCAN_IEnableMessageStoredToRxDedBuffer(const MCan_ConfigType *mcanConfig,
+ MCan_IntrLineType line)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+
+ if (line == CAN_INTR_LINE_0) {
+ mcan->MCAN_ILS &= ~MCAN_ILS_DRXL;
+ mcan->MCAN_ILE |= MCAN_ILE_EINT0;
+ } else {
+ // Interrupt Line 1
+ mcan->MCAN_ILS |= MCAN_ILS_DRXL;
+ mcan->MCAN_ILE |= MCAN_ILE_EINT1;
+ }
+
+ mcan->MCAN_IR = MCAN_IR_DRX; // clear previous flag
+ mcan->MCAN_IE |= MCAN_IE_DRXE; // enable it
+}
+
+/**
+ * \brief Configures a Dedicated TX Buffer.
+ * \param mcanConfig Pointer to a MCAN instance.
+ * \param buffer Pointer to buffer.
+ * \param id Message ID.
+ * \param idType Type of ID
+ * \param dlc Type of dlc.
+ */
+uint8_t *MCAN_ConfigTxDedBuffer(const MCan_ConfigType *mcanConfig,
+ uint8_t buffer, uint32_t id, MCan_IdType idType, MCan_DlcType dlc)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ uint32_t *pThisTxBuf = 0;
+
+ if (buffer < mcanConfig->nmbrTxDedBufElmts) {
+ pThisTxBuf = mcanConfig->msgRam.pTxDedBuf + (buffer *
+ (mcanConfig->txBufElmtSize & ELMT_SIZE_MASK));
+
+ if (idType == CAN_STD_ID)
+ *pThisTxBuf++ = ((id << 18) & (CAN_11_BIT_ID_MASK << 18));
+ else
+ *pThisTxBuf++ = BUFFER_XTD_MASK | (id & CAN_29_BIT_ID_MASK);
+
+ *pThisTxBuf++ = (uint32_t) dlc << 16;
+ /* enable transmit from buffer to set TC interrupt bit in IR, but
+ interrupt will not happen unless TC interrupt is enabled*/
+ mcan->MCAN_TXBTIE = (1 << buffer);
+ }
+
+ return (uint8_t *) pThisTxBuf; // now it points to the data field
+}
+
+/**
+ * \brief Send Tx buffer.
+ * \param mcanConfig Pointer to a MCAN instance.
+ * \param buffer Pointer to buffer.
+ */
+void MCAN_SendTxDedBuffer(const MCan_ConfigType *mcanConfig, uint8_t buffer)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+
+ if (buffer < mcanConfig->nmbrTxDedBufElmts)
+ mcan->MCAN_TXBAR = (1 << buffer);
+}
+
+/**
+ * \brief Adds Message to TX Fifo / Queue
+ * \param mcanConfig Pointer to a MCAN instance.
+ * \param id Message ID.
+ * \param idType Type of ID
+ * \param dlc Type of dlc.
+ * \param data Pointer to data.
+ */
+uint32_t MCAN_AddToTxFifoQ(const MCan_ConfigType *mcanConfig,
+ uint32_t id, MCan_IdType idType, MCan_DlcType dlc, uint8_t *data)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ uint32_t putIdx = 255;
+ uint32_t *pThisTxBuf = 0;
+ uint8_t *pTxData;
+ uint8_t msgLength;
+ uint8_t cnt;
+
+ // Configured for FifoQ and FifoQ not full?
+ if ((mcanConfig->nmbrTxFifoQElmts > 0) &&
+ ((mcan->MCAN_TXFQS & MCAN_TXFQS_TFQF) == 0)) {
+ putIdx = (mcan->MCAN_TXFQS & MCAN_TXFQS_TFQPI_Msk) >> MCAN_TXFQS_TFQPI_Pos;
+ pThisTxBuf = mcanConfig->msgRam.pTxDedBuf + (putIdx *
+ (mcanConfig->txBufElmtSize & ELMT_SIZE_MASK));
+
+ if (idType == CAN_STD_ID)
+ *pThisTxBuf++ = ((id << 18) & (CAN_11_BIT_ID_MASK << 18));
+ else
+ *pThisTxBuf++ = BUFFER_XTD_MASK | (id & CAN_29_BIT_ID_MASK);
+
+ *pThisTxBuf++ = (uint32_t) dlc << 16;
+ pTxData = (uint8_t *) pThisTxBuf;
+ msgLength = dlcToMsgLength[dlc];
+
+ for (cnt = 0; cnt < msgLength; cnt++)
+ *pTxData++ = *data++;
+
+ /* enable transmit from buffer to set TC interrupt bit in IR, but
+ interrupt will not happen unless TC interrupt is enabled */
+ mcan->MCAN_TXBTIE = (1 << putIdx);
+ // request to send
+ mcan->MCAN_TXBAR = (1 << putIdx);
+ }
+
+ return putIdx; // now it points to the data field
+}
+
+/**
+ * \brief Check if data transmitted from buffer/fifo/queue
+ * \param mcanConfig Pointer to a MCAN instance.
+ * \param buffer Pointer to data buffer.
+ */
+uint8_t MCAN_IsBufferTxd(const MCan_ConfigType *mcanConfig, uint8_t buffer)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+
+ return (mcan->MCAN_TXBTO & (1 << buffer));
+}
+
+/**
+ * \brief Configure RX Buffer Filter
+ * ID must match exactly for a RX Buffer Filter
+ * \param mcanConfig Pointer to a MCAN instance.
+ * \param buffer Pointer to data buffer.
+ * \param filter data of filter.
+ * \param idType Type of ID
+ */
+void MCAN_ConfigRxBufferFilter(const MCan_ConfigType *mcanConfig,
+ uint32_t buffer, uint32_t filter, uint32_t id, MCan_IdType idType)
+{
+ uint32_t *pThisRxFilt = 0;
+
+ if (buffer < mcanConfig->nmbrRxDedBufElmts) {
+ if (idType == CAN_STD_ID) {
+ if ((filter < mcanConfig->nmbrStdFilts)
+ && (id <= CAN_11_BIT_ID_MASK)) {
+ pThisRxFilt = mcanConfig->msgRam.pStdFilts + filter;
+ // 1 word per filter
+ *pThisRxFilt = STD_FILT_SFEC_BUFFER | (id << 16) |
+ STD_FILT_SFID2_RX_BUFFER | buffer;
+ }
+ } else {
+ // extended ID
+ if ((filter < mcanConfig->nmbrExtFilts) &&
+ (id <= CAN_29_BIT_ID_MASK)) {
+ pThisRxFilt = mcanConfig->msgRam.pExtFilts + (2 * filter);
+ // 2 words per filter
+ *pThisRxFilt++ = (uint32_t) EXT_FILT_EFEC_BUFFER | id;
+ *pThisRxFilt = EXT_FILT_EFID2_RX_BUFFER | buffer;
+ }
+ }
+ }
+}
+
+/**
+ * \brief Configure Classic Filter
+ * Classic Filters direct accepted messages to a FIFO & include both a ID and
+ * a ID mask
+ * \param mcanConfig Pointer to a MCAN instance.
+ * \param buffer Pointer to data buffer.
+ * \param fifo fifo Number.
+ * \param filter data of filter.
+ * \param idType Type of ID
+ * \param mask Mask to be match
+ */
+void MCAN_ConfigRxClassicFilter(const MCan_ConfigType *mcanConfig,
+ MCan_FifoType fifo, uint8_t filter, uint32_t id,
+ MCan_IdType idType, uint32_t mask)
+{
+ uint32_t *pThisRxFilt = 0;
+ uint32_t filterTemp;
+
+ if (idType == CAN_STD_ID) {
+ if ((filter < mcanConfig->nmbrStdFilts) && (id <= CAN_11_BIT_ID_MASK)
+ && (mask <= CAN_11_BIT_ID_MASK)) {
+ pThisRxFilt = mcanConfig->msgRam.pStdFilts + filter;
+ // 1 word per filter
+ filterTemp = (uint32_t) STD_FILT_SFT_CLASSIC | (id << 16) | mask;
+
+ if (fifo == CAN_FIFO_0)
+ *pThisRxFilt = STD_FILT_SFEC_FIFO0 | filterTemp;
+ else if (fifo == CAN_FIFO_1)
+ *pThisRxFilt = STD_FILT_SFEC_FIFO1 | filterTemp;
+ }
+ } else {
+ // extended ID
+ if ((filter < mcanConfig->nmbrExtFilts)
+ && (id <= CAN_29_BIT_ID_MASK)
+ && (mask <= CAN_29_BIT_ID_MASK)) {
+ pThisRxFilt = mcanConfig->msgRam.pExtFilts + (2 * filter);
+
+ // 2 words per filter
+ if (fifo == CAN_FIFO_0)
+ *pThisRxFilt++ = EXT_FILT_EFEC_FIFO0 | id;
+ else if (fifo == CAN_FIFO_1)
+ *pThisRxFilt++ = EXT_FILT_EFEC_FIFO1 | id;
+
+ *pThisRxFilt = (uint32_t) EXT_FILT_EFT_CLASSIC | mask;
+ }
+ }
+}
+
+/**
+ * \brief check if data received into buffer
+ * \param mcanConfig Pointer to a MCAN instance.
+ * \param buffer Pointer to data buffer.
+ */
+uint8_t MCAN_IsNewDataInRxDedBuffer(const MCan_ConfigType *mcanConfig,
+ uint8_t buffer)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+
+ if (buffer < 32)
+ return (mcan->MCAN_NDAT1 & (1 << buffer));
+ else if (buffer < 64)
+ return (mcan->MCAN_NDAT1 & (1 << (buffer - 32)));
+ else
+ return 0;
+}
+
+/**
+ * \brief Get Rx buffer
+ * \param mcanConfig Pointer to a MCAN instance.
+ * \param buffer Pointer to data buffer.
+ * \param pRxMailbox Pointer to rx Mailbox.
+ */
+void MCAN_GetRxDedBuffer(const MCan_ConfigType *mcanConfig,
+ uint8_t buffer, Mailbox64Type *pRxMailbox)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ uint32_t *pThisRxBuf = 0;
+ uint32_t tempRy; // temp copy of RX buffer word
+ uint32_t dlc;
+ uint8_t *pRxData;
+ uint8_t idx;
+
+ if (buffer < mcanConfig->nmbrRxDedBufElmts) {
+ pThisRxBuf = mcanConfig->msgRam.pRxDedBuf
+ + (buffer * (mcanConfig->rxBufElmtSize & ELMT_SIZE_MASK));
+ tempRy = *pThisRxBuf++; // word R0 contains ID
+
+ if (tempRy & BUFFER_XTD_MASK) {
+ // extended ID?
+ pRxMailbox->info.id = tempRy & BUFFER_EXT_ID_MASK;
+ } else {
+ // standard ID
+ pRxMailbox->info.id = (tempRy & BUFFER_STD_ID_MASK) >> 18;
+ }
+
+ tempRy = *pThisRxBuf++; // word R1 contains DLC & time stamp
+ dlc = (tempRy & BUFFER_DLC_MASK) >> 16;
+ pRxMailbox->info.length = dlcToMsgLength[dlc];
+ pRxMailbox->info.timestamp = tempRy & BUFFER_RXTS_MASK;
+ // copy the data from the buffer to the mailbox
+ pRxData = (uint8_t *) pThisRxBuf;
+
+ SCB_CleanDCache_by_Addr((uint32_t *)pRxData, pRxMailbox->info.length);
+ SCB_CleanDCache_by_Addr((uint32_t *) & (pRxMailbox->data[0]),
+ pRxMailbox->info.length);
+
+ for (idx = 0; idx < pRxMailbox->info.length; idx++)
+ pRxMailbox->data[idx] = *pRxData++;
+
+ /* clear the new data flag for the buffer */
+
+ if (buffer < 32)
+ mcan->MCAN_NDAT1 = (1 << buffer);
+ else
+ mcan->MCAN_NDAT1 = (1 << (buffer - 32));
+
+ }
+}
+
+/**
+ * \brief Get from the receive FIFO and place in a application mailbox
+ * \param mcanConfig Pointer to a MCAN instance.
+ * \param fifo Fifo Number
+ * \param pRxMailbox Pointer to rx Mailbox.
+ * \return: # of fifo entries at the start of the function
+ * 0 -> FIFO was empty at start
+ * 1 -> FIFO had 1 entry at start, but is empty at finish
+ * 2 -> FIFO had 2 entries at start, has 1 entry at finish
+ */
+uint32_t MCAN_GetRxFifoBuffer(const MCan_ConfigType *mcanConfig,
+ MCan_FifoType fifo, Mailbox64Type *pRxMailbox)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ uint32_t *pThisRxBuf = 0;
+ uint32_t tempRy; // temp copy of RX buffer word
+ uint32_t dlc;
+ uint8_t *pRxData;
+ uint8_t idx;
+ uint32_t *fifo_ack_reg;
+ uint32_t get_index;
+ uint32_t fill_level;
+ uint32_t element_size;
+
+ // default: fifo empty
+ fill_level = 0;
+
+ if (fifo == CAN_FIFO_0) {
+ get_index = (mcan->MCAN_RXF0S & MCAN_RXF0S_F0GI_Msk) >> MCAN_RXF0S_F0GI_Pos;
+ fill_level = (mcan->MCAN_RXF0S & MCAN_RXF0S_F0FL_Msk) >> MCAN_RXF0S_F0FL_Pos;
+ pThisRxBuf = mcanConfig->msgRam.pRxFifo0;
+ element_size = mcanConfig->rxFifo0ElmtSize & ELMT_SIZE_MASK;
+ fifo_ack_reg = (uint32_t *) &mcan->MCAN_RXF0A;
+ } else if (fifo == CAN_FIFO_1) {
+ get_index = (mcan->MCAN_RXF1S & MCAN_RXF1S_F1GI_Msk) >> MCAN_RXF1S_F1GI_Pos;
+ fill_level = (mcan->MCAN_RXF1S & MCAN_RXF1S_F1FL_Msk) >> MCAN_RXF1S_F1FL_Pos;
+ pThisRxBuf = mcanConfig->msgRam.pRxFifo1;
+ element_size = mcanConfig->rxFifo1ElmtSize & ELMT_SIZE_MASK;
+ fifo_ack_reg = (uint32_t *) &mcan->MCAN_RXF1A;
+ }
+
+ if (fill_level > 0) {
+ pThisRxBuf = pThisRxBuf + (get_index * element_size);
+ tempRy = *pThisRxBuf++; // word R0 contains ID
+
+ if (tempRy & BUFFER_XTD_MASK) {
+ // extended ID?
+ pRxMailbox->info.id = tempRy & BUFFER_EXT_ID_MASK;
+ } else {
+ // standard ID
+ pRxMailbox->info.id = (tempRy & BUFFER_STD_ID_MASK) >> 18;
+ }
+
+ tempRy = *pThisRxBuf++; // word R1 contains DLC & timestamps
+ dlc = (tempRy & BUFFER_DLC_MASK) >> 16;
+ pRxMailbox->info.length = dlcToMsgLength[dlc];
+ pRxMailbox->info.timestamp = tempRy & BUFFER_RXTS_MASK;
+ /* copy the data from the buffer to the mailbox */
+ pRxData = (uint8_t *) pThisRxBuf;
+
+ for (idx = 0; idx < pRxMailbox->info.length; idx++)
+ pRxMailbox->data[idx] = *pRxData++;
+
+ // acknowledge reading the fifo entry
+ *fifo_ack_reg = get_index;
+ /* return entries remaining in FIFO */
+ }
+
+ return (fill_level);
+}
+
+/**@}*/
+