diff --git a/arch/arm/src/samv7/Kconfig b/arch/arm/src/samv7/Kconfig index 2b7ad366a8..967c6692dd 100644 --- a/arch/arm/src/samv7/Kconfig +++ b/arch/arm/src/samv7/Kconfig @@ -1338,6 +1338,33 @@ config SAMV7_MCAN_CLKSRC_PRESCALER menu "MCAN0 device driver options" depends on SAMV7_MCAN0 +choice + prompt "MCAN0 mode" + default SAMV7_MCAN0_ISO11899_1 + +config SAMV7_MCAN0_ISO11899_1 + bool "ISO11898-1" + ---help--- + Enable ISO11898-1 mode + +config SAMV7_MCAN0_FD + bool "FD" + ---help--- + Enable FD mode + +config SAMV7_MCAN0_FD_BSW + bool "FD with fast bit rate switching" + ---help--- + Enable FD mode with fast bit rate switching mode. + +endchoice # MCAN0 mode + +config SAMV7_MCAN0_LOOPBACK + bool "Enable MCAN0 loopback mode" + default n + ---help--- + Enable the MCAN0 local loopback mode for testing purposes. + config SAMV7_MCAN0_BITRATE int "MCAN0 bitrate" default 500000 @@ -1588,6 +1615,33 @@ endmenu # MCAN0 device driver options menu "MCAN1 device driver options" depends on SAMV7_MCAN1 +choice + prompt "MCAN1 mode" + default SAMV7_MCAN1_ISO11899_1 + +config SAMV7_MCAN1_ISO11899_1 + bool "ISO11898-1" + ---help--- + Enable ISO11898-1 mode + +config SAMV7_MCAN1_FD + bool "FD" + ---help--- + Enable FD mode + +config SAMV7_MCAN1_FD_BSW + bool "FD with fast bit rate switching" + ---help--- + Enable FD mode with fast bit rate switching mode. + +endchoice # MCAN0 mode + +config SAMV7_MCAN1_LOOPBACK + bool "Enable MCAN1 loopback mode" + default n + ---help--- + Enable the MCAN1 local loopback mode for testing purposes. + config SAMV7_MCAN1_BITRATE int "MCAN1 bitrate" default 500000 @@ -1836,12 +1890,6 @@ config SAMV7_MCAN1_DEDICATED_TXFIFOQ_SIZE endmenu # MCAN1 device driver options -config SAMV7_MCAN_LOOPBACK - bool "Enable loopback mode" - default n - ---help--- - Enable the MCAN local loopback mode for testing purposes. - config SAMV7_MCAN_REGDEBUG bool "CAN Register level debug" depends on DEBUG diff --git a/arch/arm/src/samv7/sam_mcan.c b/arch/arm/src/samv7/sam_mcan.c index 3163ca0835..18f9444b6a 100644 --- a/arch/arm/src/samv7/sam_mcan.c +++ b/arch/arm/src/samv7/sam_mcan.c @@ -336,6 +336,13 @@ #endif /* CONFIG_SAMV7_MCAN0 */ +/* Loopback mode */ + +#undef SAMV7_MCAN_LOOPBACK +#if defined(CONFIG_SAMV7_MCAN0_LOOPBACK) || defined(CONFIG_SAMV7_MCAN1_LOOPBACK) +# define SAMV7_MCAN_LOOPBACK 1 +#endif + /* MCAN1 Configuration ******************************************************/ #ifdef CONFIG_SAMV7_MCAN1 @@ -587,6 +594,15 @@ /**************************************************************************** * Private Types ****************************************************************************/ +/* CAN mode of operation */ + +enum sam_canmode_e +{ + MCAN_ISO11898_1_MODE = 0, /* CAN operation according to ISO11898-1 */ + MCAN_FD_MODE = 1, /* CAN FD operation */ + MCAN_FD_BSW_MODE = 2, /* CAN FD operation with bit rate switching */ +}; + /* This structure describes the MCAN message RAM layout */ struct sam_msgram_s @@ -615,6 +631,7 @@ struct sam_config_s uint8_t port; /* MCAN port number (1 or 2) */ uint8_t pid; /* MCAN peripheral ID */ uint8_t irq; /* MCAN peripheral IRQ number */ + uint8_t mode; /* See enum sam_canmode_e */ uint8_t nstdfilters; /* Number of standard filters (up to 128) */ uint8_t nextfilters; /* Number of extended filters (up to 64) */ uint8_t nfifo0; /* Number of FIFO0 elements (up to 64) */ @@ -631,6 +648,9 @@ struct sam_config_s uint8_t rxbufferesize; /* RX buffer element size */ uint8_t txbufferecode; /* Encoded TX buffer element size */ uint8_t txbufferesize; /* TX buffer element size */ +#ifdef SAMV7_MCAN_LOOPBACK + bool loopback; /* True: Loopback mode */ +#endif /* MCAN message RAM layout */ @@ -753,6 +773,13 @@ static const struct sam_config_s g_mcan0const = .port = 0, .pid = SAM_PID_MCAN00, .irq = SAM_IRQ_MCAN00, +#if defined(CONFIG_SAMV7_MCAN0_ISO11899_1) + .mode = MCAN_ISO11898_1_MODE, +#if defined(CONFIG_SAMV7_MCAN0_FD) + .mode = MCAN_FD_MODE, +#else /* if defined(CONFIG_SAMV7_MCAN0_FD_BSW) */ + .mode = MCAN_FD_BSW_MODE, +#endif .nstdfilters = CONFIG_SAMV7_MCAN0_NSTDFILTERS, .nextfitlers = CONFIG_SAMV7_MCAN0_NEXTFILTERS, .nfifo0 = CONFIG_SAMV7_MCAN0_RXFIFO0_SIZE, @@ -770,6 +797,10 @@ static const struct sam_config_s g_mcan0const = .txbufferecode = MCAN0_TXBUFFER_ENCODED_SIZE, .txbufferesize = (MCAN0_TXBUFFER_ELEMENT_SIZE / 4) + 2, +#ifdef CONFIG_SAMV7_MCAN0_LOOPBACK + .loopback = true, +#endif + /* MCAN0 Message RAM */ .msgram = @@ -812,6 +843,13 @@ static const struct sam_config_s g_mcan1const = .port = 1, .pid = SAM_PID_MCAN10, .irq = SAM_IRQ_MCAN10, +#if defined(CONFIG_SAMV7_MCAN1_ISO11899_1) + .mode = MCAN_ISO11898_1_MODE, +#if defined(CONFIG_SAMV7_MCAN1_FD) + .mode = MCAN_FD_MODE, +#else /* if defined(CONFIG_SAMV7_MCAN1_FD_BSW) */ + .mode = MCAN_FD_BSW_MODE, +#endif .nstdfilters = CONFIG_SAMV7_MCAN1_NSTDFILTERS, .nextfitlers = CONFIG_SAMV7_MCAN1_NEXTFILTERS, .nfifo0 = CONFIG_SAMV7_MCAN1_RXFIFO0_SIZE, @@ -829,6 +867,9 @@ static const struct sam_config_s g_mcan1const = .txbufferecode = MCAN1_TXBUFFER_ENCODED_SIZE, .txbufferesize = (MCAN0_TXBUFFER_ELEMENT_SIZE / 4) + 2, +#ifdef CONFIG_SAMV7_MCAN1_LOOPBACK + .loopback = true, +#endif /* MCAN0 Message RAM */ .msgram = @@ -2289,6 +2330,7 @@ static int mcan_hwinitialize(struct sam_mcan_s *priv) sam_configpio(config->rxpinset); sam_configpio(config->txpinset); +#if 0 // REVISIT -- may apply only to SAMA5 /* Determine the maximum CAN peripheral clock frequency */ mck = BOARD_MCK_FREQUENCY; @@ -2322,11 +2364,13 @@ static int mcan_hwinitialize(struct sam_mcan_s *priv) regval |= PMC_PCR_PID(config->pid) | PMC_PCR_CMD | PMC_PCR_EN; mcan_putreg(priv, SAM_PMC_PCR, regval); +#endif /* Enable peripheral clocking */ sam_enableperiph1(config->pid); +#if 0 // REVISIT -- may apply only to SAMA5 /* Disable all CAN interrupts */ mcan_putreg(priv, SAM_CAN_IDR_OFFSET, CAN_INT_ALL); @@ -2339,23 +2383,63 @@ static int mcan_hwinitialize(struct sam_mcan_s *priv) candbg("ERROR: Failed to set bit timing: %d\n", ret); return ret; } +#endif +# error Missing SAMV71 MCAN initialization logic - /* The CAN controller is enabled by setting the CANEN flag in the CAN_MR - * register. At this stage, the internal CAN controller state machine is - * reset, error counters are reset to 0, error flags are reset to 0. - */ + /* Select FD mode with or without fast bit rate switching */ - regval = mcan_getreg(priv, SAM_CAN_MR_OFFSET); - regval |= CAN_MR_CANEN; - mcan_putreg(priv, SAM_CAN_MR_OFFSET, regval); + regval = sam_getreg(priv, SAM_MCAN_CCCR_OFFSET); + regval &= ~MCAN_CCCR_CME_MASK; - /* Once the CAN controller is enabled, bus synchronization is done - * automatically by scanning eleven recessive bits. The WAKEUP bit in - * the CAN_SR register is automatically set to 1 when the CAN controller - * is synchronized (WAKEUP and SLEEP are stuck at 0 after a reset). - */ + switch (priv->mode) + { + default: + case CONFIG_MCAN_ISO11898_1_MODE: + regval |= MCAN_CCCR_CME_ISO11898_1; + break; - while ((mcan_getreg(priv, SAM_CAN_SR_OFFSET) & CAN_INT_WAKEUP) == 0); + case CONFIG_MCAN_FD_MODE: + regval |= MCAN_CCCR_CME_FD; + break; + + case CONFIG_MCAN_FD_BSW_MODE: + regval |= MCAN_CCCR_CME_FD_BSW; + break; + } + + sam_putreg(priv, SAM_MCAN_CCCR_OFFSET, regval); + + /* Enable FIFO/Queue mode */ + + regval = sam_getreg(priv, SAM_MCAN_TXBC_OFFSET); + regval |= MCAN_TXBC_TFQM; + sam_putreg(priv, SAM_MCAN_TXBC_OFFSET, regval); + +#ifdef SAMV7_MCAN_LOOPBACK + /* Is loopback mode selected for this peripheral? */ + + if (config->loopback) + { + /* MCAN_CCCR_TEST - Test mode enable + * MCAN_CCCR_MON - Bus monitoring mode (for internal loopback) + * MCAN_TEST_LBCK - Loopback mode + */ + + regval = sam_getreg(priv, SAM_MCAN_CCCR_OFFSET); + regval |= (MCAN_CCCR_TEST | MCAN_CCCR_MON); + sam_putreg(priv, SAM_MCAN_CCCR_OFFSET, regval); + + regval = sam_getreg(priv, SAM_MCAN_TEST_OFFSET); + regval |= MCAN_TEST_LBCK; + sam_putreg(priv, SAM_MCAN_TEST_OFFSET, regval); + } +#endif + + /* Disable initialization mode to enable normal operation */ + + regval = sam_getreg(priv, SAM_MCAN_CCCR_OFFSET); + regval &= ~MCAN_CCCR_INIT; + sam_putreg(priv, SAM_MCAN_CCCR_OFFSET, regval); return OK; }