Skip to content

Commit

Permalink
drivers: can: mcan: Add CAN statistics
Browse files Browse the repository at this point in the history
Add CAN stats for MCAN driver

Signed-off-by: Grant Ramsay <gramsay@enphaseenergy.com>
  • Loading branch information
gramsay0 committed Sep 18, 2023
1 parent a4de2eb commit cf64b20
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 4 deletions.
75 changes: 71 additions & 4 deletions drivers/can/can_mcan.c
Expand Up @@ -524,13 +524,67 @@ static void can_mcan_tx_event_handler(const struct device *dev)
}
}

#if CONFIG_CAN_STATS
static void can_mcan_lec_update_stats(const struct device *dev, uint32_t lec)
{
switch (lec) {
case CAN_MCAN_PSR_LEC_STUFF_ERROR:
CAN_STATS_STUFF_ERROR_INC(dev);
break;
case CAN_MCAN_PSR_LEC_FORM_ERROR:
CAN_STATS_FORM_ERROR_INC(dev);
break;
case CAN_MCAN_PSR_LEC_ACK_ERROR:
CAN_STATS_ACK_ERROR_INC(dev);
break;
case CAN_MCAN_PSR_LEC_BIT1_ERROR:
CAN_STATS_BIT1_ERROR_INC(dev);
break;
case CAN_MCAN_PSR_LEC_BIT0_ERROR:
CAN_STATS_BIT0_ERROR_INC(dev);
break;
case CAN_MCAN_PSR_LEC_CRC_ERROR:
CAN_STATS_CRC_ERROR_INC(dev);
break;
case CAN_MCAN_PSR_LEC_NO_ERROR:
case CAN_MCAN_PSR_LEC_NO_CHANGE:
default:
break;
}
}

static void can_mcan_psr_update_stats(const struct device *dev, uint32_t psr_reg)
{
/* Reading the lower byte of the PSR register clears the protocol last
* error codes (LEC). To avoid missing errors, this function should be
* called whenever the PSR register is read.
*/
/* TODO: Protocol Exception Event (PXE) not working...
* if ((psr_reg & CAN_MCAN_PSR_PXE) != 0U)
*/
{
/* A protocol error has occurred since the last read, update stats */
uint32_t lec;

lec = FIELD_GET(CAN_MCAN_PSR_LEC, psr_reg);
can_mcan_lec_update_stats(dev, lec);
#ifdef CONFIG_CAN_FD_MODE
lec = FIELD_GET(CAN_MCAN_PSR_DLEC, psr_reg);
can_mcan_lec_update_stats(dev, lec);
#endif
}
}
#else
#define can_mcan_psr_update_stats(dev, psr_reg)
#endif

void can_mcan_line_0_isr(const struct device *dev)
{
const uint32_t events = CAN_MCAN_IR_BO | CAN_MCAN_IR_EP | CAN_MCAN_IR_EW |
CAN_MCAN_IR_TEFN | CAN_MCAN_IR_TEFL | CAN_MCAN_IR_ARA |
CAN_MCAN_IR_MRAF;
CAN_MCAN_IR_MRAF | CAN_MCAN_IR_PEA | CAN_MCAN_IR_PED;
struct can_mcan_data *data = dev->data;
uint32_t ir;
uint32_t ir, reg;
int err;

err = can_mcan_read_reg(dev, CAN_MCAN_IR, &ir);
Expand Down Expand Up @@ -562,10 +616,19 @@ void can_mcan_line_0_isr(const struct device *dev)
LOG_ERR("Access to reserved address");
}

if (ir & CAN_MCAN_IR_MRAF) {
if ((ir & CAN_MCAN_IR_MRAF) != 0U) {
LOG_ERR("Message RAM access failure");
}

if ((ir & (CAN_MCAN_IR_PEA | CAN_MCAN_IR_PED)) != 0U) {
LOG_WRN("Protocol Error");
/* Read and update protocol error stats */
err = can_mcan_read_reg(dev, CAN_MCAN_PSR, &reg);
if (err == 0) {
can_mcan_psr_update_stats(dev, reg);
}
}

err = can_mcan_read_reg(dev, CAN_MCAN_IR, &ir);
if (err != 0) {
return;
Expand Down Expand Up @@ -739,10 +802,12 @@ void can_mcan_line_1_isr(const struct device *dev)

if ((ir & CAN_MCAN_IR_RF0L) != 0U) {
LOG_ERR("Message lost on FIFO0");
CAN_STATS_RX_OVERRUN_INC(dev);
}

if ((ir & CAN_MCAN_IR_RF1L) != 0U) {
LOG_ERR("Message lost on FIFO1");
CAN_STATS_RX_OVERRUN_INC(dev);
}

err = can_mcan_read_reg(dev, CAN_MCAN_IR, &ir);
Expand All @@ -764,6 +829,7 @@ int can_mcan_get_state(const struct device *dev, enum can_state *state,
if (err != 0) {
return err;
}
can_mcan_psr_update_stats(dev, reg);

if (!data->started) {
*state = CAN_STATE_STOPPED;
Expand Down Expand Up @@ -881,6 +947,7 @@ int can_mcan_send(const struct device *dev, const struct can_frame *frame, k_tim
if (err != 0) {
return err;
}
can_mcan_psr_update_stats(dev, reg);

if ((reg & CAN_MCAN_PSR_BO) != 0U) {
return -ENETUNREACH;
Expand Down Expand Up @@ -1455,7 +1522,7 @@ int can_mcan_init(const struct device *dev)

reg = CAN_MCAN_IE_BOE | CAN_MCAN_IE_EWE | CAN_MCAN_IE_EPE | CAN_MCAN_IE_MRAFE |
CAN_MCAN_IE_TEFLE | CAN_MCAN_IE_TEFNE | CAN_MCAN_IE_RF0NE | CAN_MCAN_IE_RF1NE |
CAN_MCAN_IE_RF0LE | CAN_MCAN_IE_RF1LE;
CAN_MCAN_IE_RF0LE | CAN_MCAN_IE_RF1LE | CAN_MCAN_IE_PEAE | CAN_MCAN_IE_PEDE;

err = can_mcan_write_reg(dev, CAN_MCAN_IE, reg);
if (err != 0) {
Expand Down
9 changes: 9 additions & 0 deletions include/zephyr/drivers/can/can_mcan.h
Expand Up @@ -127,6 +127,15 @@
#define CAN_MCAN_PSR_ACT GENMASK(4, 3)
#define CAN_MCAN_PSR_LEC GENMASK(2, 0)

#define CAN_MCAN_PSR_LEC_NO_ERROR 0
#define CAN_MCAN_PSR_LEC_STUFF_ERROR 1
#define CAN_MCAN_PSR_LEC_FORM_ERROR 2
#define CAN_MCAN_PSR_LEC_ACK_ERROR 3
#define CAN_MCAN_PSR_LEC_BIT1_ERROR 4
#define CAN_MCAN_PSR_LEC_BIT0_ERROR 5
#define CAN_MCAN_PSR_LEC_CRC_ERROR 6
#define CAN_MCAN_PSR_LEC_NO_CHANGE 7

/* Transmitter Delay Compensation register */
#define CAN_MCAN_TDCR 0x048
#define CAN_MCAN_TDCR_TDCO GENMASK(14, 8)
Expand Down

0 comments on commit cf64b20

Please sign in to comment.