From 9eeb8634fc29974f65a35503f2be2a9e761a6f62 Mon Sep 17 00:00:00 2001 From: Frank Benkert Date: Wed, 11 May 2016 07:10:17 -0600 Subject: [PATCH] Improve the CAN error reporting by also report internal device driver errors. --- drivers/can.c | 50 +++++++++++++++++++++++++++++++++++++++++++++ include/nuttx/can.h | 11 +++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/drivers/can.c b/drivers/can.c index 4cca6c0dbb..2454f06c2d 100644 --- a/drivers/can.c +++ b/drivers/can.c @@ -522,6 +522,44 @@ static ssize_t can_read(FAR struct file *filep, FAR char *buffer, /* Interrupts must be disabled while accessing the cd_recv FIFO */ flags = enter_critical_section(); + +#ifdef CONFIG_CAN_ERRORS + /* Check for internal errors */ + + if (dev->cd_error != 0) + { + FAR struct can_msg_s *msg; + + /* Detected an internal driver error. Generate a + * CAN_ERROR_MESSAGE + */ + + if (buflen < CAN_MSGLEN(CAN_ERROR_DLC)) + { + goto return_with_irqdisabled; + } + + msg = (FAR struct can_msg_s *)buffer; + msg->cm_hdr.ch_id = CAN_ERROR_INTERNAL; + msg->cm_hdr.ch_dlc = CAN_ERROR_DLC; + msg->cm_hdr.ch_rtr = 0; + msg->cm_hdr.ch_error = 1; +#ifdef CONFIG_CAN_EXTID + msg->cm_hdr.ch_extid = 0; +#endif + msg->cm_hdr.ch_unused = 0; + memset(&(msg->cm_data), 0, CAN_ERROR_DLC); + msg->cm_data[5] = dev->cd_error; + + /* Reset the error flag */ + + dev->cd_error = 0; + + ret = CAN_MSGLEN(CAN_ERROR_DLC); + goto return_with_irqdisabled; + } +#endif /* CONFIG_CAN_ERRORS */ + while (dev->cd_recv.rx_head == dev->cd_recv.rx_tail) { /* The receive FIFO is empty -- was non-blocking mode selected? */ @@ -540,6 +578,7 @@ static ssize_t can_read(FAR struct file *filep, FAR char *buffer, ret = sem_wait(&dev->cd_recv.rx_sem); } while (ret >= 0 && dev->cd_recv.rx_head == dev->cd_recv.rx_tail); + dev->cd_nrxwaiters--; if (ret < 0) @@ -927,6 +966,9 @@ int can_register(FAR const char *path, FAR struct can_dev_s *dev) dev->cd_ntxwaiters = 0; dev->cd_nrxwaiters = 0; dev->cd_npendrtr = 0; +#ifdef CONFIG_CAN_ERRORS + dev->cd_error = 0; +#endif sem_init(&dev->cd_xmit.tx_sem, 0, 0); sem_init(&dev->cd_recv.rx_sem, 0, 0); @@ -1073,6 +1115,14 @@ int can_receive(FAR struct can_dev_s *dev, FAR struct can_hdr_s *hdr, err = OK; } +#ifdef CONFIG_CAN_ERRORS + else + { + /* Report rx overflow error */ + + dev->cd_error |= CAN_ERROR5_RXOVERFLOW; + } +#endif return err; } diff --git a/include/nuttx/can.h b/include/nuttx/can.h index 6f8b3d72aa..573edd16b2 100644 --- a/include/nuttx/can.h +++ b/include/nuttx/can.h @@ -219,7 +219,8 @@ # define CAN_ERROR_BUSOFF (1 << 6) /* Bit 6: Bus off */ # define CAN_ERROR_BUSERROR (1 << 7) /* Bit 7: Bus error */ # define CAN_ERROR_RESTARTED (1 << 8) /* Bit 8: Controller restarted */ - /* Bits 9-10: Available */ +# define CAN_ERROR_INTERNAL (1 << 9) /* Bit 9: Stack internal error (See CAN_ERROR5_* definitions) */ + /* Bit 10: Available */ /* The remaining definitions described the error report payload that follows the * CAN header. @@ -295,6 +296,11 @@ # define CANL_ERROR4_SHORT2GND 0x40 # define CANL_ERROR4_SHORT2CANH 0x50 +/* Data[5]: Error status of stack internals */ + +# define CAN_ERROR5_UNSPEC 0x00 /* Unspecified error */ +# define CAN_ERROR5_RXOVERFLOW (1 << 0) /* Bit 0: RX buffer overflow */ + #endif /* CONFIG_CAN_ERRORS */ /* CAN filter support ***************************************************************/ @@ -494,6 +500,9 @@ struct can_dev_s uint8_t cd_npendrtr; /* Number of pending RTR messages */ volatile uint8_t cd_ntxwaiters; /* Number of threads waiting to enqueue a message */ volatile uint8_t cd_nrxwaiters; /* Number of threads waiting to receive a message */ +#ifdef CONFIG_CAN_ERRORS + uint8_t cd_error; /* Flags to indicate internal device errors */ +#endif sem_t cd_closesem; /* Locks out new opens while close is in progress */ struct can_txfifo_s cd_xmit; /* Describes transmit FIFO */ struct can_rxfifo_s cd_recv; /* Describes receive FIFO */