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 */