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.
This commit is contained in:
Jeroen Hofstee 2022-08-21 11:30:32 +02:00 committed by fenugrec
parent 65cd7d76c9
commit c105ca4847

View File

@ -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);