From c105ca4847c9ddd63bac7fdc3c38399cb19faad1 Mon Sep 17 00:00:00 2001 From: Jeroen Hofstee Date: Sun, 21 Aug 2022 11:30:32 +0200 Subject: [PATCH] completely reset the CAN peripheral Make sure the CAN-bus state and associated error counters are also reset in can_enable. Writing to the ESR won't help, only the LEC field is writable, the rest is read-only. The only reported way to make that work is by issuing an RCC reset. In addition, socketcan requires the CAN interface to be in active-error state after open. --- src/can.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/can.c b/src/can.c index 902acd9..aa610ac 100644 --- a/src/can.c +++ b/src/can.c @@ -27,6 +27,30 @@ THE SOFTWARE. #include "can.h" #include "config.h" +// The STM32F0 only has one CAN interface, define it as CAN1 as +// well, so it doesn't need to be handled separately. +#if !defined(CAN1) && defined(CAN) +#define CAN1 CAN +#endif + +// Completely reset the CAN pheriperal, including bus-state and error counters +static void rcc_reset(CAN_TypeDef *instance) +{ +#ifdef CAN1 + if (instance == CAN1) { + __HAL_RCC_CAN1_FORCE_RESET(); + __HAL_RCC_CAN1_RELEASE_RESET(); + } +#endif + +#ifdef CAN2 + if (instance == CAN2) { + __HAL_RCC_CAN2_FORCE_RESET(); + __HAL_RCC_CAN2_RELEASE_RESET(); + } +#endif +} + void can_init(can_data_t *hcan, CAN_TypeDef *instance) { __HAL_RCC_CAN1_CLK_ENABLE(); @@ -99,6 +123,9 @@ void can_enable(can_data_t *hcan, bool loop_back, bool listen_only, bool one_sho while((can->MCR & CAN_MCR_RESET) != 0); // reset bit is set to zero after reset while((can->MSR & CAN_MSR_SLAK) == 0); // should be in sleep mode after reset + // Completely reset while being of the bus + rcc_reset(can); + can->MCR |= CAN_MCR_INRQ ; while((can->MSR & CAN_MSR_INAK) == 0);