You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2021/12/08 05:36:18 UTC
[incubator-nuttx] branch master updated: samv7: enable MCAN driver support for both rev A and rev B
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new ae57492 samv7: enable MCAN driver support for both rev A and rev B
ae57492 is described below
commit ae57492189a7f90effce53edde37db3c2630c129
Author: Michal Lenc <mi...@seznam.cz>
AuthorDate: Sun Dec 5 15:14:17 2021 +0100
samv7: enable MCAN driver support for both rev A and rev B
This commit enables the MCAN driver to function with both rev A and rev B
version of the chip. The version of the chip is selected automtically from
SAM_CHIPID_CIDR register so there is no need to predefined it in the
configuration.
The functonality was tested on rev B version of the chip. The rev A was
not tested since I do not have the functional board but the code remains
the same as in the previous NuttX version so it should not cause any
additional troubles.
The code is co-authored by Miloš Pokorný who wrote the initial transition
to rev B of the chip.
Signed-off-by: Michal Lenc <mi...@seznam.cz>
Co-authored-by: Miloš Pokorný <mi...@seznam.cz>
---
arch/arm/src/samv7/hardware/sam_mcan.h | 257 ++++++++-----------
arch/arm/src/samv7/sam_mcan.c | 442 +++++++++++++++++++++++----------
2 files changed, 413 insertions(+), 286 deletions(-)
diff --git a/arch/arm/src/samv7/hardware/sam_mcan.h b/arch/arm/src/samv7/hardware/sam_mcan.h
index 28ff965..c6829f6 100644
--- a/arch/arm/src/samv7/hardware/sam_mcan.h
+++ b/arch/arm/src/samv7/hardware/sam_mcan.h
@@ -38,11 +38,13 @@
/* 0x0000-0x0004 Reserved */
#define SAM_MCAN_CUST_OFFSET 0x0008 /* Customer Register */
-#define SAM_MCAN_FBTP_OFFSET 0x000c /* Fast Bit Timing and Prescaler Register */
+#define SAM_MCAN_REVA_FBTP_OFFSET 0x000c /* Fast Bit Timing and Prescaler Register (rev A) */
+#define SAM_MCAN_DBTP_OFFSET 0x000c /* Data Bit Timing and Prescaler Register (rev B) */
#define SAM_MCAN_TEST_OFFSET 0x0010 /* Test Register */
#define SAM_MCAN_RWD_OFFSET 0x0014 /* RAM Watchdog Register */
#define SAM_MCAN_CCCR_OFFSET 0x0018 /* CC Control Register */
-#define SAM_MCAN_BTP_OFFSET 0x001c /* Bit Timing and Prescaler Register */
+#define SAM_MCAN_REVA_BTP_OFFSET 0x001c /* Bit Timing and Prescaler Register (rev A) */
+#define SAM_MCAN_NBTP_OFFSET 0x001c /* Nominal Bit Timing and Prescaler Register (rev B) */
#define SAM_MCAN_TSCC_OFFSET 0x0020 /* Timestamp Counter Configuration Register */
#define SAM_MCAN_TSCV_OFFSET 0x0024 /* Timestamp Counter Value Register */
#define SAM_MCAN_TOCC_OFFSET 0x0028 /* Timeout Counter Configuration Register */
@@ -88,120 +90,44 @@
#define SAM_MCAN_TXEFA_OFFSET 0x00f8 /* Transmit Event FIFO Acknowledge Register */
/* 0x00fc Reserved */
-/* MCAN register addresses **************************************************/
-
-#define SAM_MCAN0_CUST (SAM_MCAN0_BASE+SAM_MCAN_CUST_OFFSET)
-#define SAM_MCAN0_FBTP (SAM_MCAN0_BASE+SAM_MCAN_FBTP_OFFSET)
-#define SAM_MCAN0_TEST (SAM_MCAN0_BASE+SAM_MCAN_TEST_OFFSET)
-#define SAM_MCAN0_RWD (SAM_MCAN0_BASE+SAM_MCAN_RWD_OFFSET)
-#define SAM_MCAN0_CCCR (SAM_MCAN0_BASE+SAM_MCAN_CCCR_OFFSET)
-#define SAM_MCAN0_BTP (SAM_MCAN0_BASE+SAM_MCAN_BTP_OFFSET)
-#define SAM_MCAN0_TSCC (SAM_MCAN0_BASE+SAM_MCAN_TSCC_OFFSET)
-#define SAM_MCAN0_TSCV (SAM_MCAN0_BASE+SAM_MCAN_TSCV_OFFSET)
-#define SAM_MCAN0_TOCC (SAM_MCAN0_BASE+SAM_MCAN_TOCC_OFFSET)
-#define SAM_MCAN0_TOCV (SAM_MCAN0_BASE+SAM_MCAN_TOCV_OFFSET)
-#define SAM_MCAN0_ECR (SAM_MCAN0_BASE+SAM_MCAN_ECR_OFFSET)
-#define SAM_MCAN0_PSR (SAM_MCAN0_BASE+SAM_MCAN_PSR_OFFSET)
-#define SAM_MCAN0_IR (SAM_MCAN0_BASE+SAM_MCAN_IR_OFFSET)
-#define SAM_MCAN0_IE (SAM_MCAN0_BASE+SAM_MCAN_IE_OFFSET)
-#define SAM_MCAN0_ILS (SAM_MCAN0_BASE+SAM_MCAN_ILS_OFFSET)
-#define SAM_MCAN0_ILE (SAM_MCAN0_BASE+SAM_MCAN_ILE_OFFSET)
-#define SAM_MCAN0_GFC (SAM_MCAN0_BASE+SAM_MCAN_GFC_OFFSET)
-#define SAM_MCAN0_SIDFC (SAM_MCAN0_BASE+SAM_MCAN_SIDFC_OFFSET)
-#define SAM_MCAN0_XIDFC (SAM_MCAN0_BASE+SAM_MCAN_XIDFC_OFFSET)
-#define SAM_MCAN0_XIDAM (SAM_MCAN0_BASE+SAM_MCAN_XIDAM_OFFSET)
-#define SAM_MCAN0_HPMS (SAM_MCAN0_BASE+SAM_MCAN_HPMS_OFFSET)
-#define SAM_MCAN0_NDAT1 (SAM_MCAN0_BASE+SAM_MCAN_NDAT1_OFFSET)
-#define SAM_MCAN0_NDAT2 (SAM_MCAN0_BASE+SAM_MCAN_NDAT2_OFFSET)
-#define SAM_MCAN0_RXF0C (SAM_MCAN0_BASE+SAM_MCAN_RXF0C_OFFSET)
-#define SAM_MCAN0_RXF0S (SAM_MCAN0_BASE+SAM_MCAN_RXF0S_OFFSET)
-#define SAM_MCAN0_RXF0A (SAM_MCAN0_BASE+SAM_MCAN_RXF0A_OFFSET)
-#define SAM_MCAN0_RXBC (SAM_MCAN0_BASE+SAM_MCAN_RXBC_OFFSET)
-#define SAM_MCAN0_RXF1C (SAM_MCAN0_BASE+SAM_MCAN_RXF1C_OFFSET)
-#define SAM_MCAN0_RXF1S (SAM_MCAN0_BASE+SAM_MCAN_RXF1S_OFFSET)
-#define SAM_MCAN0_RXF1A (SAM_MCAN0_BASE+SAM_MCAN_RXF1A_OFFSET)
-#define SAM_MCAN0_RXESC (SAM_MCAN0_BASE+SAM_MCAN_RXESC_OFFSET)
-#define SAM_MCAN0_TXBC (SAM_MCAN0_BASE+SAM_MCAN_TXBC_OFFSET)
-#define SAM_MCAN0_TXFQS (SAM_MCAN0_BASE+SAM_MCAN_TXFQS_OFFSET)
-#define SAM_MCAN0_TXESC (SAM_MCAN0_BASE+SAM_MCAN_TXESC_OFFSET)
-#define SAM_MCAN0_TXBRP (SAM_MCAN0_BASE+SAM_MCAN_TXBRP_OFFSET)
-#define SAM_MCAN0_TXBAR (SAM_MCAN0_BASE+SAM_MCAN_TXBAR_OFFSET)
-#define SAM_MCAN0_TXBCR (SAM_MCAN0_BASE+SAM_MCAN_TXBCR_OFFSET)
-#define SAM_MCAN0_TXBTO (SAM_MCAN0_BASE+SAM_MCAN_TXBTO_OFFSET)
-#define SAM_MCAN0_TXBCF (SAM_MCAN0_BASE+SAM_MCAN_TXBCF_OFFSET)
-#define SAM_MCAN0_TXBTIE (SAM_MCAN0_BASE+SAM_MCAN_TXBTIE_OFFSET)
-#define SAM_MCAN0_TXBCIE (SAM_MCAN0_BASE+SAM_MCAN_TXBCIE_OFFSET)
-#define SAM_MCAN0_TXEFC (SAM_MCAN0_BASE+SAM_MCAN_TXEFC_OFFSET)
-#define SAM_MCAN0_TXEFS (SAM_MCAN0_BASE+SAM_MCAN_TXEFS_OFFSET)
-#define SAM_MCAN0_TXEFA (SAM_MCAN0_BASE+SAM_MCAN_TXEFA_OFFSET)
-
-#define SAM_MCAN1_CUST (SAM_MCAN1_BASE+SAM_MCAN_CUST_OFFSET)
-#define SAM_MCAN1_FBTP (SAM_MCAN1_BASE+SAM_MCAN_FBTP_OFFSET)
-#define SAM_MCAN1_TEST (SAM_MCAN1_BASE+SAM_MCAN_TEST_OFFSET)
-#define SAM_MCAN1_RWD (SAM_MCAN1_BASE+SAM_MCAN_RWD_OFFSET)
-#define SAM_MCAN1_CCCR (SAM_MCAN1_BASE+SAM_MCAN_CCCR_OFFSET)
-#define SAM_MCAN1_BTP (SAM_MCAN1_BASE+SAM_MCAN_BTP_OFFSET)
-#define SAM_MCAN1_TSCC (SAM_MCAN1_BASE+SAM_MCAN_TSCC_OFFSET)
-#define SAM_MCAN1_TSCV (SAM_MCAN1_BASE+SAM_MCAN_TSCV_OFFSET)
-#define SAM_MCAN1_TOCC (SAM_MCAN1_BASE+SAM_MCAN_TOCC_OFFSET)
-#define SAM_MCAN1_TOCV (SAM_MCAN1_BASE+SAM_MCAN_TOCV_OFFSET)
-#define SAM_MCAN1_ECR (SAM_MCAN1_BASE+SAM_MCAN_ECR_OFFSET)
-#define SAM_MCAN1_PSR (SAM_MCAN1_BASE+SAM_MCAN_PSR_OFFSET)
-#define SAM_MCAN1_IR (SAM_MCAN1_BASE+SAM_MCAN_IR_OFFSET)
-#define SAM_MCAN1_IE (SAM_MCAN1_BASE+SAM_MCAN_IE_OFFSET)
-#define SAM_MCAN1_ILS (SAM_MCAN1_BASE+SAM_MCAN_ILS_OFFSET)
-#define SAM_MCAN1_ILE (SAM_MCAN1_BASE+SAM_MCAN_ILE_OFFSET)
-#define SAM_MCAN1_GFC (SAM_MCAN1_BASE+SAM_MCAN_GFC_OFFSET)
-#define SAM_MCAN1_SIDFC (SAM_MCAN1_BASE+SAM_MCAN_SIDFC_OFFSET)
-#define SAM_MCAN1_XIDFC (SAM_MCAN1_BASE+SAM_MCAN_XIDFC_OFFSET)
-#define SAM_MCAN1_XIDAM (SAM_MCAN1_BASE+SAM_MCAN_XIDAM_OFFSET)
-#define SAM_MCAN1_HPMS (SAM_MCAN1_BASE+SAM_MCAN_HPMS_OFFSET)
-#define SAM_MCAN1_NDAT1 (SAM_MCAN1_BASE+SAM_MCAN_NDAT1_OFFSET)
-#define SAM_MCAN1_NDAT2 (SAM_MCAN1_BASE+SAM_MCAN_NDAT2_OFFSET)
-#define SAM_MCAN1_RXF0C (SAM_MCAN1_BASE+SAM_MCAN_RXF0C_OFFSET)
-#define SAM_MCAN1_RXF0S (SAM_MCAN1_BASE+SAM_MCAN_RXF0S_OFFSET)
-#define SAM_MCAN1_RXF0A (SAM_MCAN1_BASE+SAM_MCAN_RXF0A_OFFSET)
-#define SAM_MCAN1_RXBC (SAM_MCAN1_BASE+SAM_MCAN_RXBC_OFFSET)
-#define SAM_MCAN1_RXF1C (SAM_MCAN1_BASE+SAM_MCAN_RXF1C_OFFSET)
-#define SAM_MCAN1_RXF1S (SAM_MCAN1_BASE+SAM_MCAN_RXF1S_OFFSET)
-#define SAM_MCAN1_RXF1A (SAM_MCAN1_BASE+SAM_MCAN_RXF1A_OFFSET)
-#define SAM_MCAN1_RXESC (SAM_MCAN1_BASE+SAM_MCAN_RXESC_OFFSET)
-#define SAM_MCAN1_TXBC (SAM_MCAN1_BASE+SAM_MCAN_TXBC_OFFSET)
-#define SAM_MCAN1_TXFQS (SAM_MCAN1_BASE+SAM_MCAN_TXFQS_OFFSET)
-#define SAM_MCAN1_TXESC (SAM_MCAN1_BASE+SAM_MCAN_TXESC_OFFSET)
-#define SAM_MCAN1_TXBRP (SAM_MCAN1_BASE+SAM_MCAN_TXBRP_OFFSET)
-#define SAM_MCAN1_TXBAR (SAM_MCAN1_BASE+SAM_MCAN_TXBAR_OFFSET)
-#define SAM_MCAN1_TXBCR (SAM_MCAN1_BASE+SAM_MCAN_TXBCR_OFFSET)
-#define SAM_MCAN1_TXBTO (SAM_MCAN1_BASE+SAM_MCAN_TXBTO_OFFSET)
-#define SAM_MCAN1_TXBCF (SAM_MCAN1_BASE+SAM_MCAN_TXBCF_OFFSET)
-#define SAM_MCAN1_TXBTIE (SAM_MCAN1_BASE+SAM_MCAN_TXBTIE_OFFSET)
-#define SAM_MCAN1_TXBCIE (SAM_MCAN1_BASE+SAM_MCAN_TXBCIE_OFFSET)
-#define SAM_MCAN1_TXEFC (SAM_MCAN1_BASE+SAM_MCAN_TXEFC_OFFSET)
-#define SAM_MCAN1_TXEFS (SAM_MCAN1_BASE+SAM_MCAN_TXEFS_OFFSET)
-#define SAM_MCAN1_TXEFA (SAM_MCAN1_BASE+SAM_MCAN_TXEFA_OFFSET)
-
/* MCAN register bit definitions ********************************************/
/* Customer Register (32-bit value) */
-/* Fast Bit Timing and Prescaler Register */
-
-#define MCAN_FBTP_FSJW_SHIFT (0) /* Bits 0-1: Fast (Re) Synchronization Jump Width */
-#define MCAN_FBTP_FSJW_MASK (3 << MCAN_FBTP_FSJW_SHIFT)
-# define MCAN_FBTP_FSJW(n) ((uint32_t)(n) << MCAN_FBTP_FSJW_SHIFT)
-#define MCAN_FBTP_FTSEG2_SHIFT (4) /* Bits 4-6: Fast Time Segment After Sample Point */
-#define MCAN_FBTP_FTSEG2_MASK (7 << MCAN_FBTP_FTSEG2_SHIFT)
-# define MCAN_FBTP_FTSEG2(n) ((uint32_t)(n) << MCAN_FBTP_FTSEG2_SHIFT)
-#define MCAN_FBTP_FTSEG1_SHIFT (8) /* Bits 8-11: Fast Time Segment Before Sample Point */
-#define MCAN_FBTP_FTSEG1_MASK (15 << MCAN_FBTP_FTSEG1_SHIFT)
-# define MCAN_FBTP_FTSEG1(n) ((uint32_t)(n) << MCAN_FBTP_FTSEG1_SHIFT)
-#define MCAN_FBTP_FBRP_SHIFT (16) /* Bits 16-20: Fast Baud Rate Prescaler */
-#define MCAN_FBTP_FBRP_MASK (31 << MCAN_FBTP_FBRP_SHIFT)
-# define MCAN_FBTP_FBRP(n) ((uint32_t)(n) << MCAN_FBTP_FBRP_SHIFT)
-#define MCAN_FBTP_TDC (1 << 23) /* Bit: 23: Transceiver Delay Compensation */
-#define MCAN_FBTP_TDCO_SHIFT (24) /* Bits 24-28: Transceiver Delay Compensation Offset */
-#define MCAN_FBTP_TDCO_MASK (31 << MCAN_FBTP_TDC_SHIFT)
-# define MCAN_FBTP_TDCO(n) ((uint32_t)(n) << MCAN_FBTP_TDC_SHIFT)
+/* Fast Bit Timing and Prescaler Register (rev A) */
+
+#define MCAN_REVA_FBTP_FSJW_SHIFT (0) /* Bits 0-1: Fast (Re) Synchronization Jump Width */
+#define MCAN_REVA_FBTP_FSJW_MASK (0x3 << MCAN_REVA_FBTP_FSJW_SHIFT)
+# define MCAN_REVA_FBTP_FSJW(n) ((uint32_t)(n) << MCAN_REVA_FBTP_FSJW_SHIFT)
+#define MCAN_REVA_FBTP_FTSEG2_SHIFT (4) /* Bits 4-6: Fast Time Segment After Sample Point */
+#define MCAN_REVA_FBTP_FTSEG2_MASK (0x7 << MCAN_REVA_FBTP_FTSEG2_SHIFT)
+# define MCAN_REVA_FBTP_FTSEG2(n) ((uint32_t)(n) << MCAN_REVA_FBTP_FTSEG2_SHIFT)
+#define MCAN_REVA_FBTP_FTSEG1_SHIFT (8) /* Bits 8-11: Fast Time Segment Before Sample Point */
+#define MCAN_REVA_FBTP_FTSEG1_MASK (0xf << MCAN_REVA_FBTP_FTSEG1_SHIFT)
+# define MCAN_REVA_FBTP_FTSEG1(n) ((uint32_t)(n) << MCAN_REVA_FBTP_FTSEG1_SHIFT)
+#define MCAN_REVA_FBTP_FBRP_SHIFT (16) /* Bits 16-20: Fast Baud Rate Prescaler */
+#define MCAN_REVA_FBTP_FBRP_MASK (0x1f << MCAN_REVA_FBTP_FBRP_SHIFT)
+# define MCAN_REVA_FBTP_FBRP(n) ((uint32_t)(n) << MCAN_REVA_FBTP_FBRP_SHIFT)
+#define MCAN_REVA_FBTP_TDC (1 << 23) /* Bit: 23: Transceiver Delay Compensation */
+#define MCAN_REVA_FBTP_TDCO_SHIFT (24) /* Bits 24-28: Transceiver Delay Compensation Offset */
+#define MCAN_REVA_FBTP_TDCO_MASK (0x1f << MCAN_REVA_FBTP_TDC_SHIFT)
+# define MCAN_REVA_FBTP_TDCO(n) ((uint32_t)(n) << MCAN_REVA_FBTP_TDC_SHIFT)
+
+/* Data Bit Timing and Prescaler Register (rev B) */
+
+#define MCAN_DBTP_DSJW_SHIFT (0) /* Bits 0-2: Data (Re) Synchronization Jump Width */
+#define MCAN_DBTP_DSJW_MASK (0x7 << MCAN_DBTP_DSJW_SHIFT)
+# define MCAN_DBTP_DSJW(n) ((uint32_t)(n) << MCAN_DBTP_DSJW_SHIFT)
+#define MCAN_DBTP_DTSEG2_SHIFT (4) /* Bits 4-7: Data Time Segment After Sample Point */
+#define MCAN_DBTP_DTSEG2_MASK (0xf << MCAN_DBTP_DTSEG2_SHIFT)
+# define MCAN_DBTP_DTSEG2(n) ((uint32_t)(n) << MCAN_DBTP_DTSEG2_SHIFT)
+#define MCAN_DBTP_DTSEG1_SHIFT (8) /* Bits 8-11: Data Time Segment Before Sample Point */
+#define MCAN_DBTP_DTSEG1_MASK (0x1f << MCAN_DBTP_DTSEG1_SHIFT)
+# define MCAN_DBTP_DTSEG1(n) ((uint32_t)(n) << MCAN_DBTP_DTSEG1_SHIFT)
+#define MCAN_DBTP_DBRP_SHIFT (16) /* Bits 16-20: Data Baud Rate Prescaler */
+#define MCAN_DBTP_DBRP_MASK (0x1f << MCAN_DBTP_DBRP_SHIFT)
+# define MCAN_DBTP_DBRP(n) ((uint32_t)(n) << MCAN_DBTP_DBRP_SHIFT)
+#define MCAN_DBTP_TDC (1 << 23) /* Bit: 23: Transceiver Delay Compensation */
/* Test Register */
@@ -214,9 +140,6 @@
# define MCAN_TEST_TX_RECESSIVE (3 << MCAN_TEST_TX_SHIFT) /* Recessive (1) at CANTX. */
#define MCAN_TEST_RX (1 << 7) /* Bit 7: Receive Pin */
-#define MCAN_TEST_TDCV_SHIFT (8) /* Bits 8-13: Transceiver Delay Compensation Value */
-#define MCAN_TEST_TDCV_MASK (0x3f << MCAN_TEST_TDCV_SHIFT)
-# define MCAN_TEST_TDCV(n) ((uint32_t)(n) << MCAN_TEST_TDCV_SHIFT)
/* RAM Watchdog Register */
@@ -237,37 +160,56 @@
#define MCAN_CCCR_MON (1 << 5) /* Bit 5: Bus Monitoring Mode */
#define MCAN_CCCR_DAR (1 << 6) /* Bit 6: Disable Automatic Retransmission */
#define MCAN_CCCR_TEST (1 << 7) /* Bit 7: Test Mode Enable */
-#define MCAN_CCCR_CME_SHIFT (8) /* Bits 8-9: CAN Mode Enable */
+#define MCAN_CCCR_CME_SHIFT (8) /* Bits 8-9: CAN Mode Enable (rev A) */
#define MCAN_CCCR_CME_MASK (3 << MCAN_CCCR_CME_SHIFT)
# define MCAN_CCCR_CME_ISO11898_1 (0 << MCAN_CCCR_CME_SHIFT) /* CAN operation according to ISO11898-1 enabled */
# define MCAN_CCCR_CME_FD (1 << MCAN_CCCR_CME_SHIFT) /* CAN FD operation enabled */
# define MCAN_CCCR_CME_FD_BSW (2 << MCAN_CCCR_CME_SHIFT) /* CAN FD operation with bit rate switching enabled */
-#define MCAN_CCCR_CMR_SHIFT (10) /* Bits 10-11: CAN Mode Request */
+#define MCAN_CCCR_FDOE (1 << 8) /* Bit 8: CAN FD Operation Enable (rev B) */
+#define MCAN_CCCR_BRSE (1 << 9) /* Bit 9: Bit Rate Switching Enable (rev B) */
+#define MCAN_CCCR_CMR_SHIFT (10) /* Bits 10-11: CAN Mode Request (rev A)*/
#define MCAN_CCCR_CMR_MASK (3 << MCAN_CCCR_CMR_SHIFT)
# define MCAN_CCCR_CMR_NOCHG (0 << MCAN_CCCR_CMR_SHIFT) /* No mode change */
# define MCAN_CCCR_CMR_FD (1 << MCAN_CCCR_CMR_SHIFT) /* Request CAN FD operation */
# define MCAN_CCCR_CMR_FD_BSW (2 << MCAN_CCCR_CMR_SHIFT) /* Request CAN FD operation with bit rate switching */
# define MCAN_CCCR_CMR_ISO11898_1 (3 << MCAN_CCCR_CMR_SHIFT) /* Request CAN operation according ISO11898-1 */
-#define MCAN_CCCR_FDO (1 << 12) /* Bit 12: CAN FD Operation */
+#define MCAN_CCCR_FDO (1 << 12) /* Bit 12: CAN FD Operation (rev A) */
+#define MCAN_CCCR_PXHD (1 << 12) /* Bit 12: Protocol Exception Event Handling (rev B) */
#define MCAN_CCCR_FDBS (1 << 13) /* Bit 13: CAN FD Bit Rate Switching */
+#define MCAN_CCCR_EFBI (1 << 13) /* Bit 13: Edge Filtering during Bus Integration */
#define MCAN_CCCR_TXP (1 << 14) /* Bit 14: Transmit Pause */
-
-/* Bit Timing and Prescaler Register */
-
-#define MCAN_BTP_SJW_SHIFT (0) /* Bits 0-3: (Re) Synchronization Jump Width */
-#define MCAN_BTP_SJW_MASK (15 << MCAN_BTP_SJW_SHIFT)
-# define MCAN_BTP_SJW(n) ((uint32_t)(n) << MCAN_BTP_SJW_SHIFT)
-#define MCAN_BTP_TSEG2_SHIFT (4) /* Bits 4-7: Time Segment After Sample Point */
-#define MCAN_BTP_TSEG2_MASK (15 << MCAN_BTP_TSEG2_SHIFT)
-# define MCAN_BTP_TSEG2(n) ((uint32_t)(n) << MCAN_BTP_TSEG2_SHIFT)
-#define MCAN_BTP_TSEG1_SHIFT (8) /* Bits 8-13: Time Segment Before Sample Point */
-#define MCAN_BTP_TSEG1_MASK (0x3f << MCAN_BTP_TSEG1_SHIFT)
-# define MCAN_BTP_TSEG1(n) ((uint32_t)(n) << MCAN_BTP_TSEG1_SHIFT)
-#define MCAN_BTP_BRP_SHIFT (16) /* Bits 16-25: Baud Rate Prescaler */
-#define MCAN_BTP_BRP_MASK (0x3ff << MCAN_BTP_BRP_SHIFT)
-# define MCAN_BTP_BRP(n) ((uint32_t)(n) << MCAN_BTP_BRP_SHIFT)
+#define MCAN_CCCR_NISO (1 << 15) /* Bit 15: Non-ISO Operation (Bosch FD)*/
+
+/* Bit Timing and Prescaler Register (rev A) */
+
+#define MCAN_REVA_BTP_SJW_SHIFT (0) /* Bits 0-3: (Re) Synchronization Jump Width */
+#define MCAN_REVA_BTP_SJW_MASK (0xf << MCAN_REVA_BTP_SJW_SHIFT)
+# define MCAN_REVA_BTP_SJW(n) ((uint32_t)(n) << MCAN_REVA_BTP_SJW_SHIFT)
+#define MCAN_REVA_BTP_TSEG2_SHIFT (4) /* Bits 4-7: Time Segment After Sample Point */
+#define MCAN_REVA_BTP_TSEG2_MASK (0xf << MCAN_REVA_BTP_TSEG2_SHIFT)
+# define MCAN_REVA_BTP_TSEG2(n) ((uint32_t)(n) << MCAN_REVA_BTP_TSEG2_SHIFT)
+#define MCAN_REVA_BTP_TSEG1_SHIFT (8) /* Bits 8-13: Time Segment Before Sample Point */
+#define MCAN_REVA_BTP_TSEG1_MASK (0x3f << MCAN_REVA_BTP_TSEG1_SHIFT)
+# define MCAN_REVA_BTP_TSEG1(n) ((uint32_t)(n) << MCAN_REVA_BTP_TSEG1_SHIFT)
+#define MCAN_REVA_BTP_BRP_SHIFT (16) /* Bits 16-25: Baud Rate Prescaler */
+#define MCAN_REVA_BTP_BRP_MASK (0x3ff << MCAN_REVA_BTP_BRP_SHIFT)
+# define MCAN_REVA_BTP_BRP(n) ((uint32_t)(n) << MCAN_REVA_BTP_BRP_SHIFT)
+
+/* Nominal Bit Timing and Prescaler Register (rev B) */
+#define MCAN_NBTP_NTSEG2_SHIFT (0) /* Bits 0-6: Nominal Time Segment After Sample Point */
+#define MCAN_NBTP_NTSEG2_MASK (0x7f << MCAN_NBTP_NTSEG2_SHIFT)
+# define MCAN_NBTP_NTSEG2(n) ((uint32_t)(n) << MCAN_NBTP_NTSEG2_SHIFT)
+#define MCAN_NBTP_NTSEG1_SHIFT (8) /* Bits 8-15: Nominal Time Segment Before Sample Point */
+#define MCAN_NBTP_NTSEG1_MASK (0xff << MCAN_NBTP_NTSEG1_SHIFT)
+# define MCAN_NBTP_NTSEG1(n) ((uint32_t)(n) << MCAN_NBTP_NTSEG1_SHIFT)
+#define MCAN_NBTP_NBRP_SHIFT (16) /* Bits 16-24: Nominal Bit Rate Prescaler */
+#define MCAN_NBTP_NBRP_MASK (0x1ff << MCAN_NBTP_NBRP_SHIFT)
+# define MCAN_NBTP_NBRP(n) ((uint32_t)(n) << MCAN_NBTP_NBRP_SHIFT)
+#define MCAN_NBTP_NSJW_SHIFT (25) /* Bits 25-31: Nominal (Re) Synchronization Jump Width */
+#define MCAN_NBTP_NSJW_MASK (0x7f << MCAN_NBTP_NSJW_SHIFT)
+# define MCAN_NBTP_NSJW(n) ((uint32_t)(n) << MCAN_NBTP_NSJW_SHIFT)
/* Timestamp Counter Configuration Register */
@@ -330,7 +272,7 @@
#define MCAN_PSR_EC_NO_CHANGE (7) /* No CAN bus event was detected since last read */
#define MCAN_PSR_LEC_SHIFT (0) /* Bits 0-2: Last Error Code */
-#define MCAN_PSR_LEC_MASK (7 << MCAN_PSR_LEC_SHIFT)
+#define MCAN_PSR_LEC_MASK (0x7 << MCAN_PSR_LEC_SHIFT)
# define MCAN_PSR_LEC(n) ((uint32_t)(n) << MCAN_PSR_LEC_SHIFT) /* See error codes above */
#define MCAN_PSR_ACT_SHIFT (3) /* Bits 3-4: Activity */
@@ -343,16 +285,25 @@
#define MCAN_PSR_EP (1 << 5) /* Bit 5: Error Passive */
#define MCAN_PSR_EW (1 << 6) /* Bit 6: Warning Status */
#define MCAN_PSR_BO (1 << 7) /* Bit 7: Bus_Off Status */
-#define MCAN_PSR_FLEC_SHIFT (8) /* Bits 8-10: Fast Last Error Code */
-#define MCAN_PSR_FLEC_MASK (7 << MCAN_PSR_FLEC_SHIFT)
+#define MCAN_PSR_FLEC_SHIFT (8) /* Bits 8-10: Fast Last Error Code (rev A) */
+#define MCAN_PSR_FLEC_MASK (0x7 << MCAN_PSR_FLEC_SHIFT)
# define MCAN_PSR_FLEC(n) ((uint32_t)(n) << MCAN_PSR_FLEC_SHIFT) /* See error codes above */
+#define MCAN_PSR_DLEC_SHIFT (8) /* Bits 8-10: Data Last Error Code (rev B) */
+#define MCAN_PSR_DLEC_MASK (0x7 << MCAN_PSR_DLEC_SHIFT)
+# define MCAN_PSR_DLEC(n) ((uint32_t)(n) << MCAN_PSR_DLEC_SHIFT) /* See error codes above */
+
#define MCAN_PSR_RESI (1 << 11) /* Bit 11: ESI Flag of Last Received CAN FD Message */
#define MCAN_PSR_RBRS (1 << 12) /* Bit 12: BRS Flag of Last Received CAN FD Message */
-#define MCAN_PSR_REDL (1 << 13) /* Bit 13: Received a CAN FD Message */
+#define MCAN_PSR_REDL (1 << 13) /* Bit 13: Received a CAN FD Message (rev A) */
+#define MCAN_PSR_RFDF (1 << 13) /* Bit 13: Received a CAN FD Message (rev B) */
+#define MCAN_PSR_PXE (1 << 14) /* Bit 14: Protocol Exception Event (rev B) */
+#define MCAN_PSR_TDCV_SHIFT (16) /* Bits 16-22: Transmitter Delay Compensation Value (rev B) */
+#define MCAN_PSR_TDCV_MASK (0x7f << MCAN_PSR_TDCV_SHIFT)
+# define MCAN_PSR_TDCV(n) ((uint32_t)(n) << MCAN_PSR_TDCV_SHIFT)
/* Common bit definitions for Interrupt Register, Interrupt Enable Register,
- * Interrupt Line Select Register
+ * Interrupt, Line Select Register
*/
#define MCAN_INT_RF0N (1 << 0) /* Bit 0: Receive FIFO 0 New Message */
@@ -380,13 +331,17 @@
#define MCAN_INT_EW (1 << 24) /* Bit 24: Warning Status */
#define MCAN_INT_BO (1 << 25) /* Bit 25: Bus_Off Status */
#define MCAN_INT_WDI (1 << 26) /* Bit 26: Watchdog Interrupt */
-#define MCAN_INT_CRCE (1 << 27) /* Bit 27: Receive CRC Error */
-#define MCAN_INT_BE (1 << 28) /* Bit 28: Bit Error */
-#define MCAN_INT_ACKE (1 << 29) /* Bit 29: Acknowledge Error */
-#define MCAN_INT_FOE (1 << 30) /* Bit 30: Format Error */
-#define MCAN_INT_STE (1 << 31) /* Bit 31: Stuff Error */
-
-#define MCAN_INT_ALL (0xffcfffff)
+#define MCAN_INT_CRCE (1 << 27) /* Bit 27: Receive CRC Error (rev A) */
+#define MCAN_INT_PEA (1 << 27) /* Bit 27: Protocol Error in Arbitration Phase (rev B) */
+#define MCAN_INT_BE (1 << 28) /* Bit 28: Bit Error (rev A) */
+#define MCAN_INT_PED (1 << 28) /* Bit 28: Protocol Error in Data Phase (rev B) */
+#define MCAN_INT_ACKE (1 << 29) /* Bit 29: Acknowledge Error (rev A) */
+#define MCAN_INT_ARA (1 << 29) /* Bit 29: Access to Reserved Address (rev B) */
+#define MCAN_INT_FOE (1 << 30) /* Bit 30: Format Error (rev A) */
+#define MCAN_INT_STE (1 << 31) /* Bit 31: Stuff Error (rev A) */
+
+#define MCAN_REVA_INT_ALL (0xffcfffff)
+#define MCAN_REVB_INT_ALL (0x3fcfffff)
/* Interrupt Line Enable Register */
@@ -632,7 +587,7 @@
/* Transmit Buffer Cancellation Finished Interrupt Enable Register */
-#define MCAN_TXBTIE(n) (1 << (n)) /* Cancellation finished interrupt enable for transmit buffer n, n=0-31 */
+#define MCAN_TXBCIE(n) (1 << (n)) /* Cancellation finished interrupt enable for transmit buffer n, n=0-31 */
/* Transmit Event FIFO Configuration Register */
@@ -695,8 +650,10 @@
#define BUFFER_R1_DLC_SHIFT (16) /* Bits 16-19: Date length code */
#define BUFFER_R1_DLC_MASK (15 << BUFFER_R1_DLC_SHIFT)
# define BUFFER_R1_DLC(n) ((uint32_t)(n) << BUFFER_R1_DLC_SHIFT)
-#define BUFFER_R1_BRS (1 << 20) /* Bit 20: Bit Rate Switch */
-#define BUFFER_R1_EDL (1 << 21) /* Bit 21: Extended Data Length */
+#define BUFFER_R1_BRS_SHIFT (20)
+#define BUFFER_R1_EDL_SHIFT (21)
+#define BUFFER_R1_BRS (1 << BUFFER_R1_BRS_SHIFT) /* Bit 20: Bit Rate Switch */
+#define BUFFER_R1_EDL (1 << BUFFER_R1_EDL_SHIFT) /* Bit 21: Extended Data Length */
/* RX buffer/RX FIFOs */
@@ -807,8 +764,4 @@
* Public Data
****************************************************************************/
-/****************************************************************************
- * Public Functions Prototypes
- ****************************************************************************/
-
#endif /* __ARCH_ARM_SRC_SAMV7_HARDWARE_SAM_MCAN_H */
diff --git a/arch/arm/src/samv7/sam_mcan.c b/arch/arm/src/samv7/sam_mcan.c
index ead4a51..3d23705 100644
--- a/arch/arm/src/samv7/sam_mcan.c
+++ b/arch/arm/src/samv7/sam_mcan.c
@@ -35,7 +35,6 @@
#include <inttypes.h>
#include <stdbool.h>
#include <string.h>
-#include <assert.h>
#include <errno.h>
#include <debug.h>
@@ -49,6 +48,7 @@
#include "arm_arch.h"
#include "hardware/sam_matrix.h"
+#include "hardware/sam_chipid.h"
#include "hardware/sam_pinmap.h"
#include "sam_periphclks.h"
#include "sam_gpio.h"
@@ -138,30 +138,30 @@
# define MCAN0_SJW (CONFIG_SAMV7_MCAN0_FSJW - 1)
# if MCAN0_TSEG1 > 63
-# error Invalid MCAN0 TSEG1
+# error Invalid MCAN0 NTSEG1
# endif
# if MCAN0_TSEG2 > 15
-# error Invalid MCAN0 TSEG2
+# error Invalid MCAN0 NTSEG2
# endif
# if MCAN0_SJW > 15
-# error Invalid MCAN0 SJW
+# error Invalid MCAN0 NSJW
# endif
-# define MCAN0_FTSEG1 (CONFIG_SAMV7_MCAN0_FPROPSEG + CONFIG_SAMV7_MCAN0_FPHASESEG1)
-# define MCAN0_FTSEG2 (CONFIG_SAMV7_MCAN0_FPHASESEG2)
-# define MCAN0_FBRP ((uint32_t)(((float) SAMV7_MCANCLK_FREQUENCY / \
- ((float)(MCAN0_FTSEG1 + MCAN0_FTSEG2 + 3) * \
+# define MCAN0_DTSEG1 (CONFIG_SAMV7_MCAN0_FPROPSEG + CONFIG_SAMV7_MCAN0_FPHASESEG1)
+# define MCAN0_DTSEG2 (CONFIG_SAMV7_MCAN0_FPHASESEG2)
+# define MCAN0_DBRP ((uint32_t)(((float) SAMV7_MCANCLK_FREQUENCY / \
+ ((float)(MCAN0_DTSEG1 + MCAN0_DTSEG2 + 3) * \
(float)CONFIG_SAMV7_MCAN0_FBITRATE)) - 1))
-# define MCAN0_FSJW (CONFIG_SAMV7_MCAN0_FFSJW - 1)
+# define MCAN0_DSJW (CONFIG_SAMV7_MCAN0_FFSJW - 1)
-# if MCAN0_FTSEG1 > 15
-# error Invalid MCAN0 FTSEG1
+# if MCAN0_DTSEG1 > 15
+# error Invalid MCAN0 DTSEG1
# endif
-# if MCAN0_FTSEG2 > 7
-# error Invalid MCAN0 FTSEG2
+# if MCAN0_DTSEG2 > 7
+# error Invalid MCAN0 DTSEG2
# endif
-# if MCAN0_FSJW > 3
-# error Invalid MCAN0 FSJW
+# if MCAN0_DSJW > 3
+# error Invalid MCAN0 DSJW
# endif
/* MCAN0 RX FIFO0 element size */
@@ -422,31 +422,31 @@
(float)CONFIG_SAMV7_MCAN1_BITRATE)) - 1))
# define MCAN1_SJW (CONFIG_SAMV7_MCAN1_FSJW - 1)
-# if MCAN1_TSEG1 > 63
-# error Invalid MCAN1 TSEG1
+# if MCAN1_NTSEG1 > 63
+# error Invalid MCAN1 NTSEG1
# endif
-# if MCAN1_TSEG2 > 15
-# error Invalid MCAN1 TSEG2
+# if MCAN1_NTSEG2 > 15
+# error Invalid MCAN1 NTSEG2
# endif
-# if MCAN1_SJW > 15
-# error Invalid MCAN1 SJW
+# if MCAN1_NSJW > 15
+# error Invalid MCAN1 NSJW
# endif
-# define MCAN1_FTSEG1 (CONFIG_SAMV7_MCAN1_FPROPSEG + CONFIG_SAMV7_MCAN1_FPHASESEG1)
-# define MCAN1_FTSEG2 (CONFIG_SAMV7_MCAN1_FPHASESEG2)
-# define MCAN1_FBRP ((uint32_t)(((float) SAMV7_MCANCLK_FREQUENCY / \
- ((float)(MCAN1_FTSEG1 + MCAN1_FTSEG2 + 3) * \
+# define MCAN1_DTSEG1 (CONFIG_SAMV7_MCAN1_FPROPSEG + CONFIG_SAMV7_MCAN1_FPHASESEG1)
+# define MCAN1_DTSEG2 (CONFIG_SAMV7_MCAN1_FPHASESEG2)
+# define MCAN1_DBRP ((uint32_t)(((float) SAMV7_MCANCLK_FREQUENCY / \
+ ((float)(MCAN1_DTSEG1 + MCAN1_DTSEG2 + 3) * \
(float)CONFIG_SAMV7_MCAN1_FBITRATE)) - 1))
-# define MCAN1_FSJW (CONFIG_SAMV7_MCAN1_FFSJW - 1)
+# define MCAN1_DSJW (CONFIG_SAMV7_MCAN1_FFSJW - 1)
-#if MCAN1_FTSEG1 > 15
-# error Invalid MCAN1 FTSEG1
+#if MCAN1_DTSEG1 > 15
+# error Invalid MCAN1 DTSEG1
#endif
-#if MCAN1_FTSEG2 > 7
-# error Invalid MCAN1 FTSEG2
+#if MCAN1_DTSEG2 > 7
+# error Invalid MCAN1 DTSEG2
#endif
-#if MCAN1_FSJW > 3
-# error Invalid MCAN1 FSJW
+#if MCAN1_DSJW > 3
+# error Invalid MCAN1 DSJW
#endif
/* MCAN1 RX FIFO0 element size */
@@ -726,22 +726,30 @@
*
* MCAN_INT_DRX - Message stored to Dedicated Receive Buffer
*
- * Mode-independent RX-related interrupts
+ * Mode-independent RX-related interrupts for revision A
*
* MCAN_INT_CRCE - Receive CRC Error
* MCAN_INT_FOE - Format Error
* MCAN_INT_STE - Stuff Error
+ *
+ * Mode-independent RX-related interrupts for revision B
+ *
+ * MCAN_INT_PEA - Protocol Error in Arbitration Phase
+ * MCAN_INT_PED - Protocol Error in Data Phase
*/
-#define MCAN_RXCOMMON_INTS (MCAN_INT_CRCE | MCAN_INT_FOE | MCAN_INT_STE)
-#define MCAN_RXFIFO0_INTS (MCAN_INT_RF0N | MCAN_INT_RF0W | MCAN_INT_RF0L)
-#define MCAN_RXFIFO1_INTS (MCAN_INT_RF1N | MCAN_INT_RF1W | MCAN_INT_RF1L)
-#define MCAN_RXFIFO_INTS (MCAN_RXFIFO0_INTS | MCAN_RXFIFO1_INTS | \
- MCAN_INT_HPM | MCAN_RXCOMMON_INTS)
-#define MCAN_RXDEDBUF_INTS (MCAN_INT_DRX | MCAN_RXCOMMON_INTS)
+#define MCAN_RXCOMMON_INTS_REVA (MCAN_INT_CRCE | MCAN_INT_FOE | MCAN_INT_STE)
+#define MCAN_RXCOMMON_INTS (MCAN_INT_PEA | MCAN_INT_PED)
+#define MCAN_RXFIFO0_INTS (MCAN_INT_RF0N | MCAN_INT_RF0W | MCAN_INT_RF0L)
+#define MCAN_RXFIFO1_INTS (MCAN_INT_RF1N | MCAN_INT_RF1W | MCAN_INT_RF1L)
+#define MCAN_RXFIFO_INTS (MCAN_RXFIFO0_INTS | MCAN_RXFIFO1_INTS | \
+ MCAN_INT_HPM | MCAN_RXCOMMON_INTS)
+#define MCAN_RXDEDBUF_INTS (MCAN_INT_DRX | MCAN_RXCOMMON_INTS)
-#define MCAN_RXERR_INTS (MCAN_INT_RF0L | MCAN_INT_RF1L | MCAN_INT_CRCE | \
- MCAN_INT_FOE | MCAN_INT_STE)
+#define MCAN_RXERR_INTS_REVA (MCAN_INT_RF0L | MCAN_INT_RF1L | MCAN_INT_CRCE | \
+ MCAN_INT_FOE | MCAN_INT_STE)
+#define MCAN_RXERR_INTS (MCAN_INT_RF0L | MCAN_INT_RF1L | MCAN_INT_PEA | \
+ MCAN_INT_PED)
/* TX FIFOQ mode interrupts
*
@@ -758,18 +766,20 @@
*
* MCAN_INT_TC - Transmission Completed
* MCAN_INT_TCF - Transmission Cancellation Finished
- * MCAN_INT_BE - Bit Error
- * MCAN_INT_ACKE - Acknowledge Error
+ * MCAN_INT_BE - Bit Error (rev A)
+ * MCAN_INT_ACKE - Acknowledge Error (rev A)
+ * MCAN_INT_PEA - Protocol Error in Arbitration Phase (rev B)
+ * MCAN_INT_PED - Protocol Error in Data Phase (rev B)
*/
-#define MCAN_TXCOMMON_INTS (MCAN_INT_TC | MCAN_INT_TCF | MCAN_INT_BE | \
- MCAN_INT_ACKE)
+#define MCAN_TXCOMMON_INTS (MCAN_INT_TC | MCAN_INT_TCF | MCAN_INT_PEA | \
+ MCAN_INT_PED)
#define MCAN_TXFIFOQ_INTS (MCAN_INT_TFE | MCAN_TXCOMMON_INTS)
#define MCAN_TXEVFIFO_INTS (MCAN_INT_TEFN | MCAN_INT_TEFW | MCAN_INT_TEFF | \
MCAN_INT_TEFL)
#define MCAN_TXDEDBUF_INTS MCAN_TXCOMMON_INTS
-#define MCAN_TXERR_INTS (MCAN_INT_TEFL | MCAN_INT_BE | MCAN_INT_ACKE)
+#define MCAN_TXERR_INTS (MCAN_INT_TEFL | MCAN_INT_PEA | MCAN_INT_PED)
/* Common-, TX- and RX-Error-Mask */
@@ -835,6 +845,9 @@ struct sam_config_s
uint32_t baud; /* Configured baud */
uint32_t btp; /* Bit timing/prescaler register setting */
uint32_t fbtp; /* Fast bit timing/prescaler register setting */
+ uint32_t nbtp; /* Nominal Bit timing/prescaler register setting */
+ uint32_t dbtp; /* Data bit timing/prescaler register setting */
+ uint8_t rev; /* Chip revision (0: A, 1: B) */
uint8_t port; /* MCAN port number (1 or 2) */
uint8_t pid; /* MCAN peripheral ID */
uint8_t irq0; /* MCAN peripheral IRQ number for interrupt line 0 */
@@ -884,6 +897,7 @@ struct sam_mcan_s
uint32_t fbtp; /* Current fast bit timing */
uint32_t rxints; /* Configured RX interrupts */
uint32_t txints; /* Configured TX interrupts */
+ uint8_t rev; /* Chip revision (0: A, 1: B) */
#ifdef CONFIG_CAN_EXTID
uint32_t extfilters[2]; /* Extended filter bit allocator. 2*32=64 */
@@ -991,27 +1005,35 @@ static const struct can_ops_s g_mcanops =
static uint32_t g_mcan0_msgram[MCAN0_MSGRAM_WORDS]
#ifdef CONFIG_ARMV7M_DCACHE
- aligned_data(MCAN_ALIGN);
+ __attribute__((aligned(MCAN_ALIGN)));
#else
;
#endif
/* Constant configuration */
-static const struct sam_config_s g_mcan0const =
+static struct sam_config_s g_mcan0const =
{
.rxpinset = GPIO_MCAN0_RX,
.txpinset = GPIO_MCAN0_TX,
.base = SAM_MCAN0_BASE,
.baud = CONFIG_SAMV7_MCAN0_BITRATE,
- .btp = MCAN_BTP_BRP(MCAN0_BRP) |
- MCAN_BTP_TSEG1(MCAN0_TSEG1) |
- MCAN_BTP_TSEG2(MCAN0_TSEG2) |
- MCAN_BTP_SJW(MCAN0_SJW),
- .fbtp = MCAN_FBTP_FBRP(MCAN0_FBRP) |
- MCAN_FBTP_FTSEG1(MCAN0_FTSEG1) |
- MCAN_FBTP_FTSEG2(MCAN0_FTSEG2) |
- MCAN_FBTP_FSJW(MCAN0_FSJW),
+ .btp = MCAN_REVA_BTP_BRP(MCAN0_BRP) |
+ MCAN_REVA_BTP_TSEG1(MCAN0_TSEG1) |
+ MCAN_REVA_BTP_TSEG2(MCAN0_TSEG2) |
+ MCAN_REVA_BTP_SJW(MCAN0_SJW),
+ .fbtp = MCAN_REVA_FBTP_FBRP(MCAN0_DBRP) |
+ MCAN_REVA_FBTP_FTSEG1(MCAN0_DTSEG1) |
+ MCAN_REVA_FBTP_FTSEG2(MCAN0_DTSEG2) |
+ MCAN_REVA_FBTP_FSJW(MCAN0_DSJW),
+ .nbtp = MCAN_NBTP_NBRP(MCAN0_BRP) |
+ MCAN_NBTP_NTSEG1(MCAN0_TSEG1) |
+ MCAN_NBTP_NTSEG2(MCAN0_TSEG2) |
+ MCAN_NBTP_NSJW(MCAN0_SJW),
+ .dbtp = MCAN_DBTP_DBRP(MCAN0_DBRP) |
+ MCAN_DBTP_DTSEG1(MCAN0_DTSEG1) |
+ MCAN_DBTP_DTSEG2(MCAN0_DTSEG2) |
+ MCAN_DBTP_DSJW(MCAN0_DSJW),
.port = 0,
.pid = SAM_PID_MCAN00,
.irq0 = SAM_IRQ_MCAN00,
@@ -1071,27 +1093,35 @@ static struct can_dev_s g_mcan0dev;
static uint32_t g_mcan1_msgram[MCAN1_MSGRAM_WORDS]
#ifdef CONFIG_ARMV7M_DCACHE
- aligned_data(MCAN_ALIGN);
+ __attribute__((aligned(MCAN_ALIGN)));
#else
;
#endif
/* MCAN1 constant configuration */
-static const struct sam_config_s g_mcan1const =
+static struct sam_config_s g_mcan1const =
{
.rxpinset = GPIO_MCAN1_RX,
.txpinset = GPIO_MCAN1_TX,
.base = SAM_MCAN1_BASE,
.baud = CONFIG_SAMV7_MCAN1_BITRATE,
- .btp = MCAN_BTP_BRP(MCAN1_BRP) |
- MCAN_BTP_TSEG1(MCAN1_TSEG1) |
- MCAN_BTP_TSEG2(MCAN1_TSEG2) |
- MCAN_BTP_SJW(MCAN1_SJW),
- .fbtp = MCAN_FBTP_FBRP(MCAN1_FBRP) |
- MCAN_FBTP_FTSEG1(MCAN1_FTSEG1) |
- MCAN_FBTP_FTSEG2(MCAN1_FTSEG2) |
- MCAN_FBTP_FSJW(MCAN1_FSJW),
+ .btp = MCAN_REVA_BTP_BRP(MCAN1_BRP) |
+ MCAN_REVA_BTP_TSEG1(MCAN1_TSEG1) |
+ MCAN_REVA_BTP_TSEG2(MCAN1_TSEG2) |
+ MCAN_REVA_BTP_SJW(MCAN1_SJW),
+ .fbtp = MCAN_REVA_FBTP_FBRP(MCAN1_DBRP) |
+ MCAN_REVA_FBTP_FTSEG1(MCAN1_DTSEG1) |
+ MCAN_REVA_FBTP_FTSEG2(MCAN1_DTSEG2) |
+ MCAN_REVA_FBTP_FSJW(MCAN1_DSJW),
+ .nbtp = MCAN_NBTP_NBRP(MCAN1_BRP) |
+ MCAN_NBTP_NTSEG1(MCAN1_TSEG1) |
+ MCAN_NBTP_NTSEG2(MCAN1_TSEG2) |
+ MCAN_NBTP_NSJW(MCAN1_SJW),
+ .dbtp = MCAN_DBTP_DBRP(MCAN1_DBRP) |
+ MCAN_DBTP_DTSEG1(MCAN1_DTSEG1) |
+ MCAN_DBTP_DTSEG2(MCAN1_DTSEG2) |
+ MCAN_DBTP_DSJW(MCAN1_DSJW),
.port = 1,
.pid = SAM_PID_MCAN10,
.irq0 = SAM_IRQ_MCAN10,
@@ -1289,17 +1319,17 @@ static void mcan_dumpregs(FAR struct sam_mcan_s *priv, FAR const char *msg)
FAR const struct sam_config_s *config = priv->config;
caninfo("MCAN%d Registers: %s\n", config->port, msg);
- caninfo(" Base: %08x\n", config->base);
+ caninfo(" Base: %08x\n", config->base);
- caninfo(" CUST: %08x FBTP: %08x TEST: %08x RWD: %08x\n",
+ caninfo(" CUST: %08x DBTP: %08x TEST: %08x RWD: %08x\n",
getreg32(config->base + SAM_MCAN_CUST_OFFSET),
- getreg32(config->base + SAM_MCAN_FBTP_OFFSET),
+ getreg32(config->base + SAM_MCAN_DBTP_OFFSET),
getreg32(config->base + SAM_MCAN_TEST_OFFSET),
getreg32(config->base + SAM_MCAN_RWD_OFFSET));
- caninfo(" CCCR: %08x BTP: %08x TSCC: %08x TSCV: %08x\n",
+ caninfo(" CCCR: %08x NBTP: %08x TSCC: %08x TSCV: %08x\n",
getreg32(config->base + SAM_MCAN_CCCR_OFFSET),
- getreg32(config->base + SAM_MCAN_BTP_OFFSET),
+ getreg32(config->base + SAM_MCAN_NBTP_OFFSET),
getreg32(config->base + SAM_MCAN_TSCC_OFFSET),
getreg32(config->base + SAM_MCAN_TSCV_OFFSET));
@@ -2672,18 +2702,37 @@ static int mcan_ioctl(FAR struct can_dev_s *dev, int cmd, unsigned long arg)
DEBUGASSERT(bt != NULL);
- regval = mcan_getreg(priv, SAM_MCAN_BTP_OFFSET);
- bt->bt_sjw = ((regval & MCAN_BTP_SJW_MASK) >>
- MCAN_BTP_SJW_SHIFT) + 1;
- bt->bt_tseg1 = ((regval & MCAN_BTP_TSEG1_MASK) >>
- MCAN_BTP_TSEG1_SHIFT) + 1;
- bt->bt_tseg2 = ((regval & MCAN_BTP_TSEG2_MASK) >>
- MCAN_BTP_TSEG2_SHIFT) + 1;
+ regval = mcan_getreg(priv, SAM_MCAN_NBTP_OFFSET);
+
+ if (priv->rev == 0)
+ {
+ /* Revision A */
+
+ bt->bt_sjw = ((regval & MCAN_REVA_BTP_SJW_MASK) >>
+ MCAN_REVA_BTP_SJW_SHIFT) + 1;
+ bt->bt_tseg1 = ((regval & MCAN_REVA_BTP_TSEG1_MASK) >>
+ MCAN_REVA_BTP_TSEG1_SHIFT) + 1;
+ bt->bt_tseg2 = ((regval & MCAN_REVA_BTP_TSEG2_MASK) >>
+ MCAN_REVA_BTP_TSEG2_SHIFT) + 1;
+ brp = ((regval & MCAN_REVA_BTP_BRP_MASK) >>
+ MCAN_REVA_BTP_BRP_SHIFT) + 1;
+ }
+ else
+ {
+ /* Revision B */
+
+ bt->bt_sjw = ((regval & MCAN_NBTP_NSJW_MASK) >>
+ MCAN_NBTP_NSJW_SHIFT) + 1;
+ bt->bt_tseg1 = ((regval & MCAN_NBTP_NTSEG1_MASK) >>
+ MCAN_NBTP_NTSEG1_SHIFT) + 1;
+ bt->bt_tseg2 = ((regval & MCAN_NBTP_NTSEG2_MASK) >>
+ MCAN_NBTP_NTSEG2_SHIFT) + 1;
+ brp = ((regval & MCAN_NBTP_NBRP_MASK) >>
+ MCAN_NBTP_NBRP_SHIFT) + 1;
+ }
- brp = ((regval & MCAN_BTP_BRP_MASK) >>
- MCAN_BTP_BRP_SHIFT) + 1;
bt->bt_baud = SAMV7_MCANCLK_FREQUENCY / brp /
- (bt->bt_tseg1 + bt->bt_tseg2 + 1);
+ (bt->bt_tseg1 + bt->bt_tseg2 + 1);
ret = OK;
}
break;
@@ -2736,8 +2785,18 @@ static int mcan_ioctl(FAR struct can_dev_s *dev, int cmd, unsigned long arg)
/* Save the value of the new bit timing register */
flags = enter_critical_section();
- priv->btp = MCAN_BTP_BRP(brp) | MCAN_BTP_TSEG1(tseg1) |
- MCAN_BTP_TSEG2(tseg2) | MCAN_BTP_SJW(sjw);
+ if (priv->rev == 0)
+ {
+ priv->btp = MCAN_REVA_BTP_BRP(brp) |
+ MCAN_REVA_BTP_TSEG1(tseg1) |
+ MCAN_REVA_BTP_TSEG2(tseg2) |
+ MCAN_REVA_BTP_SJW(sjw);
+ }
+ else
+ {
+ priv->btp = MCAN_NBTP_NBRP(brp) | MCAN_NBTP_NTSEG1(tseg1) |
+ MCAN_NBTP_NTSEG2(tseg2) | MCAN_NBTP_NSJW(sjw);
+ }
/* We need to reset to instantiate the new timing. Save
* current state information so that recover to this
@@ -2988,7 +3047,7 @@ static int mcan_send(FAR struct can_dev_s *dev, FAR struct can_msg_s *msg)
/* Format the TX FIFOQ entry
*
- * Format word T1:
+ * Format word T0:
* Transfer message ID (ID) - Value from message structure
* Remote Transmission Request (RTR) - Value from message structure
* Extended Identifier (XTD) - Depends on configuration.
@@ -3024,6 +3083,19 @@ static int mcan_send(FAR struct can_dev_s *dev, FAR struct can_msg_s *msg)
*/
txbuffer[1] = BUFFER_R1_DLC(msg->cm_hdr.ch_dlc);
+
+#ifdef CONFIG_CAN_FD
+ if (msg->cm_hdr.ch_edl)
+ {
+ txbuffer[1] |= BUFFER_R1_EDL;
+ }
+
+ if (msg->cm_hdr.ch_brs)
+ {
+ txbuffer[1] |= BUFFER_R1_BRS;
+ }
+#endif
+
reginfo("T1: %08x\n", txbuffer[1]);
/* Followed by the amount of data corresponding to the DLC (T2..) */
@@ -3261,6 +3333,8 @@ static void mcan_error(FAR struct can_dev_s *dev, uint32_t status)
uint16_t errbits;
uint8_t data[CAN_ERROR_DLC];
int ret;
+ uint32_t lec;
+ uint32_t dlec;
/* Encode error bits */
@@ -3339,43 +3413,54 @@ static void mcan_error(FAR struct can_dev_s *dev, uint32_t status)
data[1] |= CAN_ERROR1_UNSPEC;
}
- if ((status & MCAN_INT_CRCE) != 0)
+ if ((status & (MCAN_INT_PEA | MCAN_INT_CRCE)) != 0)
{
- /* Receive CRC Error */
+ lec = psr & MCAN_PSR_LEC_MASK;
+ dlec = (psr & MCAN_PSR_DLEC_MASK) >> MCAN_PSR_DLEC_SHIFT;
- errbits |= CAN_ERROR_PROTOCOL;
- data[3] |= (CAN_ERROR3_CRCSEQ | CAN_ERROR3_CRCDEL);
- }
+ if ((lec == MCAN_PSR_EC_CRC_ERROR) || (dlec == MCAN_PSR_EC_CRC_ERROR))
+ {
+ /* Receive CRC Error */
- if ((status & MCAN_INT_BE) != 0)
- {
- /* Bit Error */
+ errbits |= CAN_ERROR_PROTOCOL;
+ data[3] |= (CAN_ERROR3_CRCSEQ | CAN_ERROR3_CRCDEL);
+ }
- errbits |= CAN_ERROR_PROTOCOL;
- data[2] |= CAN_ERROR2_BIT;
- }
+ if ((lec == MCAN_PSR_EC_BIT0_ERROR) || \
+ (lec == MCAN_PSR_EC_BIT1_ERROR) || \
+ (dlec == MCAN_PSR_EC_BIT0_ERROR) || \
+ (dlec == MCAN_PSR_EC_BIT1_ERROR))
+ {
+ /* Bit Error */
- if ((status & MCAN_INT_ACKE) != 0)
- {
- /* Acknowledge Error */
+ errbits |= CAN_ERROR_PROTOCOL;
+ data[2] |= CAN_ERROR2_BIT;
+ }
- errbits |= CAN_ERROR_NOACK;
- }
+ if ((lec == MCAN_PSR_EC_ACK_ERROR) || (dlec == MCAN_PSR_EC_ACK_ERROR))
+ {
+ /* Acknowledge Error */
- if ((status & MCAN_INT_FOE) != 0)
- {
- /* Format Error */
+ errbits |= CAN_ERROR_NOACK;
+ }
- errbits |= CAN_ERROR_PROTOCOL;
- data[2] |= CAN_ERROR2_FORM;
- }
+ if ((lec == MCAN_PSR_EC_FORM_ERROR) || \
+ (dlec == MCAN_PSR_EC_FORM_ERROR))
+ {
+ /* Format Error */
- if ((status & MCAN_INT_STE) != 0)
- {
- /* Stuff Error */
+ errbits |= CAN_ERROR_PROTOCOL;
+ data[2] |= CAN_ERROR2_FORM;
+ }
+
+ if ((lec == MCAN_PSR_EC_STUFF_ERROR) || \
+ (dlec == MCAN_PSR_EC_STUFF_ERROR))
+ {
+ /* Stuff Error */
- errbits |= CAN_ERROR_PROTOCOL;
- data[2] |= CAN_ERROR2_STUFF;
+ errbits |= CAN_ERROR_PROTOCOL;
+ data[2] |= CAN_ERROR2_STUFF;
+ }
}
if (errbits != 0)
@@ -3490,6 +3575,11 @@ static void mcan_receive(FAR struct can_dev_s *dev, FAR uint32_t *rxbuffer,
hdr.ch_dlc = (regval & BUFFER_R1_DLC_MASK) >> BUFFER_R1_DLC_SHIFT;
+#ifdef CONFIG_CAN_FD
+ hdr.ch_edl = (regval >> BUFFER_R1_EDL_SHIFT) & 1u;
+ hdr.ch_brs = (regval >> BUFFER_R1_BRS_SHIFT) & 1u;
+#endif
+
/* And provide the CAN message to the upper half logic */
ret = can_receive(dev, &hdr, (FAR uint8_t *)rxbuffer);
@@ -3525,6 +3615,7 @@ static int mcan_interrupt(int irq, void *context, FAR void *arg)
unsigned int nelem;
unsigned int ndx;
bool handled;
+ uint32_t psr;
DEBUGASSERT(dev != NULL);
priv = dev->cd_priv;
@@ -3551,8 +3642,9 @@ static int mcan_interrupt(int irq, void *context, FAR void *arg)
if ((pending & MCAN_CMNERR_INTS) != 0)
{
- canerr("ERROR: Common %08"PRIx32"\n",
- pending & MCAN_CMNERR_INTS);
+ psr = mcan_getreg(priv, SAM_MCAN_PSR_OFFSET);
+ canerr("ERROR: Common %08"PRIx32", PSR %08"PRIx32"\n",
+ pending & MCAN_CMNERR_INTS, psr);
/* Clear the error indications */
@@ -3563,7 +3655,9 @@ static int mcan_interrupt(int irq, void *context, FAR void *arg)
if ((pending & MCAN_TXERR_INTS) != 0)
{
- canerr("ERROR: TX %08"PRIx32"\n", pending & MCAN_TXERR_INTS);
+ psr = mcan_getreg(priv, SAM_MCAN_PSR_OFFSET);
+ canerr("ERROR: TX %08"PRIx32", PSR %08"PRIx32"\n",
+ pending & MCAN_TXERR_INTS, psr);
/* An Acknowledge-Error will occur if for example the device
* is not connected to the bus.
@@ -3571,11 +3665,19 @@ static int mcan_interrupt(int irq, void *context, FAR void *arg)
* The CAN-Standard states that the Chip has to retry the
* message forever, which will produce an ACKE every time.
* To prevent this Interrupt-Flooding and the high CPU-Load
- * we disable the ACKE here as long we didn't transfer at
+ * we disable the all errors here as long we didn't transfer at
* least one message successfully (see MCAN_INT_TC below).
*/
- ie &= ~MCAN_INT_ACKE;
+ if (priv->rev == 0)
+ {
+ ie &= ~MCAN_INT_ACKE;
+ }
+ else
+ {
+ ie &= ~(MCAN_INT_PEA | MCAN_INT_PED);
+ }
+
mcan_putreg(priv, SAM_MCAN_IE_OFFSET, ie);
/* Clear the error indications */
@@ -3597,7 +3699,9 @@ static int mcan_interrupt(int irq, void *context, FAR void *arg)
if ((pending & MCAN_RXERR_INTS) != 0)
{
- canerr("ERROR: RX %08"PRIx32"\n", pending & MCAN_RXERR_INTS);
+ psr = mcan_getreg(priv, SAM_MCAN_PSR_OFFSET);
+ canerr("ERROR: RX %08"PRIx32", PSR %08"PRIx32"\n",
+ pending & MCAN_RXERR_INTS, psr);
/* To prevent Interrupt-Flooding the current active
* RX error interrupts are disabled. After successfully
@@ -3634,11 +3738,17 @@ static int mcan_interrupt(int irq, void *context, FAR void *arg)
* re-enable the error interrupt here again.
*/
- if ((ie & MCAN_INT_ACKE) == 0)
+ if ((priv->rev == 0) && ((ie & MCAN_INT_ACKE) == 0))
{
ie |= MCAN_INT_ACKE;
mcan_putreg(priv, SAM_MCAN_IE_OFFSET, ie);
}
+ else if ((priv->rev == 1) && \
+ ((ie & (MCAN_INT_PEA | MCAN_INT_PED)) == 0))
+ {
+ ie |= MCAN_INT_PEA | MCAN_INT_PED;
+ mcan_putreg(priv, SAM_MCAN_IE_OFFSET, ie);
+ }
/* Clear the pending TX completion interrupt (and all
* other TX-related interrupts)
@@ -3847,7 +3957,7 @@ static int mcan_hw_initialize(struct sam_mcan_s *priv)
FAR uint32_t *msgram;
uint32_t regval;
uint32_t cntr;
- uint32_t cmr;
+ uint32_t cmr = 0;
caninfo("MCAN%d\n", config->port);
@@ -3905,12 +4015,27 @@ static int mcan_hw_initialize(struct sam_mcan_s *priv)
/* Clear all pending interrupts. */
- mcan_putreg(priv, SAM_MCAN_IR_OFFSET, MCAN_INT_ALL);
+ if (priv->rev == 0)
+ {
+ mcan_putreg(priv, SAM_MCAN_IR_OFFSET, MCAN_REVA_INT_ALL);
+ }
+ else
+ {
+ mcan_putreg(priv, SAM_MCAN_IR_OFFSET, MCAN_REVB_INT_ALL);
+ }
/* Configure MCAN bit timing */
- mcan_putreg(priv, SAM_MCAN_BTP_OFFSET, priv->btp);
- mcan_putreg(priv, SAM_MCAN_FBTP_OFFSET, priv->fbtp);
+ if (priv->rev == 0)
+ {
+ mcan_putreg(priv, SAM_MCAN_REVA_BTP_OFFSET, priv->btp);
+ mcan_putreg(priv, SAM_MCAN_REVA_FBTP_OFFSET, priv->fbtp);
+ }
+ else
+ {
+ mcan_putreg(priv, SAM_MCAN_NBTP_OFFSET, priv->btp);
+ mcan_putreg(priv, SAM_MCAN_DBTP_OFFSET, priv->fbtp);
+ }
/* Configure message RAM starting addresses and sizes. */
@@ -3989,25 +4114,49 @@ static int mcan_hw_initialize(struct sam_mcan_s *priv)
*/
regval = mcan_getreg(priv, SAM_MCAN_CCCR_OFFSET);
- regval &= ~(MCAN_CCCR_CME_MASK | MCAN_CCCR_CMR_MASK);
+ if (priv->rev == 0)
+ {
+ regval &= ~(MCAN_CCCR_CME_MASK | MCAN_CCCR_CMR_MASK);
+ }
+ else
+ {
+ regval &= ~(MCAN_CCCR_FDOE | MCAN_CCCR_BRSE | MCAN_CCCR_NISO);
+ }
switch (config->mode)
{
default:
case MCAN_ISO11898_1_MODE:
- regval |= MCAN_CCCR_CME_ISO11898_1;
- cmr = MCAN_CCCR_CMR_ISO11898_1;
+ if (priv->rev == 0)
+ {
+ regval |= MCAN_CCCR_CME_ISO11898_1;
+ cmr = MCAN_CCCR_CMR_ISO11898_1;
+ }
break;
#ifdef CONFIG_CAN_FD
case MCAN_FD_MODE:
- regval |= MCAN_CCCR_CME_FD;
- cmr = MCAN_CCCR_CMR_FD;
+ if (priv->rev == 0)
+ {
+ regval |= MCAN_CCCR_CME_FD;
+ cmr = MCAN_CCCR_CMR_FD;
+ }
+ else
+ {
+ regval |= MCAN_CCCR_FDOE;
+ }
break;
case MCAN_FD_BSW_MODE:
- regval |= MCAN_CCCR_CME_FD_BSW;
- cmr = MCAN_CCCR_CMR_FD_BSW;
+ if (priv->rev == 0)
+ {
+ regval |= MCAN_CCCR_CME_FD_BSW;
+ cmr = MCAN_CCCR_CMR_FD_BSW;
+ }
+ else
+ {
+ regval |= (MCAN_CCCR_FDOE | MCAN_CCCR_BRSE);
+ }
break;
#endif
}
@@ -4016,10 +4165,13 @@ static int mcan_hw_initialize(struct sam_mcan_s *priv)
mcan_putreg(priv, SAM_MCAN_CCCR_OFFSET, regval);
- /* Request the mode change */
+ if (priv->rev == 0)
+ {
+ /* Request the mode change */
- regval |= cmr;
- mcan_putreg(priv, SAM_MCAN_CCCR_OFFSET, regval);
+ regval |= cmr;
+ mcan_putreg(priv, SAM_MCAN_CCCR_OFFSET, regval);
+ }
#if 0 /* Not necessary in initialization mode */
/* Wait for the mode to take effect */
@@ -4195,12 +4347,34 @@ FAR struct can_dev_s *sam_mcan_initialize(int port)
memset(priv, 0, sizeof(struct sam_mcan_s));
priv->config = config;
+ /* Get the revision of the chip (A or B ) */
+
+ regval = getreg32(SAM_CHIPID_CIDR);
+ priv->rev = regval & CHIPID_CIDR_VERSION_MASK;
+
/* Set the initial bit timing. This might change subsequently
* due to IOCTL command processing.
*/
- priv->btp = config->btp;
- priv->fbtp = config->fbtp;
+ if (priv->rev == 0)
+ {
+ /* Revision A */
+
+ priv->btp = config->btp;
+ priv->fbtp = config->fbtp;
+ }
+ else if (priv->rev == 1)
+ {
+ /* Revision B */
+
+ priv->btp = config->nbtp;
+ priv->fbtp = config->dbtp;
+ }
+ else
+ {
+ canerr("ERROR: Incorrect chip revision: %d\n", priv->rev);
+ return NULL;
+ }
/* Initialize semaphores */