SAMV7 MCAN: Add logic to report CAN errors

This commit is contained in:
Gregory Nutt
2015-08-18 08:48:13 -06:00
parent b7d6720a23
commit ff84e67e59
+116
View File
@@ -954,6 +954,7 @@ static bool mcan_txempty(FAR struct can_dev_s *dev);
static bool mcan_dedicated_rxbuffer_available(FAR struct sam_mcan_s *priv,
int bufndx);
#endif
static void mcan_error(FAR struct can_dev_s *dev, uint32_t status);
static void mcan_receive(FAR struct can_dev_s *dev,
FAR uint32_t *rxbuffer, unsigned long nwords);
static void mcan_interrupt(FAR struct can_dev_s *dev);
@@ -2760,6 +2761,108 @@ bool mcan_dedicated_rxbuffer_available(FAR struct sam_mcan_s *priv, int bufndx)
}
#endif
/****************************************************************************
* Name: mcan_error
*
* Description:
* Report a CAN error
*
* Input Parameters:
* dev - CAN-common state data
* status - Interrupt status with error bits set
*
* Returned Value:
* None
*
****************************************************************************/
static void mcan_error(FAR struct can_dev_s *dev, uint32_t status)
{
struct can_hdr_s hdr;
uint16_t errbits;
int ret;
/* Encode error bits */
errbits = 0;
if ((status & (MCAN_INT_ELO | MCAN_INT_EW)) != 0)
{
errbits |= CAN_ERROR_SYSTEM;
}
if ((status & (MCAN_INT_RF0L | MCAN_INT_RF1L)) != 0)
{
errbits |= CAN_ERROR_RXLOST;
}
if ((status & MCAN_INT_TEFL) != 0)
{
errbits |= CAN_ERROR_TXLOST;
}
if ((status & (MCAN_INT_MRAF | MCAN_INT_BO)) != 0)
{
errbits |= CAN_ERROR_ACCESS;
}
if ((status & MCAN_INT_TOO) != 0)
{
errbits |= CAN_ERROR_TIMEOUT;
}
if ((status & MCAN_INT_EP) != 0)
{
errbits |= CAN_ERROR_PASSIVE;
}
if ((status & MCAN_INT_CRCE) != 0)
{
errbits |= CAN_ERROR_CRC;
}
if ((status & MCAN_INT_BE) != 0)
{
errbits |= CAN_ERROR_BIT;
}
if ((status & MCAN_INT_ACKE) != 0)
{
errbits |= CAN_ERROR_ACK;
}
if ((status & MCAN_INT_FOE) != 0)
{
errbits |= CAN_ERROR_FORMAT;
}
if ((status & MCAN_INT_STE) != 0)
{
errbits |= CAN_ERROR_STUFF;
}
if (errbits != 0)
{
/* Format the CAN header for the error report. */
hdr.ch_id = errbits;
hdr.ch_dlc = 0;
hdr.ch_rtr = 0;
hdr.ch_error = 1;
#ifdef CONFIG_CAN_EXTID
hdr.ch_extid = 0;
#endif
hdr.ch_unused = 0;
/* And provide the error report to the upper half logic */
ret = can_receive(dev, &hdr, NULL);
if (ret < 0)
{
canlldbg("ERROR: can_receive failed: %d\n", ret);
}
}
}
/****************************************************************************
* Name: mcan_receive
*
@@ -2892,6 +2995,10 @@ static void mcan_interrupt(FAR struct can_dev_s *dev)
/* Clear the error indications */
mcan_putreg(priv, SAM_MCAN_IR_OFFSET, MCAN_CMNERR_INTS);
/* Report errors */
mcan_error(dev, pending & MCAN_CMNERR_INTS);
handled = true;
}
@@ -2905,6 +3012,10 @@ static void mcan_interrupt(FAR struct can_dev_s *dev)
mcan_putreg(priv, SAM_MCAN_IR_OFFSET, MCAN_TXERR_INTS);
/* Report errors */
mcan_error(dev, pending & MCAN_TXERR_INTS);
/* REVISIT: Will MCAN_INT_TC also be set in the event of
* a transmission error? Each write must conclude with a
* call to man_buffer_release(), whether or not the write
@@ -3003,6 +3114,11 @@ static void mcan_interrupt(FAR struct can_dev_s *dev)
/* Clear the error indications */
mcan_putreg(priv, SAM_MCAN_IR_OFFSET, MCAN_RXERR_INTS);
/* Report errors */
mcan_error(dev, pending & MCAN_TXERR_INTS);
handled = true;
}
/* Clear the RX FIFO1 new message interrupt */