diff --git a/drivers/can/Kconfig b/drivers/can/Kconfig index 1d663c75691..d6a2b88a1d6 100644 --- a/drivers/can/Kconfig +++ b/drivers/can/Kconfig @@ -193,4 +193,44 @@ config MCP2515_SPI_SCK_FREQUENCY endif # CAN_MCP2515 -endif +menuconfig CAN_SJA1000 + tristate "Philips/NXP SJA1000 devices" + +if CAN_SJA1000 + +config CAN_SJA1000_BITRATE + int "SJA1000 bitrate" + default 1000000 + ---help--- + SJA1000 bit rate. + +config CAN_SJA1000_SJW + int "SJA1000 Synchronization Jump Width" + default 1 + range 1 4 + ---help--- + The duration of a synchronization jump is SJW. + +config CAN_SJA1000_SAM + bool "The CAN bus is sampled 3 times" + default false + ---help--- + Recommended for low to medium speed buses + to filter spikes on the bus-line. + +config CAN_SJA1000_SAMPLEP + int "SJA1000 CAN sample point (Percentage)" + default 87 + range 0 100 + +config CANBUS_REGDEBUG + bool "CAN BUS register debug enable." + default false + +config CAN_SJA1000_DEBUG + bool "SJA1000 CAN BUS trace debug enable." + default false + +endif # CAN_SJA1000 + +endif # CAN diff --git a/drivers/can/Make.defs b/drivers/can/Make.defs index 5d4014e7f14..49a4e7ca0ee 100644 --- a/drivers/can/Make.defs +++ b/drivers/can/Make.defs @@ -28,6 +28,10 @@ ifeq ($(CONFIG_CAN_MCP2515),y) CSRCS += mcp2515.c endif +ifeq ($(CONFIG_CAN_SJA1000),y) + CSRCS += sja1000.c +endif + # Include CAN device driver build support DEPPATH += --dep-path can diff --git a/drivers/can/sja1000.c b/drivers/can/sja1000.c new file mode 100644 index 00000000000..5da5f815661 --- /dev/null +++ b/drivers/can/sja1000.c @@ -0,0 +1,1174 @@ +/**************************************************************************** + * drivers/can/sja1000.c + * + * SJA1000 CAN driver based on esp32c3_twai.c + * + * License header retained from original source. + * + * 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 +#include + +#include +#include "sja1000.h" + +#include + +#ifdef CONFIG_CAN_SJA1000 + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration + * ************************************************************/ + +#if defined(CONFIG_CAN_SJA1000_DEBUG) +#define cantrace _info +#else +#define cantrace _none +#endif /* CONFIG_CAN_SJA1000_DEBUG */ + +/* Default values written to various registers on initialization */ + +#define SJA1000_INIT_TEC 0 +#define SJA1000_INIT_REC 0 +#define SJA1000_INIT_EWL 96 + +#define SJA1000_ACCEPTANCE_CODE 0x0 /* 32-bit address to match */ +#define SJA1000_ACCEPTANCE_MASK 0xffffffff /* 32-bit address mask */ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* SJA1000 Register access */ + +#ifdef CONFIG_CANBUS_REGDEBUG +static void sja1000_printreg(uint32_t addr, uint32_t value); +#endif + +/* SJA1000 methods */ + +static void sja1000_reset(struct can_dev_s *dev); +static int sja1000_setup(struct can_dev_s *dev); +static void sja1000_shutdown(struct can_dev_s *dev); +static void sja1000_rxint(struct can_dev_s *dev, bool enable); +static void sja1000_txint(struct can_dev_s *dev, bool enable); +static int sja1000_ioctl(struct can_dev_s *dev, int cmd, unsigned long arg); +static int sja1000_remoterequest(struct can_dev_s *dev, uint16_t id); +static int sja1000_send(struct can_dev_s *dev, struct can_msg_s *msg); +static bool sja1000_txready(struct can_dev_s *dev); +static bool sja1000_txempty(struct can_dev_s *dev); + +/* SJA1000 interrupts */ + +static int sja1000_interrupt(FAR struct sja1000_config_s *config, + void *arg); + +/* SJA1000 acceptance filter */ + +static void sja1000_set_acc_filter(struct sja1000_dev_s *priv, + uint32_t code, uint32_t mask, + bool single_filter); + +/* SJA1000 bit-timing initialization */ + +static int sja1000_baud_rate(struct sja1000_dev_s *priv, int rate, + int clock, int sjw, int sampl_pt, int flags); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct can_ops_s g_sja1000ops = +{ + .co_reset = sja1000_reset, + .co_setup = sja1000_setup, + .co_shutdown = sja1000_shutdown, + .co_rxint = sja1000_rxint, + .co_txint = sja1000_txint, + .co_ioctl = sja1000_ioctl, + .co_remoterequest = sja1000_remoterequest, + .co_send = sja1000_send, + .co_txready = sja1000_txready, + .co_txempty = sja1000_txempty, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sja1000_printreg + * + * Description: + * Print the value read from a register. + * + * Input Parameters: + * addr - The register address + * value - The register value + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_CANBUS_REGDEBUG +static void sja1000_printreg(uint32_t addr, uint32_t value) +{ + static uint32_t prevaddr; + static uint32_t preval; + static uint32_t count; + + /* 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 %" PRId32 " more times]\n", count - 3); + } + + /* Save the new address, value, and count */ + + prevaddr = addr; + preval = value; + count = 1; + } + + /* Show the register value read */ + + caninfo("%08" PRIx32 "->%08" PRIx32 "\n", addr, value); +} +#endif /* CONFIG_CANBUS_REGDEBUG */ + +/**************************************************************************** + * Name: sja1000_reset + * + * Description: + * Reset the SJA1000 device. Called early to initialize the hardware. + *This function is called, before litex_sja1000_setup() and on error + *conditions. + * + * Input Parameters: + * dev - An instance of the "upper half" CAN driver state structure. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void sja1000_reset(struct can_dev_s *dev) +{ + struct sja1000_dev_s *priv = (struct sja1000_dev_s *)dev->cd_priv; + struct sja1000_config_s *config = priv->config; + uint8_t port = config->port; + irqstate_t flags; + int ret; + + caninfo("SJA1000 Device %" PRIu8 "\n", port); + +#ifdef CONFIG_ARCH_HAVE_MULTICPU + flags = spin_lock_irqsave(&priv->lock); +#else + flags = enter_critical_section(); +#endif /* CONFIG_ARCH_HAVE_MULTICPU */ + + /* Disable the SJA1000 and stop ongoing transmissions */ + + uint32_t mode_value = SJA1000_RESET_MODE_M | SJA1000_LISTEN_ONLY_MODE_M; + sja1000_putreg(priv, + SJA1000_MODE_REG, mode_value); /* Enter Reset Mode */ + + sja1000_modifyreg32(priv, + SJA1000_CLOCK_DIVIDER_REG, 0, SJA1000_EXT_MODE_M); + + sja1000_putreg(priv, SJA1000_INT_ENA_REG, 0); /* Disable interrupts */ + sja1000_getreg(priv, SJA1000_STATUS_REG); /* Clear status bits */ + + sja1000_putreg(priv, + SJA1000_TX_ERR_CNT_REG, SJA1000_INIT_TEC); /* TEC */ + sja1000_putreg(priv, + SJA1000_RX_ERR_CNT_REG, SJA1000_INIT_REC); /* REC */ + sja1000_putreg(priv, + SJA1000_ERR_WARNING_LIMIT_REG, SJA1000_INIT_EWL); /* EWL */ + + sja1000_set_acc_filter( + priv, SJA1000_ACCEPTANCE_CODE, SJA1000_ACCEPTANCE_MASK, true); + + /* Set bit timing */ + + ret = sja1000_baud_rate(priv, config->bitrate, config->clk_freq, + config->sjw, config->samplep, 0); + + if (ret != OK) + { + canerr("ERROR: Failed to set bit timing: %d\n", ret); + } + + /* Restart the SJA1000 */ + + if (config->loopback) + { + /* Leave Reset Mode, enter Test Mode */ + + sja1000_putreg(priv, SJA1000_MODE_REG, SJA1000_SELF_TEST_MODE_M); + } + else + { + /* Leave Reset Mode */ + + sja1000_putreg(priv, SJA1000_MODE_REG, 0); + } + + /* Abort transmission, release RX buffer and clear overrun. + * Command register can only be modified when in Operation Mode. + */ + + sja1000_putreg(priv, SJA1000_CMD_REG, SJA1000_ABORT_TX_M + | SJA1000_RELEASE_BUF_M + | SJA1000_CLR_OVERRUN_M); + +#ifdef CONFIG_ARCH_HAVE_MULTICPU + spin_unlock_irqrestore(&priv->lock, flags); +#else + leave_critical_section(flags); +#endif /* CONFIG_ARCH_HAVE_MULTICPU */ +} + +/**************************************************************************** + * Name: sja1000_setup + * + * Description: + * Configure the SJA1000. This method is called the first time that the + *SJA1000 device is opened. This will occur when the port is first opened. + * This setup includes configuring and attaching SJA1000 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 sja1000_setup(struct can_dev_s *dev) +{ + struct sja1000_dev_s *priv = (struct sja1000_dev_s *)dev->cd_priv; + struct sja1000_config_s *config = priv->config; + uint8_t port = config->port; + irqstate_t flags; + int ret = OK; + + caninfo("SJA1000 (%" PRIu8 ")\n", port); + +#ifdef CONFIG_ARCH_HAVE_MULTICPU + flags = spin_lock_irqsave(&priv->lock); +#else + flags = enter_critical_section(); +#endif /* CONFIG_ARCH_HAVE_MULTICPU */ + + sja1000_putreg(priv, SJA1000_INT_ENA_REG, SJA1000_DEFAULT_INTERRUPTS); + + /* clear latched interrupts */ + + sja1000_getreg(priv, SJA1000_INT_RAW_REG); + + /* Attach the SJA1000 interrupts and handler. */ + + ret = config->attach( + config, (sja1000_handler_t)sja1000_interrupt, (FAR void *)dev); + if (ret < 0) + { + canerr("ERROR: Failed to attach to IRQ Handler!\n"); + return ret; + } + +#ifdef CONFIG_ARCH_HAVE_MULTICPU + spin_unlock_irqrestore(&priv->lock, flags); +#else + leave_critical_section(flags); +#endif /* CONFIG_ARCH_HAVE_MULTICPU */ + + return ret; +} + +/**************************************************************************** + * Name: sja1000_shutdown + * + * Description: + * Disable the SJA1000. This method is called when the SJA1000 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 sja1000_shutdown(struct can_dev_s *dev) +{ + int ret; + struct sja1000_dev_s *priv = (struct sja1000_dev_s *)dev->cd_priv; + struct sja1000_config_s *config = priv->config; + uint8_t port = config->port; + + cantrace("shutdown SJA1000 (%" PRIu8 ")\n", port); + + /* Detach the SJA1000 interrupts and handler. */ + + ret = config->detach(config); + if (ret < 0) + { + canerr("ERROR: Failed to detach from IRQ Handler!\n"); + } +} + +/**************************************************************************** + * Name: sja1000_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 sja1000_rxint(struct can_dev_s *dev, bool enable) +{ + struct sja1000_dev_s *priv = (struct sja1000_dev_s *)dev->cd_priv; + struct sja1000_config_s *config = priv->config; + uint8_t port = config->port; + uint32_t regval; + irqstate_t flags; + + cantrace("SJA1000 (%" PRIu8 ") enable: %d\n", port, enable); + + /* The INT_ENA register is also modified from the interrupt handler, + * so we have to protect this code section. + */ + +#ifdef CONFIG_ARCH_HAVE_MULTICPU + flags = spin_lock_irqsave(&priv->lock); +#else + flags = enter_critical_section(); +#endif /* CONFIG_ARCH_HAVE_MULTICPU */ + + regval = sja1000_getreg(priv, SJA1000_INT_ENA_REG); + if (enable) + { + regval |= SJA1000_RX_INT_ENA_M; + } + else + { + regval &= ~SJA1000_RX_INT_ENA_M; + } + + sja1000_putreg(priv, SJA1000_INT_ENA_REG, regval); +#ifdef CONFIG_ARCH_HAVE_MULTICPU + spin_unlock_irqrestore(&priv->lock, flags); +#else + leave_critical_section(flags); +#endif /* CONFIG_ARCH_HAVE_MULTICPU */ +} + +/**************************************************************************** + * Name: sja1000_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 sja1000_txint(struct can_dev_s *dev, bool enable) +{ + struct sja1000_dev_s *priv = (struct sja1000_dev_s *)dev->cd_priv; + struct sja1000_config_s *config = priv->config; + uint8_t port = config->port; + uint32_t regval; + irqstate_t flags; + + cantrace("SJA1000 (%" PRIu8 ") enable: %d\n", 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. + */ + +#ifdef CONFIG_ARCH_HAVE_MULTICPU + flags = spin_lock_irqsave(&priv->lock); +#else + flags = enter_critical_section(); +#endif /* CONFIG_ARCH_HAVE_MULTICPU */ + + /* Disable all TX interrupts */ + + regval = sja1000_getreg(priv, SJA1000_INT_ENA_REG); + regval &= ~(SJA1000_TX_INT_ENA_M); + sja1000_putreg(priv, SJA1000_INT_ENA_REG, regval); +#ifdef CONFIG_ARCH_HAVE_MULTICPU + spin_unlock_irqrestore(&priv->lock, flags); +#else + leave_critical_section(flags); +#endif /* CONFIG_ARCH_HAVE_MULTICPU */ + } + + cantrace("Exiting.\n"); +} + +/**************************************************************************** + * Name: sja1000_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 sja1000_ioctl(struct can_dev_s *dev, int cmd, unsigned long arg) +{ + struct sja1000_dev_s *priv = (struct sja1000_dev_s *)dev->cd_priv; + struct sja1000_config_s *config = priv->config; + int ret = -ENOTTY; + uint8_t port = config->port; + + cantrace("SJA1000 (%" PRIu8 ") cmd=%04x arg=%lu\n", 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: + { + struct canioc_bittiming_s *bt = (struct canioc_bittiming_s *)arg; + uint32_t timing0; + uint32_t timing1; + uint32_t brp; + + DEBUGASSERT(bt != NULL); + + timing0 = sja1000_getreg(priv, SJA1000_BUS_TIMING_0_REG); + timing1 = sja1000_getreg(priv, SJA1000_BUS_TIMING_1_REG); + + brp = ((timing0 & SJA1000_BAUD_PRESC_M) + 1) * 2; + bt->bt_sjw = ((timing0 & SJA1000_SYNC_JUMP_WIDTH_M) + >> SJA1000_SYNC_JUMP_WIDTH_S) + + 1; + + bt->bt_tseg1 + = ((timing1 & SJA1000_TIME_SEG1_M) >> SJA1000_TIME_SEG1_S) + + 1; + bt->bt_tseg2 + = ((timing1 & SJA1000_TIME_SEG2_M) >> SJA1000_TIME_SEG2_S) + + 1; + bt->bt_baud = config->clk_freq + / (brp * (bt->bt_tseg1 + bt->bt_tseg2 + 1)); + + cantrace("Retrieved baud rate. TS1: %" PRId8 " TS2: %" PRId8 + " BRP: %" PRId32 "\n", + bt->bt_tseg1, bt->bt_tseg2, brp); + cantrace("timing0: 0x%" PRIx32 ", timing1: 0x%" PRIx32 " Baud: " + "%" PRId32 + "\n", + timing0, timing1, bt->bt_baud); + + ret = OK; + } + break; + + /* Unsupported/unrecognized command */ + + default: + canerr("ERROR: Unrecognized command: %04x\n", cmd); + break; + } + + return ret; +} + +static int sja1000_remoterequest(struct can_dev_s *dev, uint16_t id) +{ + canwarn("Remote request not implemented\n"); + return -ENOSYS; +} + +/**************************************************************************** + * Name: sja1000_send + * + * Description: + * Send one SJA1000 message. + * + * One SJA1000-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 SJA1000 identifier + * Byte 1: Bits 5-7: Bits 0-2 of the 11-bit SJA1000 identifier + * Bit 4: Remote Transmission Request (RTR) + * Bits 0-3: Data Length Code (DLC) + * Bytes 2-10: SJA1000 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 sja1000_send(struct can_dev_s *dev, struct can_msg_s *msg) +{ + struct sja1000_dev_s *priv = (struct sja1000_dev_s *)dev->cd_priv; + struct sja1000_config_s *config = priv->config; + uint32_t regval; + uint32_t i; + uint32_t len; + uint32_t id; + uint32_t frame_info; + irqstate_t flags; + uint8_t port = config->port; + int ret = OK; + + cantrace("SJA1000 (%" PRIu8 ") ID: %" PRIu32 " DLC: %" PRIu8 "\n", 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); + } + +#ifdef CONFIG_ARCH_HAVE_MULTICPU + flags = spin_lock_irqsave(&priv->lock); +#else + flags = enter_critical_section(); +#endif /* CONFIG_ARCH_HAVE_MULTICPU */ + + /* 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 = sja1000_getreg(priv, SJA1000_INT_ENA_REG); + regval |= SJA1000_TX_INT_ENA_M; + sja1000_putreg(priv, SJA1000_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); + sja1000_putreg(priv, SJA1000_DATA_0_REG, frame_info); + + id <<= 3; + sja1000_putreg(priv, SJA1000_DATA_4_REG, id & 0xff); + id >>= 8; + sja1000_putreg(priv, SJA1000_DATA_3_REG, id & 0xff); + id >>= 8; + sja1000_putreg(priv, SJA1000_DATA_2_REG, id & 0xff); + id >>= 8; + sja1000_putreg(priv, SJA1000_DATA_1_REG, id & 0xff); + for (i = 0; i < len; i++) + { + sja1000_putreg(priv, + (SJA1000_DATA_5_REG + i), 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); + sja1000_putreg(priv, SJA1000_DATA_0_REG, frame_info); + id <<= 5; + sja1000_putreg(priv, SJA1000_DATA_1_REG, (id >> 8) & 0xff); + sja1000_putreg(priv, SJA1000_DATA_2_REG, id & 0xff); + for (i = 0; i < len; i++) + { + sja1000_putreg(priv, + (SJA1000_DATA_3_REG + i), msg->cm_data[i]); + } + } + + /* Send the message */ + + if (config->loopback) + { + sja1000_putreg(priv, SJA1000_CMD_REG, + SJA1000_SELF_RX_REQ_M | SJA1000_ABORT_TX_M); + } + else + { + sja1000_putreg(priv, SJA1000_CMD_REG, SJA1000_TX_REQ_M); + } + +#ifdef CONFIG_ARCH_HAVE_MULTICPU + spin_unlock_irqrestore(&priv->lock, flags); +#else + leave_critical_section(flags); +#endif /* CONFIG_ARCH_HAVE_MULTICPU */ + + return ret; +} + +/**************************************************************************** + * Name: sja1000_txready + * + * Description: + * Return true if the SJA1000 hardware can accept another TX message. + * + * Input Parameters: + * dev - An instance of the "upper half" CAN driver state structure. + * + * Returned Value: + * True if the SJA1000 hardware is ready to accept another TX message. + * + ****************************************************************************/ + +static bool sja1000_txready(struct can_dev_s *dev) +{ + struct sja1000_dev_s *priv = dev->cd_priv; + struct sja1000_config_s *config = priv->config; + uint8_t port = config->port; + uint32_t regval = sja1000_getreg(priv, SJA1000_STATUS_REG); + + caninfo("SJA1000 (%" PRIu8 ") txready: %d\n", port, + ((regval & SJA1000_TX_BUF_ST_M) != 0)); + return ((regval & SJA1000_TX_BUF_ST_M) != 0); +} + +/**************************************************************************** + * Name: sja1000_txempty + * + * Description: + * Return true if all message have been sent. If for example, the SJA1000 + * 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 SJA1000 hardware. + * + ****************************************************************************/ + +static bool sja1000_txempty(struct can_dev_s *dev) +{ + struct sja1000_dev_s *priv = dev->cd_priv; + struct sja1000_config_s *config = priv->config; + uint8_t port = config->port; + uint32_t regval = sja1000_getreg(priv, SJA1000_STATUS_REG); + + caninfo("SJA1000 (%" PRIu8 ") txempty: %d\n", port, + ((regval & SJA1000_TX_BUF_ST_M) != 0)); + return ((regval & SJA1000_TX_BUF_ST_M) != 0); +} + +/**************************************************************************** + * Name: sja1000_interrupt + * + * Description: + * SJA1000 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 sja1000_interrupt(FAR struct sja1000_config_s *config, void *arg) +{ +#ifdef CONFIG_CAN_SJA1000 + struct can_dev_s *dev = (struct can_dev_s *)arg; + struct sja1000_dev_s *priv = dev->cd_priv; + 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 = sja1000_getreg(priv, SJA1000_INT_RAW_REG); + + cantrace("Entered. Regval = 0x%" PRIx32 "\n", regval); + + /* Check for a receive interrupt */ + + if ((regval & SJA1000_RX_INT_ST_M) != 0) + { + memset(&hdr, 0, sizeof(hdr)); + memset(data, 0, sizeof(data)); + + frame_info = sja1000_getreg(priv, SJA1000_DATA_0_REG); + + /* Construct the SJA1000 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 = (sja1000_getreg(priv, SJA1000_DATA_1_REG) << 21) + + (sja1000_getreg(priv, SJA1000_DATA_2_REG) << 13) + + (sja1000_getreg(priv, SJA1000_DATA_3_REG) << 5) + + (sja1000_getreg(priv, SJA1000_DATA_4_REG) >> 3); + datastart = SJA1000_DATA_5_REG; + } + else +#endif /* CONFIG_CAN_EXTID */ + { + /* The provided ID should be 11 bits */ + + hdr.ch_id = (sja1000_getreg(priv, SJA1000_DATA_1_REG) << 3) + + (sja1000_getreg(priv, SJA1000_DATA_2_REG) >> 5); + datastart = SJA1000_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] = sja1000_getreg(priv, (datastart + i)); + } + + /* Release the receive buffer */ + + sja1000_putreg(priv, SJA1000_CMD_REG, SJA1000_RELEASE_BUF_M); + +#ifdef CONFIG_CAN_ERRORS + hdr.ch_error = 0; /* Error reporting not supported */ +#endif /* CONFIG_CAN_ERRORS */ + can_receive(dev, &hdr, data); + } + + /* Check for TX buffer complete */ + + if ((regval & SJA1000_TX_INT_ST_M) != 0) + { + /* Disable all further TX buffer interrupts */ + + regval = sja1000_getreg(priv, SJA1000_INT_ENA_REG); + regval &= ~SJA1000_TX_INT_ENA_M; + sja1000_putreg(priv, SJA1000_INT_ENA_REG, regval); + + /* Indicate that the TX is done and a new TX buffer is available */ + + can_txdone(dev); + } + +#endif /* CONFIG_CAN_SJA1000 */ + return OK; +} + +/**************************************************************************** + * Name: sja1000_set_acc_filter + * + * Description: + * Call to set acceptance filter. + * Must be called in reset mode. + * + * Input Parameters: + * priv - Private SJA1000 context + * code - Acceptance Code. + * mask - Acceptance Mask. + * single_filter - Whether to enable single filter mode. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void sja1000_set_acc_filter(struct sja1000_dev_s *priv, + 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 = sja1000_getreg(priv, SJA1000_MODE_REG); + if (single_filter) + { + regval |= SJA1000_RX_FILTER_MODE_M; + } + else + { + regval &= ~(SJA1000_RX_FILTER_MODE_M); + } + + sja1000_putreg(priv, SJA1000_MODE_REG, regval); + + for (int i = 0; i < 4; i++) + { + sja1000_putreg(priv, (SJA1000_DATA_0_REG + i), + ((code_swapped >> (i * 8)) & 0xff)); + sja1000_putreg(priv, (SJA1000_DATA_4_REG + i), + ((mask_swapped >> (i * 8)) & 0xff)); + } +} + +/**************************************************************************** + * Name: sja1000_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 sja1000_baud_rate(struct sja1000_dev_s *priv, int rate, + int clock, int sjw, int sampl_pt, int flags) +{ + struct sja1000_config_s *config = priv->config; + const struct can_bittiming_const_s *timing = config->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("Setting baud rate. TS1: %d TS2: %d BRP: %d\n", tseg1, tseg2, + best_brp); + + /* Configure bit timing */ + + timing0 = ((best_brp - 1) / 2) & SJA1000_BAUD_PRESC_M; + timing0 |= ((sjw - 1) << SJA1000_SYNC_JUMP_WIDTH_S) + & SJA1000_SYNC_JUMP_WIDTH_M; + timing1 = (tseg1 - 1) & SJA1000_TIME_SEG1_M; + timing1 |= ((tseg2 - 1) << SJA1000_TIME_SEG2_S) & SJA1000_TIME_SEG2_M; + + if (config->triple_sample) + { + /* The bus is sampled 3 times (recommended for low to medium speed + * buses to spikes on the bus-line). + */ + + timing1 |= (config->triple_sample << SJA1000_TIME_SAMP_S) + & SJA1000_TIME_SAMP_M; + } + + cantrace("Writing to BTR0, BTR1: timing0: 0x%" PRIx32 " timing1: " + "0x%" PRIx32 "\n", + timing0, timing1); + + sja1000_putreg(priv, SJA1000_BUS_TIMING_1_REG, timing1); + sja1000_putreg(priv, SJA1000_BUS_TIMING_0_REG, timing0); + +#ifdef CONFIG_CANBUS_REGDEBUG + timing1 = sja1000_getreg(priv, SJA1000_BUS_TIMING_1_REG); + timing0 = sja1000_getreg(priv, SJA1000_BUS_TIMING_0_REG); + caninfo("Read-verify: timing0: 0x%" PRIx32 " timing1: 0x%" PRIx32 "\n", + timing0, timing1); +#endif /* CONFIG_CANBUS_REGDEBUG */ + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sja1000_instantiate + * + * Description: + * Initialize the selected SJA1000 CAN Bus Controller + * + * Input Parameters: + * priv - An instance of the "lower half" CAN driver state structure. + * + * Returned Value: + * Valid CAN device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +FAR struct can_dev_s *sja1000_instantiate(FAR struct sja1000_dev_s *priv) +{ + struct sja1000_config_s *config = priv->config; + FAR struct can_dev_s *dev; + irqstate_t flags; + + DEBUGASSERT(dev); + DEBUGASSERT(priv); + DEBUGASSERT(config); + + cantrace("Starting sja1000_instantiate()!\n"); + + /* Allocate a CAN Device structure */ + + dev = kmm_zalloc(sizeof(struct can_dev_s)); + if (dev == NULL) + { + canerr("ERROR: Failed to allocate instance of can_dev_s!\n"); + return NULL; + } + +#ifdef CONFIG_ARCH_HAVE_MULTICPU + flags = spin_lock_irqsave(&priv->lock); +#else + flags = enter_critical_section(); +#endif /* CONFIG_ARCH_HAVE_MULTICPU */ + +#ifdef CONFIG_ARCH_HAVE_MULTICPU + priv->lock = SP_UNLOCKED; +#endif /* CONFIG_ARCH_HAVE_MULTICPU */ + + dev->cd_ops = &g_sja1000ops; + dev->cd_priv = (FAR void *)priv; + +#ifdef CONFIG_ARCH_HAVE_MULTICPU + spin_unlock_irqrestore(&priv->lock, flags); +#else + leave_critical_section(flags); +#endif /* CONFIG_ARCH_HAVE_MULTICPU */ + + /* Reset chip */ + + sja1000_reset(dev); + + return dev; +} + +#endif /* CONFIG_CAN_SJA1000 */ diff --git a/drivers/can/sja1000.h b/drivers/can/sja1000.h new file mode 100644 index 00000000000..ee156b88408 --- /dev/null +++ b/drivers/can/sja1000.h @@ -0,0 +1,911 @@ +/**************************************************************************** + * drivers/can/sja1000.h + * + * SJA1000 CAN driver based on esp32c3_twai.h + * + * License header retained from original source. + * + * 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 __DRIVERS_CAN_SJA1000_H +#define __DRIVERS_CAN_SJA1000_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Default interrupts - Exclude data overrun (bit[3]) and brp_div (bit[4]) + */ + +#define SJA1000_DEFAULT_INTERRUPTS 0xe7 + +/* Number of standard/extended filters */ + +#define SJA1000_NFILTERS 1 + +/* SJA1000_MODE_REG register + * Mode Register + */ + +#define SJA1000_MODE_REG (0x00) + +/* SJA1000_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 SJA1000_RX_FILTER_MODE (BIT(3)) +#define SJA1000_RX_FILTER_MODE_M \ + (SJA1000_RX_FILTER_MODE_V << SJA1000_RX_FILTER_MODE_S) +#define SJA1000_RX_FILTER_MODE_V 0x00000001 +#define SJA1000_RX_FILTER_MODE_S 3 + +/* SJA1000_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 SJA1000_SELF_TEST_MODE (BIT(2)) +#define SJA1000_SELF_TEST_MODE_M \ + (SJA1000_SELF_TEST_MODE_V << SJA1000_SELF_TEST_MODE_S) +#define SJA1000_SELF_TEST_MODE_V 0x00000001 +#define SJA1000_SELF_TEST_MODE_S 2 + +/* SJA1000_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 SJA1000_LISTEN_ONLY_MODE (BIT(1)) +#define SJA1000_LISTEN_ONLY_MODE_M \ + (SJA1000_LISTEN_ONLY_MODE_V << SJA1000_LISTEN_ONLY_MODE_S) +#define SJA1000_LISTEN_ONLY_MODE_V 0x00000001 +#define SJA1000_LISTEN_ONLY_MODE_S 1 + +/* SJA1000_RESET_MODE : R/W; bitpos: [0]; default: 1; + * This bit is used to configure the operating mode of the SJA1000 + * Controller. 1: Reset mode; 0: Operating mode. + */ + +#define SJA1000_RESET_MODE (BIT(0)) +#define SJA1000_RESET_MODE_M (SJA1000_RESET_MODE_V << SJA1000_RESET_MODE_S) +#define SJA1000_RESET_MODE_V 0x00000001 +#define SJA1000_RESET_MODE_S 0 + +/* SJA1000_CMD_REG register + * Command Register + */ + +#define SJA1000_CMD_REG (0x01) + +/* SJA1000_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 SJA1000_SELF_RX_REQ (BIT(4)) +#define SJA1000_SELF_RX_REQ_M \ + (SJA1000_SELF_RX_REQ_V << SJA1000_SELF_RX_REQ_S) +#define SJA1000_SELF_RX_REQ_V 0x00000001 +#define SJA1000_SELF_RX_REQ_S 4 + +/* SJA1000_CLR_OVERRUN : WO; bitpos: [3]; default: 0; + * Set the bit to 1 to clear the data overrun status bit. + */ + +#define SJA1000_CLR_OVERRUN (BIT(3)) +#define SJA1000_CLR_OVERRUN_M \ + (SJA1000_CLR_OVERRUN_V << SJA1000_CLR_OVERRUN_S) +#define SJA1000_CLR_OVERRUN_V 0x00000001 +#define SJA1000_CLR_OVERRUN_S 3 + +/* SJA1000_RELEASE_BUF : WO; bitpos: [2]; default: 0; + * Set the bit to 1 to release the RX buffer. + */ + +#define SJA1000_RELEASE_BUF (BIT(2)) +#define SJA1000_RELEASE_BUF_M \ + (SJA1000_RELEASE_BUF_V << SJA1000_RELEASE_BUF_S) +#define SJA1000_RELEASE_BUF_V 0x00000001 +#define SJA1000_RELEASE_BUF_S 2 + +/* SJA1000_ABORT_TX : WO; bitpos: [1]; default: 0; + * Set the bit to 1 to cancel a pending transmission request. + */ + +#define SJA1000_ABORT_TX (BIT(1)) +#define SJA1000_ABORT_TX_M (SJA1000_ABORT_TX_V << SJA1000_ABORT_TX_S) +#define SJA1000_ABORT_TX_V 0x00000001 +#define SJA1000_ABORT_TX_S 1 + +/* SJA1000_TX_REQ : WO; bitpos: [0]; default: 0; + * Set the bit to 1 to allow the driving nodes start transmission. + */ + +#define SJA1000_TX_REQ (BIT(0)) +#define SJA1000_TX_REQ_M (SJA1000_TX_REQ_V << SJA1000_TX_REQ_S) +#define SJA1000_TX_REQ_V 0x00000001 +#define SJA1000_TX_REQ_S 0 + +/* SJA1000_STATUS_REG register + * Status register + */ + +#define SJA1000_STATUS_REG (0x02) + +/* SJA1000_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 SJA1000_MISS_ST (BIT(8)) +#define SJA1000_MISS_ST_M (SJA1000_MISS_ST_V << SJA1000_MISS_ST_S) +#define SJA1000_MISS_ST_V 0x00000001 +#define SJA1000_MISS_ST_S 8 + +/* SJA1000_BUS_OFF_ST : RO; bitpos: [7]; default: 0; + * 1: In bus-off status, the SJA1000 Controller is no longer involved in bus + * activities. + */ + +#define SJA1000_BUS_OFF_ST (BIT(7)) +#define SJA1000_BUS_OFF_ST_M (SJA1000_BUS_OFF_ST_V << SJA1000_BUS_OFF_ST_S) +#define SJA1000_BUS_OFF_ST_V 0x00000001 +#define SJA1000_BUS_OFF_ST_S 7 + +/* SJA1000_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 SJA1000_ERR_WARNING_LIMIT_REG. + */ + +#define SJA1000_ERR_ST (BIT(6)) +#define SJA1000_ERR_ST_M (SJA1000_ERR_ST_V << SJA1000_ERR_ST_S) +#define SJA1000_ERR_ST_V 0x00000001 +#define SJA1000_ERR_ST_S 6 + +/* SJA1000_TX_ST : RO; bitpos: [5]; default: 0; + * 1: The SJA1000 Controller is transmitting a message to the bus. + */ + +#define SJA1000_TX_ST (BIT(5)) +#define SJA1000_TX_ST_M (SJA1000_TX_ST_V << SJA1000_TX_ST_S) +#define SJA1000_TX_ST_V 0x00000001 +#define SJA1000_TX_ST_S 5 + +/* SJA1000_RX_ST : RO; bitpos: [4]; default: 0; + * 1: The SJA1000 Controller is receiving a message from the bus. + */ + +#define SJA1000_RX_ST (BIT(4)) +#define SJA1000_RX_ST_M (SJA1000_RX_ST_V << SJA1000_RX_ST_S) +#define SJA1000_RX_ST_V 0x00000001 +#define SJA1000_RX_ST_S 4 + +/* SJA1000_TX_COMPLETE : RO; bitpos: [3]; default: 0; + * 1: The SJA1000 controller has successfully received a packet from the + * bus. + */ + +#define SJA1000_TX_COMPLETE (BIT(3)) +#define SJA1000_TX_COMPLETE_M \ + (SJA1000_TX_COMPLETE_V << SJA1000_TX_COMPLETE_S) +#define SJA1000_TX_COMPLETE_V 0x00000001 +#define SJA1000_TX_COMPLETE_S 3 + +/* SJA1000_TX_BUF_ST : RO; bitpos: [2]; default: 0; + * 1: The TX buffer is empty, the CPU may write a message into it. + */ + +#define SJA1000_TX_BUF_ST (BIT(2)) +#define SJA1000_TX_BUF_ST_M (SJA1000_TX_BUF_ST_V << SJA1000_TX_BUF_ST_S) +#define SJA1000_TX_BUF_ST_V 0x00000001 +#define SJA1000_TX_BUF_ST_S 2 + +/* SJA1000_OVERRUN_ST : RO; bitpos: [1]; default: 0; + * 1: The RX FIFO is full and data overrun has occurred. + */ + +#define SJA1000_OVERRUN_ST (BIT(1)) +#define SJA1000_OVERRUN_ST_M (SJA1000_OVERRUN_ST_V << SJA1000_OVERRUN_ST_S) +#define SJA1000_OVERRUN_ST_V 0x00000001 +#define SJA1000_OVERRUN_ST_S 1 + +/* SJA1000_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 SJA1000_RX_BUF_ST (BIT(0)) +#define SJA1000_RX_BUF_ST_M (SJA1000_RX_BUF_ST_V << SJA1000_RX_BUF_ST_S) +#define SJA1000_RX_BUF_ST_V 0x00000001 +#define SJA1000_RX_BUF_ST_S 0 + +/* SJA1000_INT_RAW_REG register + * Interrupt Register + */ + +#define SJA1000_INT_RAW_REG (0x03) + +/* SJA1000_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 SJA1000_BUS_ERR_INT_ST (BIT(7)) +#define SJA1000_BUS_ERR_INT_ST_M \ + (SJA1000_BUS_ERR_INT_ST_V << SJA1000_BUS_ERR_INT_ST_S) +#define SJA1000_BUS_ERR_INT_ST_V 0x00000001 +#define SJA1000_BUS_ERR_INT_ST_S 7 + +/* SJA1000_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 SJA1000_ARB_LOST_INT_ST (BIT(6)) +#define SJA1000_ARB_LOST_INT_ST_M \ + (SJA1000_ARB_LOST_INT_ST_V << SJA1000_ARB_LOST_INT_ST_S) +#define SJA1000_ARB_LOST_INT_ST_V 0x00000001 +#define SJA1000_ARB_LOST_INT_ST_S 6 + +/* SJA1000_ERR_PASSIVE_INT_ST : RO; bitpos: [5]; default: 0; + * Error passive interrupt. If this bit is set to 1, it indicates the + * SJA1000 Controller is switched between error active status and error + * passive status due to the change of error counters. + */ + +#define SJA1000_ERR_PASSIVE_INT_ST (BIT(5)) +#define SJA1000_ERR_PASSIVE_INT_ST_M \ + (SJA1000_ERR_PASSIVE_INT_ST_V << SJA1000_ERR_PASSIVE_INT_ST_S) +#define SJA1000_ERR_PASSIVE_INT_ST_V 0x00000001 +#define SJA1000_ERR_PASSIVE_INT_ST_S 5 + +/* SJA1000_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 SJA1000_OVERRUN_INT_ST (BIT(3)) +#define SJA1000_OVERRUN_INT_ST_M \ + (SJA1000_OVERRUN_INT_ST_V << SJA1000_OVERRUN_INT_ST_S) +#define SJA1000_OVERRUN_INT_ST_V 0x00000001 +#define SJA1000_OVERRUN_INT_ST_S 3 + +/* SJA1000_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 SJA1000_ERR_WARN_INT_ST (BIT(2)) +#define SJA1000_ERR_WARN_INT_ST_M \ + (SJA1000_ERR_WARN_INT_ST_V << SJA1000_ERR_WARN_INT_ST_S) +#define SJA1000_ERR_WARN_INT_ST_V 0x00000001 +#define SJA1000_ERR_WARN_INT_ST_S 2 + +/* SJA1000_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 SJA1000_TX_INT_ST (BIT(1)) +#define SJA1000_TX_INT_ST_M (SJA1000_TX_INT_ST_V << SJA1000_TX_INT_ST_S) +#define SJA1000_TX_INT_ST_V 0x00000001 +#define SJA1000_TX_INT_ST_S 1 + +/* SJA1000_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 SJA1000_RX_INT_ST (BIT(0)) +#define SJA1000_RX_INT_ST_M (SJA1000_RX_INT_ST_V << SJA1000_RX_INT_ST_S) +#define SJA1000_RX_INT_ST_V 0x00000001 +#define SJA1000_RX_INT_ST_S 0 + +/* SJA1000_INT_ENA_REG register + * Interrupt Enable Register + */ + +#define SJA1000_INT_ENA_REG (0x04) + +/* SJA1000_BUS_ERR_INT_ENA : R/W; bitpos: [7]; default: 0; + * Set this bit to 1 to enable error interrupt. + */ + +#define SJA1000_BUS_ERR_INT_ENA (BIT(7)) +#define SJA1000_BUS_ERR_INT_ENA_M \ + (SJA1000_BUS_ERR_INT_ENA_V << SJA1000_BUS_ERR_INT_ENA_S) +#define SJA1000_BUS_ERR_INT_ENA_V 0x00000001 +#define SJA1000_BUS_ERR_INT_ENA_S 7 + +/* SJA1000_ARB_LOST_INT_ENA : R/W; bitpos: [6]; default: 0; + * Set this bit to 1 to enable arbitration lost interrupt. + */ + +#define SJA1000_ARB_LOST_INT_ENA (BIT(6)) +#define SJA1000_ARB_LOST_INT_ENA_M \ + (SJA1000_ARB_LOST_INT_ENA_V << SJA1000_ARB_LOST_INT_ENA_S) +#define SJA1000_ARB_LOST_INT_ENA_V 0x00000001 +#define SJA1000_ARB_LOST_INT_ENA_S 6 + +/* SJA1000_ERR_PASSIVE_INT_ENA : R/W; bitpos: [5]; default: 0; + * Set this bit to 1 to enable error passive interrupt. + */ + +#define SJA1000_ERR_PASSIVE_INT_ENA (BIT(5)) +#define SJA1000_ERR_PASSIVE_INT_ENA_M \ + (SJA1000_ERR_PASSIVE_INT_ENA_V << SJA1000_ERR_PASSIVE_INT_ENA_S) +#define SJA1000_ERR_PASSIVE_INT_ENA_V 0x00000001 +#define SJA1000_ERR_PASSIVE_INT_ENA_S 5 + +/* SJA1000_OVERRUN_INT_ENA : R/W; bitpos: [3]; default: 0; + * Set this bit to 1 to enable data overrun interrupt. + */ + +#define SJA1000_OVERRUN_INT_ENA (BIT(3)) +#define SJA1000_OVERRUN_INT_ENA_M \ + (SJA1000_OVERRUN_INT_ENA_V << SJA1000_OVERRUN_INT_ENA_S) +#define SJA1000_OVERRUN_INT_ENA_V 0x00000001 +#define SJA1000_OVERRUN_INT_ENA_S 3 + +/* SJA1000_ERR_WARN_INT_ENA : R/W; bitpos: [2]; default: 0; + * Set this bit to 1 to enable error warning interrupt. + */ + +#define SJA1000_ERR_WARN_INT_ENA (BIT(2)) +#define SJA1000_ERR_WARN_INT_ENA_M \ + (SJA1000_ERR_WARN_INT_ENA_V << SJA1000_ERR_WARN_INT_ENA_S) +#define SJA1000_ERR_WARN_INT_ENA_V 0x00000001 +#define SJA1000_ERR_WARN_INT_ENA_S 2 + +/* SJA1000_TX_INT_ENA : R/W; bitpos: [1]; default: 0; + * Set this bit to 1 to enable transmit interrupt. + */ + +#define SJA1000_TX_INT_ENA (BIT(1)) +#define SJA1000_TX_INT_ENA_M (SJA1000_TX_INT_ENA_V << SJA1000_TX_INT_ENA_S) +#define SJA1000_TX_INT_ENA_V 0x00000001 +#define SJA1000_TX_INT_ENA_S 1 + +/* SJA1000_RX_INT_ENA : R/W; bitpos: [0]; default: 0; + * Set this bit to 1 to enable receive interrupt. + */ + +#define SJA1000_RX_INT_ENA (BIT(0)) +#define SJA1000_RX_INT_ENA_M (SJA1000_RX_INT_ENA_V << SJA1000_RX_INT_ENA_S) +#define SJA1000_RX_INT_ENA_V 0x00000001 +#define SJA1000_RX_INT_ENA_S 0 + +/* SJA1000_BUS_TIMING_0_REG register + * Bus Timing Register 0 + */ + +#define SJA1000_BUS_TIMING_0_REG (0x06) + +/* SJA1000_SYNC_JUMP_WIDTH : RO | R/W; bitpos: [7:6]; default: 0; + * Synchronization Jump Width (SJW), 1 \verb+~+ 14 Tq wide. + */ + +#define SJA1000_SYNC_JUMP_WIDTH 0x00000003 +#define SJA1000_SYNC_JUMP_WIDTH_M \ + (SJA1000_SYNC_JUMP_WIDTH_V << SJA1000_SYNC_JUMP_WIDTH_S) +#define SJA1000_SYNC_JUMP_WIDTH_V 0x00000003 +#define SJA1000_SYNC_JUMP_WIDTH_S 6 + +/* SJA1000_BAUD_PRESC : RO | R/W; bitpos: [5:0]; default: 0; + * Baud Rate Prescaler, determines the frequency dividing ratio. + */ + +#define SJA1000_BAUD_PRESC 0x0000003F +#define SJA1000_BAUD_PRESC_M (SJA1000_BAUD_PRESC_V << SJA1000_BAUD_PRESC_S) +#define SJA1000_BAUD_PRESC_V 0x0000003F +#define SJA1000_BAUD_PRESC_S 0 + +/* SJA1000_BUS_TIMING_1_REG register + * Bus Timing Register 1 + */ + +#define SJA1000_BUS_TIMING_1_REG (0x07) + +/* SJA1000_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 SJA1000_TIME_SAMP (BIT(7)) +#define SJA1000_TIME_SAMP_M (SJA1000_TIME_SAMP_V << SJA1000_TIME_SAMP_S) +#define SJA1000_TIME_SAMP_V 0x00000001 +#define SJA1000_TIME_SAMP_S 7 + +/* SJA1000_TIME_SEG2 : RO | R/W; bitpos: [6:4]; default: 0; + * The width of PBS2. + */ + +#define SJA1000_TIME_SEG2 0x00000007 +#define SJA1000_TIME_SEG2_M (SJA1000_TIME_SEG2_V << SJA1000_TIME_SEG2_S) +#define SJA1000_TIME_SEG2_V 0x00000007 +#define SJA1000_TIME_SEG2_S 4 + +/* SJA1000_TIME_SEG1 : RO | R/W; bitpos: [3:0]; default: 0; + * The width of PBS1. + */ + +#define SJA1000_TIME_SEG1 0x0000000F +#define SJA1000_TIME_SEG1_M (SJA1000_TIME_SEG1_V << SJA1000_TIME_SEG1_S) +#define SJA1000_TIME_SEG1_V 0x0000000F +#define SJA1000_TIME_SEG1_S 0 + +/* SJA1000_ARB_LOST_CAP_REG register + * Arbitration Lost Capture Register + */ + +#define SJA1000_ARB_LOST_CAP_REG (0x0B) + +/* SJA1000_ARB_LOST_CAP : RO; bitpos: [4:0]; default: 0; + * This register contains information about the bit position of lost + * arbitration. + */ + +#define SJA1000_ARB_LOST_CAP 0x0000001F +#define SJA1000_ARB_LOST_CAP_M \ + (SJA1000_ARB_LOST_CAP_V << SJA1000_ARB_LOST_CAP_S) +#define SJA1000_ARB_LOST_CAP_V 0x0000001F +#define SJA1000_ARB_LOST_CAP_S 0 + +/* SJA1000_ERR_CODE_CAP_REG register + * Error Code Capture Register + */ + +#define SJA1000_ERR_CODE_CAP_REG (0x0C) + +/* SJA1000_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 SJA1000_ECC_TYPE 0x00000003 +#define SJA1000_ECC_TYPE_M (SJA1000_ECC_TYPE_V << SJA1000_ECC_TYPE_S) +#define SJA1000_ECC_TYPE_V 0x00000003 +#define SJA1000_ECC_TYPE_S 6 + +/* SJA1000_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 SJA1000_ECC_DIRECTION (BIT(5)) +#define SJA1000_ECC_DIRECTION_M \ + (SJA1000_ECC_DIRECTION_V << SJA1000_ECC_DIRECTION_S) +#define SJA1000_ECC_DIRECTION_V 0x00000001 +#define SJA1000_ECC_DIRECTION_S 5 + +/* SJA1000_ECC_SEGMENT : RO; bitpos: [4:0]; default: 0; + * This register contains information about the location of errors, see + * Table 181 for details. + */ + +#define SJA1000_ECC_SEGMENT 0x0000001F +#define SJA1000_ECC_SEGMENT_M \ + (SJA1000_ECC_SEGMENT_V << SJA1000_ECC_SEGMENT_S) +#define SJA1000_ECC_SEGMENT_V 0x0000001F +#define SJA1000_ECC_SEGMENT_S 0 + +/* SJA1000_ERR_WARNING_LIMIT_REG register + * Error Warning Limit Register + */ + +#define SJA1000_ERR_WARNING_LIMIT_REG (0x0D) + +/* SJA1000_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 SJA1000_ERR_WARNING_LIMIT 0x000000FF +#define SJA1000_ERR_WARNING_LIMIT_M \ + (SJA1000_ERR_WARNING_LIMIT_V << SJA1000_ERR_WARNING_LIMIT_S) +#define SJA1000_ERR_WARNING_LIMIT_V 0x000000FF +#define SJA1000_ERR_WARNING_LIMIT_S 0 + +/* SJA1000_RX_ERR_CNT_REG register + * Receive Error Counter Register + */ + +#define SJA1000_RX_ERR_CNT_REG (0x0E) + +/* SJA1000_RX_ERR_CNT : RO | R/W; bitpos: [7:0]; default: 0; + * The RX error counter register, reflects value changes under reception + * status. + */ + +#define SJA1000_RX_ERR_CNT 0x000000FF +#define SJA1000_RX_ERR_CNT_M (SJA1000_RX_ERR_CNT_V << SJA1000_RX_ERR_CNT_S) +#define SJA1000_RX_ERR_CNT_V 0x000000FF +#define SJA1000_RX_ERR_CNT_S 0 + +/* SJA1000_TX_ERR_CNT_REG register + * Transmit Error Counter Register + */ + +#define SJA1000_TX_ERR_CNT_REG (0x0F) + +/* SJA1000_TX_ERR_CNT : RO | R/W; bitpos: [7:0]; default: 0; + * The TX error counter register, reflects value changes under transmission + * status. + */ + +#define SJA1000_TX_ERR_CNT 0x000000FF +#define SJA1000_TX_ERR_CNT_M (SJA1000_TX_ERR_CNT_V << SJA1000_TX_ERR_CNT_S) +#define SJA1000_TX_ERR_CNT_V 0x000000FF +#define SJA1000_TX_ERR_CNT_S 0 + +/* SJA1000_DATA_0_REG register + * Data register 0 + */ + +#define SJA1000_DATA_0_REG (0x10) + +/* SJA1000_TX_BYTE_0 : WO; bitpos: [7:0]; default: 0; + * Stored the 0th byte information of the data to be transmitted under + * operating mode. + */ + +#define SJA1000_TX_BYTE_0 0x000000FF +#define SJA1000_TX_BYTE_0_M (SJA1000_TX_BYTE_0_V << SJA1000_TX_BYTE_0_S) +#define SJA1000_TX_BYTE_0_V 0x000000FF +#define SJA1000_TX_BYTE_0_S 0 + +/* SJA1000_ACCEPTANCE_CODE_0 : WO; bitpos: [7:0]; default: 0; + * Stored the 0th byte of the filter code in reset mode. + */ + +#define SJA1000_ACCEPTANCE_CODE_0 0x000000FF +#define SJA1000_ACCEPTANCE_CODE_0_M \ + (SJA1000_ACCEPTANCE_CODE_0_V << SJA1000_ACCEPTANCE_CODE_0_S) +#define SJA1000_ACCEPTANCE_CODE_0_V 0x000000FF +#define SJA1000_ACCEPTANCE_CODE_0_S 0 + +/* SJA1000_DATA_1_REG register + * Data register 1 + */ + +#define SJA1000_DATA_1_REG (0x11) + +/* SJA1000_TX_BYTE_1 : WO; bitpos: [7:0]; default: 0; + * Stored the 1st byte information of the data to be transmitted under + * operating mode. + */ + +#define SJA1000_TX_BYTE_1 0x000000FF +#define SJA1000_TX_BYTE_1_M (SJA1000_TX_BYTE_1_V << SJA1000_TX_BYTE_1_S) +#define SJA1000_TX_BYTE_1_V 0x000000FF +#define SJA1000_TX_BYTE_1_S 0 + +/* SJA1000_ACCEPTANCE_CODE_1 : WO; bitpos: [7:0]; default: 0; + * Stored the 1st byte of the filter code in reset mode. + */ + +#define SJA1000_ACCEPTANCE_CODE_1 0x000000FF +#define SJA1000_ACCEPTANCE_CODE_1_M \ + (SJA1000_ACCEPTANCE_CODE_1_V << SJA1000_ACCEPTANCE_CODE_1_S) +#define SJA1000_ACCEPTANCE_CODE_1_V 0x000000FF +#define SJA1000_ACCEPTANCE_CODE_1_S 0 + +/* SJA1000_DATA_2_REG register + * Data register 2 + */ + +#define SJA1000_DATA_2_REG (0x12) + +/* SJA1000_TX_BYTE_2 : WO; bitpos: [7:0]; default: 0; + * Stored the 2nd byte information of the data to be transmitted under + * operating mode. + */ + +#define SJA1000_TX_BYTE_2 0x000000FF +#define SJA1000_TX_BYTE_2_M (SJA1000_TX_BYTE_2_V << SJA1000_TX_BYTE_2_S) +#define SJA1000_TX_BYTE_2_V 0x000000FF +#define SJA1000_TX_BYTE_2_S 0 + +/* SJA1000_ACCEPTANCE_CODE_2 : WO; bitpos: [7:0]; default: 0; + * Stored the 2nd byte of the filter code in reset mode. + */ + +#define SJA1000_ACCEPTANCE_CODE_2 0x000000FF +#define SJA1000_ACCEPTANCE_CODE_2_M \ + (SJA1000_ACCEPTANCE_CODE_2_V << SJA1000_ACCEPTANCE_CODE_2_S) +#define SJA1000_ACCEPTANCE_CODE_2_V 0x000000FF +#define SJA1000_ACCEPTANCE_CODE_2_S 0 + +/* SJA1000_DATA_3_REG register + * Data register 3 + */ + +#define SJA1000_DATA_3_REG (0x13) + +/* SJA1000_TX_BYTE_3 : WO; bitpos: [7:0]; default: 0; + * Stored the 3rd byte information of the data to be transmitted under + * operating mode. + */ + +#define SJA1000_TX_BYTE_3 0x000000FF +#define SJA1000_TX_BYTE_3_M (SJA1000_TX_BYTE_3_V << SJA1000_TX_BYTE_3_S) +#define SJA1000_TX_BYTE_3_V 0x000000FF +#define SJA1000_TX_BYTE_3_S 0 + +/* SJA1000_ACCEPTANCE_CODE_3 : WO; bitpos: [7:0]; default: 0; + * Stored the 3rd byte of the filter code in reset mode. + */ + +#define SJA1000_ACCEPTANCE_CODE_3 0x000000FF +#define SJA1000_ACCEPTANCE_CODE_3_M \ + (SJA1000_ACCEPTANCE_CODE_3_V << SJA1000_ACCEPTANCE_CODE_3_S) +#define SJA1000_ACCEPTANCE_CODE_3_V 0x000000FF +#define SJA1000_ACCEPTANCE_CODE_3_S 0 + +/* SJA1000_DATA_4_REG register + * Data register 4 + */ + +#define SJA1000_DATA_4_REG (0x14) + +/* SJA1000_TX_BYTE_4 : WO; bitpos: [7:0]; default: 0; + * Stored the 4th byte information of the data to be transmitted under + * operating mode. + */ + +#define SJA1000_TX_BYTE_4 0x000000FF +#define SJA1000_TX_BYTE_4_M (SJA1000_TX_BYTE_4_V << SJA1000_TX_BYTE_4_S) +#define SJA1000_TX_BYTE_4_V 0x000000FF +#define SJA1000_TX_BYTE_4_S 0 + +/* SJA1000_ACCEPTANCE_MASK_0 : WO; bitpos: [7:0]; default: 0; + * Stored the 0th byte of the filter code in reset mode. + */ + +#define SJA1000_ACCEPTANCE_MASK_0 0x000000FF +#define SJA1000_ACCEPTANCE_MASK_0_M \ + (SJA1000_ACCEPTANCE_MASK_0_V << SJA1000_ACCEPTANCE_MASK_0_S) +#define SJA1000_ACCEPTANCE_MASK_0_V 0x000000FF +#define SJA1000_ACCEPTANCE_MASK_0_S 0 + +/* SJA1000_DATA_5_REG register + * Data register 5 + */ + +#define SJA1000_DATA_5_REG (0x15) + +/* SJA1000_TX_BYTE_5 : WO; bitpos: [7:0]; default: 0; + * Stored the 5th byte information of the data to be transmitted under + * operating mode. + */ + +#define SJA1000_TX_BYTE_5 0x000000FF +#define SJA1000_TX_BYTE_5_M (SJA1000_TX_BYTE_5_V << SJA1000_TX_BYTE_5_S) +#define SJA1000_TX_BYTE_5_V 0x000000FF +#define SJA1000_TX_BYTE_5_S 0 + +/* SJA1000_ACCEPTANCE_MASK_1 : WO; bitpos: [7:0]; default: 0; + * Stored the 1st byte of the filter code in reset mode. + */ + +#define SJA1000_ACCEPTANCE_MASK_1 0x000000FF +#define SJA1000_ACCEPTANCE_MASK_1_M \ + (SJA1000_ACCEPTANCE_MASK_1_V << SJA1000_ACCEPTANCE_MASK_1_S) +#define SJA1000_ACCEPTANCE_MASK_1_V 0x000000FF +#define SJA1000_ACCEPTANCE_MASK_1_S 0 + +/* SJA1000_DATA_6_REG register + * Data register 6 + */ + +#define SJA1000_DATA_6_REG (0x16) + +/* SJA1000_TX_BYTE_6 : WO; bitpos: [7:0]; default: 0; + * Stored the 6th byte information of the data to be transmitted under + * operating mode. + */ + +#define SJA1000_TX_BYTE_6 0x000000FF +#define SJA1000_TX_BYTE_6_M (SJA1000_TX_BYTE_6_V << SJA1000_TX_BYTE_6_S) +#define SJA1000_TX_BYTE_6_V 0x000000FF +#define SJA1000_TX_BYTE_6_S 0 + +/* SJA1000_ACCEPTANCE_MASK_2 : WO; bitpos: [7:0]; default: 0; + * Stored the 2nd byte of the filter code in reset mode. + */ + +#define SJA1000_ACCEPTANCE_MASK_2 0x000000FF +#define SJA1000_ACCEPTANCE_MASK_2_M \ + (SJA1000_ACCEPTANCE_MASK_2_V << SJA1000_ACCEPTANCE_MASK_2_S) +#define SJA1000_ACCEPTANCE_MASK_2_V 0x000000FF +#define SJA1000_ACCEPTANCE_MASK_2_S 0 + +/* SJA1000_DATA_7_REG register + * Data register 7 + */ + +#define SJA1000_DATA_7_REG (0x17) + +/* SJA1000_TX_BYTE_7 : WO; bitpos: [7:0]; default: 0; + * Stored the 7th byte information of the data to be transmitted under + * operating mode. + */ + +#define SJA1000_TX_BYTE_7 0x000000FF +#define SJA1000_TX_BYTE_7_M (SJA1000_TX_BYTE_7_V << SJA1000_TX_BYTE_7_S) +#define SJA1000_TX_BYTE_7_V 0x000000FF +#define SJA1000_TX_BYTE_7_S 0 + +/* SJA1000_ACCEPTANCE_MASK_3 : WO; bitpos: [7:0]; default: 0; + * Stored the 3th byte of the filter code in reset mode. + */ + +#define SJA1000_ACCEPTANCE_MASK_3 0x000000FF +#define SJA1000_ACCEPTANCE_MASK_3_M \ + (SJA1000_ACCEPTANCE_MASK_3_V << SJA1000_ACCEPTANCE_MASK_3_S) +#define SJA1000_ACCEPTANCE_MASK_3_V 0x000000FF +#define SJA1000_ACCEPTANCE_MASK_3_S 0 + +/* SJA1000_DATA_8_REG register + * Data register 8 + */ + +#define SJA1000_DATA_8_REG (0x18) + +/* SJA1000_TX_BYTE_8 : WO; bitpos: [7:0]; default: 0; + * Stored the 8th byte information of the data to be transmitted under + * operating mode. + */ + +#define SJA1000_TX_BYTE_8 0x000000FF +#define SJA1000_TX_BYTE_8_M (SJA1000_TX_BYTE_8_V << SJA1000_TX_BYTE_8_S) +#define SJA1000_TX_BYTE_8_V 0x000000FF +#define SJA1000_TX_BYTE_8_S 0 + +/* SJA1000_DATA_9_REG register + * Data register 9 + */ + +#define SJA1000_DATA_9_REG (0x19) + +/* SJA1000_TX_BYTE_9 : WO; bitpos: [7:0]; default: 0; + * Stored the 9th byte information of the data to be transmitted under + * operating mode. + */ + +#define SJA1000_TX_BYTE_9 0x000000FF +#define SJA1000_TX_BYTE_9_M (SJA1000_TX_BYTE_9_V << SJA1000_TX_BYTE_9_S) +#define SJA1000_TX_BYTE_9_V 0x000000FF +#define SJA1000_TX_BYTE_9_S 0 + +/* SJA1000_DATA_10_REG register + * Data register 10 + */ + +#define SJA1000_DATA_10_REG (0x1A) + +/* SJA1000_TX_BYTE_10 : WO; bitpos: [7:0]; default: 0; + * Stored the 10th byte information of the data to be transmitted under + * operating mode. + */ + +#define SJA1000_TX_BYTE_10 0x000000FF +#define SJA1000_TX_BYTE_10_M (SJA1000_TX_BYTE_10_V << SJA1000_TX_BYTE_10_S) +#define SJA1000_TX_BYTE_10_V 0x000000FF +#define SJA1000_TX_BYTE_10_S 0 + +/* SJA1000_DATA_11_REG register + * Data register 11 + */ + +#define SJA1000_DATA_11_REG (0x1B) + +/* SJA1000_TX_BYTE_11 : WO; bitpos: [7:0]; default: 0; + * Stored the 11th byte information of the data to be transmitted under + * operating mode. + */ + +#define SJA1000_TX_BYTE_11 0x000000FF +#define SJA1000_TX_BYTE_11_M (SJA1000_TX_BYTE_11_V << SJA1000_TX_BYTE_11_S) +#define SJA1000_TX_BYTE_11_V 0x000000FF +#define SJA1000_TX_BYTE_11_S 0 + +/* SJA1000_DATA_12_REG register + * Data register 12 + */ + +#define SJA1000_DATA_12_REG (0x1C) + +/* SJA1000_TX_BYTE_12 : WO; bitpos: [7:0]; default: 0; + * Stored the 12th byte information of the data to be transmitted under + * operating mode. + */ + +#define SJA1000_TX_BYTE_12 0x000000FF +#define SJA1000_TX_BYTE_12_M (SJA1000_TX_BYTE_12_V << SJA1000_TX_BYTE_12_S) +#define SJA1000_TX_BYTE_12_V 0x000000FF +#define SJA1000_TX_BYTE_12_S 0 + +/* SJA1000_RX_MESSAGE_CNT_REG register + * Receive Message Counter Register + */ + +#define SJA1000_RX_MESSAGE_CNT_REG (0x1D) + +/* SJA1000_RX_MESSAGE_COUNTER : RO; bitpos: [6:0]; default: 0; + * This register reflects the number of messages available within the RX + * FIFO. + */ + +#define SJA1000_RX_MESSAGE_COUNTER 0x0000007F +#define SJA1000_RX_MESSAGE_COUNTER_M \ + (SJA1000_RX_MESSAGE_COUNTER_V << SJA1000_RX_MESSAGE_COUNTER_S) +#define SJA1000_RX_MESSAGE_COUNTER_V 0x0000007F +#define SJA1000_RX_MESSAGE_COUNTER_S 0 + +/* SJA1000_CLOCK_DIVIDER_REG register + * Clock Divider register + */ + +#define SJA1000_CLOCK_DIVIDER_REG (0x1F) + +/* SJA1000_CLOCK_OFF : RO | R/W; bitpos: [3]; default: 0; + * This bit can be configured under reset mode. 1: Disable the external + * CLKOUT pin; 0: Enable the external CLKOUT pin + */ + +#define SJA1000_CLOCK_OFF (BIT(3)) +#define SJA1000_CLOCK_OFF_M (SJA1000_CLOCK_OFF_V << SJA1000_CLOCK_OFF_S) +#define SJA1000_CLOCK_OFF_V 0x00000001 +#define SJA1000_CLOCK_OFF_S 3 + +/* SJA1000_EXT_MODE : RO | R/W; bitpos: [7]; default: 0; + * This bit can be configured under reset mode. 1: Extended mode, compatible + * with CAN2.0B; 0: Basic mode + */ + +#define SJA1000_EXT_MODE (BIT(7)) +#define SJA1000_EXT_MODE_M (SJA1000_EXT_MODE_V << SJA1000_EXT_MODE_S) +#define SJA1000_EXT_MODE_V 0x00000001 +#define SJA1000_EXT_MODE_S 7 + +/* SJA1000_CD : R/W; bitpos: [7:0]; default: 0; + * These bits are used to configure frequency dividing coefficients of the + * external CLKOUT pin. + */ + +#define SJA1000_CD 0x00000007 +#define SJA1000_CD_M (SJA1000_CD_V << SJA1000_CD_S) +#define SJA1000_CD_V 0x00000007 +#define SJA1000_CD_S 0 + +#endif /* __DRIVERS_CAN_SJA1000_H */ diff --git a/include/nuttx/can/sja1000.h b/include/nuttx/can/sja1000.h new file mode 100644 index 00000000000..f3faf094837 --- /dev/null +++ b/include/nuttx/can/sja1000.h @@ -0,0 +1,236 @@ +/**************************************************************************** + * include/nuttx/can/sja1000.h + * + * SJA1000 CAN driver based on esp32c3_twai.h + * + * License header retained from original source. + * + * 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 __INCLUDE_NUTTX_CAN_SJA1000_H +#define __INCLUDE_NUTTX_CAN_SJA1000_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* CAN hardware-dependent bit-timing constant + * + * Used for calculating and checking bit-timing parameters + */ + +struct can_bittiming_const_s +{ + char name[16]; /* Name of the CAN controller hardware */ + uint32_t tseg1_min; /* Time segment 1 = prop_seg + phase_seg1 */ + uint32_t tseg1_max; + uint32_t tseg2_min; /* Time segment 2 = phase_seg2 */ + uint32_t tseg2_max; + uint32_t sjw_max; /* Synchronisation jump width */ + uint32_t brp_min; /* Bit-rate prescaler */ + uint32_t brp_max; + uint32_t brp_inc; +}; + +/* Type of the SJA1000 interrupt handling callback */ + +struct sja1000_config_s; /* Forward reference */ +typedef CODE void (*sja1000_handler_t)(FAR struct sja1000_config_s *config, + FAR void *arg); + +/* A reference to a structure of this type must be passed to the SJA1000 + * driver when the driver is instantiated. This structure provides + * information about the configuration of the SJA1000 and provides some + * board-specific hooks. + * + * Memory for this structure is provided by the caller. It is not copied by + * the driver and is presumed to persist while the driver is active. The + * memory must be writeable because, under certain circumstances, the driver + * may modify the frequency. + */ + +struct sja1000_config_s +{ + /* Device configuration */ + + const struct can_bittiming_const_s *bittiming_const; + uint8_t port; /* SJA1000 device port number */ + uint8_t periph; /* Peripheral ID (optional) */ + uint8_t irq; /* IRQ associated with this SJA1000 */ + uint8_t cpu; /* CPU ID */ + int8_t cpuint; /* CPU interrupt assigned to this SJA1000 */ + uint32_t bitrate; /* Configured bit rate */ + uint32_t samplep; /* Configured sample point */ + uint32_t sjw; /* Synchronization jump width */ + uint32_t clk_freq; /* Peripheral clock frequency */ + bool loopback; /* Enable loopback mode */ + bool triple_sample; /* Enable triple-sampling of CAN BUS */ + + /* Device characterization */ + + /* IRQ/GPIO access callbacks. These operations all hidden behind + * callbacks to isolate the driver from differences in GPIO + * interrupt handling by varying boards and MCUs. + * + * attach - Attach interrupt handler to the interrupt + * detach - Detach interrupt handler from the interrupt + */ + + CODE int (*attach)(FAR struct sja1000_config_s *config, + sja1000_handler_t handler, FAR void *arg); + CODE int (*detach)(FAR struct sja1000_config_s *config); +}; + +/* This structure provides the current state of a CAN peripheral */ + +struct sja1000_dev_s +{ + FAR struct sja1000_config_s *config; /* The constant configuration */ + uint8_t filters; /* STD/EXT filter bit allocator. */ + uint8_t nalloc; /* Number of allocated filters */ + uint32_t base; /* SJA1000 register base address */ + +#ifdef CONFIG_ARCH_HAVE_MULTICPU + spinlock_t lock; /* Device specific lock */ +#endif /* CONFIG_ARCH_HAVE_MULTICPU */ + + /* Register read/write callbacks. These operations all hidden behind + * callbacks to isolate the driver from differences in register read/write + * handling by varying boards and MCUs. + * + * getreg - Read from a register address + * putreg - Write to a register address + */ + + CODE uint32_t (*getreg)(struct sja1000_dev_s *sja_priv, uint32_t reg); + CODE void (*putreg)(struct sja1000_dev_s *sja_priv, uint32_t reg, + uint32_t value); + CODE void (*modifyreg32)(struct sja1000_dev_s *sja_priv, uint32_t reg, + uint32_t clearbits, uint32_t setbits); +}; + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +#ifdef CONFIG_CAN_SJA1000 + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Name: sja1000_getreg + * + * Description: + * Read the value of an SJA1000 register. + * + * Input Parameters: + * priv - sja1000 lower-half driver context + * reg - The SJA1000 register address to read + * + * Returned Value: + * + ****************************************************************************/ + +static inline uint32_t sja1000_getreg(struct sja1000_dev_s *sja_priv, + uint32_t reg) +{ + return sja_priv->getreg(sja_priv, reg); +} + +/**************************************************************************** + * Name: sja1000_putreg + * + * Description: + * Set the value of an SJA1000 register. + * + * Input Parameters: + * priv - sja1000 lower-half driver context + * reg - The SJA1000 register address to write + * value - The value to write to the register + * + * Returned Value: + * None + * + ****************************************************************************/ + +static inline void sja1000_putreg(struct sja1000_dev_s *sja_priv, + uint32_t reg, uint32_t value) +{ + sja_priv->putreg(sja_priv, reg, value); +} + +/**************************************************************************** + * Name: sja1000_modifyreg32 + * + * Description: + * Modify the value of an SJA1000 register. + * + * Input Parameters: + * priv - sja1000 lower-half driver context + * reg - The SJA1000 register address to modify + * clearbits - Bitmask of the bits to clear in a register + * setbits - Bitmask of the bits to set in a register + * + * Returned Value: + * None + * + ****************************************************************************/ + +static inline void sja1000_modifyreg32(struct sja1000_dev_s *sja_priv, + uint32_t reg, uint32_t clearbits, uint32_t setbits) +{ + sja_priv->modifyreg32(sja_priv, reg, clearbits, setbits); +} + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: sja1000_instantiate + * + * Description: + * Initialize the selected SJA1000 CAN Bus Controller + * + * Input Parameters: + * priv - An instance of the "lower half" CAN driver state structure. + * + * Returned Value: + * Valid CAN device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +struct can_dev_s; + +FAR struct can_dev_s *sja1000_instantiate(FAR struct sja1000_dev_s *priv); + +#endif /* __ASSEMBLY__ */ + +#endif /* CONFIG_CAN_SJA1000 */ + +#endif /* __INCLUDE_NUTTX_CAN_SJA1000_H */