aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/stm32/fdcan.c49
1 files changed, 47 insertions, 2 deletions
diff --git a/src/stm32/fdcan.c b/src/stm32/fdcan.c
index 5344d26b..8a2d1ab2 100644
--- a/src/stm32/fdcan.c
+++ b/src/stm32/fdcan.c
@@ -1,11 +1,12 @@
// FDCAN support on stm32 chips
//
-// Copyright (C) 2021-2022 Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2021-2025 Kevin O'Connor <kevin@koconnor.net>
// Copyright (C) 2019 Eug Krashtan <eug.krashtan@gmail.com>
// Copyright (C) 2020 Pontus Borg <glpontus@gmail.com>
//
// This file may be distributed under the terms of the GNU GPLv3 license.
+#include "board/irq.h" // irq_save
#include "command.h" // DECL_CONSTANT_STR
#include "generic/armcm_boot.h" // armcm_enable_irq
#include "generic/canbus.h" // canbus_notify_tx
@@ -184,6 +185,38 @@ canhw_set_filter(uint32_t id)
SOC_CAN->CCCR &= ~FDCAN_CCCR_INIT;
}
+static struct {
+ uint32_t rx_error, tx_error;
+} CAN_Errors;
+
+// Report interface status
+void
+canhw_get_status(struct canbus_status *status)
+{
+ irqstatus_t flag = irq_save();
+ uint32_t psr = SOC_CAN->PSR, lec = psr & FDCAN_PSR_LEC_Msk;
+ if (lec && lec != 7) {
+ // Reading PSR clears it - so update state here
+ if (lec >= 3 && lec <= 5)
+ CAN_Errors.tx_error += 1;
+ else
+ CAN_Errors.rx_error += 1;
+ }
+ uint32_t rx_error = CAN_Errors.rx_error, tx_error = CAN_Errors.tx_error;
+ irq_restore(flag);
+
+ status->rx_error = rx_error;
+ status->tx_error = tx_error;
+ if (psr & FDCAN_PSR_BO)
+ status->bus_state = CANBUS_STATE_OFF;
+ else if (psr & FDCAN_PSR_EP)
+ status->bus_state = CANBUS_STATE_PASSIVE;
+ else if (psr & FDCAN_PSR_EW)
+ status->bus_state = CANBUS_STATE_WARN;
+ else
+ status->bus_state = 0;
+}
+
// This function handles CAN global interrupts
void
CAN_IRQHandler(void)
@@ -220,6 +253,18 @@ CAN_IRQHandler(void)
SOC_CAN->IR = FDCAN_IE_TC;
canbus_notify_tx();
}
+ if (ir & (FDCAN_IR_PED | FDCAN_IR_PEA)) {
+ // Bus error
+ uint32_t psr = SOC_CAN->PSR;
+ SOC_CAN->IR = FDCAN_IR_PED | FDCAN_IR_PEA;
+ uint32_t lec = psr & FDCAN_PSR_LEC_Msk;
+ if (lec && lec != 7) {
+ if (lec >= 3 && lec <= 5)
+ CAN_Errors.tx_error += 1;
+ else
+ CAN_Errors.rx_error += 1;
+ }
+ }
}
static inline const uint32_t
@@ -320,6 +365,6 @@ can_init(void)
/*##-3- Configure Interrupts #################################*/
armcm_enable_irq(CAN_IRQHandler, CAN_IT0_IRQn, 1);
SOC_CAN->ILE = FDCAN_ILE_EINT0;
- SOC_CAN->IE = FDCAN_IE_RF0NE | FDCAN_IE_TC;
+ SOC_CAN->IE = FDCAN_IE_RF0NE | FDCAN_IE_TC | FDCAN_IE_PEDE | FDCAN_IE_PEAE;
}
DECL_INIT(can_init);