Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Duet3D/RepRapFirmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Crocker <dcrocker@eschertech.com>2020-08-21 18:12:36 +0300
committerDavid Crocker <dcrocker@eschertech.com>2020-08-21 18:12:36 +0300
commit5e120aea3f73520c38697ff72feb7bf5225b8bd5 (patch)
tree6268537c4ddad87d4d0ce1abb4bb27e5785b06af /src/Hardware/SAME70
parent3532dadb4ed57373ce8c0550d543c58381a60cea (diff)
Started adding CAN support to Duet 3 Mini build
Diffstat (limited to 'src/Hardware/SAME70')
-rw-r--r--src/Hardware/SAME70/CanDriver.cpp689
-rw-r--r--src/Hardware/SAME70/CanDriver.h1138
2 files changed, 1827 insertions, 0 deletions
diff --git a/src/Hardware/SAME70/CanDriver.cpp b/src/Hardware/SAME70/CanDriver.cpp
new file mode 100644
index 00000000..32daeff2
--- /dev/null
+++ b/src/Hardware/SAME70/CanDriver.cpp
@@ -0,0 +1,689 @@
+/**
+ * \file
+ *
+ * \brief SAM Control Area Network (MCAN) Low Level Driver
+ *
+ * Copyright (c) 2015-2019 Microchip Technology Inc. and its subsidiaries.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Subject to your compliance with these terms, you may use Microchip
+ * software and any derivatives exclusively with Microchip products.
+ * It is your responsibility to comply with third party license terms applicable
+ * to your use of third party software (including open source software) that
+ * may accompany Microchip software.
+ *
+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
+ *
+ * \asf_license_stop
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
+ */
+
+#include "CanDriver.h"
+
+#if SUPPORT_CAN_EXPANSION
+
+#include <sam/drivers/pmc/pmc.h>
+#include <cstring>
+
+// Values from conf_mcan.h
+
+/*
+ * Below is the message RAM setting, it will be stored in the system RAM.
+ * Please adjust the message size according to your application.
+ */
+/** Range: 1..64 */
+#define CONF_MCAN0_RX_FIFO_0_NUM 16
+/** Range: 1..64 */
+#define CONF_MCAN0_RX_FIFO_1_NUM 16
+/** Range: 1..64 */
+#define CONF_MCAN0_RX_BUFFER_NUM 4
+/** Range: 1..16 */
+#define CONF_MCAN0_TX_BUFFER_NUM 6
+/** Range: 1..16 */
+#define CONF_MCAN0_TX_FIFO_QUEUE_NUM 8
+/** Range: 1..32 */
+#define CONF_MCAN0_TX_EVENT_FIFO 8
+/** Range: 1..128 */
+#define CONF_MCAN0_RX_STANDARD_ID_FILTER_NUM 1
+/** Range: 1..64 */
+#define CONF_MCAN0_RX_EXTENDED_ID_FILTER_NUM 3
+/** Range: 1..64 */
+#define CONF_MCAN1_RX_FIFO_0_NUM 16
+/** Range: 1..64 */
+#define CONF_MCAN1_RX_FIFO_1_NUM 16
+/** Range: 1..64 */
+#define CONF_MCAN1_RX_BUFFER_NUM 4
+/** Range: 1..16 */
+#define CONF_MCAN1_TX_BUFFER_NUM 6
+/** Range: 1..16 */
+#define CONF_MCAN1_TX_FIFO_QUEUE_NUM 8
+/** Range: 1..32 */
+#define CONF_MCAN1_TX_EVENT_FIFO 8
+/** Range: 1..128 */
+#define CONF_MCAN1_RX_STANDARD_ID_FILTER_NUM 1
+/** Range: 1..64 */
+#define CONF_MCAN1_RX_EXTENDED_ID_FILTER_NUM 3
+
+/**
+ * The setting of the nominal bit rate is based on the PCK5 which is 48M which you can
+ * change in the conf_clock.h. Below is the default configuration. The
+ * time quanta is 48MHz. And each bit is (1 + NTSEG1 + 1 + NTSEG2 + 1) = 48 time
+ * quanta which means the bit rate is 48MHz/49 = 1Mbps.
+ */
+/** Nominal bit Baud Rate Prescaler */
+#define CONF_MCAN_NBTP_NBRP_VALUE (1 - 1)
+/** Nominal bit (Re)Synchronization Jump Width */
+#define CONF_MCAN_NBTP_NSJW_VALUE (8 - 1)
+/** Nominal bit Time segment before sample point */
+#define CONF_MCAN_NBTP_NTSEG1_VALUE (26 - 1)
+/** Nominal bit Time segment after sample point */
+#define CONF_MCAN_NBTP_NTSEG2_VALUE (21 - 1)
+
+/*
+ * The setting of the data bit rate is based on the PCK5 which is 48M which you can
+ * change. Below is the default configuration. The
+ * time quanta is 48MHz / (0+1) = 48MHz. And each bit is (1 + FTSEG1 + 1 + FTSEG2 + 1) = 12 time
+ * quanta which means the bit rate is 48MHz/12=4MHz.
+ */
+/** Data bit Baud Rate Prescaler */
+#define CONF_MCAN_FBTP_FBRP_VALUE (1 - 1)
+/** Data bit (Re)Synchronization Jump Width */
+#define CONF_MCAN_FBTP_FSJW_VALUE (3 - 1)
+/** Data bit Time segment before sample point */
+#define CONF_MCAN_FBTP_FTSEG1_VALUE (8 - 1)
+/** Data bit Time segment after sample point */
+#define CONF_MCAN_FBTP_FTSEG2_VALUE (3 - 1)
+
+
+/* PCK5 ID assigned to MCAN module */
+#define PMC_PCK_5 5
+/* Get a value of 2 to 15 bit. */
+#define BIT_2_TO_15_MASK 0x0000fffc
+
+#define __nocache __attribute__((section(".ram_nocache")))
+
+/* Message ram definition. */
+alignas(4) __nocache static struct mcan_rx_element mcan0_rx_buffer[CONF_MCAN0_RX_BUFFER_NUM];
+alignas(4) __nocache static struct mcan_rx_element mcan0_rx_fifo_0[CONF_MCAN0_RX_FIFO_0_NUM];
+alignas(4) __nocache static struct mcan_rx_element mcan0_rx_fifo_1[CONF_MCAN0_RX_FIFO_1_NUM];
+alignas(4) __nocache static struct mcan_tx_element mcan0_tx_buffer[CONF_MCAN0_TX_BUFFER_NUM + CONF_MCAN0_TX_FIFO_QUEUE_NUM];
+alignas(4) __nocache static struct mcan_tx_event_element mcan0_tx_event_fifo[CONF_MCAN0_TX_EVENT_FIFO];
+alignas(4) __nocache static struct mcan_standard_message_filter_element mcan0_rx_standard_filter[CONF_MCAN0_RX_STANDARD_ID_FILTER_NUM];
+alignas(4) __nocache static struct mcan_extended_message_filter_element mcan0_rx_extended_filter[CONF_MCAN0_RX_EXTENDED_ID_FILTER_NUM];
+
+alignas(4) __nocache static struct mcan_rx_element mcan1_rx_buffer[CONF_MCAN1_RX_BUFFER_NUM];
+alignas(4) __nocache static struct mcan_rx_element mcan1_rx_fifo_0[CONF_MCAN1_RX_FIFO_0_NUM];
+alignas(4) __nocache static struct mcan_rx_element mcan1_rx_fifo_1[CONF_MCAN1_RX_FIFO_1_NUM];
+alignas(4) __nocache static struct mcan_tx_element mcan1_tx_buffer[CONF_MCAN1_TX_BUFFER_NUM + CONF_MCAN1_TX_FIFO_QUEUE_NUM];
+alignas(4) __nocache static struct mcan_tx_event_element mcan1_tx_event_fifo[CONF_MCAN1_TX_EVENT_FIFO];
+alignas(4) __nocache static struct mcan_standard_message_filter_element mcan1_rx_standard_filter[CONF_MCAN1_RX_STANDARD_ID_FILTER_NUM];
+alignas(4) __nocache static struct mcan_extended_message_filter_element mcan1_rx_extended_filter[CONF_MCAN1_RX_EXTENDED_ID_FILTER_NUM];
+
+/**
+ * \brief initialize MCAN memory .
+ *
+ * \param hw Base address of the MCAN
+ *
+ */
+static void _mcan_message_memory_init(Mcan *hw)
+{
+ if (hw == MCAN0) {
+ hw->MCAN_SIDFC = ((uint32_t)mcan0_rx_standard_filter & BIT_2_TO_15_MASK) |
+ MCAN_SIDFC_LSS(CONF_MCAN0_RX_STANDARD_ID_FILTER_NUM);
+ hw->MCAN_XIDFC = ((uint32_t)mcan0_rx_extended_filter & BIT_2_TO_15_MASK) |
+ MCAN_XIDFC_LSE(CONF_MCAN0_RX_EXTENDED_ID_FILTER_NUM);
+ hw->MCAN_RXF0C = ((uint32_t)mcan0_rx_fifo_0 & BIT_2_TO_15_MASK) |
+ MCAN_RXF0C_F0S(CONF_MCAN0_RX_FIFO_0_NUM);
+ hw->MCAN_RXF1C = ((uint32_t)mcan0_rx_fifo_1 & BIT_2_TO_15_MASK) |
+ MCAN_RXF1C_F1S(CONF_MCAN0_RX_FIFO_1_NUM);
+ hw->MCAN_RXBC = ((uint32_t)mcan0_rx_buffer & BIT_2_TO_15_MASK);
+ hw->MCAN_TXBC = ((uint32_t)mcan0_tx_buffer & BIT_2_TO_15_MASK) |
+ MCAN_TXBC_NDTB(CONF_MCAN0_TX_BUFFER_NUM) |
+ MCAN_TXBC_TFQS(CONF_MCAN0_TX_FIFO_QUEUE_NUM);
+ hw->MCAN_TXEFC = ((uint32_t)mcan0_tx_event_fifo & BIT_2_TO_15_MASK) |
+ MCAN_TXEFC_EFS(CONF_MCAN0_TX_EVENT_FIFO);
+ } else if (hw == MCAN1) {
+ hw->MCAN_SIDFC = ((uint32_t)mcan1_rx_standard_filter & BIT_2_TO_15_MASK) |
+ MCAN_SIDFC_LSS(CONF_MCAN1_RX_STANDARD_ID_FILTER_NUM);
+ hw->MCAN_XIDFC = ((uint32_t)mcan1_rx_extended_filter & BIT_2_TO_15_MASK) |
+ MCAN_XIDFC_LSE(CONF_MCAN1_RX_EXTENDED_ID_FILTER_NUM);
+ hw->MCAN_RXF0C = ((uint32_t)mcan1_rx_fifo_0 & BIT_2_TO_15_MASK) |
+ MCAN_RXF0C_F0S(CONF_MCAN1_RX_FIFO_0_NUM);
+ hw->MCAN_RXF1C = ((uint32_t)mcan1_rx_fifo_1 & BIT_2_TO_15_MASK) |
+ MCAN_RXF1C_F1S(CONF_MCAN1_RX_FIFO_1_NUM);
+ hw->MCAN_RXBC = ((uint32_t)mcan1_rx_buffer & BIT_2_TO_15_MASK);
+ hw->MCAN_TXBC = ((uint32_t)mcan1_tx_buffer & BIT_2_TO_15_MASK) |
+ MCAN_TXBC_NDTB(CONF_MCAN1_TX_BUFFER_NUM) |
+ MCAN_TXBC_TFQS(CONF_MCAN1_TX_FIFO_QUEUE_NUM);
+ hw->MCAN_TXEFC = ((uint32_t)mcan1_tx_event_fifo & BIT_2_TO_15_MASK) |
+ MCAN_TXEFC_EFS(CONF_MCAN1_TX_EVENT_FIFO);
+ }
+
+ /**
+ * The data size in conf_mcan.h should be 8/12/16/20/24/32/48/64,
+ * The corresponding setting value in register is 0/1//2/3/4/5/6/7.
+ * To simplify the calculation, separate to two group 8/12/16/20/24 which
+ * increased with 4 and 32/48/64 which increased with 16.
+ */
+ if (CONF_MCAN_ELEMENT_DATA_SIZE <= 24) {
+ hw->MCAN_RXESC = MCAN_RXESC_RBDS((CONF_MCAN_ELEMENT_DATA_SIZE - 8) / 4) |
+ MCAN_RXESC_F0DS((CONF_MCAN_ELEMENT_DATA_SIZE - 8) / 4) |
+ MCAN_RXESC_F1DS((CONF_MCAN_ELEMENT_DATA_SIZE - 8) / 4);
+ hw->MCAN_TXESC = MCAN_TXESC_TBDS((CONF_MCAN_ELEMENT_DATA_SIZE - 8) / 4);
+ } else {
+ hw->MCAN_RXESC = MCAN_RXESC_RBDS((CONF_MCAN_ELEMENT_DATA_SIZE - 32) / 16 + 5) |
+ MCAN_RXESC_F0DS((CONF_MCAN_ELEMENT_DATA_SIZE - 32) / 16 + 5) |
+ MCAN_RXESC_F1DS((CONF_MCAN_ELEMENT_DATA_SIZE - 32) / 16 + 5);
+ hw->MCAN_TXESC = MCAN_TXESC_TBDS((CONF_MCAN_ELEMENT_DATA_SIZE - 32) / 16 + 5);
+ }
+}
+
+/**
+ * \brief set default configuration when initialization.
+ *
+ * \param hw Base address of the MCAN
+ * \param config default configuration parameters.
+ */
+static void _mcan_set_configuration(Mcan *hw, struct mcan_config *config)
+{
+#if (SAMV71B || SAME70B || SAMV70B)
+ /* Timing setting for Rev B */
+ hw->MCAN_NBTP = MCAN_NBTP_NBRP(CONF_MCAN_NBTP_NBRP_VALUE) |
+ MCAN_NBTP_NSJW(CONF_MCAN_NBTP_NSJW_VALUE) |
+ MCAN_NBTP_NTSEG1(CONF_MCAN_NBTP_NTSEG1_VALUE) |
+ MCAN_NBTP_NTSEG2(CONF_MCAN_NBTP_NTSEG2_VALUE);
+ hw->MCAN_DBTP = MCAN_DBTP_DBRP(CONF_MCAN_FBTP_FBRP_VALUE) |
+ MCAN_DBTP_DSJW(CONF_MCAN_FBTP_FSJW_VALUE) |
+ MCAN_DBTP_DTSEG1(CONF_MCAN_FBTP_FTSEG1_VALUE) |
+ MCAN_DBTP_DTSEG2(CONF_MCAN_FBTP_FTSEG2_VALUE);
+
+ hw->MCAN_TDCR = MCAN_TDCR_TDCO(config->delay_compensation_offset) |
+ MCAN_TDCR_TDCF(config->delay_compensation_filter_window_length);
+
+ if (config->tdc_enable) {
+ hw->MCAN_DBTP |= MCAN_DBTP_TDC_ENABLED;
+ }
+#else
+ /* Timing setting. */
+ hw->MCAN_BTP = MCAN_BTP_BRP(CONF_MCAN_NBTP_NBRP_VALUE) |
+ MCAN_BTP_SJW(CONF_MCAN_NBTP_NSJW_VALUE) |
+ MCAN_BTP_TSEG1(CONF_MCAN_NBTP_NTSEG1_VALUE) |
+ MCAN_BTP_TSEG2(CONF_MCAN_NBTP_NTSEG2_VALUE);
+ hw->MCAN_FBTP = MCAN_FBTP_FBRP(CONF_MCAN_FBTP_FBRP_VALUE) |
+ MCAN_FBTP_FSJW(CONF_MCAN_FBTP_FSJW_VALUE) |
+ MCAN_FBTP_FTSEG1(CONF_MCAN_FBTP_FTSEG1_VALUE) |
+ MCAN_FBTP_FTSEG2(CONF_MCAN_FBTP_FTSEG2_VALUE) |
+ MCAN_FBTP_TDCO(config->delay_compensation_offset);
+
+ if (config->tdc_enable) {
+ hw->MCAN_FBTP |= MCAN_FBTP_TDC_ENABLED;
+ }
+#endif
+ hw->MCAN_RWD |= MCAN_RWD_WDC(config->watchdog_configuration);
+
+ if (config->transmit_pause) {
+ hw->MCAN_CCCR |= MCAN_CCCR_TXP;
+ }
+
+ if (!config->automatic_retransmission) {
+ hw->MCAN_CCCR |= MCAN_CCCR_DAR;
+ }
+
+ if (config->clock_stop_request) {
+ hw->MCAN_CCCR |= MCAN_CCCR_CSR;
+ }
+
+ hw->MCAN_TSCC = MCAN_TSCC_TCP(config->timestamp_prescaler) |
+ MCAN_TSCC_TSS_TCP_INC;
+
+ hw->MCAN_TOCC = MCAN_TOCC_TOP(config->timeout_period) |
+ config->timeout_mode | config->timeout_enable;
+
+ hw->MCAN_GFC = MCAN_GFC_ANFS(config->nonmatching_frames_action_standard) |
+ MCAN_GFC_ANFE(config->nonmatching_frames_action_extended);
+ if (config->remote_frames_standard_reject) {
+ hw->MCAN_GFC |= MCAN_GFC_RRFS;
+ }
+ if (config->remote_frames_extended_reject) {
+ hw->MCAN_GFC|= MCAN_GFC_RRFE;
+ }
+
+ hw->MCAN_XIDAM = config->extended_id_mask;
+
+ if (config->rx_fifo_0_overwrite) {
+ hw->MCAN_RXF0C |= MCAN_RXF0C_F0OM;
+ }
+ hw->MCAN_RXF0C |= MCAN_RXF0C_F0WM(config->rx_fifo_0_watermark);
+
+ if (config->rx_fifo_1_overwrite) {
+ hw->MCAN_RXF1C |= MCAN_RXF1C_F1OM;
+ }
+ hw->MCAN_RXF1C |= MCAN_RXF1C_F1WM(config->rx_fifo_1_watermark);
+
+ if (config->tx_queue_mode) {
+ hw->MCAN_TXBC |= MCAN_TXBC_TFQM;
+ }
+
+ hw->MCAN_TXEFC |= MCAN_TXEFC_EFWM(config->tx_event_fifo_watermark);
+}
+
+/**
+ * \brief enable can module clock.
+ *
+ * \param module_inst MCAN instance
+ *
+ */
+static void _mcan_enable_peripheral_clock(struct mcan_module *const module_inst)
+{
+ if (module_inst->hw == MCAN0) {
+ /* Turn on the digital interface clock. */
+ pmc_enable_periph_clk(ID_MCAN0);
+ } else if (module_inst->hw == MCAN1) {
+ /* Turn on the digital interface clock. */
+ pmc_enable_periph_clk(ID_MCAN1);
+ }
+}
+
+/**
+ * \brief initialize can module.
+ *
+ * \param module_inst MCAN instance
+ * \param hw Base address of MCAN.
+ * \param config default configuration .
+ */
+void mcan_init(struct mcan_module *const module_inst, Mcan *hw, struct mcan_config *config)
+{
+ /* Sanity check arguments */
+ Assert(module_inst);
+ Assert(hw);
+ Assert(config);
+
+ /* Associate the software module instance with the hardware module */
+ module_inst->hw = hw;
+
+ pmc_disable_pck(PMC_PCK_5);
+
+#if 1 // dc42 use UPLL not PLLA as recommended in the documentation, so the MCAN clock is independent of the CPU clock frequency
+ pmc_switch_pck_to_upllck(PMC_PCK_5, PMC_PCK_PRES(9)); // run PCLK5 at 48MHz
+#else
+ pmc_switch_pck_to_pllack(PMC_PCK_5, PMC_PCK_PRES(9));
+#endif
+ pmc_enable_pck(PMC_PCK_5);
+
+ /* Enable peripheral clock */
+ _mcan_enable_peripheral_clock(module_inst);
+
+
+ /* Configuration Change Enable. */
+ hw->MCAN_CCCR |= MCAN_CCCR_CCE;
+
+ /* Initialize the message memory address. */
+ _mcan_message_memory_init(hw);
+
+ /* Set the configuration. */
+ _mcan_set_configuration(hw, config);
+
+ /* Enable the interrupt setting which no need change. */
+ hw->MCAN_ILE = MCAN_ILE_EINT0 | MCAN_ILE_EINT1;
+ hw->MCAN_TXBTIE = 0xFFFFFFFFul;
+ hw->MCAN_TXBCIE = 0xFFFFFFFFul;
+}
+
+/**
+ * \brief start can module after initialization.
+ *
+ * \param module_inst MCAN instance
+ *
+ */
+void mcan_start(struct mcan_module *const module_inst)
+{
+ module_inst->hw->MCAN_CCCR &= ~MCAN_CCCR_INIT;
+ /* Wait for the sync. */
+ while (module_inst->hw->MCAN_CCCR & MCAN_CCCR_INIT);
+}
+
+/**
+ * \brief stop mcan module when bus off occurs
+ *
+ * \param module_inst MCAN instance
+ *
+ */
+void mcan_stop(struct mcan_module *const module_inst)
+{
+ module_inst->hw->MCAN_CCCR |= MCAN_CCCR_INIT;
+ /* Wait for the sync. */
+ while (!(module_inst->hw->MCAN_CCCR & MCAN_CCCR_INIT));
+}
+
+/**
+ * \brief switch mcan module into fd mode.
+ *
+ * \param module_inst MCAN instance
+ *
+ */
+void mcan_enable_fd_mode(struct mcan_module *const module_inst)
+{
+ module_inst->hw->MCAN_CCCR |= MCAN_CCCR_INIT;
+ /* Wait for the sync. */
+ while (!(module_inst->hw->MCAN_CCCR & MCAN_CCCR_INIT));
+ module_inst->hw->MCAN_CCCR |= MCAN_CCCR_CCE;
+#if (SAMV71B || SAME70B || SAMV70B)
+ module_inst->hw->MCAN_CCCR |= (MCAN_CCCR_FDOE | MCAN_CCCR_BRSE);
+#else
+ module_inst->hw->MCAN_CCCR |= MCAN_CCCR_CME(2);
+ module_inst->hw->MCAN_CCCR |= MCAN_CCCR_CMR(2);
+#endif
+
+}
+
+/**
+ * \brief disable fd mode of mcan module.
+ *
+ * \param module_inst MCAN instance
+ *
+ */
+void mcan_disable_fd_mode(struct mcan_module *const module_inst)
+{
+ module_inst->hw->MCAN_CCCR |= MCAN_CCCR_INIT;
+ /* Wait for the sync. */
+ while (!(module_inst->hw->MCAN_CCCR & MCAN_CCCR_INIT));
+ module_inst->hw->MCAN_CCCR |= MCAN_CCCR_CCE;
+#if (SAMV71B || SAME70B || SAMV70B)
+ module_inst->hw->MCAN_CCCR &= MCAN_CCCR_FDOE;
+#else
+ module_inst->hw->MCAN_CCCR &= MCAN_CCCR_CME(MCAN_CCCR_CME_ISO11898_1);
+#endif
+}
+
+/**
+ * \brief enable restricted mode of mcan module.
+ *
+ * \param module_inst MCAN instance
+ *
+ */
+void mcan_enable_restricted_operation_mode(struct mcan_module *const module_inst)
+{
+ module_inst->hw->MCAN_CCCR |= MCAN_CCCR_INIT;
+ /* Wait for the sync. */
+ while (!(module_inst->hw->MCAN_CCCR & MCAN_CCCR_INIT));
+ module_inst->hw->MCAN_CCCR |= MCAN_CCCR_CCE;
+
+ module_inst->hw->MCAN_CCCR |= MCAN_CCCR_ASM;
+}
+
+/**
+ * \brief disable restricted mode of mcan module.
+ *
+ * \param module_inst MCAN instance
+ *
+ */
+void mcan_disable_restricted_operation_mode(struct mcan_module *const module_inst)
+{
+ module_inst->hw->MCAN_CCCR &= ~MCAN_CCCR_ASM;
+}
+
+/**
+ * \brief enable bus monitor mode of mcan module.
+ *
+ * \param module_inst MCAN instance
+ *
+ */
+void mcan_enable_bus_monitor_mode(struct mcan_module *const module_inst)
+{
+ module_inst->hw->MCAN_CCCR |= MCAN_CCCR_INIT;
+ /* Wait for the sync. */
+ while (!(module_inst->hw->MCAN_CCCR & MCAN_CCCR_INIT));
+ module_inst->hw->MCAN_CCCR |= MCAN_CCCR_CCE;
+
+ module_inst->hw->MCAN_CCCR |= MCAN_CCCR_MON;
+}
+
+/**
+ * \brief disable bus monitor mode of mcan module.
+ *
+ * \param module_inst MCAN instance
+ *
+ */
+void mcan_disable_bus_monitor_mode(struct mcan_module *const module_inst)
+{
+ module_inst->hw->MCAN_CCCR &= ~MCAN_CCCR_MON;
+}
+
+/**
+ * \brief enable sleep mode of mcan module.
+ *
+ * \param module_inst MCAN instance
+ *
+ */
+void mcan_enable_sleep_mode(struct mcan_module *const module_inst)
+{
+ module_inst->hw->MCAN_CCCR |= MCAN_CCCR_CSR;
+ /* Wait for the sync. */
+ while (!(module_inst->hw->MCAN_CCCR & MCAN_CCCR_INIT));
+
+ while (!(module_inst->hw->MCAN_CCCR & MCAN_CCCR_CSA));
+}
+
+/**
+ * \brief disable sleep mode of mcan module.
+ *
+ * \param module_inst MCAN instance
+ *
+ */
+void mcan_disable_sleep_mode(struct mcan_module *const module_inst)
+{
+ /* Enable peripheral clock */
+ _mcan_enable_peripheral_clock(module_inst);
+
+ module_inst->hw->MCAN_CCCR &= ~MCAN_CCCR_CSR;
+ while ((module_inst->hw->MCAN_CCCR & MCAN_CCCR_CSA));
+}
+
+/**
+ * \brief enable test mode of mcan module.
+ *
+ * \param module_inst MCAN instance
+ *
+ */
+void mcan_enable_test_mode(struct mcan_module *const module_inst)
+{
+ module_inst->hw->MCAN_CCCR |= MCAN_CCCR_INIT;
+ /* Wait for the sync. */
+ while (!(module_inst->hw->MCAN_CCCR & MCAN_CCCR_INIT));
+ module_inst->hw->MCAN_CCCR |= MCAN_CCCR_CCE;
+
+ module_inst->hw->MCAN_CCCR |= MCAN_CCCR_TEST;
+ module_inst->hw->MCAN_TEST |= MCAN_TEST_LBCK;
+}
+
+/**
+ * \brief disable test mode of mcan module.
+ *
+ * \param module_inst MCAN instance
+ *
+ */
+void mcan_disable_test_mode(struct mcan_module *const module_inst)
+{
+ module_inst->hw->MCAN_CCCR &= ~MCAN_CCCR_TEST;
+}
+
+/**
+ * \brief set standard receive CAN ID.
+ *
+ * \param module_inst MCAN instance
+ * \param sd_filter structure of CAN ID
+ * \param index CAN messages memory index for different CAN ID
+ *
+ * \return status code.
+ */
+enum status_code mcan_set_rx_standard_filter(struct mcan_module *const module_inst, struct mcan_standard_message_filter_element *sd_filter, uint32_t index)
+{
+ if (module_inst->hw == MCAN0) {
+ mcan0_rx_standard_filter[index].S0.reg = sd_filter->S0.reg;
+ return STATUS_OK;
+ } else if (module_inst->hw == MCAN1) {
+ mcan1_rx_standard_filter[index].S0.reg = sd_filter->S0.reg;
+ return STATUS_OK;
+ }
+ return ERR_INVALID_ARG;
+}
+
+/**
+ * \brief set extended receive CAN ID.
+ *
+ * \param module_inst MCAN instance
+ * \param sd_filter structure of extended CAN ID
+ * \param index CAN messages memory index for different CAN ID
+ *
+ * \return status code.
+ */
+enum status_code mcan_set_rx_extended_filter(struct mcan_module *const module_inst, struct mcan_extended_message_filter_element *et_filter, uint32_t index)
+{
+ if (module_inst->hw == MCAN0) {
+ mcan0_rx_extended_filter[index].F0.reg = et_filter->F0.reg;
+ mcan0_rx_extended_filter[index].F1.reg = et_filter->F1.reg;
+ return STATUS_OK;
+ } else if (module_inst->hw == MCAN1) {
+ mcan1_rx_extended_filter[index].F0.reg = et_filter->F0.reg;
+ mcan1_rx_extended_filter[index].F1.reg = et_filter->F1.reg;
+ return STATUS_OK;
+ }
+ return ERR_INVALID_ARG;
+}
+
+/**
+ * \brief get dedicated rx buffer element .
+ *
+ * \param module_inst MCAN instance
+ * \param rx_element structure of element
+ * \param index CAN messages memory index for receiving CAN ID
+ *
+ * \return status code.
+ */
+enum status_code mcan_get_rx_buffer_element(struct mcan_module *const module_inst, struct mcan_rx_element *rx_element, uint32_t index)
+{
+ if (module_inst->hw == MCAN0) {
+ *rx_element = mcan0_rx_buffer[index];
+ return STATUS_OK;
+ } else if (module_inst->hw == MCAN1) {
+ *rx_element = mcan1_rx_buffer[index];
+ return STATUS_OK;
+ }
+ return ERR_INVALID_ARG;
+}
+
+/**
+ * \brief get FIFO rx buffer element .
+ *
+ * \param module_inst MCAN instance
+ * \param rx_element structure of element
+ * \param index CAN messages memory index for receiving CAN ID
+ *
+ * \return status code.
+ */
+enum status_code mcan_get_rx_fifo_0_element(struct mcan_module *const module_inst, struct mcan_rx_element *rx_element, uint32_t index)
+{
+ if (module_inst->hw == MCAN0) {
+ *rx_element = mcan0_rx_fifo_0[index];
+ return STATUS_OK;
+ } else if (module_inst->hw == MCAN1) {
+ *rx_element = mcan1_rx_fifo_0[index];
+ return STATUS_OK;
+ }
+ return ERR_INVALID_ARG;
+}
+
+/**
+ * \brief get FIFO rx buffer element .
+ *
+ * \param module_inst MCAN instance
+ * \param rx_element structure of element
+ * \param index CAN messages memory index for receiving CAN ID
+ *
+ * \return status code.
+ */
+enum status_code mcan_get_rx_fifo_1_element(struct mcan_module *const module_inst, struct mcan_rx_element *rx_element, uint32_t index)
+{
+ if (module_inst->hw == MCAN0) {
+ *rx_element = mcan0_rx_fifo_1[index];
+ return STATUS_OK;
+ } else if (module_inst->hw == MCAN1) {
+ *rx_element = mcan1_rx_fifo_1[index];
+ return STATUS_OK;
+ }
+ return ERR_INVALID_ARG;
+}
+
+/**
+ * \brief set dedicated transmit buffer element .
+ *
+ * \param module_inst MCAN instance
+ * \param tx_element structure of element
+ * \param index CAN messages memory index for transmitting CAN ID
+ *
+ * \return status code.
+ */
+enum status_code mcan_set_tx_buffer_element(struct mcan_module *const module_inst, struct mcan_tx_element *tx_element, uint32_t index)
+{
+ uint32_t i;
+ if (module_inst->hw == MCAN0) {
+ mcan0_tx_buffer[index].T0.reg = tx_element->T0.reg;
+ mcan0_tx_buffer[index].T1.reg = tx_element->T1.reg;
+ for (i = 0; i < CONF_MCAN_ELEMENT_DATA_SIZE; i++) {
+ mcan0_tx_buffer[index].data[i] = tx_element->data[i];
+ }
+ return STATUS_OK;
+ } else if (module_inst->hw == MCAN1) {
+ mcan1_tx_buffer[index].T0.reg = tx_element->T0.reg;
+ mcan1_tx_buffer[index].T1.reg = tx_element->T1.reg;
+ for (i = 0; i < CONF_MCAN_ELEMENT_DATA_SIZE; i++) {
+ mcan1_tx_buffer[index].data[i] = tx_element->data[i];
+ }
+ return STATUS_OK;
+ }
+ return ERR_INVALID_ARG;
+}
+
+/**
+ * \brief set FIFO transmit buffer element .
+ *
+ * \param module_inst MCAN instance
+ * \param tx_element structure of element
+ * \param index CAN messages memory index for transmitting CAN ID
+ *
+ * \return status code.
+ */
+enum status_code mcan_get_tx_event_fifo_element(struct mcan_module *const module_inst, struct mcan_tx_event_element *tx_event_element, uint32_t index)
+{
+ if (module_inst->hw == MCAN0) {
+ tx_event_element->E0.reg = mcan0_tx_event_fifo[index].E0.reg;
+ tx_event_element->E1.reg = mcan0_tx_event_fifo[index].E1.reg;
+ return STATUS_OK;
+ } else if (module_inst->hw == MCAN1) {
+ tx_event_element->E0.reg = mcan1_tx_event_fifo[index].E0.reg;
+ tx_event_element->E1.reg = mcan1_tx_event_fifo[index].E1.reg;
+ return STATUS_OK;
+ }
+ return ERR_INVALID_ARG;
+}
+
+#endif // SUPPORT_CAN_EXPANSION
+
+// End
+
diff --git a/src/Hardware/SAME70/CanDriver.h b/src/Hardware/SAME70/CanDriver.h
new file mode 100644
index 00000000..46cb02bc
--- /dev/null
+++ b/src/Hardware/SAME70/CanDriver.h
@@ -0,0 +1,1138 @@
+/**
+ * \file
+ *
+ * \brief SAM Control Area Network (MCAN) Low Level Driver
+ *
+ * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Subject to your compliance with these terms, you may use Microchip
+ * software and any derivatives exclusively with Microchip products.
+ * It is your responsibility to comply with third party license terms applicable
+ * to your use of third party software (including open source software) that
+ * may accompany Microchip software.
+ *
+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
+ *
+ * \asf_license_stop
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
+ */
+
+
+#ifndef SRC_HARDWARE_CANDRIVER_H_
+#define SRC_HARDWARE_CANDRIVER_H_
+
+#include <RepRapFirmware.h>
+
+#if SUPPORT_CAN_EXPANSION
+
+#include <compiler.h>
+#include <status_codes.h>
+
+/** The value should be 8/12/16/20/24/32/48/64. */
+#define CONF_MCAN_ELEMENT_DATA_SIZE 64
+
+/* -------- MCAN_RX_ELEMENT_R0 : (MCAN RX element: 0x00) (R/W 32) Rx Element R0 Configuration -------- */
+typedef union {
+ struct {
+ /* bit: 0..28 Identifier */
+ uint32_t ID:29;
+ /* bit: 29 Remote Transmission Request */
+ uint32_t RTR:1;
+ /* bit: 30 Extended Identifier */
+ uint32_t XTD:1;
+ /* bit: 31 Error State Indicator */
+ uint32_t ESI:1;
+ } bit;
+ /* Type used for register access */
+ uint32_t reg;
+} MCAN_RX_ELEMENT_R0_Type;
+
+#define MCAN_RX_ELEMENT_R0_ID_Pos 0
+#define MCAN_RX_ELEMENT_R0_ID_Msk (0x1FFFFFFFul << MCAN_RX_ELEMENT_R0_ID_Pos)
+#define MCAN_RX_ELEMENT_R0_ID(value) ((MCAN_RX_ELEMENT_R0_ID_Msk & ((value) << MCAN_RX_ELEMENT_R0_ID_Pos)))
+#define MCAN_RX_ELEMENT_R0_RTR_Pos 29
+#define MCAN_RX_ELEMENT_R0_RTR (0x1ul << MCAN_RX_ELEMENT_R0_RTR_Pos)
+#define MCAN_RX_ELEMENT_R0_XTD_Pos 30
+#define MCAN_RX_ELEMENT_R0_XTD (0x1ul << MCAN_RX_ELEMENT_R0_XTD_Pos)
+#define MCAN_RX_ELEMENT_R0_ESI_Pos 31
+#define MCAN_RX_ELEMENT_R0_ESI (0x1ul << MCAN_RX_ELEMENT_R0_ESI_Pos)
+
+/* -------- MCAN_RX_ELEMENT_R1 : (MCAN RX element: 0x01) (R/W 32) Rx Element R1 Configuration -------- */
+typedef union {
+ struct {
+ /* bit: 0..15 Rx Timestamp */
+ uint32_t RXTS:16;
+ /* bit: 16..19 Data Length Code */
+ uint32_t DLC:4;
+ /* bit: 20 Bit Rate Switch */
+ uint32_t BRS:1;
+ /* bit: 21 FD Format */
+ uint32_t EDL:1;
+ /* bit: 22..23 Reserved */
+ uint32_t :2;
+ /* bit: 24..30 Filter Index */
+ uint32_t FIDX:7;
+ /* bit: 31 Accepted Non-matching Frame */
+ uint32_t ANMF:1;
+ } bit;
+ /* Type used for register access */
+ uint32_t reg;
+} MCAN_RX_ELEMENT_R1_Type;
+
+#define MCAN_RX_ELEMENT_R1_RXTS_Pos 0
+#define MCAN_RX_ELEMENT_R1_RXTS_Msk (0xFFFFul << MCAN_RX_ELEMENT_R1_RXTS_Pos)
+#define MCAN_RX_ELEMENT_R1_RXTS(value) ((MCAN_RX_ELEMENT_R1_RXTS_Msk & ((value) << MCAN_RX_ELEMENT_R1_RXTS_Pos)))
+#define MCAN_RX_ELEMENT_R1_DLC_Pos 16
+#define MCAN_RX_ELEMENT_R1_DLC_Msk (0xFul << MCAN_RX_ELEMENT_R1_DLC_Pos)
+#define MCAN_RX_ELEMENT_R1_DLC(value) ((MCAN_RX_ELEMENT_R1_DLC_Msk & ((value) << MCAN_RX_ELEMENT_R1_DLC_Pos)))
+#define MCAN_RX_ELEMENT_R1_BRS_Pos 20
+#define MCAN_RX_ELEMENT_R1_BRS (0x1ul << MCAN_RX_ELEMENT_R1_BRS_Pos)
+#define MCAN_RX_ELEMENT_R1_FDF_Pos 21
+#define MCAN_RX_ELEMENT_R1_FDF (0x1ul << MCAN_RX_ELEMENT_R1_FDF_Pos)
+#define MCAN_RX_ELEMENT_R1_FIDX_Pos 24
+#define MCAN_RX_ELEMENT_R1_FIDX_Msk (0x7Ful << MCAN_RX_ELEMENT_R1_FIDX_Pos)
+#define MCAN_RX_ELEMENT_R1_FIDX(value) ((MCAN_RX_ELEMENT_R1_FIDX_Msk & ((value) << MCAN_RX_ELEMENT_R1_FIDX_Pos)))
+#define MCAN_RX_ELEMENT_R1_ANMF_Pos 31
+#define MCAN_RX_ELEMENT_R1_ANMF (0x1ul << MCAN_RX_ELEMENT_R1_ANMF_Pos)
+
+//TODO there is no need for these 3 structs to be different
+/**
+ * \brief MCAN receive element structure for buffer.
+ */
+struct mcan_rx_element {
+ __IO MCAN_RX_ELEMENT_R0_Type R0;
+ __IO MCAN_RX_ELEMENT_R1_Type R1;
+ uint8_t data[CONF_MCAN_ELEMENT_DATA_SIZE];
+
+ mcan_rx_element& operator=(const mcan_rx_element& other)
+ {
+ R0.reg = other.R0.reg;
+ R1.reg = other.R1.reg;
+ memcpy(data, other.data, sizeof(data));
+ return *this;
+ }
+};
+
+/* -------- MCAN_TX_ELEMENT_T0 : (MCAN TX element: 0x00) (R/W 32) Tx Element T0 Configuration -------- */
+typedef union {
+ struct {
+ /* bit: 0..28 Identifier */
+ uint32_t ID:29;
+ /* bit: 29 Remote Transmission Request */
+ uint32_t RTR:1;
+ /* bit: 30 Extended Identifier */
+ uint32_t XTD:1;
+#if (SAMV71B || SAME70B || SAMV70B)
+ /* bit: 31 Error State Indicator */
+ uint32_t ESI:1;
+#else
+ /* bit: 31 Reserved */
+ uint32_t :1;
+#endif
+ } bit;
+ /* Type used for register access */
+ uint32_t reg;
+} MCAN_TX_ELEMENT_T0_Type;
+
+#define MCAN_TX_ELEMENT_T0_EXTENDED_ID_Pos 0
+#define MCAN_TX_ELEMENT_T0_EXTENDED_ID_Msk (0x1FFFFFFFul << MCAN_TX_ELEMENT_T0_EXTENDED_ID_Pos)
+#define MCAN_TX_ELEMENT_T0_EXTENDED_ID(value) ((MCAN_TX_ELEMENT_T0_EXTENDED_ID_Msk & ((value) << MCAN_TX_ELEMENT_T0_EXTENDED_ID_Pos)))
+#define MCAN_TX_ELEMENT_T0_STANDARD_ID_Pos 18
+#define MCAN_TX_ELEMENT_T0_STANDARD_ID_Msk (0x7FFul << MCAN_TX_ELEMENT_T0_STANDARD_ID_Pos)
+#define MCAN_TX_ELEMENT_T0_STANDARD_ID(value) ((MCAN_TX_ELEMENT_T0_STANDARD_ID_Msk & ((value) << MCAN_TX_ELEMENT_T0_STANDARD_ID_Pos)))
+#define MCAN_TX_ELEMENT_T0_RTR_Pos 29
+#define MCAN_TX_ELEMENT_T0_RTR (0x1ul << MCAN_TX_ELEMENT_T0_RTR_Pos)
+#define MCAN_TX_ELEMENT_T0_XTD_Pos 30
+#define MCAN_TX_ELEMENT_T0_XTD (0x1ul << MCAN_TX_ELEMENT_T0_XTD_Pos)
+#if (SAMV71B || SAME70B || SAMV70B)
+#define MCAN_TX_ELEMENT_T0_ESI_Pos 31
+#define MCAN_TX_ELEMENT_T0_ESI (0x1ul << MCAN_TX_ELEMENT_T0_ESI_Pos)
+#endif
+
+/* -------- MCAN_TX_ELEMENT_T1 : (MCAN TX element: 0x01) (R/W 32) Tx Element T1 Configuration -------- */
+typedef union {
+ struct {
+ /* bit: 0..15 Reserved */
+ uint32_t :16;
+ /* bit: 16..19 Data Length Code */
+ uint32_t DLC:4;
+#if (SAMV71B || SAME70B || SAMV70B)
+ /* bit: 20 Bit Rate Switch */
+ uint32_t BRS:1;
+ /* bit: 21 FD Format */
+ uint32_t FDF:1;
+ /* bit: 22 Reserved */
+ uint32_t :1;
+#else
+ /* bit: 20..22 Reserved */
+ uint32_t :3;
+#endif
+ /* bit: 23 Event FIFO Control */
+ uint32_t EFCC:1;
+ /* bit: 24..31 Message Marker */
+ uint32_t MM:8;
+ } bit;
+ /* Type used for register access */
+ uint32_t reg;
+} MCAN_TX_ELEMENT_T1_Type;
+
+#define MCAN_TX_ELEMENT_T1_DLC_Pos 16
+#define MCAN_TX_ELEMENT_T1_DLC_Msk (0xFul << MCAN_TX_ELEMENT_T1_DLC_Pos)
+#define MCAN_TX_ELEMENT_T1_DLC(value) ((MCAN_TX_ELEMENT_T1_DLC_Msk & ((value) << MCAN_TX_ELEMENT_T1_DLC_Pos)))
+/**< \brief (MCAN_RXESC) 8 byte data field */
+#define MCAN_TX_ELEMENT_T1_DLC_DATA8_Val 0x8ul
+/**< \brief (MCAN_RXESC) 12 byte data field */
+#define MCAN_TX_ELEMENT_T1_DLC_DATA12_Val 0x9ul
+/**< \brief (MCAN_RXESC) 16 byte data field */
+#define MCAN_TX_ELEMENT_T1_DLC_DATA16_Val 0xAul
+/**< \brief (MCAN_RXESC) 20 byte data field */
+#define MCAN_TX_ELEMENT_T1_DLC_DATA20_Val 0xBul
+/**< \brief (MCAN_RXESC) 24 byte data field */
+#define MCAN_TX_ELEMENT_T1_DLC_DATA24_Val 0xCul
+/**< \brief (MCAN_RXESC) 32 byte data field */
+#define MCAN_TX_ELEMENT_T1_DLC_DATA32_Val 0xDul
+/**< \brief (MCAN_RXESC) 48 byte data field */
+#define MCAN_TX_ELEMENT_T1_DLC_DATA48_Val 0xEul
+/**< \brief (MCAN_RXESC) 64 byte data field */
+#define MCAN_TX_ELEMENT_T1_DLC_DATA64_Val 0xFul
+#if (SAMV71B || SAME70B || SAMV70B)
+#define MCAN_TX_ELEMENT_T1_BRS_Pos 20
+#define MCAN_TX_ELEMENT_T1_BRS (0x1ul << MCAN_TX_ELEMENT_T1_BRS_Pos)
+#define MCAN_TX_ELEMENT_T1_FDF_Pos 21
+#define MCAN_TX_ELEMENT_T1_FDF (0x1ul << MCAN_TX_ELEMENT_T1_FDF_Pos)
+#endif
+#define MCAN_TX_ELEMENT_T1_EFC_Pos 23
+#define MCAN_TX_ELEMENT_T1_EFC (0x1ul << MCAN_TX_ELEMENT_T1_EFC_Pos)
+#define MCAN_TX_ELEMENT_T1_MM_Pos 24
+#define MCAN_TX_ELEMENT_T1_MM_Msk (0xFFul << MCAN_TX_ELEMENT_T1_MM_Pos)
+#define MCAN_TX_ELEMENT_T1_MM(value) ((MCAN_TX_ELEMENT_T1_MM_Msk & ((value) << MCAN_TX_ELEMENT_T1_MM_Pos)))
+
+/**
+ * \brief MCAN transfer element structure.
+ *
+ * Common element structure for transfer buffer and FIFO/QUEUE.
+ */
+struct mcan_tx_element {
+ __IO MCAN_TX_ELEMENT_T0_Type T0;
+ __IO MCAN_TX_ELEMENT_T1_Type T1;
+ uint8_t data[CONF_MCAN_ELEMENT_DATA_SIZE];
+};
+
+/* -------- MCAN_TX_EVENT_ELEMENT_E0 : (MCAN TX event element: 0x00) (R/W 32) Tx Event Element E0 Configuration -------- */
+typedef union {
+ struct {
+ /* bit: 0..28 Identifier */
+ uint32_t ID:29;
+ /* bit: 29 Remote Transmission Request */
+ uint32_t RTR:1;
+ /* bit: 30 Extended Identifier */
+ uint32_t XTD:1;
+ /* bit: 31 Error State Indicator */
+ uint32_t ESI:1;
+ } bit;
+ /* Type used for register access */
+ uint32_t reg;
+} MCAN_TX_EVENT_ELEMENT_E0_Type;
+
+#define MCAN_TX_EVENT_ELEMENT_E0_ID_Pos 0
+#define MCAN_TX_EVENT_ELEMENT_E0_ID_Msk (0x1FFFFFFFul << MCAN_TX_EVENT_ELEMENT_E0_ID_Pos)
+#define MCAN_TX_EVENT_ELEMENT_E0_ID(value) ((MCAN_TX_EVENT_ELEMENT_E0_ID_Msk & ((value) << MCAN_TX_EVENT_ELEMENT_E0_ID_Pos)))
+#define MCAN_TX_EVENT_ELEMENT_E0_RTR_Pos 29
+#define MCAN_TX_EVENT_ELEMENT_E0_RTR (0x1ul << MCAN_TX_EVENT_ELEMENT_E0_RTR_Pos)
+#define MCAN_TX_EVENT_ELEMENT_E0_XTD_Pos 30
+#define MCAN_TX_EVENT_ELEMENT_E0_XTD (0x1ul << MCAN_TX_EVENT_ELEMENT_E0_XTD_Pos)
+#define MCAN_TX_EVENT_ELEMENT_E0_ESI_Pos 31
+#define MCAN_TX_EVENT_ELEMENT_E0_ESI (0x1ul << MCAN_TX_EVENT_ELEMENT_E0_ESI_Pos)
+
+/* -------- MCAN_TX_EVENT_ELEMENT_E1 : (MCAN TX event element: 0x01) (R/W 32) Tx Event Element E1 Configuration -------- */
+typedef union {
+ struct {
+ /* bit: 0..15 Tx Timestamp */
+ uint32_t TXTS:16;
+ /* bit: 16..19 Data Length Code */
+ uint32_t DLC:4;
+ /* bit: 20 Bit Rate Switch */
+ uint32_t BRS:1;
+ /* bit: 21 FD Format */
+ uint32_t EDL:1;
+ /* bit: 22..23 Event Type */
+ uint32_t ET:2;
+ /* bit: 24..31 Message Marker */
+ uint32_t MM:8;
+ } bit;
+ /* Type used for register access */
+ uint32_t reg;
+} MCAN_TX_EVENT_ELEMENT_E1_Type;
+
+#define MCAN_TX_EVENT_ELEMENT_E1_TXTS_Pos 0
+#define MCAN_TX_EVENT_ELEMENT_E1_TXTS_Msk (0xFFFFul << MCAN_TX_EVENT_ELEMENT_E1_TXTS_Pos)
+#define MCAN_TX_EVENT_ELEMENT_E1_TXTS(value) ((MCAN_TX_EVENT_ELEMENT_E1_TXTS_Msk & ((value) << MCAN_TX_EVENT_ELEMENT_E1_TXTS_Pos)))
+#define MCAN_TX_EVENT_ELEMENT_E1_DLC_Pos 16
+#define MCAN_TX_EVENT_ELEMENT_E1_DLC_Msk (0xFul << MCAN_TX_EVENT_ELEMENT_E1_DLC_Pos)
+#define MCAN_TX_EVENT_ELEMENT_E1_DLC(value) ((MCAN_TX_EVENT_ELEMENT_E1_DLC_Msk & ((value) << MCAN_TX_EVENT_ELEMENT_E1_DLC_Pos)))
+#define MCAN_TX_EVENT_ELEMENT_E1_BRS_Pos 20
+#define MCAN_TX_EVENT_ELEMENT_E1_BRS (0x1ul << MCAN_TX_EVENT_ELEMENT_E1_BRS_Pos)
+#define MCAN_TX_EVENT_ELEMENT_E1_FDF_Pos 21
+#define MCAN_TX_EVENT_ELEMENT_E1_FDF (0x1ul << MCAN_TX_EVENT_ELEMENT_E1_FDF_Pos)
+#define MCAN_TX_EVENT_ELEMENT_E1_ET_Pos 22
+#define MCAN_TX_EVENT_ELEMENT_E1_ET_Msk (0x3ul << MCAN_TX_EVENT_ELEMENT_E1_ET_Pos)
+#define MCAN_TX_EVENT_ELEMENT_E1_ET(value) ((MCAN_TX_EVENT_ELEMENT_E1_ET_Msk & ((value) << MCAN_TX_EVENT_ELEMENT_E1_ET_Pos)))
+#define MCAN_TX_EVENT_ELEMENT_E1_MM_Pos 24
+#define MCAN_TX_EVENT_ELEMENT_E1_MM_Msk (0xFFul << MCAN_TX_EVENT_ELEMENT_E1_MM_Pos)
+#define MCAN_TX_EVENT_ELEMENT_E1_MM(value) ((MCAN_TX_EVENT_ELEMENT_E1_MM_Msk & ((value) << MCAN_TX_EVENT_ELEMENT_E1_MM_Pos)))
+
+/**
+ * \brief MCAN transfer event FIFO element structure.
+ *
+ * Common element structure for transfer event FIFO.
+ */
+struct mcan_tx_event_element {
+ __IO MCAN_TX_EVENT_ELEMENT_E0_Type E0;
+ __IO MCAN_TX_EVENT_ELEMENT_E1_Type E1;
+};
+
+/* -------- MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0 : (MCAN standard message ID filter element: 0x00) (R/W 32) Standard Message ID Filter Element S0 Configuration -------- */
+typedef union {
+ struct {
+ /* bit: 0..10 Standard Filter ID 2 */
+ uint32_t SFID2:11;
+ /* bit: 11..15 Reserved */
+ uint32_t :5;
+ /* bit: 16..26 Standard Filter ID 1 */
+ uint32_t SFID1:11;
+ /* bit: 27..29 Standard Filter Element Configuration */
+ uint32_t SFEC:3;
+ /* bit: 30..31 Standard Filter Type */
+ uint32_t SFT:2;
+ } bit;
+ /* Type used for register access */
+ uint32_t reg;
+} MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_Type;
+
+#define MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFID2_Pos 0
+#define MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFID2_Msk (0x7FFul << MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFID2_Pos)
+#define MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFID2(value) ((MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFID2_Msk & ((value) << MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFID2_Pos)))
+#define MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFID1_Pos 16
+#define MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFID1_Msk (0x7FFul << MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFID1_Pos)
+#define MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFID1(value) ((MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFID1_Msk & ((value) << MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFID1_Pos)))
+#define MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFEC_Pos 27
+#define MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFEC_Msk (0x7ul << MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFEC_Pos)
+#define MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFEC(value) ((MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFEC_Msk & ((value) << MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFEC_Pos)))
+#define MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFEC_DISABLE_Val 0
+#define MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFEC_STF0M_Val 1
+#define MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFEC_STF1M_Val 2
+#define MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFEC_REJECT_Val 3
+#define MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFEC_PRIORITY_Val 4
+#define MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFEC_PRIF0M_Val 5
+#define MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFEC_PRIF1M_Val 6
+#define MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFEC_STRXBUF_Val 7
+#define MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFT_Pos 30
+#define MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFT_Msk (0x3ul << MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFT_Pos)
+#define MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFT(value) ((MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFT_Msk & ((value) << MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFT_Pos)))
+#define MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFT_RANGE MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFT(0)
+#define MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFT_DUAL MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFT(1)
+#define MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFT_CLASSIC MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFT(2)
+
+/**
+ * \brief MCAN standard message ID filter element structure.
+ *
+ * Common element structure for standard message ID filter element.
+ */
+struct mcan_standard_message_filter_element {
+ __IO MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_Type S0;
+};
+
+/* -------- MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F0 : (MCAN extended message ID filter element: 0x00) (R/W 32) Extended Message ID Filter Element F0 Configuration -------- */
+typedef union {
+ struct {
+ /* bit: 0..28 Extended Filter ID 1 */
+ uint32_t EFID1:29;
+ /* bit: 29..31 Extended Filter Element Configuration */
+ uint32_t EFEC:3;
+ } bit;
+ /* Type used for register access */
+ uint32_t reg;
+} MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F0_Type;
+
+#define MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F0_EFID1_Pos 0
+#define MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F0_EFID1_Msk (0x1FFFFFFFul << MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F0_EFID1_Pos)
+#define MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F0_EFID1(value) ((MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F0_EFID1_Msk & ((value) << MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F0_EFID1_Pos)))
+#define MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F0_EFEC_Pos 29
+#define MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F0_EFEC_Msk (0x7ul << MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F0_EFEC_Pos)
+#define MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F0_EFEC(value) ((MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F0_EFEC_Msk & ((value) << MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F0_EFEC_Pos)))
+#define MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F0_EFEC_DISABLE_Val 0
+#define MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F0_EFEC_STF0M_Val 1
+#define MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F0_EFEC_STF1M_Val 2
+#define MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F0_EFEC_REJECT_Val 3
+#define MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F0_EFEC_PRIORITY_Val 4
+#define MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F0_EFEC_PRIF0M_Val 5
+#define MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F0_EFEC_PRIF1M_Val 6
+#define MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F0_EFEC_STRXBUF_Val 7
+
+/* -------- MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F1 : (MCAN extended message ID filter element: 0x01) (R/W 32) Extended Message ID Filter Element F1 Configuration -------- */
+typedef union {
+ struct {
+ /* bit: 0..28 Extended Filter ID 2 */
+ uint32_t EFID2:29;
+ /* bit: 29 Reserved */
+ uint32_t :1;
+ /* bit: 30..31 Extended Filter Type */
+ uint32_t EFT:2;
+ } bit;
+ /* Type used for register access */
+ uint32_t reg;
+} MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F1_Type;
+
+#define MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F1_EFID2_Pos 0
+#define MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F1_EFID2_Msk (0x1FFFFFFFul << MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F1_EFID2_Pos)
+#define MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F1_EFID2(value) ((MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F1_EFID2_Msk & ((value) << MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F1_EFID2_Pos)))
+#define MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F1_EFT_Pos 30
+#define MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F1_EFT_Msk (0x3ul << MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F1_EFT_Pos)
+#define MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F1_EFT(value) ((MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F1_EFT_Msk & ((value) << MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F1_EFT_Pos)))
+#define MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F1_EFT_RANGEM MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F1_EFT(0)
+#define MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F1_EFT_DUAL MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F1_EFT(1)
+#define MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F1_EFT_CLASSIC MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F1_EFT(2)
+#define MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F1_EFT_RANGE MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F1_EFT(3)
+
+/**
+ * \brief MCAN extended message ID filter element structure.
+ *
+ * Common element structure for extended message ID filter element.
+ */
+struct mcan_extended_message_filter_element {
+ __IO MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F0_Type F0;
+ __IO MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F1_Type F1;
+};
+/** @} */
+
+/**
+ * \defgroup asfdoc_sam_mcan_group SAM Control Area Network (MCAN) Low Level Driver
+ *
+ * This driver for AtmelĀ® | SMART SAM devices provides an low level
+ * interface for the configuration and management of the device's
+ * Control Area Network functionality.
+ *
+ * \note Since "The Control Area Network (CAN) performs communication according
+ * to ISO 11898-1 (Bosch CAN specification 2.0 part A,B) and to Bosch CAN FD
+ * specification V1.0", the driver is focus on the MAC layer and try to offer
+ * the APIs which can be used by upper application layer.
+ *
+ * For storage of Rx/Tx messages and for storage of the filter configuration,
+ * a message RAM is needed to the CAN module. In this driver, the message RAM
+ * is static allocated, the related setting is defined and can be changed in
+ * the module configuration file "conf_mcan.h".
+ *
+ * The following peripherals are used by this module:
+ * - CAN (Control Area Network)
+ *
+ * The following devices can use this module:
+ * - SAMV71
+ *
+ * The outline of this documentation is as follows:
+ * - \ref asfdoc_sam_mcan_prerequisites
+ * - \ref asfdoc_sam_mcan_module_overview
+ * - \ref asfdoc_sam_mcan_special_considerations
+ * - \ref asfdoc_sam_mcan_extra_info
+ * - \ref asfdoc_sam_mcan_examples
+ * - \ref asfdoc_sam_mcan_api_overview
+ *
+ *
+ * \section asfdoc_sam_mcan_prerequisites Prerequisites
+ *
+ * There are no prerequisites for this module.
+ *
+ *
+ * \section asfdoc_sam_mcan_module_overview Module Overview
+ *
+ * This driver provides an interface for the Control Area Network Controller
+ * functions on the device.
+ *
+ *
+ * \section asfdoc_sam_mcan_special_considerations Special Considerations
+ *
+ * There are no special considerations for this module.
+ *
+ *
+ * \section asfdoc_sam_mcan_extra_info Extra Information
+ *
+ * For extra information see \ref asfdoc_sam_mcan_extra. This includes:
+ * - \ref asfdoc_sam_mcan_extra_acronyms
+ * - \ref asfdoc_sam_mcan_extra_dependencies
+ * - \ref asfdoc_sam_mcan_extra_errata
+ * - \ref asfdoc_sam_mcan_extra_history
+ *
+ *
+ * \section asfdoc_sam_mcan_examples Examples
+ *
+ * For a list of examples related to this driver, see
+ * \ref asfdoc_sam_mcan_exqsg.
+ *
+ *
+ * \section asfdoc_sam_mcan_api_overview API Overview
+ * @{
+ */
+
+/**
+ * \name Module Setting
+ * @{
+ */
+
+/**
+ * \brief Can time out modes.
+ */
+enum mcan_timeout_mode {
+ /** Continuous operation. */
+ MCAN_TIMEOUT_CONTINUES = MCAN_TOCC_TOS_CONTINUOUS,
+ /** Timeout controlled by TX Event FIFO. */
+ MCAN_TIMEOUT_TX_EVEN_FIFO = MCAN_TOCC_TOS_TX_EV_TIMEOUT,
+ /** Timeout controlled by Rx FIFO 0. */
+ MCAN_TIMEOUT_RX_FIFO_0 = MCAN_TOCC_TOS_RX0_EV_TIMEOUT,
+ /** Timeout controlled by Rx FIFO 1. */
+ MCAN_TIMEOUT_RX_FIFO_1 = MCAN_TOCC_TOS_RX1_EV_TIMEOUT,
+};
+
+/**
+ * \brief Can nonmatching frames action.
+ */
+enum mcan_nonmatching_frames_action {
+ /** Accept in Rx FIFO 0. */
+ MCAN_NONMATCHING_FRAMES_FIFO_0,
+ /** Accept in Rx FIFO 1. */
+ MCAN_NONMATCHING_FRAMES_FIFO_1,
+ /** Reject. */
+ MCAN_NONMATCHING_FRAMES_REJECT,
+};
+
+/**
+ * \brief MCAN software device instance structure.
+ *
+ * MCAN software instance structure, used to retain software state information
+ * of an associated hardware module instance.
+ *
+ * \note The fields of this structure should not be altered by the user
+ * application; they are reserved for module-internal use only.
+ */
+struct mcan_module {
+ Mcan *hw;
+};
+
+/**
+ * \brief MCAN configuration structure.
+ *
+ * Configuration structure for an MCAN instance. This structure should be
+ * initialized by the \ref mcan_get_config_defaults()
+ * function before being modified by the user application.
+ */
+struct mcan_config {
+ /** MCAN run in standby control. */
+ bool run_in_standby;
+ /** Start value of the Message RAM Watchdog Counter */
+ uint8_t watchdog_configuration;
+ /** Transmit Pause. */
+ bool transmit_pause;
+ /** Edge Filtering during Bus Integration. */
+ bool edge_filtering;
+ /** Protocol Exception Handling. */
+ bool protocol_exception_handling;
+ /** Automatic Retransmission. */
+ bool automatic_retransmission;
+ /** Clock Stop Request. */
+ bool clock_stop_request;
+ /** Clock Stop Acknowledge. */
+ bool clock_stop_acknowledge;
+ /** Timestamp Counter Prescaler: 0x0-0xF */
+ uint8_t timestamp_prescaler;
+ /** Timeout Period. */
+ uint16_t timeout_period;
+ /** Timeout Mode. */
+ enum mcan_timeout_mode timeout_mode;
+ /** Timeout enable. */
+ bool timeout_enable;
+ /** Transceiver Delay Compensation enable. */
+ bool tdc_enable;
+ /** Transmitter Delay Compensation Offset : 0x0-0x7F */
+ uint8_t delay_compensation_offset;
+#if (SAMV71B || SAME70B || SAMV70B)
+ /** Transmitter Delay Compensation Filter Window Length : 0x0-0x7F */
+ uint8_t delay_compensation_filter_window_length;
+#endif
+ /** Nonmatching frames action for standard frames. */
+ enum mcan_nonmatching_frames_action nonmatching_frames_action_standard;
+ /** Nonmatching frames action for extended frames. */
+ enum mcan_nonmatching_frames_action nonmatching_frames_action_extended;
+ /** Reject Remote Standard Frames. */
+ bool remote_frames_standard_reject;
+ /** Reject Remote Extended Frames. */
+ bool remote_frames_extended_reject;
+ /** Extended ID Mask: 0x0-0x1FFFFFFF. */
+ uint32_t extended_id_mask;
+ /** Rx FIFO 0 Operation Mode. */
+ bool rx_fifo_0_overwrite;
+ /** Rx FIFO 0 Watermark: 1-64, other value disable it. */
+ uint8_t rx_fifo_0_watermark;
+ /** Rx FIFO 1 Operation Mode. */
+ bool rx_fifo_1_overwrite;
+ /** Rx FIFO 1 Watermark: 1-64, other value disable it. */
+ uint8_t rx_fifo_1_watermark;
+ /** Tx FIFO/Queue Mode, 0 for FIFO and 1 for Queue. */
+ bool tx_queue_mode;
+ /** Tx Event FIFO Watermark: 1-32, other value disable it. */
+ uint8_t tx_event_fifo_watermark;
+};
+
+/**
+ * \brief Initializes an MCAN configuration structure to defaults
+ *
+ * Initializes a given MCAN configuration struct to a set of known default
+ * values. This function should be called on any new instance of the
+ * configuration struct before being modified by the user application.
+ *
+ * The default configuration is as follows:
+ * \li Not run in standby mode
+ * \li Disable Watchdog
+ * \li Transmit pause enabled
+ * \li Edge filtering during bus integration enabled
+ * \li Protocol exception handling enabled
+ * \li Automatic retransmission enabled
+ * \li Clock stop request disabled
+ * \li Clock stop acknowledge disabled
+ * \li Timestamp Counter Prescaler 1
+ * \li Timeout Period with 0xFFFF
+ * \li Timeout Mode: Continuous operation
+ * \li Disable Timeout
+ * \li Transmitter Delay Compensation Offset is 0
+ * \li Transmitter Delay Compensation Filter Window Length is 0
+ * \li Reject nonmatching standard frames
+ * \li Reject nonmatching extended frames
+ * \li Reject remote standard frames
+ * \li Reject remote extended frames
+ * \li Extended ID Mask is 0x1FFFFFFF
+ * \li Rx FIFO 0 Operation Mode: overwrite
+ * \li Disable Rx FIFO 0 Watermark
+ * \li Rx FIFO 1 Operation Mode: overwrite
+ * \li Disable Rx FIFO 1 Watermark
+ * \li Tx FIFO/Queue Mode: FIFO
+ * \li Disable Tx Event FIFO Watermark
+ *
+ * \param[out] config Pointer to configuration struct to initialize to
+ * default values
+ */
+static inline void mcan_get_config_defaults(struct mcan_config *const config)
+{
+ /* Sanity check arguments */
+ Assert(config);
+
+ /* Default configuration values */
+ config->run_in_standby = false;
+ config->watchdog_configuration = 0x00;
+ config->transmit_pause = true;
+ config->edge_filtering = true;
+ config->protocol_exception_handling = true;
+ config->automatic_retransmission = true;
+ config->clock_stop_request = false;
+ config->clock_stop_acknowledge = false;
+ config->timestamp_prescaler = 0;
+ config->timeout_period = 0xFFFF;
+ config->timeout_mode = MCAN_TIMEOUT_CONTINUES;
+ config->timeout_enable = false;
+ config->tdc_enable = false;
+ config->delay_compensation_offset = 0;
+#if (SAMV71B || SAME70B || SAMV70B)
+ config->delay_compensation_filter_window_length = 0;
+#endif
+ config->nonmatching_frames_action_standard = MCAN_NONMATCHING_FRAMES_REJECT;
+ config->nonmatching_frames_action_extended = MCAN_NONMATCHING_FRAMES_REJECT;
+ config->remote_frames_standard_reject = true;
+ config->remote_frames_extended_reject = true;
+ config->extended_id_mask = 0x1FFFFFFF;
+ config->rx_fifo_0_overwrite = true;
+ config->rx_fifo_0_watermark = 0;
+ config->rx_fifo_1_overwrite = true;
+ config->rx_fifo_1_watermark = 0;
+ config->tx_queue_mode = false;
+ config->tx_event_fifo_watermark = 0;
+}
+
+void mcan_init(struct mcan_module *const module_inst, Mcan *hw, struct mcan_config *config);
+void mcan_start(struct mcan_module *const module_inst);
+void mcan_stop(struct mcan_module *const module_inst);
+void mcan_enable_fd_mode(struct mcan_module *const module_inst);
+void mcan_disable_fd_mode(struct mcan_module *const module_inst);
+void mcan_enable_restricted_operation_mode(struct mcan_module *const module_inst);
+void mcan_disable_restricted_operation_mode(struct mcan_module *const module_inst);
+
+void mcan_enable_bus_monitor_mode(struct mcan_module *const module_inst);
+void mcan_disable_bus_monitor_mode(struct mcan_module *const module_inst);
+void mcan_enable_sleep_mode(struct mcan_module *const module_inst);
+void mcan_disable_sleep_mode(struct mcan_module *const module_inst);
+void mcan_enable_test_mode(struct mcan_module *const module_inst);
+void mcan_disable_test_mode(struct mcan_module *const module_inst);
+
+/**
+ * \brief Can read timestamp count value.
+ *
+ * \param[in] module_inst Pointer to the MCAN software instance struct
+ *
+ * \return Timestamp count value.
+ */
+static inline uint16_t mcan_read_timestamp_count_value(struct mcan_module *const module_inst)
+{
+ return module_inst->hw->MCAN_TSCV;
+}
+
+/**
+ * \brief Can read timeout count value.
+ *
+ * \param[in] module_inst Pointer to the MCAN software instance struct
+ *
+ * \return Timeout count value.
+ */
+static inline uint16_t mcan_read_timeout_count_value(struct mcan_module *const module_inst)
+{
+ return module_inst->hw->MCAN_TOCV;
+}
+
+/**
+ * \brief Can read error count.
+ *
+ * \param[in] module_inst Pointer to the MCAN software instance struct
+ *
+ * \return Error count value.
+ */
+static inline uint32_t mcan_read_error_count(struct mcan_module *const module_inst)
+{
+ return module_inst->hw->MCAN_ECR;
+}
+
+/**
+ * \brief Can read protocol status.
+ *
+ * \param[in] module_inst Pointer to the MCAN software instance struct
+ *
+ * \return protocol status value.
+ */
+static inline uint32_t mcan_read_protocal_status(struct mcan_module *const module_inst)
+{
+ return module_inst->hw->MCAN_PSR;
+}
+
+/** @} */
+
+/**
+ * \name Rx Handling
+ * @{
+ */
+
+/**
+ * \brief Read high priority message status.
+ *
+ * \param[in] module_inst Pointer to the MCAN software instance struct
+ *
+ * \return High priority message status value.
+ */
+static inline uint32_t mcan_read_high_priority_message_status(struct mcan_module *const module_inst)
+{
+ return module_inst->hw->MCAN_HPMS;
+}
+
+/**
+ * \brief Get Rx buffer status.
+ *
+ * \param[in] module_inst Pointer to the MCAN software instance struct
+ * \param[in] index Index offset in Rx buffer
+ *
+ * \return Rx buffer status value.
+ *
+ * \retval true Rx Buffer updated from new message.
+ * \retval false Rx Buffer not updated.
+ */
+static inline bool mcan_rx_get_buffer_status(struct mcan_module *const module_inst, uint32_t index)
+{
+ if (index < 32) {
+ if (module_inst->hw->MCAN_NDAT1 & (1 << index)) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ index -= 32;
+ if (module_inst->hw->MCAN_NDAT2 & (1 << index)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
+
+/**
+ * \brief Clear Rx buffer status.
+ *
+ * \param[in] module_inst Pointer to the MCAN software instance struct
+ * \param[in] index Index offset in Rx buffer
+ *
+ */
+static inline void mcan_rx_clear_buffer_status(struct mcan_module *const module_inst, uint32_t index)
+{
+ if (index < 32) {
+ module_inst->hw->MCAN_NDAT1 = (1 << index);
+ } else {
+ index -= 32;
+ module_inst->hw->MCAN_NDAT2 = (1 << index);
+ }
+}
+
+/**
+ * \brief Get Rx FIFO status.
+ *
+ * \param[in] module_inst Pointer to the MCAN software instance struct
+ * \param[in] fifo_number Rx FIFO 0 or 1
+ *
+ * \return Rx FIFO status value.
+ */
+static inline uint32_t mcan_rx_get_fifo_status(struct mcan_module *const module_inst, bool fifo_number)
+{
+ if (!fifo_number) {
+ return module_inst->hw->MCAN_RXF0S;
+ } else {
+ return module_inst->hw->MCAN_RXF1S;
+ }
+}
+
+/**
+ * \brief Set Rx acknowledge.
+ *
+ * \param[in] module_inst Pointer to the MCAN software instance struct
+ * \param[in] fifo_number Rx FIFO 0 or 1
+ * \param[in] index Index offset in FIFO
+ */
+static inline void mcan_rx_fifo_acknowledge(struct mcan_module *const module_inst, bool fifo_number, uint32_t index)
+{
+ if (!fifo_number) {
+ module_inst->hw->MCAN_RXF0A = MCAN_RXF0A_F0AI(index);
+ } else {
+ module_inst->hw->MCAN_RXF1A = MCAN_RXF1A_F1AI(index);
+ }
+}
+
+/**
+ * \brief Get the standard message filter default value.
+ *
+ * The default configuration is as follows:
+ * \li Classic filter: SFID1 = filter, SFID2 = mask
+ * \li Store in Rx FIFO 0 if filter matches
+ * \li SFID2 = 0x7FFul
+ * \li SFID1 = 0x0ul
+ *
+ * \param[out] sd_filter Pointer to standard filter element struct to initialize to default values
+ */
+static inline void mcan_get_standard_message_filter_element_default(struct mcan_standard_message_filter_element *sd_filter)
+{
+ sd_filter->S0.reg = MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFID2_Msk |
+ MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFID1(0) |
+ MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFEC(
+ MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFEC_STF0M_Val) |
+ MCAN_STANDARD_MESSAGE_FILTER_ELEMENT_S0_SFT_CLASSIC;
+}
+
+enum status_code mcan_set_rx_standard_filter(struct mcan_module *const module_inst, struct mcan_standard_message_filter_element *sd_filter, uint32_t index);
+
+/**
+ * \brief Get the extended message filter default value.
+ *
+ * The default configuration is as follows:
+ * \li Classic filter: SFID1 = filter, SFID2 = mask
+ * \li Store in Rx FIFO 1 if filter matches
+ * \li SFID2 = 0x1FFFFFFFul
+ * \li SFID1 = 0x0ul
+ *
+ * \param[out] et_filter Pointer to extended filter element struct to initialize to default values
+ */
+static inline void mcan_get_extended_message_filter_element_default(struct mcan_extended_message_filter_element *et_filter)
+{
+ et_filter->F0.reg = MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F0_EFID1(0) |
+ MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F0_EFEC(
+ MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F0_EFEC_STF1M_Val);
+ et_filter->F1.reg = MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F1_EFID2_Msk |
+ MCAN_EXTENDED_MESSAGE_FILTER_ELEMENT_F1_EFT_CLASSIC;
+}
+
+enum status_code mcan_set_rx_extended_filter(struct mcan_module *const module_inst, struct mcan_extended_message_filter_element *et_filter, uint32_t index);
+
+enum status_code mcan_get_rx_buffer_element(struct mcan_module *const module_inst, struct mcan_rx_element *rx_element, uint32_t index);
+
+enum status_code mcan_get_rx_fifo_0_element(struct mcan_module *const module_inst, struct mcan_rx_element *rx_element, uint32_t index);
+
+enum status_code mcan_get_rx_fifo_1_element(struct mcan_module *const module_inst, struct mcan_rx_element *rx_element, uint32_t index);
+
+/**
+ * \brief Get Tx FIFO/Queue status.
+ *
+ * \param[in] module_inst Pointer to the MCAN software instance struct
+ *
+ * \return Tx FIFO/Queue status value.
+ */
+static inline uint32_t mcan_tx_get_fifo_queue_status(struct mcan_module *const module_inst)
+{
+ return module_inst->hw->MCAN_TXFQS;
+}
+
+/**
+ * \brief Get Tx buffer request pending status.
+ *
+ * \param[in] module_inst Pointer to the MCAN software instance struct
+ *
+ * \return Bit mask of Tx buffer request pending status value.
+ */
+static inline uint32_t mcan_tx_get_pending_status(struct mcan_module *const module_inst)
+{
+ return module_inst->hw->MCAN_TXBRP;
+}
+
+/**
+ * \brief Tx buffer add transfer request.
+ *
+ * \param[in] module_inst Pointer to the MCAN software instance struct
+ * \param[in] trig_mask The mask value to trigger transfer buffer
+ *
+ * \return Status of the result.
+ *
+ * \retval STATUS_OK Set the transfer request.
+ * \retval STATUS_ERR_BUSY The module is in configuration.
+ */
+static inline enum status_code mcan_tx_transfer_request(struct mcan_module *const module_inst, uint32_t trig_mask)
+{
+ if (module_inst->hw->MCAN_CCCR & MCAN_CCCR_CCE) {
+ return ERR_BUSY;
+ }
+ module_inst->hw->MCAN_TXBAR = trig_mask;
+ return STATUS_OK;
+}
+
+/**
+ * \brief Set Tx Queue operation.
+ *
+ * \param[in] module_inst Pointer to the MCAN software instance struct
+ * \param[in] trig_mask The mask value to cancel transfer buffer
+ *
+ * \return Status of the result.
+ *
+ * \retval STATUS_OK Set the transfer request.
+ * \retval STATUS_BUSY The module is in configuration.
+ */
+static inline enum status_code mcan_tx_cancel_request(struct mcan_module *const module_inst, uint32_t trig_mask)
+{
+ if (module_inst->hw->MCAN_CCCR & MCAN_CCCR_CCE) {
+ return STATUS_ERR_BUSY;
+ }
+ module_inst->hw->MCAN_TXBCR = trig_mask;
+ return STATUS_OK;
+}
+
+/**
+ * \brief Get Tx transmission status.
+ *
+ * \param[in] module_inst Pointer to the MCAN software instance struct
+ *
+ * \return Bit mask of Tx transmission status value.
+ */
+static inline uint32_t mcan_tx_get_transmission_status(struct mcan_module *const module_inst)
+{
+ return module_inst->hw->MCAN_TXBTO;
+}
+
+/**
+ * \brief Get Tx cancellation status.
+ *
+ * \param[in] module_inst Pointer to the MCAN software instance struct
+ *
+ * \return Bit mask of Tx cancellation status value.
+ */
+static inline uint32_t mcan_tx_get_cancellation_status(struct mcan_module *const module_inst)
+{
+ return module_inst->hw->MCAN_TXBCF;
+}
+
+/**
+ * \brief Get Tx event FIFO status.
+ *
+ * \param[in] module_inst Pointer to the MCAN software instance struct
+ *
+ * \return Tx event FIFO status value.
+ */
+static inline uint32_t mcan_tx_get_event_fifo_status(struct mcan_module *const module_inst)
+{
+ return module_inst->hw->MCAN_TXEFS;
+}
+
+/**
+ * \brief Set Tx Queue operation.
+ *
+ * \param[in] module_inst Pointer to the MCAN software instance struct
+ * \param[in] index Index for the transfer FIFO
+ */
+static inline void mcan_tx_event_fifo_acknowledge(struct mcan_module *const module_inst, uint32_t index)
+{
+ module_inst->hw->MCAN_TXEFA = MCAN_TXEFA_EFAI(index);
+}
+
+/**
+ * \brief Get the default transfer buffer element.
+ *
+ * The default configuration is as follows:
+ * \li 11-bit standard identifier
+ * \li Transmit data frame
+ * \li ID = 0x0ul
+ * \li Store Tx events
+ * \li Frame transmitted in Classic MCAN format
+ * \li Data Length Code is 8
+ *
+ * \param[out] tx_element Pointer to transfer element struct to initialize to default values
+ */
+static inline void mcan_get_tx_buffer_element_defaults(struct mcan_tx_element *tx_element)
+{
+ tx_element->T0.reg = 0;
+ tx_element->T1.reg = MCAN_TX_ELEMENT_T1_EFC |
+ MCAN_TX_ELEMENT_T1_DLC(MCAN_TX_ELEMENT_T1_DLC_DATA8_Val);
+}
+
+enum status_code mcan_set_tx_buffer_element(
+ struct mcan_module *const module_inst,
+ struct mcan_tx_element *tx_element, uint32_t index);
+
+enum status_code mcan_get_tx_event_fifo_element(
+ struct mcan_module *const module_inst,
+ struct mcan_tx_event_element *tx_event_element, uint32_t index);
+
+/**
+ * \brief Can module interrupt source.
+ *
+ * Enum for the interrupt source.
+ */
+enum mcan_interrupt_source {
+ /** Rx FIFO 0 New Message Interrupt Enable. */
+ MCAN_RX_FIFO_0_NEW_MESSAGE = MCAN_IE_RF0NE,
+ /** Rx FIFO 0 Watermark Reached Interrupt Enable. */
+ MCAN_RX_FIFO_0_WATERMARK = MCAN_IE_RF0WE,
+ /** Rx FIFO 0 Full Interrupt Enable. */
+ MCAN_RX_FIFO_0_FULL = MCAN_IE_RF0FE,
+ /** Rx FIFO 0 Message Lost Interrupt Enable. */
+ MCAN_RX_FIFO_0_LOST_MESSAGE = MCAN_IE_RF0LE,
+ /** Rx FIFO 1 New Message Interrupt Enable. */
+ MCAN_RX_FIFO_1_NEW_MESSAGE = MCAN_IE_RF1NE,
+ /** Rx FIFO 1 Watermark Reached Interrupt Enable. */
+ MCAN_RX_FIFO_1_WATERMARK = MCAN_IE_RF1WE,
+ /** Rx FIFO 1 Full Interrupt Enable. */
+ MCAN_RX_FIFO_1_FULL = MCAN_IE_RF1FE,
+ /** Rx FIFO 1 Message Lost Interrupt Enable. */
+ MCAN_RX_FIFO_1_MESSAGE_LOST = MCAN_IE_RF1LE,
+ /** High Priority Message Interrupt Enable. */
+ MCAN_RX_HIGH_PRIORITY_MESSAGE = MCAN_IE_HPME,
+ /** Transmission Completed Interrupt Enable. */
+ MCAN_TIMESTAMP_COMPLETE = MCAN_IE_TCE,
+ /** Transmission Cancellation Finished Interrupt Enable. */
+ MCAN_TX_CANCELLATION_FINISH = MCAN_IE_TCFE,
+ /** Tx FIFO Empty Interrupt Enable. */
+ MCAN_TX_FIFO_EMPTY = MCAN_IE_TFEE,
+ /** Tx Event FIFO New Entry Interrupt Enable. */
+ MCAN_TX_EVENT_FIFO_NEW_ENTRY = MCAN_IE_TEFNE,
+ /** Tx Event FIFO Watermark Reached Interrupt Enable. */
+ MCAN_TX_EVENT_FIFO_WATERMARK = MCAN_IE_TEFWE,
+ /** Tx Event FIFO Full Interrupt Enable. */
+ MCAN_TX_EVENT_FIFO_FULL = MCAN_IE_TEFFE,
+ /** Tx Event FIFO Element Lost Interrupt Enable. */
+ MCAN_TX_EVENT_FIFO_ELEMENT_LOST = MCAN_IE_TEFLE,
+ /** Timestamp Wraparound Interrupt Enable. */
+ MCAN_TIMESTAMP_WRAPAROUND = MCAN_IE_TSWE,
+ /** Message RAM Access Failure Interrupt Enable. */
+ MCAN_MESSAGE_RAM_ACCESS_FAILURE = MCAN_IE_MRAFE,
+ /** Timeout Occurred Interrupt Enable. */
+ MCAN_TIMEOUT_OCCURRED = MCAN_IE_TOOE,
+ /** Message stored to Dedicated Rx Buffer Interrupt Enable. */
+ MCAN_RX_BUFFER_NEW_MESSAGE = MCAN_IE_DRXE,
+ /** Error Logging Overflow Interrupt Enable. */
+ MCAN_ERROR_LOGGING_OVERFLOW = MCAN_IE_ELOE,
+ /** Error Passive Interrupt Enable. */
+ MCAN_ERROR_PASSIVE = MCAN_IE_EPE,
+ /** Warning Status Interrupt Enable. */
+ MCAN_WARNING_STATUS = MCAN_IE_EWE,
+ /** Bus_Off Status Interrupt Enable. */
+ MCAN_BUS_OFF = MCAN_IE_BOE,
+ /** Watchdog Interrupt Enable. */
+ MCAN_WATCHDOG = MCAN_IE_WDIE,
+ /**CRC Error Interrupt Enable */
+ MCAN_CRC_ERROR = MCAN_IE_CRCEE,
+ /** Bit Error Interrupt Enable. */
+ MCAN_BIT_ERROR = MCAN_IE_BEE,
+ /** Acknowledge Error Interrupt Enable . */
+ MCAN_ACKNOWLEDGE_ERROR = MCAN_IE_ACKEE,
+ /** Format Error Interrupt Enable */
+ MCAN_FORMAT_ERROR = MCAN_IE_FOEE,
+ /** Stuff Error Interrupt Enable */
+ MCAN_STUFF_ERROR = MCAN_IE_STEE
+};
+
+/**
+ * \brief Enable MCAN interrupt.
+ *
+ * \param[in] module_inst Pointer to the MCAN software instance struct
+ * \param[in] source Interrupt source type
+ */
+static inline void mcan_enable_interrupt(struct mcan_module *const module_inst, const enum mcan_interrupt_source source)
+{
+ module_inst->hw->MCAN_IE |= source;
+}
+
+/**
+ * \brief Disable MCAN interrupt.
+ *
+ * \param[in] module_inst Pointer to the MCAN software instance struct
+ * \param[in] source Interrupt source type
+ */
+static inline void mcan_disable_interrupt(struct mcan_module *const module_inst, const enum mcan_interrupt_source source)
+{
+ module_inst->hw->MCAN_IE &= ~source;
+}
+
+/**
+ * \brief Get MCAN interrupt status.
+ *
+ * \param[in] module_inst Pointer to the MCAN software instance struct
+ */
+static inline uint32_t mcan_read_interrupt_status(struct mcan_module *const module_inst)
+{
+ return module_inst->hw->MCAN_IR;
+}
+
+/**
+ * \brief Clear MCAN interrupt status.
+ *
+ * \param[in] module_inst Pointer to the MCAN software instance struct
+ * \param[in] source Interrupt source type
+ *
+ * \return Bit mask of interrupt status value.
+ */
+static inline void mcan_clear_interrupt_status(struct mcan_module *const module_inst, const enum mcan_interrupt_source source)
+{
+ module_inst->hw->MCAN_IR = source;
+}
+
+#endif
+
+#endif /* SRC_HARDWARE_CANDRIVER_H_ */