From 1090e1a8ea7449e1e2e1d4fa5c693936ebdf699c Mon Sep 17 00:00:00 2001 From: "Alan C. Assis" Date: Sun, 3 Apr 2022 15:14:42 -0300 Subject: [PATCH] xtensa/esp32: Add support to TWAI/CANBus controller --- arch/xtensa/include/esp32/irq.h | 6 +- arch/xtensa/src/esp32/Kconfig | 62 + arch/xtensa/src/esp32/Make.defs | 4 + arch/xtensa/src/esp32/esp32_twai.c | 1257 +++++++++++++++++ arch/xtensa/src/esp32/esp32_twai.h | 77 + arch/xtensa/src/esp32/hardware/esp32_dport.h | 6 +- .../src/esp32/hardware/esp32_gpio_sigmap.h | 6 +- arch/xtensa/src/esp32/hardware/esp32_soc.h | 2 + arch/xtensa/src/esp32/hardware/esp32_twai.h | 856 +++++++++++ 9 files changed, 2270 insertions(+), 6 deletions(-) create mode 100644 arch/xtensa/src/esp32/esp32_twai.c create mode 100644 arch/xtensa/src/esp32/esp32_twai.h create mode 100644 arch/xtensa/src/esp32/hardware/esp32_twai.h diff --git a/arch/xtensa/include/esp32/irq.h b/arch/xtensa/include/esp32/irq.h index bd2a4fc35e..2ccb8fdcdc 100644 --- a/arch/xtensa/include/esp32/irq.h +++ b/arch/xtensa/include/esp32/irq.h @@ -117,7 +117,8 @@ #define ESP32_PERIPH_PWM3 42 /* INTR_STATUS_REG_1, bit 10 */ #define ESP32_PERIPH_LEDC 43 /* INTR_STATUS_REG_1, bit 11 */ #define ESP32_PERIPH_EFUSE 44 /* INTR_STATUS_REG_1, bit 12 */ -#define ESP32_PERIPH_CAN 45 /* INTR_STATUS_REG_1, bit 13 */ +#define ESP32_PERIPH_TWAI 45 /* INTR_STATUS_REG_1, bit 13 */ +#define ESP32_PERIPH_CAN ESP32_PERIPH_TWAI #define ESP32_PERIPH_RTC_CORE 46 /* INTR_STATUS_REG_1, bit 14 */ #define ESP32_PERIPH_RMT 47 /* INTR_STATUS_REG_1, bit 15 */ #define ESP32_PERIPH_PCNT 48 /* INTR_STATUS_REG_1, bit 16 */ @@ -244,7 +245,8 @@ #define ESP32_IRQ_PWM3 (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_PWM3) #define ESP32_IRQ_LEDC (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_LEDC) #define ESP32_IRQ_EFUSE (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_EFUSE) -#define ESP32_IRQ_CAN (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_CAN) +#define ESP32_IRQ_TWAI (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_CAN) +#define ESP32_IRQ_CAN ESP32_IRQ_TWAI #define ESP32_IRQ_RTC_CORE (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_RTC_CORE) #define ESP32_IRQ_RMT (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_RMT) #define ESP32_IRQ_PCNT (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_PCNT) diff --git a/arch/xtensa/src/esp32/Kconfig b/arch/xtensa/src/esp32/Kconfig index 4c0d3b12f6..b6032cae9f 100644 --- a/arch/xtensa/src/esp32/Kconfig +++ b/arch/xtensa/src/esp32/Kconfig @@ -309,6 +309,11 @@ config ESP32_I2C bool default n +config ESP32_TWAI + bool + default n + select CAN + config ESP32_I2S0 bool "I2S 0" default n @@ -527,6 +532,11 @@ config ESP32_I2C1 default n select ESP32_I2C +config ESP32_TWAI0 + bool "TWAI (CAN) 0" + default n + select ESP32_TWAI + config ESP32_AES_ACCELERATOR bool "AES Accelerator" default n @@ -830,6 +840,58 @@ config ESP32_I2CTIMEOMS endmenu # I2C configuration +menu "TWAI driver options" + depends on ESP32_TWAI + +if ESP32_TWAI0 + +config ESP32_TWAI0_TXPIN + int "TWAI0 TX Pin" + default 21 + +config ESP32_TWAI0_RXPIN + int "TWAI0 RX Pin" + default 22 + +config ESP32_TWAI0_BITRATE + int "TWAI0 bitrate" + default 1000000 + ---help--- + TWAI0 bit rate. Required if ESP32_TWAI0 is defined. + +config ESP32_TWAI0_SAMPLEP + int "TWAI0 sample point" + default 80 + ---help--- + TWAI0 sample point location as a percent value. Required + if ESP32_TWAI0 is defined. + +config ESP32_TWAI0_SJW + int "TWAI0 synchronization jump width" + default 3 + ---help--- + SJW limits the number of Time Quanta corrections during bit + Resynchronization. Default: 3 + +config ESP32_TWAI0_SAM + bool "TWAI0 sampling" + default n + ---help--- + The bus is sampled 3 times (recommended for low to medium speed buses + to spikes on the bus-line). + +endif # ESP32_TWAI0 + +config ESP32_TWAI_REGDEBUG + bool "TWAI register level debug" + depends on DEBUG_CAN_INFO + default n + ---help--- + Output detailed register-level TWAI debug information. Requires also + CONFIG_DEBUG_CAN_INFO. + +endmenu #ESP32_TWAI + menu "SPI configuration" depends on ESP32_SPI diff --git a/arch/xtensa/src/esp32/Make.defs b/arch/xtensa/src/esp32/Make.defs index 5bfdac40b3..77fd05d0f4 100644 --- a/arch/xtensa/src/esp32/Make.defs +++ b/arch/xtensa/src/esp32/Make.defs @@ -107,6 +107,10 @@ ifeq ($(CONFIG_ESP32_I2C),y) CHIP_CSRCS += esp32_i2c.c endif +ifeq ($(CONFIG_ESP32_TWAI),y) +CHIP_CSRCS += esp32_twai.c +endif + ifeq ($(CONFIG_ESP32_SPI),y) CHIP_CSRCS += esp32_spi.c ifeq ($(CONFIG_SPI_SLAVE),y) diff --git a/arch/xtensa/src/esp32/esp32_twai.c b/arch/xtensa/src/esp32/esp32_twai.c new file mode 100644 index 0000000000..ce5a3c0431 --- /dev/null +++ b/arch/xtensa/src/esp32/esp32_twai.c @@ -0,0 +1,1257 @@ +/**************************************************************************** + * arch/xtensa/src/esp32/esp32_twai.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "xtensa.h" + +#include "esp32_gpio.h" +#include "esp32_twai.h" +#include "esp32_irq.h" +#include "esp32_clockconfig.h" + +#include "hardware/esp32_dport.h" +#include "hardware/esp32_gpio_sigmap.h" + +#if defined(CONFIG_ESP32_TWAI) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* Default values written to various registers on initialization */ + +#define TWAI_INIT_TEC 0 +#define TWAI_INIT_REC 0 +#define TWAI_INIT_EWL 96 + +/* Exclude data overrun (bit[3]) and brp_div (bit[4]) */ + +#define TWAI_DEFAULT_INTERRUPTS 0xe7 + +#define TWAI_ACCEPTANCE_CODE 0x0 /* 32-bit address to match */ +#define TWAI_ACCEPTANCE_MASK 0xffffffff /* 32-bit address mask */ + +#ifdef CONFIG_ESP32_TWAI0 + +/* A TWAI bit rate must be provided */ + +# ifndef CONFIG_ESP32_TWAI0_BITRATE +# error "CONFIG_ESP32_TWAI0_BITRATE is not defined" +# endif + +/* If no sample point is provided, use a sample point of 80 */ + +# ifndef CONFIG_ESP32_TWAI0_SAMPLEP +# define CONFIG_ESP32_TWAI0_SAMPLEP 80 +# endif +#endif + +/* If no Synchronization Jump Width is provided, use a SJW of 3 */ + +#ifndef CONFIG_ESP32_TWAI0_SJW +# define CONFIG_ESP32_TWAI0_SJW 3 +#endif + +/* Debug ********************************************************************/ + +/* Non-standard debug that may be enabled just for testing TWAI */ + +#ifndef CONFIG_DEBUG_CAN_INFO +# undef CONFIG_ESP32_TWAI_REGDEBUG +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* CAN hardware-dependent bit-timing constant + * Used for calculating and checking bit-timing parameters + */ + +struct can_bittiming_const +{ + uint32_t tseg1_min; /* Time segment 1 */ + uint32_t tseg1_max; + uint32_t tseg2_min; /* Time segment 2 */ + uint32_t tseg2_max; + uint32_t sjw_min; /* Synchronization jump width */ + uint32_t sjw_max; + uint32_t brp_min; /* Bit-rate prescaler */ + uint32_t brp_max; + uint32_t brp_inc; +}; + +struct twai_dev_s +{ + /* Device configuration */ + + const struct can_bittiming_const *bittiming_const; + uint8_t port; /* TWAI port number */ + uint8_t periph; /* Peripheral ID */ + uint8_t irq; /* IRQ associated with this TWAI */ + uint8_t cpu; /* CPU ID */ + uint8_t cpuint; /* CPU interrupt assigned to this TWAI */ + uint32_t bitrate; /* Configured bit rate */ + uint32_t samplep; /* Configured sample point */ + uint32_t sjw; /* Synchronization jump width */ + uint32_t base; /* TWAI register base address */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* TWAI Register access */ + +#ifdef CONFIG_ESP32_TWAI_REGDEBUG +static void twai_printreg(uint32_t addr, uint32_t value); +#endif + +static uint32_t twai_getreg(uint32_t addr); +static void twai_putreg(uint32_t addr, uint32_t value); + +/* TWAI methods */ + +static void esp32twai_reset(FAR struct can_dev_s *dev); +static int esp32twai_setup(FAR struct can_dev_s *dev); +static void esp32twai_shutdown(FAR struct can_dev_s *dev); +static void esp32twai_rxint(FAR struct can_dev_s *dev, bool enable); +static void esp32twai_txint(FAR struct can_dev_s *dev, bool enable); +static int esp32twai_ioctl(FAR struct can_dev_s *dev, int cmd, + unsigned long arg); +static int esp32twai_remoterequest(FAR struct can_dev_s *dev, + uint16_t id); +static int esp32twai_send(FAR struct can_dev_s *dev, + FAR struct can_msg_s *msg); +static bool esp32twai_txready(FAR struct can_dev_s *dev); +static bool esp32twai_txempty(FAR struct can_dev_s *dev); + +/* TWAI interrupts */ + +static int esp32twai_interrupt(int irq, void *context, FAR void *arg); + +/* TWAI acceptance filter */ + +static void esp32twai_set_acc_filter(uint32_t code, uint32_t mask, + bool single_filter); + +/* TWAI bit-timing initialization */ + +static int twai_baud_rate(FAR struct twai_dev_s *priv, int rate, int clock, + int sjw, int sampl_pt, int flags); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct can_bittiming_const esp32_twai_bittiming_const = +{ + .tseg1_min = 1, + .tseg1_max = 16, + .tseg2_min = 1, + .tseg2_max = 8, + .sjw_min = 1, + .sjw_max = 3, + .brp_min = 1, + .brp_max = 64, + .brp_inc = 1, +}; + +static const struct can_ops_s g_twaiops = +{ + .co_reset = esp32twai_reset, + .co_setup = esp32twai_setup, + .co_shutdown = esp32twai_shutdown, + .co_rxint = esp32twai_rxint, + .co_txint = esp32twai_txint, + .co_ioctl = esp32twai_ioctl, + .co_remoterequest = esp32twai_remoterequest, + .co_send = esp32twai_send, + .co_txready = esp32twai_txready, + .co_txempty = esp32twai_txempty, +}; + +#ifdef CONFIG_ESP32_TWAI0 +static struct twai_dev_s g_twai0priv = +{ + .bittiming_const = &esp32_twai_bittiming_const, + .port = 0, + .periph = ESP32_PERIPH_TWAI, + .irq = ESP32_IRQ_TWAI, + .cpuint = -ENOMEM, + .bitrate = CONFIG_ESP32_TWAI0_BITRATE, + .samplep = CONFIG_ESP32_TWAI0_SAMPLEP, + .sjw = CONFIG_ESP32_TWAI0_SJW, + .base = DR_REG_TWAI_BASE, +}; + +static struct can_dev_s g_twai0dev = +{ + .cd_ops = &g_twaiops, + .cd_priv = &g_twai0priv, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: twai_printreg + * + * Description: + * Print the value read from a register. + * + * Input Parameters: + * addr - The register address + * value - The register value + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_ESP32_TWAI_REGDEBUG +static void twai_printreg(uint32_t addr, uint32_t value) +{ + static uint32_t prevaddr = 0; + static uint32_t preval = 0; + static uint32_t count = 0; + + /* Is this the same value that we read from the same register last time? + * Are we polling the register? If so, suppress some of the output. + */ + + if (addr == prevaddr && value == preval) + { + if (count == 0xffffffff || ++count > 3) + { + if (count == 4) + { + caninfo("...\n"); + } + + return; + } + } + + /* No this is a new address or value */ + + else + { + /* Did we print "..." for the previous value? */ + + if (count > 3) + { + /* Yes.. then show how many times the value repeated */ + + caninfo("[repeats %d more times]\n", count - 3); + } + + /* Save the new address, value, and count */ + + prevaddr = addr; + preval = value; + count = 1; + } + + /* Show the register value read */ + + caninfo("%08x->%08x\n", addr, value); +} +#endif + +/**************************************************************************** + * Name: twai_getreg + * + * Description: + * Read the value of an TWAI register. + * + * Input Parameters: + * addr - The address to the register to read + * + * Returned Value: + * + ****************************************************************************/ + +#ifdef CONFIG_ESP32_TWAI_REGDEBUG +static uint32_t twai_getreg(uint32_t addr) +{ + uint32_t value; + + /* Read the value from the register */ + + value = getreg32(addr); + twai_printreg(addr, value); + return value; +} +#else +static uint32_t twai_getreg(uint32_t addr) +{ + return getreg32(addr); +} +#endif + +/**************************************************************************** + * Name: twai_putreg + * + * Description: + * Set the value of an TWAI register. + * + * Input Parameters: + * addr - The address to the register to write + * value - The value to write to the register + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_ESP32_TWAI_REGDEBUG +static void twai_putreg(uint32_t addr, uint32_t value) +{ + /* Show the register value being written */ + + caninfo("%08x<-%08x\n", addr, value); + + /* Write the value */ + + putreg32(value, addr); +} +#else +static void twai_putreg(uint32_t addr, uint32_t value) +{ + putreg32(value, addr); +} +#endif + +/**************************************************************************** + * Name: esp32twai_reset + * + * Description: + * Reset the TWAI device. Called early to initialize the hardware. This + * function is called, before esp32_twai_setup() and on error conditions. + * + * Input Parameters: + * dev - An instance of the "upper half" CAN driver state structure. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp32twai_reset(FAR struct can_dev_s *dev) +{ + FAR struct twai_dev_s *priv = (FAR struct twai_dev_s *)dev->cd_priv; + irqstate_t flags; + int ret; + + caninfo("TWAI%" PRIu8 "\n", priv->port); + + flags = enter_critical_section(); + + /* Disable the TWAI and stop ongoing transmissions */ + + uint32_t mode_value = TWAI_RESET_MODE_M | TWAI_LISTEN_ONLY_MODE_M; + twai_putreg(TWAI_MODE_REG, mode_value); /* Enter Reset Mode */ + + twai_putreg(TWAI_INT_ENA_REG, 0); /* Disable interrupts */ + twai_getreg(TWAI_STATUS_REG); /* Clear status bits */ + + twai_putreg(TWAI_TX_ERR_CNT_REG, TWAI_INIT_TEC); /* TEC */ + twai_putreg(TWAI_RX_ERR_CNT_REG, TWAI_INIT_REC); /* REC */ + twai_putreg(TWAI_ERR_WARNING_LIMIT_REG, TWAI_INIT_EWL); /* EWL */ + + esp32twai_set_acc_filter(TWAI_ACCEPTANCE_CODE, + TWAI_ACCEPTANCE_MASK, true); + + /* Set bit timing */ + + ret = twai_baud_rate(priv, priv->bitrate, esp_clk_apb_freq(), + priv->sjw, priv->samplep, 0); + + if (ret != OK) + { + canerr("ERROR: Failed to set bit timing: %d\n", ret); + } + + /* Restart the TWAI */ + +#ifdef CONFIG_CAN_LOOPBACK + twai_putreg(TWAI_MODE_REG, TWAI_SELF_TEST_MODE_M); /* Leave Reset Mode, enter Test Mode */ +#else + twai_putreg(TWAI_MODE_REG, 0); /* Leave Reset Mode */ +#endif + + /* Abort transmission, release RX buffer and clear overrun. + * Command register can only be modified when in Operation Mode. + */ + + twai_putreg(TWAI_CMD_REG, TWAI_ABORT_TX_M | TWAI_RELEASE_BUF_M | + TWAI_CLR_OVERRUN_M); + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: esp32twai_setup + * + * Description: + * Configure the TWAI. This method is called the first time that the TWAI + * device is opened. This will occur when the port is first opened. + * This setup includes configuring and attaching TWAI interrupts. + * + * Input Parameters: + * dev - An instance of the "upper half" CAN driver state structure. + * + * Returned Value: + * Zero on success; a negated errno on failure + * + ****************************************************************************/ + +static int esp32twai_setup(FAR struct can_dev_s *dev) +{ + FAR struct twai_dev_s *priv = (FAR struct twai_dev_s *)dev->cd_priv; + irqstate_t flags; + int ret = OK; + + caninfo("TWAI%" PRIu8 "\n", priv->port); + + flags = enter_critical_section(); + + twai_putreg(TWAI_INT_ENA_REG, TWAI_DEFAULT_INTERRUPTS); + + twai_getreg(TWAI_INT_RAW_REG); /* clear latched interrupts */ + + if (priv->cpuint != -ENOMEM) + { + /* Disable the provided CPU Interrupt to configure it. */ + + up_disable_irq(priv->cpuint); + } + + priv->cpu = up_cpu_index(); + priv->cpuint = esp32_setup_irq(priv->cpu, priv->periph, + 1, ESP32_CPUINT_LEVEL); + if (priv->cpuint < 0) + { + /* Failed to allocate a CPU interrupt of this type. */ + + ret = priv->cpuint; + leave_critical_section(flags); + + return ret; + } + + ret = irq_attach(priv->irq, esp32twai_interrupt, dev); + if (ret != OK) + { + /* Failed to attach IRQ, so CPU interrupt must be freed. */ + + esp32_teardown_irq(priv->cpu, priv->periph, priv->cpuint); + priv->cpuint = -ENOMEM; + leave_critical_section(flags); + + return ret; + } + + /* Enable the CPU interrupt that is linked to the TWAI device. */ + + up_enable_irq(priv->cpuint); + + leave_critical_section(flags); + + return ret; +} + +/**************************************************************************** + * Name: esp32twai_shutdown + * + * Description: + * Disable the TWAI. This method is called when the TWAI device is closed. + * This method reverses the operation the setup method. + * + * Input Parameters: + * dev - An instance of the "upper half" CAN driver state structure. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp32twai_shutdown(FAR struct can_dev_s *dev) +{ + FAR struct twai_dev_s *priv = (FAR struct twai_dev_s *)dev->cd_priv; + +#ifdef CONFIG_DEBUG_CAN_INFO + caninfo("shutdown TWAI%" PRIu8 "\n", priv->port); +#endif + + if (priv->cpuint != -ENOMEM) + { + /* Disable cpu interrupt */ + + up_disable_irq(priv->cpuint); + + /* Dissociate the IRQ from the ISR */ + + irq_detach(priv->irq); + + /* Free cpu interrupt that is attached to this peripheral */ + + esp32_teardown_irq(priv->cpu, priv->periph, priv->cpuint); + priv->cpuint = -ENOMEM; + } + + return; +} + +/**************************************************************************** + * Name: esp32twai_rxint + * + * Description: + * Call to enable or disable RX interrupts. + * + * Input Parameters: + * dev - An instance of the "upper half" CAN driver state structure. + * enable - Enable or disable receive interrupt. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp32twai_rxint(FAR struct can_dev_s *dev, bool enable) +{ + FAR struct twai_dev_s *priv = (FAR struct twai_dev_s *)dev->cd_priv; + uint32_t regval; + irqstate_t flags; + + caninfo("TWAI%" PRIu8 " enable: %d\n", priv->port, enable); + + /* The INT_ENA register is also modified from the interrupt handler, + * so we have to protect this code section. + */ + + flags = enter_critical_section(); + regval = twai_getreg(TWAI_INT_ENA_REG); + if (enable) + { + regval |= TWAI_RX_INT_ENA_M; + } + else + { + regval &= ~TWAI_RX_INT_ENA_M; + } + + twai_putreg(TWAI_INT_ENA_REG, regval); + leave_critical_section(flags); + return; +} + +/**************************************************************************** + * Name: esp32twai_txint + * + * Description: + * Call to enable or disable TX interrupts. + * + * Input Parameters: + * dev - An instance of the "upper half" CAN driver state structure. + * enable - Enable or disable transmit interrupt. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp32twai_txint(FAR struct can_dev_s *dev, bool enable) +{ + FAR struct twai_dev_s *priv = (FAR struct twai_dev_s *)dev->cd_priv; + uint32_t regval; + irqstate_t flags; + + caninfo("TWAI%" PRIu8 " enable: %d\n", priv->port, enable); + + /* Only disabling of the TX interrupt is supported here. The TX interrupt + * is automatically enabled just before a message is sent in order to avoid + * lost TX interrupts. + */ + + if (!enable) + { + /* TX interrupts are also disabled from the interrupt handler, so we + * have to protect this code section. + */ + + flags = enter_critical_section(); + + /* Disable all TX interrupts */ + + regval = twai_getreg(TWAI_INT_ENA_REG); + regval &= ~(TWAI_TX_INT_ENA_M); + twai_putreg(TWAI_INT_ENA_REG, regval); + leave_critical_section(flags); + } +} + +/**************************************************************************** + * Name: esp32twai_ioctl + * + * Description: + * All ioctl calls will be routed through this method + * + * Input Parameters: + * dev - An instance of the "upper half" CAN driver state structure. + * cmd - A ioctl command. + * arg - A ioctl argument. + * + * Returned Value: + * Zero on success; a negated errno on failure + * + ****************************************************************************/ + +static int esp32twai_ioctl(FAR struct can_dev_s *dev, int cmd, + unsigned long arg) +{ + FAR struct twai_dev_s *priv = (FAR struct twai_dev_s *)dev->cd_priv; + int ret = -ENOTTY; + + caninfo("TWAI%" PRIu8 " cmd=%04x arg=%lu\n", priv->port, cmd, arg); + + /* Handle the command */ + + switch (cmd) + { + /* CANIOC_GET_BITTIMING: + * Description: Return the current bit timing settings + * Argument: A pointer to a write-able instance of struct + * canioc_bittiming_s in which current bit timing + * values will be returned. + * Returned Value: Zero (OK) is returned on success. Otherwise -1 + * (ERROR) is returned with the errno variable set + * to indicate the nature of the error. + * Dependencies: None + */ + + case CANIOC_GET_BITTIMING: + { + FAR struct canioc_bittiming_s *bt = + (FAR struct canioc_bittiming_s *)arg; + uint32_t timing0; + uint32_t timing1; + uint32_t brp; + + DEBUGASSERT(bt != NULL); + + timing0 = twai_getreg(TWAI_BUS_TIMING_0_REG); + timing1 = twai_getreg(TWAI_BUS_TIMING_1_REG); + + brp = ((timing0 & TWAI_BAUD_PRESC_M) + 1) * 2; + bt->bt_sjw = ((timing0 & TWAI_SYNC_JUMP_WIDTH_M) >> + TWAI_SYNC_JUMP_WIDTH_S) + 1; + + bt->bt_tseg1 = ((timing1 & TWAI_TIME_SEG1_M) >> + TWAI_TIME_SEG1_S) + 1; + bt->bt_tseg2 = ((timing1 & TWAI_TIME_SEG2_M) >> + TWAI_TIME_SEG2_S)+ 1; + bt->bt_baud = esp_clk_apb_freq() / + (brp * (bt->bt_tseg1 + bt->bt_tseg2 + 1)); + + ret = OK; + } + break; + + /* Unsupported/unrecognized command */ + + default: + canerr("ERROR: Unrecognized command: %04x\n", cmd); + break; + } + + return ret; +} + +static int esp32twai_remoterequest(FAR struct can_dev_s *dev, uint16_t id) +{ + canwarn("Remote request not implemented\n"); + return -ENOSYS; +} + +/**************************************************************************** + * Name: esp32twai_send + * + * Description: + * Send one TWAI message. + * + * One TWAI-message consists of a maximum of 10 bytes. A message is + * composed of at least the first 2 bytes (when there are no data bytes). + * + * Byte 0: Bits 0-7: Bits 3-10 of the 11-bit TWAI identifier + * Byte 1: Bits 5-7: Bits 0-2 of the 11-bit TWAI identifier + * Bit 4: Remote Transmission Request (RTR) + * Bits 0-3: Data Length Code (DLC) + * Bytes 2-10: TWAI data + * + * Input Parameters: + * dev - An instance of the "upper half" CAN driver state structure. + * msg - A message to send. + * + * Returned Value: + * Zero on success; a negated errno on failure + * + ****************************************************************************/ + +static int esp32twai_send(FAR struct can_dev_s *dev, + FAR struct can_msg_s *msg) +{ + FAR struct twai_dev_s *priv = (FAR struct twai_dev_s *)dev->cd_priv; + uint32_t regval; + uint32_t i; + uint32_t len; + uint32_t id; + uint32_t frame_info; + irqstate_t flags; + int ret = OK; + + caninfo("TWAI%" PRIu8 " ID: %" PRIu32 " DLC: %" PRIu8 "\n", + priv->port, (uint32_t)msg->cm_hdr.ch_id, msg->cm_hdr.ch_dlc); + + len = (uint32_t)msg->cm_hdr.ch_dlc; + if (len > CAN_MAXDATALEN) len = CAN_MAXDATALEN; + + frame_info = len; + + if (msg->cm_hdr.ch_rtr) + { + frame_info |= (1 << 6); + } + + flags = enter_critical_section(); + + /* Make sure that TX interrupts are enabled BEFORE sending the + * message. + * + * NOTE: The INT_ENA is also modified from the interrupt handler, but the + * following is safe because interrupts are disabled here. + */ + + regval = twai_getreg(TWAI_INT_ENA_REG); + regval |= TWAI_TX_INT_ENA_M; + twai_putreg(TWAI_INT_ENA_REG, regval); + + /* Set up the transfer */ + +#ifdef CONFIG_CAN_EXTID + if (msg->cm_hdr.ch_extid) + { + /* The provided ID should be 29 bits */ + + id = (uint32_t)msg->cm_hdr.ch_id; + DEBUGASSERT((id & ~CAN_MAX_EXTMSGID) == 0); + frame_info |= (1 << 7); + twai_putreg(TWAI_DATA_0_REG, frame_info); + + id <<= 3; + twai_putreg(TWAI_DATA_4_REG, id & 0xff); + id >>= 8; + twai_putreg(TWAI_DATA_3_REG, id & 0xff); + id >>= 8; + twai_putreg(TWAI_DATA_2_REG, id & 0xff); + id >>= 8; + twai_putreg(TWAI_DATA_1_REG, id & 0xff); + for (i = 0; i < len; i++) + { + twai_putreg(TWAI_DATA_5_REG + (i * 4), msg->cm_data[i]); + } + } + else +#endif + { + /* The provided ID should be 11 bits */ + + id = (uint32_t)msg->cm_hdr.ch_id; + DEBUGASSERT((id & ~CAN_MAX_STDMSGID) == 0); + twai_putreg(TWAI_DATA_0_REG, frame_info); + id <<= 5; + twai_putreg(TWAI_DATA_1_REG, (id >> 8) & 0xff); + twai_putreg(TWAI_DATA_2_REG, id & 0xff); + for (i = 0; i < len; i++) + { + twai_putreg(TWAI_DATA_3_REG + (i * 4), msg->cm_data[i]); + } + } + + /* Send the message */ + +#ifdef CONFIG_CAN_LOOPBACK + twai_putreg(TWAI_CMD_REG, TWAI_SELF_RX_REQ_M | TWAI_ABORT_TX_M); +#else + twai_putreg(TWAI_CMD_REG, TWAI_TX_REQ_M); +#endif + + leave_critical_section(flags); + + return ret; +} + +/**************************************************************************** + * Name: esp32twai_txready + * + * Description: + * Return true if the TWAI hardware can accept another TX message. + * + * Input Parameters: + * dev - An instance of the "upper half" CAN driver state structure. + * + * Returned Value: + * True if the TWAI hardware is ready to accept another TX message. + * + ****************************************************************************/ + +static bool esp32twai_txready(FAR struct can_dev_s *dev) +{ + FAR struct twai_dev_s *priv = dev->cd_priv; + uint32_t regval = twai_getreg(TWAI_STATUS_REG); + + caninfo("TWAI%" PRIu8 " txready: %d\n", priv->port, + ((regval & TWAI_TX_BUF_ST_M) != 0)); + return ((regval & TWAI_TX_BUF_ST_M) != 0); +} + +/**************************************************************************** + * Name: esp32twai_txempty + * + * Description: + * Return true if all message have been sent. If for example, the TWAI + * hardware implements FIFOs, then this would mean the transmit FIFO is + * empty. This method is called when the driver needs to make sure that + * all characters are "drained" from the TX hardware before calling + * co_shutdown(). + * + * Input Parameters: + * dev - An instance of the "upper half" CAN driver state structure. + * + * Returned Value: + * True if there are no pending TX transfers in the TWAI hardware. + * + ****************************************************************************/ + +static bool esp32twai_txempty(FAR struct can_dev_s *dev) +{ + FAR struct twai_dev_s *priv = dev->cd_priv; + uint32_t regval = twai_getreg(TWAI_STATUS_REG); + + caninfo("TWAI%" PRIu8 " txempty: %d\n", priv->port, + ((regval & TWAI_TX_BUF_ST_M) != 0)); + return ((regval & TWAI_TX_BUF_ST_M) != 0); +} + +/**************************************************************************** + * Name: esp32twai_interrupt + * + * Description: + * TWAI0 RX/TX interrupt handler + * + * Input Parameters: + * irq - The IRQ number of the interrupt. + * context - The register state save array at the time of the interrupt. + * arg - The pointer to driver structure. + * + * Returned Value: + * Zero on success; a negated errno on failure + * + ****************************************************************************/ + +static int esp32twai_interrupt(int irq, void *context, FAR void *arg) +{ +#ifdef CONFIG_ESP32_TWAI0 + FAR struct can_dev_s *dev = (FAR struct can_dev_s *)arg; + struct can_hdr_s hdr; + uint8_t data[8]; + uint32_t frame_info; + uint32_t len; + uint32_t datastart; + uint32_t regval; + uint32_t i; + + /* Read the interrupt register results in clearing bits */ + + regval = twai_getreg(TWAI_INT_RAW_REG); + + /* Check for a receive interrupt */ + + if ((regval & TWAI_RX_INT_ST_M) != 0) + { + memset(&hdr, 0, sizeof(hdr)); + memset(data, 0, sizeof(data)); + + frame_info = twai_getreg(TWAI_DATA_0_REG); + + /* Construct the TWAI header */ + + if (frame_info & (1 << 6)) + { + hdr.ch_rtr = 1; + } + +#ifdef CONFIG_CAN_EXTID + if (frame_info & (1 << 7)) + { + /* The provided ID should be 29 bits */ + + hdr.ch_extid = 1; + hdr.ch_id = + (twai_getreg(TWAI_DATA_1_REG) << 21) + + (twai_getreg(TWAI_DATA_2_REG) << 13) + + (twai_getreg(TWAI_DATA_3_REG) << 5) + + (twai_getreg(TWAI_DATA_4_REG) >> 3); + datastart = TWAI_DATA_5_REG; + } + else +#endif + { + /* The provided ID should be 11 bits */ + + hdr.ch_id = + (twai_getreg(TWAI_DATA_1_REG) << 3) + + (twai_getreg(TWAI_DATA_2_REG) >> 5); + datastart = TWAI_DATA_3_REG; + } + + len = frame_info & 0xf; + if (len > CAN_MAXDATALEN) len = CAN_MAXDATALEN; + hdr.ch_dlc = len; + + for (i = 0; i < len; i++) + { + data[i] = twai_getreg(datastart + (i * 4)); + } + + /* Release the receive buffer */ + + twai_putreg(TWAI_CMD_REG, TWAI_RELEASE_BUF_M); + +#ifdef CONFIG_CAN_ERRORS + hdr.ch_error = 0; /* Error reporting not supported */ +#endif + can_receive(dev, &hdr, data); + } + + /* Check for TX buffer complete */ + + if ((regval & TWAI_TX_INT_ST_M) != 0) + { + /* Disable all further TX buffer interrupts */ + + regval = twai_getreg(TWAI_INT_ENA_REG); + regval &= ~TWAI_TX_INT_ENA_M; + twai_putreg(TWAI_INT_ENA_REG, regval); + + /* Indicate that the TX is done and a new TX buffer is available */ + + can_txdone(dev); + } + +#endif + return OK; +} + +/**************************************************************************** + * Name: esp32twai_set_acc_filter + * + * Description: + * Call to set acceptance filter. + * Must be called in reset mode. + * + * Input Parameters: + * code - Acceptance Code. + * mask - Acceptance Mask. + * single_filter - Whether to enable single filter mode. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp32twai_set_acc_filter(uint32_t code, uint32_t mask, + bool single_filter) +{ + uint32_t regval; + uint32_t code_swapped = __builtin_bswap32(code); + uint32_t mask_swapped = __builtin_bswap32(mask); + + regval = twai_getreg(TWAI_MODE_REG); + if (single_filter) + { + regval |= TWAI_RX_FILTER_MODE_M; + } + else + { + regval &= ~(TWAI_RX_FILTER_MODE_M); + } + + twai_putreg(TWAI_MODE_REG, regval); + + for (int i = 0; i < 4; i++) + { + twai_putreg(TWAI_DATA_0_REG + (i * 4), + ((code_swapped >> (i * 8)) & 0xff)); + twai_putreg(TWAI_DATA_4_REG + (i * 4), + ((mask_swapped >> (i * 8)) & 0xff)); + } +} + +/**************************************************************************** + * Name: twai_baud_rate + * + * Description: + * Set the CAN bus timing registers based on the configured bit-rate and + * sample point position. + * + * The bit timing logic monitors the serial bus-line and performs sampling + * and adjustment of the sample point by synchronizing on the start-bit edge + * and resynchronizing on the following edges. + * + * Its operation may be explained simply by splitting nominal bit time into + * three segments as follows: + * + * 1. Synchronization segment (SYNC_SEG): a bit change is expected to occur + * within this time segment. It has a fixed length of one time quantum + * (1 x tCAN). + * 2. Bit segment 1 (BS1): defines the location of the sample point. It + * includes the PROP_SEG and PHASE_SEG1 of the CAN standard. Its duration + * is programmable between 1 and 16 time quanta but may be automatically + * lengthened to compensate for positive phase drifts due to differences + * in the frequency of the various nodes of the network. + * 3. Bit segment 2 (BS2): defines the location of the transmit point. It + * represents the PHASE_SEG2 of the CAN standard. Its duration is + * programmable between 1 and 8 time quanta but may also be automatically + * shortened to compensate for negative phase drifts. + * + * Pictorially: + * + * |<----------------- NOMINAL BIT TIME ----------------->| + * |<- SYNC_SEG ->|<------ BS1 ------>|<------ BS2 ------>| + * |<---- Tq ---->|<----- Tbs1 ------>|<----- Tbs2 ------>| + * + * Where + * Tbs1 is the duration of the BS1 segment + * Tbs2 is the duration of the BS2 segment + * Tq is the "Time Quantum" + * + * Relationships: + * + * baud = 1 / bit_time + * bit_time = Tq + Tbs1 + Tbs2 + * Tbs1 = Tq * ts1 + * Tbs2 = Tq * ts2 + * Tq = brp * Tcan + * + * Where: + * Tcan is the period of the APB clock + * + * Input Parameters: + * priv - A reference to the CAN block status + * + * Returned Value: + * Zero on success; a negated errno on failure + * + ****************************************************************************/ + +static int twai_baud_rate(struct twai_dev_s *priv, int rate, int clock, + int sjw, int sampl_pt, int flags) +{ + FAR const struct can_bittiming_const *timing = + &esp32_twai_bittiming_const; + int best_error = 1000000000; + int error; + int best_tseg = 0; + int best_brp = 0; + int best_rate = 0; + int brp = 0; + int tseg = 0; + int tseg1 = 0; + int tseg2 = 0; + uint32_t timing0; + uint32_t timing1; + + /* tseg even = round down, odd = round up */ + + for (tseg = (0 + 0 + 2) * 2; + tseg <= (timing->tseg2_max + timing->tseg1_max + 2) * 2 + 1; tseg++) + { + brp = clock / ((1 + tseg / 2) * rate) + tseg % 2; + if (brp == 0 || brp > 64) + { + continue; + } + + error = rate - clock / (brp * (1 + tseg / 2)); + if (error < 0) + { + error = -error; + } + + if (error <= best_error) + { + best_error = error; + best_tseg = tseg / 2; + best_brp = brp; + best_rate = clock / (brp * (1 + tseg / 2)); + } + } + + if (best_error && (rate / best_error < 10)) + { + canerr("baud rate %d is not possible with %d Hz clock\n", + rate, clock); + canerr("%d bps. brp=%d, best_tseg=%d, tseg1=%d, tseg2=%d\n", + best_rate, best_brp, best_tseg, tseg1, tseg2); + return -EINVAL; + } + + tseg2 = best_tseg - (sampl_pt * (best_tseg + 1)) / 100 + 1; + if (tseg2 < 0) + { + tseg2 = 0; + } + + if (tseg2 > timing->tseg2_max) + { + tseg2 = timing->tseg2_max; + } + + tseg1 = best_tseg - tseg2; + if (tseg1 > timing->tseg1_max) + { + tseg1 = timing->tseg1_max; + tseg2 = best_tseg - tseg1; + } + + caninfo("TS1: %d TS2: %d BRP: %d\n", tseg1, tseg2, best_brp); + + /* Configure bit timing */ + + timing0 = (best_brp - 1) / 2; + timing0 |= (sjw - 1) << TWAI_SYNC_JUMP_WIDTH_S; + + timing1 = tseg1 - 1; + timing1 |= (tseg2 - 1) << TWAI_TIME_SEG2_S; + +#ifdef CONFIG_ESP32_TWAI0_SAM + /* The bus is sampled 3 times (recommended for low to medium speed buses + * to spikes on the bus-line). + */ + + timing1 |= CONFIG_ESP32_TWAI0_SAM << TWAI_TIME_SAMP_S; +#endif + + twai_putreg(TWAI_BUS_TIMING_0_REG, timing0); + twai_putreg(TWAI_BUS_TIMING_1_REG, timing1); + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32_twaiinitialize + * + * Description: + * Initialize the selected TWAI port + * + * Input Parameters: + * Port number (for hardware that has multiple TWAI interfaces) + * + * Returned Value: + * Valid TWAI device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +FAR struct can_dev_s *esp32_twaiinitialize(int port) +{ + FAR struct can_dev_s *twaidev; + irqstate_t flags; + + caninfo("TWAI%" PRIu8 "\n", port); + + flags = enter_critical_section(); + +#ifdef CONFIG_ESP32_TWAI0 + if (port == 0) + { + /* Enable power to the TWAI module and + * Enable clocking to the TWAI module + */ + + modifyreg32(DPORT_PERIP_CLK_EN_REG, 0, DPORT_TWAI_CLK_EN); + modifyreg32(DPORT_PERIP_RST_EN_REG, DPORT_TWAI_RST, 0); + + /* Configure CAN GPIO pins */ + + esp32_gpio_matrix_out(CONFIG_ESP32_TWAI0_TXPIN, TWAI_TX_IDX, 0, 0); + esp32_configgpio(CONFIG_ESP32_TWAI0_TXPIN, OUTPUT_FUNCTION_1); + + esp32_configgpio(CONFIG_ESP32_TWAI0_RXPIN, INPUT_FUNCTION_1); + esp32_gpio_matrix_in(CONFIG_ESP32_TWAI0_RXPIN, TWAI_RX_IDX, 0); + + twaidev = &g_twai0dev; + } + else +#endif + + { + canerr("ERROR: Unsupported port: %d\n", port); + leave_critical_section(flags); + return NULL; + } + + /* Then just perform a TWAI reset operation */ + + esp32twai_reset(twaidev); + + leave_critical_section(flags); + + return twaidev; +} +#endif diff --git a/arch/xtensa/src/esp32/esp32_twai.h b/arch/xtensa/src/esp32/esp32_twai.h new file mode 100644 index 0000000000..7a1d3d23d0 --- /dev/null +++ b/arch/xtensa/src/esp32/esp32_twai.h @@ -0,0 +1,77 @@ +/**************************************************************************** + * arch/xtensa/src/esp32/esp32_twai.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_XTENSA_SRC_ESP32_ESP32_TWAI_H +#define __ARCH_XTENSA_SRC_ESP32_ESP32_TWAI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "hardware/esp32_twai.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +extern "C" +{ +#endif + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32_twaiinitialize + * + * Description: + * Initialize the selected CAN port + * + * Input Parameters: + * Port number (for hardware that has multiple TWAI interfaces) + * + * Returned Value: + * Valid TWAI device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +#if defined(CONFIG_CAN) && defined(CONFIG_ESP32_TWAI) +struct can_dev_s; +FAR struct can_dev_s *esp32_twaiinitialize(int port); +#endif + +#ifdef __cplusplus +} +#endif +#endif /* __ASSEMBLY__ */ + +#endif /* __ARCH_XTENSA_SRC_ESP32_ESP32_TWAI_H */ diff --git a/arch/xtensa/src/esp32/hardware/esp32_dport.h b/arch/xtensa/src/esp32/hardware/esp32_dport.h index a545535d88..968efaac61 100644 --- a/arch/xtensa/src/esp32/hardware/esp32_dport.h +++ b/arch/xtensa/src/esp32/hardware/esp32_dport.h @@ -1099,7 +1099,8 @@ #define DPORT_SPI_DMA_CLK_EN (BIT(22)) #define DPORT_I2S1_CLK_EN (BIT(21)) #define DPORT_PWM1_CLK_EN (BIT(20)) -#define DPORT_CAN_CLK_EN (BIT(19)) +#define DPORT_TWAI_CLK_EN (BIT(19)) +#define DPORT_CAN_CLK_EN DPORT_TWAI_CLK_EN #define DPORT_I2C_EXT1_CLK_EN (BIT(18)) #define DPORT_PWM0_CLK_EN (BIT(17)) #define DPORT_SPI_CLK_EN (BIT(16)) @@ -1134,7 +1135,8 @@ #define DPORT_SPI_DMA_RST (BIT(22)) #define DPORT_I2S1_RST (BIT(21)) #define DPORT_PWM1_RST (BIT(20)) -#define DPORT_CAN_RST (BIT(19)) +#define DPORT_TWAI_RST (BIT(19)) +#define DPORT_CAN_RST DPORT_CAN_RST #define DPORT_I2C_EXT1_RST (BIT(18)) #define DPORT_PWM0_RST (BIT(17)) #define DPORT_SPI_RST (BIT(16)) diff --git a/arch/xtensa/src/esp32/hardware/esp32_gpio_sigmap.h b/arch/xtensa/src/esp32/hardware/esp32_gpio_sigmap.h index e86fb49515..c83e909674 100644 --- a/arch/xtensa/src/esp32/hardware/esp32_gpio_sigmap.h +++ b/arch/xtensa/src/esp32/hardware/esp32_gpio_sigmap.h @@ -205,7 +205,8 @@ #define RMT_SIG_OUT5_IDX 92 #define EXT_ADC_START_IDX 93 #define RMT_SIG_OUT6_IDX 93 -#define CAN_RX_IDX 94 +#define TWAI_RX_IDX 94 +#define CAN_RX_IDX TWAI_RX_IDX #define RMT_SIG_OUT7_IDX 94 #define I2CEXT1_SCL_IN_IDX 95 #define I2CEXT1_SCL_OUT_IDX 95 @@ -263,7 +264,8 @@ #define PWM2_OUT4L_IDX 121 #define PWM3_CAP1_IN_IDX 122 #define PWM3_CAP2_IN_IDX 123 -#define CAN_TX_IDX 123 +#define TWAI_TX_IDX 123 +#define CAN_TX_IDX TWAI_TX_IDX #define PWM3_CAP3_IN_IDX 124 #define CAN_BUS_OFF_ON_IDX 124 #define CAN_CLKOUT_IDX 125 diff --git a/arch/xtensa/src/esp32/hardware/esp32_soc.h b/arch/xtensa/src/esp32/hardware/esp32_soc.h index a57412d4e9..f778795388 100644 --- a/arch/xtensa/src/esp32/hardware/esp32_soc.h +++ b/arch/xtensa/src/esp32/hardware/esp32_soc.h @@ -245,6 +245,8 @@ #define DR_REG_I2C1_EXT_BASE 0x3ff67000 #define DR_REG_SDMMC_BASE 0x3ff68000 #define DR_REG_EMAC_BASE 0x3ff69000 +#define DR_REG_TWAI_BASE 0x3ff6b000 +#define DR_REG_CAN_BASE DR_REG_TWAI_BASE #define DR_REG_PWM1_BASE 0x3ff6c000 #define DR_REG_I2S1_BASE 0x3ff6d000 #define DR_REG_UART2_BASE 0x3ff6e000 diff --git a/arch/xtensa/src/esp32/hardware/esp32_twai.h b/arch/xtensa/src/esp32/hardware/esp32_twai.h new file mode 100644 index 0000000000..c9811826e6 --- /dev/null +++ b/arch/xtensa/src/esp32/hardware/esp32_twai.h @@ -0,0 +1,856 @@ +/**************************************************************************** + * arch/xtensa/src/esp32/hardware/esp32_twai.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_XTENSA_SRC_ESP32_HARDWARE_ESP32_TWAI_H +#define __ARCH_XTENSA_SRC_ESP32_HARDWARE_ESP32_TWAI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "esp32_soc.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* TWAI_MODE_REG register + * Mode Register + */ + +#define TWAI_MODE_REG (DR_REG_TWAI_BASE + 0x0) + +/* TWAI_RX_FILTER_MODE : R/W; bitpos: [3]; default: 0; + * This bit is used to configure the filter mode. 0: Dual filter mode; 1: + * Single filter mode. + */ + +#define TWAI_RX_FILTER_MODE (BIT(3)) +#define TWAI_RX_FILTER_MODE_M (TWAI_RX_FILTER_MODE_V << TWAI_RX_FILTER_MODE_S) +#define TWAI_RX_FILTER_MODE_V 0x00000001 +#define TWAI_RX_FILTER_MODE_S 3 + +/* TWAI_SELF_TEST_MODE : R/W; bitpos: [2]; default: 0; + * 1: Self test mode. In this mode the TX nodes can perform a successful + * transmission without receiving the acknowledge signal. This mode is often + * used to test a single node with the self reception request command. + */ + +#define TWAI_SELF_TEST_MODE (BIT(2)) +#define TWAI_SELF_TEST_MODE_M (TWAI_SELF_TEST_MODE_V << TWAI_SELF_TEST_MODE_S) +#define TWAI_SELF_TEST_MODE_V 0x00000001 +#define TWAI_SELF_TEST_MODE_S 2 + +/* TWAI_LISTEN_ONLY_MODE : R/W; bitpos: [1]; default: 0; + * 1: Listen only mode. In this mode the nodes will only receive messages + * from the bus, without generating the acknowledge signal nor updating the + * RX error counter. + */ + +#define TWAI_LISTEN_ONLY_MODE (BIT(1)) +#define TWAI_LISTEN_ONLY_MODE_M (TWAI_LISTEN_ONLY_MODE_V << TWAI_LISTEN_ONLY_MODE_S) +#define TWAI_LISTEN_ONLY_MODE_V 0x00000001 +#define TWAI_LISTEN_ONLY_MODE_S 1 + +/* TWAI_RESET_MODE : R/W; bitpos: [0]; default: 1; + * This bit is used to configure the operating mode of the TWAI Controller. + * 1: Reset mode; 0: Operating mode. + */ + +#define TWAI_RESET_MODE (BIT(0)) +#define TWAI_RESET_MODE_M (TWAI_RESET_MODE_V << TWAI_RESET_MODE_S) +#define TWAI_RESET_MODE_V 0x00000001 +#define TWAI_RESET_MODE_S 0 + +/* TWAI_CMD_REG register + * Command Register + */ + +#define TWAI_CMD_REG (DR_REG_TWAI_BASE + 0x4) + +/* TWAI_SELF_RX_REQ : WO; bitpos: [4]; default: 0; + * Self reception request command. Set the bit to 1 to allow a message be + * transmitted and received simultaneously. + */ + +#define TWAI_SELF_RX_REQ (BIT(4)) +#define TWAI_SELF_RX_REQ_M (TWAI_SELF_RX_REQ_V << TWAI_SELF_RX_REQ_S) +#define TWAI_SELF_RX_REQ_V 0x00000001 +#define TWAI_SELF_RX_REQ_S 4 + +/* TWAI_CLR_OVERRUN : WO; bitpos: [3]; default: 0; + * Set the bit to 1 to clear the data overrun status bit. + */ + +#define TWAI_CLR_OVERRUN (BIT(3)) +#define TWAI_CLR_OVERRUN_M (TWAI_CLR_OVERRUN_V << TWAI_CLR_OVERRUN_S) +#define TWAI_CLR_OVERRUN_V 0x00000001 +#define TWAI_CLR_OVERRUN_S 3 + +/* TWAI_RELEASE_BUF : WO; bitpos: [2]; default: 0; + * Set the bit to 1 to release the RX buffer. + */ + +#define TWAI_RELEASE_BUF (BIT(2)) +#define TWAI_RELEASE_BUF_M (TWAI_RELEASE_BUF_V << TWAI_RELEASE_BUF_S) +#define TWAI_RELEASE_BUF_V 0x00000001 +#define TWAI_RELEASE_BUF_S 2 + +/* TWAI_ABORT_TX : WO; bitpos: [1]; default: 0; + * Set the bit to 1 to cancel a pending transmission request. + */ + +#define TWAI_ABORT_TX (BIT(1)) +#define TWAI_ABORT_TX_M (TWAI_ABORT_TX_V << TWAI_ABORT_TX_S) +#define TWAI_ABORT_TX_V 0x00000001 +#define TWAI_ABORT_TX_S 1 + +/* TWAI_TX_REQ : WO; bitpos: [0]; default: 0; + * Set the bit to 1 to allow the driving nodes start transmission. + */ + +#define TWAI_TX_REQ (BIT(0)) +#define TWAI_TX_REQ_M (TWAI_TX_REQ_V << TWAI_TX_REQ_S) +#define TWAI_TX_REQ_V 0x00000001 +#define TWAI_TX_REQ_S 0 + +/* TWAI_STATUS_REG register + * Status register + */ + +#define TWAI_STATUS_REG (DR_REG_TWAI_BASE + 0x8) + +/* TWAI_MISS_ST : RO; bitpos: [8]; default: 0; + * This bit reflects whether the data packet in the RX FIFO is complete. 1: + * The current packet is missing; 0: The current packet is complete + */ + +#define TWAI_MISS_ST (BIT(8)) +#define TWAI_MISS_ST_M (TWAI_MISS_ST_V << TWAI_MISS_ST_S) +#define TWAI_MISS_ST_V 0x00000001 +#define TWAI_MISS_ST_S 8 + +/* TWAI_BUS_OFF_ST : RO; bitpos: [7]; default: 0; + * 1: In bus-off status, the TWAI Controller is no longer involved in bus + * activities. + */ + +#define TWAI_BUS_OFF_ST (BIT(7)) +#define TWAI_BUS_OFF_ST_M (TWAI_BUS_OFF_ST_V << TWAI_BUS_OFF_ST_S) +#define TWAI_BUS_OFF_ST_V 0x00000001 +#define TWAI_BUS_OFF_ST_S 7 + +/* TWAI_ERR_ST : RO; bitpos: [6]; default: 0; + * 1: At least one of the RX/TX error counter has reached or exceeded the + * value set in register TWAI_ERR_WARNING_LIMIT_REG. + */ + +#define TWAI_ERR_ST (BIT(6)) +#define TWAI_ERR_ST_M (TWAI_ERR_ST_V << TWAI_ERR_ST_S) +#define TWAI_ERR_ST_V 0x00000001 +#define TWAI_ERR_ST_S 6 + +/* TWAI_TX_ST : RO; bitpos: [5]; default: 0; + * 1: The TWAI Controller is transmitting a message to the bus. + */ + +#define TWAI_TX_ST (BIT(5)) +#define TWAI_TX_ST_M (TWAI_TX_ST_V << TWAI_TX_ST_S) +#define TWAI_TX_ST_V 0x00000001 +#define TWAI_TX_ST_S 5 + +/* TWAI_RX_ST : RO; bitpos: [4]; default: 0; + * 1: The TWAI Controller is receiving a message from the bus. + */ + +#define TWAI_RX_ST (BIT(4)) +#define TWAI_RX_ST_M (TWAI_RX_ST_V << TWAI_RX_ST_S) +#define TWAI_RX_ST_V 0x00000001 +#define TWAI_RX_ST_S 4 + +/* TWAI_TX_COMPLETE : RO; bitpos: [3]; default: 0; + * 1: The TWAI controller has successfully received a packet from the bus. + */ + +#define TWAI_TX_COMPLETE (BIT(3)) +#define TWAI_TX_COMPLETE_M (TWAI_TX_COMPLETE_V << TWAI_TX_COMPLETE_S) +#define TWAI_TX_COMPLETE_V 0x00000001 +#define TWAI_TX_COMPLETE_S 3 + +/* TWAI_TX_BUF_ST : RO; bitpos: [2]; default: 0; + * 1: The TX buffer is empty, the CPU may write a message into it. + */ + +#define TWAI_TX_BUF_ST (BIT(2)) +#define TWAI_TX_BUF_ST_M (TWAI_TX_BUF_ST_V << TWAI_TX_BUF_ST_S) +#define TWAI_TX_BUF_ST_V 0x00000001 +#define TWAI_TX_BUF_ST_S 2 + +/* TWAI_OVERRUN_ST : RO; bitpos: [1]; default: 0; + * 1: The RX FIFO is full and data overrun has occurred. + */ + +#define TWAI_OVERRUN_ST (BIT(1)) +#define TWAI_OVERRUN_ST_M (TWAI_OVERRUN_ST_V << TWAI_OVERRUN_ST_S) +#define TWAI_OVERRUN_ST_V 0x00000001 +#define TWAI_OVERRUN_ST_S 1 + +/* TWAI_RX_BUF_ST : RO; bitpos: [0]; default: 0; + * 1: The data in the RX buffer is not empty, with at least one received + * data packet. + */ + +#define TWAI_RX_BUF_ST (BIT(0)) +#define TWAI_RX_BUF_ST_M (TWAI_RX_BUF_ST_V << TWAI_RX_BUF_ST_S) +#define TWAI_RX_BUF_ST_V 0x00000001 +#define TWAI_RX_BUF_ST_S 0 + +/* TWAI_INT_RAW_REG register + * Interrupt Register + */ + +#define TWAI_INT_RAW_REG (DR_REG_TWAI_BASE + 0xc) + +/* TWAI_BUS_ERR_INT_ST : RO; bitpos: [7]; default: 0; + * Error interrupt. If this bit is set to 1, it indicates an error is + * detected on the bus. + */ + +#define TWAI_BUS_ERR_INT_ST (BIT(7)) +#define TWAI_BUS_ERR_INT_ST_M (TWAI_BUS_ERR_INT_ST_V << TWAI_BUS_ERR_INT_ST_S) +#define TWAI_BUS_ERR_INT_ST_V 0x00000001 +#define TWAI_BUS_ERR_INT_ST_S 7 + +/* TWAI_ARB_LOST_INT_ST : RO; bitpos: [6]; default: 0; + * Arbitration lost interrupt. If this bit is set to 1, it indicates an + * arbitration lost interrupt is generated. + */ + +#define TWAI_ARB_LOST_INT_ST (BIT(6)) +#define TWAI_ARB_LOST_INT_ST_M (TWAI_ARB_LOST_INT_ST_V << TWAI_ARB_LOST_INT_ST_S) +#define TWAI_ARB_LOST_INT_ST_V 0x00000001 +#define TWAI_ARB_LOST_INT_ST_S 6 + +/* TWAI_ERR_PASSIVE_INT_ST : RO; bitpos: [5]; default: 0; + * Error passive interrupt. If this bit is set to 1, it indicates the TWAI + * Controller is switched between error active status and error passive + * status due to the change of error counters. + */ + +#define TWAI_ERR_PASSIVE_INT_ST (BIT(5)) +#define TWAI_ERR_PASSIVE_INT_ST_M (TWAI_ERR_PASSIVE_INT_ST_V << TWAI_ERR_PASSIVE_INT_ST_S) +#define TWAI_ERR_PASSIVE_INT_ST_V 0x00000001 +#define TWAI_ERR_PASSIVE_INT_ST_S 5 + +/* TWAI_OVERRUN_INT_ST : RO; bitpos: [3]; default: 0; + * Data overrun interrupt. If this bit is set to 1, it indicates a data + * overrun interrupt is generated in the RX FIFO. + */ + +#define TWAI_OVERRUN_INT_ST (BIT(3)) +#define TWAI_OVERRUN_INT_ST_M (TWAI_OVERRUN_INT_ST_V << TWAI_OVERRUN_INT_ST_S) +#define TWAI_OVERRUN_INT_ST_V 0x00000001 +#define TWAI_OVERRUN_INT_ST_S 3 + +/* TWAI_ERR_WARN_INT_ST : RO; bitpos: [2]; default: 0; + * Error warning interrupt. If this bit is set to 1, it indicates the error + * status signal and the bus-off status signal of Status register have + * changed (e.g., switched from 0 to 1 or from 1 to 0). + */ + +#define TWAI_ERR_WARN_INT_ST (BIT(2)) +#define TWAI_ERR_WARN_INT_ST_M (TWAI_ERR_WARN_INT_ST_V << TWAI_ERR_WARN_INT_ST_S) +#define TWAI_ERR_WARN_INT_ST_V 0x00000001 +#define TWAI_ERR_WARN_INT_ST_S 2 + +/* TWAI_TX_INT_ST : RO; bitpos: [1]; default: 0; + * Transmit interrupt. If this bit is set to 1, it indicates the message + * transmitting mis- sion is finished and a new transmission is able to + * execute. + */ + +#define TWAI_TX_INT_ST (BIT(1)) +#define TWAI_TX_INT_ST_M (TWAI_TX_INT_ST_V << TWAI_TX_INT_ST_S) +#define TWAI_TX_INT_ST_V 0x00000001 +#define TWAI_TX_INT_ST_S 1 + +/* TWAI_RX_INT_ST : RO; bitpos: [0]; default: 0; + * Receive interrupt. If this bit is set to 1, it indicates there are + * messages to be handled in the RX FIFO. + */ + +#define TWAI_RX_INT_ST (BIT(0)) +#define TWAI_RX_INT_ST_M (TWAI_RX_INT_ST_V << TWAI_RX_INT_ST_S) +#define TWAI_RX_INT_ST_V 0x00000001 +#define TWAI_RX_INT_ST_S 0 + +/* TWAI_INT_ENA_REG register + * Interrupt Enable Register + */ + +#define TWAI_INT_ENA_REG (DR_REG_TWAI_BASE + 0x10) + +/* TWAI_BUS_ERR_INT_ENA : R/W; bitpos: [7]; default: 0; + * Set this bit to 1 to enable error interrupt. + */ + +#define TWAI_BUS_ERR_INT_ENA (BIT(7)) +#define TWAI_BUS_ERR_INT_ENA_M (TWAI_BUS_ERR_INT_ENA_V << TWAI_BUS_ERR_INT_ENA_S) +#define TWAI_BUS_ERR_INT_ENA_V 0x00000001 +#define TWAI_BUS_ERR_INT_ENA_S 7 + +/* TWAI_ARB_LOST_INT_ENA : R/W; bitpos: [6]; default: 0; + * Set this bit to 1 to enable arbitration lost interrupt. + */ + +#define TWAI_ARB_LOST_INT_ENA (BIT(6)) +#define TWAI_ARB_LOST_INT_ENA_M (TWAI_ARB_LOST_INT_ENA_V << TWAI_ARB_LOST_INT_ENA_S) +#define TWAI_ARB_LOST_INT_ENA_V 0x00000001 +#define TWAI_ARB_LOST_INT_ENA_S 6 + +/* TWAI_ERR_PASSIVE_INT_ENA : R/W; bitpos: [5]; default: 0; + * Set this bit to 1 to enable error passive interrupt. + */ + +#define TWAI_ERR_PASSIVE_INT_ENA (BIT(5)) +#define TWAI_ERR_PASSIVE_INT_ENA_M (TWAI_ERR_PASSIVE_INT_ENA_V << TWAI_ERR_PASSIVE_INT_ENA_S) +#define TWAI_ERR_PASSIVE_INT_ENA_V 0x00000001 +#define TWAI_ERR_PASSIVE_INT_ENA_S 5 + +/* TWAI_OVERRUN_INT_ENA : R/W; bitpos: [3]; default: 0; + * Set this bit to 1 to enable data overrun interrupt. + */ + +#define TWAI_OVERRUN_INT_ENA (BIT(3)) +#define TWAI_OVERRUN_INT_ENA_M (TWAI_OVERRUN_INT_ENA_V << TWAI_OVERRUN_INT_ENA_S) +#define TWAI_OVERRUN_INT_ENA_V 0x00000001 +#define TWAI_OVERRUN_INT_ENA_S 3 + +/* TWAI_ERR_WARN_INT_ENA : R/W; bitpos: [2]; default: 0; + * Set this bit to 1 to enable error warning interrupt. + */ + +#define TWAI_ERR_WARN_INT_ENA (BIT(2)) +#define TWAI_ERR_WARN_INT_ENA_M (TWAI_ERR_WARN_INT_ENA_V << TWAI_ERR_WARN_INT_ENA_S) +#define TWAI_ERR_WARN_INT_ENA_V 0x00000001 +#define TWAI_ERR_WARN_INT_ENA_S 2 + +/* TWAI_TX_INT_ENA : R/W; bitpos: [1]; default: 0; + * Set this bit to 1 to enable transmit interrupt. + */ + +#define TWAI_TX_INT_ENA (BIT(1)) +#define TWAI_TX_INT_ENA_M (TWAI_TX_INT_ENA_V << TWAI_TX_INT_ENA_S) +#define TWAI_TX_INT_ENA_V 0x00000001 +#define TWAI_TX_INT_ENA_S 1 + +/* TWAI_RX_INT_ENA : R/W; bitpos: [0]; default: 0; + * Set this bit to 1 to enable receive interrupt. + */ + +#define TWAI_RX_INT_ENA (BIT(0)) +#define TWAI_RX_INT_ENA_M (TWAI_RX_INT_ENA_V << TWAI_RX_INT_ENA_S) +#define TWAI_RX_INT_ENA_V 0x00000001 +#define TWAI_RX_INT_ENA_S 0 + +/* TWAI_BUS_TIMING_0_REG register + * Bus Timing Register 0 + */ + +#define TWAI_BUS_TIMING_0_REG (DR_REG_TWAI_BASE + 0x18) + +/* TWAI_SYNC_JUMP_WIDTH : RO | R/W; bitpos: [15:14]; default: 0; + * Synchronization Jump Width (SJW), 1 \verb+~+ 14 Tq wide. + */ + +#define TWAI_SYNC_JUMP_WIDTH 0x00000003 +#define TWAI_SYNC_JUMP_WIDTH_M (TWAI_SYNC_JUMP_WIDTH_V << TWAI_SYNC_JUMP_WIDTH_S) +#define TWAI_SYNC_JUMP_WIDTH_V 0x00000003 +#define TWAI_SYNC_JUMP_WIDTH_S 14 + +/* TWAI_BAUD_PRESC : RO | R/W; bitpos: [13:0]; default: 0; + * Baud Rate Prescaler, determines the frequency dividing ratio. + */ + +#define TWAI_BAUD_PRESC 0x00003FFF +#define TWAI_BAUD_PRESC_M (TWAI_BAUD_PRESC_V << TWAI_BAUD_PRESC_S) +#define TWAI_BAUD_PRESC_V 0x00003FFF +#define TWAI_BAUD_PRESC_S 0 + +/* TWAI_BUS_TIMING_1_REG register + * Bus Timing Register 1 + */ + +#define TWAI_BUS_TIMING_1_REG (DR_REG_TWAI_BASE + 0x1c) + +/* TWAI_TIME_SAMP : RO | R/W; bitpos: [7]; default: 0; + * The number of sample points. 0: the bus is sampled once; 1: the bus is + * sampled three times + */ + +#define TWAI_TIME_SAMP (BIT(7)) +#define TWAI_TIME_SAMP_M (TWAI_TIME_SAMP_V << TWAI_TIME_SAMP_S) +#define TWAI_TIME_SAMP_V 0x00000001 +#define TWAI_TIME_SAMP_S 7 + +/* TWAI_TIME_SEG2 : RO | R/W; bitpos: [6:4]; default: 0; + * The width of PBS2. + */ + +#define TWAI_TIME_SEG2 0x00000007 +#define TWAI_TIME_SEG2_M (TWAI_TIME_SEG2_V << TWAI_TIME_SEG2_S) +#define TWAI_TIME_SEG2_V 0x00000007 +#define TWAI_TIME_SEG2_S 4 + +/* TWAI_TIME_SEG1 : RO | R/W; bitpos: [3:0]; default: 0; + * The width of PBS1. + */ + +#define TWAI_TIME_SEG1 0x0000000F +#define TWAI_TIME_SEG1_M (TWAI_TIME_SEG1_V << TWAI_TIME_SEG1_S) +#define TWAI_TIME_SEG1_V 0x0000000F +#define TWAI_TIME_SEG1_S 0 + +/* TWAI_ARB_LOST_CAP_REG register + * Arbitration Lost Capture Register + */ + +#define TWAI_ARB_LOST_CAP_REG (DR_REG_TWAI_BASE + 0x2c) + +/* TWAI_ARB_LOST_CAP : RO; bitpos: [4:0]; default: 0; + * This register contains information about the bit position of lost + * arbitration. + */ + +#define TWAI_ARB_LOST_CAP 0x0000001F +#define TWAI_ARB_LOST_CAP_M (TWAI_ARB_LOST_CAP_V << TWAI_ARB_LOST_CAP_S) +#define TWAI_ARB_LOST_CAP_V 0x0000001F +#define TWAI_ARB_LOST_CAP_S 0 + +/* TWAI_ERR_CODE_CAP_REG register + * Error Code Capture Register + */ + +#define TWAI_ERR_CODE_CAP_REG (DR_REG_TWAI_BASE + 0x30) + +/* TWAI_ECC_TYPE : RO; bitpos: [7:6]; default: 0; + * This register contains information about error types: 00: bit error; 01: + * form error; 10: stuff error; 11: other type of error + */ + +#define TWAI_ECC_TYPE 0x00000003 +#define TWAI_ECC_TYPE_M (TWAI_ECC_TYPE_V << TWAI_ECC_TYPE_S) +#define TWAI_ECC_TYPE_V 0x00000003 +#define TWAI_ECC_TYPE_S 6 + +/* TWAI_ECC_DIRECTION : RO; bitpos: [5]; default: 0; + * This register contains information about transmission direction of the + * node when error occurs. 1: Error occurs when receiving a message; 0: + * Error occurs when transmitting a message + */ + +#define TWAI_ECC_DIRECTION (BIT(5)) +#define TWAI_ECC_DIRECTION_M (TWAI_ECC_DIRECTION_V << TWAI_ECC_DIRECTION_S) +#define TWAI_ECC_DIRECTION_V 0x00000001 +#define TWAI_ECC_DIRECTION_S 5 + +/* TWAI_ECC_SEGMENT : RO; bitpos: [4:0]; default: 0; + * This register contains information about the location of errors, see + * Table 181 for details. + */ + +#define TWAI_ECC_SEGMENT 0x0000001F +#define TWAI_ECC_SEGMENT_M (TWAI_ECC_SEGMENT_V << TWAI_ECC_SEGMENT_S) +#define TWAI_ECC_SEGMENT_V 0x0000001F +#define TWAI_ECC_SEGMENT_S 0 + +/* TWAI_ERR_WARNING_LIMIT_REG register + * Error Warning Limit Register + */ + +#define TWAI_ERR_WARNING_LIMIT_REG (DR_REG_TWAI_BASE + 0x34) + +/* TWAI_ERR_WARNING_LIMIT : RO | R/W; bitpos: [7:0]; default: 96; + * Error warning threshold. In the case when any of a error counter value + * exceeds the threshold, or all the error counter values are below the + * threshold, an error warning interrupt will be triggered (given the enable + * signal is valid). + */ + +#define TWAI_ERR_WARNING_LIMIT 0x000000FF +#define TWAI_ERR_WARNING_LIMIT_M (TWAI_ERR_WARNING_LIMIT_V << TWAI_ERR_WARNING_LIMIT_S) +#define TWAI_ERR_WARNING_LIMIT_V 0x000000FF +#define TWAI_ERR_WARNING_LIMIT_S 0 + +/* TWAI_RX_ERR_CNT_REG register + * Receive Error Counter Register + */ + +#define TWAI_RX_ERR_CNT_REG (DR_REG_TWAI_BASE + 0x38) + +/* TWAI_RX_ERR_CNT : RO | R/W; bitpos: [7:0]; default: 0; + * The RX error counter register, reflects value changes under reception + * status. + */ + +#define TWAI_RX_ERR_CNT 0x000000FF +#define TWAI_RX_ERR_CNT_M (TWAI_RX_ERR_CNT_V << TWAI_RX_ERR_CNT_S) +#define TWAI_RX_ERR_CNT_V 0x000000FF +#define TWAI_RX_ERR_CNT_S 0 + +/* TWAI_TX_ERR_CNT_REG register + * Transmit Error Counter Register + */ + +#define TWAI_TX_ERR_CNT_REG (DR_REG_TWAI_BASE + 0x3c) + +/* TWAI_TX_ERR_CNT : RO | R/W; bitpos: [7:0]; default: 0; + * The TX error counter register, reflects value changes under transmission + * status. + */ + +#define TWAI_TX_ERR_CNT 0x000000FF +#define TWAI_TX_ERR_CNT_M (TWAI_TX_ERR_CNT_V << TWAI_TX_ERR_CNT_S) +#define TWAI_TX_ERR_CNT_V 0x000000FF +#define TWAI_TX_ERR_CNT_S 0 + +/* TWAI_DATA_0_REG register + * Data register 0 + */ + +#define TWAI_DATA_0_REG (DR_REG_TWAI_BASE + 0x40) + +/* TWAI_TX_BYTE_0 : WO; bitpos: [7:0]; default: 0; + * Stored the 0th byte information of the data to be transmitted under + * operating mode. + */ + +#define TWAI_TX_BYTE_0 0x000000FF +#define TWAI_TX_BYTE_0_M (TWAI_TX_BYTE_0_V << TWAI_TX_BYTE_0_S) +#define TWAI_TX_BYTE_0_V 0x000000FF +#define TWAI_TX_BYTE_0_S 0 + +/* TWAI_ACCEPTANCE_CODE_0 : WO; bitpos: [7:0]; default: 0; + * Stored the 0th byte of the filter code in reset mode. + */ + +#define TWAI_ACCEPTANCE_CODE_0 0x000000FF +#define TWAI_ACCEPTANCE_CODE_0_M (TWAI_ACCEPTANCE_CODE_0_V << TWAI_ACCEPTANCE_CODE_0_S) +#define TWAI_ACCEPTANCE_CODE_0_V 0x000000FF +#define TWAI_ACCEPTANCE_CODE_0_S 0 + +/* TWAI_DATA_1_REG register + * Data register 1 + */ + +#define TWAI_DATA_1_REG (DR_REG_TWAI_BASE + 0x44) + +/* TWAI_TX_BYTE_1 : WO; bitpos: [7:0]; default: 0; + * Stored the 1st byte information of the data to be transmitted under + * operating mode. + */ + +#define TWAI_TX_BYTE_1 0x000000FF +#define TWAI_TX_BYTE_1_M (TWAI_TX_BYTE_1_V << TWAI_TX_BYTE_1_S) +#define TWAI_TX_BYTE_1_V 0x000000FF +#define TWAI_TX_BYTE_1_S 0 + +/* TWAI_ACCEPTANCE_CODE_1 : WO; bitpos: [7:0]; default: 0; + * Stored the 1st byte of the filter code in reset mode. + */ + +#define TWAI_ACCEPTANCE_CODE_1 0x000000FF +#define TWAI_ACCEPTANCE_CODE_1_M (TWAI_ACCEPTANCE_CODE_1_V << TWAI_ACCEPTANCE_CODE_1_S) +#define TWAI_ACCEPTANCE_CODE_1_V 0x000000FF +#define TWAI_ACCEPTANCE_CODE_1_S 0 + +/* TWAI_DATA_2_REG register + * Data register 2 + */ + +#define TWAI_DATA_2_REG (DR_REG_TWAI_BASE + 0x48) + +/* TWAI_TX_BYTE_2 : WO; bitpos: [7:0]; default: 0; + * Stored the 2nd byte information of the data to be transmitted under + * operating mode. + */ + +#define TWAI_TX_BYTE_2 0x000000FF +#define TWAI_TX_BYTE_2_M (TWAI_TX_BYTE_2_V << TWAI_TX_BYTE_2_S) +#define TWAI_TX_BYTE_2_V 0x000000FF +#define TWAI_TX_BYTE_2_S 0 + +/* TWAI_ACCEPTANCE_CODE_2 : WO; bitpos: [7:0]; default: 0; + * Stored the 2nd byte of the filter code in reset mode. + */ + +#define TWAI_ACCEPTANCE_CODE_2 0x000000FF +#define TWAI_ACCEPTANCE_CODE_2_M (TWAI_ACCEPTANCE_CODE_2_V << TWAI_ACCEPTANCE_CODE_2_S) +#define TWAI_ACCEPTANCE_CODE_2_V 0x000000FF +#define TWAI_ACCEPTANCE_CODE_2_S 0 + +/* TWAI_DATA_3_REG register + * Data register 3 + */ + +#define TWAI_DATA_3_REG (DR_REG_TWAI_BASE + 0x4c) + +/* TWAI_TX_BYTE_3 : WO; bitpos: [7:0]; default: 0; + * Stored the 3rd byte information of the data to be transmitted under + * operating mode. + */ + +#define TWAI_TX_BYTE_3 0x000000FF +#define TWAI_TX_BYTE_3_M (TWAI_TX_BYTE_3_V << TWAI_TX_BYTE_3_S) +#define TWAI_TX_BYTE_3_V 0x000000FF +#define TWAI_TX_BYTE_3_S 0 + +/* TWAI_ACCEPTANCE_CODE_3 : WO; bitpos: [7:0]; default: 0; + * Stored the 3rd byte of the filter code in reset mode. + */ + +#define TWAI_ACCEPTANCE_CODE_3 0x000000FF +#define TWAI_ACCEPTANCE_CODE_3_M (TWAI_ACCEPTANCE_CODE_3_V << TWAI_ACCEPTANCE_CODE_3_S) +#define TWAI_ACCEPTANCE_CODE_3_V 0x000000FF +#define TWAI_ACCEPTANCE_CODE_3_S 0 + +/* TWAI_DATA_4_REG register + * Data register 4 + */ + +#define TWAI_DATA_4_REG (DR_REG_TWAI_BASE + 0x50) + +/* TWAI_TX_BYTE_4 : WO; bitpos: [7:0]; default: 0; + * Stored the 4th byte information of the data to be transmitted under + * operating mode. + */ + +#define TWAI_TX_BYTE_4 0x000000FF +#define TWAI_TX_BYTE_4_M (TWAI_TX_BYTE_4_V << TWAI_TX_BYTE_4_S) +#define TWAI_TX_BYTE_4_V 0x000000FF +#define TWAI_TX_BYTE_4_S 0 + +/* TWAI_ACCEPTANCE_MASK_0 : WO; bitpos: [7:0]; default: 0; + * Stored the 0th byte of the filter code in reset mode. + */ + +#define TWAI_ACCEPTANCE_MASK_0 0x000000FF +#define TWAI_ACCEPTANCE_MASK_0_M (TWAI_ACCEPTANCE_MASK_0_V << TWAI_ACCEPTANCE_MASK_0_S) +#define TWAI_ACCEPTANCE_MASK_0_V 0x000000FF +#define TWAI_ACCEPTANCE_MASK_0_S 0 + +/* TWAI_DATA_5_REG register + * Data register 5 + */ + +#define TWAI_DATA_5_REG (DR_REG_TWAI_BASE + 0x54) + +/* TWAI_TX_BYTE_5 : WO; bitpos: [7:0]; default: 0; + * Stored the 5th byte information of the data to be transmitted under + * operating mode. + */ + +#define TWAI_TX_BYTE_5 0x000000FF +#define TWAI_TX_BYTE_5_M (TWAI_TX_BYTE_5_V << TWAI_TX_BYTE_5_S) +#define TWAI_TX_BYTE_5_V 0x000000FF +#define TWAI_TX_BYTE_5_S 0 + +/* TWAI_ACCEPTANCE_MASK_1 : WO; bitpos: [7:0]; default: 0; + * Stored the 1st byte of the filter code in reset mode. + */ + +#define TWAI_ACCEPTANCE_MASK_1 0x000000FF +#define TWAI_ACCEPTANCE_MASK_1_M (TWAI_ACCEPTANCE_MASK_1_V << TWAI_ACCEPTANCE_MASK_1_S) +#define TWAI_ACCEPTANCE_MASK_1_V 0x000000FF +#define TWAI_ACCEPTANCE_MASK_1_S 0 + +/* TWAI_DATA_6_REG register + * Data register 6 + */ + +#define TWAI_DATA_6_REG (DR_REG_TWAI_BASE + 0x58) + +/* TWAI_TX_BYTE_6 : WO; bitpos: [7:0]; default: 0; + * Stored the 6th byte information of the data to be transmitted under + * operating mode. + */ + +#define TWAI_TX_BYTE_6 0x000000FF +#define TWAI_TX_BYTE_6_M (TWAI_TX_BYTE_6_V << TWAI_TX_BYTE_6_S) +#define TWAI_TX_BYTE_6_V 0x000000FF +#define TWAI_TX_BYTE_6_S 0 + +/* TWAI_ACCEPTANCE_MASK_2 : WO; bitpos: [7:0]; default: 0; + * Stored the 2nd byte of the filter code in reset mode. + */ + +#define TWAI_ACCEPTANCE_MASK_2 0x000000FF +#define TWAI_ACCEPTANCE_MASK_2_M (TWAI_ACCEPTANCE_MASK_2_V << TWAI_ACCEPTANCE_MASK_2_S) +#define TWAI_ACCEPTANCE_MASK_2_V 0x000000FF +#define TWAI_ACCEPTANCE_MASK_2_S 0 + +/* TWAI_DATA_7_REG register + * Data register 7 + */ + +#define TWAI_DATA_7_REG (DR_REG_TWAI_BASE + 0x5c) + +/* TWAI_TX_BYTE_7 : WO; bitpos: [7:0]; default: 0; + * Stored the 7th byte information of the data to be transmitted under + * operating mode. + */ + +#define TWAI_TX_BYTE_7 0x000000FF +#define TWAI_TX_BYTE_7_M (TWAI_TX_BYTE_7_V << TWAI_TX_BYTE_7_S) +#define TWAI_TX_BYTE_7_V 0x000000FF +#define TWAI_TX_BYTE_7_S 0 + +/* TWAI_ACCEPTANCE_MASK_3 : WO; bitpos: [7:0]; default: 0; + * Stored the 3th byte of the filter code in reset mode. + */ + +#define TWAI_ACCEPTANCE_MASK_3 0x000000FF +#define TWAI_ACCEPTANCE_MASK_3_M (TWAI_ACCEPTANCE_MASK_3_V << TWAI_ACCEPTANCE_MASK_3_S) +#define TWAI_ACCEPTANCE_MASK_3_V 0x000000FF +#define TWAI_ACCEPTANCE_MASK_3_S 0 + +/* TWAI_DATA_8_REG register + * Data register 8 + */ + +#define TWAI_DATA_8_REG (DR_REG_TWAI_BASE + 0x60) + +/* TWAI_TX_BYTE_8 : WO; bitpos: [7:0]; default: 0; + * Stored the 8th byte information of the data to be transmitted under + * operating mode. + */ + +#define TWAI_TX_BYTE_8 0x000000FF +#define TWAI_TX_BYTE_8_M (TWAI_TX_BYTE_8_V << TWAI_TX_BYTE_8_S) +#define TWAI_TX_BYTE_8_V 0x000000FF +#define TWAI_TX_BYTE_8_S 0 + +/* TWAI_DATA_9_REG register + * Data register 9 + */ + +#define TWAI_DATA_9_REG (DR_REG_TWAI_BASE + 0x64) + +/* TWAI_TX_BYTE_9 : WO; bitpos: [7:0]; default: 0; + * Stored the 9th byte information of the data to be transmitted under + * operating mode. + */ + +#define TWAI_TX_BYTE_9 0x000000FF +#define TWAI_TX_BYTE_9_M (TWAI_TX_BYTE_9_V << TWAI_TX_BYTE_9_S) +#define TWAI_TX_BYTE_9_V 0x000000FF +#define TWAI_TX_BYTE_9_S 0 + +/* TWAI_DATA_10_REG register + * Data register 10 + */ + +#define TWAI_DATA_10_REG (DR_REG_TWAI_BASE + 0x68) + +/* TWAI_TX_BYTE_10 : WO; bitpos: [7:0]; default: 0; + * Stored the 10th byte information of the data to be transmitted under + * operating mode. + */ + +#define TWAI_TX_BYTE_10 0x000000FF +#define TWAI_TX_BYTE_10_M (TWAI_TX_BYTE_10_V << TWAI_TX_BYTE_10_S) +#define TWAI_TX_BYTE_10_V 0x000000FF +#define TWAI_TX_BYTE_10_S 0 + +/* TWAI_DATA_11_REG register + * Data register 11 + */ + +#define TWAI_DATA_11_REG (DR_REG_TWAI_BASE + 0x6c) + +/* TWAI_TX_BYTE_11 : WO; bitpos: [7:0]; default: 0; + * Stored the 11th byte information of the data to be transmitted under + * operating mode. + */ + +#define TWAI_TX_BYTE_11 0x000000FF +#define TWAI_TX_BYTE_11_M (TWAI_TX_BYTE_11_V << TWAI_TX_BYTE_11_S) +#define TWAI_TX_BYTE_11_V 0x000000FF +#define TWAI_TX_BYTE_11_S 0 + +/* TWAI_DATA_12_REG register + * Data register 12 + */ + +#define TWAI_DATA_12_REG (DR_REG_TWAI_BASE + 0x70) + +/* TWAI_TX_BYTE_12 : WO; bitpos: [7:0]; default: 0; + * Stored the 12th byte information of the data to be transmitted under + * operating mode. + */ + +#define TWAI_TX_BYTE_12 0x000000FF +#define TWAI_TX_BYTE_12_M (TWAI_TX_BYTE_12_V << TWAI_TX_BYTE_12_S) +#define TWAI_TX_BYTE_12_V 0x000000FF +#define TWAI_TX_BYTE_12_S 0 + +/* TWAI_RX_MESSAGE_CNT_REG register + * Receive Message Counter Register + */ + +#define TWAI_RX_MESSAGE_CNT_REG (DR_REG_TWAI_BASE + 0x74) + +/* TWAI_RX_MESSAGE_COUNTER : RO; bitpos: [6:0]; default: 0; + * This register reflects the number of messages available within the RX + * FIFO. + */ + +#define TWAI_RX_MESSAGE_COUNTER 0x0000007F +#define TWAI_RX_MESSAGE_COUNTER_M (TWAI_RX_MESSAGE_COUNTER_V << TWAI_RX_MESSAGE_COUNTER_S) +#define TWAI_RX_MESSAGE_COUNTER_V 0x0000007F +#define TWAI_RX_MESSAGE_COUNTER_S 0 + +/* TWAI_CLOCK_DIVIDER_REG register + * Clock Divider register + */ + +#define TWAI_CLOCK_DIVIDER_REG (DR_REG_TWAI_BASE + 0x7c) + +/* TWAI_CLOCK_OFF : RO | R/W; bitpos: [8]; default: 0; + * This bit can be configured under reset mode. 1: Disable the external + * CLKOUT pin; 0: Enable the external CLKOUT pin + */ + +#define TWAI_CLOCK_OFF (BIT(8)) +#define TWAI_CLOCK_OFF_M (TWAI_CLOCK_OFF_V << TWAI_CLOCK_OFF_S) +#define TWAI_CLOCK_OFF_V 0x00000001 +#define TWAI_CLOCK_OFF_S 8 + +/* TWAI_CD : R/W; bitpos: [7:0]; default: 0; + * These bits are used to configure frequency dividing coefficients of the + * external CLKOUT pin. + */ + +#define TWAI_CD 0x000000FF +#define TWAI_CD_M (TWAI_CD_V << TWAI_CD_S) +#define TWAI_CD_V 0x000000FF +#define TWAI_CD_S 0 + +#endif /* __ARCH_XTENSA_SRC_ESP32_HARDWARE_ESP32_TWAI_H */