From c2c166cb1c5aa52dc67375addf10db0c08d4b712 Mon Sep 17 00:00:00 2001 From: Stuart Baker Date: Mon, 15 Aug 2022 20:36:56 -0500 Subject: [PATCH 1/7] Add ioctl() for getting the CAN state. --- src/freertos_drivers/st/Stm32Can.cxx | 16 ++++++++++++++++ src/freertos_drivers/st/Stm32Can.hxx | 7 +++++++ 2 files changed, 23 insertions(+) diff --git a/src/freertos_drivers/st/Stm32Can.cxx b/src/freertos_drivers/st/Stm32Can.cxx index b62d25707..446e76156 100644 --- a/src/freertos_drivers/st/Stm32Can.cxx +++ b/src/freertos_drivers/st/Stm32Can.cxx @@ -37,6 +37,8 @@ #include +#include "can_ioctl.h" + #include "stm32f_hal_conf.hxx" #if defined (STM32F072xB) || defined (STM32F091xC) @@ -95,6 +97,7 @@ Stm32Can *Stm32Can::instances[1] = {NULL}; */ Stm32Can::Stm32Can(const char *name) : Can(name) + , state_(CAN_STATE_STOPPED) { /* only one instance allowed */ HASSERT(instances[0] == NULL); @@ -123,6 +126,19 @@ Stm32Can::Stm32Can(const char *name) #endif } +// +// Stm32Can::ioctl() +// +int Stm32Can::ioctl(File *file, unsigned long int key, unsigned long data) +{ + if (key == SIOCGCANSTATE) + { + *((can_state_t*)data) = state_; + return 0; + } + return -EINVAL; +} + /** Enable use of the device. */ void Stm32Can::enable() diff --git a/src/freertos_drivers/st/Stm32Can.hxx b/src/freertos_drivers/st/Stm32Can.hxx index 86812386f..fdcff50de 100644 --- a/src/freertos_drivers/st/Stm32Can.hxx +++ b/src/freertos_drivers/st/Stm32Can.hxx @@ -70,6 +70,13 @@ public: static Stm32Can *instances[1]; private: + /// Request an ioctl transaction. + /// @param file file reference for this device + /// @param key ioctl key + /// @param data key data + /// @return >= 0 upon success, -errno upon failure + int ioctl(File *file, unsigned long int key, unsigned long data) override; + void enable() override; /**< function to enable device */ void disable() override; /**< function to disable device */ void tx_msg() override; /**< function to try and transmit a message */ From 8e044e1327616eaec4a0155681f920d620ed40ca Mon Sep 17 00:00:00 2001 From: Stuart Baker Date: Mon, 15 Aug 2022 20:37:08 -0500 Subject: [PATCH 2/7] Properly handle bus error/off states. --- src/freertos_drivers/st/Stm32Can.cxx | 88 ++++++++++++++++++++-------- src/freertos_drivers/st/Stm32Can.hxx | 2 + 2 files changed, 65 insertions(+), 25 deletions(-) diff --git a/src/freertos_drivers/st/Stm32Can.cxx b/src/freertos_drivers/st/Stm32Can.cxx index 446e76156..e74681c25 100644 --- a/src/freertos_drivers/st/Stm32Can.cxx +++ b/src/freertos_drivers/st/Stm32Can.cxx @@ -55,6 +55,7 @@ #define CAN_TX_IRQN USB_HP_CAN1_TX_IRQn #define CAN_IRQN CAN_TX_IRQN #define CAN_SECOND_IRQN USB_LP_CAN1_RX0_IRQn +#define CAN_THIRD_IRQN CAN1_SCE_IRQn #define CAN CAN1 #define CAN_CLOCK (cm3_cpu_clock_hz >> 1) @@ -65,6 +66,7 @@ #define CAN_TX_IRQN USB_HP_CAN_TX_IRQn #define CAN_IRQN CAN_TX_IRQN #define CAN_SECOND_IRQN USB_LP_CAN_RX0_IRQn +#define CAN_THIRD_IRQN CAN1_SCE_IRQn #define CAN_CLOCK (cm3_cpu_clock_hz >> 1) #elif defined (STM32L431xx) || defined (STM32L432xx) @@ -74,6 +76,7 @@ #define CAN_TX_IRQN CAN1_TX_IRQn #define CAN_IRQN CAN_TX_IRQN #define CAN_SECOND_IRQN CAN1_RX0_IRQn +#define CAN_THIRD_IRQN CAN1_SCE_IRQn #define CAN_CLOCK (cm3_cpu_clock_hz) #elif defined (STM32F767xx) @@ -84,6 +87,7 @@ #define CAN_TX_IRQN CAN1_TX_IRQn #define CAN_IRQN CAN_TX_IRQN #define CAN_SECOND_IRQN CAN1_RX0_IRQn +#define CAN_THIRD_IRQN CAN1_SCE_IRQn #define CAN_CLOCK (cm3_cpu_clock_hz >> 2) // 54 MHz, sysclk/4 #else @@ -178,11 +182,15 @@ void Stm32Can::enable() CAN->FA1R = 0x000000001; CAN->FMR &= ~CAN_FMR_FINIT; + state_ = CAN_STATE_ACTIVE; + /* enable interrupts */ - CAN->IER = (/*CAN_IER_ERRIE |*/ CAN_IER_BOFIE | CAN_IER_FMPIE0); + CAN->IER = (CAN_IER_BOFIE | CAN_IER_EPVIE | CAN_IER_EWGIE); // errors + CAN->IER |= (CAN_IER_ERRIE | CAN_IER_FMPIE0); // error + receive HAL_NVIC_EnableIRQ(CAN_IRQN); #ifdef SPLIT_INT HAL_NVIC_EnableIRQ(CAN_SECOND_IRQN); + HAL_NVIC_EnableIRQ(CAN_THIRD_IRQN); #endif } @@ -193,9 +201,12 @@ void Stm32Can::disable() HAL_NVIC_DisableIRQ(CAN_IRQN); #ifdef SPLIT_INT HAL_NVIC_DisableIRQ(CAN_SECOND_IRQN); + HAL_NVIC_DisableIRQ(CAN_THIRD_IRQN); #endif CAN->IER = 0; + state_ = CAN_STATE_STOPPED; + /* disable sleep, enter init mode */ CAN->MCR = CAN_MCR_INRQ; } @@ -277,30 +288,6 @@ void Stm32Can::rx_interrupt_handler() { unsigned msg_receive_count = 0; - if (CAN->ESR & CAN_ESR_BOFF) - { - /* bus off error condition */ - CAN->TSR |= CAN_TSR_ABRQ2; - CAN->TSR |= CAN_TSR_ABRQ1; - CAN->TSR |= CAN_TSR_ABRQ0; - CAN->IER &= ~CAN_IER_TMEIE; - txBuf->flush(); - txBuf->signal_condition_from_isr(); - } -#if 0 - if (CAN->MSR & CAN_MSR_ERRI) - { - /* error condition */ - CAN->TSR |= CAN_TSR_ABRQ2; - CAN->TSR |= CAN_TSR_ABRQ1; - CAN->TSR |= CAN_TSR_ABRQ0; - CAN->IER &= ~CAN_IER_TMEIE; - CAN->MSR &= ~CAN_MSR_ERRI; - txBuf->flush(); - txBuf->signal_condition_from_isr(); - ++softErrorCount; - } -#endif while (CAN->RF0R & CAN_RF0R_FMP0) { /* rx data received */ @@ -355,6 +342,7 @@ void Stm32Can::rx_interrupt_handler() /* advance the "zero copy" buffer by the number of messages received */ rxBuf->advance(msg_receive_count); rxBuf->signal_condition_from_isr(); + state_ = CAN_STATE_ACTIVE; } } @@ -429,9 +417,48 @@ void Stm32Can::tx_interrupt_handler() CAN->IER &= ~CAN_IER_TMEIE; } txBuf->signal_condition_from_isr(); + state_ = CAN_STATE_ACTIVE; } } +/* + * Stm32Can::sce_interrupt_handler() + */ +void Stm32Can::sce_interrupt_handler() +{ + if (CAN->MSR & CAN_MSR_ERRI) + { + /* error interrupt has occured */ + CAN->MSR |= CAN_MSR_ERRI; // clear flag + + if (CAN->ESR & CAN_ESR_BOFF) + { + /* bus off error condition */ + CAN->TSR |= CAN_TSR_ABRQ2; + CAN->TSR |= CAN_TSR_ABRQ1; + CAN->TSR |= CAN_TSR_ABRQ0; + CAN->IER &= ~CAN_IER_TMEIE; + txBuf->flush(); + txBuf->signal_condition_from_isr(); + ++busOffCount; + state_ = CAN_STATE_BUS_OFF; + CAN->ESR &= ~CAN_ESR_BOFF; + } + else if (CAN->ESR & CAN_ESR_EPVF) + { + /* error passive condition */ + ++softErrorCount; + state_ = CAN_STATE_BUS_PASSIVE; + CAN->ESR &= ~CAN_ESR_EPVF; + } + else if (CAN->ESR & CAN_ESR_EWGF) + { + /* error warning condition */ + state_ = CAN_STATE_BUS_WARNING; + CAN->ESR &= ~CAN_ESR_EWGF; + } + } +} extern "C" { /** This is the interrupt handler for the can device. @@ -440,6 +467,7 @@ extern "C" { #if defined (STM32F072xB) || defined (STM32F091xC) void cec_can_interrupt_handler(void) { + Stm32Can::instances[0]->sce_interrupt_handler(); Stm32Can::instances[0]->rx_interrupt_handler(); Stm32Can::instances[0]->tx_interrupt_handler(); } @@ -455,6 +483,11 @@ void usb_lp_can1_rx0_interrupt_handler(void) Stm32Can::instances[0]->rx_interrupt_handler(); } +void can1_sce_interrupt_handler(void) +{ + Stm32Can::instances[0]->sce_interrupt_handler(); +} + #elif defined(STM32F767xx) || defined(STM32L431xx) || defined(STM32L432xx) void can1_tx_interrupt_handler(void) @@ -467,6 +500,11 @@ void can1_rx0_interrupt_handler(void) Stm32Can::instances[0]->rx_interrupt_handler(); } +void can1_sce_interrupt_handler(void) +{ + Stm32Can::instances[0]->sce_interrupt_handler(); +} + #else #error Dont know what STM32 chip you have. #endif diff --git a/src/freertos_drivers/st/Stm32Can.hxx b/src/freertos_drivers/st/Stm32Can.hxx index fdcff50de..011efa2ab 100644 --- a/src/freertos_drivers/st/Stm32Can.hxx +++ b/src/freertos_drivers/st/Stm32Can.hxx @@ -65,6 +65,8 @@ public: void rx_interrupt_handler(); /** Handle an interrupt. */ void tx_interrupt_handler(); + /** Handle an interrupt. */ + void sce_interrupt_handler(); /** Instance pointers help us get context from the interrupt handler(s) */ static Stm32Can *instances[1]; From ad8e2f5e95c6e3c925f546585f08f5c0eb64edc7 Mon Sep 17 00:00:00 2001 From: Stuart Baker Date: Mon, 15 Aug 2022 20:42:56 -0500 Subject: [PATCH 3/7] Change execution priority. --- src/freertos_drivers/st/Stm32Can.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/freertos_drivers/st/Stm32Can.cxx b/src/freertos_drivers/st/Stm32Can.cxx index e74681c25..f762bf935 100644 --- a/src/freertos_drivers/st/Stm32Can.cxx +++ b/src/freertos_drivers/st/Stm32Can.cxx @@ -467,9 +467,9 @@ extern "C" { #if defined (STM32F072xB) || defined (STM32F091xC) void cec_can_interrupt_handler(void) { - Stm32Can::instances[0]->sce_interrupt_handler(); Stm32Can::instances[0]->rx_interrupt_handler(); Stm32Can::instances[0]->tx_interrupt_handler(); + Stm32Can::instances[0]->sce_interrupt_handler(); } #elif defined (STM32F103xB) || defined (STM32F303xC) || defined (STM32F303xE) From 43d4a506192a4d01f639d5ab085321edf09745cf Mon Sep 17 00:00:00 2001 From: Stuart Baker Date: Mon, 15 Aug 2022 20:43:13 -0500 Subject: [PATCH 4/7] Support Arduino. --- src/freertos_drivers/st/Stm32Can.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/freertos_drivers/st/Stm32Can.cxx b/src/freertos_drivers/st/Stm32Can.cxx index f762bf935..f8dadf078 100644 --- a/src/freertos_drivers/st/Stm32Can.cxx +++ b/src/freertos_drivers/st/Stm32Can.cxx @@ -578,6 +578,10 @@ void CAN1_RX0_IRQHandler(void) { Stm32Can::instances[0]->rx_interrupt_handler(); } +void CAN1_SCE_IRQHandler(void) +{ + Stm32Can::instances[0]->sce_interrupt_handler(); +} } // extern "C" #endif From 68e604c67973598f565a33a2814a06498217d805 Mon Sep 17 00:00:00 2001 From: Stuart Baker Date: Mon, 15 Aug 2022 20:44:37 -0500 Subject: [PATCH 5/7] Add SCE interrupt handler call to Common CAN IRQ handler for Arduino. --- src/freertos_drivers/st/Stm32Can.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/freertos_drivers/st/Stm32Can.cxx b/src/freertos_drivers/st/Stm32Can.cxx index f8dadf078..3abd1cbce 100644 --- a/src/freertos_drivers/st/Stm32Can.cxx +++ b/src/freertos_drivers/st/Stm32Can.cxx @@ -569,6 +569,7 @@ void CEC_CAN_IRQHandler(void) { Stm32Can::instances[0]->rx_interrupt_handler(); Stm32Can::instances[0]->tx_interrupt_handler(); + Stm32Can::instances[0]->sce_interrupt_handler(); } void CAN1_TX_IRQHandler(void) { From 3844918fc85c5ea0a11f1097b56cb17915f4cf01 Mon Sep 17 00:00:00 2001 From: Stuart Baker Date: Mon, 15 Aug 2022 20:47:13 -0500 Subject: [PATCH 6/7] Reverse error handling order and make clearing the flags non-exclusive. --- src/freertos_drivers/st/Stm32Can.cxx | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/freertos_drivers/st/Stm32Can.cxx b/src/freertos_drivers/st/Stm32Can.cxx index 3abd1cbce..051a430fd 100644 --- a/src/freertos_drivers/st/Stm32Can.cxx +++ b/src/freertos_drivers/st/Stm32Can.cxx @@ -431,6 +431,19 @@ void Stm32Can::sce_interrupt_handler() /* error interrupt has occured */ CAN->MSR |= CAN_MSR_ERRI; // clear flag + if (CAN->ESR & CAN_ESR_EWGF) + { + /* error warning condition */ + state_ = CAN_STATE_BUS_WARNING; + CAN->ESR &= ~CAN_ESR_EWGF; + } + if (CAN->ESR & CAN_ESR_EPVF) + { + /* error passive condition */ + ++softErrorCount; + state_ = CAN_STATE_BUS_PASSIVE; + CAN->ESR &= ~CAN_ESR_EPVF; + } if (CAN->ESR & CAN_ESR_BOFF) { /* bus off error condition */ @@ -444,19 +457,6 @@ void Stm32Can::sce_interrupt_handler() state_ = CAN_STATE_BUS_OFF; CAN->ESR &= ~CAN_ESR_BOFF; } - else if (CAN->ESR & CAN_ESR_EPVF) - { - /* error passive condition */ - ++softErrorCount; - state_ = CAN_STATE_BUS_PASSIVE; - CAN->ESR &= ~CAN_ESR_EPVF; - } - else if (CAN->ESR & CAN_ESR_EWGF) - { - /* error warning condition */ - state_ = CAN_STATE_BUS_WARNING; - CAN->ESR &= ~CAN_ESR_EWGF; - } } } From 619dfd50698467f0691a177fd5cf49f74a94b943 Mon Sep 17 00:00:00 2001 From: Stuart Baker Date: Tue, 16 Aug 2022 19:23:51 -0500 Subject: [PATCH 7/7] Fix review comments. --- src/freertos_drivers/st/Stm32Can.cxx | 2 ++ src/freertos_drivers/st/Stm32Can.hxx | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/freertos_drivers/st/Stm32Can.cxx b/src/freertos_drivers/st/Stm32Can.cxx index 051a430fd..6f241cb08 100644 --- a/src/freertos_drivers/st/Stm32Can.cxx +++ b/src/freertos_drivers/st/Stm32Can.cxx @@ -126,6 +126,8 @@ Stm32Can::Stm32Can(const char *name) #ifdef SPLIT_INT HAL_NVIC_DisableIRQ(CAN_SECOND_IRQN); SetInterruptPriority(CAN_SECOND_IRQN, configKERNEL_INTERRUPT_PRIORITY); + HAL_NVIC_DisableIRQ(CAN_THIRD_IRQN); + SetInterruptPriority(CAN_THIRD_IRQN, configKERNEL_INTERRUPT_PRIORITY); #endif #endif } diff --git a/src/freertos_drivers/st/Stm32Can.hxx b/src/freertos_drivers/st/Stm32Can.hxx index 011efa2ab..499bbfc2d 100644 --- a/src/freertos_drivers/st/Stm32Can.hxx +++ b/src/freertos_drivers/st/Stm32Can.hxx @@ -88,6 +88,8 @@ private: */ static unsigned int intCount; + uint8_t state_; ///< present bus state + /** Default constructor. */ Stm32Can();