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 eb17e0582bebba6e142470188d1569972cfb590c Author: Peter van der Perk <peter.vanderp...@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 <oliver.hartk...@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 */