diff --git a/boards/arm/nucleo_g474re/nucleo_g474re.dts b/boards/arm/nucleo_g474re/nucleo_g474re.dts index c74fa63dc687f..ea5983ef76750 100644 --- a/boards/arm/nucleo_g474re/nucleo_g474re.dts +++ b/boards/arm/nucleo_g474re/nucleo_g474re.dts @@ -18,6 +18,7 @@ zephyr,shell-uart = &lpuart1; zephyr,sram = &sram0; zephyr,flash = &flash0; + zephyr,can-primary = &can1; }; leds { @@ -153,3 +154,14 @@ pinctrl-0 = <&adc1_in1_pa0>; status = "okay"; }; + +&can1 { + pinctrl-0 = <&fdcan1_rx_pa11 &fdcan1_tx_pa12>; + bus-speed = <125000>; + sjw = <1>; + sample-point = <875>; + bus-speed-data = <1000000>; + sjw-data = <1>; + sample-point-data = <875>; + status = "okay"; +}; diff --git a/boards/arm/nucleo_g474re/nucleo_g474re.yaml b/boards/arm/nucleo_g474re/nucleo_g474re.yaml index 02bba376e11eb..00bce2fa75bd8 100644 --- a/boards/arm/nucleo_g474re/nucleo_g474re.yaml +++ b/boards/arm/nucleo_g474re/nucleo_g474re.yaml @@ -22,3 +22,5 @@ supported: - watchdog - adc - dma + - can + - canfd diff --git a/drivers/can/CMakeLists.txt b/drivers/can/CMakeLists.txt index 7784e2e278448..de1b19253eccd 100644 --- a/drivers/can/CMakeLists.txt +++ b/drivers/can/CMakeLists.txt @@ -4,6 +4,8 @@ zephyr_sources_ifdef(CONFIG_CAN can_common.c) zephyr_sources_ifdef(CONFIG_CAN_LOOPBACK can_loopback.c) zephyr_sources_ifdef(CONFIG_CAN_MCP2515 can_mcp2515.c) zephyr_sources_ifdef(CONFIG_CAN_STM32 can_stm32.c) +zephyr_sources_ifdef(CONFIG_CAN_STM32FD can_stm32fd.c) +zephyr_sources_ifdef(CONFIG_CAN_MCAN can_mcan.c) zephyr_sources_ifdef(CONFIG_CAN_MCUX_FLEXCAN can_mcux_flexcan.c) zephyr_sources_ifdef(CONFIG_USERSPACE can_handlers.c) diff --git a/drivers/can/Kconfig b/drivers/can/Kconfig index aae8c55aadd03..13b864b025d8c 100644 --- a/drivers/can/Kconfig +++ b/drivers/can/Kconfig @@ -24,11 +24,30 @@ config CAN_SHELL help Enable CAN Shell for testing. -config CAN_FD_MODE +config CAN_HAS_CANFD bool + help + driver supports CAN-FD + +config CAN_FD_MODE + bool "CAN-FD" + default y + depends on CAN_HAS_CANFD help Enable CAN-FD compatible API +if CAN_FD_MODE + +config CANFD_MAX_DLC + int "Max data length code in CAN frames" + range 8 15 + default 15 + help + Maximum allowed DLC in a CAN frame. This parameter sets the + data buffer size in a CAN frame and is therefore only used to + optimize memory consumption. +endif # CAN_FD_MODE + config CAN_INIT_PRIORITY int "CAN driver init priority" default 80 @@ -47,7 +66,7 @@ config CAN_WORKQ_FRAMES_BUF_CNT config CAN_RX_TIMESTAMP bool "Enable receiving timestamps" - depends on CAN_STM32 || CAN_MCUX_FLEXCAN + depends on CAN_STM32 || CAN_MCUX_FLEXCAN || CAN_STM32FD help This option enables a timestamp value of the CAN free running timer. The value is incremented every bit time and starts when the controller @@ -63,8 +82,10 @@ config CAN_AUTO_BUS_OFF_RECOVERY available. source "drivers/can/Kconfig.stm32" +source "drivers/can/Kconfig.stm32fd" source "drivers/can/Kconfig.mcux" source "drivers/can/Kconfig.mcp2515" +source "drivers/can/Kconfig.mcan" source "drivers/can/Kconfig.loopback" source "drivers/can/Kconfig.net" diff --git a/drivers/can/Kconfig.mcan b/drivers/can/Kconfig.mcan new file mode 100644 index 0000000000000..99f28cf54b2c0 --- /dev/null +++ b/drivers/can/Kconfig.mcan @@ -0,0 +1,22 @@ +# Bosch m_can configuration options + +# Copyright (c) 2020 Alexander Wachter +# SPDX-License-Identifier: Apache-2.0 + +config CAN_MCAN + bool + select CAN_HAS_CANFD + help + Enable Bosch m_can driver. + This driver supports the Bosch m_can IP. This IP is built into the + STM32G4, STM32G0 and the Microchip SAM controllers with CAN-FD. + +if CAN_MCAN + +config CAN_DELAY_COMP + bool "Enable transceiver delay compensation" + default y + help + Enable the automatic transceiver delay compensation. + +endif #CAN_MCAN diff --git a/drivers/can/Kconfig.stm32fd b/drivers/can/Kconfig.stm32fd new file mode 100644 index 0000000000000..3434f8428fcc6 --- /dev/null +++ b/drivers/can/Kconfig.stm32fd @@ -0,0 +1,42 @@ +# STM32 CAN configuration options + +# Copyright (c) 2020 Alexander Wachter +# SPDX-License-Identifier: Apache-2.0 + +DT_COMPAT_STM32_FDCAN := st,stm32-fdcan + +config CAN_STM32FD + bool "STM32 FDCAN driver" + default $(dt_compat_enabled,$(DT_COMPAT_STM32_FDCAN)) + select CAN_MCAN + select USE_STM32_LL_RCC + +if CAN_STM32FD + +config CAN_MAX_STD_ID_FILTER + int "Maximum number of std ID filters" + default 28 + range 0 28 + help + Defines the maximum number of filters with standard ID (11-bit) + that can be attached. + +config CAN_MAX_EXT_ID_FILTER + int "Maximum number of ext ID filters" + default 8 + range 0 8 + help + Defines the maximum number of filters with extended ID (29-bit) + that can be attached. + +config CAN_STM32_CLOCK_DIVISOR + int "CAN clock divisor" + range 1 30 + default 1 + help + The APB clock is divided by this value (stored in CKDIV register) + before it is fed to the CAN core. + Note that the the divisor affects all CAN controllers. + Allowed values: 1 or 2 * n, where n <= 15. + +endif #CAN_STM32FD diff --git a/drivers/can/can_mcan.c b/drivers/can/can_mcan.c new file mode 100644 index 0000000000000..f1526df537cba --- /dev/null +++ b/drivers/can/can_mcan.c @@ -0,0 +1,879 @@ +/* + * Copyright (c) 2020 Alexander Wachter + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include "can_mcan.h" +#include "can_mcan_int.h" + +#include +LOG_MODULE_DECLARE(can_driver, CONFIG_CAN_LOG_LEVEL); + +#define CAN_INIT_TIMEOUT (100) +#define CAN_DIV_CEIL(val, div) (((val) + (div) - 1) / (div)) + +#ifdef CONFIG_CAN_FD_MODE +#define MCAN_MAX_DLC CANFD_MAX_DLC +#else +#define MCAN_MAX_DLC CAN_MAX_DLC +#endif + +static int can_exit_sleep_mode(struct can_mcan_reg *can) +{ + uint32_t start_time; + + can->cccr &= ~CAN_MCAN_CCCR_CSR; + start_time = k_cycle_get_32(); + + while ((can->cccr & CAN_MCAN_CCCR_CSA) == CAN_MCAN_CCCR_CSA) { + if (k_cycle_get_32() - start_time > + k_ms_to_cyc_ceil32(CAN_INIT_TIMEOUT)) { + can->cccr |= CAN_MCAN_CCCR_CSR; + return CAN_TIMEOUT; + } + } + + return 0; +} + +static int can_enter_init_mode(struct can_mcan_reg *can, k_timeout_t timeout) +{ + int64_t start_time; + + can->cccr |= CAN_MCAN_CCCR_INIT; + start_time = k_uptime_ticks(); + + while ((can->cccr & CAN_MCAN_CCCR_INIT) == 0U) { + if (k_uptime_ticks() - start_time > timeout.ticks) { + can->cccr &= ~CAN_MCAN_CCCR_INIT; + return CAN_TIMEOUT; + } + } + + return 0; +} + +static int can_leave_init_mode(struct can_mcan_reg *can, k_timeout_t timeout) +{ + int64_t start_time; + + can->cccr &= ~CAN_MCAN_CCCR_INIT; + start_time = k_uptime_ticks(); + + while ((can->cccr & CAN_MCAN_CCCR_INIT) != 0U) { + if (k_uptime_ticks() - start_time > timeout.ticks) { + return CAN_TIMEOUT; + } + } + + return 0; +} + +void can_mcan_configure_timing(struct can_mcan_reg *can, + const struct can_timing *timing, + const struct can_timing *timing_data) +{ + if (timing) { + __ASSERT_NO_MSG(timing->prop_seg == 0); + __ASSERT_NO_MSG(timing->phase_seg1 <= 0x100 && + timing->phase_seg1 > 0); + __ASSERT_NO_MSG(timing->phase_seg2 <= 0x80 && + timing->phase_seg2 > 0); + __ASSERT_NO_MSG(timing->prescaler <= 0x200 && + timing->prescaler > 0); + __ASSERT_NO_MSG(timing->sjw <= 0x80 && timing->sjw > 0); + + can->nbtp = (((uint32_t)timing->phase_seg1 - 1UL) & 0xFF) << + CAN_MCAN_NBTP_NTSEG1_POS | + (((uint32_t)timing->phase_seg2 - 1UL) & 0x7F) << + CAN_MCAN_NBTP_NTSEG2_POS | + (((uint32_t)timing->sjw - 1UL) & 0x7F) << + CAN_MCAN_NBTP_NSJW_POS | + (((uint32_t)timing->prescaler - 1UL) & 0x1FF) << + CAN_MCAN_NBTP_NBRP_POS; + } + +#ifdef CONFIG_CAN_FD_MODE + if (timing_data) { + __ASSERT_NO_MSG(timing_data->prop_seg == 0); + __ASSERT_NO_MSG(timing_data->phase_seg1 <= 0x20 && + timing_data->phase_seg1 > 0); + __ASSERT_NO_MSG(timing_data->phase_seg2 <= 0x10 && + timing_data->phase_seg2 > 0); + __ASSERT_NO_MSG(timing_data->prescaler <= 20 && + timing_data->prescaler > 0); + __ASSERT_NO_MSG(timing_data->sjw <= 0x80 && + timing_data->sjw > 0); + + can->dbtp = (((uint32_t)timing_data->phase_seg1 - 1UL) & 0x1F) << + CAN_MCAN_DBTP_DTSEG1_POS | + (((uint32_t)timing_data->phase_seg2 - 1UL) & 0x0F) << + CAN_MCAN_DBTP_DTSEG2_POS | + (((uint32_t)timing_data->sjw - 1UL) & 0x0F) << + CAN_MCAN_DBTP_DSJW_POS | + (((uint32_t)timing_data->prescaler - 1UL) & 0x1F) << + CAN_MCAN_DBTP_DBRP_POS; + } +#endif +} + +int can_mcan_set_timing(const struct can_mcan_config *cfg, + const struct can_timing *timing, + const struct can_timing *timing_data) +{ + struct can_mcan_reg *can = cfg->can; + int ret; + + ret = can_enter_init_mode(can, K_MSEC(CAN_INIT_TIMEOUT)); + if (ret) { + LOG_ERR("Failed to enter init mode"); + return -EIO; + } + + can_mcan_configure_timing(can, timing, timing_data); + + ret = can_leave_init_mode(can, K_MSEC(CAN_INIT_TIMEOUT)); + if (ret) { + LOG_ERR("Failed to leave init mode"); + return -EIO; + } + + return 0; +} + +int can_mcan_set_mode(const struct can_mcan_config *cfg, enum can_mode mode) +{ + struct can_mcan_reg *can = cfg->can; + int ret; + + ret = can_enter_init_mode(can, K_MSEC(CAN_INIT_TIMEOUT)); + if (ret) { + LOG_ERR("Failed to enter init mode"); + return -EIO; + } + + /* Configuration Change Enable */ + can->cccr |= CAN_MCAN_CCCR_CCE; + + switch (mode) { + case CAN_NORMAL_MODE: + LOG_DBG("Config normal mode"); + can->cccr &= ~(CAN_MCAN_CCCR_TEST | CAN_MCAN_CCCR_MON); + break; + + case CAN_SILENT_MODE: + LOG_DBG("Config silent mode"); + can->cccr &= ~CAN_MCAN_CCCR_TEST; + can->cccr |= CAN_MCAN_CCCR_MON; + break; + + case CAN_LOOPBACK_MODE: + LOG_DBG("Config loopback mode"); + can->cccr &= ~CAN_MCAN_CCCR_MON; + can->cccr |= CAN_MCAN_CCCR_TEST; + can->test |= CAN_MCAN_TEST_LBCK; + break; + + case CAN_SILENT_LOOPBACK_MODE: + LOG_DBG("Config silent loopback mode"); + can->cccr |= (CAN_MCAN_CCCR_TEST | CAN_MCAN_CCCR_MON); + can->test |= CAN_MCAN_TEST_LBCK; + break; + default: + break; + } + + ret = can_leave_init_mode(can, K_MSEC(CAN_INIT_TIMEOUT)); + if (ret) { + LOG_ERR("Failed to leave init mode"); + } + + return 0; +} + +int can_mcan_init(const struct device *dev, const struct can_mcan_config *cfg, + struct can_mcan_msg_sram *msg_ram, + struct can_mcan_data *data) +{ + struct can_mcan_reg *can = cfg->can; + struct can_timing timing; +#ifdef CONFIG_CAN_FD_MODE + struct can_timing timing_data; +#endif + int ret; + + k_mutex_init(&data->inst_mutex); + k_mutex_init(&data->tx_mtx); + k_sem_init(&data->tx_sem, NUM_TX_BUF_ELEMENTS, NUM_TX_BUF_ELEMENTS); + for (int i = 0; i < ARRAY_SIZE(data->tx_fin_sem); ++i) { + k_sem_init(&data->tx_fin_sem[i], 0, 1); + } + + ret = can_exit_sleep_mode(can); + if (ret) { + LOG_ERR("Failed to exit sleep mode"); + return -EIO; + } + + ret = can_enter_init_mode(can, K_MSEC(CAN_INIT_TIMEOUT)); + if (ret) { + LOG_ERR("Failed to enter init mode"); + return -EIO; + } + + /* Configuration Change Enable */ + can->cccr |= CAN_MCAN_CCCR_CCE; + + LOG_DBG("IP rel: %lu.%lu.%lu %02lu.%lu.%lu", + (can->crel & CAN_MCAN_CREL_REL) >> CAN_MCAN_CREL_REL_POS, + (can->crel & CAN_MCAN_CREL_STEP) >> CAN_MCAN_CREL_STEP_POS, + (can->crel & CAN_MCAN_CREL_SUBSTEP) >> + CAN_MCAN_CREL_SUBSTEP_POS, + (can->crel & CAN_MCAN_CREL_YEAR) >> CAN_MCAN_CREL_YEAR_POS, + (can->crel & CAN_MCAN_CREL_MON) >> CAN_MCAN_CREL_MON_POS, + (can->crel & CAN_MCAN_CREL_DAY) >> CAN_MCAN_CREL_DAY_POS); + +#ifndef CONFIG_CAN_STM32FD + can->sidfc = ((uint32_t)msg_ram->std_filt & CAN_MCAN_SIDFC_FLSSA_MSK) | + (ARRAY_SIZE(msg_ram->std_filt) << CAN_MCAN_SIDFC_LSS_POS); + can->xidfc = ((uint32_t)msg_ram->ext_filt & CAN_MCAN_XIDFC_FLESA_MSK) | + (ARRAY_SIZE(msg_ram->ext_filt) << CAN_MCAN_XIDFC_LSS_POS); + can->rxf0c = ((uint32_t)msg_ram->rx_fifo0 & CAN_MCAN_RXF0C_F0SA) | + (ARRAY_SIZE(msg_ram->rx_fifo0) << CAN_MCAN_RXF0C_F0S_POS); + can->rxf1c = ((uint32_t)msg_ram->rx_fifo1 & CAN_MCAN_RXF1C_F1SA) | + (ARRAY_SIZE(msg_ram->rx_fifo1) << CAN_MCAN_RXF1C_F1S_POS); + can->rxbc = ((uint32_t)msg_ram->rx_buffer & CAN_MCAN_RXBC_RBSA); + can->txefc = ((uint32_t)msg_ram->tx_event_fifo & CAN_MCAN_TXEFC_EFSA_MSK) | + (ARRAY_SIZE(msg_ram->tx_event_fifo) << + CAN_MCAN_TXEFC_EFS_POS); + can->txbc = ((uint32_t)msg_ram->tx_buffer & CAN_MCAN_TXBC_TBSA) | + (ARRAY_SIZE(msg_ram->tx_buffer) << CAN_MCAN_TXBC_TFQS_POS); + if (sizeof(msg_ram->tx_buffer[0].data) <= 24) { + can->txesc = (sizeof(msg_ram->tx_buffer[0].data) - 8) / 4; + } else { + can->txesc = (sizeof(msg_ram->tx_buffer[0].data) - 32) / 16 + 5; + } + + if (sizeof(msg_ram->rx_fifo0[0].data) <= 24) { + can->rxesc = (((sizeof(msg_ram->rx_fifo0[0].data) - 8) / 4) << + CAN_MCAN_RXESC_F0DS_POS) | + (((sizeof(msg_ram->rx_fifo1[0].data) - 8) / 4) << + CAN_MCAN_RXESC_F1DS_POS) | + (((sizeof(msg_ram->rx_buffer[0].data) - 8) / 4) << + CAN_MCAN_RXESC_RBDS_POS); + } else { + can->rxesc = (((sizeof(msg_ram->rx_fifo0[0].data) - 32) + / 16 + 5) << CAN_MCAN_RXESC_F0DS_POS) | + (((sizeof(msg_ram->rx_fifo1[0].data) - 32) + / 16 + 5) << CAN_MCAN_RXESC_F1DS_POS) | + (((sizeof(msg_ram->rx_buffer[0].data) - 32) + / 16 + 5) << CAN_MCAN_RXESC_RBDS_POS); + } +#endif + +#ifdef CONFIG_CAN_FD_MODE + can->cccr |= CAN_MCAN_CCCR_FDOE | CAN_MCAN_CCCR_BRSE; +#else + can->cccr &= ~(CAN_MCAN_CCCR_FDOE | CAN_MCAN_CCCR_BRSE); +#endif + can->cccr &= ~(CAN_MCAN_CCCR_TEST | CAN_MCAN_CCCR_MON | + CAN_MCAN_CCCR_ASM); + can->test &= ~(CAN_MCAN_TEST_LBCK); + +#if defined(CONFIG_CAN_DELAY_COMP) && defined(CONFIG_CAN_FD_MODE) + can->dbtp |= CAN_MCAN_DBTP_TDC; + can->tdcr |= cfg->tx_delay_comp_offset << CAN_MCAN_TDCR_TDCO_POS; + +#endif + +#ifdef CONFIG_CAN_STM32FD + can->rxgfc |= (CONFIG_CAN_MAX_STD_ID_FILTER << CAN_MCAN_RXGFC_LSS_POS) | + (CONFIG_CAN_MAX_EXT_ID_FILTER << CAN_MCAN_RXGFC_LSE_POS) | + (0x2 << CAN_MCAN_RXGFC_ANFS_POS) | + (0x2 << CAN_MCAN_RXGFC_ANFE_POS); +#else + can->gfc |= (0x2 << CAN_MCAN_GFC_ANFE_POS) | + (0x2 << CAN_MCAN_GFC_ANFS_POS); +#endif /* CONFIG_CAN_STM32FD */ + + if (cfg->sample_point) { + ret = can_calc_timing(dev, &timing, cfg->bus_speed, + cfg->sample_point); + if (ret == -EINVAL) { + LOG_ERR("Can't find timing for given param"); + return -EIO; + } + LOG_DBG("Presc: %d, TS1: %d, TS2: %d", + timing.prescaler, timing.phase_seg1, timing.phase_seg2); + LOG_DBG("Sample-point err : %d", ret); + } else if (cfg->prop_ts1) { + timing.prop_seg = 0; + timing.phase_seg1 = cfg->prop_ts1; + timing.phase_seg2 = cfg->ts2; + ret = can_calc_prescaler(dev, &timing, cfg->bus_speed); + if (ret) { + LOG_WRN("Bitrate error: %d", ret); + } + } +#ifdef CONFIG_CAN_FD_MODE + if (cfg->sample_point_data) { + ret = can_calc_timing_data(dev, &timing_data, + cfg->bus_speed_data, + cfg->sample_point_data); + if (ret == -EINVAL) { + LOG_ERR("Can't find timing for given dataphase param"); + return -EIO; + } + + LOG_DBG("Sample-point err data phase: %d", ret); + } else if (cfg->prop_ts1_data) { + timing_data.prop_seg = 0; + timing_data.phase_seg1 = cfg->prop_ts1_data; + timing_data.phase_seg2 = cfg->ts2_data; + ret = can_calc_prescaler(dev, &timing_data, + cfg->bus_speed_data); + if (ret) { + LOG_WRN("Dataphase bitrate error: %d", ret); + } + } +#endif + +#ifdef CONFIG_CAN_FD_MODE + timing_data.sjw = cfg->sjw_data; + can_mcan_configure_timing(can, &timing, &timing_data); +#else + timing.sjw = cfg->sjw; + can_mcan_configure_timing(can, &timing, NULL); +#endif + + can->ie = CAN_MCAN_IE_BO | CAN_MCAN_IE_EW | CAN_MCAN_IE_EP | + CAN_MCAN_IE_MRAF | CAN_MCAN_IE_TEFL | CAN_MCAN_IE_TEFN | + CAN_MCAN_IE_RF0N | CAN_MCAN_IE_RF1N | CAN_MCAN_IE_RF0L | + CAN_MCAN_IE_RF1L; + +#ifdef CONFIG_CAN_STM32FD + can->ils = CAN_MCAN_ILS_RXFIFO0 | CAN_MCAN_ILS_RXFIFO1; +#else + can->ils = CAN_MCAN_ILS_RF0N | CAN_MCAN_ILS_RF1N; +#endif + can->ile = CAN_MCAN_ILE_EINT0 | CAN_MCAN_ILE_EINT1; + /* Interrupt on every TX fifo element*/ + can->txbtie = CAN_MCAN_TXBTIE_TIE; + + ret = can_leave_init_mode(can, K_MSEC(CAN_INIT_TIMEOUT)); + if (ret) { + LOG_ERR("Failed to leave init mode"); + return -EIO; + } + + /* No memset because only aligned ptr are allowed */ + for (uint32_t *ptr = (uint32_t *)msg_ram; + ptr < (uint32_t *)msg_ram + + sizeof(struct can_mcan_msg_sram) / sizeof(uint32_t); + ptr++) { + *ptr = 0; + } + + return 0; +} + +static void can_mcan_state_change_handler(const struct can_mcan_config *cfg, + struct can_mcan_data *data) +{ + enum can_state state; + struct can_bus_err_cnt err_cnt; + + state = can_mcan_get_state(cfg, &err_cnt); + + if (data->state_change_isr) { + data->state_change_isr(state, err_cnt); + } +} + +static void can_mcan_tc_event_handler(struct can_mcan_reg *can, + struct can_mcan_msg_sram *msg_ram, + struct can_mcan_data *data) +{ + volatile struct can_mcan_tx_event_fifo *tx_event; + can_tx_callback_t tx_cb; + uint32_t event_idx, tx_idx; + + while (can->txefs & CAN_MCAN_TXEFS_EFFL) { + event_idx = (can->txefs & CAN_MCAN_TXEFS_EFGI) >> + CAN_MCAN_TXEFS_EFGI_POS; + tx_event = &msg_ram->tx_event_fifo[event_idx]; + tx_idx = tx_event->mm.idx; + /* Acknowledge TX event */ + can->txefa = event_idx; + + k_sem_give(&data->tx_sem); + + tx_cb = data->tx_fin_cb[tx_idx]; + if (tx_cb == NULL) { + k_sem_give(&data->tx_fin_sem[tx_idx]); + } else { + tx_cb(CAN_TX_OK, data->tx_fin_cb_arg[tx_idx]); + } + } +} + +void can_mcan_line_0_isr(const struct can_mcan_config *cfg, + struct can_mcan_msg_sram *msg_ram, + struct can_mcan_data *data) +{ + struct can_mcan_reg *can = cfg->can; + + do { + if (can->ir & (CAN_MCAN_IR_BO | CAN_MCAN_IR_EP | + CAN_MCAN_IR_EW)) { + can->ir = CAN_MCAN_IR_BO | CAN_MCAN_IR_EP | + CAN_MCAN_IR_EW; + can_mcan_state_change_handler(cfg, data); + } + /* TX event FIFO new entry */ + if (can->ir & CAN_MCAN_IR_TEFN) { + can->ir = CAN_MCAN_IR_TEFN; + can_mcan_tc_event_handler(can, msg_ram, data); + } + + if (can->ir & CAN_MCAN_IR_TEFL) { + can->ir = CAN_MCAN_IR_TEFL; + LOG_ERR("TX FIFO element lost"); + k_sem_give(&data->tx_sem); + } + + if (can->ir & CAN_MCAN_IR_ARA) { + can->ir = CAN_MCAN_IR_ARA; + LOG_ERR("Access to reserved address"); + } + + if (can->ir & CAN_MCAN_IR_MRAF) { + can->ir = CAN_MCAN_IR_MRAF; + LOG_ERR("Message RAM access failure"); + } + + } while (can->ir & (CAN_MCAN_IR_BO | CAN_MCAN_IR_EW | CAN_MCAN_IR_EP | + CAN_MCAN_IR_TEFL | CAN_MCAN_IR_TEFN)); +} + +static void can_mcan_get_message(struct can_mcan_data *data, + volatile struct can_mcan_rx_fifo *fifo, + volatile uint32_t *fifo_status_reg, + volatile uint32_t *fifo_ack_reg) +{ + uint32_t get_idx, filt_idx; + struct zcan_frame frame; + can_rx_callback_t cb; + volatile uint32_t *src, *dst, *end; + int data_length; + void *cb_arg; + struct can_mcan_rx_fifo_hdr hdr; + + while ((*fifo_status_reg & CAN_MCAN_RXF0S_F0FL)) { + get_idx = (*fifo_status_reg & CAN_MCAN_RXF0S_F0GI) >> + CAN_MCAN_RXF0S_F0GI_POS; + hdr = fifo[get_idx].hdr; + + if (hdr.xtd) { + frame.id = hdr.ext_id; + } else { + frame.id = hdr.std_id; + } + frame.fd = hdr.fdf; + frame.rtr = hdr.rtr ? CAN_REMOTEREQUEST : + CAN_DATAFRAME; + frame.id_type = hdr.xtd ? CAN_EXTENDED_IDENTIFIER : + CAN_STANDARD_IDENTIFIER; + frame.dlc = hdr.dlc; + frame.brs = hdr.brs; +#if defined(CONFIG_CAN_RX_TIMESTAMP) + frame.timestamp = hdr.rxts; +#endif + + filt_idx = hdr.fidx; + + /* Check if RTR must match */ + if ((hdr.xtd && data->ext_filt_rtr_mask & (1U << filt_idx) && + ((data->ext_filt_rtr >> filt_idx) & 1U) != frame.rtr) || + (data->std_filt_rtr_mask & (1U << filt_idx) && + ((data->std_filt_rtr >> filt_idx) & 1U) != frame.rtr)) { + continue; + } + + data_length = can_dlc_to_bytes(frame.dlc); + if (data_length <= sizeof(frame.data)) { + /* data needs to be written in 32 bit blocks!*/ + for (src = fifo[get_idx].data_32, + dst = frame.data_32, + end = dst + CAN_DIV_CEIL(data_length, sizeof(uint32_t)); + dst < end; + src++, dst++) { + *dst = *src; + } + + if (frame.id_type == CAN_STANDARD_IDENTIFIER) { + LOG_DBG("Frame on filter %d, ID: 0x%x", + filt_idx, frame.id); + cb = data->rx_cb_std[filt_idx]; + cb_arg = data->cb_arg_std[filt_idx]; + } else { + LOG_DBG("Frame on filter %d, ID: 0x%x", + filt_idx + NUM_STD_FILTER_DATA, + frame.id); + cb = data->rx_cb_ext[filt_idx]; + cb_arg = data->cb_arg_ext[filt_idx]; + } + + if (cb) { + cb(&frame, cb_arg); + } else { + LOG_DBG("cb missing"); + } + } else { + LOG_ERR("Frame is too big"); + } + + *fifo_ack_reg = get_idx; + } +} + +void can_mcan_line_1_isr(const struct can_mcan_config *cfg, + struct can_mcan_msg_sram *msg_ram, + struct can_mcan_data *data) +{ + struct can_mcan_reg *can = cfg->can; + + do { + if (can->ir & CAN_MCAN_IR_RF0N) { + can->ir = CAN_MCAN_IR_RF0N; + LOG_DBG("RX FIFO0 INT"); + can_mcan_get_message(data, msg_ram->rx_fifo0, + &can->rxf0s, &can->rxf0a); + } + + if (can->ir & CAN_MCAN_IR_RF1N) { + can->ir = CAN_MCAN_IR_RF1N; + LOG_DBG("RX FIFO1 INT"); + can_mcan_get_message(data, msg_ram->rx_fifo1, + &can->rxf1s, &can->rxf1a); + } + + if (can->ir & CAN_MCAN_IR_RF0L) { + can->ir = CAN_MCAN_IR_RF0L; + LOG_ERR("Message lost on FIFO0"); + } + + if (can->ir & CAN_MCAN_IR_RF1L) { + can->ir = CAN_MCAN_IR_RF1L; + LOG_ERR("Message lost on FIFO1"); + } + + } while (can->ir & (CAN_MCAN_IR_RF0N | CAN_MCAN_IR_RF1N | + CAN_MCAN_IR_RF0L | CAN_MCAN_IR_RF1L)); +} + +enum can_state can_mcan_get_state(const struct can_mcan_config *cfg, + struct can_bus_err_cnt *err_cnt) +{ + struct can_mcan_reg *can = cfg->can; + + err_cnt->rx_err_cnt = (can->ecr & CAN_MCAN_ECR_TEC_MSK) << + CAN_MCAN_ECR_TEC_POS; + + err_cnt->tx_err_cnt = (can->ecr & CAN_MCAN_ECR_REC_MSK) << + CAN_MCAN_ECR_REC_POS; + + if (can->psr & CAN_MCAN_PSR_BO) { + return CAN_BUS_OFF; + } + + if (can->psr & CAN_MCAN_PSR_EP) { + return CAN_ERROR_PASSIVE; + } + + return CAN_ERROR_ACTIVE; +} + +#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY +int can_mcan_recover(struct can_mcan_reg *can, k_timeout_t timeout) +{ + return can_leave_init_mode(can, timeout); +} +#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */ + + +int can_mcan_send(const struct can_mcan_config *cfg, + struct can_mcan_data *data, + struct can_mcan_msg_sram *msg_ram, + const struct zcan_frame *frame, + k_timeout_t timeout, + can_tx_callback_t callback, void *callback_arg) +{ + struct can_mcan_reg *can = cfg->can; + size_t data_length = can_dlc_to_bytes(frame->dlc); + struct can_mcan_tx_buffer_hdr tx_hdr = { + .rtr = frame->rtr == CAN_REMOTEREQUEST, + .xtd = frame->id_type == CAN_EXTENDED_IDENTIFIER, + .esi = 0, + .dlc = frame->dlc, +#ifdef CONFIG_CAN_FD_MODE + .brs = frame->brs == true, +#endif + .fdf = frame->fd, + .efc = 1, + }; + uint32_t put_idx; + int ret; + struct can_mcan_mm mm; + volatile uint32_t *dst, *end; + const uint32_t *src; + + LOG_DBG("Sending %d bytes. Id: 0x%x, ID type: %s %s %s %s", + data_length, frame->id, + frame->id_type == CAN_STANDARD_IDENTIFIER ? + "standard" : "extended", + frame->rtr == CAN_DATAFRAME ? "" : "RTR", + frame->fd == CAN_DATAFRAME ? "" : "FD frame", + frame->brs == CAN_DATAFRAME ? "" : "BRS"); + + if (data_length > sizeof(frame->data)) { + LOG_ERR("data length (%zu) > max frame data length (%zu)", + data_length, sizeof(frame->data)); + return CAN_TX_EINVAL; + } + + if (frame->fd != 1 && frame->dlc > MCAN_MAX_DLC) { + LOG_ERR("DLC of %d without fd flag set.", frame->dlc); + return CAN_TX_EINVAL; + } + + if (can->psr & CAN_MCAN_PSR_BO) { + return CAN_TX_BUS_OFF; + } + + ret = k_sem_take(&data->tx_sem, timeout); + if (ret != 0) { + return CAN_TIMEOUT; + } + + __ASSERT_NO_MSG((can->txfqs & CAN_MCAN_TXFQS_TFQF) != + CAN_MCAN_TXFQS_TFQF); + + k_mutex_lock(&data->tx_mtx, K_FOREVER); + + put_idx = ((can->txfqs & CAN_MCAN_TXFQS_TFQPI) >> + CAN_MCAN_TXFQS_TFQPI_POS); + + mm.idx = put_idx; + mm.cnt = data->mm.cnt++; + tx_hdr.mm = mm; + + if (frame->id_type == CAN_STANDARD_IDENTIFIER) { + tx_hdr.std_id = frame->id & CAN_STD_ID_MASK; + } else { + tx_hdr.ext_id = frame->id; + } + + msg_ram->tx_buffer[put_idx].hdr = tx_hdr; + + for (src = frame->data_32, + dst = msg_ram->tx_buffer[put_idx].data_32, + end = dst + CAN_DIV_CEIL(data_length, sizeof(uint32_t)); + dst < end; + src++, dst++) { + *dst = *src; + } + + data->tx_fin_cb[put_idx] = callback; + data->tx_fin_cb_arg[put_idx] = callback_arg; + + can->txbar = (1U << put_idx); + + k_mutex_unlock(&data->tx_mtx); + + if (callback == NULL) { + LOG_DBG("Waiting for TX complete"); + k_sem_take(&data->tx_fin_sem[put_idx], K_FOREVER); + } + + return CAN_TX_OK; +} + +static int can_mcan_get_free_std(volatile struct can_mcan_std_filter *filters) +{ + for (int i = 0; i < NUM_STD_FILTER_DATA; ++i) { + if (filters[i].sfce == CAN_MCAN_FCE_DISABLE) { + return i; + } + } + + return CAN_NO_FREE_FILTER; +} + +/* Use masked configuration only for simplicity. If someone needs more than + * 28 standard filters, dual mode needs to be implemented. + * Dual mode gets tricky, because we can only activate both filters. + * If one of the IDs is not used anymore, we would need to mark it as unused. + */ +int can_mcan_attach_std(struct can_mcan_data *data, + struct can_mcan_msg_sram *msg_ram, + can_rx_callback_t isr, void *cb_arg, + const struct zcan_filter *filter) +{ + struct can_mcan_std_filter filter_element = { + .id1 = filter->id, + .id2 = filter->id_mask, + .sft = CAN_MCAN_SFT_MASKED + }; + int filter_nr; + + k_mutex_lock(&data->inst_mutex, K_FOREVER); + filter_nr = can_mcan_get_free_std(msg_ram->std_filt); + + if (filter_nr == CAN_NO_FREE_FILTER) { + LOG_INF("No free standard id filter left"); + return CAN_NO_FREE_FILTER; + } + + /* TODO propper fifo balancing */ + filter_element.sfce = filter_nr & 0x01 ? CAN_MCAN_FCE_FIFO1 : + CAN_MCAN_FCE_FIFO0; + + msg_ram->std_filt[filter_nr] = filter_element; + + k_mutex_unlock(&data->inst_mutex); + + LOG_DBG("Attached std filter at %d", filter_nr); + + if (filter->rtr) { + data->std_filt_rtr |= (1U << filter_nr); + } else { + data->std_filt_rtr &= ~(1U << filter_nr); + } + + if (filter->rtr_mask) { + data->std_filt_rtr_mask |= (1U << filter_nr); + } else { + data->std_filt_rtr_mask &= ~(1U << filter_nr); + } + + data->rx_cb_std[filter_nr] = isr; + data->cb_arg_std[filter_nr] = cb_arg; + + return filter_nr; +} + +static int can_mcan_get_free_ext(volatile struct can_mcan_ext_filter *filters) +{ + for (int i = 0; i < NUM_EXT_FILTER_DATA; ++i) { + if (filters[i].efce == CAN_MCAN_FCE_DISABLE) { + return i; + } + } + + return CAN_NO_FREE_FILTER; +} + +static int can_mcan_attach_ext(struct can_mcan_data *data, + struct can_mcan_msg_sram *msg_ram, + can_rx_callback_t isr, void *cb_arg, + const struct zcan_filter *filter) +{ + struct can_mcan_ext_filter filter_element = { + .id2 = filter->id_mask, + .id1 = filter->id, + .eft = CAN_MCAN_EFT_MASKED + }; + int filter_nr; + + k_mutex_lock(&data->inst_mutex, K_FOREVER); + filter_nr = can_mcan_get_free_ext(msg_ram->ext_filt); + + if (filter_nr == CAN_NO_FREE_FILTER) { + LOG_INF("No free extender id filter left"); + return CAN_NO_FREE_FILTER; + } + + /* TODO propper fifo balancing */ + filter_element.efce = filter_nr & 0x01 ? CAN_MCAN_FCE_FIFO1 : + CAN_MCAN_FCE_FIFO0; + + msg_ram->ext_filt[filter_nr] = filter_element; + + k_mutex_unlock(&data->inst_mutex); + + LOG_DBG("Attached ext filter at %d", filter_nr); + + if (filter->rtr) { + data->ext_filt_rtr |= (1U << filter_nr); + } else { + data->ext_filt_rtr &= ~(1U << filter_nr); + } + + if (filter->rtr_mask) { + data->ext_filt_rtr_mask |= (1U << filter_nr); + } else { + data->ext_filt_rtr_mask &= ~(1U << filter_nr); + } + + data->rx_cb_ext[filter_nr] = isr; + data->cb_arg_ext[filter_nr] = cb_arg; + + return filter_nr; +} + +int can_mcan_attach_isr(struct can_mcan_data *data, + struct can_mcan_msg_sram *msg_ram, + can_rx_callback_t isr, void *cb_arg, + const struct zcan_filter *filter) +{ + int filter_nr; + + if (!isr) { + return -EINVAL; + } + + if (filter->id_type == CAN_STANDARD_IDENTIFIER) { + filter_nr = can_mcan_attach_std(data, msg_ram, isr, cb_arg, + filter); + } else { + filter_nr = can_mcan_attach_ext(data, msg_ram, isr, cb_arg, + filter); + filter_nr += NUM_STD_FILTER_DATA; + } + + if (filter_nr == CAN_NO_FREE_FILTER) { + LOG_INF("No free filter left"); + } + + return filter_nr; +} + +void can_mcan_detach(struct can_mcan_data *data, + struct can_mcan_msg_sram *msg_ram, int filter_nr) +{ + const struct can_mcan_ext_filter ext_filter = {0}; + const struct can_mcan_std_filter std_filter = {0}; + + k_mutex_lock(&data->inst_mutex, K_FOREVER); + if (filter_nr >= NUM_STD_FILTER_DATA) { + filter_nr -= NUM_STD_FILTER_DATA; + if (filter_nr >= NUM_STD_FILTER_DATA) { + LOG_ERR("Wrong filter id"); + return; + } + + msg_ram->ext_filt[filter_nr] = ext_filter; + data->rx_cb_ext[filter_nr] = NULL; + } else { + msg_ram->std_filt[filter_nr] = std_filter; + data->rx_cb_std[filter_nr] = NULL; + } + + k_mutex_unlock(&data->inst_mutex); +} diff --git a/drivers/can/can_mcan.h b/drivers/can/can_mcan.h new file mode 100644 index 0000000000000..33bc8896aa3db --- /dev/null +++ b/drivers/can/can_mcan.h @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2020 Alexander Wachter + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +#ifndef ZEPHYR_DRIVERS_CAN_MCAN_H_ +#define ZEPHYR_DRIVERS_CAN_MCAN_H_ + +#define NUM_STD_FILTER_ELEMENTS DT_PROP(DT_PATH(soc, can), std_filter_elements) +#define NUM_EXT_FILTER_ELEMENTS DT_PROP(DT_PATH(soc, can), ext_filter_elements) +#define NUM_RX_FIFO0_ELEMENTS DT_PROP(DT_PATH(soc, can), rx_fifo0_elements) +#define NUM_RX_FIFO1_ELEMENTS DT_PROP(DT_PATH(soc, can), rx_fifo0_elements) +#define NUM_RX_BUF_ELEMENTS DT_PROP(DT_PATH(soc, can), rx_buffer_elements) +#define NUM_TX_EVENT_FIFO_ELEMENTS \ + DT_PROP(DT_PATH(soc, can), tx_event_fifo_elements) +#define NUM_TX_BUF_ELEMENTS DT_PROP(DT_PATH(soc, can), tx_buffer_elements) + + +#ifdef CONFIG_CAN_STM32FD +#define NUM_STD_FILTER_DATA CONFIG_CAN_MAX_STD_ID_FILTER +#define NUM_EXT_FILTER_DATA CONFIG_CAN_MAX_EXT_ID_FILTER +#else +#define NUM_STD_FILTER_DATA NUM_STD_FILTER_ELEMENTS +#define NUM_EXT_FILTER_DATA NUM_EXT_FILTER_ELEMENTS +#endif + +struct can_mcan_rx_fifo_hdr { + union { + struct { + volatile uint32_t ext_id : 29; /* Extended Identifier */ + volatile uint32_t rtr : 1; /* Remote Transmission Request*/ + volatile uint32_t xtd : 1; /* Extended identifier */ + volatile uint32_t esi : 1; /* Error state indicator */ + }; + struct { + volatile uint32_t pad1 : 18; + volatile uint32_t std_id : 11; /* Standard Identifier */ + volatile uint32_t pad2 : 3; + }; + }; + + volatile uint32_t rxts : 16; /* Rx timestamp */ + volatile uint32_t dlc : 4; /* Data Length Code */ + volatile uint32_t brs : 1; /* Bit Rate Switch */ + volatile uint32_t fdf : 1; /* FD Format */ + volatile uint32_t res : 2; /* Reserved */ + volatile uint32_t fidx : 7; /* Filter Index */ + volatile uint32_t anmf : 1; /* Accepted non-matching frame */ +} __packed; + +struct can_mcan_rx_fifo { + struct can_mcan_rx_fifo_hdr hdr; + union { + volatile uint8_t data[64]; + volatile uint32_t data_32[16]; + }; +} __packed; + +struct can_mcan_mm { + volatile uint8_t idx : 5; + volatile uint8_t cnt : 3; +} __packed; + +struct can_mcan_tx_buffer_hdr { + union { + struct { + volatile uint32_t ext_id : 29; /* Identifier */ + volatile uint32_t rtr : 1; /* Retmote Transmission Request*/ + volatile uint32_t xtd : 1; /* Extended identifier */ + volatile uint32_t esi : 1; /* Error state indicator */ + }; + struct { + volatile uint32_t pad1 : 18; + volatile uint32_t std_id : 11; /* Identifier */ + volatile uint32_t pad2 : 3; + }; + }; + volatile uint16_t res1; /* Reserved */ + volatile uint8_t dlc : 4; /* Data Length Code */ + volatile uint8_t brs : 1; /* Bit Rate Switch */ + volatile uint8_t fdf : 1; /* FD Format */ + volatile uint8_t res2 : 1; /* Reserved */ + volatile uint8_t efc : 1; /* Event FIFO control (Store Tx events) */ + struct can_mcan_mm mm; /* Message marker */ +} __packed; + +struct can_mcan_tx_buffer { + struct can_mcan_tx_buffer_hdr hdr; + union { + volatile uint8_t data[64]; + volatile uint32_t data_32[16]; + }; +} __packed; + +#define CAN_MCAN_TE_TX 0x1 /* TX event */ +#define CAN_MCAN_TE_TXC 0x2 /* TX event in spite of cancellation */ + +struct can_mcan_tx_event_fifo { + volatile uint32_t id : 29; /* Identifier */ + volatile uint32_t rtr : 1; /* Retmote Transmission Request*/ + volatile uint32_t xtd : 1; /* Extended identifier */ + volatile uint32_t esi : 1; /* Error state indicator */ + + volatile uint16_t txts; /* TX Timestamp */ + volatile uint8_t dlc : 4; /* Data Length Code */ + volatile uint8_t brs : 1; /* Bit Rate Switch */ + volatile uint8_t fdf : 1; /* FD Format */ + volatile uint8_t et : 2; /* Event type */ + struct can_mcan_mm mm; /* Message marker */ +} __packed; + +#define CAN_MCAN_FCE_DISABLE 0x0 +#define CAN_MCAN_FCE_FIFO0 0x1 +#define CAN_MCAN_FCE_FIFO1 0x2 +#define CAN_MCAN_FCE_REJECT 0x3 +#define CAN_MCAN_FCE_PRIO 0x4 +#define CAN_MCAN_FCE_PRIO_FIFO0 0x5 +#define CAN_MCAN_FCE_PRIO_FIFO1 0x7 + +#define CAN_MCAN_SFT_RANGE 0x0 +#define CAN_MCAN_SFT_DUAL 0x1 +#define CAN_MCAN_SFT_MASKED 0x2 +#define CAN_MCAN_SFT_DISABLED 0x3 + +struct can_mcan_std_filter { + volatile uint32_t id2 : 11; /* ID2 for dual or range, mask otherwise */ + volatile uint32_t res : 5; + volatile uint32_t id1 : 11; + volatile uint32_t sfce : 3; /* Filter config */ + volatile uint32_t sft : 2; /* Filter type */ +} __packed; + +#define CAN_MCAN_EFT_RANGE_XIDAM 0x0 +#define CAN_MCAN_EFT_DUAL 0x1 +#define CAN_MCAN_EFT_MASKED 0x2 +#define CAN_MCAN_EFT_RANGE 0x3 + +struct can_mcan_ext_filter { + volatile uint32_t id1 : 29; + volatile uint32_t efce : 3; /* Filter config */ + volatile uint32_t id2 : 29; /* ID2 for dual or range, mask otherwise */ + volatile uint32_t res : 1; + volatile uint32_t eft : 2; /* Filter type */ +} __packed; + +struct can_mcan_msg_sram { + volatile struct can_mcan_std_filter std_filt[NUM_STD_FILTER_ELEMENTS]; + volatile struct can_mcan_ext_filter ext_filt[NUM_EXT_FILTER_ELEMENTS]; + volatile struct can_mcan_rx_fifo rx_fifo0[NUM_RX_FIFO0_ELEMENTS]; + volatile struct can_mcan_rx_fifo rx_fifo1[NUM_RX_FIFO1_ELEMENTS]; + volatile struct can_mcan_rx_fifo rx_buffer[NUM_RX_BUF_ELEMENTS]; + volatile struct can_mcan_tx_event_fifo tx_event_fifo[NUM_TX_BUF_ELEMENTS]; + volatile struct can_mcan_tx_buffer tx_buffer[NUM_TX_BUF_ELEMENTS]; +} __packed; + +struct can_mcan_data { + struct k_mutex inst_mutex; + struct k_sem tx_sem; + struct k_mutex tx_mtx; + struct k_sem tx_fin_sem[NUM_TX_BUF_ELEMENTS]; + can_tx_callback_t tx_fin_cb[NUM_TX_BUF_ELEMENTS]; + void *tx_fin_cb_arg[NUM_TX_BUF_ELEMENTS]; + can_rx_callback_t rx_cb_std[NUM_STD_FILTER_DATA]; + can_rx_callback_t rx_cb_ext[NUM_EXT_FILTER_DATA]; + void *cb_arg_std[NUM_STD_FILTER_DATA]; + void *cb_arg_ext[NUM_EXT_FILTER_DATA]; + can_state_change_isr_t state_change_isr; + uint32_t std_filt_rtr; + uint32_t std_filt_rtr_mask; + uint8_t ext_filt_rtr; + uint8_t ext_filt_rtr_mask; + struct can_mcan_mm mm; +} __aligned(4); + +struct can_mcan_config { + struct can_mcan_reg *can; /*!< CAN Registers*/ + uint32_t bus_speed; + uint32_t bus_speed_data; + uint16_t sjw; + uint16_t sample_point; + uint16_t prop_ts1; + uint16_t ts2; +#ifdef CONFIG_CAN_FD_MODE + uint16_t sample_point_data; + uint8_t sjw_data; + uint8_t prop_ts1_data; + uint8_t ts2_data; + uint8_t tx_delay_comp_offset; +#endif +}; + +struct can_mcan_reg; + +int can_mcan_set_mode(const struct can_mcan_config *cfg, enum can_mode mode); + +int can_mcan_set_timing(const struct can_mcan_config *cfg, + const struct can_timing *timing, + const struct can_timing *timing_data); + +int can_mcan_init(const struct device *dev, const struct can_mcan_config *cfg, + struct can_mcan_msg_sram *msg_ram, + struct can_mcan_data *data); + +void can_mcan_line_0_isr(const struct can_mcan_config *cfg, + struct can_mcan_msg_sram *msg_ram, + struct can_mcan_data *data); + +void can_mcan_line_1_isr(const struct can_mcan_config *cfg, + struct can_mcan_msg_sram *msg_ram, + struct can_mcan_data *data); + +int can_mcan_recover(struct can_mcan_reg *can, k_timeout_t timeout); + +int can_mcan_send(const struct can_mcan_config *cfg, struct can_mcan_data *data, + struct can_mcan_msg_sram *msg_ram, + const struct zcan_frame *frame, + k_timeout_t timeout, can_tx_callback_t callback, + void *callback_arg); + +int can_mcan_attach_isr(struct can_mcan_data *data, + struct can_mcan_msg_sram *msg_ram, + can_rx_callback_t isr, void *cb_arg, + const struct zcan_filter *filter); + +void can_mcan_detach(struct can_mcan_data *data, + struct can_mcan_msg_sram *msg_ram, int filter_nr); + +enum can_state can_mcan_get_state(const struct can_mcan_config *cfg, + struct can_bus_err_cnt *err_cnt); + +#endif /* ZEPHYR_DRIVERS_CAN_MCAN_H_ */ diff --git a/drivers/can/can_mcan_int.h b/drivers/can/can_mcan_int.h new file mode 100644 index 0000000000000..421be753a1019 --- /dev/null +++ b/drivers/can/can_mcan_int.h @@ -0,0 +1,1560 @@ +/* + * Copyright (c) 2020 Alexander Wachter + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +#ifndef ZEPHYR_DRIVERS_CAN_MCAN_INT_H_ +#define ZEPHYR_DRIVERS_CAN_MCAN_INT_H_ + +#include + +/* + * Register Masks are taken from the stm32cube library and extended for + * full M_CAN IPs + * Copyright (c) 2019 STMicroelectronics. + */ +/**************** Bit definition for CAN_MCAN_CREL register *****************/ +/* Timestamp Day */ +#define CAN_MCAN_CREL_DAY_POS (0U) +#define CAN_MCAN_CREL_DAY_MSK (0xFFUL << CAN_MCAN_CREL_DAY_POS) +#define CAN_MCAN_CREL_DAY CAN_MCAN_CREL_DAY_MSK +/* Timestamp Month */ +#define CAN_MCAN_CREL_MON_POS (8U) +#define CAN_MCAN_CREL_MON_MSK (0xFFUL << CAN_MCAN_CREL_MON_POS) +#define CAN_MCAN_CREL_MON CAN_MCAN_CREL_MON_MSK +/* Timestamp Year */ +#define CAN_MCAN_CREL_YEAR_POS (16U) +#define CAN_MCAN_CREL_YEAR_MSK (0xFUL << CAN_MCAN_CREL_YEAR_POS) +#define CAN_MCAN_CREL_YEAR CAN_MCAN_CREL_YEAR_MSK +/* Substep of Core release */ +#define CAN_MCAN_CREL_SUBSTEP_POS (20U) +#define CAN_MCAN_CREL_SUBSTEP_MSK (0xFUL << CAN_MCAN_CREL_SUBSTEP_POS) +#define CAN_MCAN_CREL_SUBSTEP CAN_MCAN_CREL_SUBSTEP_MSK +/* Step of Core release */ +#define CAN_MCAN_CREL_STEP_POS (24U) +#define CAN_MCAN_CREL_STEP_MSK (0xFUL << CAN_MCAN_CREL_STEP_POS) +#define CAN_MCAN_CREL_STEP CAN_MCAN_CREL_STEP_MSK +/* Core release */ +#define CAN_MCAN_CREL_REL_POS (28U) +#define CAN_MCAN_CREL_REL_MSK (0xFUL << CAN_MCAN_CREL_REL_POS) +#define CAN_MCAN_CREL_REL CAN_MCAN_CREL_REL_MSK + +/**************** Bit definition for CAN_MCAN_ENDN register *****************/ +/* Endiannes Test Value */ +#define CAN_MCAN_ENDN_ETV_POS (0U) +#define CAN_MCAN_ENDN_ETV_MSK (0xFFFFFFFFUL << CAN_MCAN_ENDN_ETV_POS) +#define CAN_MCAN_ENDN_ETV CAN_MCAN_ENDN_ETV_MSK + +/*************** Bit definition for CAN_MCAN_DBTP register ******************/ +/* Synchronization Jump Width */ +#define CAN_MCAN_DBTP_DSJW_POS (0U) +#define CAN_MCAN_DBTP_DSJW_MSK (0xFUL << CAN_MCAN_DBTP_DSJW_POS) +#define CAN_MCAN_DBTP_DSJW CAN_MCAN_DBTP_DSJW_MSK +/* Data time segment after sample point */ +#define CAN_MCAN_DBTP_DTSEG2_POS (4U) +#define CAN_MCAN_DBTP_DTSEG2_MSK (0xFUL << CAN_MCAN_DBTP_DTSEG2_POS) +#define CAN_MCAN_DBTP_DTSEG2 CAN_MCAN_DBTP_DTSEG2_MSK +/* Data time segment before sample point */ +#define CAN_MCAN_DBTP_DTSEG1_POS (8U) +#define CAN_MCAN_DBTP_DTSEG1_MSK (0x1FUL << CAN_MCAN_DBTP_DTSEG1_POS) +#define CAN_MCAN_DBTP_DTSEG1 CAN_MCAN_DBTP_DTSEG1_MSK +/* Data BIt Rate Prescaler */ +#define CAN_MCAN_DBTP_DBRP_POS (16U) +#define CAN_MCAN_DBTP_DBRP_MSK (0x1FUL << CAN_MCAN_DBTP_DBRP_POS) +#define CAN_MCAN_DBTP_DBRP CAN_MCAN_DBTP_DBRP_MSK +/* Transceiver Delay Compensation */ +#define CAN_MCAN_DBTP_TDC_POS (23U) +#define CAN_MCAN_DBTP_TDC_MSK (0x1UL << CAN_MCAN_DBTP_TDC_POS) +#define CAN_MCAN_DBTP_TDC CAN_MCAN_DBTP_TDC_MSK + +/*************** Bit definition for CAN_MCAN_TEST register *****************/ +/* Loop Back mode */ +#define CAN_MCAN_TEST_LBCK_POS (4U) +#define CAN_MCAN_TEST_LBCK_MSK (0x1UL << CAN_MCAN_TEST_LBCK_POS) +#define CAN_MCAN_TEST_LBCK CAN_MCAN_TEST_LBCK_MSK +/* Control of Transmit Pin */ +#define CAN_MCAN_TEST_TX_POS (5U) +#define CAN_MCAN_TEST_TX_MSK (0x3UL << CAN_MCAN_TEST_TX_POS) +#define CAN_MCAN_TEST_TX CAN_MCAN_TEST_TX_MSK +/* Receive Pin */ +#define CAN_MCAN_TEST_RX_POS (7U) +#define CAN_MCAN_TEST_RX_MSK (0x1UL << CAN_MCAN_TEST_RX_POS) +#define CAN_MCAN_TEST_RX CAN_MCAN_TEST_RX_MSK +/* Does not exist on STM32 begin */ +/* Tx Buffer Number Prepared */ +#define CAN_MCAN_TEST_TXBNP_POS (8U) +#define CAN_MCAN_TEST_TXBNP_MSK (0x1FUL << CAN_MCAN_TEST_TXBNP_POS) +#define CAN_MCAN_TEST_TXBNP CAN_MCAN_TEST_RX_MSK +/* Prepared Valid */ +#define CAN_MCAN_TEST_PVAL_POS (13U) +#define CAN_MCAN_TEST_PVAL_MSK (0x1UL << CAN_MCAN_TEST_PVAL_POS) +#define CAN_MCAN_TEST_PVAL CAN_MCAN_TEST_RX_MSK +/* Tx Buffer Number Started */ +#define CAN_MCAN_TEST_TXBNS_POS (16U) +#define CAN_MCAN_TEST_TXBNS_MSK (0x1FUL << CAN_MCAN_TEST_TXBNS_POS) +#define CAN_MCAN_TEST_TXBNS CAN_MCAN_TEST_RX_MSK +/* Started Valid */ +#define CAN_MCAN_TEST_SVAL_POS (12U) +#define CAN_MCAN_TEST_SVAL_MSK (0x1UL << CAN_MCAN_TEST_SVAL_POS) +#define CAN_MCAN_TEST_SVAL CAN_MCAN_TEST_RX_MSK +/* Does not exist on STM32 end */ + +/*************** Bit definition for CAN_MCAN_RWD register ******************/ +/* Watchdog configuration */ +#define CAN_MCAN_RWD_WDC_POS (0U) +#define CAN_MCAN_RWD_WDC_MSK (0xFFUL << CAN_MCAN_RWD_WDC_POS) +#define CAN_MCAN_RWD_WDC CAN_MCAN_RWD_WDC_MSK +/* Watchdog value */ +#define CAN_MCAN_RWD_WDV_POS (8U) +#define CAN_MCAN_RWD_WDV_MSK (0xFFUL << CAN_MCAN_RWD_WDV_POS) +#define CAN_MCAN_RWD_WDV CAN_MCAN_RWD_WDV_MSK + +/*************** Bit definition for CAN_MCAN_CCCR register ******************/ +/* Initialization */ +#define CAN_MCAN_CCCR_INIT_POS (0U) +#define CAN_MCAN_CCCR_INIT_MSK (0x1UL << CAN_MCAN_CCCR_INIT_POS) +#define CAN_MCAN_CCCR_INIT CAN_MCAN_CCCR_INIT_MSK +/* Configuration Change Enable */ +#define CAN_MCAN_CCCR_CCE_POS (1U) +#define CAN_MCAN_CCCR_CCE_MSK (0x1UL << CAN_MCAN_CCCR_CCE_POS) +#define CAN_MCAN_CCCR_CCE CAN_MCAN_CCCR_CCE_MSK +/* ASM Restricted Operation Mode */ +#define CAN_MCAN_CCCR_ASM_POS (2U) +#define CAN_MCAN_CCCR_ASM_MSK (0x1UL << CAN_MCAN_CCCR_ASM_POS) +#define CAN_MCAN_CCCR_ASM CAN_MCAN_CCCR_ASM_MSK +/* Clock Stop Acknowledge */ +#define CAN_MCAN_CCCR_CSA_POS (3U) +#define CAN_MCAN_CCCR_CSA_MSK (0x1UL << CAN_MCAN_CCCR_CSA_POS) +#define CAN_MCAN_CCCR_CSA CAN_MCAN_CCCR_CSA_MSK +/* Clock Stop Request */ +#define CAN_MCAN_CCCR_CSR_POS (4U) +#define CAN_MCAN_CCCR_CSR_MSK (0x1UL << CAN_MCAN_CCCR_CSR_POS) +#define CAN_MCAN_CCCR_CSR CAN_MCAN_CCCR_CSR_MSK +/* Bus Monitoring Mode */ +#define CAN_MCAN_CCCR_MON_POS (5U) +#define CAN_MCAN_CCCR_MON_MSK (0x1UL << CAN_MCAN_CCCR_MON_POS) +#define CAN_MCAN_CCCR_MON CAN_MCAN_CCCR_MON_MSK +/* Disable Automatic Retransmission */ +#define CAN_MCAN_CCCR_DAR_POS (6U) +#define CAN_MCAN_CCCR_DAR_MSK (0x1UL << CAN_MCAN_CCCR_DAR_POS) +#define CAN_MCAN_CCCR_DAR CAN_MCAN_CCCR_DAR_MSK +/* Test Mode Enable */ +#define CAN_MCAN_CCCR_TEST_POS (7U) +#define CAN_MCAN_CCCR_TEST_MSK (0x1UL << CAN_MCAN_CCCR_TEST_POS) +#define CAN_MCAN_CCCR_TEST CAN_MCAN_CCCR_TEST_MSK +/* FD Operation Enable */ +#define CAN_MCAN_CCCR_FDOE_POS (8U) +#define CAN_MCAN_CCCR_FDOE_MSK (0x1UL << CAN_MCAN_CCCR_FDOE_POS) +#define CAN_MCAN_CCCR_FDOE CAN_MCAN_CCCR_FDOE_MSK +/* FDCAN Bit Rate Switching */ +#define CAN_MCAN_CCCR_BRSE_POS (9U) +#define CAN_MCAN_CCCR_BRSE_MSK (0x1UL << CAN_MCAN_CCCR_BRSE_POS) +#define CAN_MCAN_CCCR_BRSE CAN_MCAN_CCCR_BRSE_MSK +/* does not exist on stm32 begin*/ +/* Use Timestamping Uni */ +#define CAN_MCAN_CCCR_UTSU_POS (10U) +#define CAN_MCAN_CCCR_UTSU_MSK (0x1UL << CAN_MCAN_CCCR_UTSU_POS) +#define CAN_MCAN_CCCR_UTSU CAN_MCAN_CCCR_UTSU_MSK +/* FDCAN Wide Message Marker */ +#define CAN_MCAN_CCCR_WMM_POS (11U) +#define CAN_MCAN_CCCR_WMM_MSK (0x1UL << CAN_MCAN_CCCR_WMM_POS) +#define CAN_MCAN_CCCR_WMM CAN_MCAN_CCCR_WMM_MSK +/* end */ +/* Protocol Exception Handling Disable */ +#define CAN_MCAN_CCCR_PXHD_POS (12U) +#define CAN_MCAN_CCCR_PXHD_MSK (0x1UL << CAN_MCAN_CCCR_PXHD_POS) +#define CAN_MCAN_CCCR_PXHD CAN_MCAN_CCCR_PXHD_MSK +/* Edge Filtering during Bus Integration */ +#define CAN_MCAN_CCCR_EFBI_POS (13U) +#define CAN_MCAN_CCCR_EFBI_MSK (0x1UL << CAN_MCAN_CCCR_EFBI_POS) +#define CAN_MCAN_CCCR_EFBI CAN_MCAN_CCCR_EFBI_MSK +/* Two CAN bit times Pause */ +#define CAN_MCAN_CCCR_TXP_POS (14U) +#define CAN_MCAN_CCCR_TXP_MSK (0x1UL << CAN_MCAN_CCCR_TXP_POS) +#define CAN_MCAN_CCCR_TXP CAN_MCAN_CCCR_TXP_MSK +/* Non ISO Operation */ +#define CAN_MCAN_CCCR_NISO_POS (15U) +#define CAN_MCAN_CCCR_NISO_MSK (0x1UL << CAN_MCAN_CCCR_NISO_POS) +#define CAN_MCAN_CCCR_NISO CAN_MCAN_CCCR_NISO_MSK + +/*************** Bit definition for CAN_MCAN_NBTP register ******************/ +/* Nominal Time segment after sample point */ +#define CAN_MCAN_NBTP_NTSEG2_POS (0U) +#define CAN_MCAN_NBTP_NTSEG2_MSK (0x7FUL << CAN_MCAN_NBTP_NTSEG2_POS) +#define CAN_MCAN_NBTP_NTSEG2 CAN_MCAN_NBTP_NTSEG2_MSK +/* Nominal Time segment before sample point */ +#define CAN_MCAN_NBTP_NTSEG1_POS (8U) +#define CAN_MCAN_NBTP_NTSEG1_MSK (0xFFUL << CAN_MCAN_NBTP_NTSEG1_POS) +#define CAN_MCAN_NBTP_NTSEG1 CAN_MCAN_NBTP_NTSEG1_MSK +/* Bit Rate Prescaler */ +#define CAN_MCAN_NBTP_NBRP_POS (16U) +#define CAN_MCAN_NBTP_NBRP_MSK (0x1FFUL << CAN_MCAN_NBTP_NBRP_POS) +#define CAN_MCAN_NBTP_NBRP CAN_MCAN_NBTP_NBRP_MSK +/* Nominal (Re)Synchronization Jump Width */ +#define CAN_MCAN_NBTP_NSJW_POS (25U) +#define CAN_MCAN_NBTP_NSJW_MSK (0x7FUL << CAN_MCAN_NBTP_NSJW_POS) +#define CAN_MCAN_NBTP_NSJW CAN_MCAN_NBTP_NSJW_MSK + +/*************** Bit definition for CAN_MCAN_TSCC register ******************/ +/* Timestamp Select */ +#define CAN_MCAN_TSCC_TSS_POS (0U) +#define CAN_MCAN_TSCC_TSS_MSK (0x3UL << CAN_MCAN_TSCC_TSS_POS) +#define CAN_MCAN_TSCC_TSS CAN_MCAN_TSCC_TSS_MSK +/* Timestamp Counter Prescaler */ +#define CAN_MCAN_TSCC_TCP_POS (16U) +#define CAN_MCAN_TSCC_TCP_MSK (0xFUL << CAN_MCAN_TSCC_TCP_POS) +#define CAN_MCAN_TSCC_TCP CAN_MCAN_TSCC_TCP_MSK +/*************** Bit definition for CAN_MCAN_TSCV register ******************/ +/* Timestamp Counter */ +#define CAN_MCAN_TSCV_TSC_POS (0U) +#define CAN_MCAN_TSCV_TSC_MSK (0xFFFFUL << CAN_MCAN_TSCV_TSC_POS) +#define CAN_MCAN_TSCV_TSC CAN_MCAN_TSCV_TSC_MSK + +/*************** Bit definition for CAN_MCAN_TOCC register ******************/ +/* Enable Timeout Counter */ +#define CAN_MCAN_TOCC_ETOC_POS (0U) +#define CAN_MCAN_TOCC_ETOC_MSK (0x1UL << CAN_MCAN_TOCC_ETOC_POS) +#define CAN_MCAN_TOCC_ETOC CAN_MCAN_TOCC_ETOC_MSK +/* Timeout Select */ +#define CAN_MCAN_TOCC_TOS_POS (1U) +#define CAN_MCAN_TOCC_TOS_MSK (0x3UL << CAN_MCAN_TOCC_TOS_POS) +#define CAN_MCAN_TOCC_TOS CAN_MCAN_TOCC_TOS_MSK +/* Timeout Period */ +#define CAN_MCAN_TOCC_TOP_POS (16U) +#define CAN_MCAN_TOCC_TOP_MSK (0xFFFFUL << CAN_MCAN_TOCC_TOP_POS) +#define CAN_MCAN_TOCC_TOP CAN_MCAN_TOCC_TOP_MSK + +/*************** Bit definition for CAN_MCAN_TOCV register ******************/ +/* Timeout Counter */ +#define CAN_MCAN_TOCV_TOC_POS (0U) +#define CAN_MCAN_TOCV_TOC_MSK (0xFFFFUL << CAN_MCAN_TOCV_TOC_POS) +#define CAN_MCAN_TOCV_TOC CAN_MCAN_TOCV_TOC_MSK + +/*************** Bit definition for CAN_MCAN_ECR register *******************/ +/* Transmit Error Counter */ +#define CAN_MCAN_ECR_TEC_POS (0U) +#define CAN_MCAN_ECR_TEC_MSK (0xFFUL << CAN_MCAN_ECR_TEC_POS) +#define CAN_MCAN_ECR_TEC CAN_MCAN_ECR_TEC_MSK +/* Receive Error Counter */ +#define CAN_MCAN_ECR_REC_POS (8U) +#define CAN_MCAN_ECR_REC_MSK (0x7FUL << CAN_MCAN_ECR_REC_POS) +#define CAN_MCAN_ECR_REC CAN_MCAN_ECR_REC_MSK +/* Receive Error Passive */ +#define CAN_MCAN_ECR_RP_POS (15U) +#define CAN_MCAN_ECR_RP_MSK (0x1UL << CAN_MCAN_ECR_RP_POS) +#define CAN_MCAN_ECR_RP CAN_MCAN_ECR_RP_MSK +/* CAN Error Logging */ +#define CAN_MCAN_ECR_CEL_POS (16U) +#define CAN_MCAN_ECR_CEL_MSK (0xFFUL << CAN_MCAN_ECR_CEL_POS) +#define CAN_MCAN_ECR_CEL CAN_MCAN_ECR_CEL_MSK + +/*************** Bit definition for CAN_MCAN_PSR register *******************/ +/* Last Error Code */ +#define CAN_MCAN_PSR_LEC_POS (0U) +#define CAN_MCAN_PSR_LEC_MSK (0x7UL << CAN_MCAN_PSR_LEC_POS) +#define CAN_MCAN_PSR_LEC CAN_MCAN_PSR_LEC_MSK +/* Activity */ +#define CAN_MCAN_PSR_ACT_POS (3U) +#define CAN_MCAN_PSR_ACT_MSK (0x3UL << CAN_MCAN_PSR_ACT_POS) +#define CAN_MCAN_PSR_ACT CAN_MCAN_PSR_ACT_MSK +/* Error Passive */ +#define CAN_MCAN_PSR_EP_POS (5U) +#define CAN_MCAN_PSR_EP_MSK (0x1UL << CAN_MCAN_PSR_EP_POS) +#define CAN_MCAN_PSR_EP CAN_MCAN_PSR_EP_MSK +/* Warning Status */ +#define CAN_MCAN_PSR_EW_POS (6U) +#define CAN_MCAN_PSR_EW_MSK (0x1UL << CAN_MCAN_PSR_EW_POS) +#define CAN_MCAN_PSR_EW CAN_MCAN_PSR_EW_MSK +/* Bus_Off Status */ +#define CAN_MCAN_PSR_BO_POS (7U) +#define CAN_MCAN_PSR_BO_MSK (0x1UL << CAN_MCAN_PSR_BO_POS) +#define CAN_MCAN_PSR_BO CAN_MCAN_PSR_BO_MSK +/* Data Last Error Code */ +#define CAN_MCAN_PSR_DLEC_POS (8U) +#define CAN_MCAN_PSR_DLEC_MSK (0x7UL << CAN_MCAN_PSR_DLEC_POS) +#define CAN_MCAN_PSR_DLEC CAN_MCAN_PSR_DLEC_MSK +/* ESI flag of last received FDCAN Message */ +#define CAN_MCAN_PSR_RESI_POS (11U) +#define CAN_MCAN_PSR_RESI_MSK (0x1UL << CAN_MCAN_PSR_RESI_POS) +#define CAN_MCAN_PSR_RESI CAN_MCAN_PSR_RESI_MSK +/* BRS flag of last received FDCAN Message */ +#define CAN_MCAN_PSR_RBRS_POS (12U) +#define CAN_MCAN_PSR_RBRS_MSK (0x1UL << CAN_MCAN_PSR_RBRS_POS) +#define CAN_MCAN_PSR_RBRS CAN_MCAN_PSR_RBRS_MSK +/* Received FDCAN Message */ +#define CAN_MCAN_PSR_REDL_POS (13U) +#define CAN_MCAN_PSR_REDL_MSK (0x1UL << CAN_MCAN_PSR_REDL_POS) +#define CAN_MCAN_PSR_REDL CAN_MCAN_PSR_REDL_MSK +/* Protocol Exception Event */ +#define CAN_MCAN_PSR_PXE_POS (14U) +#define CAN_MCAN_PSR_PXE_MSK (0x1UL << CAN_MCAN_PSR_PXE_POS) +#define CAN_MCAN_PSR_PXE CAN_MCAN_PSR_PXE_MSK + /* Transmitter Delay Compensation Value */ +#define CAN_MCAN_PSR_TDCV_POS (16U) +#define CAN_MCAN_PSR_TDCV_MSK (0x7FUL << CAN_MCAN_PSR_TDCV_POS) +#define CAN_MCAN_PSR_TDCV CAN_MCAN_PSR_TDCV_MSK + +/*************** Bit definition for CAN_MCAN_TDCR register ******************/ +/* Transmitter Delay Compensation Filter */ +#define CAN_MCAN_TDCR_TDCF_POS (0U) +#define CAN_MCAN_TDCR_TDCF_MSK (0x7FUL << CAN_MCAN_TDCR_TDCF_POS) +#define CAN_MCAN_TDCR_TDCF CAN_MCAN_TDCR_TDCF_MSK +/* Transmitter Delay Compensation Offset */ +#define CAN_MCAN_TDCR_TDCO_POS (8U) +#define CAN_MCAN_TDCR_TDCO_MSK (0x7FUL << CAN_MCAN_TDCR_TDCO_POS) +#define CAN_MCAN_TDCR_TDCO CAN_MCAN_TDCR_TDCO_MSK + +/*************** Bit definition for CAN_MCAN_IR register ********************/ +#ifdef CONFIG_CAN_STM32FD +/* Rx FIFO 0 New Message */ +#define CAN_MCAN_IR_RF0N_POS (0U) +#define CAN_MCAN_IR_RF0N_MSK (0x1UL << CAN_MCAN_IR_RF0N_POS) +#define CAN_MCAN_IR_RF0N CAN_MCAN_IR_RF0N_MSK +/* Rx FIFO 0 Full */ +#define CAN_MCAN_IR_RF0F_POS (1U) +#define CAN_MCAN_IR_RF0F_MSK (0x1UL << CAN_MCAN_IR_RF0F_POS) +#define CAN_MCAN_IR_RF0F CAN_MCAN_IR_RF0F_MSK +/* Rx FIFO 0 Message Lost */ +#define CAN_MCAN_IR_RF0L_POS (2U) +#define CAN_MCAN_IR_RF0L_MSK (0x1UL << CAN_MCAN_IR_RF0L_POS) +#define CAN_MCAN_IR_RF0L CAN_MCAN_IR_RF0L_MSK +/* Rx FIFO 1 New Message */ +#define CAN_MCAN_IR_RF1N_POS (3U) +#define CAN_MCAN_IR_RF1N_MSK (0x1UL << CAN_MCAN_IR_RF1N_POS) +#define CAN_MCAN_IR_RF1N CAN_MCAN_IR_RF1N_MSK +/* Rx FIFO 1 Full */ +#define CAN_MCAN_IR_RF1F_POS (4U) +#define CAN_MCAN_IR_RF1F_MSK (0x1UL << CAN_MCAN_IR_RF1F_POS) +#define CAN_MCAN_IR_RF1F CAN_MCAN_IR_RF1F_MSK +/* Rx FIFO 1 Message Lost */ +#define CAN_MCAN_IR_RF1L_POS (5U) +#define CAN_MCAN_IR_RF1L_MSK (0x1UL << CAN_MCAN_IR_RF1L_POS) +#define CAN_MCAN_IR_RF1L CAN_MCAN_IR_RF1L_MSK +/* High Priority Message */ +#define CAN_MCAN_IR_HPM_POS (6U) +#define CAN_MCAN_IR_HPM_MSK (0x1UL << CAN_MCAN_IR_HPM_POS) +#define CAN_MCAN_IR_HPM CAN_MCAN_IR_HPM_MSK +/* Transmission Completed */ +#define CAN_MCAN_IR_TC_POS (7U) +#define CAN_MCAN_IR_TC_MSK (0x1UL << CAN_MCAN_IR_TC_POS) +#define CAN_MCAN_IR_TC CAN_MCAN_IR_TC_MSK +/* Transmission Cancellation Finished */ +#define CAN_MCAN_IR_TCF_POS (8U) +#define CAN_MCAN_IR_TCF_MSK (0x1UL << CAN_MCAN_IR_TCF_POS) +#define CAN_MCAN_IR_TCF CAN_MCAN_IR_TCF_MSK +/* Tx FIFO Empty */ +#define CAN_MCAN_IR_TFE_POS (9U) +#define CAN_MCAN_IR_TFE_MSK (0x1UL << CAN_MCAN_IR_TFE_POS) +#define CAN_MCAN_IR_TFE CAN_MCAN_IR_TFE_MSK +/* Tx Event FIFO New Entry */ +#define CAN_MCAN_IR_TEFN_POS (10U) +#define CAN_MCAN_IR_TEFN_MSK (0x1UL << CAN_MCAN_IR_TEFN_POS) +#define CAN_MCAN_IR_TEFN CAN_MCAN_IR_TEFN_MSK +/* Tx Event FIFO Full */ +#define CAN_MCAN_IR_TEFF_POS (11U) +#define CAN_MCAN_IR_TEFF_MSK (0x1UL << CAN_MCAN_IR_TEFF_POS) +#define CAN_MCAN_IR_TEFF CAN_MCAN_IR_TEFF_MSK +/* Tx Event FIFO Element Lost */ +#define CAN_MCAN_IR_TEFL_POS (12U) +#define CAN_MCAN_IR_TEFL_MSK (0x1UL << CAN_MCAN_IR_TEFL_POS) +#define CAN_MCAN_IR_TEFL CAN_MCAN_IR_TEFL_MSK +/* Timestamp Wraparound */ +#define CAN_MCAN_IR_TSW_POS (13U) +#define CAN_MCAN_IR_TSW_MSK (0x1UL << CAN_MCAN_IR_TSW_POS) +#define CAN_MCAN_IR_TSW CAN_MCAN_IR_TSW_MSK +/* Message RAM Access Failure */ +#define CAN_MCAN_IR_MRAF_POS (14U) +#define CAN_MCAN_IR_MRAF_MSK (0x1UL << CAN_MCAN_IR_MRAF_POS) +#define CAN_MCAN_IR_MRAF CAN_MCAN_IR_MRAF_MSK +/* Timeout Occurred */ +#define CAN_MCAN_IR_TOO_POS (15U) +#define CAN_MCAN_IR_TOO_MSK (0x1UL << CAN_MCAN_IR_TOO_POS) +#define CAN_MCAN_IR_TOO CAN_MCAN_IR_TOO_MSK +/* Error Logging Overflow */ +#define CAN_MCAN_IR_ELO_POS (16U) +#define CAN_MCAN_IR_ELO_MSK (0x1UL << CAN_MCAN_IR_ELO_POS) +#define CAN_MCAN_IR_ELO CAN_MCAN_IR_ELO_MSK +/* Error Passive */ +#define CAN_MCAN_IR_EP_POS (17U) +#define CAN_MCAN_IR_EP_MSK (0x1UL << CAN_MCAN_IR_EP_POS) +#define CAN_MCAN_IR_EP CAN_MCAN_IR_EP_MSK +/* Warning Status */ +#define CAN_MCAN_IR_EW_POS (18U) +#define CAN_MCAN_IR_EW_MSK (0x1UL << CAN_MCAN_IR_EW_POS) +#define CAN_MCAN_IR_EW CAN_MCAN_IR_EW_MSK +/* Bus_Off Status */ +#define CAN_MCAN_IR_BO_POS (19U) +#define CAN_MCAN_IR_BO_MSK (0x1UL << CAN_MCAN_IR_BO_POS) +#define CAN_MCAN_IR_BO CAN_MCAN_IR_BO_MSK +/* Watchdog Interrupt */ +#define CAN_MCAN_IR_WDI_POS (20U) +#define CAN_MCAN_IR_WDI_MSK (0x1UL << CAN_MCAN_IR_WDI_POS) +#define CAN_MCAN_IR_WDI CAN_MCAN_IR_WDI_MSK +/* Protocol Error in Arbitration Phase */ +#define CAN_MCAN_IR_PEA_POS (21U) +#define CAN_MCAN_IR_PEA_MSK (0x1UL << CAN_MCAN_IR_PEA_POS) +#define CAN_MCAN_IR_PEA CAN_MCAN_IR_PEA_MSK +/* Protocol Error in Data Phase */ +#define CAN_MCAN_IR_PED_POS (22U) +#define CAN_MCAN_IR_PED_MSK (0x1UL << CAN_MCAN_IR_PED_POS) +#define CAN_MCAN_IR_PED CAN_MCAN_IR_PED_MSK + /* Access to Reserved Address */ +#define CAN_MCAN_IR_ARA_POS (23U) +#define CAN_MCAN_IR_ARA_MSK (0x1UL << CAN_MCAN_IR_ARA_POS) +#define CAN_MCAN_IR_ARA CAN_MCAN_IR_ARA_MSK + +#else /* CONFIG_CAN_STM32FD */ + +/* Rx FIFO 0 New Message */ +#define CAN_MCAN_IR_RF0N_POS (0U) +#define CAN_MCAN_IR_RF0N_MSK (0x1UL << CAN_MCAN_IR_RF0N_POS) +#define CAN_MCAN_IR_RF0N CAN_MCAN_IR_RF0N_MSK +/* Rx FIFO 0 Watermark Reached*/ +#define CAN_MCAN_IR_RF0W_POS (1U) +#define CAN_MCAN_IR_RF0W_MSK (0x1UL << CAN_MCAN_IR_RF0W_POS) +#define CAN_MCAN_IR_RF0W CAN_MCAN_IR_RF0W_MSK +/* Rx FIFO 0 Full */ +#define CAN_MCAN_IR_RF0F_POS (2U) +#define CAN_MCAN_IR_RF0F_MSK (0x1UL << CAN_MCAN_IR_RF0F_POS) +#define CAN_MCAN_IR_RF0F CAN_MCAN_IR_RF0F_MSK +/* Rx FIFO 0 Message Lost */ +#define CAN_MCAN_IR_RF0L_POS (3U) +#define CAN_MCAN_IR_RF0L_MSK (0x1UL << CAN_MCAN_IR_RF0L_POS) +#define CAN_MCAN_IR_RF0L CAN_MCAN_IR_RF0L_MSK +/* Rx FIFO 1 New Message */ +#define CAN_MCAN_IR_RF1N_POS (4U) +#define CAN_MCAN_IR_RF1N_MSK (0x1UL << CAN_MCAN_IR_RF1N_POS) +#define CAN_MCAN_IR_RF1N CAN_MCAN_IR_RF1N_MSK +/* Rx FIFO 1 Watermark Reached*/ +#define CAN_MCAN_IR_RF1W_POS (5U) +#define CAN_MCAN_IR_RF1W_MSK (0x1UL << CAN_MCAN_IR_RF1W_POS) +#define CAN_MCAN_IR_RF1W CAN_MCAN_IR_RF1W_MSK +/* Rx FIFO 1 Full */ +#define CAN_MCAN_IR_RF1F_POS (6U) +#define CAN_MCAN_IR_RF1F_MSK (0x1UL << CAN_MCAN_IR_RF1F_POS) +#define CAN_MCAN_IR_RF1F CAN_MCAN_IR_RF1F_MSK +/* Rx FIFO 1 Message Lost */ +#define CAN_MCAN_IR_RF1L_POS (7U) +#define CAN_MCAN_IR_RF1L_MSK (0x1UL << CAN_MCAN_IR_RF1L_POS) +#define CAN_MCAN_IR_RF1L CAN_MCAN_IR_RF1L_MSK +/* High Priority Message */ +#define CAN_MCAN_IR_HPM_POS (8U) +#define CAN_MCAN_IR_HPM_MSK (0x1UL << CAN_MCAN_IR_HPM_POS) +#define CAN_MCAN_IR_HPM CAN_MCAN_IR_HPM_MSK +/* Transmission Completed */ +#define CAN_MCAN_IR_TC_POS (9U) +#define CAN_MCAN_IR_TC_MSK (0x1UL << CAN_MCAN_IR_TC_POS) +#define CAN_MCAN_IR_TC CAN_MCAN_IR_TC_MSK +/* Transmission Cancellation Finished */ +#define CAN_MCAN_IR_TCF_POS (10U) +#define CAN_MCAN_IR_TCF_MSK (0x1UL << CAN_MCAN_IR_TCF_POS) +#define CAN_MCAN_IR_TCF CAN_MCAN_IR_TCF_MSK +/* Tx FIFO Empty */ +#define CAN_MCAN_IR_TFE_POS (11U) +#define CAN_MCAN_IR_TFE_MSK (0x1UL << CAN_MCAN_IR_TFE_POS) +#define CAN_MCAN_IR_TFE CAN_MCAN_IR_TFE_MSK +/* Tx Event FIFO New Entry */ +#define CAN_MCAN_IR_TEFN_POS (12U) +#define CAN_MCAN_IR_TEFN_MSK (0x1UL << CAN_MCAN_IR_TEFN_POS) +#define CAN_MCAN_IR_TEFN CAN_MCAN_IR_TEFN_MSK +/* Tx Event FIFO Watermark */ +#define CAN_MCAN_IR_TEFW_POS (13U) +#define CAN_MCAN_IR_TEFW_MSK (0x1UL << CAN_MCAN_IR_TEFW_POS) +#define CAN_MCAN_IR_TEFW CAN_MCAN_IR_TEFW_MSK +/* Tx Event FIFO Full */ +#define CAN_MCAN_IR_TEFF_POS (14U) +#define CAN_MCAN_IR_TEFF_MSK (0x1UL << CAN_MCAN_IR_TEFF_POS) +#define CAN_MCAN_IR_TEFF CAN_MCAN_IR_TEFF_MSK +/* Tx Event FIFO Element Lost */ +#define CAN_MCAN_IR_TEFL_POS (15U) +#define CAN_MCAN_IR_TEFL_MSK (0x1UL << CAN_MCAN_IR_TEFL_POS) +#define CAN_MCAN_IR_TEFL CAN_MCAN_IR_TEFL_MSK +/* Timestamp Wraparound */ +#define CAN_MCAN_IR_TSW_POS (16U) +#define CAN_MCAN_IR_TSW_MSK (0x1UL << CAN_MCAN_IR_TSW_POS) +#define CAN_MCAN_IR_TSW CAN_MCAN_IR_TSW_MSK +/* Message RAM Access Failure */ +#define CAN_MCAN_IR_MRAF_POS (17U) +#define CAN_MCAN_IR_MRAF_MSK (0x1UL << CAN_MCAN_IR_MRAF_POS) +#define CAN_MCAN_IR_MRAF CAN_MCAN_IR_MRAF_MSK +/* Timeout Occurred */ +#define CAN_MCAN_IR_TOO_POS (18U) +#define CAN_MCAN_IR_TOO_MSK (0x1UL << CAN_MCAN_IR_TOO_POS) +#define CAN_MCAN_IR_TOO CAN_MCAN_IR_TOO_MSK +/* Message stored to Dedicated Rx Buffer */ +#define CAN_MCAN_IR_DRX_POS (19U) +#define CAN_MCAN_IR_DRX_MSK (0x1UL << CAN_MCAN_IR_DRX_POS) +#define CAN_MCAN_IR_DRX CAN_MCAN_IR_DRX_MSK +/* Bit Error Corrected */ +#define CAN_MCAN_IR_BEC_POS (20U) +#define CAN_MCAN_IR_BEC_MSK (0x1UL << CAN_MCAN_IR_BEC_POS) +#define CAN_MCAN_IR_BEC CAN_MCAN_IR_BEC_MSK +/* Bit Error Uncorrected */ +#define CAN_MCAN_IR_BEU_POS (21U) +#define CAN_MCAN_IR_BEU_MSK (0x1UL << CAN_MCAN_IR_BEU_POS) +#define CAN_MCAN_IR_BEU CAN_MCAN_IR_BEU_MSK +/* Error Logging Overflow */ +#define CAN_MCAN_IR_ELO_POS (22U) +#define CAN_MCAN_IR_ELO_MSK (0x1UL << CAN_MCAN_IR_ELO_POS) +#define CAN_MCAN_IR_ELO CAN_MCAN_IR_ELO_MSK +/* Error Passive*/ +#define CAN_MCAN_IR_EP_POS (23U) +#define CAN_MCAN_IR_EP_MSK (0x1UL << CAN_MCAN_IR_EP_POS) +#define CAN_MCAN_IR_EP CAN_MCAN_IR_EP_MSK +/* Warning Status*/ +#define CAN_MCAN_IR_EW_POS (24U) +#define CAN_MCAN_IR_EW_MSK (0x1UL << CAN_MCAN_IR_EW_POS) +#define CAN_MCAN_IR_EW CAN_MCAN_IR_EW_MSK +/* Bus_Off Status*/ +#define CAN_MCAN_IR_BO_POS (25U) +#define CAN_MCAN_IR_BO_MSK (0x1UL << CAN_MCAN_IR_BO_POS) +#define CAN_MCAN_IR_BO CAN_MCAN_IR_BO_MSK +/* Watchdog Interrupt */ +#define CAN_MCAN_IR_WDI_POS (26U) +#define CAN_MCAN_IR_WDI_MSK (0x1UL << CAN_MCAN_IR_WDI_POS) +#define CAN_MCAN_IR_WDI CAN_MCAN_IR_WDI_MSK +/* Protocol Error in Arbitration Phase */ +#define CAN_MCAN_IR_PEA_POS (27U) +#define CAN_MCAN_IR_PEA_MSK (0x1UL << CAN_MCAN_IR_PEA_POS) +#define CAN_MCAN_IR_PEA CAN_MCAN_IR_PEA_MSK +/* Protocol Error in Data Phase */ +#define CAN_MCAN_IR_PED_POS (28U) +#define CAN_MCAN_IR_PED_MSK (0x1UL << CAN_MCAN_IR_PED_POS) +#define CAN_MCAN_IR_PED CAN_MCAN_IR_PED_MSK +/* Access to Reserved Address */ +#define CAN_MCAN_IR_ARA_POS (29U) +#define CAN_MCAN_IR_ARA_MSK (0x1UL << CAN_MCAN_IR_ARA_POS) +#define CAN_MCAN_IR_ARA CAN_MCAN_IR_ARA_MSK + +#endif /* CONFIG_CAN_STM32FD */ + +/*************** Bit definition for CAN_MCAN_IE register ********************/ +#ifdef CONFIG_CAN_STM32FD +/* Rx FIFO 0 New Message Enable */ +#define CAN_MCAN_IE_RF0N_POS (0U) +#define CAN_MCAN_IE_RF0N_MSK (0x1UL << CAN_MCAN_IE_RF0N_POS) +#define CAN_MCAN_IE_RF0N CAN_MCAN_IE_RF0N_MSK +/* Rx FIFO 0 Full Enable */ +#define CAN_MCAN_IE_RF0F_POS (1U) +#define CAN_MCAN_IE_RF0F_MSK (0x1UL << CAN_MCAN_IE_RF0F_POS) +#define CAN_MCAN_IE_RF0F CAN_MCAN_IE_RF0F_MSK +/* Rx FIFO 0 Message Lost Enable */ +#define CAN_MCAN_IE_RF0L_POS (2U) +#define CAN_MCAN_IE_RF0L_MSK (0x1UL << CAN_MCAN_IE_RF0L_POS) +#define CAN_MCAN_IE_RF0L CAN_MCAN_IE_RF0L_MSK +/* Rx FIFO 1 New Message Enable */ +#define CAN_MCAN_IE_RF1N_POS (3U) +#define CAN_MCAN_IE_RF1N_MSK (0x1UL << CAN_MCAN_IE_RF1N_POS) +#define CAN_MCAN_IE_RF1N CAN_MCAN_IE_RF1N_MSK +/* Rx FIFO 1 Full Enable */ +#define CAN_MCAN_IE_RF1F_POS (4U) +#define CAN_MCAN_IE_RF1F_MSK (0x1UL << CAN_MCAN_IE_RF1F_POS) +#define CAN_MCAN_IE_RF1F CAN_MCAN_IE_RF1F_MSK +/* Rx FIFO 1 Message Lost Enable */ +#define CAN_MCAN_IE_RF1L_POS (5U) +#define CAN_MCAN_IE_RF1L_MSK (0x1UL << CAN_MCAN_IE_RF1L_POS) +#define CAN_MCAN_IE_RF1L CAN_MCAN_IE_RF1L_MSK +/* High Priority Message Enable */ +#define CAN_MCAN_IE_HPM_POS (6U) +#define CAN_MCAN_IE_HPM_MSK (0x1UL << CAN_MCAN_IE_HPM_POS) +#define CAN_MCAN_IE_HPM CAN_MCAN_IE_HPM_MSK +/* Transmission Completed Enable */ +#define CAN_MCAN_IE_TC_POS (7U) +#define CAN_MCAN_IE_TC_MSK (0x1UL << CAN_MCAN_IE_TC_POS) +#define CAN_MCAN_IE_TC CAN_MCAN_IE_TC_MSK +/* Transmission Cancellation Finished Enable*/ +#define CAN_MCAN_IE_TCF_POS (8U) +#define CAN_MCAN_IE_TCF_MSK (0x1UL << CAN_MCAN_IE_TCF_POS) +#define CAN_MCAN_IE_TCF CAN_MCAN_IE_TCF_MSK +/* Tx FIFO Empty Enable */ +#define CAN_MCAN_IE_TFE_POS (9U) +#define CAN_MCAN_IE_TFE_MSK (0x1UL << CAN_MCAN_IE_TFE_POS) +#define CAN_MCAN_IE_TFE CAN_MCAN_IE_TFE_MSK +/* Tx Event FIFO New Entry Enable */ +#define CAN_MCAN_IE_TEFN_POS (10U) +#define CAN_MCAN_IE_TEFN_MSK (0x1UL << CAN_MCAN_IE_TEFN_POS) +#define CAN_MCAN_IE_TEFN CAN_MCAN_IE_TEFN_MSK +/* Tx Event FIFO Full Enable */ +#define CAN_MCAN_IE_TEFF_POS (11U) +#define CAN_MCAN_IE_TEFF_MSK (0x1UL << CAN_MCAN_IE_TEFF_POS) +#define CAN_MCAN_IE_TEFF CAN_MCAN_IE_TEFF_MSK +/* Tx Event FIFO Element Lost Enable */ +#define CAN_MCAN_IE_TEFL_POS (12U) +#define CAN_MCAN_IE_TEFL_MSK (0x1UL << CAN_MCAN_IE_TEFL_POS) +#define CAN_MCAN_IE_TEFL CAN_MCAN_IE_TEFL_MSK + /* Timestamp Wraparound Enable */ +#define CAN_MCAN_IE_TSW_POS (13U) +#define CAN_MCAN_IE_TSW_MSK (0x1UL << CAN_MCAN_IE_TSW_POS) +#define CAN_MCAN_IE_TSW CAN_MCAN_IE_TSW_MSK +/* Message RAM Access Failure Enable */ +#define CAN_MCAN_IE_MRAF_POS (14U) +#define CAN_MCAN_IE_MRAF_MSK (0x1UL << CAN_MCAN_IE_MRAF_POS) +#define CAN_MCAN_IE_MRAF CAN_MCAN_IE_MRAF_MSK +/* Timeout Occurred Enable */ +#define CAN_MCAN_IE_TOO_POS (15U) +#define CAN_MCAN_IE_TOO_MSK (0x1UL << CAN_MCAN_IE_TOO_POS) +#define CAN_MCAN_IE_TOO CAN_MCAN_IE_TOO_MSK +/* Error Logging Overflow Enable */ +#define CAN_MCAN_IE_ELO_POS (16U) +#define CAN_MCAN_IE_ELO_MSK (0x1UL << CAN_MCAN_IE_ELO_POS) +#define CAN_MCAN_IE_ELO CAN_MCAN_IE_ELO_MSK +/* Error Passive Enable */ +#define CAN_MCAN_IE_EP_POS (17U) +#define CAN_MCAN_IE_EP_MSK (0x1UL << CAN_MCAN_IE_EP_POS) +#define CAN_MCAN_IE_EP CAN_MCAN_IE_EP_MSK +/* Warning Status Enable */ +#define CAN_MCAN_IE_EW_POS (18U) +#define CAN_MCAN_IE_EW_MSK (0x1UL << CAN_MCAN_IE_EW_POS) +#define CAN_MCAN_IE_EW CAN_MCAN_IE_EW_MSK +/* Bus_Off Status Enable */ +#define CAN_MCAN_IE_BO_POS (19U) +#define CAN_MCAN_IE_BO_MSK (0x1UL << CAN_MCAN_IE_BO_POS) +#define CAN_MCAN_IE_BO CAN_MCAN_IE_BO_MSK +/* Watchdog Interrupt Enable */ +#define CAN_MCAN_IE_WDI_POS (20U) +#define CAN_MCAN_IE_WDI_MSK (0x1UL << CAN_MCAN_IE_WDI_POS) +#define CAN_MCAN_IE_WDI CAN_MCAN_IE_WDIE_MSK +/* Protocol Error in Arbitration Phase Enable */ +#define CAN_MCAN_IE_PEA_POS (21U) +#define CAN_MCAN_IE_PEA_MSK (0x1UL << CAN_MCAN_IE_PEA_POS) +#define CAN_MCAN_IE_PEA CAN_MCAN_IE_PEA_MSK +/* Protocol Error in Data Phase Enable */ +#define CAN_MCAN_IE_PED_POS (22U) +#define CAN_MCAN_IE_PED_MSK (0x1UL << CAN_MCAN_IE_PED_POS) +#define CAN_MCAN_IE_PED CAN_MCAN_IE_PED_MSK +/* Access to Reserved Address Enable */ +#define CAN_MCAN_IE_ARA_POS (23U) +#define CAN_MCAN_IE_ARA_MSK (0x1UL << CAN_MCAN_IE_ARA_POS) +#define CAN_MCAN_IE_ARA CAN_MCAN_IE_ARA_MSK + +#else /* CONFIG_CAN_STM32FD */ + +/* Rx FIFO 0 New Message */ +#define CAN_MCAN_IE_RF0N_POS (0U) +#define CAN_MCAN_IE_RF0N_MSK (0x1UL << CAN_MCAN_IE_RF0N_POS) +#define CAN_MCAN_IE_RF0N CAN_MCAN_IE_RF0N_MSK +/* Rx FIFO 0 Watermark Reached*/ +#define CAN_MCAN_IE_RF0W_POS (1U) +#define CAN_MCAN_IE_RF0W_MSK (0x1UL << CAN_MCAN_IE_RF0W_POS) +#define CAN_MCAN_IE_RF0W CAN_MCAN_IE_RF0W_MSK +/* Rx FIFO 0 Full */ +#define CAN_MCAN_IE_RF0F_POS (2U) +#define CAN_MCAN_IE_RF0F_MSK (0x1UL << CAN_MCAN_IE_RF0F_POS) +#define CAN_MCAN_IE_RF0F CAN_MCAN_IE_RF0F_MSK +/* Rx FIFO 0 Message Lost */ +#define CAN_MCAN_IE_RF0L_POS (3U) +#define CAN_MCAN_IE_RF0L_MSK (0x1UL << CAN_MCAN_IE_RF0L_POS) +#define CAN_MCAN_IE_RF0L CAN_MCAN_IE_RF0L_MSK +/* Rx FIFO 1 New Message */ +#define CAN_MCAN_IE_RF1N_POS (4U) +#define CAN_MCAN_IE_RF1N_MSK (0x1UL << CAN_MCAN_IE_RF1N_POS) +#define CAN_MCAN_IE_RF1N CAN_MCAN_IE_RF1N_MSK +/* Rx FIFO 1 Watermark Reached*/ +#define CAN_MCAN_IE_RF1W_POS (5U) +#define CAN_MCAN_IE_RF1W_MSK (0x1UL << CAN_MCAN_IE_RF1W_POS) +#define CAN_MCAN_IE_RF1W CAN_MCAN_IE_RF1W_MSK +/* Rx FIFO 1 Full */ +#define CAN_MCAN_IE_RF1F_POS (6U) +#define CAN_MCAN_IE_RF1F_MSK (0x1UL << CAN_MCAN_IE_RF1F_POS) +#define CAN_MCAN_IE_RF1F CAN_MCAN_IE_RF1F_MSK +/* Rx FIFO 1 Message Lost */ +#define CAN_MCAN_IE_RF1L_POS (7U) +#define CAN_MCAN_IE_RF1L_MSK (0x1UL << CAN_MCAN_IE_RF1L_POS) +#define CAN_MCAN_IE_RF1L CAN_MCAN_IE_RF1L_MSK +/* High Priority Message */ +#define CAN_MCAN_IE_HPM_POS (8U) +#define CAN_MCAN_IE_HPM_MSK (0x1UL << CAN_MCAN_IE_HPM_POS) +#define CAN_MCAN_IE_HPM CAN_MCAN_IE_HPM_MSK +/* Transmission Completed */ +#define CAN_MCAN_IE_TC_POS (9U) +#define CAN_MCAN_IE_TC_MSK (0x1UL << CAN_MCAN_IE_TC_POS) +#define CAN_MCAN_IE_TC CAN_MCAN_IE_TC_MSK +/* Transmission Cancellation Finished */ +#define CAN_MCAN_IE_TCF_POS (10U) +#define CAN_MCAN_IE_TCF_MSK (0x1UL << CAN_MCAN_IE_TCF_POS) +#define CAN_MCAN_IE_TCF CAN_MCAN_IE_TCF_MSK +/* Tx FIFO Empty */ +#define CAN_MCAN_IE_TFE_POS (11U) +#define CAN_MCAN_IE_TFE_MSK (0x1UL << CAN_MCAN_IE_TFE_POS) +#define CAN_MCAN_IE_TFE CAN_MCAN_IE_TFE_MSK +/* Tx Event FIFO New Entry */ +#define CAN_MCAN_IE_TEFN_POS (12U) +#define CAN_MCAN_IE_TEFN_MSK (0x1UL << CAN_MCAN_IE_TEFN_POS) +#define CAN_MCAN_IE_TEFN CAN_MCAN_IE_TEFN_MSK +/* Tx Event FIFO Watermark */ +#define CAN_MCAN_IE_TEFW_POS (13U) +#define CAN_MCAN_IE_TEFW_MSK (0x1UL << CAN_MCAN_IE_TEFW_POS) +#define CAN_MCAN_IE_TEFW CAN_MCAN_IE_TEFW_MSK +/* Tx Event FIFO Full */ +#define CAN_MCAN_IE_TEFF_POS (14U) +#define CAN_MCAN_IE_TEFF_MSK (0x1UL << CAN_MCAN_IE_TEFF_POS) +#define CAN_MCAN_IE_TEFF CAN_MCAN_IE_TEFF_MSK +/* Tx Event FIFO Element Lost */ +#define CAN_MCAN_IE_TEFL_POS (15U) +#define CAN_MCAN_IE_TEFL_MSK (0x1UL << CAN_MCAN_IE_TEFL_POS) +#define CAN_MCAN_IE_TEFL CAN_MCAN_IE_TEFL_MSK +/* Timestamp Wraparound */ +#define CAN_MCAN_IE_TSW_POS (16U) +#define CAN_MCAN_IE_TSW_MSK (0x1UL << CAN_MCAN_IE_TSW_POS) +#define CAN_MCAN_IE_TSW CAN_MCAN_IE_TSW_MSK +/* Message RAM Access Failure */ +#define CAN_MCAN_IE_MRAF_POS (17U) +#define CAN_MCAN_IE_MRAF_MSK (0x1UL << CAN_MCAN_IE_MRAF_POS) +#define CAN_MCAN_IE_MRAF CAN_MCAN_IE_MRAF_MSK +/* Timeout Occurred */ +#define CAN_MCAN_IE_TOO_POS (18U) +#define CAN_MCAN_IE_TOO_MSK (0x1UL << CAN_MCAN_IE_TOO_POS) +#define CAN_MCAN_IE_TOO CAN_MCAN_IE_TOO_MSK +/* Message stored to Dedicated Rx Buffer */ +#define CAN_MCAN_IE_DRX_POS (19U) +#define CAN_MCAN_IE_DRX_MSK (0x1UL << CAN_MCAN_IE_DRX_POS) +#define CAN_MCAN_IE_DRX CAN_MCAN_IE_DRX_MSK +/* Bit Error Corrected */ +#define CAN_MCAN_IE_BEC_POS (20U) +#define CAN_MCAN_IE_BEC_MSK (0x1UL << CAN_MCAN_IE_BEC_POS) +#define CAN_MCAN_IE_BEC CAN_MCAN_IE_BEC_MSK +/* Bit Error Uncorrected */ +#define CAN_MCAN_IE_BEU_POS (21U) +#define CAN_MCAN_IE_BEU_MSK (0x1UL << CAN_MCAN_IE_BEU_POS) +#define CAN_MCAN_IE_BEU CAN_MCAN_IE_BEU_MSK +/* Error Logging Overflow */ +#define CAN_MCAN_IE_ELO_POS (22U) +#define CAN_MCAN_IE_ELO_MSK (0x1UL << CAN_MCAN_IE_ELO_POS) +#define CAN_MCAN_IE_ELO CAN_MCAN_IE_ELO_MSK +/* Error Passive*/ +#define CAN_MCAN_IE_EP_POS (23U) +#define CAN_MCAN_IE_EP_MSK (0x1UL << CAN_MCAN_IE_EP_POS) +#define CAN_MCAN_IE_EP CAN_MCAN_IE_EP_MSK +/* Warning Status*/ +#define CAN_MCAN_IE_EW_POS (24U) +#define CAN_MCAN_IE_EW_MSK (0x1UL << CAN_MCAN_IE_EW_POS) +#define CAN_MCAN_IE_EW CAN_MCAN_IE_EW_MSK +/* Bus_Off Status*/ +#define CAN_MCAN_IE_BO_POS (25U) +#define CAN_MCAN_IE_BO_MSK (0x1UL << CAN_MCAN_IE_BO_POS) +#define CAN_MCAN_IE_BO CAN_MCAN_IE_BO_MSK +/* Watchdog Interrupt */ +#define CAN_MCAN_IE_WDI_POS (26U) +#define CAN_MCAN_IE_WDI_MSK (0x1UL << CAN_MCAN_IE_WDI_POS) +#define CAN_MCAN_IE_WDI CAN_MCAN_IE_WDI_MSK +/* Protocol Error in Arbitration Phase */ +#define CAN_MCAN_IE_PEA_POS (27U) +#define CAN_MCAN_IE_PEA_MSK (0x1UL << CAN_MCAN_IE_PEA_POS) +#define CAN_MCAN_IE_PEA CAN_MCAN_IE_PEA_MSK +/* Protocol Error in Data Phase */ +#define CAN_MCAN_IE_PED_POS (28U) +#define CAN_MCAN_IE_PED_MSK (0x1UL << CAN_MCAN_IE_PED_POS) +#define CAN_MCAN_IE_PED CAN_MCAN_IE_PED_MSK +/* Access to Reserved Address */ +#define CAN_MCAN_IE_ARA_POS (29U) +#define CAN_MCAN_IE_ARA_MSK (0x1UL << CAN_MCAN_IE_ARA_POS) +#define CAN_MCAN_IE_ARA CAN_MCAN_IE_ARA_MSK + +#endif /* CONFIG_CAN_STM32FD */ + +/*************** Bit definition for CAN_MCAN_ILS register *******************/ +#ifdef CONFIG_CAN_STM32FD +/* Rx FIFO 0 */ +#define CAN_MCAN_ILS_RXFIFO0_POS (0U) +#define CAN_MCAN_ILS_RXFIFO0_MSK (0x1UL << CAN_MCAN_ILS_RXFIFO0_POS) +#define CAN_MCAN_ILS_RXFIFO0 CAN_MCAN_ILS_RXFIFO0_MSK +/* Rx FIFO 1 */ +#define CAN_MCAN_ILS_RXFIFO1_POS (1U) +#define CAN_MCAN_ILS_RXFIFO1_MSK (0x1UL << CAN_MCAN_ILS_RXFIFO1_POS) +#define CAN_MCAN_ILS_RXFIFO1 CAN_MCAN_ILS_RXFIFO1_MSK +/* Transmission Cancellation Finished */ +#define CAN_MCAN_ILS_SMSG_POS (2U) +#define CAN_MCAN_ILS_SMSG_MSK (0x1UL << CAN_MCAN_ILS_SMSG_POS) +#define CAN_MCAN_ILS_SMSG CAN_MCAN_ILS_SMSG_MSK +/* Tx Event FIFO Element Lost */ +#define CAN_MCAN_ILS_TFERR_POS (3U) +#define CAN_MCAN_ILS_TFERR_MSK (0x1UL << CAN_MCAN_ILS_TFERR_POS) +#define CAN_MCAN_ILS_TFERR CAN_MCAN_ILS_TFERR_MSK +/* Timeout Occurred */ +#define CAN_MCAN_ILS_MISC_POS (4U) +#define CAN_MCAN_ILS_MISC_MSK (0x1UL << CAN_MCAN_ILS_MISC_POS) +#define CAN_MCAN_ILS_MISC CAN_MCAN_ILS_MISC_MSK +/* Error Passive Error Logging Overflow */ +#define CAN_MCAN_ILS_BERR_POS (5U) +#define CAN_MCAN_ILS_BERR_MSK (0x1UL << CAN_MCAN_ILS_BERR_POS) +#define CAN_MCAN_ILS_BERR CAN_MCAN_ILS_BERR_MSK +/* Access to Reserved Address Line */ +#define CAN_MCAN_ILS_PERR_POS (6U) +#define CAN_MCAN_ILS_PERR_MSK (0x1UL << CAN_MCAN_ILS_PERR_POS) +#define CAN_MCAN_ILS_PERR CAN_MCAN_ILS_PERR_MSK + +#else/* CONFIG_CAN_STM32FD */ +/* Rx FIFO 0 New Message */ +#define CAN_MCAN_ILS_RF0N_POS (0U) +#define CAN_MCAN_ILS_RF0N_MSK (0x1UL << CAN_MCAN_ILS_RF0N_POS) +#define CAN_MCAN_ILS_RF0N CAN_MCAN_ILS_RF0N_MSK +/* Rx FIFO 0 Watermark Reached*/ +#define CAN_MCAN_ILS_RF0W_POS (1U) +#define CAN_MCAN_ILS_RF0W_MSK (0x1UL << CAN_MCAN_ILS_RF0W_POS) +#define CAN_MCAN_ILS_RF0W CAN_MCAN_ILS_RF0W_MSK +/* Rx FIFO 0 Full */ +#define CAN_MCAN_ILS_RF0F_POS (2U) +#define CAN_MCAN_ILS_RF0F_MSK (0x1UL << CAN_MCAN_ILS_RF0F_POS) +#define CAN_MCAN_ILS_RF0F CAN_MCAN_ILS_RF0F_MSK +/* Rx FIFO 0 Message Lost */ +#define CAN_MCAN_ILS_RF0L_POS (3U) +#define CAN_MCAN_ILS_RF0L_MSK (0x1UL << CAN_MCAN_ILS_RF0L_POS) +#define CAN_MCAN_ILS_RF0L CAN_MCAN_ILS_RF0L_MSK +/* Rx FIFO 1 New Message */ +#define CAN_MCAN_ILS_RF1N_POS (4U) +#define CAN_MCAN_ILS_RF1N_MSK (0x1UL << CAN_MCAN_ILS_RF1N_POS) +#define CAN_MCAN_ILS_RF1N CAN_MCAN_ILS_RF1N_MSK +/* Rx FIFO 1 Watermark Reached*/ +#define CAN_MCAN_ILS_RF1W_POS (5U) +#define CAN_MCAN_ILS_RF1W_MSK (0x1UL << CAN_MCAN_ILS_RF1W_POS) +#define CAN_MCAN_ILS_RF1W CAN_MCAN_ILS_RF1W_MSK +/* Rx FIFO 1 Full */ +#define CAN_MCAN_ILS_RF1F_POS (6U) +#define CAN_MCAN_ILS_RF1F_MSK (0x1UL << CAN_MCAN_ILS_RF1F_POS) +#define CAN_MCAN_ILS_RF1F CAN_MCAN_ILS_RF1F_MSK +/* Rx FIFO 1 Message Lost */ +#define CAN_MCAN_ILS_RF1L_POS (7U) +#define CAN_MCAN_ILS_RF1L_MSK (0x1UL << CAN_MCAN_ILS_RF1L_POS) +#define CAN_MCAN_ILS_RF1L CAN_MCAN_ILS_RF1L_MSK +/* High Priority Message */ +#define CAN_MCAN_ILS_HPM_POS (8U) +#define CAN_MCAN_ILS_HPM_MSK (0x1UL << CAN_MCAN_ILS_HPM_POS) +#define CAN_MCAN_ILS_HPM CAN_MCAN_ILS_HPM_MSK +/* Transmission Completed */ +#define CAN_MCAN_ILS_TC_POS (9U) +#define CAN_MCAN_ILS_TC_MSK (0x1UL << CAN_MCAN_ILS_TC_POS) +#define CAN_MCAN_ILS_TC CAN_MCAN_ILS_TC_MSK +/* Transmission Cancellation Finished */ +#define CAN_MCAN_ILS_TCF_POS (10U) +#define CAN_MCAN_ILS_TCF_MSK (0x1UL << CAN_MCAN_ILS_TCF_POS) +#define CAN_MCAN_ILS_TCF CAN_MCAN_ILS_TCF_MSK +/* Tx FIFO Empty */ +#define CAN_MCAN_ILS_TFE_POS (11U) +#define CAN_MCAN_ILS_TFE_MSK (0x1UL << CAN_MCAN_ILS_TFE_POS) +#define CAN_MCAN_ILS_TFE CAN_MCAN_ILS_TFE_MSK +/* Tx Event FIFO New Entry */ +#define CAN_MCAN_ILS_TEFN_POS (12U) +#define CAN_MCAN_ILS_TEFN_MSK (0x1UL << CAN_MCAN_ILS_TEFN_POS) +#define CAN_MCAN_ILS_TEFN CAN_MCAN_ILS_TEFN_MSK +/* Tx Event FIFO Watermark */ +#define CAN_MCAN_ILS_TEFW_POS (13U) +#define CAN_MCAN_ILS_TEFW_MSK (0x1UL << CAN_MCAN_ILS_TEFW_POS) +#define CAN_MCAN_ILS_TEFW CAN_MCAN_ILS_TEFW_MSK +/* Tx Event FIFO Full */ +#define CAN_MCAN_ILS_TEFF_POS (14U) +#define CAN_MCAN_ILS_TEFF_MSK (0x1UL << CAN_MCAN_ILS_TEFF_POS) +#define CAN_MCAN_ILS_TEFF CAN_MCAN_ILS_TEFF_MSK +/* Tx Event FIFO Element Lost */ +#define CAN_MCAN_ILS_TEFL_POS (15U) +#define CAN_MCAN_ILS_TEFL_MSK (0x1UL << CAN_MCAN_ILS_TEFL_POS) +#define CAN_MCAN_ILS_TEFL CAN_MCAN_ILS_TEFL_MSK +/* Timestamp Wraparound */ +#define CAN_MCAN_ILS_TSW_POS (16U) +#define CAN_MCAN_ILS_TSW_MSK (0x1UL << CAN_MCAN_ILS_TSW_POS) +#define CAN_MCAN_ILS_TSW CAN_MCAN_ILS_TSW_MSK +/* Message RAM Access Failure */ +#define CAN_MCAN_ILS_MRAF_POS (17U) +#define CAN_MCAN_ILS_MRAF_MSK (0x1UL << CAN_MCAN_ILS_MRAF_POS) +#define CAN_MCAN_ILS_MRAF CAN_MCAN_ILS_MRAF_MSK +/* Timeout Occurred */ +#define CAN_MCAN_ILS_TOO_POS (18U) +#define CAN_MCAN_ILS_TOO_MSK (0x1UL << CAN_MCAN_ILS_TOO_POS) +#define CAN_MCAN_ILS_TOO CAN_MCAN_ILS_TOO_MSK +/* Message stored to Dedicated Rx Buffer */ +#define CAN_MCAN_ILS_DRX_POS (19U) +#define CAN_MCAN_ILS_DRX_MSK (0x1UL << CAN_MCAN_ILS_DRX_POS) +#define CAN_MCAN_ILS_DRX CAN_MCAN_ILS_DRX_MSK +/* Bit Error Corrected */ +#define CAN_MCAN_ILS_BEC_POS (20U) +#define CAN_MCAN_ILS_BEC_MSK (0x1UL << CAN_MCAN_ILS_BEC_POS) +#define CAN_MCAN_ILS_BEC CAN_MCAN_ILS_BEC_MSK +/* Bit Error Uncorrected */ +#define CAN_MCAN_ILS_BEU_POS (21U) +#define CAN_MCAN_ILS_BEU_MSK (0x1UL << CAN_MCAN_ILS_BEU_POS) +#define CAN_MCAN_ILS_BEU CAN_MCAN_ILS_BEU_MSK +/* Error Logging Overflow */ +#define CAN_MCAN_ILS_ELO_POS (22U) +#define CAN_MCAN_ILS_ELO_MSK (0x1UL << CAN_MCAN_ILS_ELO_POS) +#define CAN_MCAN_ILS_ELO CAN_MCAN_ILS_ELO_MSK +/* Error Passive*/ +#define CAN_MCAN_ILS_EP_POS (23U) +#define CAN_MCAN_ILS_EP_MSK (0x1UL << CAN_MCAN_ILS_EP_POS) +#define CAN_MCAN_ILS_EP CAN_MCAN_ILS_EP_MSK +/* Warning Status*/ +#define CAN_MCAN_ILS_EW_POS (24U) +#define CAN_MCAN_ILS_EW_MSK (0x1UL << CAN_MCAN_ILS_EW_POS) +#define CAN_MCAN_ILS_EW CAN_MCAN_ILS_EW_MSK +/* Bus_Off Status*/ +#define CAN_MCAN_ILS_BO_POS (25U) +#define CAN_MCAN_ILS_BO_MSK (0x1UL << CAN_MCAN_ILS_BO_POS) +#define CAN_MCAN_ILS_BO CAN_MCAN_ILS_BO_MSK +/* Watchdog Interrupt */ +#define CAN_MCAN_ILS_WDI_POS (26U) +#define CAN_MCAN_ILS_WDI_MSK (0x1UL << CAN_MCAN_ILS_WDI_POS) +#define CAN_MCAN_ILS_WDI CAN_MCAN_ILS_WDI_MSK +/* Protocol Error in Arbitration Phase */ +#define CAN_MCAN_ILS_PEA_POS (27U) +#define CAN_MCAN_ILS_PEA_MSK (0x1UL << CAN_MCAN_ILS_PEA_POS) +#define CAN_MCAN_ILS_PEA CAN_MCAN_ILS_PEA_MSK +/* Protocol Error in Data Phase */ +#define CAN_MCAN_ILS_PED_POS (28U) +#define CAN_MCAN_ILS_PED_MSK (0x1UL << CAN_MCAN_ILS_PED_POS) +#define CAN_MCAN_ILS_PED CAN_MCAN_ILS_PED_MSK +/* Access to Reserved Address */ +#define CAN_MCAN_ILS_ARA_POS (29U) +#define CAN_MCAN_ILS_ARA_MSK (0x1UL << CAN_MCAN_ILS_ARA_POS) +#define CAN_MCAN_ILS_ARA CAN_MCAN_IL_ARA_MSK + +#endif /* CONFIG_CAN_STM32FD */ + +/*************** Bit definition for CAN_MCAN_ILE register *******************/ +/* Enable Interrupt Line 0 */ +#define CAN_MCAN_ILE_EINT0_POS (0U) +#define CAN_MCAN_ILE_EINT0_MSK (0x1UL << CAN_MCAN_ILE_EINT0_POS) +#define CAN_MCAN_ILE_EINT0 CAN_MCAN_ILE_EINT0_MSK +/* Enable Interrupt Line 1 */ +#define CAN_MCAN_ILE_EINT1_POS (1U) +#define CAN_MCAN_ILE_EINT1_MSK (0x1UL << CAN_MCAN_ILE_EINT1_POS) +#define CAN_MCAN_ILE_EINT1 CAN_MCAN_ILE_EINT1_MSK + +/*************** Bit definition for CAN_MCAN_RXGFC register *****************/ +#ifdef CONFIG_CAN_STM32FD +/* Reject Remote Frames Extended */ +#define CAN_MCAN_RXGFC_RRFE_POS (0U) +#define CAN_MCAN_RXGFC_RRFE_MSK (0x1UL << CAN_MCAN_RXGFC_RRFE_POS) +#define CAN_MCAN_RXGFC_RRFE CAN_MCAN_RXGFC_RRFE_MSK +/* Reject Remote Frames Standard */ +#define CAN_MCAN_RXGFC_RRFS_POS (1U) +#define CAN_MCAN_RXGFC_RRFS_MSK (0x1UL << CAN_MCAN_RXGFC_RRFS_POS) +#define CAN_MCAN_RXGFC_RRFS CAN_MCAN_RXGFC_RRFS_MSK +/* Accept Non-matching Frames Extended */ +#define CAN_MCAN_RXGFC_ANFE_POS (2U) +#define CAN_MCAN_RXGFC_ANFE_MSK (0x3UL << CAN_MCAN_RXGFC_ANFE_POS) +#define CAN_MCAN_RXGFC_ANFE CAN_MCAN_RXGFC_ANFE_MSK +/* Accept Non-matching Frames Standard */ +#define CAN_MCAN_RXGFC_ANFS_POS (4U) +#define CAN_MCAN_RXGFC_ANFS_MSK (0x3UL << CAN_MCAN_RXGFC_ANFS_POS) +#define CAN_MCAN_RXGFC_ANFS CAN_MCAN_RXGFC_ANFS_MSK +/* FIFO 1 operation mode */ +#define CAN_MCAN_RXGFC_F1OM_POS (8U) +#define CAN_MCAN_RXGFC_F1OM_MSK (0x1UL << CAN_MCAN_RXGFC_F1OM_POS) +#define CAN_MCAN_RXGFC_F1OM CAN_MCAN_RXGFC_F1OM_MSK +/* FIFO 0 operation mode */ +#define CAN_MCAN_RXGFC_F0OM_POS (9U) +#define CAN_MCAN_RXGFC_F0OM_MSK (0x1UL << CAN_MCAN_RXGFC_F0OM_POS) +#define CAN_MCAN_RXGFC_F0OM CAN_MCAN_RXGFC_F0OM_MSK +/* List Size Standard */ +#define CAN_MCAN_RXGFC_LSS_POS (16U) +#define CAN_MCAN_RXGFC_LSS_MSK (0x1FUL << CAN_MCAN_RXGFC_LSS_POS) +#define CAN_MCAN_RXGFC_LSS CAN_MCAN_RXGFC_LSS_MSK +/* List Size Extended */ +#define CAN_MCAN_RXGFC_LSE_POS (24U) +#define CAN_MCAN_RXGFC_LSE_MSK (0xFUL << CAN_MCAN_RXGFC_LSE_POS) +#define CAN_MCAN_RXGFC_LSE CAN_MCAN_RXGFC_LSE_MSK + +#else /* CONFIG_CAN_STM32FD */ + +/* Reject Remote Frames Extended */ +#define CAN_MCAN_GFC_RRFE_POS (0U) +#define CAN_MCAN_GFC_RRFE_MSK (0x1UL << CAN_MCAN_GFC_RRFE_POS) +#define CAN_MCAN_GFC_RRFE CAN_MCAN_GFC_RRFE_MSK +/* Reject Remote Frames Standard */ +#define CAN_MCAN_GFC_RRFS_POS (1U) +#define CAN_MCAN_GFC_RRFS_MSK (0x1UL << CAN_MCAN_GFC_RRFS_POS) +#define CAN_MCAN_GFC_RRFS CAN_MCAN_GFC_RRFS_MSK +/* Accept Non-matching Frames Extended */ +#define CAN_MCAN_GFC_ANFE_POS (2U) +#define CAN_MCAN_GFC_ANFE_MSK (0x3UL << CAN_MCAN_GFC_ANFE_POS) +#define CAN_MCAN_GFC_ANFE CAN_MCAN_GFC_ANFE_MSK +/* Accept Non-matching Frames Standard */ +#define CAN_MCAN_GFC_ANFS_POS (4U) +#define CAN_MCAN_GFC_ANFS_MSK (0x3UL << CAN_MCAN_GFC_ANFS_POS) +#define CAN_MCAN_GFC_ANFS CAN_MCAN_GFC_ANFS_MSK + +/* Filter List Standard Start Address */ +#define CAN_MCAN_SIDFC_FLSSA_POS (2U) +#define CAN_MCAN_SIDFC_FLSSA_MSK (0x3FFFUL << CAN_MCAN_SIDFC_FLSSA_POS) +#define CAN_MCAN_SIDFC_FLSSA CAN_MCAN_SIDFC_FLSSA_MSK +/* List Size Standard */ +#define CAN_MCAN_SIDFC_LSS_POS (16U) +#define CAN_MCAN_SIDFC_LSS_MSK (0xFFUL << CAN_MCAN_SIDFC_LSS_POS) +#define CAN_MCAN_SIDFC_LSS CAN_MCAN_SIDFC_LSS_MSK + +/* Filter List Extended Start Address */ +#define CAN_MCAN_XIDFC_FLESA_POS (2U) +#define CAN_MCAN_XIDFC_FLESA_MSK (0x3FFFUL << CAN_MCAN_XIDFC_FLESA_POS) +#define CAN_MCAN_XIDFC_FLESA CAN_MCAN_XIDFC_FLESA_MSK +/* List Size Extended */ +#define CAN_MCAN_XIDFC_LSS_POS (16U) +#define CAN_MCAN_XIDFC_LSS_MSK (0x7FUL << CAN_MCAN_XIDFC_LSS_POS) +#define CAN_MCAN_XIDFC_LSS CAN_MCAN_XIDFC_LSS_MSK + +#endif /* CONFIG_CAN_STM32FD */ + +/*************** Bit definition for CAN_MCAN_XIDAM register *****************/ +/* Extended ID Mask */ +#define CAN_MCAN_XIDAM_EIDM_POS (0U) +#define CAN_MCAN_XIDAM_EIDM_MSK (0x1FFFFFFFUL << CAN_MCAN_XIDAM_EIDM_POS) +#define CAN_MCAN_XIDAM_EIDM CAN_MCAN_XIDAM_EIDM_MSK + +/*************** Bit definition for CAN_MCAN_HPMS register ******************/ +#ifdef CONFIG_CAN_STM32FD +/* Buffer Index */ +#define CAN_MCAN_HPMS_BIDX_POS (0U) +#define CAN_MCAN_HPMS_BIDX_MSK (0x7UL << CAN_MCAN_HPMS_BIDX_POS) +#define CAN_MCAN_HPMS_BIDX CAN_MCAN_HPMS_BIDX_MSK +/* Message Storage Indicator */ +#define CAN_MCAN_HPMS_MSI_POS (6U) +#define CAN_MCAN_HPMS_MSI_MSK (0x3UL << CAN_MCAN_HPMS_MSI_POS) +#define CAN_MCAN_HPMS_MSI CAN_MCAN_HPMS_MSI_MSK +/* Filter Index */ +#define CAN_MCAN_HPMS_FIDX_POS (8U) +#define CAN_MCAN_HPMS_FIDX_MSK (0x1FUL << CAN_MCAN_HPMS_FIDX_POS) +#define CAN_MCAN_HPMS_FIDX CAN_MCAN_HPMS_FIDX_MSK +/* Filter List */ +#define CAN_MCAN_HPMS_FLST_POS (15U) +#define CAN_MCAN_HPMS_FLST_MSK (0x1UL << CAN_MCAN_HPMS_FLST_POS) +#define CAN_MCAN_HPMS_FLST CAN_MCAN_HPMS_FLST_MSK + +#else /* CONFIG_CAN_STM32FD */ + +/* Buffer Index */ +#define CAN_MCAN_HPMS_BIDX_POS (0U) +#define CAN_MCAN_HPMS_BIDX_MSK (0x3FUL << CAN_MCAN_HPMS_BIDX_POS) +#define CAN_MCAN_HPMS_BIDX CAN_MCAN_HPMS_BIDX_MSK +/* Message Storage Indicator */ +#define CAN_MCAN_HPMS_MSI_POS (6U) +#define CAN_MCAN_HPMS_MSI_MSK (0x3UL << CAN_MCAN_HPMS_MSI_POS) +#define CAN_MCAN_HPMS_MSI CAN_MCAN_HPMS_MSI_MSK +/* Filter Index */ +#define CAN_MCAN_HPMS_FIDX_POS (8U) +#define CAN_MCAN_HPMS_FIDX_MSK (0x7FUL << CAN_MCAN_HPMS_FIDX_POS) +#define CAN_MCAN_HPMS_FIDX CAN_MCAN_HPMS_FIDX_MSK +/* Filter List */ +#define CAN_MCAN_HPMS_FLST_POS (15U) +#define CAN_MCAN_HPMS_FLST_MSK (0x1UL << CAN_MCAN_HPMS_FLST_POS) +#define CAN_MCAN_HPMS_FLST CAN_MCAN_HPMS_FLST_MSK + +#endif /* CONFIG_CAN_STM32FD */ + +/*************** Bit definition for CAN_MCAN_RXF0C register *****************/ +/* Rx FIFO 0 Start Address */ +#define CAN_MCAN_RXF0C_F0SA_POS (2U) +#define CAN_MCAN_RXF0C_F0SA_MSK (0x3FFFUL << CAN_MCAN_RXF0C_F0SA_POS) +#define CAN_MCAN_RXF0C_F0SA CAN_MCAN_RXF0C_F0SA_MSK +/* Rx FIFO 0 Size */ +#define CAN_MCAN_RXF0C_F0S_POS (16U) +#define CAN_MCAN_RXF0C_F0S_MSK (0x7FUL << CAN_MCAN_RXF0C_F0S_POS) +#define CAN_MCAN_RXF0C_F0S CAN_MCAN_RXF0C_F0S_MSK +/* Rx FIFO 0 Watermark */ +#define CAN_MCAN_RXF0C_F0WM_POS (24) +#define CAN_MCAN_RXF0C_F0WM_MSK (0x7FUL << CAN_MCAN_RXF0C_F0WM_POS) +#define CAN_MCAN_RXF0C_F0WM CAN_MCAN_RXF0C_F0WM_MSK +/* FIFO 0 Operation Mode */ +#define CAN_MCAN_RXF0C_F0OM_POS (31) +#define CAN_MCAN_RXF0C_F0OM_MSK (0x1UL << CAN_MCAN_RXF0C_F0OM_POS) +#define CAN_MCAN_RXF0C_F0OM CAN_MCAN_RXF0C_F0OM_MSK + +/*************** Bit definition for CAN_MCAN_RXF0S register *****************/ +#ifdef CONFIG_CAN_STM32FD +/* Rx FIFO 0 Fill Level */ +#define CAN_MCAN_RXF0S_F0FL_POS (0U) +#define CAN_MCAN_RXF0S_F0FL_MSK (0xFUL << CAN_MCAN_RXF0S_F0FL_POS) +#define CAN_MCAN_RXF0S_F0FL CAN_MCAN_RXF0S_F0FL_MSK +/* Rx FIFO 0 Get Index */ +#define CAN_MCAN_RXF0S_F0GI_POS (8U) +#define CAN_MCAN_RXF0S_F0GI_MSK (0x3UL << CAN_MCAN_RXF0S_F0GI_POS) +#define CAN_MCAN_RXF0S_F0GI CAN_MCAN_RXF0S_F0GI_MSK +/* Rx FIFO 0 Put Index */ +#define CAN_MCAN_RXF0S_F0PI_POS (16U) +#define CAN_MCAN_RXF0S_F0PI_MSK (0x3UL << CAN_MCAN_RXF0S_F0PI_POS) +#define CAN_MCAN_RXF0S_F0PI CAN_MCAN_RXF0S_F0PI_MSK +/* Rx FIFO 0 Full */ +#define CAN_MCAN_RXF0S_F0F_POS (24U) +#define CAN_MCAN_RXF0S_F0F_MSK (0x1UL << CAN_MCAN_RXF0S_F0F_POS) +#define CAN_MCAN_RXF0S_F0F CAN_MCAN_RXF0S_F0F_MSK +/* Rx FIFO 0 Message Lost */ +#define CAN_MCAN_RXF0S_RF0L_POS (25U) +#define CAN_MCAN_RXF0S_RF0L_MSK (0x1UL << CAN_MCAN_RXF0S_RF0L_POS) +#define CAN_MCAN_RXF0S_RF0L CAN_MCAN_RXF0S_RF0L_MSK + +#else /* CONFIG_CAN_STM32FD */ + +/* Rx FIFO 0 Fill Level */ +#define CAN_MCAN_RXF0S_F0FL_POS (0U) +#define CAN_MCAN_RXF0S_F0FL_MSK (0x3FUL << CAN_MCAN_RXF0S_F0FL_POS) +#define CAN_MCAN_RXF0S_F0FL CAN_MCAN_RXF0S_F0FL_MSK +/* Rx FIFO 0 Get Index */ +#define CAN_MCAN_RXF0S_F0GI_POS (8U) +#define CAN_MCAN_RXF0S_F0GI_MSK (0x3FUL << CAN_MCAN_RXF0S_F0GI_POS) +#define CAN_MCAN_RXF0S_F0GI CAN_MCAN_RXF0S_F0GI_MSK +/* Rx FIFO 0 Put Index */ +#define CAN_MCAN_RXF0S_F0PI_POS (16U) +#define CAN_MCAN_RXF0S_F0PI_MSK (0x3FUL << CAN_MCAN_RXF0S_F0PI_POS) +#define CAN_MCAN_RXF0S_F0PI CAN_MCAN_RXF0S_F0PI_MSK +/* Rx FIFO 0 Full */ +#define CAN_MCAN_RXF0S_F0F_POS (24U) +#define CAN_MCAN_RXF0S_F0F_MSK (0x1UL << CAN_MCAN_RXF0S_F0F_POS) +#define CAN_MCAN_RXF0S_F0F CAN_MCAN_RXF0S_F0F_MSK +/* Rx FIFO 0 Message Lost */ +#define CAN_MCAN_RXF0S_RF0L_POS (25U) +#define CAN_MCAN_RXF0S_RF0L_MSK (0x1UL << CAN_MCAN_RXF0S_RF0L_POS) +#define CAN_MCAN_RXF0S_RF0L CAN_MCAN_RXF0S_RF0L_MSK +#endif + +/*************** Bit definition for CAN_MCAN_RXF0A register *****************/ +#ifdef CONFIG_CAN_STM32FD +/* Rx FIFO 0 Acknowledge Index */ +#define CAN_MCAN_RXF0A_F0AI_POS (0U) +#define CAN_MCAN_RXF0A_F0AI_MSK (0x7UL << CAN_MCAN_RXF0A_F0AI_POS) +#define CAN_MCAN_RXF0A_F0AI CAN_MCAN_RXF0A_F0AI_MSK +#else +/* Rx FIFO 0 Acknowledge Index */ +#define CAN_MCAN_RXF0A_F0AI_POS (0U) +#define CAN_MCAN_RXF0A_F0AI_MSK (0x3FUL << CAN_MCAN_RXF0A_F0AI_POS) +#define CAN_MCAN_RXF0A_F0AI CAN_MCAN_RXF0A_F0AI_MSK + +#endif /* CONFIG_CAN_STM32FD */ + +/*************** Bit definition for CAN_MCAN_RXBC register ******************/ +/* Rx Buffer Start Address */ +#define CAN_MCAN_RXBC_RBSA_POS (2U) +#define CAN_MCAN_RXBC_RBSA_MSK (0x3FFFUL << CAN_MCAN_RXBC_RBSA_POS) +#define CAN_MCAN_RXBC_RBSA CAN_MCAN_RXBC_RBSA_MSK + +/*************** Bit definition for CAN_MCAN_RXF1C register *****************/ +/* Rx FIFO 0 Start Address */ +#define CAN_MCAN_RXF1C_F1SA_POS (2U) +#define CAN_MCAN_RXF1C_F1SA_MSK (0x3FFFUL << CAN_MCAN_RXF1C_F1SA_POS) +#define CAN_MCAN_RXF1C_F1SA CAN_MCAN_RXF1C_F1SA_MSK +/* Rx FIFO 0 Size */ +#define CAN_MCAN_RXF1C_F1S_POS (16U) +#define CAN_MCAN_RXF1C_F1S_MSK (0x7FUL << CAN_MCAN_RXF1C_F1S_POS) +#define CAN_MCAN_RXF1C_F1S CAN_MCAN_RXF1C_F1S_MSK +/* Rx FIFO 0 Watermark */ +#define CAN_MCAN_RXF1C_F1WM_POS (24) +#define CAN_MCAN_RXF1C_F1WM_MSK (0x7FUL << CAN_MCAN_RXF1C_F1WM_POS) +#define CAN_MCAN_RXF1C_F1WM CAN_MCAN_RXF1C_F1WM_MSK +/* FIFO 0 Operation Mode */ +#define CAN_MCAN_RXF1C_F1OM_POS (31) +#define CAN_MCAN_RXF1C_F1OM_MSK (0x1UL << CAN_MCAN_RXF1C_F1OM_POS) +#define CAN_MCAN_RXF1C_F1OM CAN_MCAN_RXF1C_F1OM_MSK + +/*************** Bit definition for CAN_MCAN_RXF1S register *****************/ +#ifdef CONFIG_CAN_STM32FD +/* Rx FIFO 1 Fill Level */ +#define CAN_MCAN_RXF1S_F1FL_POS (0U) +#define CAN_MCAN_RXF1S_F1FL_MSK (0xFUL << CAN_MCAN_RXF1S_F1FL_POS) +#define CAN_MCAN_RXF1S_F1FL CAN_MCAN_RXF1S_F1FL_MSK +/* Rx FIFO 1 Get Index */ +#define CAN_MCAN_RXF1S_F1GI_POS (8U) +#define CAN_MCAN_RXF1S_F1GI_MSK (0x3UL << CAN_MCAN_RXF1S_F1GI_POS) +#define CAN_MCAN_RXF1S_F1GI CAN_MCAN_RXF1S_F1GI_MSK +/* Rx FIFO 1 Put Index */ +#define CAN_MCAN_RXF1S_F1PI_POS (16U) +#define CAN_MCAN_RXF1S_F1PI_MSK (0x3UL << CAN_MCAN_RXF1S_F1PI_POS) +#define CAN_MCAN_RXF1S_F1PI CAN_MCAN_RXF1S_F1PI_MSK +/* Rx FIFO 1 Full */ +#define CAN_MCAN_RXF1S_F1F_POS (24U) +#define CAN_MCAN_RXF1S_F1F_MSK (0x1UL << CAN_MCAN_RXF1S_F1F_POS) +#define CAN_MCAN_RXF1S_F1F CAN_MCAN_RXF1S_F1F_MSK +/* Rx FIFO 1 Message Lost */ +#define CAN_MCAN_RXF1S_RF1L_POS (25U) +#define CAN_MCAN_RXF1S_RF1L_MSK (0x1UL << CAN_MCAN_RXF1S_RF1L_POS) +#define CAN_MCAN_RXF1S_RF1L CAN_MCAN_RXF1S_RF1L_MSK + +#else /* CONFIG_CAN_STM32FD */ + +/* Rx FIFO 1 Fill Level */ +#define CAN_MCAN_RXF1S_F1FL_POS (0U) +#define CAN_MCAN_RXF1S_F1FL_MSK (0x7FUL << CAN_MCAN_RXF1S_F1FL_POS) +#define CAN_MCAN_RXF1S_F1FL CAN_MCAN_RXF1S_F1FL_MSK +/* Rx FIFO 1 Get Index */ +#define CAN_MCAN_RXF1S_F1GI_POS (8U) +#define CAN_MCAN_RXF1S_F1GI_MSK (0x3FUL << CAN_MCAN_RXF1S_F1GI_POS) +#define CAN_MCAN_RXF1S_F1GI CAN_MCAN_RXF1S_F1GI_MSK +/* Rx FIFO 1 Put Index */ +#define CAN_MCAN_RXF1S_F1PI_POS (16U) +#define CAN_MCAN_RXF1S_F1PI_MSK (0x3FUL << CAN_MCAN_RXF1S_F1PI_POS) +#define CAN_MCAN_RXF1S_F1PI CAN_MCAN_RXF1S_F1PI_MSK +/* Rx FIFO 1 Full */ +#define CAN_MCAN_RXF1S_F1F_POS (24U) +#define CAN_MCAN_RXF1S_F1F_MSK (0x1UL << CAN_MCAN_RXF1S_F1F_POS) +#define CAN_MCAN_RXF1S_F1F CAN_MCAN_RXF1S_F1F_MSK +/* Rx FIFO 1 Message Lost */ +#define CAN_MCAN_RXF1S_RF1L_POS (25U) +#define CAN_MCAN_RXF1S_RF1L_MSK (0x1UL << CAN_MCAN_RXF1S_RF1L_POS) +#define CAN_MCAN_RXF1S_RF1L CAN_MCAN_RXF1S_RF1L_MSK + +#endif /* CONFIG_CAN_STM32FD */ + +/*************** Bit definition for CAN_MCAN_RXF1A register *****************/ +/* Rx FIFO 1 Acknowledge Index */ +#ifdef CONFIG_CAN_STM32FD +#define CAN_MCAN_RXF1A_F1AI_POS (0U) +#define CAN_MCAN_RXF1A_F1AI_MSK (0x7UL << CAN_MCAN_RXF1A_F1AI_POS) +#define CAN_MCAN_RXF1A_F1AI CAN_MCAN_RXF1A_F1AI_MSK +#else +#define CAN_MCAN_RXF1A_F1AI_POS (0U) +#define CAN_MCAN_RXF1A_F1AI_MSK (0x3FUL << CAN_MCAN_RXF1A_F1AI_POS) +#define CAN_MCAN_RXF1A_F1AI CAN_MCAN_RXF1A_F1AI_MSK +#endif /* CONFIG_CAN_STM32FD */ + +/*************** Bit definition for CAN_MCAN_RXESC register *****************/ +/* Rx FIFO 0 Data Field Size */ +#define CAN_MCAN_RXESC_F0DS_POS (0U) +#define CAN_MCAN_RXESC_F0DS_MSK (0x7UL << CAN_MCAN_RXESC_F0DS_POS) +#define CAN_MCAN_RXESC_F0DS CAN_MCAN_RXESC_F0DS_MSK +/* Rx FIFO 1 Data Field Size */ +#define CAN_MCAN_RXESC_F1DS_POS (4U) +#define CAN_MCAN_RXESC_F1DS_MSK (0x7UL << CAN_MCAN_RXESC_F1DS_POS) +#define CAN_MCAN_RXESC_F1DS CAN_MCAN_RXESC_F1DS_MSK +/* Receive Buffer Data Field Size */ +#define CAN_MCAN_RXESC_RBDS_POS (8U) +#define CAN_MCAN_RXESC_RBDS_MSK (0x7UL << CAN_MCAN_RXESC_RBDS_POS) +#define CAN_MCAN_RXESC_RBDS CAN_MCAN_RXESC_RBDS_MSK + +/*************** Bit definition for CAN_MCAN_TXBC register ******************/ +#ifdef CONFIG_CAN_STM32FD +/* Tx FIFO/Queue Mode */ +#define CAN_MCAN_TXBC_TFQM_POS (24U) +#define CAN_MCAN_TXBC_TFQM_MSK (0x1UL << CAN_MCAN_TXBC_TFQM_POS) +#define CAN_MCAN_TXBC_TFQM CAN_MCAN_TXBC_TFQM_MSK +#else +/* Tx Buffers Start Address */ +#define CAN_MCAN_TXBC_TBSA_POS (2U) +#define CAN_MCAN_TXBC_TBSA_MSK (0x3FFFUL << CAN_MCAN_TXBC_TBSA_POS) +#define CAN_MCAN_TXBC_TBSA CAN_MCAN_TXBC_TBSA_MSK +/* Number of Dedicated Transmit Buffers */ +#define CAN_MCAN_TXBC_NDTB_POS (16U) +#define CAN_MCAN_TXBC_NDTB_MSK (0x3FUL << CAN_MCAN_TXBC_NDTB_POS) +#define CAN_MCAN_TXBC_NDTB CAN_MCAN_TXBC_NDTB_MSK +/* Transmit FIFO/Queue Size */ +#define CAN_MCAN_TXBC_TFQS_POS (24U) +#define CAN_MCAN_TXBC_TFQS_MSK (0x3FUL << CAN_MCAN_TXBC_TFQS_POS) +#define CAN_MCAN_TXBC_TFQS CAN_MCAN_TXBC_TFQS_MSK +/* Tx FIFO/Queue Mode */ +#define CAN_MCAN_TXBC_TFQM_POS (30U) +#define CAN_MCAN_TXBC_TFQM_MSK (0x3FUL << CAN_MCAN_TXBC_TFQM_POS) +#define CAN_MCAN_TXBC_TFQM CAN_MCAN_TXBC_TFQM_MSK + +#endif /* CONFIG_CAN_STM32FD */ + +/*************** Bit definition for CAN_MCAN_TXFQS register *****************/ +#ifdef CONFIG_CAN_STM32FD +/* Tx FIFO Free Level */ +#define CAN_MCAN_TXFQS_TFFL_POS (0U) +#define CAN_MCAN_TXFQS_TFFL_MSK (0x7UL << CAN_MCAN_TXFQS_TFFL_POS) +#define CAN_MCAN_TXFQS_TFFL CAN_MCAN_TXFQS_TFFL_MSK +/* Tx FIFO Get Index */ +#define CAN_MCAN_TXFQS_TFGI_POS (8U) +#define CAN_MCAN_TXFQS_TFGI_MSK (0x3UL << CAN_MCAN_TXFQS_TFGI_POS) +#define CAN_MCAN_TXFQS_TFGI CAN_MCAN_TXFQS_TFGI_MSK +/* Tx FIFO/Queue Put Index */ +#define CAN_MCAN_TXFQS_TFQPI_POS (16U) +#define CAN_MCAN_TXFQS_TFQPI_MSK (0x3UL << CAN_MCAN_TXFQS_TFQPI_POS) +#define CAN_MCAN_TXFQS_TFQPI CAN_MCAN_TXFQS_TFQPI_MSK +/* Tx FIFO/Queue Full */ +#define CAN_MCAN_TXFQS_TFQF_POS (21U) +#define CAN_MCAN_TXFQS_TFQF_MSK (0x1UL << CAN_MCAN_TXFQS_TFQF_POS) +#define CAN_MCAN_TXFQS_TFQF CAN_MCAN_TXFQS_TFQF_MSK + +#else /* CONFIG_CAN_STM32FD */ + +/* Tx FIFO Free Level */ +#define CAN_MCAN_TXFQS_TFFL_POS (0U) +#define CAN_MCAN_TXFQS_TFFL_MSK (0x3FUL << CAN_MCAN_TXFQS_TFFL_POS) +#define CAN_MCAN_TXFQS_TFFL CAN_MCAN_TXFQS_TFFL_MSK +/* Tx FIFO Get Index */ +#define CAN_MCAN_TXFQS_TFGI_POS (8U) +#define CAN_MCAN_TXFQS_TFGI_MSK (0x1FUL << CAN_MCAN_TXFQS_TFGI_POS) +#define CAN_MCAN_TXFQS_TFGI CAN_MCAN_TXFQS_TFGI_MSK +/* Tx FIFO/Queue Put Index */ +#define CAN_MCAN_TXFQS_TFQPI_POS (16U) +#define CAN_MCAN_TXFQS_TFQPI_MSK (0x1FUL << CAN_MCAN_TXFQS_TFQPI_POS) +#define CAN_MCAN_TXFQS_TFQPI CAN_MCAN_TXFQS_TFQPI_MSK +/* Tx FIFO/Queue Full */ +#define CAN_MCAN_TXFQS_TFQF_POS (21U) +#define CAN_MCAN_TXFQS_TFQF_MSK (0x1UL << CAN_MCAN_TXFQS_TFQF_POS) +#define CAN_MCAN_TXFQS_TFQF CAN_MCAN_TXFQS_TFQF_MSK + +#endif /* CONFIG_CAN_STM32FD */ + +/*************** Bit definition for CAN_MCAN_TXESC register *****************/ +/* Tx Buffer Data Field Size */ +#define CAN_MCAN_TXESC_TBDS_POS (0U) +#define CAN_MCAN_TXESC_TBDS_MSK (0x7UL << CAN_MCAN_TXESC_TBDS_POS) +#define CAN_MCAN_TXESC_TBDS CAN_MCAN_TXESC_TBDS_MSK + +/*************** Bit definition for CAN_MCAN_TXBRP register *****************/ +#ifdef CONFIG_CAN_STM32FD +/* Transmission Request Pending */ +#define CAN_MCAN_TXBRP_TRP_POS (0U) +#define CAN_MCAN_TXBRP_TRP_MSK (0x7UL << CAN_MCAN_TXBRP_TRP_POS) +#define CAN_MCAN_TXBRP_TRP CAN_MCAN_TXBRP_TRP_MSK +#else +/* Transmission Request Pending */ +#define CAN_MCAN_TXBRP_TRP_POS (0U) +#define CAN_MCAN_TXBRP_TRP_MSK (0xFFFFFFFFUL << CAN_MCAN_TXBRP_TRP_POS) +#define CAN_MCAN_TXBRP_TRP CAN_MCAN_TXBRP_TRP_MSK +#endif /* CONFIG_CAN_STM32FD */ + +/*************** Bit definition for CAN_MCAN_TXBAR register *****************/ +#ifdef CONFIG_CAN_STM32FD +/* Add Request */ +#define CAN_MCAN_TXBAR_AR_POS (0U) +#define CAN_MCAN_TXBAR_AR_MSK (0x7UL << CAN_MCAN_TXBAR_AR_POS) +#define CAN_MCAN_TXBAR_AR CAN_MCAN_TXBAR_AR_MSK +#else +/* Add Request */ +#define CAN_MCAN_TXBAR_AR_POS (0U) +#define CAN_MCAN_TXBAR_AR_MSK (0xFFFFFFFFUL << CAN_MCAN_TXBAR_AR_POS) +#define CAN_MCAN_TXBAR_AR CAN_MCAN_TXBAR_AR_MSK +#endif /* CONFIG_CAN_STM32FD */ + +/*************** Bit definition for CAN_MCAN_TXBCR register *****************/ +#ifdef CONFIG_CAN_STM32FD +/* Cancellation Request */ +#define CAN_MCAN_TXBCR_CR_POS (0U) +#define CAN_MCAN_TXBCR_CR_MSK (0x7UL << CAN_MCAN_TXBCR_CR_POS) +#define CAN_MCAN_TXBCR_CR CAN_MCAN_TXBCR_CR_MSK +#else +/* Cancellation Request */ +#define CAN_MCAN_TXBCR_CR_POS (0U) +#define CAN_MCAN_TXBCR_CR_MSK (0xFFFFFFFFUL << CAN_MCAN_TXBCR_CR_POS) +#define CAN_MCAN_TXBCR_CR CAN_MCAN_TXBCR_CR_MSK +#endif /* CONFIG_CAN_STM32FD */ + +/*************** Bit definition for CAN_MCAN_TXBTO register *****************/ +#ifdef CONFIG_CAN_STM32FD +/* Transmission Occurred */ +#define CAN_MCAN_TXBTO_TO_POS (0U) +#define CAN_MCAN_TXBTO_TO_MSK (0x7UL << CAN_MCAN_TXBTO_TO_POS) +#define CAN_MCAN_TXBTO_TO CAN_MCAN_TXBTO_TO_MSK +#else +/* Transmission Occurred */ +#define CAN_MCAN_TXBTO_TO_POS (0U) +#define CAN_MCAN_TXBTO_TO_MSK (0xFFFFFFFFUL << CAN_MCAN_TXBTO_TO_POS) +#define CAN_MCAN_TXBTO_TO CAN_MCAN_TXBTO_TO_MSK +#endif /* CONFIG_CAN_STM32FD */ + +/*************** Bit definition for CAN_MCAN_TXBCF register *****************/ +#ifdef CONFIG_CAN_STM32FD +/* Cancellation Finished */ +#define CAN_MCAN_TXBCF_CF_POS (0U) +#define CAN_MCAN_TXBCF_CF_MSK (0x7UL << CAN_MCAN_TXBCF_CF_POS) +#define CAN_MCAN_TXBCF_CF CAN_MCAN_TXBCF_CF_MSK +#else +/* Cancellation Finished */ +#define CAN_MCAN_TXBCF_CF_POS (0U) +#define CAN_MCAN_TXBCF_CF_MSK (0xFFFFFFFFUL << CAN_MCAN_TXBCF_CF_POS) +#define CAN_MCAN_TXBCF_CF CAN_MCAN_TXBCF_CF_MSK +#endif /* CONFIG_CAN_STM32FD */ + +/*************** Bit definition for CAN_MCAN_TXBTIE register ****************/ +#ifdef CONFIG_CAN_STM32FD +/* Transmission Interrupt Enable */ +#define CAN_MCAN_TXBTIE_TIE_POS (0U) +#define CAN_MCAN_TXBTIE_TIE_MSK (0x7UL << CAN_MCAN_TXBTIE_TIE_POS) +#define CAN_MCAN_TXBTIE_TIE CAN_MCAN_TXBTIE_TIE_MSK +#else +/* Transmission Interrupt Enable */ +#define CAN_MCAN_TXBTIE_TIE_POS (0U) +#define CAN_MCAN_TXBTIE_TIE_MSK (0xFFFFFFFFUL << CAN_MCAN_TXBTIE_TIE_POS) +#define CAN_MCAN_TXBTIE_TIE CAN_MCAN_TXBTIE_TIE_MSK +#endif /* CONFIG_CAN_STM32FD */ + +/*************** Bit definition for CAN_MCAN_ TXBCIE register ***************/ +#ifdef CONFIG_CAN_STM32FD +/* Cancellation Finished Interrupt Enable */ +#define CAN_MCAN_TXBCIE_CFIE_POS (0U) +#define CAN_MCAN_TXBCIE_CFIE_MSK (0x7UL << CAN_MCAN_TXBCIE_CFIE_POS) +#define CAN_MCAN_TXBCIE_CFIE CAN_MCAN_TXBCIE_CFIE_MSK +#else +/* Cancellation Finished Interrupt Enable */ +#define CAN_MCAN_TXBCIE_CFIE_POS (0U) +#define CAN_MCAN_TXBCIE_CFIE_MSK (0xFFFFFFFFUL << CAN_MCAN_TXBCIE_CFIE_POS) +#define CAN_MCAN_TXBCIE_CFIE CAN_MCAN_TXBCIE_CFIE_MSK +#endif /* CONFIG_CAN_STM32FD */ + +/*************** Bit definition for CAN_MCAN_TXEFC register *****************/ +/* Event FIFO Watermark */ +#define CAN_MCAN_TXEFC_EFSA_POS (0U) +#define CAN_MCAN_TXEFC_EFSA_MSK (0x3FFFUL << CAN_MCAN_TXEFC_EFSA_POS) +#define CAN_MCAN_TXEFC_EFSA CAN_MCAN_TXEFC_EFSA_MSK +/* Event FIFO Size */ +#define CAN_MCAN_TXEFC_EFS_POS (16U) +#define CAN_MCAN_TXEFC_EFS_MSK (0x3FUL << CAN_MCAN_TXEFC_EFS_POS) +#define CAN_MCAN_TXEFC_EFS CAN_MCAN_TXEFC_EFS_MSK +/* Event FIFO Start Address */ +#define CAN_MCAN_TXEFC_EFWM_POS (24U) +#define CAN_MCAN_TXEFC_EFWM_MSK (0x3FUL << CAN_MCAN_TXEFC_EFWM_POS) +#define CAN_MCAN_TXEFC_EFWM CAN_MCAN_TXEFC_EFWM_POS + +/*************** Bit definition for CAN_MCAN_TXEFS register *****************/ +#ifdef CONFIG_CAN_STM32FD +/* Event FIFO Fill Level */ +#define CAN_MCAN_TXEFS_EFFL_POS (0U) +#define CAN_MCAN_TXEFS_EFFL_MSK (0x7UL << CAN_MCAN_TXEFS_EFFL_POS) +#define CAN_MCAN_TXEFS_EFFL CAN_MCAN_TXEFS_EFFL_MSK +/* Event FIFO Get Index */ +#define CAN_MCAN_TXEFS_EFGI_POS (8U) +#define CAN_MCAN_TXEFS_EFGI_MSK (0x3UL << CAN_MCAN_TXEFS_EFGI_POS) +#define CAN_MCAN_TXEFS_EFGI CAN_MCAN_TXEFS_EFGI_MSK +/* Event FIFO Put Index */ +#define CAN_MCAN_TXEFS_EFPI_POS (16U) +#define CAN_MCAN_TXEFS_EFPI_MSK (0x3UL << CAN_MCAN_TXEFS_EFPI_POS) +#define CAN_MCAN_TXEFS_EFPI CAN_MCAN_TXEFS_EFPI_MSK +/* Event FIFO Full */ +#define CAN_MCAN_TXEFS_EFF_POS (24U) +#define CAN_MCAN_TXEFS_EFF_MSK (0x1UL << CAN_MCAN_TXEFS_EFF_POS) +#define CAN_MCAN_TXEFS_EFF CAN_MCAN_TXEFS_EFF_MSK +/* Tx Event FIFO Element Lost */ +#define CAN_MCAN_TXEFS_TEFL_POS (25U) +#define CAN_MCAN_TXEFS_TEFL_MSK (0x1UL << CAN_MCAN_TXEFS_TEFL_POS) +#define CAN_MCAN_TXEFS_TEFL CAN_MCAN_TXEFS_TEFL_MSK + +#else /* CONFIG_CAN_STM32FD */ +/* Event FIFO Fill Level */ +#define CAN_MCAN_TXEFS_EFFL_POS (0U) +#define CAN_MCAN_TXEFS_EFFL_MSK (0x3FUL << CAN_MCAN_TXEFS_EFFL_POS) +#define CAN_MCAN_TXEFS_EFFL CAN_MCAN_TXEFS_EFFL_MSK +/* Event FIFO Get Index */ +#define CAN_MCAN_TXEFS_EFGI_POS (8U) +#define CAN_MCAN_TXEFS_EFGI_MSK (0x1FUL << CAN_MCAN_TXEFS_EFGI_POS) +#define CAN_MCAN_TXEFS_EFGI CAN_MCAN_TXEFS_EFGI_MSK +#define CAN_MCAN_TXEFS_EFPI_POS (16U) +/* Event FIFO Put Index */ +#define CAN_MCAN_TXEFS_EFPI_MSK (0x1FUL << CAN_MCAN_TXEFS_EFPI_POS) +#define CAN_MCAN_TXEFS_EFPI CAN_MCAN_TXEFS_EFPI_MSK +/* Event FIFO Full */ +#define CAN_MCAN_TXEFS_EFF_POS (24U) +#define CAN_MCAN_TXEFS_EFF_MSK (0x1UL << CAN_MCAN_TXEFS_EFF_POS) +#define CAN_MCAN_TXEFS_EFF CAN_MCAN_TXEFS_EFF_MSK +/* Tx Event FIFO Element Lost */ +#define CAN_MCAN_TXEFS_TEFL_POS (25U) +#define CAN_MCAN_TXEFS_TEFL_MSK (0x1UL << CAN_MCAN_TXEFS_TEFL_POS) +#define CAN_MCAN_TXEFS_TEFL CAN_MCAN_TXEFS_TEFL_MSK + +#endif /* CONFIG_CAN_STM32FD */ + +/*************** Bit definition for CAN_MCAN_TXEFA register *****************/ +#ifdef CONFIG_CAN_STM32FD +/* Event FIFO Acknowledge Index */ +#define CAN_MCAN_TXEFA_EFAI_POS (0U) +#define CAN_MCAN_TXEFA_EFAI_MSK (0x3UL << CAN_MCAN_TXEFA_EFAI_POS) +#define CAN_MCAN_TXEFA_EFAI CAN_MCAN_TXEFA_EFAI_MSK +#else +/* Event FIFO Acknowledge Index */ +#define CAN_MCAN_TXEFA_EFAI_POS (0U) +#define CAN_MCAN_TXEFA_EFAI_MSK (0x1FUL << CAN_MCAN_TXEFA_EFAI_POS) +#define CAN_MCAN_TXEFA_EFAI CAN_MCAN_TXEFA_EFAI_MSK +#endif /* CONFIG_CAN_STM32FD */ + +#ifdef CONFIG_CAN_STM32FD +struct can_mcan_reg { + volatile uint32_t crel; /* Core Release Register */ + volatile uint32_t endn; /* Endian Register */ + volatile uint32_t cust; /* Customer Register */ + volatile uint32_t dbtp; /* Data Bit Timing & Prescaler Register */ + volatile uint32_t test; /* Test Register */ + volatile uint32_t rwd; /* RAM Watchdog */ + volatile uint32_t cccr; /* CC Control Register */ + volatile uint32_t nbtp; /* Nominal Bit Timing & Prescaler Register */ + volatile uint32_t tscc; /* Timestamp Counter Configuration */ + volatile uint32_t tscv; /* Timestamp Counter Value */ + volatile uint32_t tocc; /* Timeout Counter Configuration */ + volatile uint32_t tocv; /* Timeout Counter Value */ + uint32_t res1[4]; /* Reserved (4) */ + volatile uint32_t ecr; /* Error Counter Register */ + volatile uint32_t psr; /* Protocol Status Register */ + volatile uint32_t tdcr; /* Transmitter Delay Compensation */ + uint32_t res2; /* Reserved (1) */ + volatile uint32_t ir; /* Interrupt Register */ + volatile uint32_t ie; /* Interrupt Enable */ + volatile uint32_t ils; /* Interrupt Line Select */ + volatile uint32_t ile; /* Interrupt Line Enable */ + uint32_t res3[8]; /* Reserved (8) */ + volatile uint32_t rxgfc; /* Global Filter Configuration */ + volatile uint32_t xidam; /* Extended ID AND Mask */ + volatile uint32_t hpms; /* High Priority Message Status */ + uint32_t res4; /* Reserved (1) */ + volatile uint32_t rxf0s; /* Rx FIFO 0 Status */ + volatile uint32_t rxf0a; /* Rx FIFO 0 Acknowledge */ + volatile uint32_t rxf1s; /* Rx FIFO 1 Status */ + volatile uint32_t rxf1a; /* Rx FIFO 1 Acknowledge */ + uint32_t res5[8]; /* Reserved (8) */ + volatile uint32_t txbc; /* Tx Buffer Configuration */ + volatile uint32_t txfqs; /* Tx FIFO/Queue Status */ + volatile uint32_t txbrp; /* Tx Buffer Request Pending */ + volatile uint32_t txbar; /* Tx Buffer Add Request */ + volatile uint32_t txbcr; /* Tx Buffer Cancellation */ + volatile uint32_t txbto; /* Tx Buffer Transmission */ + volatile uint32_t txbcf; /* Tx Buffer Cancellation Finished */ + volatile uint32_t txbtie; /* Tx Buffer Transmission Interrupt Enable */ + volatile uint32_t txcbie; /* Tx Buffer Cancellation Fi.Interrupt En. */ + volatile uint32_t txefs; /* Tx Event FIFO Status */ + volatile uint32_t txefa; /* Tx Event FIFO Acknowledge */ +}; +#else /* CONFIG_CAN_STM32FD */ + +struct can_mcan_reg { + volatile uint32_t crel; /* Core Release Register */ + volatile uint32_t endn; /* Endian Register */ + volatile uint32_t cust; /* Customer Register */ + volatile uint32_t dbtp; /* Data Bit Timing & Prescaler Register */ + volatile uint32_t test; /* Test Register */ + volatile uint32_t rwd; /* RAM Watchdog */ + volatile uint32_t cccr; /* CC Control Register */ + volatile uint32_t nbtp; /* Nominal Bit Timing & Prescaler Register */ + volatile uint32_t tscc; /* Timestamp Counter Configuration */ + volatile uint32_t tscv; /* Timestamp Counter Value */ + volatile uint32_t tocc; /* Timeout Counter Configuration */ + volatile uint32_t tocv; /* Timeout Counter Value */ + uint32_t res1[4]; /* Reserved (4) */ + volatile uint32_t ecr; /* Error Counter Register */ + volatile uint32_t psr; /* Protocol Status Register */ + volatile uint32_t tdcr; /* Transmitter Delay Compensation */ + uint32_t res2; /* Reserved (1) */ + volatile uint32_t ir; /* Interrupt Register */ + volatile uint32_t ie; /* Interrupt Enable */ + volatile uint32_t ils; /* Interrupt Line Select */ + volatile uint32_t ile; /* Interrupt Line Enable */ + uint32_t res3[8]; /* Reserved (8) */ + volatile uint32_t gfc; /* Global Filter Configuration */ + volatile uint32_t sidfc; /* Standard ID Filter Configuration */ + volatile uint32_t xidfc; /* Extended ID Filter Configuration */ + volatile uint32_t res4; /* Reserved (1) */ + volatile uint32_t xidam; /* Extended ID AND Mask */ + volatile uint32_t hpms; /* High Priority Message Status */ + volatile uint32_t ndata1; /* New Data 1 */ + volatile uint32_t ndata2; /* New Data 2 */ + volatile uint32_t rxf0c; /* Rx FIFO 0 Configuration */ + volatile uint32_t rxf0s; /* Rx FIFO 0 Status */ + volatile uint32_t rxf0a; /* FIFO 0 Acknowledge */ + volatile uint32_t rxbc; /* Rx Buffer Configuration */ + volatile uint32_t rxf1c; /* Rx FIFO 1 Configuration */ + volatile uint32_t rxf1s; /* Rx FIFO 1 Status */ + volatile uint32_t rxf1a; /* Rx FIFO 1 Acknowledge*/ + volatile uint32_t rxesc; /* Rx Buffer / FIFO Element Size Config */ + volatile uint32_t txbc; /* Buffer Configuration */ + volatile uint32_t txfqs; /* FIFO/Queue Status */ + volatile uint32_t txesc; /* Tx Buffer Element Size Configuration */ + volatile uint32_t txbrp; /* Buffer Request Pending */ + volatile uint32_t txbar; /* Add Request */ + volatile uint32_t txbcr; /* Buffer Cancellation Request */ + volatile uint32_t txbto; /* Tx Buffer Transmission Occurred */ + volatile uint32_t txbcf; /* Tx Buffer Cancellation Finished */ + volatile uint32_t txbtie; /* Tx Buffer Transmission Interrupt Enable */ + volatile uint32_t txbcie; /* Tx Buffer Cancellation Fin. Interrupt En. */ + volatile uint32_t res5[2]; /* Reserved (2) */ + volatile uint32_t txefc; /* Tx Event FIFO Configuration */ + volatile uint32_t txefs; /* Tx Event FIFO Status */ + volatile uint32_t txefa; /* Tx Event FIFO Acknowledge */ +}; + +#endif /* CONFIG_CAN_STM32FD */ + +#endif /*ZEPHYR_DRIVERS_CAN_MCAN_INT_H_*/ diff --git a/drivers/can/can_stm32fd.c b/drivers/can/can_stm32fd.c new file mode 100644 index 0000000000000..43256d95641cf --- /dev/null +++ b/drivers/can/can_stm32fd.c @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2020 Alexander Wachter + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include "can_stm32fd.h" +#include + +#include +LOG_MODULE_DECLARE(can_driver, CONFIG_CAN_LOG_LEVEL); + +#if CONFIG_CAN_STM32_CLOCK_DIVISOR != 1 && CONFIG_CAN_STM32_CLOCK_DIVISOR & 0x01 +#error CAN_STM32_CLOCK_DIVISOR invalid.\ +Allowed values are 1 or 2 * n, where n <= 15 +#endif + +#define DT_DRV_COMPAT st_stm32_fdcan + +int can_stm32fd_get_core_clock(const struct device *dev, uint32_t *rate) +{ + ARG_UNUSED(dev); + int rate_tmp; + + rate_tmp = LL_RCC_GetFDCANClockFreq(LL_RCC_FDCAN_CLKSOURCE); + + if (rate_tmp == LL_RCC_PERIPH_FREQUENCY_NO) { + LOG_ERR("Can't read core clock"); + return -EIO; + } + + *rate = rate_tmp / CONFIG_CAN_STM32_CLOCK_DIVISOR; + + return 0; +} + +void can_stm32fd_clock_enable(void) +{ + LL_RCC_SetFDCANClockSource(LL_RCC_FDCAN_CLKSOURCE_PCLK1); + __HAL_RCC_FDCAN_CLK_ENABLE(); + + FDCAN_CONFIG->CKDIV = CONFIG_CAN_STM32_CLOCK_DIVISOR >> 1; +} + +void can_stm32fd_register_state_change_isr(const struct device *dev, + can_state_change_isr_t isr) +{ + struct can_stm32fd_data *data = DEV_DATA(dev); + + data->mcan_data.state_change_isr = isr; +} + +static int can_stm32fd_init(const struct device *dev) +{ + const struct can_stm32fd_config *cfg = DEV_CFG(dev); + const struct can_mcan_config *mcan_cfg = &cfg->mcan_cfg; + struct can_mcan_data *mcan_data = &DEV_DATA(dev)->mcan_data; + struct can_mcan_msg_sram *msg_ram = cfg->msg_sram; + int ret; + + /* Configure dt provided device signals when available */ + ret = stm32_dt_pinctrl_configure(cfg->pinctrl, + ARRAY_SIZE(cfg->pinctrl), + (uint32_t)mcan_cfg->can); + if (ret < 0) { + LOG_ERR("CAN pinctrl setup failed (%d)", ret); + return ret; + } + + can_stm32fd_clock_enable(); + ret = can_mcan_init(dev, mcan_cfg, msg_ram, mcan_data); + if (ret) { + return ret; + } + + cfg->config_irq(); + + return ret; +} + +enum can_state can_stm32fd_get_state(const struct device *dev, + struct can_bus_err_cnt *err_cnt) +{ + const struct can_stm32fd_config *cfg = DEV_CFG(dev); + const struct can_mcan_config *mcan_cfg = &cfg->mcan_cfg; + + return can_mcan_get_state(mcan_cfg, err_cnt); +} + +int can_stm32fd_send(const struct device *dev, const struct zcan_frame *frame, + k_timeout_t timeout, can_tx_callback_t callback, + void *callback_arg) +{ + const struct can_stm32fd_config *cfg = DEV_CFG(dev); + const struct can_mcan_config *mcan_cfg = &cfg->mcan_cfg; + struct can_mcan_data *mcan_data = &DEV_DATA(dev)->mcan_data; + struct can_mcan_msg_sram *msg_ram = cfg->msg_sram; + + return can_mcan_send(mcan_cfg, mcan_data, msg_ram, frame, timeout, + callback, callback_arg); +} + +int can_stm32fd_attach_isr(const struct device *dev, can_rx_callback_t isr, + void *cb_arg, const struct zcan_filter *filter) +{ + const struct can_stm32fd_config *cfg = DEV_CFG(dev); + struct can_mcan_data *mcan_data = &DEV_DATA(dev)->mcan_data; + struct can_mcan_msg_sram *msg_ram = cfg->msg_sram; + + return can_mcan_attach_isr(mcan_data, msg_ram, isr, cb_arg, filter); +} + +void can_stm32fd_detach(const struct device *dev, int filter_nr) +{ + const struct can_stm32fd_config *cfg = DEV_CFG(dev); + struct can_mcan_data *mcan_data = &DEV_DATA(dev)->mcan_data; + struct can_mcan_msg_sram *msg_ram = cfg->msg_sram; + + can_mcan_detach(mcan_data, msg_ram, filter_nr); +} + +int can_stm32fd_set_mode(const struct device *dev, enum can_mode mode) +{ + const struct can_stm32fd_config *cfg = DEV_CFG(dev); + const struct can_mcan_config *mcan_cfg = &cfg->mcan_cfg; + + return can_mcan_set_mode(mcan_cfg, mode); +} + +int can_stm32fd_set_timing(const struct device *dev, + const struct can_timing *timing, + const struct can_timing *timing_data) +{ + const struct can_stm32fd_config *cfg = DEV_CFG(dev); + const struct can_mcan_config *mcan_cfg = &cfg->mcan_cfg; + + return can_mcan_set_timing(mcan_cfg, timing, timing_data); +} + +void can_stm32fd_line_0_isr(void *arg) +{ + struct device *dev = (struct device *)arg; + const struct can_stm32fd_config *cfg = DEV_CFG(dev); + const struct can_mcan_config *mcan_cfg = &cfg->mcan_cfg; + struct can_stm32fd_data *data = DEV_DATA(dev); + struct can_mcan_data *mcan_data = &data->mcan_data; + struct can_mcan_msg_sram *msg_ram = cfg->msg_sram; + + can_mcan_line_0_isr(mcan_cfg, msg_ram, mcan_data); +} + +void can_stm32fd_line_1_isr(void *arg) +{ + struct device *dev = (struct device *)arg; + const struct can_stm32fd_config *cfg = DEV_CFG(dev); + const struct can_mcan_config *mcan_cfg = &cfg->mcan_cfg; + struct can_mcan_data *mcan_data = &DEV_DATA(dev)->mcan_data; + struct can_mcan_msg_sram *msg_ram = cfg->msg_sram; + + can_mcan_line_1_isr(mcan_cfg, msg_ram, mcan_data); +} + +static const struct can_driver_api can_api_funcs = { + .set_mode = can_stm32fd_set_mode, + .set_timing = can_stm32fd_set_timing, + .send = can_stm32fd_send, + .attach_isr = can_stm32fd_attach_isr, + .detach = can_stm32fd_detach, + .get_state = can_stm32fd_get_state, +#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY + .recover = can_mcan_recover, +#endif + .get_core_clock = can_stm32fd_get_core_clock, + .register_state_change_isr = can_stm32fd_register_state_change_isr, + .timing_min = { + .sjw = 0x7f, + .prop_seg = 0x00, + .phase_seg1 = 0x01, + .phase_seg2 = 0x01, + .prescaler = 0x01 + }, + .timing_max = { + .sjw = 0x7f, + .prop_seg = 0x00, + .phase_seg1 = 0x100, + .phase_seg2 = 0x80, + .prescaler = 0x200 + }, +#ifdef CONFIG_CAN_FD_MODE + .timing_min_data = { + .sjw = 0x01, + .prop_seg = 0x01, + .phase_seg1 = 0x01, + .phase_seg2 = 0x01, + .prescaler = 0x01 + }, + .timing_max_data = { + .sjw = 0x10, + .prop_seg = 0x00, + .phase_seg1 = 0x20, + .phase_seg2 = 0x10, + .prescaler = 0x20 + } +#endif +}; + +#define CAN_STM32FD_IRQ_CFG_FUNCTION(inst) \ +static void config_can_##inst##_irq(void) \ +{ \ + LOG_DBG("Enable CAN" #inst " IRQ"); \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(inst, line_0, irq), \ + DT_INST_IRQ_BY_NAME(inst, line_0, priority), \ + can_stm32fd_line_0_isr, DEVICE_DT_INST_GET(inst), 0); \ + irq_enable(DT_INST_IRQ_BY_NAME(inst, line_0, irq)); \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(inst, line_1, irq), \ + DT_INST_IRQ_BY_NAME(inst, line_1, priority), \ + can_stm32fd_line_1_isr, DEVICE_DT_INST_GET(inst), 0); \ + irq_enable(DT_INST_IRQ_BY_NAME(inst, line_1, irq)); \ +} + +#ifdef CONFIG_CAN_FD_MODE + +#define CAN_STM32FD_CFG_INST(inst) \ +static const struct can_stm32fd_config can_stm32fd_cfg_##inst = { \ + .msg_sram = (struct can_mcan_msg_sram *) \ + DT_INST_REG_ADDR_BY_NAME(inst, message_ram), \ + .config_irq = config_can_##inst##_irq, \ + .mcan_cfg = { \ + .can = (struct can_mcan_reg *) \ + DT_INST_REG_ADDR_BY_NAME(inst, m_can), \ + .bus_speed = DT_INST_PROP(inst, bus_speed), \ + .sjw = DT_INST_PROP(inst, sjw), \ + .sample_point = DT_INST_PROP_OR(inst, sample_point, 0), \ + .prop_ts1 = DT_INST_PROP_OR(inst, prop_seg, 0) + \ + DT_INST_PROP_OR(inst, phase_seg1, 0), \ + .ts2 = DT_INST_PROP_OR(inst, phase_seg2, 0), \ + .bus_speed_data = DT_INST_PROP(inst, bus_speed_data), \ + .sjw_data = DT_INST_PROP(inst, sjw_data), \ + .sample_point_data = \ + DT_INST_PROP_OR(inst, sample_point_data, 0), \ + .prop_ts1_data = DT_INST_PROP_OR(inst, prop_seg_data, 0) + \ + DT_INST_PROP_OR(inst, phase_seg1_data, 0), \ + .ts2_data = DT_INST_PROP_OR(inst, phase_seg2_data, 0), \ + .tx_delay_comp_offset = \ + DT_INST_PROP(inst, tx_delay_comp_offset) \ + }, \ + .pinctrl = ST_STM32_DT_INST_PINCTRL(inst, 0), \ +}; + +#else /* CONFIG_CAN_FD_MODE */ + +#define CAN_STM32FD_CFG_INST(inst) \ +static const struct can_stm32fd_config can_stm32fd_cfg_##inst = { \ + .msg_sram = (struct can_mcan_msg_sram *) \ + DT_INST_REG_ADDR_BY_NAME(inst, message_ram), \ + .config_irq = config_can_##inst##_irq, \ + .mcan_cfg = { \ + .can = (struct can_mcan_reg *) \ + DT_INST_REG_ADDR_BY_NAME(inst, m_can), \ + .bus_speed = DT_INST_PROP(inst, bus_speed), \ + .sjw = DT_INST_PROP(inst, sjw), \ + .sample_point = DT_INST_PROP_OR(inst, sample_point, 0), \ + .prop_ts1 = DT_INST_PROP_OR(inst, prop_seg, 0) + \ + DT_INST_PROP_OR(inst, phase_seg1, 0), \ + .ts2 = DT_INST_PROP_OR(inst, phase_seg2, 0), \ + }, \ + .pinctrl = ST_STM32_DT_INST_PINCTRL(inst, 0), \ +}; + +#endif /* CONFIG_CAN_FD_MODE */ + +#define CAN_STM32FD_DATA_INST(inst) \ +static struct can_stm32fd_data can_stm32fd_dev_data_##inst; + +#define CAN_STM32FD_DEVICE_INST(inst) \ +DEVICE_DT_INST_DEFINE(inst, &can_stm32fd_init, NULL, \ + &can_stm32fd_dev_data_##inst, &can_stm32fd_cfg_##inst, \ + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ + &can_api_funcs); + +#define CAN_STM32FD_INST(inst) \ +CAN_STM32FD_IRQ_CFG_FUNCTION(inst) \ +CAN_STM32FD_CFG_INST(inst) \ +CAN_STM32FD_DATA_INST(inst) \ +CAN_STM32FD_DEVICE_INST(inst) + +DT_INST_FOREACH_STATUS_OKAY(CAN_STM32FD_INST) diff --git a/drivers/can/can_stm32fd.h b/drivers/can/can_stm32fd.h new file mode 100644 index 0000000000000..8901899e57a45 --- /dev/null +++ b/drivers/can/can_stm32fd.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2020 Alexander Wachter + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +#ifndef ZEPHYR_DRIVERS_CAN_STM32FD_H_ +#define ZEPHYR_DRIVERS_CAN_STM32FD_H_ + +#include "can_mcan.h" +#include + +#define DEV_DATA(dev) ((struct can_stm32fd_data *)(dev)->data) +#define DEV_CFG(dev) ((const struct can_stm32fd_config *)(dev)->config) + +struct can_stm32fd_config { + struct can_mcan_msg_sram *msg_sram; + void (*config_irq)(void); + struct can_mcan_config mcan_cfg; + /* CAN always has an RX and TX pin. Hence, hardcode it to two*/ + const struct soc_gpio_pinctrl pinctrl[2]; +}; + +struct can_stm32fd_data { + struct can_mcan_data mcan_data; +}; + +#endif /*ZEPHYR_DRIVERS_CAN_STM32FD_H_*/ diff --git a/dts/arm/st/g4/stm32g4.dtsi b/dts/arm/st/g4/stm32g4.dtsi index 1341891b9135a..2425814e99a9a 100644 --- a/dts/arm/st/g4/stm32g4.dtsi +++ b/dts/arm/st/g4/stm32g4.dtsi @@ -345,6 +345,30 @@ label = "SPI_3"; }; + can { + compatible = "bosch,m-can-base"; + #address-cells = <1>; + #size-cells = <1>; + std-filter-elements = <28>; + ext-filter-elements = <8>; + rx-fifo0-elements = <3>; + rx-fifo1-elements = <3>; + rx-buffer-elements = <0>; + tx-buffer-elements = <3>; + + can1: can@40006400 { + compatible = "st,stm32-fdcan"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40006400 0x400>, <0x4000A400 0x350>; + reg-names = "m_can", "message_ram"; + interrupts = <21 0>, <22 0>; + interrupt-names = "LINE_0", "LINE_1"; + status = "disabled"; + label = "CAN_1"; + }; + }; + timers1: timers@40012c00 { compatible = "st,stm32-timers"; reg = <0x40012c00 0x400>; diff --git a/dts/arm/st/g4/stm32g474.dtsi b/dts/arm/st/g4/stm32g474.dtsi index 04c5fb445d362..83c2dd94a76ee 100644 --- a/dts/arm/st/g4/stm32g474.dtsi +++ b/dts/arm/st/g4/stm32g474.dtsi @@ -8,6 +8,32 @@ / { soc { + can { + can2: can@40006800 { + compatible = "st,stm32-fdcan"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40006800 0x400>, <0x4000A800 0x350>; + reg-names = "m_can", "message_ram"; + interrupts = <86 0>, <87 0>; + interrupt-names = "LINE_0", "LINE_1"; + status = "disabled"; + label = "CAN_2"; + }; + + can3: can@40006C00 { + compatible = "st,stm32-fdcan"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40006C00 0x400>, <0x4000AC00 0x350>; + reg-names = "m_can", "message_ram"; + interrupts = <88 0>, <89 0>; + interrupt-names = "LINE_0", "LINE_1"; + status = "disabled"; + label = "CAN_3"; + }; + }; + dac2: dac@50000c00 { compatible = "st,stm32-dac"; reg = <0x50000c00 0x400>; diff --git a/dts/bindings/can/bosch,m-can-base.yaml b/dts/bindings/can/bosch,m-can-base.yaml new file mode 100644 index 0000000000000..44e0271ce3325 --- /dev/null +++ b/dts/bindings/can/bosch,m-can-base.yaml @@ -0,0 +1,28 @@ +description: Bosch m_can CAN-FD controller base + +compatible: "bosch,m-can-base" + +properties: + std-filter-elements: + type: int + required: true + + ext-filter-elements: + type: int + required: true + + rx-fifo0-elements: + type: int + required: true + + rx-fifo1-elements: + type: int + required: true + + rx-buffer-elements: + type: int + required: true + + tx-buffer-elements: + type: int + required: true diff --git a/dts/bindings/can/bosch-mcan.yaml b/dts/bindings/can/bosch-mcan.yaml new file mode 100644 index 0000000000000..8710b41cefe57 --- /dev/null +++ b/dts/bindings/can/bosch-mcan.yaml @@ -0,0 +1,12 @@ +description: Bosch m_can CAN-FD controller + +compatible: "bosch,m-can" + +include: can-fd-controller.yaml + +properties: + reg: + required: true + + interrupts: + required: true diff --git a/dts/bindings/can/can-fd-controller.yaml b/dts/bindings/can/can-fd-controller.yaml index 9e6f09840a35c..d4f546d578c6a 100644 --- a/dts/bindings/can/can-fd-controller.yaml +++ b/dts/bindings/can/can-fd-controller.yaml @@ -30,3 +30,7 @@ properties: Sample point in permille for the data phase. This param is required if segments are not given. If the sample point is given, the segments are ignored. + tx-delay-comp-offset: + type: int + required: false + default: 0 diff --git a/dts/bindings/can/st,stm32-fdcan.yaml b/dts/bindings/can/st,stm32-fdcan.yaml new file mode 100644 index 0000000000000..8da5e0a73e18f --- /dev/null +++ b/dts/bindings/can/st,stm32-fdcan.yaml @@ -0,0 +1,16 @@ +description: Bosch m_can CAN-FD controller + +compatible: "st,stm32-fdcan" + +include: bosch-mcan.yaml + +properties: + pinctrl-0: + type: phandles + required: false + description: | + GPIO pin configuration for CAN signals (RX, TX). We expect + that the phandles will reference pinctrl nodes. + + For example the can1 would be + pinctrl-0 = <&fdcan1_rx_pa11 &fdcan1_tx_pa12>; diff --git a/include/drivers/can.h b/include/drivers/can.h index 30b251ab26c00..ac081f41bd17c 100644 --- a/include/drivers/can.h +++ b/include/drivers/can.h @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -33,7 +34,22 @@ extern "C" { #define CAN_STD_ID_MASK CAN_MAX_STD_ID #define CAN_EXT_ID_MASK (0x1FFFFFFF) #define CAN_MAX_DLC (8) +#define CANFD_MAX_DLC CONFIG_CANFD_MAX_DLC +#ifndef CONFIG_CANFD_MAX_DLC #define CAN_MAX_DLEN 8 +#else +#if CONFIG_CANFD_MAX_DLC <= 8 +#define CAN_MAX_DLEN CONFIG_CANFD_MAX_DLC +#elif CONFIG_CANFD_MAX_DLC <= 12 +#define CAN_MAX_DLEN CONFIG_CANFD_MAX_DLC + (CONFIG_CANFD_MAX_DLC - 8) * 4 +#elif CONFIG_CANFD_MAX_DLC == 13 +#define CAN_MAX_DLEN 32 +#elif CONFIG_CANFD_MAX_DLC == 14 +#define CAN_MAX_DLEN 48 +#elif CONFIG_CANFD_MAX_DLC == 15 +#define CAN_MAX_DLEN 64 +#endif +#endif /* CONFIG_CANFD_MAX_DLC */ /* CAN_TX_* are the error flags from tx_callback and send.*/ /** send successfully */ @@ -388,6 +404,45 @@ __subsystem struct can_driver_api { #endif }; +/** + * @brief Convert the DLC to the number of bytes + * + * This function converts a the Data Length Code to the number of bytes. + * + * @param dlc The Data Length Code + * + * @retval Number of bytes + */ +static inline uint8_t can_dlc_to_bytes(uint8_t dlc) +{ + static const uint8_t dlc_table[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 12, + 16, 20, 24, 32, 48, 64}; + + return dlc > 0x0F ? 64 : dlc_table[dlc]; +} + +/** + * @brief Convert a number of bytes to the DLC + * + * This function converts a number of bytes to the Data Length Code + * + * @param num_bytes The number of bytes + * + * @retval The DLC + */ + +static inline uint8_t can_bytes_to_dlc(uint8_t num_bytes) +{ + return num_bytes <= 8 ? num_bytes : + num_bytes <= 12 ? 9 : + num_bytes <= 16 ? 10 : + num_bytes <= 20 ? 11 : + num_bytes <= 24 ? 12 : + num_bytes <= 32 ? 13 : + num_bytes <= 48 ? 14 : + 15; +} + /** * @brief Perform data transfer to CAN bus. * diff --git a/tests/drivers/can/api/prj.conf b/tests/drivers/can/api/prj.conf index f9126d9886309..e9bd29cf66d88 100644 --- a/tests/drivers/can/api/prj.conf +++ b/tests/drivers/can/api/prj.conf @@ -1,2 +1,3 @@ CONFIG_CAN=y +CONFIG_CAN_FD_MODE=n CONFIG_ZTEST=y diff --git a/tests/drivers/can/api/src/main.c b/tests/drivers/can/api/src/main.c index b198ded34f497..5e65b0523caac 100644 --- a/tests/drivers/can/api/src/main.c +++ b/tests/drivers/can/api/src/main.c @@ -31,14 +31,18 @@ #define TEST_SEND_TIMEOUT K_MSEC(100) #define TEST_RECEIVE_TIMEOUT K_MSEC(100) -#define TEST_CAN_STD_ID 0x555 -#define TEST_CAN_STD_MASK_ID 0x55A +#define TEST_CAN_STD_ID_1 0x555 +#define TEST_CAN_STD_ID_2 0x556 +#define TEST_CAN_STD_MASK_ID_1 0x55A +#define TEST_CAN_STD_MASK_ID_2 0x56A #define TEST_CAN_STD_MASK 0x7F0 #define TEST_CAN_SOME_STD_ID 0x123 -#define TEST_CAN_EXT_ID 0x15555555 -#define TEST_CAN_EXT_MASK_ID 0x1555555A -#define TEST_CAN_EXT_MASK 0x1FFFFFF0 +#define TEST_CAN_EXT_ID_1 0x15555555 +#define TEST_CAN_EXT_ID_2 0x15555556 +#define TEST_CAN_EXT_MASK_ID_1 0x1555555A +#define TEST_CAN_EXT_MASK_ID_2 0x1555556A +#define TEST_CAN_EXT_MASK 0x1FFFFFF0 #if defined(CONFIG_CAN_LOOPBACK_DEV_NAME) @@ -53,66 +57,99 @@ struct k_sem rx_cb_sem; struct k_sem tx_cb_sem; const struct device *can_dev; -struct zcan_frame test_std_msg = { +const struct zcan_frame test_std_msg_1 = { .id_type = CAN_STANDARD_IDENTIFIER, .rtr = CAN_DATAFRAME, - .id = TEST_CAN_STD_ID, + .id = TEST_CAN_STD_ID_1, .dlc = 8, .data = {1, 2, 3, 4, 5, 6, 7, 8} }; -struct zcan_frame test_std_mask_msg = { +const struct zcan_frame test_std_msg_2 = { .id_type = CAN_STANDARD_IDENTIFIER, .rtr = CAN_DATAFRAME, - .id = TEST_CAN_STD_MASK_ID, + .id = TEST_CAN_STD_ID_2, .dlc = 8, .data = {1, 2, 3, 4, 5, 6, 7, 8} }; -struct zcan_frame test_ext_msg = { +const struct zcan_frame test_ext_msg_1 = { .id_type = CAN_EXTENDED_IDENTIFIER, .rtr = CAN_DATAFRAME, - .id = TEST_CAN_EXT_ID, + .id = TEST_CAN_EXT_ID_1, .dlc = 8, .data = {1, 2, 3, 4, 5, 6, 7, 8} }; -struct zcan_frame test_ext_mask_msg = { +const struct zcan_frame test_ext_msg_2 = { .id_type = CAN_EXTENDED_IDENTIFIER, .rtr = CAN_DATAFRAME, - .id = TEST_CAN_EXT_MASK_ID, + .id = TEST_CAN_EXT_ID_2, .dlc = 8, .data = {1, 2, 3, 4, 5, 6, 7, 8} }; -const struct zcan_filter test_std_filter = { +const struct zcan_filter test_std_filter_1 = { .id_type = CAN_STANDARD_IDENTIFIER, .rtr = CAN_DATAFRAME, - .id = TEST_CAN_STD_ID, + .id = TEST_CAN_STD_ID_1, .rtr_mask = 1, .id_mask = CAN_STD_ID_MASK }; -const struct zcan_filter test_std_masked_filter = { +const struct zcan_filter test_std_filter_2 = { .id_type = CAN_STANDARD_IDENTIFIER, .rtr = CAN_DATAFRAME, - .id = TEST_CAN_STD_ID, + .id = TEST_CAN_STD_ID_2, + .rtr_mask = 1, + .id_mask = CAN_STD_ID_MASK +}; + +const struct zcan_filter test_std_masked_filter_1 = { + .id_type = CAN_STANDARD_IDENTIFIER, + .rtr = CAN_DATAFRAME, + .id = TEST_CAN_STD_MASK_ID_1, .rtr_mask = 1, .id_mask = TEST_CAN_STD_MASK }; -const struct zcan_filter test_ext_filter = { +const struct zcan_filter test_std_masked_filter_2 = { + .id_type = CAN_STANDARD_IDENTIFIER, + .rtr = CAN_DATAFRAME, + .id = TEST_CAN_STD_MASK_ID_2, + .rtr_mask = 1, + .id_mask = TEST_CAN_STD_MASK +}; + + +const struct zcan_filter test_ext_filter_1 = { + .id_type = CAN_EXTENDED_IDENTIFIER, + .rtr = CAN_DATAFRAME, + .id = TEST_CAN_EXT_ID_1, + .rtr_mask = 1, + .id_mask = CAN_EXT_ID_MASK +}; + +const struct zcan_filter test_ext_filter_2 = { .id_type = CAN_EXTENDED_IDENTIFIER, .rtr = CAN_DATAFRAME, - .id = TEST_CAN_EXT_ID, + .id = TEST_CAN_EXT_ID_2, .rtr_mask = 1, .id_mask = CAN_EXT_ID_MASK }; -const struct zcan_filter test_ext_masked_filter = { +const struct zcan_filter test_ext_masked_filter_1 = { .id_type = CAN_EXTENDED_IDENTIFIER, .rtr = CAN_DATAFRAME, - .id = TEST_CAN_EXT_ID, + .id = TEST_CAN_EXT_MASK_ID_1, + .rtr_mask = 1, + .id_mask = TEST_CAN_EXT_MASK +}; + +const struct zcan_filter test_ext_masked_filter_2 = { + .id_type = CAN_EXTENDED_IDENTIFIER, + .rtr = CAN_DATAFRAME, + .id = TEST_CAN_EXT_ID_1, .rtr_mask = 1, .id_mask = TEST_CAN_EXT_MASK }; @@ -125,13 +162,14 @@ const struct zcan_filter test_std_some_filter = { .id_mask = CAN_STD_ID_MASK }; -struct zcan_work can_work; +struct zcan_work can_work_1; +struct zcan_work can_work_2; -static inline void check_msg(struct zcan_frame *msg1, struct zcan_frame *msg2, +static inline void check_msg(const struct zcan_frame *msg1, + const struct zcan_frame *msg2, uint32_t mask) { int cmp_res; - zassert_equal(msg1->id_type, msg2->id_type, "ID type does not match"); @@ -143,105 +181,160 @@ static inline void check_msg(struct zcan_frame *msg1, struct zcan_frame *msg2, zassert_equal(msg1->dlc, msg2->dlc, "DLC does not match"); - cmp_res = memcmp(msg1->data, msg2->data, msg1->dlc); zassert_equal(cmp_res, 0, "Received data differ"); } -static void tx_std_isr(uint32_t error_flags, void *arg) +static void tx_std_isr_1(uint32_t error_flags, void *arg) { - struct zcan_frame *msg = (struct zcan_frame *)arg; + const struct zcan_frame *msg = (const struct zcan_frame *)arg; k_sem_give(&tx_cb_sem); - zassert_equal(msg->id, TEST_CAN_STD_ID, "Arg does not match"); + zassert_equal(msg->id, TEST_CAN_STD_ID_1, "Arg does not match"); } -static void tx_std_masked_isr(uint32_t error_flags, void *arg) +static void tx_std_isr_2(uint32_t error_flags, void *arg) { - struct zcan_frame *msg = (struct zcan_frame *)arg; + const struct zcan_frame *msg = (const struct zcan_frame *)arg; k_sem_give(&tx_cb_sem); - zassert_equal(msg->id, TEST_CAN_STD_MASK_ID, "Arg does not match"); + zassert_equal(msg->id, TEST_CAN_STD_ID_2, "Arg does not match"); } -static void tx_ext_isr(uint32_t error_flags, void *arg) +static void tx_ext_isr_1(uint32_t error_flags, void *arg) { - struct zcan_frame *msg = (struct zcan_frame *)arg; + const struct zcan_frame *msg = (const struct zcan_frame *)arg; k_sem_give(&tx_cb_sem); - zassert_equal(msg->id, TEST_CAN_EXT_ID, "Arg does not match"); + zassert_equal(msg->id, TEST_CAN_EXT_ID_1, "Arg does not match"); } -static void tx_ext_masked_isr(uint32_t error_flags, void *arg) +static void tx_ext_isr_2(uint32_t error_flags, void *arg) { - struct zcan_frame *msg = (struct zcan_frame *)arg; + const struct zcan_frame *msg = (const struct zcan_frame *)arg; k_sem_give(&tx_cb_sem); - zassert_equal(msg->id, TEST_CAN_EXT_MASK_ID, "Arg does not match"); + zassert_equal(msg->id, TEST_CAN_EXT_ID_2, "Arg does not match"); +} + +static void rx_std_isr_1(struct zcan_frame *msg, void *arg) +{ + check_msg(msg, &test_std_msg_1, 0); + zassert_equal_ptr(arg, &test_std_filter_1, "arg does not match"); + k_sem_give(&rx_isr_sem); +} + +static void rx_std_isr_2(struct zcan_frame *msg, void *arg) +{ + check_msg(msg, &test_std_msg_2, 0); + zassert_equal_ptr(arg, &test_std_filter_2, "arg does not match"); + k_sem_give(&rx_isr_sem); +} + +static void rx_std_mask_isr_1(struct zcan_frame *msg, void *arg) +{ + check_msg(msg, &test_std_msg_1, 0x0F); + zassert_equal_ptr(arg, &test_std_masked_filter_1, "arg does not match"); + k_sem_give(&rx_isr_sem); +} + +static void rx_std_mask_isr_2(struct zcan_frame *msg, void *arg) +{ + check_msg(msg, &test_std_msg_2, 0x0F); + zassert_equal_ptr(arg, &test_std_masked_filter_2, "arg does not match"); + k_sem_give(&rx_isr_sem); } -static void rx_std_isr(struct zcan_frame *msg, void *arg) +static void rx_ext_isr_1(struct zcan_frame *msg, void *arg) { - check_msg(msg, &test_std_msg, 0); - zassert_equal_ptr(arg, &test_std_filter, "arg does not match"); + check_msg(msg, &test_ext_msg_1, 0); + zassert_equal_ptr(arg, &test_ext_filter_1, "arg does not match"); k_sem_give(&rx_isr_sem); } -static void rx_std_mask_isr(struct zcan_frame *msg, void *arg) +static void rx_ext_isr_2(struct zcan_frame *msg, void *arg) { - check_msg(msg, &test_std_msg, 0x0F); - zassert_equal_ptr(arg, &test_std_masked_filter, "arg does not match"); + check_msg(msg, &test_ext_msg_2, 0); + zassert_equal_ptr(arg, &test_ext_filter_2, "arg does not match"); k_sem_give(&rx_isr_sem); } -static void rx_ext_isr(struct zcan_frame *msg, void *arg) +static void rx_ext_mask_isr_1(struct zcan_frame *msg, void *arg) { - check_msg(msg, &test_ext_msg, 0); - zassert_equal_ptr(arg, &test_ext_filter, "arg does not match"); + check_msg(msg, &test_ext_msg_1, 0x0F); + zassert_equal_ptr(arg, &test_ext_masked_filter_1, "arg does not match"); k_sem_give(&rx_isr_sem); } -static void rx_ext_mask_isr(struct zcan_frame *msg, void *arg) +static void rx_ext_mask_isr_2(struct zcan_frame *msg, void *arg) { - check_msg(msg, &test_ext_msg, 0x0F); - zassert_equal_ptr(arg, &test_ext_masked_filter, "arg does not match"); + check_msg(msg, &test_ext_msg_2, 0x0F); + zassert_equal_ptr(arg, &test_ext_masked_filter_2, "arg does not match"); k_sem_give(&rx_isr_sem); } -static void rx_std_cb(struct zcan_frame *msg, void *arg) +static void rx_std_cb_1(struct zcan_frame *msg, void *arg) { - check_msg(msg, &test_std_msg, 0); - zassert_equal_ptr(arg, &test_std_filter, "arg does not match"); + check_msg(msg, &test_std_msg_1, 0); + zassert_equal_ptr(arg, &test_std_filter_1, "arg does not match"); k_sem_give(&rx_cb_sem); } -static void rx_std_mask_cb(struct zcan_frame *msg, void *arg) +static void rx_std_cb_2(struct zcan_frame *msg, void *arg) { - check_msg(msg, &test_std_msg, 0x0F); - zassert_equal_ptr(arg, &test_std_masked_filter, "arg does not match"); + check_msg(msg, &test_std_msg_2, 0); + zassert_equal_ptr(arg, &test_std_filter_2, "arg does not match"); k_sem_give(&rx_cb_sem); } -static void rx_ext_cb(struct zcan_frame *msg, void *arg) +static void rx_std_mask_cb_1(struct zcan_frame *msg, void *arg) { - check_msg(msg, &test_ext_msg, 0); - zassert_equal_ptr(arg, &test_ext_filter, "arg does not match"); + check_msg(msg, &test_std_msg_1, 0x0F); + zassert_equal_ptr(arg, &test_std_masked_filter_1, "arg does not match"); k_sem_give(&rx_cb_sem); } -static void rx_ext_mask_cb(struct zcan_frame *msg, void *arg) +static void rx_std_mask_cb_2(struct zcan_frame *msg, void *arg) { - check_msg(msg, &test_ext_msg, 0x0F); - zassert_equal_ptr(arg, &test_ext_masked_filter, "arg does not match"); + check_msg(msg, &test_std_msg_2, 0x0F); + zassert_equal_ptr(arg, &test_std_masked_filter_2, "arg does not match"); + k_sem_give(&rx_cb_sem); +} + +static void rx_ext_cb_1(struct zcan_frame *msg, void *arg) +{ + check_msg(msg, &test_ext_msg_1, 0); + zassert_equal_ptr(arg, &test_ext_filter_1, "arg does not match"); + k_sem_give(&rx_cb_sem); +} + +static void rx_ext_cb_2(struct zcan_frame *msg, void *arg) +{ + check_msg(msg, &test_ext_msg_2, 0); + zassert_equal_ptr(arg, &test_ext_filter_2, "arg does not match"); + k_sem_give(&rx_cb_sem); +} + +static void rx_ext_mask_cb_1(struct zcan_frame *msg, void *arg) +{ + check_msg(msg, &test_ext_msg_1, 0x0F); + zassert_equal_ptr(arg, &test_ext_masked_filter_1, "arg does not match"); + k_sem_give(&rx_cb_sem); +} + +static void rx_ext_mask_cb_2(struct zcan_frame *msg, void *arg) +{ + check_msg(msg, &test_ext_msg_2, 0x0F); + zassert_equal_ptr(arg, &test_ext_masked_filter_2, "arg does not match"); k_sem_give(&rx_cb_sem); } static void send_test_msg(const struct device *can_dev, - struct zcan_frame *msg) + const struct zcan_frame *msg) { int ret; @@ -252,28 +345,12 @@ static void send_test_msg(const struct device *can_dev, } static void send_test_msg_nowait(const struct device *can_dev, - struct zcan_frame *msg) + const struct zcan_frame *msg, + can_tx_callback_t cb) { int ret; - - if (msg->id_type == CAN_STANDARD_IDENTIFIER) { - if (msg->id == TEST_CAN_STD_ID) { - ret = can_send(can_dev, msg, TEST_SEND_TIMEOUT, - tx_std_isr, msg); - } else { - ret = can_send(can_dev, msg, TEST_SEND_TIMEOUT, - tx_std_masked_isr, msg); - } - } else { - if (msg->id == TEST_CAN_EXT_ID) { - ret = can_send(can_dev, msg, TEST_SEND_TIMEOUT, - tx_ext_isr, msg); - } else { - ret = can_send(can_dev, msg, TEST_SEND_TIMEOUT, - tx_ext_masked_isr, msg); - } - } - + ret = can_send(can_dev, msg, TEST_SEND_TIMEOUT, cb, + (struct zcan_frame *)msg); zassert_not_equal(ret, CAN_TX_ARB_LOST, "Arbitration though in loopback mode"); zassert_equal(ret, CAN_TX_OK, "Can't send a message. Err: %d", ret); @@ -293,31 +370,14 @@ static inline int attach_msgq(const struct device *can_dev, } static inline int attach_workq(const struct device *can_dev, - const struct zcan_filter *filter) + const struct zcan_filter *filter, + struct zcan_work *work, + can_rx_callback_t cb) { int filter_id; - if (filter->id_type == CAN_STANDARD_IDENTIFIER) { - if (filter->id_mask == CAN_STD_ID_MASK) { - filter_id = can_attach_workq(can_dev, &k_sys_work_q, - &can_work, rx_std_cb, - (void *)filter, filter); - } else { - filter_id = can_attach_workq(can_dev, &k_sys_work_q, - &can_work, rx_std_mask_cb, - (void *)filter, filter); - } - } else { - if (filter->id_mask == CAN_EXT_ID_MASK) { - filter_id = can_attach_workq(can_dev, &k_sys_work_q, - &can_work, rx_ext_cb, - (void *)filter, filter); - } else { - filter_id = can_attach_workq(can_dev, &k_sys_work_q, - &can_work, rx_ext_mask_cb, - (void *)filter, filter); - } - } + filter_id = can_attach_workq(can_dev, &k_sys_work_q, work, cb, + (void *)filter, filter); zassert_not_equal(filter_id, CAN_NO_FREE_FILTER, "Filter full even for a single one"); @@ -327,30 +387,14 @@ static inline int attach_workq(const struct device *can_dev, } static inline int attach_isr(const struct device *can_dev, - const struct zcan_filter *filter) + const struct zcan_filter *filter, + can_rx_callback_t isr) { int filter_id; k_sem_reset(&rx_isr_sem); - if (filter->id_type == CAN_STANDARD_IDENTIFIER) { - if (filter->id_mask == CAN_STD_ID_MASK) { - filter_id = can_attach_isr(can_dev, rx_std_isr, - (void *)filter, filter); - } else { - filter_id = can_attach_isr(can_dev, rx_std_mask_isr, - (void *)filter, filter); - } - } else { - if (filter->id_mask == CAN_EXT_ID_MASK) { - filter_id = can_attach_isr(can_dev, rx_ext_isr, - (void *)filter, filter); - } else { - filter_id = can_attach_isr(can_dev, rx_ext_mask_isr, - (void *)filter, filter); - } - } - + filter_id = can_attach_isr(can_dev, isr, (void *)filter, filter); zassert_not_equal(filter_id, CAN_NO_FREE_FILTER, "Filter full even for a single one"); zassert_true((filter_id >= 0), "Negative filter number"); @@ -358,46 +402,119 @@ static inline int attach_isr(const struct device *can_dev, return filter_id; } -static void send_receive(const struct zcan_filter *filter, struct zcan_frame *msg) +static void send_receive(const struct zcan_filter *filter1, + const struct zcan_filter *filter2, + const struct zcan_frame *msg1, + const struct zcan_frame *msg2) { - int ret, filter_id; + int ret, filter_id_1, filter_id_2; struct zcan_frame msg_buffer; uint32_t mask = 0U; zassert_not_null(can_dev, "Device not not found"); - filter_id = attach_msgq(can_dev, filter); - send_test_msg(can_dev, msg); + filter_id_1 = attach_msgq(can_dev, filter1); + send_test_msg(can_dev, msg1); ret = k_msgq_get(&can_msgq, &msg_buffer, TEST_RECEIVE_TIMEOUT); zassert_equal(ret, 0, "Receiving timeout"); - if (filter->id_type == CAN_STANDARD_IDENTIFIER) { - if (filter->id_mask != CAN_STD_ID_MASK) { + if (filter1->id_type == CAN_STANDARD_IDENTIFIER) { + if (filter1->id_mask != CAN_STD_ID_MASK) { mask = 0x0F; } } else { - if (filter->id_mask != CAN_EXT_ID_MASK) { + if (filter1->id_mask != CAN_EXT_ID_MASK) { mask = 0x0F; } } - check_msg(&msg_buffer, msg, mask); - can_detach(can_dev, filter_id); + check_msg(&msg_buffer, msg1, mask); + can_detach(can_dev, filter_id_1); k_sem_reset(&tx_cb_sem); - filter_id = attach_isr(can_dev, filter); - send_test_msg_nowait(can_dev, msg); + if (msg1->id_type == CAN_STANDARD_IDENTIFIER) { + if (filter1->id_mask == CAN_STD_ID_MASK) { + filter_id_1 = attach_isr(can_dev, filter1, + rx_std_isr_1); + filter_id_2 = attach_isr(can_dev, filter2, + rx_std_isr_2); + send_test_msg_nowait(can_dev, msg1, tx_std_isr_1); + send_test_msg_nowait(can_dev, msg2, tx_std_isr_2); + } else { + filter_id_1 = attach_isr(can_dev, filter1, + rx_std_mask_isr_1); + filter_id_2 = attach_isr(can_dev, filter2, + rx_std_mask_isr_2); + send_test_msg_nowait(can_dev, msg1, tx_std_isr_1); + send_test_msg_nowait(can_dev, msg2, tx_std_isr_2); + } + } else { + if (filter1->id_mask == CAN_EXT_ID_MASK) { + filter_id_1 = attach_isr(can_dev, filter1, + rx_ext_isr_1); + filter_id_2 = attach_isr(can_dev, filter2, + rx_ext_isr_2); + send_test_msg_nowait(can_dev, msg1, tx_ext_isr_1); + send_test_msg_nowait(can_dev, msg2, tx_ext_isr_2); + } else { + filter_id_1 = attach_isr(can_dev, filter1, + rx_ext_mask_isr_1); + filter_id_2 = attach_isr(can_dev, filter2, + rx_ext_mask_isr_2); + send_test_msg_nowait(can_dev, msg1, tx_ext_isr_1); + send_test_msg_nowait(can_dev, msg2, tx_ext_isr_2); + } + } + + ret = k_sem_take(&rx_isr_sem, TEST_RECEIVE_TIMEOUT); + zassert_equal(ret, 0, "Receiving timeout"); ret = k_sem_take(&rx_isr_sem, TEST_RECEIVE_TIMEOUT); zassert_equal(ret, 0, "Receiving timeout"); ret = k_sem_take(&tx_cb_sem, TEST_SEND_TIMEOUT); zassert_equal(ret, 0, "Missing TX callback"); - can_detach(can_dev, filter_id); + ret = k_sem_take(&tx_cb_sem, TEST_SEND_TIMEOUT); + zassert_equal(ret, 0, "Missing TX callback"); + can_detach(can_dev, filter_id_1); + can_detach(can_dev, filter_id_2); + + if (msg1->id_type == CAN_STANDARD_IDENTIFIER) { + if (filter1->id_mask == CAN_STD_ID_MASK) { + filter_id_1 = attach_workq(can_dev, filter1, + &can_work_1, rx_std_cb_1); + filter_id_2 = attach_workq(can_dev, filter2, + &can_work_2, rx_std_cb_2); + } else { + filter_id_1 = attach_workq(can_dev, filter1, + &can_work_1, + rx_std_mask_cb_1); + filter_id_2 = attach_workq(can_dev, filter2, + &can_work_2, + rx_std_mask_cb_2); + } + } else { + if (filter1->id_mask == CAN_EXT_ID_MASK) { + filter_id_1 = attach_workq(can_dev, filter1, + &can_work_1, rx_ext_cb_1); + filter_id_2 = attach_workq(can_dev, filter2, + &can_work_2, rx_ext_cb_2); + } else { + filter_id_1 = attach_workq(can_dev, filter1, + &can_work_1, + rx_ext_mask_cb_1); + filter_id_2 = attach_workq(can_dev, filter2, + &can_work_2, + rx_ext_mask_cb_2); + } + } - filter_id = attach_workq(can_dev, filter); - send_test_msg(can_dev, msg); + send_test_msg(can_dev, msg1); + send_test_msg(can_dev, msg2); ret = k_sem_take(&rx_cb_sem, TEST_RECEIVE_TIMEOUT); zassert_equal(ret, 0, "Receiving timeout"); - can_detach(can_dev, filter_id); + ret = k_sem_take(&rx_cb_sem, TEST_RECEIVE_TIMEOUT); + zassert_equal(ret, 0, "Receiving timeout"); + can_detach(can_dev, filter_id_2); + can_detach(can_dev, filter_id_1); } /* @@ -421,7 +538,7 @@ static void test_send_and_forget(void) { zassert_not_null(can_dev, "Device not not found"); - send_test_msg(can_dev, &test_std_msg); + send_test_msg(can_dev, &test_std_msg_1); } /* @@ -432,28 +549,32 @@ static void test_filter_attach(void) { int filter_id; - filter_id = attach_isr(can_dev, &test_std_filter); + filter_id = attach_isr(can_dev, &test_std_filter_1, rx_std_isr_1); can_detach(can_dev, filter_id); - filter_id = attach_isr(can_dev, &test_ext_filter); + filter_id = attach_isr(can_dev, &test_ext_filter_1, rx_ext_isr_1); can_detach(can_dev, filter_id); - filter_id = attach_msgq(can_dev, &test_std_filter); + filter_id = attach_msgq(can_dev, &test_std_filter_1); can_detach(can_dev, filter_id); - filter_id = attach_msgq(can_dev, &test_ext_filter); + filter_id = attach_msgq(can_dev, &test_ext_filter_1); can_detach(can_dev, filter_id); - filter_id = attach_isr(can_dev, &test_std_masked_filter); + filter_id = attach_isr(can_dev, &test_std_masked_filter_1, + rx_std_mask_isr_1); can_detach(can_dev, filter_id); - filter_id = attach_isr(can_dev, &test_ext_masked_filter); + filter_id = attach_isr(can_dev, &test_ext_masked_filter_1, + rx_ext_mask_isr_1); can_detach(can_dev, filter_id); - filter_id = attach_workq(can_dev, &test_std_filter); + filter_id = attach_workq(can_dev, &test_std_filter_1, &can_work_1, + rx_std_cb_1); can_detach(can_dev, filter_id); - filter_id = attach_workq(can_dev, &test_std_filter); + filter_id = attach_workq(can_dev, &test_ext_filter_1, &can_work_2, + rx_ext_cb_1); can_detach(can_dev, filter_id); } @@ -465,7 +586,7 @@ static void test_receive_timeout(void) int ret, filter_id; struct zcan_frame msg; - filter_id = attach_msgq(can_dev, &test_std_filter); + filter_id = attach_msgq(can_dev, &test_std_filter_1); ret = k_msgq_get(&can_msgq, &msg, TEST_RECEIVE_TIMEOUT); zassert_equal(ret, -EAGAIN, "Got a message without sending it"); @@ -482,7 +603,7 @@ static void test_send_callback(void) k_sem_reset(&tx_cb_sem); - send_test_msg_nowait(can_dev, &test_std_msg); + send_test_msg_nowait(can_dev, &test_std_msg_1, tx_std_isr_1); ret = k_sem_take(&tx_cb_sem, TEST_SEND_TIMEOUT); zassert_equal(ret, 0, "Missing TX callback"); @@ -495,7 +616,8 @@ static void test_send_callback(void) */ void test_send_receive_std(void) { - send_receive(&test_std_filter, &test_std_msg); + send_receive(&test_std_filter_1, &test_std_filter_2, + &test_std_msg_1, &test_std_msg_2); } /* @@ -505,7 +627,8 @@ void test_send_receive_std(void) */ void test_send_receive_ext(void) { - send_receive(&test_ext_filter, &test_ext_msg); + send_receive(&test_ext_filter_1, &test_ext_filter_2, + &test_ext_msg_1, &test_ext_msg_2); } /* @@ -517,7 +640,8 @@ void test_send_receive_ext(void) */ void test_send_receive_std_masked(void) { - send_receive(&test_std_masked_filter, &test_std_mask_msg); + send_receive(&test_std_masked_filter_1, &test_std_masked_filter_2, + &test_std_msg_1, &test_std_msg_2); } /* @@ -529,7 +653,8 @@ void test_send_receive_std_masked(void) */ void test_send_receive_ext_masked(void) { - send_receive(&test_ext_masked_filter, &test_ext_mask_msg); + send_receive(&test_ext_masked_filter_1, &test_ext_masked_filter_2, + &test_ext_msg_1, &test_ext_msg_2); } /* @@ -541,11 +666,12 @@ void test_send_receive_buffer(void) { int filter_id, i, ret; - filter_id = attach_workq(can_dev, &test_std_filter); + filter_id = attach_workq(can_dev, &test_std_filter_1, &can_work_1, + rx_std_cb_1); k_sem_reset(&rx_cb_sem); for (i = 0; i < CONFIG_CAN_WORKQ_FRAMES_BUF_CNT; i++) { - send_test_msg(can_dev, &test_std_msg); + send_test_msg(can_dev, &test_std_msg_1); } for (i = 0; i < CONFIG_CAN_WORKQ_FRAMES_BUF_CNT; i++) { @@ -554,7 +680,7 @@ void test_send_receive_buffer(void) } for (i = 0; i < CONFIG_CAN_WORKQ_FRAMES_BUF_CNT; i++) { - send_test_msg(can_dev, &test_std_msg); + send_test_msg(can_dev, &test_std_msg_1); } for (i = 0; i < CONFIG_CAN_WORKQ_FRAMES_BUF_CNT; i++) { @@ -575,9 +701,9 @@ static void test_send_receive_wrong_id(void) int ret, filter_id; struct zcan_frame msg_buffer; - filter_id = attach_msgq(can_dev, &test_std_filter); + filter_id = attach_msgq(can_dev, &test_std_filter_1); - send_test_msg(can_dev, &test_std_mask_msg); + send_test_msg(can_dev, &test_std_msg_2); ret = k_msgq_get(&can_msgq, &msg_buffer, TEST_RECEIVE_TIMEOUT); zassert_equal(ret, -EAGAIN, @@ -596,16 +722,16 @@ static void test_send_invalid_dlc(void) frame.dlc = CAN_MAX_DLC + 1; - ret = can_send(can_dev, &frame, TEST_SEND_TIMEOUT, tx_std_isr, NULL); + ret = can_send(can_dev, &frame, TEST_SEND_TIMEOUT, tx_std_isr_1, NULL); zassert_equal(ret, CAN_TX_EINVAL, "ret [%d] not equal to %d", ret, CAN_TX_EINVAL); } void test_main(void) { - k_sem_init(&rx_isr_sem, 0, 1); + k_sem_init(&rx_isr_sem, 0, 2); k_sem_init(&rx_cb_sem, 0, INT_MAX); - k_sem_init(&tx_cb_sem, 0, 1); + k_sem_init(&tx_cb_sem, 0, 2); can_dev = device_get_binding(CAN_DEVICE_NAME); zassert_not_null(can_dev, "Device not found"); @@ -616,11 +742,11 @@ void test_main(void) ztest_unit_test(test_receive_timeout), ztest_unit_test(test_send_callback), ztest_unit_test(test_send_receive_std), + ztest_unit_test(test_send_invalid_dlc), ztest_unit_test(test_send_receive_ext), ztest_unit_test(test_send_receive_std_masked), ztest_unit_test(test_send_receive_ext_masked), ztest_unit_test(test_send_receive_buffer), - ztest_unit_test(test_send_receive_wrong_id), - ztest_unit_test(test_send_invalid_dlc)); + ztest_unit_test(test_send_receive_wrong_id)); ztest_run_test_suite(can_driver); } diff --git a/tests/drivers/can/canfd/CMakeLists.txt b/tests/drivers/can/canfd/CMakeLists.txt new file mode 100644 index 0000000000000..ae5c07152a9f1 --- /dev/null +++ b/tests/drivers/can/canfd/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.13.1) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(integration) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/drivers/can/canfd/prj.conf b/tests/drivers/can/canfd/prj.conf new file mode 100644 index 0000000000000..d22c065813de3 --- /dev/null +++ b/tests/drivers/can/canfd/prj.conf @@ -0,0 +1,3 @@ +CONFIG_CAN=y +CONFIG_CAN_FD_MODE=y +CONFIG_ZTEST=y diff --git a/tests/drivers/can/canfd/src/main.c b/tests/drivers/can/canfd/src/main.c new file mode 100644 index 0000000000000..f7676d35b660a --- /dev/null +++ b/tests/drivers/can/canfd/src/main.c @@ -0,0 +1,402 @@ +/* + * Copyright (c) 2019 Alexander Wachter + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include + +/* + * @addtogroup t_can_driver + * @{ + * @defgroup t_canfd test_canfd + * @brief TestPurpose: Test CAN-FD + * @details + * - Test Steps + * -# Set driver to loopback mode + * -# Send and receive a message + * -# Send and receive a message with fd + * - Expected Results + * -# All tests MUST pass + * @} + */ + +#define TEST_SEND_TIMEOUT K_MSEC(100) +#define TEST_RECEIVE_TIMEOUT K_MSEC(100) + +#define TEST_CAN_STD_ID_1 0x555 +#define TEST_CAN_STD_ID_2 0x556 + + +#if defined(CONFIG_CAN_LOOPBACK_DEV_NAME) +#define CAN_DEVICE_NAME CONFIG_CAN_LOOPBACK_DEV_NAME +#else +#define CAN_DEVICE_NAME DT_CHOSEN_ZEPHYR_CAN_PRIMARY_LABEL +#endif + +CAN_DEFINE_MSGQ(can_msgq, 5); +struct k_sem rx_isr_sem; +struct k_sem rx_cb_sem; +struct k_sem tx_cb_sem; +const struct device *can_dev; + +const struct zcan_frame test_std_msg_1 = { + .id_type = CAN_STANDARD_IDENTIFIER, + .rtr = CAN_DATAFRAME, + .id = TEST_CAN_STD_ID_1, + .dlc = 8, + .data = {1, 2, 3, 4, 5, 6, 7, 8} +}; + +const struct zcan_frame test_std_msg_2 = { + .id_type = CAN_STANDARD_IDENTIFIER, + .rtr = CAN_DATAFRAME, + .id = TEST_CAN_STD_ID_2, + .dlc = 8, + .data = {1, 2, 3, 4, 5, 6, 7, 8} +}; + +const struct zcan_frame test_std_msg_fd_1 = { + .id = TEST_CAN_STD_ID_1, + .fd = 1, + .rtr = CAN_DATAFRAME, + .id_type = CAN_STANDARD_IDENTIFIER, + .dlc = 0xf, + .brs = 1, + .data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64} +}; + +const struct zcan_frame test_std_msg_fd_2 = { + .id = TEST_CAN_STD_ID_2, + .fd = 1, + .rtr = CAN_DATAFRAME, + .id_type = CAN_STANDARD_IDENTIFIER, + .dlc = 0xf, + .brs = 1, + .data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64} +}; + +const struct zcan_filter test_std_filter_1 = { + .id_type = CAN_STANDARD_IDENTIFIER, + .rtr = CAN_DATAFRAME, + .id = TEST_CAN_STD_ID_1, + .rtr_mask = 1, + .id_mask = CAN_STD_ID_MASK +}; + +const struct zcan_filter test_std_filter_2 = { + .id_type = CAN_STANDARD_IDENTIFIER, + .rtr = CAN_DATAFRAME, + .id = TEST_CAN_STD_ID_2, + .rtr_mask = 1, + .id_mask = CAN_STD_ID_MASK +}; + + +struct zcan_work can_work_1; +struct zcan_work can_work_2; + +static inline void check_msg(const struct zcan_frame *msg1, + const struct zcan_frame *msg2) +{ + int cmp_res; + + zassert_equal(msg1->id_type, msg2->id_type, "ID type does not match"); + + zassert_equal(msg1->rtr, msg2->rtr, "RTR bit does not match"); + + zassert_equal(msg1->id, msg2->id, "ID does not match"); + + zassert_equal(msg1->dlc, msg2->dlc, "DLC does not match"); + + cmp_res = memcmp(msg1->data, msg2->data, can_dlc_to_bytes(msg1->dlc)); + + zassert_equal(cmp_res, 0, "Received data differ"); +} + +static void tx_std_isr_1(uint32_t error_flags, void *arg) +{ + const struct zcan_frame *msg = (const struct zcan_frame *)arg; + + k_sem_give(&tx_cb_sem); + + zassert_equal(msg->id, TEST_CAN_STD_ID_1, "Arg does not match"); +} + +static void tx_std_isr_2(uint32_t error_flags, void *arg) +{ + const struct zcan_frame *msg = (const struct zcan_frame *)arg; + + k_sem_give(&tx_cb_sem); + + zassert_equal(msg->id, TEST_CAN_STD_ID_2, "Arg does not match"); +} + +static void rx_std_isr_1(struct zcan_frame *msg, void *arg) +{ + check_msg(msg, &test_std_msg_1); + zassert_equal_ptr(arg, &test_std_filter_1, "arg does not match"); + k_sem_give(&rx_isr_sem); +} + +static void rx_std_isr_2(struct zcan_frame *msg, void *arg) +{ + check_msg(msg, &test_std_msg_2); + zassert_equal_ptr(arg, &test_std_filter_2, "arg does not match"); + k_sem_give(&rx_isr_sem); +} + +static void rx_std_isr_fd_1(struct zcan_frame *msg, void *arg) +{ + check_msg(msg, &test_std_msg_fd_1); + zassert_equal_ptr(arg, &test_std_filter_1, "arg does not match"); + k_sem_give(&rx_isr_sem); +} + +static void rx_std_isr_fd_2(struct zcan_frame *msg, void *arg) +{ + check_msg(msg, &test_std_msg_fd_2); + zassert_equal_ptr(arg, &test_std_filter_2, "arg does not match"); + k_sem_give(&rx_isr_sem); +} + +static void rx_std_cb_1(struct zcan_frame *msg, void *arg) +{ + check_msg(msg, &test_std_msg_1); + zassert_equal_ptr(arg, &test_std_filter_1, "arg does not match"); + k_sem_give(&rx_cb_sem); +} + +static void rx_std_cb_2(struct zcan_frame *msg, void *arg) +{ + check_msg(msg, &test_std_msg_2); + zassert_equal_ptr(arg, &test_std_filter_2, "arg does not match"); + k_sem_give(&rx_cb_sem); +} + +static void rx_std_fd_cb_1(struct zcan_frame *msg, void *arg) +{ + check_msg(msg, &test_std_msg_fd_1); + zassert_equal_ptr(arg, &test_std_filter_1, "arg does not match"); + k_sem_give(&rx_cb_sem); +} + +static void rx_std_fd_cb_2(struct zcan_frame *msg, void *arg) +{ + check_msg(msg, &test_std_msg_fd_2); + zassert_equal_ptr(arg, &test_std_filter_2, "arg does not match"); + k_sem_give(&rx_cb_sem); +} + +static void send_test_msg(const struct device *can_dev, + const struct zcan_frame *msg) +{ + int ret; + + ret = can_send(can_dev, msg, TEST_SEND_TIMEOUT, NULL, NULL); + zassert_not_equal(ret, CAN_TX_ARB_LOST, + "Arbitration though in loopback mode"); + zassert_equal(ret, CAN_TX_OK, "Can't send a message. Err: %d", ret); +} + +static void send_test_msg_nowait(const struct device *can_dev, + const struct zcan_frame *msg, + can_tx_callback_t cb) +{ + int ret; + + ret = can_send(can_dev, msg, TEST_SEND_TIMEOUT, cb, + (struct zcan_frame *)msg); + zassert_not_equal(ret, CAN_TX_ARB_LOST, + "Arbitration though in loopback mode"); + zassert_equal(ret, CAN_TX_OK, "Can't send a message. Err: %d", ret); +} + +static inline int attach_msgq(const struct device *can_dev, + const struct zcan_filter *filter) +{ + int filter_id; + + filter_id = can_attach_msgq(can_dev, &can_msgq, filter); + zassert_not_equal(filter_id, CAN_NO_FREE_FILTER, + "Filter full even for a single one"); + zassert_true((filter_id >= 0), "Negative filter number"); + + return filter_id; +} + +static inline int attach_workq(const struct device *can_dev, + const struct zcan_filter *filter, + struct zcan_work *work, + can_rx_callback_t cb) +{ + int filter_id; + + filter_id = can_attach_workq(can_dev, &k_sys_work_q, work, cb, + (void *)filter, filter); + + zassert_not_equal(filter_id, CAN_NO_FREE_FILTER, + "Filter full even for a single one"); + zassert_true((filter_id >= 0), "Negative filter number"); + + return filter_id; +} + +static inline int attach_isr(const struct device *can_dev, + const struct zcan_filter *filter, + can_rx_callback_t isr) +{ + int filter_id; + + k_sem_reset(&rx_isr_sem); + + filter_id = can_attach_isr(can_dev, isr, (void *)filter, filter); + zassert_not_equal(filter_id, CAN_NO_FREE_FILTER, + "Filter full even for a single one"); + zassert_true((filter_id >= 0), "Negative filter number"); + + return filter_id; +} + +static void send_receive(const struct zcan_filter *filter1, + const struct zcan_filter *filter2, + const struct zcan_frame *msg1, + const struct zcan_frame *msg2) +{ + int ret, filter_id_1, filter_id_2; + struct zcan_frame msg_buffer; + + zassert_not_null(can_dev, "Device not not found"); + + filter_id_1 = attach_msgq(can_dev, filter1); + send_test_msg(can_dev, msg1); + ret = k_msgq_get(&can_msgq, &msg_buffer, TEST_RECEIVE_TIMEOUT); + zassert_equal(ret, 0, "Receiving timeout"); + + check_msg(&msg_buffer, msg1); + can_detach(can_dev, filter_id_1); + + k_sem_reset(&tx_cb_sem); + + if (msg1->fd) { + filter_id_1 = attach_isr(can_dev, filter1, rx_std_isr_fd_1); + } else { + filter_id_1 = attach_isr(can_dev, filter1, rx_std_isr_1); + } + + if (msg2->fd) { + filter_id_2 = attach_isr(can_dev, filter2, rx_std_isr_fd_2); + } else { + filter_id_2 = attach_isr(can_dev, filter2, rx_std_isr_2); + } + + send_test_msg_nowait(can_dev, msg1, tx_std_isr_1); + send_test_msg_nowait(can_dev, msg2, tx_std_isr_2); + + ret = k_sem_take(&rx_isr_sem, TEST_RECEIVE_TIMEOUT); + zassert_equal(ret, 0, "Receiving timeout"); + ret = k_sem_take(&rx_isr_sem, TEST_RECEIVE_TIMEOUT); + zassert_equal(ret, 0, "Receiving timeout"); + ret = k_sem_take(&tx_cb_sem, TEST_SEND_TIMEOUT); + zassert_equal(ret, 0, "Missing TX callback"); + ret = k_sem_take(&tx_cb_sem, TEST_SEND_TIMEOUT); + zassert_equal(ret, 0, "Missing TX callback"); + can_detach(can_dev, filter_id_1); + can_detach(can_dev, filter_id_2); + + if (msg1->fd) { + filter_id_1 = attach_workq(can_dev, filter1, &can_work_1, + rx_std_fd_cb_1); + } else { + filter_id_1 = attach_workq(can_dev, filter1, &can_work_1, + rx_std_cb_1); + } + + if (msg2->fd) { + filter_id_2 = attach_workq(can_dev, filter2, &can_work_2, + rx_std_fd_cb_2); + } else { + filter_id_2 = attach_workq(can_dev, filter2, &can_work_2, + rx_std_cb_2); + } + + send_test_msg(can_dev, msg1); + send_test_msg(can_dev, msg2); + ret = k_sem_take(&rx_cb_sem, TEST_RECEIVE_TIMEOUT); + zassert_equal(ret, 0, "Receiving timeout"); + ret = k_sem_take(&rx_cb_sem, TEST_RECEIVE_TIMEOUT); + zassert_equal(ret, 0, "Receiving timeout"); + can_detach(can_dev, filter_id_2); + can_detach(can_dev, filter_id_1); +} + +/* + * Set driver to loopback mode + * The driver stays in loopback mode after that. + * The controller can now be tested against itself + */ +static void test_set_loopback(void) +{ + int ret; + + ret = can_set_mode(can_dev, CAN_LOOPBACK_MODE); + zassert_equal(ret, 0, "Can't set loopback-mode. Err: %d", ret); +} + +/* + * Attach to a filter that should pass the message and send the message. + * The massage should be received within a small timeout. + * Standard identifier, classic frame + */ +void test_send_receive_std(void) +{ + send_receive(&test_std_filter_1, &test_std_filter_2, + &test_std_msg_1, &test_std_msg_2); +} + +/* + * Attach to a filter that should pass the message and send the message. + * The massage should be received within a small timeout. + * Standard identifier, fd frame + */ +void test_send_receive_fd(void) +{ + send_receive(&test_std_filter_1, &test_std_filter_2, + &test_std_msg_fd_1, &test_std_msg_fd_2); +} + +/* + * Attach to a filter that should pass the message and send the message. + * The massage should be received within a small timeout. + * Standard identifier, classic frame and fd + */ +void test_send_receive_mix(void) +{ + send_receive(&test_std_filter_1, &test_std_filter_2, + &test_std_msg_fd_1, &test_std_msg_2); +} + +void test_main(void) +{ + k_sem_init(&rx_isr_sem, 0, 2); + k_sem_init(&rx_cb_sem, 0, INT_MAX); + k_sem_init(&tx_cb_sem, 0, 2); + can_dev = device_get_binding(CAN_DEVICE_NAME); + zassert_not_null(can_dev, "Device not found"); + + ztest_test_suite(canfd_driver, + ztest_unit_test(test_set_loopback), + ztest_unit_test(test_send_receive_std), + ztest_unit_test(test_send_receive_fd), + ztest_unit_test(test_send_receive_mix)); + ztest_run_test_suite(canfd_driver); +} diff --git a/tests/drivers/can/canfd/testcase.yaml b/tests/drivers/can/canfd/testcase.yaml new file mode 100644 index 0000000000000..c79afdb8710af --- /dev/null +++ b/tests/drivers/can/canfd/testcase.yaml @@ -0,0 +1,4 @@ +tests: + drivers.canfd: + tags: driver can + depends_on: canfd