diff --git a/src/freertos_drivers/st/Stm32Can.cxx b/src/freertos_drivers/st/Stm32Can.cxx index d86bff4f0..05dba02ee 100644 --- a/src/freertos_drivers/st/Stm32Can.cxx +++ b/src/freertos_drivers/st/Stm32Can.cxx @@ -44,72 +44,141 @@ #if defined (STM32F072xB) || defined (STM32F091xC) #include "stm32f0xx_hal_cortex.h" -#define CAN_IRQN CEC_CAN_IRQn - +#define CAN1_IRQN CEC_CAN_IRQn +#define CAN1 CAN #define CAN_CLOCK cpu_clock_hz #elif defined (STM32F103xB) #include "stm32f1xx_hal_cortex.h" #define SPLIT_INT -#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 CAN1_TX_IRQN USB_HP_CAN1_TX_IRQn +#define CAN1_IRQN CAN1_TX_IRQN +#define CAN1_SECOND_IRQN USB_LP_CAN1_RX0_IRQn +#define CAN1_THIRD_IRQN CAN1_SCE_IRQn + +#ifdef CAN2 +#define CAN2_TX_IRQN USB_HP_CAN2_TX_IRQn +#define CAN2_IRQN CAN2_TX_IRQN +#define CAN2_SECOND_IRQN USB_LP_CAN2_RX0_IRQn +#define CAN2_THIRD_IRQN CAN2_SCE_IRQn +#endif + #define CAN_CLOCK (cm3_cpu_clock_hz >> 1) #elif defined (STM32F303xC) || defined (STM32F303xE) #include "stm32f3xx_hal_cortex.h" #define SPLIT_INT -#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 CAN_SCE_IRQn +#define CAN1_TX_IRQN USB_HP_CAN_TX_IRQn +#define CAN1_IRQN CAN1_TX_IRQN +#define CAN1_SECOND_IRQN USB_LP_CAN_RX0_IRQn +#define CAN1_THIRD_IRQN CAN_SCE_IRQn +#define CAN1 CAN #define CAN_CLOCK (cm3_cpu_clock_hz >> 1) #elif defined (STM32L431xx) || defined (STM32L432xx) #include "stm32l4xx_hal_cortex.h" #define SPLIT_INT -#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 CAN1_TX_IRQN CAN1_TX_IRQn +#define CAN1_IRQN CAN1_TX_IRQN +#define CAN1_SECOND_IRQN CAN1_RX0_IRQn +#define CAN1_THIRD_IRQN CAN1_SCE_IRQn #define CAN_CLOCK (cm3_cpu_clock_hz) +#ifdef CAN2 +#define CAN2_TX_IRQN CAN2_TX_IRQn +#define CAN2_IRQN CAN2_TX_IRQN +#define CAN2_SECOND_IRQN CAN2_RX0_IRQn +#define CAN2_THIRD_IRQN CAN2_SCE_IRQn +#endif + #elif defined (STM32F767xx) #include "stm32f7xx_hal_cortex.h" #define SPLIT_INT -#define CAN CAN1 -#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 CAN1_TX_IRQN CAN1_TX_IRQn +#define CAN1_IRQN CAN1_TX_IRQN +#define CAN1_SECOND_IRQN CAN1_RX0_IRQn +#define CAN1_THIRD_IRQN CAN1_SCE_IRQn #define CAN_CLOCK (cm3_cpu_clock_hz >> 2) // 54 MHz, sysclk/4 +#ifdef CAN2 +#define CAN2_TX_IRQN CAN2_TX_IRQn +#define CAN2_IRQN CAN2_TX_IRQN +#define CAN2_SECOND_IRQN CAN2_RX0_IRQn +#define CAN2_THIRD_IRQN CAN2_SCE_IRQn +#endif + +#ifdef CAN3 +#define CAN3_TX_IRQN CAN3_TX_IRQn +#define CAN3_IRQN CAN3_TX_IRQN +#define CAN3_SECOND_IRQN CAN3_RX0_IRQn +#define CAN3_THIRD_IRQN CAN3_SCE_IRQn +#endif + #else #error Dont know what STM32 chip you have. #endif -Stm32Can *Stm32Can::instances[1] = {NULL}; +Stm32Can *Stm32Can::instances[MAXCANIFS] = {NULL,NULL,NULL}; /** Constructor. * @param name name of this device instance in the file system */ -Stm32Can::Stm32Can(const char *name) +Stm32Can::Stm32Can(const char *name, uint8_t index) : Can(name) , state_(CAN_STATE_STOPPED) { - /* only one instance allowed */ - HASSERT(instances[0] == NULL); +#if defined(CAN3) + HASSERT(index < 3); +#elif defined(CAN2) + HASSERT(index < 2); +#else + HASSERT(index < 1); +#endif + + /* only one instance per interface allowed */ + HASSERT(instances[index] == NULL); - instances[0] = this; + instances[index] = this; + switch (index) + { + case 0: /* CAN1... */ + can_ = CAN1; + can_irqn_ = CAN1_IRQN; +#ifdef SPLIT_INT + can_second_irqn_ = CAN1_SECOND_IRQN; + can_third_irqn_ = CAN1_THIRD_IRQN; +#endif + break; +#ifdef CAN2 + case 1: /* CAN2... */ + can_ = CAN2; + can_irqn_ = CAN2_IRQN; +#ifdef SPLIT_INT + can_second_irqn_ = CAN2_SECOND_IRQN; + can_third_irqn_ = CAN2_THIRD_IRQN; +#endif + break; +#endif +#ifdef CAN3 + case 2: /* CAN3... */ + can_ = CAN3; + can_irqn_ = CAN3_IRQN; +#ifdef SPLIT_INT + can_second_irqn_ = CAN3_SECOND_IRQN; + can_third_irqn_ = CAN3_THIRD_IRQN; +#endif + break; +#endif + default: + break; + } /* should already be disabled, but just in case */ - HAL_NVIC_DisableIRQ(CAN_IRQN); + HAL_NVIC_DisableIRQ(can_irqn_); #if defined (STM32F030x6) || defined (STM32F031x6) || defined (STM32F038xx) \ || defined (STM32F030x8) || defined (STM32F030xC) || defined (STM32F042x6) \ @@ -121,13 +190,13 @@ Stm32Can::Stm32Can(const char *name) /* The priority of CAN interrupt is as high as possible while maintaining * FreeRTOS compatibility. */ - SetInterruptPriority(CAN_IRQN, configKERNEL_INTERRUPT_PRIORITY); + SetInterruptPriority(can_irqn_, configKERNEL_INTERRUPT_PRIORITY); #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); + 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 } @@ -152,7 +221,7 @@ int Stm32Can::ioctl(File *file, unsigned long int key, unsigned long data) void Stm32Can::enable() { /* disable sleep, enter init mode */ - CAN->MCR = CAN_MCR_INRQ; + can_->MCR = CAN_MCR_INRQ; /* Time triggered tranmission off * Bus off state is left automatically @@ -161,40 +230,40 @@ void Stm32Can::enable() * receive FIFO not locked on overrun * TX FIFO mode on */ - CAN->MCR |= (CAN_MCR_ABOM | CAN_MCR_TXFP); + can_->MCR |= (CAN_MCR_ABOM | CAN_MCR_TXFP); /* Setup timing. * 125,000 Kbps = 8 usec/bit */ - CAN->BTR = (CAN_BS1_5TQ | CAN_BS2_2TQ | CAN_SJW_1TQ | + can_->BTR = (CAN_BS1_5TQ | CAN_BS2_2TQ | CAN_SJW_1TQ | ((CAN_CLOCK / 1000000) - 1)); /* enter normal mode */ - CAN->MCR &= ~CAN_MCR_INRQ; + can_->MCR &= ~CAN_MCR_INRQ; /* Enter filter initialization mode. Filter 0 will be used as a single * 32-bit filter, ID Mask Mode, we accept everything, no mask. */ - CAN->FMR |= CAN_FMR_FINIT; - CAN->FM1R = 0; - CAN->FS1R = 0x000000001; - CAN->FFA1R = 0; - CAN->sFilterRegister[0].FR1 = 0; - CAN->sFilterRegister[0].FR2 = 0; + can_->FMR |= CAN_FMR_FINIT; + can_->FM1R = 0; + can_->FS1R = 0x000000001; + can_->FFA1R = 0; + can_->sFilterRegister[0].FR1 = 0; + can_->sFilterRegister[0].FR2 = 0; /* Activeate filter and exit initialization mode. */ - CAN->FA1R = 0x000000001; - CAN->FMR &= ~CAN_FMR_FINIT; + can_->FA1R = 0x000000001; + can_->FMR &= ~CAN_FMR_FINIT; state_ = CAN_STATE_ACTIVE; /* enable interrupts */ - 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); + 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); + HAL_NVIC_EnableIRQ(can_second_irqn_); + HAL_NVIC_EnableIRQ(can_third_irqn_); #endif } @@ -202,17 +271,17 @@ void Stm32Can::enable() */ void Stm32Can::disable() { - HAL_NVIC_DisableIRQ(CAN_IRQN); + HAL_NVIC_DisableIRQ(can_irqn_); #ifdef SPLIT_INT - HAL_NVIC_DisableIRQ(CAN_SECOND_IRQN); - HAL_NVIC_DisableIRQ(CAN_THIRD_IRQN); + HAL_NVIC_DisableIRQ(can_second_irqn_); + HAL_NVIC_DisableIRQ(can_third_irqn_); #endif - CAN->IER = 0; + can_->IER = 0; state_ = CAN_STATE_STOPPED; /* disable sleep, enter init mode */ - CAN->MCR = CAN_MCR_INRQ; + can_->MCR = CAN_MCR_INRQ; } /* Try and transmit a message. @@ -224,8 +293,8 @@ void Stm32Can::tx_msg() // workaround because the STM32 CAN controller can get stuck in this state // and never get to bus off if the TX attempts end up with no-ack (meaning // the controller is alone on the bus). - if ((CAN->ESR & CAN_ESR_EPVF) && ((CAN->ESR & CAN_ESR_LEC_Msk) != 0) && - ((CAN->TSR & (CAN_TSR_TME0 | CAN_TSR_TME1 | CAN_TSR_TME2)) == 0)) + if ((can_->ESR & CAN_ESR_EPVF) && ((can_->ESR & CAN_ESR_LEC_Msk) != 0) && + ((can_->TSR & (CAN_TSR_TME0 | CAN_TSR_TME1 | CAN_TSR_TME2)) == 0)) { txBuf->flush(); txBuf->signal_condition(); @@ -241,17 +310,17 @@ void Stm32Can::tx_msg() for (i = 0; i < msg_count; ++i, ++can_frame) { volatile CAN_TxMailBox_TypeDef *mailbox; - if (CAN->TSR & CAN_TSR_TME0) + if (can_->TSR & CAN_TSR_TME0) { - mailbox = CAN->sTxMailBox + 0; + mailbox = can_->sTxMailBox + 0; } - else if (CAN->TSR & CAN_TSR_TME1) + else if (can_->TSR & CAN_TSR_TME1) { - mailbox = CAN->sTxMailBox + 1; + mailbox = can_->sTxMailBox + 1; } - else if (CAN->TSR & CAN_TSR_TME2) + else if (can_->TSR & CAN_TSR_TME2) { - mailbox = CAN->sTxMailBox + 2; + mailbox = can_->sTxMailBox + 2; } else { @@ -296,7 +365,7 @@ void Stm32Can::tx_msg() } /* enable transmit interrupt */ - CAN->IER |= CAN_IER_TMEIE; + can_->IER |= CAN_IER_TMEIE; } /** Handle an interrupt. @@ -305,26 +374,26 @@ void Stm32Can::rx_interrupt_handler() { unsigned msg_receive_count = 0; - while (CAN->RF0R & CAN_RF0R_FMP0) + while (can_->RF0R & CAN_RF0R_FMP0) { /* rx data received */ struct can_frame *can_frame; size_t msg_count = rxBuf->data_write_pointer(&can_frame); if (msg_count) { - if (CAN->sFIFOMailBox[0].RIR & CAN_RI0R_IDE) + if (can_->sFIFOMailBox[0].RIR & CAN_RI0R_IDE) { /* extended frame */ - can_frame->can_id = CAN->sFIFOMailBox[0].RIR >> 3; + can_frame->can_id = can_->sFIFOMailBox[0].RIR >> 3; can_frame->can_eff = 1; } else { /* standard frame */ - can_frame->can_id = CAN->sFIFOMailBox[0].RIR >> 21; + can_frame->can_id = can_->sFIFOMailBox[0].RIR >> 21; can_frame->can_eff = 0; } - if (CAN->sFIFOMailBox[0].RIR & CAN_RI0R_RTR) + if (can_->sFIFOMailBox[0].RIR & CAN_RI0R_RTR) { /* remote frame */ can_frame->can_rtr = 1; @@ -334,15 +403,15 @@ void Stm32Can::rx_interrupt_handler() { /* data frame */ can_frame->can_rtr = 0; - can_frame->can_dlc = CAN->sFIFOMailBox[0].RDTR & CAN_RDT0R_DLC; - can_frame->data[0] = (CAN->sFIFOMailBox[0].RDLR >> 0) & 0xFF; - can_frame->data[1] = (CAN->sFIFOMailBox[0].RDLR >> 8) & 0xFF; - can_frame->data[2] = (CAN->sFIFOMailBox[0].RDLR >> 16) & 0xFF; - can_frame->data[3] = (CAN->sFIFOMailBox[0].RDLR >> 24) & 0xFF; - can_frame->data[4] = (CAN->sFIFOMailBox[0].RDHR >> 0) & 0xFF; - can_frame->data[5] = (CAN->sFIFOMailBox[0].RDHR >> 8) & 0xFF; - can_frame->data[6] = (CAN->sFIFOMailBox[0].RDHR >> 16) & 0xFF; - can_frame->data[7] = (CAN->sFIFOMailBox[0].RDHR >> 24) & 0xFF; + can_frame->can_dlc = can_->sFIFOMailBox[0].RDTR & CAN_RDT0R_DLC; + can_frame->data[0] = (can_->sFIFOMailBox[0].RDLR >> 0) & 0xFF; + can_frame->data[1] = (can_->sFIFOMailBox[0].RDLR >> 8) & 0xFF; + can_frame->data[2] = (can_->sFIFOMailBox[0].RDLR >> 16) & 0xFF; + can_frame->data[3] = (can_->sFIFOMailBox[0].RDLR >> 24) & 0xFF; + can_frame->data[4] = (can_->sFIFOMailBox[0].RDHR >> 0) & 0xFF; + can_frame->data[5] = (can_->sFIFOMailBox[0].RDHR >> 8) & 0xFF; + can_frame->data[6] = (can_->sFIFOMailBox[0].RDHR >> 16) & 0xFF; + can_frame->data[7] = (can_->sFIFOMailBox[0].RDHR >> 24) & 0xFF; } } else @@ -350,7 +419,7 @@ void Stm32Can::rx_interrupt_handler() ++overrunCount; } /* release FIFO */ - CAN->RF0R |= CAN_RF0R_RFOM0; + can_->RF0R |= CAN_RF0R_RFOM0; ++msg_receive_count; } @@ -365,7 +434,7 @@ void Stm32Can::rx_interrupt_handler() void Stm32Can::tx_interrupt_handler() { - if (CAN->TSR & (CAN_TSR_RQCP0 | CAN_TSR_RQCP1 | CAN_TSR_RQCP2)) + if (can_->TSR & (CAN_TSR_RQCP0 | CAN_TSR_RQCP1 | CAN_TSR_RQCP2)) { /* transmit request completed, should be able to send another */ struct can_frame *can_frame; @@ -379,17 +448,17 @@ void Stm32Can::tx_interrupt_handler() for (i = 0; i < msg_count; ++i, ++can_frame) { volatile CAN_TxMailBox_TypeDef *mailbox; - if (CAN->TSR & CAN_TSR_TME0) + if (can_->TSR & CAN_TSR_TME0) { - mailbox = CAN->sTxMailBox + 0; + mailbox = can_->sTxMailBox + 0; } - else if (CAN->TSR & CAN_TSR_TME1) + else if (can_->TSR & CAN_TSR_TME1) { - mailbox = CAN->sTxMailBox + 1; + mailbox = can_->sTxMailBox + 1; } - else if (CAN->TSR & CAN_TSR_TME2) + else if (can_->TSR & CAN_TSR_TME2) { - mailbox = CAN->sTxMailBox + 2; + mailbox = can_->sTxMailBox + 2; } else { @@ -431,7 +500,7 @@ void Stm32Can::tx_interrupt_handler() else { /* no more data left to transmit */ - CAN->IER &= ~CAN_IER_TMEIE; + can_->IER &= ~CAN_IER_TMEIE; } txBuf->signal_condition_from_isr(); state_ = CAN_STATE_ACTIVE; @@ -443,26 +512,26 @@ void Stm32Can::tx_interrupt_handler() */ void Stm32Can::sce_interrupt_handler() { - if (CAN->MSR & CAN_MSR_ERRI) + if (can_->MSR & CAN_MSR_ERRI) { /* error interrupt has occured */ - CAN->MSR |= CAN_MSR_ERRI; // clear flag + can_->MSR |= CAN_MSR_ERRI; // clear flag bool cancel_queue = false; - if (CAN->ESR & CAN_ESR_EWGF) + if (can_->ESR & CAN_ESR_EWGF) { /* error warning condition */ state_ = CAN_STATE_BUS_WARNING; } - if (CAN->ESR & CAN_ESR_EPVF) + if (can_->ESR & CAN_ESR_EPVF) { /* error passive condition */ ++softErrorCount; state_ = CAN_STATE_BUS_PASSIVE; cancel_queue = true; } - if (CAN->ESR & CAN_ESR_BOFF) + if (can_->ESR & CAN_ESR_BOFF) { /* bus off error condition */ ++busOffCount; @@ -471,10 +540,10 @@ void Stm32Can::sce_interrupt_handler() } if (cancel_queue) { - CAN->TSR |= CAN_TSR_ABRQ2; - CAN->TSR |= CAN_TSR_ABRQ1; - CAN->TSR |= CAN_TSR_ABRQ0; - CAN->IER &= ~CAN_IER_TMEIE; + 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(); } @@ -520,6 +589,24 @@ void can1_sce_interrupt_handler(void) Stm32Can::instances[0]->sce_interrupt_handler(); } +#ifdef CAN2 +void usb_hp_can2_tx_interrupt_handler(void) +{ + Stm32Can::instances[1]->tx_interrupt_handler(); +} + +void usb_lp_can2_rx0_interrupt_handler(void) +{ + Stm32Can::instances[1]->rx_interrupt_handler(); +} + +void can2_sce_interrupt_handler(void) +{ + Stm32Can::instances[1]->sce_interrupt_handler(); +} + +#endif + #elif defined(STM32F767xx) || defined(STM32L431xx) || defined(STM32L432xx) //---------------------------------------------------------------------------- // @@ -542,6 +629,38 @@ void can1_sce_interrupt_handler(void) Stm32Can::instances[0]->sce_interrupt_handler(); } +#ifdef CAN2 +void can2_tx_interrupt_handler(void) +{ + Stm32Can::instances[1]->tx_interrupt_handler(); +} + +void can2_rx0_interrupt_handler(void) +{ + Stm32Can::instances[1]->rx_interrupt_handler(); +} + +void can2_sce_interrupt_handler(void) +{ + Stm32Can::instances[1]->sce_interrupt_handler(); +} +#endif +#ifdef CAN3 +void can3_tx_interrupt_handler(void) +{ + Stm32Can::instances[2]->tx_interrupt_handler(); +} + +void can3_rx0_interrupt_handler(void) +{ + Stm32Can::instances[2]->rx_interrupt_handler(); +} + +void can3_sce_interrupt_handler(void) +{ + Stm32Can::instances[2]->sce_interrupt_handler(); +} +#endif #else #error Dont know what STM32 chip you have. diff --git a/src/freertos_drivers/st/Stm32Can.hxx b/src/freertos_drivers/st/Stm32Can.hxx index fb54c334a..14e2a6c85 100644 --- a/src/freertos_drivers/st/Stm32Can.hxx +++ b/src/freertos_drivers/st/Stm32Can.hxx @@ -45,6 +45,10 @@ #include "stm32f_hal_conf.hxx" +/// Max possible number of CAN ifs across the whole STM32 -- the constructor +/// will calculate the actual max for the specific chip compiling for +#define MAXCANIFS 3 + /** Specialization of CAN driver for LPC17xx and LPC40xx CAN. */ class Stm32Can : public Can @@ -53,7 +57,7 @@ public: /** Constructor. * @param name name of this device instance in the file system */ - Stm32Can(const char *name); + Stm32Can(const char *name, uint8_t index = 0); /** Destructor. */ @@ -69,7 +73,7 @@ public: void sce_interrupt_handler(); /** Instance pointers help us get context from the interrupt handler(s) */ - static Stm32Can *instances[1]; + static Stm32Can *instances[MAXCANIFS]; private: #ifndef ARDUINO @@ -91,11 +95,15 @@ private: static unsigned int intCount; uint8_t state_; ///< present bus state - - /** Default constructor. - */ + + CAN_TypeDef *can_; ///< CAN hardware registers for this instance (defined in the SDK). + IRQn_Type can_irqn_; ///< CAN IRQn for this instance. + IRQn_Type can_second_irqn_; ///< CAN Second IRQn (if used) for this instance. + IRQn_Type can_third_irqn_; ///< CAN Third IRQn (if used) for this instance. + + /** Default constructor. */ Stm32Can(); - + DISALLOW_COPY_AND_ASSIGN(Stm32Can); };