CARME-M4 BSP  V1.5
can.c
Go to the documentation of this file.
1 
80 #ifdef __cplusplus
81 extern "C" {
82 #endif /* __cplusplus */
83 
84 /*----- Header-Files -------------------------------------------------------*/
85 #include <string.h> /* Memory and string functions */
86 #include <stdio.h> /* Standard input and output */
87 
88 #include <stm32f4xx.h> /* Processor STM32F407IG */
89 #include <carme.h> /* CARME Module */
90 #include <can_sja1000.h> /* CAN Controller SJA1000 defines */
91 #include <can.h> /* CARME CAN Module */
92 
93 /*----- Macros -------------------------------------------------------------*/
94 
95 /*----- Data types ---------------------------------------------------------*/
96 
97 /*----- Function prototypes ------------------------------------------------*/
98 static void CARME_CAN_InitSTM(void);
99 static void CARME_CAN_SetBusTiming(uint8_t btr0, uint8_t btr1);
100 
101 /*----- Data ---------------------------------------------------------------*/
102 static IRQ_CALLBACK CARME_CAN_IRQCallbacks[CARME_CAN_IRQID_COUNT];
103 
104 /*----- Implementation -----------------------------------------------------*/
105 
116 static void CARME_CAN_InitSTM(void) {
117 
118  GPIO_InitTypeDef GPIO_InitStruct;
119  EXTI_InitTypeDef EXTI_InitStruct;
120  NVIC_InitTypeDef NVIC_InitStruct;
121 
122  /* Initialize the GPIO */
123  GPIO_StructInit(&GPIO_InitStruct);
124  GPIO_InitStruct.GPIO_Pin = CARME_CAN_nCAN_INT_PIN;
125  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
126  GPIO_InitStruct.GPIO_Speed = GPIO_Fast_Speed;
127  GPIO_Init(CARME_CAN_nCAN_INT_PORT, &GPIO_InitStruct);
128 
129  /* Enable the external interrupt */
133  EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
134  EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;
135  EXTI_InitStruct.EXTI_LineCmd = ENABLE;
136  EXTI_Init(&EXTI_InitStruct);
137 
138  /* Enable and set EXTI Line8 Interrupt to the lowest priority */
139  NVIC_InitStruct.NVIC_IRQChannel = CARME_CAN_nCAN_IRQn_CH;
140  NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x0F;
141  NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x0F;
142  NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
143  NVIC_Init(&NVIC_InitStruct);
144 }
145 
166 void CARME_CAN_Init(uint32_t baud, uint8_t flags) {
167 
168  uint8_t i;
169 
170  /* initialize global variables */
171  memset(CARME_CAN_IRQCallbacks, 0, sizeof(CARME_CAN_IRQCallbacks));
172 
173  /* initialize stm32f4xx registers */
175 
176  /* bypass RX comparator and set PeliCAN mode */
179 
180  /* output configuration, TX1: float, TX0: pushpull */
182 
183  /* set Baudrate */
184  CARME_CAN_SetBaudrate(baud);
185 
186  /* configure acceptance filter to accept all CAN-Messages */
187  for (i = 0; i < 4; i++) {
188  CARME_CAN_Write_Register(SJA1000_ACR(i), 0x00); /* acceptance code */
189  CARME_CAN_Write_Register(SJA1000_AMR(i), 0xff); /* acceptance mask */
190  }
191 
192  CARME_CAN_Write_Register(SJA1000_IR, 0x00); /* clear all interrupts */
193 
194  /* set the operation mode */
195  i = 1;
196  if (flags & CARME_CAN_DF_NORMAL) {
197  i &= ~SJA1000_MOD_RM; /* clear RM bit -> Normal Mode */
198  }
199  if (flags & CARME_CAN_DF_LISTEN_ONLY) {
200  i |= SJA1000_MOD_LOM; /* set LOM bit -> Listen only mode */
201  }
202  CARME_CAN_Write_Register(SJA1000_MOD, i); /* switch in operating mode */
203 }
204 
236 void CARME_CAN_InitI(uint32_t baud, uint8_t flags, uint32_t interrupts) {
237 
238  /* initialize normal settings, hold controller in Reset-Mode */
240 
241  /* enable interrupts */
243 
244  CARME_CAN_SetMode(flags);
245 }
246 
259  IRQ_CALLBACK pIRQCallback) {
260 
261  CARME_CAN_IRQCallbacks[id] = pIRQCallback;
262 }
263 
274 
275  CARME_CAN_IRQCallbacks[id] = NULL;
276 }
277 
293 
294  uint8_t mod = CARME_CAN_Read_Register(SJA1000_MOD);
295 
296  switch (flags) {
297  case CARME_CAN_DF_NORMAL:
298  mod &= ~SJA1000_MOD_RM;
299  break;
300  case CARME_CAN_DF_RESET:
301  mod |= SJA1000_MOD_RM;
302  break;
303  default:
305  }
306  CARME_CAN_Write_Register(SJA1000_MOD, mod); /* switch mode */
307 
308  return CARME_NO_ERROR;
309 }
310 
325 
327  uint8_t sr = CARME_CAN_Read_Register(SJA1000_SR);
328 
329  if (sr & SJA1000_SR_ES) {
331  }
332 
333  if ((sr & SJA1000_SR_RBS) == 0) {
335  }
336 
337  /* read first Frame Format Information */
338  uint8_t ff = CARME_CAN_Read_Register(SJA1000_RX_BUF(0));
339 
340  /* Read Frame format */
341  rxMsg->ext = (ff & SJA1000_FRAMEINFO_FF) != 0;
342 
343  /* read RTR */
344  rxMsg->rtr = (ff & SJA1000_FRAMEINFO_RTR) != 0;
345 
346  /* read number of data bytes */
347  rxMsg->dlc = ff & 0x0f;
348  if (rxMsg->dlc > 8)
349  rxMsg->dlc = 8;
350 
351  /* read identifier */
352  if (rxMsg->ext) {
353  rxMsg->id = CARME_CAN_Read_Register(SJA1000_RX_BUF(1)) << 21;
354  rxMsg->id |= CARME_CAN_Read_Register(SJA1000_RX_BUF(2)) << 13;
355  rxMsg->id |= CARME_CAN_Read_Register(SJA1000_RX_BUF(3)) << 5;
356  rxMsg->id |= CARME_CAN_Read_Register(SJA1000_RX_BUF(4)) >> 3;
357  }
358  else {
359  rxMsg->id = CARME_CAN_Read_Register(SJA1000_RX_BUF(1)) << 3;
360  rxMsg->id |= CARME_CAN_Read_Register(SJA1000_RX_BUF(2)) >> 5;
361  }
362 
363  /* read data bytes */
364  int rxDataOffset;
365  if (rxMsg->ext) {
366  rxDataOffset = SJA1000_RX_BUF(5);
367  }
368  else {
369  rxDataOffset = SJA1000_RX_BUF(3);
370  }
371  int i;
372  for (i = 0; i < rxMsg->dlc; i++) {
373  rxMsg->data[i] = CARME_CAN_Read_Register(rxDataOffset + i);
374  }
375 
376  /* release buffer */
378  return err;
379 }
380 
392 
393  uint8_t ir = CARME_CAN_Read_Register(SJA1000_IR);
394  do {
395 
396  if (ir & SJA1000_IR_RI) {
397  if (CARME_CAN_IRQCallbacks[CARME_CAN_IRQID_RX_INTERRUPT]) {
398  CARME_CAN_IRQCallbacks[CARME_CAN_IRQID_RX_INTERRUPT]();
399  }
400  } else if (ir & SJA1000_IR_TI) {
401  if (CARME_CAN_IRQCallbacks[CARME_CAN_IRQID_TX_INTERRUPT]) {
402  CARME_CAN_IRQCallbacks[CARME_CAN_IRQID_TX_INTERRUPT]();
403  }
404  } else if (ir & SJA1000_IR_EI) {
405  if (CARME_CAN_IRQCallbacks[CARME_CAN_IRQID_ERROR_INTERRUPT]) {
406  CARME_CAN_IRQCallbacks[CARME_CAN_IRQID_ERROR_INTERRUPT]();
407  }
408  } else if (ir & SJA1000_IR_DOI) {
409  if (CARME_CAN_IRQCallbacks[CARME_CAN_IRQID_DATAOVERFLOW_INTERRUPT]) {
410  CARME_CAN_IRQCallbacks[CARME_CAN_IRQID_DATAOVERFLOW_INTERRUPT]();
411  }
412  } else if (ir & SJA1000_IR_WUI) {
413  if (CARME_CAN_IRQCallbacks[CARME_CAN_IRQID_WAKEUP_INTERRUPT]) {
414  CARME_CAN_IRQCallbacks[CARME_CAN_IRQID_WAKEUP_INTERRUPT]();
415  }
416  } else if (ir & SJA1000_IR_EPI) {
417  if (CARME_CAN_IRQCallbacks[CARME_CAN_IRQID_PASSIVE_INTERRUPT]) {
418  CARME_CAN_IRQCallbacks[CARME_CAN_IRQID_PASSIVE_INTERRUPT]();
419  }
420  } else if (ir & SJA1000_IR_ALI) {
421  if (CARME_CAN_IRQCallbacks[CARME_CAN_IRQID_ARITRATION_LOST_INTERRUPT]) {
422  CARME_CAN_IRQCallbacks[CARME_CAN_IRQID_ARITRATION_LOST_INTERRUPT]();
423  }
424  } else if (ir & SJA1000_IR_BEI) {
425  if (CARME_CAN_IRQCallbacks[CARME_CAN_IRQID_BUS_ERROR_INTERRUPT]) {
426  CARME_CAN_IRQCallbacks[CARME_CAN_IRQID_BUS_ERROR_INTERRUPT]();
427  }
428  }
429 
431 
432  } while (ir);
433 }
434 
444 static void CARME_CAN_SetBusTiming(uint8_t btr0, uint8_t btr1) {
445 
448 }
449 
470 
471  switch (baud) {
472  case CARME_CAN_BAUD_125K:
473  CARME_CAN_SetBusTiming(0x45, 0x1c); /* 125k Baud */
474  break;
475  case CARME_CAN_BAUD_250K:
476  CARME_CAN_SetBusTiming(0x42, 0x1c); /* 250k Baud */
477  break;
478  case CARME_CAN_BAUD_500K:
479  CARME_CAN_SetBusTiming(0x40, 0x6f); /* 500k Baud */
480  break;
481  case CARME_CAN_BAUD_1M:
482  CARME_CAN_SetBusTiming(0x40, 0x09); /* 1M Baud */
483  break;
484  default:
486  break;
487  }
488 
489  return CARME_NO_ERROR;
490 }
491 
502 
503  uint8_t sr;
504  uint8_t i;
505  uint8_t txDataOffset;
506 
507  /* wait until transmit buffer is free */
508  do {
509 
511  if (sr & SJA1000_SR_ES) {
513  }
514  } while ((sr & SJA1000_SR_TBS) == 0);
515 
516  /* prepare frame format information */
517  unsigned char ff = 0;
518  if (txMsg->ext) {
519  /* set FF bit for extended frame (EFF) */
520  ff |= SJA1000_FRAMEINFO_FF;
521  }
522 
523  if (txMsg->rtr) {
524  ff |= SJA1000_FRAMEINFO_RTR;
525  }
526 
527  ff |= txMsg->dlc & 0xff;
528 
529  /* write frame format information */
531 
532  /* write identifier bytes */
533  if (txMsg->ext) {
534  CARME_CAN_Write_Register(SJA1000_TX_BUF(1), (txMsg->id >> 21) & 0xff);
535  CARME_CAN_Write_Register(SJA1000_TX_BUF(2), (txMsg->id >> 13) & 0xff);
536  CARME_CAN_Write_Register(SJA1000_TX_BUF(3), (txMsg->id >> 5) & 0xff);
537  CARME_CAN_Write_Register(SJA1000_TX_BUF(4), (txMsg->id << 3) & 0xf8);
538  }
539  else {
540  CARME_CAN_Write_Register(SJA1000_TX_BUF(1), (txMsg->id >> 3) & 0xff);
541  CARME_CAN_Write_Register(SJA1000_TX_BUF(2), (txMsg->id << 5) & 0xe0);
542  }
543 
544  if (txMsg->ext) {
545  txDataOffset = SJA1000_TX_BUF(5);
546  }
547  else {
548  txDataOffset = SJA1000_TX_BUF(3);
549  }
550  for (i = 0; i < max(txMsg->dlc, 8); i++) {
551  CARME_CAN_Write_Register(txDataOffset + i, txMsg->data[i]);
552  }
553 
554  /* send data */
556 
557  return CARME_NO_ERROR;
558 }
559 
658 
660  uint8_t mod;
661  uint8_t i;
662 
665  }
666 
667  /* set/clear AFM bit in MOD register */
669  if (af->afm == MODE_SINGLE) {
670  mod |= SJA1000_MOD_AFM;
671  }
672  else if (af->afm == MODE_DUAL) {
673  mod &= ~SJA1000_MOD_AFM;
674  }
675  else {
677  }
679 
680  /* write to acceptance mask and code registers */
681  for (i = 0; i < 4; i++) {
684  }
685 
686  return err;
687 }
688 
701 
703  uint8_t mod;
704  uint8_t i;
705 
708  }
709 
710  /* read AFM bit in MOD register */
712  if (mod & SJA1000_MOD_AFM) {
713  af->afm = MODE_SINGLE;
714  }
715  else {
716  af->afm = MODE_DUAL;
717  }
718 
719  /* read acceptance mask and code registers */
720  for (i = 0; i < 4; i++) {
723  }
724 
725  return err;
726 }
727 
728 #ifdef CARME_CAN_DEBUG
729 
736 void CARME_CAN_PrintRegisters(void) {
737 
738  printf("PeliCAN Mode\n\r"
739  "MOD = 0x%02x\n\r"
740  "CMR = 0x%02x\n\r"
741  "SR = 0x%02x\n\r"
742  "IR = 0x%02x\n\r"
743  "IER = 0x%02x\n\r"
744  "OCR = 0x%02x\n\r"
745  "BTR0 = 0x%02x\n\r"
746  "BTR1 = 0x%02x\n\r"
747  "RMC = 0x%02x\n\r"
748  "RBSA = 0x%02x\n\r",
759 }
760 
769 void CARME_CAN_GetRegisterString(char* pStr) {
770 
771  sprintf(pStr, "PeliCAN Mode\n\r"
772  "MOD = 0x%02x\n\r"
773  "CMR = 0x%02x\n\r"
774  "SR = 0x%02x\n\r"
775  "IR = 0x%02x\n\r"
776  "IER = 0x%02x\n\r"
777  "OCR = 0x%02x\n\r"
778  "BTR0 = 0x%02x\n\r"
779  "BTR1 = 0x%02x\n\r"
780  "RMC = 0x%02x\n\r"
781  "RBSA = 0x%02x\n\r"
782  "RXERR = 0x%02x\n\r"
783  "TXERR = 0x%02x\n\r",
796 }
797 #endif
798 
799 #ifdef __cplusplus
800 }
801 #endif /* __cplusplus */
802 
#define CARME_ERROR_CAN_ERROR_STATUS
Definition: can.h:100
void SYSCFG_EXTILineConfig(uint8_t EXTI_PortSourceGPIOx, uint8_t EXTI_PinSourcex)
Selects the GPIO pin used as EXTI Line.
#define SJA1000_CDR_CBP
Definition: can_sja1000.h:159
uint8_t ERROR_CODES
Error variable.
Definition: carme.h:255
Information about the acceptance filter.
Definition: can.h:163
#define SJA1000_IR_EI
Definition: can_sja1000.h:154
void NVIC_Init(NVIC_InitTypeDef *NVIC_InitStruct)
Initializes the NVIC peripheral according to the specified parameters in the NVIC_InitStruct.
Definition: misc.c:136
#define SJA1000_RXERR
Definition: can_sja1000.h:99
uint8_t NVIC_IRQChannelPreemptionPriority
Definition: misc.h:61
#define CARME_CAN_nCAN_IRQn_CH
Definition: can.h:85
void CARME_CAN_Init(uint32_t baud, uint8_t flags)
Initialize GPIOs and the CAN-Controller.
Definition: can.c:166
uint8_t data[8]
Definition: can.h:145
#define SJA1000_IR_EPI
Definition: can_sja1000.h:127
#define SJA1000_OCR
Definition: can_sja1000.h:93
#define CARME_ERROR_CAN_INVALID_BAUDRATE
Definition: can.h:95
EXTIMode_TypeDef EXTI_Mode
GPIOSpeed_TypeDef GPIO_Speed
#define SJA1000_AMR(_n_)
Definition: can_sja1000.h:105
static uint8_t CARME_CAN_Read_Register(uint8_t registerAddress)
Reads a value from a SJA1000 register.
Definition: can.h:217
#define SJA1000_MOD_AFM
Definition: can_sja1000.h:114
#define SJA1000_IR_BEI
Definition: can_sja1000.h:125
void EXTI_Init(EXTI_InitTypeDef *EXTI_InitStruct)
Initializes the EXTI peripheral according to the specified parameters in the EXTI_InitStruct.
#define SJA1000_RBSA
Definition: can_sja1000.h:102
#define CARME_CAN_DF_NORMAL
Definition: can.h:114
#define CARME_CAN_DF_RESET
Definition: can.h:113
#define SJA1000_CMR_TR
Definition: can_sja1000.h:123
#define CARME_CAN_BAUD_250K
Definition: can.h:89
#define SJA1000_BTR1
Definition: can_sja1000.h:92
uint8_t ext
Definition: can.h:140
#define CARME_CAN_nCAN_INT_PIN
Definition: can.h:84
#define SJA1000_IR_ALI
Definition: can_sja1000.h:126
NVIC Init Structure definition.
Definition: misc.h:54
#define SJA1000_TX_BUF(_n_)
Definition: can_sja1000.h:107
#define NULL
SDIO Static flags, TimeOut, FIFO Address.
static void CARME_CAN_SetBusTiming(uint8_t btr0, uint8_t btr1)
Set the Bus-Timing-Registers of the SJA1000 directly.
Definition: can.c:444
#define max(a, b)
Get the maximum of two numbers.
Definition: carme.h:231
void GPIO_StructInit(GPIO_InitTypeDef *GPIO_InitStruct)
Fills each GPIO_InitStruct member with its default value.
uint8_t NVIC_IRQChannel
Definition: misc.h:56
#define CARME_ERROR_CAN_INVALID_ACCEPTANCE_MODE
Definition: can.h:99
#define CARME_CAN_BAUD_500K
Definition: can.h:90
#define SJA1000_TXERR
Definition: can_sja1000.h:100
FunctionalState NVIC_IRQChannelCmd
Definition: misc.h:71
EXTI Init Structure definition.
enum CARME_CAN_ACCEPTANCE_FILTER_MODE afm
Definition: can.h:166
void GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_InitStruct)
Initializes the GPIOx peripheral according to the specified parameters in the GPIO_InitStruct.
ERROR_CODES CARME_CAN_SetAcceptaceFilter(CARME_CAN_ACCEPTANCE_FILTER *af)
ACCEPTANCE FILTER With the help of the acceptance filter the CAN controller is able to allow passing ...
Definition: can.c:657
#define CARME_GPIO_TO_EXTIPINSOURCE(GPIO_PIN)
Get EXTI_PinSourcex from GPIO_Pin_x.
Definition: carme.h:186
#define SJA1000_ACR(_n_)
Definition: can_sja1000.h:104
#define SJA1000_FRAMEINFO_RTR
Definition: can_sja1000.h:141
#define SJA1000_CMR
Definition: can_sja1000.h:86
uint32_t id
Definition: can.h:139
CARME_CAN_IRQ_CALLBACKS
Interrupt sources of the CAN-Controller.
Definition: can.h:122
uint8_t NVIC_IRQChannelSubPriority
Definition: misc.h:66
#define SJA1000_SR
Definition: can_sja1000.h:87
#define CARME_CAN_DF_LISTEN_ONLY
Definition: can.h:115
#define CARME_CAN_BAUD_125K
Definition: can.h:88
#define SJA1000_FRAMEINFO_FF
Definition: can_sja1000.h:140
void CARME_CAN_RegisterIRQCallback(enum CARME_CAN_IRQ_CALLBACKS id, IRQ_CALLBACK pIRQCallback)
Registers a callback function. Callback functions are called in Interruptmode. Use this function afte...
Definition: can.c:258
#define CARME_ERROR_CAN_INVALID_MODE
Definition: can.h:97
SJA1000 specific declarations.
#define CARME_CAN_BAUD_1M
Definition: can.h:91
void CARME_CAN_InitI(uint32_t baud, uint8_t flags, uint32_t interrupts)
Initialize GPIOs and the CAN-Controller.
Definition: can.c:236
GPIOMode_TypeDef GPIO_Mode
#define SJA1000_BTR0
Definition: can_sja1000.h:91
static void CARME_CAN_Write_Register(uint8_t registerAddress, uint8_t val)
Write a value in a SJA1000 register.
Definition: can.h:207
GPIO Init structure definition.
#define CARME_NO_ERROR
Definition: carme.h:135
#define SJA1000_IR_RI
Definition: can_sja1000.h:156
#define SJA1000_IR_DOI
Definition: can_sja1000.h:153
ERROR_CODES CARME_CAN_Write(CARME_CAN_MESSAGE *txMsg)
Sends a CAN-Messsage over the CAN-Bus.
Definition: can.c:501
#define SJA1000_IR_TI
Definition: can_sja1000.h:155
#define SJA1000_IR
Definition: can_sja1000.h:88
#define CARME_CAN_nCAN_INT_PORT
Definition: can.h:83
#define SJA1000_MOD
Definition: can_sja1000.h:85
void CARME_CAN_UnregisterIRQCallback(enum CARME_CAN_IRQ_CALLBACKS id)
Unregisters a callback function. Callback functions are called in Interruptmode.
Definition: can.c:273
Definition: can.h:155
ERROR_CODES CARME_CAN_GetAcceptaceFilter(CARME_CAN_ACCEPTANCE_FILTER *af)
Get the Acceptance Filter settings.
Definition: can.c:700
EXTITrigger_TypeDef EXTI_Trigger
#define SJA1000_SR_RBS
Definition: can_sja1000.h:150
uint8_t dlc
Definition: can.h:144
#define SJA1000_CDR_CANMODE
Definition: can_sja1000.h:158
#define CARME_GPIO_TO_EXTILINE(GPIO_PIN)
Get EXTI_Linex from GPIO_Pin_x.
Definition: carme.h:208
uint8_t rtr
Definition: can.h:143
#define SJA1000_IR_WUI
Definition: can_sja1000.h:152
ERROR_CODES CARME_CAN_Read(CARME_CAN_MESSAGE *rxMsg)
Reads a CAN-Message from the Receive-Buffer. If no message is in the buffer, the function returns CAR...
Definition: can.c:324
#define SJA1000_SR_TBS
Definition: can_sja1000.h:148
#define CARME_ERROR_CAN_RXFIFO_EMPTY
Definition: can.h:96
#define SJA1000_IER
Definition: can_sja1000.h:89
#define SJA1000_CMR_RRB
Definition: can_sja1000.h:121
ERROR_CODES CARME_CAN_SetBaudrate(uint32_t baud)
Set the baudrate for the CAN-Communication.
Definition: can.c:469
#define SJA1000_MOD_RM
Definition: can_sja1000.h:117
static void CARME_CAN_InitSTM(void)
Initialize the stm32f4xx GPIOs and the nCAN_INT. The CAN interrupt is on CARME_CAN_nCAN_IRQn_CH with...
Definition: can.c:116
#define SJA1000_RMC
Definition: can_sja1000.h:101
Drivers for the CAN interface. Uses the SJA1000 CAN controller on the CARME motherboard.
#define CARME_ERROR_CAN_INVALID_OPMODE
Definition: can.h:98
#define SJA1000_CDR
Definition: can_sja1000.h:103
#define SJA1000_SR_ES
Definition: can_sja1000.h:144
This struct encapsulates a CAN message.
Definition: can.h:138
#define SJA1000_RX_BUF(_n_)
Definition: can_sja1000.h:106
#define SJA1000_MOD_LOM
Definition: can_sja1000.h:116
void(* IRQ_CALLBACK)()
Pointer to a function.
Definition: can.h:172
void CARME_CAN_Interrupt_Handler(void)
This function will be called from the Interrupt-Handler on a CAN-Interrupt. If it was not the EXTI L...
Definition: can.c:391
FunctionalState EXTI_LineCmd
#define CARME_GPIO_TO_EXTIPORTSOURCE(GPIO_PORT)
Get EXTI_PortSourceGPIOx from GPIOx.
Definition: carme.h:171
ERROR_CODES CARME_CAN_SetMode(uint8_t flags)
Change operating mode from the CAN-Controller.
Definition: can.c:292