Skip to content

Commit

Permalink
drivers: can: mcp251xfd: Add can statistics support
Browse files Browse the repository at this point in the history
Adds support for tracking CAN bus errors when CONFIG_CAN_STATS=y

Signed-off-by: Andriy Gelman <[email protected]>
  • Loading branch information
talih0 authored and jhedberg committed Apr 6, 2024
1 parent 20b2c98 commit 8372df0
Showing 1 changed file with 73 additions and 2 deletions.
75 changes: 73 additions & 2 deletions drivers/can/can_mcp251xfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -958,6 +958,7 @@ static int mcp251xfd_handle_ivmif(const struct device *dev)
uint32_t *reg;
struct mcp251xfd_data *dev_data = dev->data;
int ret;
uint32_t tmp;

k_mutex_lock(&dev_data->mutex, K_FOREVER);

Expand All @@ -967,9 +968,9 @@ static int mcp251xfd_handle_ivmif(const struct device *dev)
goto done;
}

*reg = sys_le32_to_cpu(*reg);
tmp = sys_le32_to_cpu(*reg);

if ((*reg & MCP251XFD_REG_BDIAG1_TXBOERR) != 0) {
if ((tmp & MCP251XFD_REG_BDIAG1_TXBOERR) != 0) {
LOG_INF("ivmif bus-off error");
mcp251xfd_reset_tx_fifos(dev, -ENETDOWN);
}
Expand All @@ -978,12 +979,65 @@ static int mcp251xfd_handle_ivmif(const struct device *dev)
reg = mcp251xfd_get_spi_buf_ptr(dev);
reg[0] = 0;
ret = mcp251xfd_write(dev, MCP251XFD_REG_BDIAG1, MCP251XFD_REG_SIZE);
if (ret < 0) {
goto done;
}

/* There's no flag for DACKERR */
if ((tmp & MCP251XFD_REG_BDIAG1_NACKERR) != 0) {
CAN_STATS_ACK_ERROR_INC(dev);
}

if ((tmp & (MCP251XFD_REG_BDIAG1_NBIT0ERR | MCP251XFD_REG_BDIAG1_DBIT0ERR)) != 0) {
CAN_STATS_BIT0_ERROR_INC(dev);
}

if ((tmp & (MCP251XFD_REG_BDIAG1_NBIT1ERR | MCP251XFD_REG_BDIAG1_DBIT1ERR)) != 0) {
CAN_STATS_BIT1_ERROR_INC(dev);
}

if ((tmp & (MCP251XFD_REG_BDIAG1_NCRCERR | MCP251XFD_REG_BDIAG1_DCRCERR)) != 0) {
CAN_STATS_CRC_ERROR_INC(dev);
}

if ((tmp & (MCP251XFD_REG_BDIAG1_NFORMERR | MCP251XFD_REG_BDIAG1_DFORMERR)) != 0) {
CAN_STATS_FORM_ERROR_INC(dev);
}

if ((tmp & (MCP251XFD_REG_BDIAG1_NSTUFERR | MCP251XFD_REG_BDIAG1_DSTUFERR)) != 0) {
CAN_STATS_STUFF_ERROR_INC(dev);
}

done:
k_mutex_unlock(&dev_data->mutex);
return ret;
}

#if defined(CONFIG_CAN_STATS)
static int mcp251xfd_handle_rxovif(const struct device *dev)
{
uint8_t *reg_byte;
struct mcp251xfd_data *dev_data = dev->data;
int ret;

k_mutex_lock(&dev_data->mutex, K_FOREVER);

reg_byte = mcp251xfd_get_spi_buf_ptr(dev);
*reg_byte = 0;

ret = mcp251xfd_write(dev, MCP251XFD_REG_FIFOSTA(MCP251XFD_RX_FIFO_IDX), 1);
if (ret < 0) {
goto done;
}

CAN_STATS_RX_OVERRUN_INC(dev);

done:
k_mutex_unlock(&dev_data->mutex);
return ret;
}
#endif

static void mcp251xfd_handle_interrupts(const struct device *dev)
{
const struct mcp251xfd_config *dev_cfg = dev->config;
Expand Down Expand Up @@ -1064,6 +1118,15 @@ static void mcp251xfd_handle_interrupts(const struct device *dev)
}
}

#if defined(CONFIG_CAN_STATS)
if ((reg_int & MCP251XFD_REG_INT_RXOVIF) != 0) {
ret = mcp251xfd_handle_rxovif(dev);
if (ret < 0) {
LOG_ERR("Error handling RXOVIF [%d]", ret);
}
}
#endif

/* Break from loop if INT pin is inactive */
consecutive_calls++;
ret = gpio_pin_get_dt(&dev_cfg->int_gpio_dt);
Expand Down Expand Up @@ -1156,6 +1219,8 @@ static int mcp251xfd_start(const struct device *dev)

k_mutex_lock(&dev_data->mutex, K_FOREVER);

CAN_STATS_RESET(dev);

ret = mcp251xfd_set_mode_internal(dev, dev_data->next_mcp251xfd_mode);
if (ret < 0) {
LOG_ERR("Failed to set the mode [%d]", ret);
Expand Down Expand Up @@ -1347,6 +1412,9 @@ static inline int mcp251xfd_init_int_reg(const struct device *dev)

tmp = MCP251XFD_REG_INT_RXIE | MCP251XFD_REG_INT_MODIE | MCP251XFD_REG_INT_TEFIE |
MCP251XFD_REG_INT_CERRIE;
#if defined(CONFIG_CAN_STATS)
tmp |= MCP251XFD_REG_INT_RXOVIE;
#endif

*reg = sys_cpu_to_le32(tmp);

Expand Down Expand Up @@ -1388,6 +1456,9 @@ static inline int mcp251xfd_init_rx_fifo(const struct device *dev)
uint32_t tmp;

tmp = MCP251XFD_REG_FIFOCON_TFNRFNIE | MCP251XFD_REG_FIFOCON_FRESET;
#if defined(CONFIG_CAN_STATS)
tmp |= MCP251XFD_REG_FIFOCON_RXOVIE;
#endif
tmp |= FIELD_PREP(MCP251XFD_REG_FIFOCON_FSIZE_MASK, MCP251XFD_RX_FIFO_ITEMS - 1);
tmp |= FIELD_PREP(MCP251XFD_REG_FIFOCON_PLSIZE_MASK,
can_bytes_to_dlc(MCP251XFD_PAYLOAD_SIZE) - 8);
Expand Down

0 comments on commit 8372df0

Please sign in to comment.