You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gn...@apache.org on 2020/06/02 14:09:27 UTC
[incubator-nuttx] 09/31: Added CAN FD driver support
This is an automated email from the ASF dual-hosted git repository.
gnutt pushed a commit to branch SocketCAN
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 437ca3a3a52abd32e4b23a8293871ac7f73ae54b
Author: Peter van der Perk <pe...@nxp.com>
AuthorDate: Tue Feb 25 08:28:20 2020 +0100
Added CAN FD driver support
CAN FD receive is working in SocketCAN
---
arch/arm/src/s32k1xx/s32k1xx_flexcan.c | 433 +++++++++++++++++----------------
include/nuttx/can/error.h | 125 ++++++++++
2 files changed, 351 insertions(+), 207 deletions(-)
diff --git a/arch/arm/src/s32k1xx/s32k1xx_flexcan.c b/arch/arm/src/s32k1xx/s32k1xx_flexcan.c
index 50a5c18..bb0d1d0 100644
--- a/arch/arm/src/s32k1xx/s32k1xx_flexcan.c
+++ b/arch/arm/src/s32k1xx/s32k1xx_flexcan.c
@@ -32,23 +32,14 @@
#include <debug.h>
#include <errno.h>
-#include <arpa/inet.h>
-
#include <nuttx/can.h>
#include <nuttx/wdog.h>
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <nuttx/wqueue.h>
#include <nuttx/signal.h>
-#include <nuttx/net/mii.h>
-#include <nuttx/net/arp.h>
-#include <nuttx/net/phy.h>
#include <nuttx/net/netdev.h>
-#ifdef CONFIG_NET_PKT
-# include <nuttx/net/pkt.h>
-#endif
-
#include "up_arch.h"
#include "chip.h"
#include "s32k1xx_config.h"
@@ -70,6 +61,7 @@
#if !defined(CONFIG_SCHED_WORKQUEUE)
# error Work queue support is required
+ //FIXME maybe for enet not sure for FLEXCAN
#else
/* Select work queue. Always use the LP work queue if available. If not,
@@ -109,17 +101,21 @@
/* Fixme nice variables/constants */
-#define RXMBCOUNT 6
-#define FILTERCOUNT 0
-#define RXANDFILTERMBCOUNT (RXMBCOUNT + FILTERCOUNT)
-#define TXMBCOUNT 12 //???????????? why 12 idk it works
-#define TOTALMBCOUNT RXANDFILTERMBCOUNT + TXMBCOUNT
-#define TXMBMASK (((1 << TXMBCOUNT)-1) << RXANDFILTERMBCOUNT)
+#define CAN_FD
+
+#define RXMBCOUNT 5
+#define TXMBCOUNT 2
+#define TOTALMBCOUNT RXMBCOUNT + TXMBCOUNT
+
+#define IFLAG1_RX ((1 << RXMBCOUNT)-1)
+#define IFLAG1_TX (((1 << TXMBCOUNT)-1) << RXMBCOUNT)
#define CAN_FIFO_NE (1 << 5)
#define CAN_FIFO_OV (1 << 6)
#define CAN_FIFO_WARN (1 << 7)
-#define FIFO_IFLAG1 (CAN_FIFO_NE | CAN_FIFO_WARN | CAN_FIFO_OV)
+
+/* Interrupt flags for RX fifo */
+#define IFLAG1_RXFIFO (CAN_FIFO_NE | CAN_FIFO_WARN | CAN_FIFO_OV)
static int peak_tx_mailbox_index_ = 0;
@@ -162,40 +158,14 @@ static int peak_tx_mailbox_index_ = 0;
#define FLEXCAN_ALIGN_MASK (FLEXCAN_ALIGN - 1)
#define FLEXCAN_ALIGN_UP(n) (((n) + FLEXCAN_ALIGN_MASK) & ~FLEXCAN_ALIGN_MASK)
-/* TX timeout = 1 minute */
-
-#define S32K1XX_TXTIMEOUT (60*CLK_TCK)
-#define MII_MAXPOLLS (0x1ffff)
-#define LINK_WAITUS (500*1000)
-#define LINK_NLOOPS (10)
-
-/* Interrupt groups */
-
-#define RX_INTERRUPTS (FLEXCAN_INT_RXF | FLEXCAN_INT_RXB)
-#define TX_INTERRUPTS FLEXCAN_INT_TXF
-#define ERROR_INTERRUPTS (FLEXCAN_INT_UN | FLEXCAN_INT_RL | FLEXCAN_INT_LC | \
- FLEXCAN_INT_EBERR | FLEXCAN_INT_BABT | FLEXCAN_INT_BABR)
-
-/* The subset of errors that require us to reset the hardware - this list
- * may need to be revisited if it's found that some error above leads to a
- * locking up of the Ethernet interface.
- */
-
-#define CRITICAL_ERROR (FLEXCAN_INT_UN | FLEXCAN_INT_RL | FLEXCAN_INT_EBERR )
-
-/* This is a helper pointer for accessing the contents of the Ethernet header */
-
-#define BUF ((struct eth_hdr_s *)priv->dev.d_buf)
-
-#define S32K1XX_BUF_SIZE FLEXCAN_ALIGN_UP(CONFIG_NET_ETH_PKTSIZE)
/****************************************************************************
* Private Types
****************************************************************************/
-union txcs_e
+union cs_e
{
- volatile uint32_t w;
+ volatile uint32_t cs;
struct
{
volatile uint32_t time_stamp : 16;
@@ -205,21 +175,10 @@ union txcs_e
volatile uint32_t srr : 1;
volatile uint32_t res : 1;
volatile uint32_t code : 4;
- volatile uint32_t res2 : 4;
- };
-};
-
-union rxcs_e
-{
- volatile uint32_t cs;
- struct
- {
- volatile uint32_t time_stamp : 16;
- volatile uint32_t dlc : 4;
- volatile uint32_t rtr : 1;
- volatile uint32_t ide : 1;
- volatile uint32_t srr : 1;
- volatile uint32_t res : 9;
+ volatile uint32_t res2 : 1;
+ volatile uint32_t esi : 1;
+ volatile uint32_t brs : 1;
+ volatile uint32_t edl : 1;
};
};
@@ -241,33 +200,25 @@ union id_e
union data_e
{
- volatile uint32_t l;
- volatile uint32_t h;
+ volatile uint32_t w00;
struct
{
- volatile uint32_t b3 : 8;
- volatile uint32_t b2 : 8;
- volatile uint32_t b1 : 8;
- volatile uint32_t b0 : 8;
- volatile uint32_t b7 : 8;
- volatile uint32_t b6 : 8;
- volatile uint32_t b5 : 8;
- volatile uint32_t b4 : 8;
+ volatile uint32_t b03 : 8;
+ volatile uint32_t b02 : 8;
+ volatile uint32_t b01 : 8;
+ volatile uint32_t b00 : 8;
};
};
-struct mbtx_s
+struct mb_s
{
- union txcs_e cs;
+ union cs_e cs;
union id_e id;
- union data_e data;
-};
-
-struct mbrx_s
-{
- union rxcs_e cs;
- union id_e id;
- union data_e data;
+#ifdef CAN_FD
+ union data_e data[16];
+#else
+ union data_e data[2];
+#endif
};
/* The s32k1xx_driver_s encapsulates all state information for a single
@@ -292,8 +243,8 @@ struct s32k1xx_driver_s
struct net_driver_s dev; /* Interface understood by the network */
- struct mbrx_s *rx;
- struct mbtx_s *tx;
+ struct mb_s *rx;
+ struct mb_s *tx;
};
/****************************************************************************
@@ -324,6 +275,28 @@ static inline uint16_t s32k1xx_swap16(uint16_t value);
#endif
#endif
+/****************************************************************************
+ * Name: arm_clz
+ *
+ * Description:
+ * Access to CLZ instructions
+ *
+ * Input Parameters:
+ * value - The value to perform the Count Leading Zeros operation on
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static inline uint32_t arm_clz(unsigned int value)
+{
+ uint32_t ret;
+
+ __asm__ __volatile__ ("clz %0, %1" : "=r"(ret) : "r"(value));
+ return ret;
+}
+
/* Common TX logic */
static bool s32k1xx_txringfull(FAR struct s32k1xx_driver_s *priv);
@@ -340,8 +313,8 @@ static uint32_t s32k1xx_waitmcr_change(uint32_t mask,
/* Interrupt handling */
static void s32k1xx_dispatch(FAR struct s32k1xx_driver_s *priv);
-static void s32k1xx_receive(FAR struct s32k1xx_driver_s *priv);
-static void s32k1xx_txdone(FAR struct s32k1xx_driver_s *priv);
+static void s32k1xx_receive(FAR struct s32k1xx_driver_s *priv, uint32_t flags);
+static void s32k1xx_txdone(FAR struct s32k1xx_driver_s *priv, uint32_t flags);
static void s32k1xx_flexcan_interrupt_work(FAR void *arg);
static int s32k1xx_flexcan_interrupt(int irq, FAR void *context,
@@ -363,12 +336,6 @@ static int s32k1xx_ifdown(struct net_driver_s *dev);
static void s32k1xx_txavail_work(FAR void *arg);
static int s32k1xx_txavail(struct net_driver_s *dev);
-#ifdef CONFIG_NET_MCASTGROUP
-static int s32k1xx_addmac(struct net_driver_s *dev,
- FAR const uint8_t *mac);
-static int s32k1xx_rmmac(struct net_driver_s *dev, FAR const uint8_t *mac);
-#endif
-
#ifdef CONFIG_NETDEV_IOCTL
static int s32k1xx_ioctl(struct net_driver_s *dev, int cmd,
unsigned long arg);
@@ -456,11 +423,12 @@ static int s32k1xx_transmit(FAR struct s32k1xx_driver_s *priv)
if ((getreg32(S32K1XX_CAN0_ESR2) & (CAN_ESR2_IMB | CAN_ESR2_VPS)) ==
(CAN_ESR2_IMB | CAN_ESR2_VPS))
{
- mbi = (getreg32(S32K1XX_CAN0_ESR2) & CAN_ESR2_LPTM_MASK) >>
- CAN_ESR2_LPTM_SHIFT;
+ mbi = ((getreg32(S32K1XX_CAN0_ESR2) &
+ CAN_ESR2_LPTM_MASK) >> CAN_ESR2_LPTM_SHIFT);
+ mbi -= RXMBCOUNT;
}
- uint32_t mb_bit = 1 << (RXANDFILTERMBCOUNT + mbi);
+ uint32_t mb_bit = 1 << (RXMBCOUNT + mbi);
while (mbi < TXMBCOUNT)
{
@@ -474,7 +442,7 @@ static int s32k1xx_transmit(FAR struct s32k1xx_driver_s *priv)
mbi++;
}
- if ((mbi - RXANDFILTERMBCOUNT) == TXMBCOUNT)
+ if (mbi == TXMBCOUNT)
{
nwarn("No TX MB available mbi %i\r\n", mbi);
return 0; /* No transmission for you! */
@@ -483,9 +451,9 @@ static int s32k1xx_transmit(FAR struct s32k1xx_driver_s *priv)
peak_tx_mailbox_index_ =
(peak_tx_mailbox_index_ > mbi ? peak_tx_mailbox_index_ : mbi);
- union txcs_e cs;
+ union cs_e cs;
cs.code = CAN_TXMB_DATAORREMOTE;
- struct mbtx_s *mb = &priv->tx[mbi];
+ struct mb_s *mb = &priv->tx[mbi];
mb->cs.code = CAN_TXMB_INACTIVE;
if (0) /* FIXME detect Std or Ext id */
@@ -506,14 +474,14 @@ static int s32k1xx_transmit(FAR struct s32k1xx_driver_s *priv)
/* FIXME endian swap instruction or somekind takes 1.5us right now */
- mb->data.b0 = frame->data[0];
- mb->data.b1 = frame->data[1];
- mb->data.b2 = frame->data[2];
- mb->data.b3 = frame->data[3];
- mb->data.b4 = frame->data[4];
- mb->data.b5 = frame->data[5];
- mb->data.b6 = frame->data[6];
- mb->data.b7 = frame->data[7];
+ mb->data[0].b00 = frame->data[0];
+ mb->data[0].b01 = frame->data[1];
+ mb->data[0].b02 = frame->data[2];
+ mb->data[0].b03 = frame->data[3];
+ mb->data[1].b00 = frame->data[4];
+ mb->data[1].b01 = frame->data[5];
+ mb->data[1].b02 = frame->data[6];
+ mb->data[1].b03 = frame->data[7];
#if 0
/* Registering the pending transmission so we can track its deadline and
@@ -646,77 +614,142 @@ static inline void s32k1xx_dispatch(FAR struct s32k1xx_driver_s *priv)
*
****************************************************************************/
-static void s32k1xx_receive(FAR struct s32k1xx_driver_s *priv)
+static void s32k1xx_receive(FAR struct s32k1xx_driver_s *priv, uint32_t flags)
{
#warning Missing logic
+ uint32_t regval;
+
s32k1xx_gpiowrite(PIN_PORTD | PIN31, 1);
- struct can_frame frame;
- uint32_t flags = getreg32(S32K1XX_CAN0_IFLAG1);
- if ((flags & FIFO_IFLAG1) == 0)
+ //FIXME naive what if multiple flags are high??
+ uint32_t mb_index = arm_clz(flags);
+
+ if (mb_index)
{
- /* Weird, IRQ is here but no data to read */
+ struct mb_s *rf = &priv->rx[31 - mb_index];
- return;
- }
+ /* Read the frame contents */
- if (flags & CAN_FIFO_OV)
- {
-#if 0
- error_cnt_++;
-#endif
- putreg32(CAN_FIFO_OV, S32K1XX_CAN0_IFLAG1);
- }
+ if(rf->cs.edl) /* CAN FD frame */
+ {
- if (flags & CAN_FIFO_WARN)
- {
-#if 0
- fifo_warn_cnt_++;
-#endif
- putreg32(CAN_FIFO_WARN, S32K1XX_CAN0_IFLAG1);
- }
+ struct canfd_frame frame;
- if (flags & CAN_FIFO_NE)
- {
- struct mbrx_s *rf = priv->rx;
+ if (rf->cs.ide)
+ {
+ frame.can_id = MASKEXTID & rf->id.ext;
+ frame.can_id |= FLAGEFF;
+ }
+ else
+ {
+ frame.can_id = MASKSTDID & rf->id.std;
+ }
- /* Read the frame contents */
+ if (rf->cs.rtr)
+ {
+ frame.can_id |= FLAGRTR;
+ }
- if (rf->cs.ide)
- {
- frame.can_id = MASKEXTID & rf->id.ext;
- frame.can_id |= FLAGEFF;
+ if(rf->cs.dlc < 9){
+ frame.len = rf->cs.dlc;
+ } else {
+ switch(rf->cs.dlc)
+ {
+ case 9:
+ frame.len = 12;
+ break;
+
+ case 10:
+ frame.len = 16;
+ break;
+
+ case 11:
+ frame.len = 20;
+ break;
+
+ case 12:
+ frame.len = 24;
+ break;
+
+ case 13:
+ frame.len = 32;
+ break;
+
+ case 14:
+ frame.len = 48;
+ break;
+
+ case 15:
+ frame.len = 64;
+ break;
+ }
+ }
+
+ int j = 0;
+ for(int i = 0; i < (frame.len + 4 - 1) / 4; i++)
+ {
+ frame.data[0+j] = rf->data[i].b00;
+ frame.data[1+j] = rf->data[i].b01;
+ frame.data[2+j] = rf->data[i].b02;
+ frame.data[3+j] = rf->data[i].b03;
+ j = j + 4;
+ }
+
+ /* Clear MB interrupt flag */
+ regval = getreg32(S32K1XX_CAN0_IFLAG1);
+ regval |= (1 << mb_index);
+ putreg32(regval, S32K1XX_CAN0_IFLAG1);
+
+ /* Copy the buffer pointer to priv->dev.d_buf. Set amount of data
+ * in priv->dev.d_len
+ */
+
+ priv->dev.d_len = sizeof(struct canfd_frame);
+ priv->dev.d_buf = (uint8_t *)s32k1xx_swap32((uint32_t)&frame); /* FIXME */
}
- else
+ else /* CAN 2.0 Frame */
{
- frame.can_id = MASKSTDID & rf->id.std;
- }
+ struct can_frame frame;
- if (rf->cs.rtr)
- {
- frame.can_id |= FLAGRTR;
- }
+ if (rf->cs.ide)
+ {
+ frame.can_id = MASKEXTID & rf->id.ext;
+ frame.can_id |= FLAGEFF;
+ }
+ else
+ {
+ frame.can_id = MASKSTDID & rf->id.std;
+ }
- frame.can_dlc = rf->cs.dlc;
+ if (rf->cs.rtr)
+ {
+ frame.can_id |= FLAGRTR;
+ }
- frame.data[0] = rf->data.b0;
- frame.data[1] = rf->data.b1;
- frame.data[2] = rf->data.b2;
- frame.data[3] = rf->data.b3;
- frame.data[4] = rf->data.b4;
- frame.data[5] = rf->data.b5;
- frame.data[6] = rf->data.b6;
- frame.data[7] = rf->data.b7;
+ frame.can_dlc = rf->cs.dlc;
- putreg32(CAN_FIFO_NE, S32K1XX_CAN0_IFLAG1);
+ frame.data[0] = rf->data[0].b00;
+ frame.data[1] = rf->data[0].b01;
+ frame.data[2] = rf->data[0].b02;
+ frame.data[3] = rf->data[0].b03;
+ frame.data[4] = rf->data[1].b00;
+ frame.data[5] = rf->data[1].b01;
+ frame.data[6] = rf->data[1].b02;
+ frame.data[7] = rf->data[1].b03;
- /* Copy the buffer pointer to priv->dev.d_buf. Set amount of data
- * in priv->dev.d_len
- */
+ /* Clear MB interrupt flag */
+ regval = getreg32(S32K1XX_CAN0_IFLAG1);
+ regval |= (1 << mb_index);
+ putreg32(regval, S32K1XX_CAN0_IFLAG1);
- priv->dev.d_len = sizeof(struct can_frame);
- priv->dev.d_buf = (uint8_t *)s32k1xx_swap32((uint32_t)&frame); /* FIXME */
+ /* Copy the buffer pointer to priv->dev.d_buf. Set amount of data
+ * in priv->dev.d_len
+ */
+
+ priv->dev.d_len = sizeof(struct can_frame);
+ priv->dev.d_buf = (uint8_t *)s32k1xx_swap32((uint32_t)&frame); /* FIXME */
+ }
/* Invalidate the buffer so that the correct packet will be re-read
* from memory when the packet content is accessed.
@@ -753,24 +786,21 @@ static void s32k1xx_receive(FAR struct s32k1xx_driver_s *priv)
*
****************************************************************************/
-static void s32k1xx_txdone(FAR struct s32k1xx_driver_s *priv)
+static void s32k1xx_txdone(FAR struct s32k1xx_driver_s *priv, uint32_t flags)
{
#warning Missing logic
- uint32_t tx_iflags;
- tx_iflags = getreg32(S32K1XX_CAN0_IFLAG1) & TXMBMASK;
-
/* FIXME process aborts */
/* Process TX completions */
uint32_t mb_bit = 1 << RXMBCOUNT;
- for (uint32_t mbi = 0; tx_iflags && mbi < TXMBCOUNT; mbi++)
+ for (uint32_t mbi = 0; flags && mbi < TXMBCOUNT; mbi++)
{
- if (tx_iflags & mb_bit)
+ if (flags & mb_bit)
{
putreg32(mb_bit, S32K1XX_CAN0_IFLAG1);
- tx_iflags &= ~mb_bit;
+ flags &= ~mb_bit;
#if 0
const bool txok = priv->tx[mbi].cs.code != CAN_TXMB_ABORT;
handleTxMailboxInterrupt(mbi, txok, utc_usec);
@@ -829,19 +859,19 @@ static int s32k1xx_flexcan_interrupt(int irq, FAR void *context, FAR void *arg)
FAR struct s32k1xx_driver_s *priv = &g_flexcan[0];
uint32_t flags;
flags = getreg32(S32K1XX_CAN0_IFLAG1);
- flags &= FIFO_IFLAG1;
+ flags &= IFLAG1_RX;
if (flags)
{
- s32k1xx_receive(priv);
+ s32k1xx_receive(priv, flags);
}
flags = getreg32(S32K1XX_CAN0_IFLAG1);
- flags &= TXMBMASK;
+ flags &= IFLAG1_TX;
if (flags)
{
- s32k1xx_txdone(priv);
+ s32k1xx_txdone(priv, flags);
}
}
@@ -1271,38 +1301,18 @@ static int s32k1xx_initialize(struct s32k1xx_driver_s *priv)
return -1;
}
-#if 0
- regval = getreg32(S32K1XX_CAN0_CTRL1);
- regval |= ((0 << CAN_CTRL1_PRESDIV_SHIFT) & CAN_CTRL1_PRESDIV_MASK) |
- ((46 << CAN_CTRL1_ROPSEG_SHIFT) & CAN_CTRL1_ROPSEG_MASK) |
- ((18 << CAN_CTRL1_PSEG1_SHIFT) & CAN_CTRL1_PSEG1_MASK) |
- ((12 << CAN_CTRL1_PSEG2_SHIFT) & CAN_CTRL1_PSEG2_MASK) |
- ((12 << CAN_CTRL1_RJW_SHIFT) & CAN_CTRL1_RJW_MASK) |
- CAN_CTRL1_ERRMSK |
- CAN_CTRL1_TWRNMSK |
- CAN_CTRL1_RWRNMSK;
-
- putreg32(regval, S32K1XX_CAN0_CTRL1);
-#endif
-
-#define BIT_METHOD2
-#ifdef BIT_METHOD2
- /* CAN Bit Timing (CBT) configuration for a nominal phase of 1 Mbit/s
- * with 80 time quantas,in accordance with Bosch 2012 specification,
- * sample point at 83.75%
- */
+ /* Based on 80Mhz BUS clock calc through S32DS */
regval = getreg32(S32K1XX_CAN0_CBT);
regval |= CAN_CBT_BTF | /* Enable extended bit timing configurations
* for CAN-FD for setting up separately
* nominal and data phase */
- CAN_CBT_EPRESDIV(0) | /* Prescaler divisor factor of 1 */
- CAN_CBT_EPROPSEG(46) | /* Propagation segment of 47 time quantas */
- CAN_CBT_EPSEG1(18) | /* Phase buffer segment 1 of 19 time quantas */
- CAN_CBT_EPSEG2(12) | /* Phase buffer segment 2 of 13 time quantas */
- CAN_CBT_ERJW(12); /* Resynchronization jump width same as PSEG2 */
+ CAN_CBT_EPRESDIV(3) | /* Prescaler divisor factor of 3 */
+ CAN_CBT_EPROPSEG(7) | /* Propagation segment of 7 time quantas */
+ CAN_CBT_EPSEG1(6) | /* Phase buffer segment 1 of 6 time quantas */
+ CAN_CBT_EPSEG2(3) | /* Phase buffer segment 2 of 3 time quantas */
+ CAN_CBT_ERJW(1); /* Resynchronization jump width */
putreg32(regval, S32K1XX_CAN0_CBT);
-#endif
#ifdef CAN_FD
/* Enable CAN FD feature */
@@ -1311,17 +1321,14 @@ static int s32k1xx_initialize(struct s32k1xx_driver_s *priv)
regval |= CAN_MCR_FDEN;
putreg32(regval, S32K1XX_CAN0_MCR);
- /* CAN-FD Bit Timing (FDCBT) for a data phase of 4 Mbit/s with 20 time quantas,
- * in accordance with Bosch 2012 specification, sample point at 75%
- */
-
+ /* Based on 80Mhz BUS clock calc through S32DS */
regval = getreg32(S32K1XX_CAN0_FDCBT);
regval |= CAN_FDCBT_FPRESDIV(0) | /* Prescaler divisor factor of 1 */
- CAN_FDCBT_FPROPSEG(7) | /* Propagation semgment of 7 time quantas
+ CAN_FDCBT_FPROPSEG(15) | /* Propagation semgment of 7 time quantas
* (only register that doesn't add 1) */
- CAN_FDCBT_FPSEG1(6) | /* Phase buffer segment 1 of 7 time quantas */
- CAN_FDCBT_FPSEG2(4) | /* Phase buffer segment 2 of 5 time quantas */
- CAN_FDCBT_FRJW(4); /* Resynchorinzation jump width same as PSEG2 */
+ CAN_FDCBT_FPSEG1(1) | /* Phase buffer segment 1 of 7 time quantas */
+ CAN_FDCBT_FPSEG2(1) | /* Phase buffer segment 2 of 5 time quantas */
+ CAN_FDCBT_FRJW(1); /* Resynchorinzation jump width same as PSEG2 */
putreg32(regval, S32K1XX_CAN0_FDCBT);
/* Additional CAN-FD configurations */
@@ -1351,8 +1358,20 @@ static int s32k1xx_initialize(struct s32k1xx_driver_s *priv)
putreg32(0, S32K1XX_CAN0_RXIMR(i));
}
- putreg32(FIFO_IFLAG1 | TXMBMASK, S32K1XX_CAN0_IFLAG1);
- putreg32(FIFO_IFLAG1, S32K1XX_CAN0_IMASK1);
+ for (i = 0; i < RXMBCOUNT; i++)
+ {
+ ninfo("Set MB%i to receive %p\r\n", i, &priv->rx[i]);
+ priv->rx[i].cs.edl = 0x1;
+ priv->rx[i].cs.brs = 0x1;
+ priv->rx[i].cs.esi = 0x0;
+ priv->rx[i].cs.code = 4;
+ priv->rx[i].cs.srr = 0x0;
+ priv->rx[i].cs.ide = 0x1;
+ priv->rx[i].cs.rtr = 0x0;
+ }
+
+ putreg32(IFLAG1_RX, S32K1XX_CAN0_IFLAG1);
+ putreg32(IFLAG1_RX, S32K1XX_CAN0_IMASK1);
/* Exit freeze mode */
@@ -1432,12 +1451,12 @@ static void s32k1xx_reset(struct s32k1xx_driver_s *priv)
ninfo("MB %i %p\r\n", i, &priv->rx[i].id.w);
priv->rx[i].cs.cs = 0x0;
priv->rx[i].id.w = 0x0;
- priv->rx[i].data.l = 0x0;
- priv->rx[i].data.h = 0x0;
+ priv->rx[i].data[0].w00 = 0x0;
+ priv->rx[i].data[1].w00 = 0x0;
}
regval = getreg32(S32K1XX_CAN0_MCR);
- regval |= CAN_MCR_RFEN | CAN_MCR_SLFWAK | CAN_MCR_WRNEN | CAN_MCR_SRXDIS |
+ regval |= CAN_MCR_SLFWAK | CAN_MCR_WRNEN | CAN_MCR_SRXDIS |
CAN_MCR_IRMQ | CAN_MCR_AEN |
(((TOTALMBCOUNT - 1) << CAN_MCR_MAXMB_SHIFT) & CAN_MCR_MAXMB_MASK);
putreg32(regval, S32K1XX_CAN0_MCR);
@@ -1546,9 +1565,9 @@ int s32k1xx_netinitialize(int intf)
priv->txpoll = wd_create(); /* Create periodic poll timer */
priv->txtimeout = wd_create(); /* Create TX timeout timer */
- priv->rx = (struct mbrx_s *)(S32K1XX_CAN0_MB);
- priv->tx = (struct mbtx_s *)(S32K1XX_CAN0_MB +
- (sizeof(struct mbrx_s) * RXMBCOUNT));
+ priv->rx = (struct mb_s *)(S32K1XX_CAN0_MB);
+ priv->tx = (struct mb_s *)(S32K1XX_CAN0_MB +
+ (sizeof(struct mb_s) * RXMBCOUNT));
/* Put the interface in the down state. This usually amounts to resetting
* the device and/or calling s32k1xx_ifdown().
diff --git a/include/nuttx/can/error.h b/include/nuttx/can/error.h
new file mode 100644
index 0000000..3463328
--- /dev/null
+++ b/include/nuttx/can/error.h
@@ -0,0 +1,125 @@
+/* SPDX-License-Identifier: ((GPL-2.0-only WITH Linux-syscall-note) OR BSD-3-Clause) */
+/*
+ * linux/can/error.h
+ *
+ * Definitions of the CAN error messages to be filtered and passed to the user.
+ *
+ * Author: Oliver Hartkopp <ol...@volkswagen.de>
+ * Copyright (c) 2002-2007 Volkswagen Group Electronic Research
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Volkswagen nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Alternatively, provided that this notice is retained in full, this
+ * software may be distributed under the terms of the GNU General
+ * Public License ("GPL") version 2, in which case the provisions of the
+ * GPL apply INSTEAD OF those given above.
+ *
+ * The provided data structures and external interfaces from this code
+ * are not restricted to be used by modules with a GPL compatible license.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#ifndef _UAPI_CAN_ERROR_H
+#define _UAPI_CAN_ERROR_H
+
+#define CAN_ERR_DLC 8 /* dlc for error message frames */
+
+/* error class (mask) in can_id */
+#define CAN_ERR_TX_TIMEOUT 0x00000001U /* TX timeout (by netdevice driver) */
+#define CAN_ERR_LOSTARB 0x00000002U /* lost arbitration / data[0] */
+#define CAN_ERR_CRTL 0x00000004U /* controller problems / data[1] */
+#define CAN_ERR_PROT 0x00000008U /* protocol violations / data[2..3] */
+#define CAN_ERR_TRX 0x00000010U /* transceiver status / data[4] */
+#define CAN_ERR_ACK 0x00000020U /* received no ACK on transmission */
+#define CAN_ERR_BUSOFF 0x00000040U /* bus off */
+#define CAN_ERR_BUSERROR 0x00000080U /* bus error (may flood!) */
+#define CAN_ERR_RESTARTED 0x00000100U /* controller restarted */
+
+/* arbitration lost in bit ... / data[0] */
+#define CAN_ERR_LOSTARB_UNSPEC 0x00 /* unspecified */
+ /* else bit number in bitstream */
+
+/* error status of CAN-controller / data[1] */
+#define CAN_ERR_CRTL_UNSPEC 0x00 /* unspecified */
+#define CAN_ERR_CRTL_RX_OVERFLOW 0x01 /* RX buffer overflow */
+#define CAN_ERR_CRTL_TX_OVERFLOW 0x02 /* TX buffer overflow */
+#define CAN_ERR_CRTL_RX_WARNING 0x04 /* reached warning level for RX errors */
+#define CAN_ERR_CRTL_TX_WARNING 0x08 /* reached warning level for TX errors */
+#define CAN_ERR_CRTL_RX_PASSIVE 0x10 /* reached error passive status RX */
+#define CAN_ERR_CRTL_TX_PASSIVE 0x20 /* reached error passive status TX */
+ /* (at least one error counter exceeds */
+ /* the protocol-defined level of 127) */
+#define CAN_ERR_CRTL_ACTIVE 0x40 /* recovered to error active state */
+
+/* error in CAN protocol (type) / data[2] */
+#define CAN_ERR_PROT_UNSPEC 0x00 /* unspecified */
+#define CAN_ERR_PROT_BIT 0x01 /* single bit error */
+#define CAN_ERR_PROT_FORM 0x02 /* frame format error */
+#define CAN_ERR_PROT_STUFF 0x04 /* bit stuffing error */
+#define CAN_ERR_PROT_BIT0 0x08 /* unable to send dominant bit */
+#define CAN_ERR_PROT_BIT1 0x10 /* unable to send recessive bit */
+#define CAN_ERR_PROT_OVERLOAD 0x20 /* bus overload */
+#define CAN_ERR_PROT_ACTIVE 0x40 /* active error announcement */
+#define CAN_ERR_PROT_TX 0x80 /* error occurred on transmission */
+
+/* error in CAN protocol (location) / data[3] */
+#define CAN_ERR_PROT_LOC_UNSPEC 0x00 /* unspecified */
+#define CAN_ERR_PROT_LOC_SOF 0x03 /* start of frame */
+#define CAN_ERR_PROT_LOC_ID28_21 0x02 /* ID bits 28 - 21 (SFF: 10 - 3) */
+#define CAN_ERR_PROT_LOC_ID20_18 0x06 /* ID bits 20 - 18 (SFF: 2 - 0 )*/
+#define CAN_ERR_PROT_LOC_SRTR 0x04 /* substitute RTR (SFF: RTR) */
+#define CAN_ERR_PROT_LOC_IDE 0x05 /* identifier extension */
+#define CAN_ERR_PROT_LOC_ID17_13 0x07 /* ID bits 17-13 */
+#define CAN_ERR_PROT_LOC_ID12_05 0x0F /* ID bits 12-5 */
+#define CAN_ERR_PROT_LOC_ID04_00 0x0E /* ID bits 4-0 */
+#define CAN_ERR_PROT_LOC_RTR 0x0C /* RTR */
+#define CAN_ERR_PROT_LOC_RES1 0x0D /* reserved bit 1 */
+#define CAN_ERR_PROT_LOC_RES0 0x09 /* reserved bit 0 */
+#define CAN_ERR_PROT_LOC_DLC 0x0B /* data length code */
+#define CAN_ERR_PROT_LOC_DATA 0x0A /* data section */
+#define CAN_ERR_PROT_LOC_CRC_SEQ 0x08 /* CRC sequence */
+#define CAN_ERR_PROT_LOC_CRC_DEL 0x18 /* CRC delimiter */
+#define CAN_ERR_PROT_LOC_ACK 0x19 /* ACK slot */
+#define CAN_ERR_PROT_LOC_ACK_DEL 0x1B /* ACK delimiter */
+#define CAN_ERR_PROT_LOC_EOF 0x1A /* end of frame */
+#define CAN_ERR_PROT_LOC_INTERM 0x12 /* intermission */
+
+/* error status of CAN-transceiver / data[4] */
+/* CANH CANL */
+#define CAN_ERR_TRX_UNSPEC 0x00 /* 0000 0000 */
+#define CAN_ERR_TRX_CANH_NO_WIRE 0x04 /* 0000 0100 */
+#define CAN_ERR_TRX_CANH_SHORT_TO_BAT 0x05 /* 0000 0101 */
+#define CAN_ERR_TRX_CANH_SHORT_TO_VCC 0x06 /* 0000 0110 */
+#define CAN_ERR_TRX_CANH_SHORT_TO_GND 0x07 /* 0000 0111 */
+#define CAN_ERR_TRX_CANL_NO_WIRE 0x40 /* 0100 0000 */
+#define CAN_ERR_TRX_CANL_SHORT_TO_BAT 0x50 /* 0101 0000 */
+#define CAN_ERR_TRX_CANL_SHORT_TO_VCC 0x60 /* 0110 0000 */
+#define CAN_ERR_TRX_CANL_SHORT_TO_GND 0x70 /* 0111 0000 */
+#define CAN_ERR_TRX_CANL_SHORT_TO_CANH 0x80 /* 1000 0000 */
+
+/* controller specific additional information / data[5..7] */
+
+#endif /* _UAPI_CAN_ERROR_H */