34#if (!defined(ARDUINO)) || defined(ARDUINO_ARCH_STM32)
44#if defined (STM32F072xB) || defined (STM32F091xC)
46#include "stm32f0xx_hal_cortex.h"
47#define CAN_IRQN CEC_CAN_IRQn
49#define CAN_CLOCK cpu_clock_hz
51#elif defined (STM32F103xB)
53#include "stm32f1xx_hal_cortex.h"
55#define CAN_TX_IRQN USB_HP_CAN1_TX_IRQn
56#define CAN_IRQN CAN_TX_IRQN
57#define CAN_SECOND_IRQN USB_LP_CAN1_RX0_IRQn
58#define CAN_THIRD_IRQN CAN1_SCE_IRQn
60#define CAN_CLOCK (cm3_cpu_clock_hz >> 1)
62#elif defined (STM32F303xC) || defined (STM32F303xE)
64#include "stm32f3xx_hal_cortex.h"
66#define CAN_TX_IRQN USB_HP_CAN_TX_IRQn
67#define CAN_IRQN CAN_TX_IRQN
68#define CAN_SECOND_IRQN USB_LP_CAN_RX0_IRQn
69#define CAN_THIRD_IRQN CAN_SCE_IRQn
70#define CAN_CLOCK (cm3_cpu_clock_hz >> 1)
72#elif defined (STM32L431xx) || defined (STM32L432xx)
74#include "stm32l4xx_hal_cortex.h"
76#define CAN_TX_IRQN CAN1_TX_IRQn
77#define CAN_IRQN CAN_TX_IRQN
78#define CAN_SECOND_IRQN CAN1_RX0_IRQn
79#define CAN_THIRD_IRQN CAN1_SCE_IRQn
80#define CAN_CLOCK (cm3_cpu_clock_hz)
82#elif defined (STM32F767xx)
84#include "stm32f7xx_hal_cortex.h"
87#define CAN_TX_IRQN CAN1_TX_IRQn
88#define CAN_IRQN CAN_TX_IRQN
89#define CAN_SECOND_IRQN CAN1_RX0_IRQn
90#define CAN_THIRD_IRQN CAN1_SCE_IRQn
91#define CAN_CLOCK (cm3_cpu_clock_hz >> 2)
94#error Dont know what STM32 chip you have.
112 HAL_NVIC_DisableIRQ(CAN_IRQN);
114#if defined (STM32F030x6) || defined (STM32F031x6) || defined (STM32F038xx) \
115 || defined (STM32F030x8) || defined (STM32F030xC) || defined (STM32F042x6) \
116 || defined (STM32F048xx) || defined (STM32F051x8) || defined (STM32F058xx) \
117 || defined (STM32F070x6) || defined (STM32F070xB) || defined (STM32F071xB) \
118 || defined (STM32F072xB) || defined (STM32F078xx) \
119 || defined (STM32F091xC) || defined (STM32F098xx)
124 SetInterruptPriority(CAN_IRQN, configKERNEL_INTERRUPT_PRIORITY);
127 HAL_NVIC_DisableIRQ(CAN_SECOND_IRQN);
128 SetInterruptPriority(CAN_SECOND_IRQN, configKERNEL_INTERRUPT_PRIORITY);
129 HAL_NVIC_DisableIRQ(CAN_THIRD_IRQN);
130 SetInterruptPriority(CAN_THIRD_IRQN, configKERNEL_INTERRUPT_PRIORITY);
155 CAN->MCR = CAN_MCR_INRQ;
164 CAN->MCR |= (CAN_MCR_ABOM | CAN_MCR_TXFP);
169 CAN->BTR = (CAN_BS1_5TQ | CAN_BS2_2TQ | CAN_SJW_1TQ |
170 ((CAN_CLOCK / 1000000) - 1));
173 CAN->MCR &= ~CAN_MCR_INRQ;
178 CAN->FMR |= CAN_FMR_FINIT;
180 CAN->FS1R = 0x000000001;
182 CAN->sFilterRegister[0].FR1 = 0;
183 CAN->sFilterRegister[0].FR2 = 0;
186 CAN->FA1R = 0x000000001;
187 CAN->FMR &= ~CAN_FMR_FINIT;
192 CAN->IER = (CAN_IER_BOFIE | CAN_IER_EPVIE | CAN_IER_EWGIE);
193 CAN->IER |= (CAN_IER_ERRIE | CAN_IER_FMPIE0);
194 HAL_NVIC_EnableIRQ(CAN_IRQN);
196 HAL_NVIC_EnableIRQ(CAN_SECOND_IRQN);
197 HAL_NVIC_EnableIRQ(CAN_THIRD_IRQN);
205 HAL_NVIC_DisableIRQ(CAN_IRQN);
207 HAL_NVIC_DisableIRQ(CAN_SECOND_IRQN);
208 HAL_NVIC_DisableIRQ(CAN_THIRD_IRQN);
215 CAN->MCR = CAN_MCR_INRQ;
227 if ((CAN->ESR & CAN_ESR_EPVF) && ((CAN->ESR & CAN_ESR_LEC_Msk) != 0) &&
228 ((CAN->TSR & (CAN_TSR_TME0 | CAN_TSR_TME1 | CAN_TSR_TME2)) == 0))
236 struct can_frame *can_frame;
241 for (i = 0; i < msg_count; ++i, ++can_frame)
243 volatile CAN_TxMailBox_TypeDef *mailbox;
244 if (CAN->TSR & CAN_TSR_TME0)
246 mailbox = CAN->sTxMailBox + 0;
248 else if (CAN->TSR & CAN_TSR_TME1)
250 mailbox = CAN->sTxMailBox + 1;
252 else if (CAN->TSR & CAN_TSR_TME2)
254 mailbox = CAN->sTxMailBox + 2;
263 if (can_frame->can_eff)
265 mailbox->TIR = (can_frame->can_id << 3) | CAN_TI0R_IDE;
269 mailbox->TIR = can_frame->can_id << 21;
271 if (can_frame->can_rtr)
273 mailbox->TIR |= CAN_TI0R_RTR;
277 mailbox->TDTR = can_frame->can_dlc;
278 mailbox->TDLR = (can_frame->data[0] << 0) |
279 (can_frame->data[1] << 8) |
280 (can_frame->data[2] << 16) |
281 (can_frame->data[3] << 24);
282 mailbox->TDHR = (can_frame->data[4] << 0) |
283 (can_frame->data[5] << 8) |
284 (can_frame->data[6] << 16) |
285 (can_frame->data[7] << 24);
289 mailbox->TIR |= CAN_TI0R_TXRQ;
299 CAN->IER |= CAN_IER_TMEIE;
306 unsigned msg_receive_count = 0;
308 while (CAN->RF0R & CAN_RF0R_FMP0)
311 struct can_frame *can_frame;
315 if (CAN->sFIFOMailBox[0].RIR & CAN_RI0R_IDE)
318 can_frame->can_id = CAN->sFIFOMailBox[0].RIR >> 3;
319 can_frame->can_eff = 1;
324 can_frame->can_id = CAN->sFIFOMailBox[0].RIR >> 21;
325 can_frame->can_eff = 0;
327 if (CAN->sFIFOMailBox[0].RIR & CAN_RI0R_RTR)
330 can_frame->can_rtr = 1;
331 can_frame->can_dlc = 0;
336 can_frame->can_rtr = 0;
337 can_frame->can_dlc = CAN->sFIFOMailBox[0].RDTR & CAN_RDT0R_DLC;
338 can_frame->data[0] = (CAN->sFIFOMailBox[0].RDLR >> 0) & 0xFF;
339 can_frame->data[1] = (CAN->sFIFOMailBox[0].RDLR >> 8) & 0xFF;
340 can_frame->data[2] = (CAN->sFIFOMailBox[0].RDLR >> 16) & 0xFF;
341 can_frame->data[3] = (CAN->sFIFOMailBox[0].RDLR >> 24) & 0xFF;
342 can_frame->data[4] = (CAN->sFIFOMailBox[0].RDHR >> 0) & 0xFF;
343 can_frame->data[5] = (CAN->sFIFOMailBox[0].RDHR >> 8) & 0xFF;
344 can_frame->data[6] = (CAN->sFIFOMailBox[0].RDHR >> 16) & 0xFF;
345 can_frame->data[7] = (CAN->sFIFOMailBox[0].RDHR >> 24) & 0xFF;
353 CAN->RF0R |= CAN_RF0R_RFOM0;
357 if (msg_receive_count)
368 if (CAN->TSR & (CAN_TSR_RQCP0 | CAN_TSR_RQCP1 | CAN_TSR_RQCP2))
371 struct can_frame *can_frame;
379 for (i = 0; i < msg_count; ++i, ++can_frame)
381 volatile CAN_TxMailBox_TypeDef *mailbox;
382 if (CAN->TSR & CAN_TSR_TME0)
384 mailbox = CAN->sTxMailBox + 0;
386 else if (CAN->TSR & CAN_TSR_TME1)
388 mailbox = CAN->sTxMailBox + 1;
390 else if (CAN->TSR & CAN_TSR_TME2)
392 mailbox = CAN->sTxMailBox + 2;
401 if (can_frame->can_eff)
403 mailbox->TIR = (can_frame->can_id << 3) | CAN_TI0R_IDE;
407 mailbox->TIR = can_frame->can_id << 21;
409 if (can_frame->can_rtr)
411 mailbox->TIR |= CAN_TI0R_RTR;
415 mailbox->TDTR = can_frame->can_dlc;
416 mailbox->TDLR = (can_frame->data[0] << 0) |
417 (can_frame->data[1] << 8) |
418 (can_frame->data[2] << 16) |
419 (can_frame->data[3] << 24);
420 mailbox->TDHR = (can_frame->data[4] << 0) |
421 (can_frame->data[5] << 8) |
422 (can_frame->data[6] << 16) |
423 (can_frame->data[7] << 24);
427 mailbox->TIR |= CAN_TI0R_TXRQ;
434 CAN->IER &= ~CAN_IER_TMEIE;
446 if (CAN->MSR & CAN_MSR_ERRI)
449 CAN->MSR |= CAN_MSR_ERRI;
451 bool cancel_queue =
false;
453 if (CAN->ESR & CAN_ESR_EWGF)
458 if (CAN->ESR & CAN_ESR_EPVF)
465 if (CAN->ESR & CAN_ESR_BOFF)
474 CAN->TSR |= CAN_TSR_ABRQ2;
475 CAN->TSR |= CAN_TSR_ABRQ1;
476 CAN->TSR |= CAN_TSR_ABRQ0;
477 CAN->IER &= ~CAN_IER_TMEIE;
494#if defined (STM32F072xB) || defined (STM32F091xC)
495void cec_can_interrupt_handler(
void)
501#elif defined (STM32F103xB) || defined (STM32F303xC) || defined (STM32F303xE)
508void usb_hp_can1_tx_interrupt_handler(
void)
513void usb_lp_can1_rx0_interrupt_handler(
void)
518void can1_sce_interrupt_handler(
void)
523#elif defined(STM32F767xx) || defined(STM32L431xx) || defined(STM32L432xx)
530void can1_tx_interrupt_handler(
void)
535void can1_rx0_interrupt_handler(
void)
540void can1_sce_interrupt_handler(
void)
547#error Dont know what STM32 chip you have.
554#if defined(ARDUINO_ARCH_STM32)
556#include "stm32_def.h"
557#include "PinAF_STM32F1.h"
558#include <PeripheralPins.h>
560void arduino_can_pinmap(PinName tx_pin, PinName rx_pin) {
561 __HAL_RCC_CAN1_CLK_ENABLE();
562 void* can_tx = pinmap_peripheral(tx_pin, PinMap_CAN_TD);
563 void* can_rx = pinmap_peripheral(rx_pin, PinMap_CAN_RD);
564 void* can = pinmap_merge_peripheral(can_tx, can_rx);
566 DIE(
"Could not find CAN peripheral");
569 GPIO_InitTypeDef GPIO_InitStruct;
571 GPIO_InitStruct.Pin = STM_GPIO_PIN(tx_pin);
572 auto fn = pinmap_function(tx_pin, PinMap_CAN_TD);
573 GPIO_InitStruct.Mode = STM_PIN_MODE(fn);
574 GPIO_InitStruct.Pull = STM_PIN_PUPD(fn);
575 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
577 pin_SetF1AFPin(STM_PIN_AFNUM(fn));
579 GPIO_InitStruct.Alternate = STM_PIN_AFNUM(fn);
581 HAL_GPIO_Init(set_GPIO_Port_Clock(STM_PORT(tx_pin)), &GPIO_InitStruct);
583 GPIO_InitStruct.Pin = STM_GPIO_PIN(rx_pin);
584 fn = pinmap_function(rx_pin, PinMap_CAN_RD);
585 GPIO_InitStruct.Mode = STM_PIN_MODE(fn);
586 GPIO_InitStruct.Pull = STM_PIN_PUPD(fn);
587 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
589 pin_SetF1AFPin(STM_PIN_AFNUM(fn));
591 GPIO_InitStruct.Alternate = STM_PIN_AFNUM(fn);
593 HAL_GPIO_Init(set_GPIO_Port_Clock(STM_PORT(rx_pin)), &GPIO_InitStruct);
597void USB_HP_CAN_TX_IRQHandler(
void)
602void USB_LP_CAN_RX0_IRQHandler(
void)
606void CEC_CAN_IRQHandler(
void)
612void CAN1_TX_IRQHandler(
void)
616void CAN1_RX0_IRQHandler(
void)
620void CAN1_SCE_IRQHandler(
void)
Base class for a CAN device for the Arduino environment.
unsigned int overrunCount
overrun count
unsigned int softErrorCount
soft error count
DeviceBuffer< struct can_frame > * txBuf
transmit buffer
unsigned int busOffCount
bus-off count
DeviceBuffer< struct can_frame > * rxBuf
receive buffer
void flush()
flush all the data out of the buffer and reset the buffer.
size_t advance(size_t items)
Add a number of items to the buffer by advancing the writeIndex.
void signal_condition()
Signal the wakeup condition.
size_t consume(size_t items)
Remove a number of items from the buffer by advancing the readIndex.
void signal_condition_from_isr()
Signal the wakeup condition from an ISR context.
size_t data_write_pointer(T **buf)
Get a reference to the current location in the buffer for write.
size_t data_read_pointer(T **buf)
Get a reference to the current location in the buffer for read.
Specialization of CAN driver for LPC17xx and LPC40xx CAN.
int ioctl(File *file, unsigned long int key, unsigned long data) override
Request an ioctl transaction.
void enable() override
function to enable device
uint8_t state_
present bus state
void sce_interrupt_handler()
Handle an interrupt.
void rx_interrupt_handler()
Handle an interrupt.
void tx_interrupt_handler()
Handle an interrupt.
Stm32Can()
Default constructor.
static Stm32Can * instances[1]
Instance pointers help us get context from the interrupt handler(s)
void disable() override
function to disable device
void tx_msg() override
function to try and transmit a message
#define CAN_STATE_BUS_OFF
CAN bus off.
#define CAN_STATE_ACTIVE
CAN bus active.
#define SIOCGCANSTATE
Read the CAN state.
#define CAN_STATE_BUS_WARNING
CAN bus error warning.
uint32_t can_state_t
CAN state type.
#define CAN_STATE_STOPPED
CAN bus stopped.
#define CAN_STATE_BUS_PASSIVE
CAN bus error passive.
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
#define DIE(MSG)
Unconditionally terminates the current process with a message.