From bfa14406d6242eedcd7507681b06ca026ff2ac35 Mon Sep 17 00:00:00 2001 From: TimJTi <56726697+TimJTi@users.noreply.github.com> Date: Tue, 26 Sep 2023 16:07:54 +0100 Subject: [PATCH] SAMA5D2 add new mcan ioctls --- arch/arm/src/sama5/sam_mcan.c | 200 ++++++++++++++++++++++++++++++++-- 1 file changed, 188 insertions(+), 12 deletions(-) diff --git a/arch/arm/src/sama5/sam_mcan.c b/arch/arm/src/sama5/sam_mcan.c index 2f0b9d5266..54c2a2d76d 100644 --- a/arch/arm/src/sama5/sam_mcan.c +++ b/arch/arm/src/sama5/sam_mcan.c @@ -878,17 +878,17 @@ struct sam_mcan_s const struct sam_config_s *config; - enum can_state_s state; /* See enum can_state_s */ + enum can_state_s state; /* See enum can_state_s */ #ifdef CONFIG_CAN_EXTID - uint8_t nextalloc; /* Number of allocated extended filters */ + uint8_t nextalloc; /* Number of allocated extended filters */ #endif - uint8_t nstdalloc; /* Number of allocated standard filters */ - mutex_t lock; /* Enforces mutually exclusive access */ - sem_t txfsem; /* Used to wait for TX FIFO availability */ - uint32_t btp; /* Current bit timing */ - uint32_t fbtp; /* Current fast bit timing */ - uint32_t rxints; /* Configured RX interrupts */ - uint32_t txints; /* Configured TX interrupts */ + uint8_t nstdalloc; /* Number of allocated standard filters */ + mutex_t lock; /* Enforces mutually exclusive access */ + sem_t txfsem; /* Used to wait for TX FIFO availability */ + uint32_t btp; /* Current bit timing */ + uint32_t fbtp; /* Current fast bit timing */ + uint32_t rxints; /* Configured RX interrupts */ + uint32_t txints; /* Configured TX interrupts */ #ifdef CONFIG_CAN_EXTID uint32_t extfilters[2]; /* Extended filter bit allocator. 2*32=64 */ @@ -936,6 +936,10 @@ static int mcan_add_stdfilter(struct sam_mcan_s *priv, struct canioc_stdfilter_s *stdconfig); static int mcan_del_stdfilter(struct sam_mcan_s *priv, int ndx); +static int mcan_set_nart(struct sam_mcan_s *priv, bool enable); +static int mcan_cancel_tx_buffers(struct sam_mcan_s *priv); +static int mcan_cancel_rx_fifos(struct sam_mcan_s *priv); + /* CAN driver methods */ static void mcan_reset(struct can_dev_s *dev); @@ -2838,6 +2842,69 @@ static int mcan_ioctl(struct can_dev_s *dev, int cmd, unsigned long arg) } break; + /* CANIOC_SET_NART: + * Description: Enable/Disable NART (No Automatic Retry) + * Argument: Set to 1 to enable NART, 0 to disable. + * Default is disabled. + * 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_SET_NART: + { + ret = mcan_set_nart(priv, (bool)arg); + } + break; + + /* CANIOC_IFLUSH + * Description: Flush data received but not read + * Argument: None + * 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_IFLUSH: + { + ret = mcan_cancel_rx_fifos(priv); + } + break; + + /* CANIOC_OFLUSH + * Description: Flush data queued but not transmitted + * Argument: None + * 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_OFLUSH: + { + ret = mcan_cancel_tx_buffers(priv); + } + break; + + /* CANIOC_IOFLUSH + * Description: Flush data received but not read, and data queued + but not transmitted + * Argument: None + * 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_IOFLUSH: + { + ret = mcan_cancel_tx_buffers(priv); + ret = mcan_cancel_rx_fifos(priv); + } + break; + /* Unsupported/unrecognized command */ default: @@ -2876,7 +2943,8 @@ static int mcan_remoterequest(struct can_dev_s *dev, uint16_t id) * Send one can message. * * One CAN-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). + * composed of at least the && priv->config != NULLfirst 2 bytes + * (when there are no data bytes). * * Byte 0: Bits 0-7: Bits 3-10 of the 11-bit CAN identifier * Byte 1: Bits 5-7: Bits 0-2 of the 11-bit CAN identifier @@ -3380,6 +3448,114 @@ static void mcan_error(struct can_dev_s *dev, uint32_t status) } #endif /* CONFIG_CAN_ERRORS */ +/**************************************************************************** + * Name: mcan_set_nart + * + * Description: + * Enable/Disable NART (No Automatic Retry), + * AKA "DAR" - Disable Automatic Retry + * + * Input Parameters: + * priv - An instance of the MCAN driver state structure. + * enable - enable or disable. + * + * Returned Value: + * Zero on success; a negated errno on failure + * + ****************************************************************************/ + +static int mcan_set_nart(struct sam_mcan_s *priv, bool enable) +{ + uint32_t regval; + + DEBUGASSERT(priv != NULL); + + regval = mcan_getreg(priv, SAM_MCAN_CCCR_OFFSET); + if (enable) + { + regval |= MCAN_CCCR_DAR; + } + else + { + regval &= ~MCAN_CCCR_DAR; + } + + mcan_putreg(priv, SAM_MCAN_CCCR_OFFSET, regval); + + return OK; +} + +/**************************************************************************** + * Name: mcan_cancel_tx_buffers + * + * Description: + * Cancel all pending, buffered, transmissions + * + * Input Parameters: + * priv - An instance of the MCAN driver state structure. + * + * Returned Value: + * Success + * + ****************************************************************************/ + +static int mcan_cancel_tx_buffers(struct sam_mcan_s *priv) +{ + uint32_t regval; + + DEBUGASSERT(priv != NULL); + + mcan_putreg(priv, SAM_MCAN_TXBCR_OFFSET, 0xffff); + + do + { + regval = mcan_getreg(priv, SAM_MCAN_TXBRP_OFFSET); + } + while (regval != 0); + + return OK; +} + +/**************************************************************************** + * Name: mcan_cancel_rx_fifos + * + * Description: + * Cancel all queued/received messages + * + * Input Parameters: + * priv - An instance of the MCAN driver state structure. + * + * Returned Value: + * Success + * + ****************************************************************************/ + +static int mcan_cancel_rx_fifos(struct sam_mcan_s *priv) +{ + uint32_t ir; + uint32_t ie; + uint32_t pending; + + DEBUGASSERT(priv != NULL); + + mcan_putreg(priv, SAM_MCAN_RXF0A_OFFSET, 0); + mcan_putreg(priv, SAM_MCAN_RXF1A_OFFSET, 0); + + /* Clear RX interrupts */ + + ir = mcan_getreg(priv, SAM_MCAN_IR_OFFSET); + ie = mcan_getreg(priv, SAM_MCAN_IE_OFFSET); + + pending = (ir & ie); + + if ((pending & priv->rxints) != 0) + { + mcan_putreg(priv, SAM_MCAN_IR_OFFSET, priv->rxints); + } + + return OK; +} + /**************************************************************************** * Name: mcan_receive * @@ -3713,7 +3889,7 @@ static int mcan_interrupt(int irq, void *context, void *arg) /* Check if there is anything in RX FIFO1 */ regval = mcan_getreg(priv, SAM_MCAN_RXF1S_OFFSET); - nelem = (regval & MCAN_RXF0S_F0FL_MASK) >> MCAN_RXF0S_F0FL_SHIFT; + nelem = (regval & MCAN_RXF1S_F1FL_MASK) >> MCAN_RXF1S_F1FL_SHIFT; if (nelem == 0) { /* Break out of the loop if RX FIFO1 is empty */ @@ -3729,7 +3905,7 @@ static int mcan_interrupt(int irq, void *context, void *arg) ndx = (regval & MCAN_RXF1S_F1GI_MASK) >> MCAN_RXF1S_F1GI_SHIFT; - if ((regval & MCAN_RXF0S_RF0L) != 0) + if ((regval & MCAN_RXF1S_RF1L) != 0) { canerr("ERROR: Message lost: %08" PRIx32 "\n", regval); }