canard_stm32.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 UAVCAN Team
3  *
4  * Distributed under the MIT License, available in the file LICENSE.
5  *
6  * Author: Pavel Kirienko <pavel.kirienko@zubax.com>
7  */
8 
9 #include "canard_stm32.h"
10 #include "_internal_bxcan.h"
11 #include <unistd.h>
12 
13 
14 #if CANARD_STM32_USE_CAN2
15 # define BXCAN CANARD_STM32_CAN2
16 #else
17 # define BXCAN CANARD_STM32_CAN1
18 #endif
19 
20 /*
21  * State variables
22  */
24 
25 static bool g_abort_tx_on_error = false;
26 
27 
29 {
30  const uint32_t clean_a = a & CANARD_CAN_EXT_ID_MASK;
31  const uint32_t clean_b = b & CANARD_CAN_EXT_ID_MASK;
32 
33  /*
34  * STD vs EXT - if 11 most significant bits are the same, EXT loses.
35  */
36  const bool ext_a = (a & CANARD_CAN_FRAME_EFF) != 0;
37  const bool ext_b = (b & CANARD_CAN_FRAME_EFF) != 0;
38  if (ext_a != ext_b)
39  {
40  const uint32_t arb11_a = ext_a ? (clean_a >> 18U) : clean_a;
41  const uint32_t arb11_b = ext_b ? (clean_b >> 18U) : clean_b;
42  if (arb11_a != arb11_b)
43  {
44  return arb11_a < arb11_b;
45  }
46  else
47  {
48  return ext_b;
49  }
50  }
51 
52  /*
53  * RTR vs Data frame - if frame identifiers and frame types are the same, RTR loses.
54  */
55  const bool rtr_a = (a & CANARD_CAN_FRAME_RTR) != 0;
56  const bool rtr_b = (b & CANARD_CAN_FRAME_RTR) != 0;
57  if ((clean_a == clean_b) && (rtr_a != rtr_b))
58  {
59  return rtr_b;
60  }
61 
62  /*
63  * Plain ID arbitration - greater value loses.
64  */
65  return clean_a < clean_b;
66 }
67 
70 {
71  uint32_t out = 0;
72 
73  if (id & CANARD_CAN_FRAME_EFF)
74  {
75  out = ((id & CANARD_CAN_EXT_ID_MASK) << 3U) | CANARD_STM32_CAN_TIR_IDE;
76  }
77  else
78  {
79  out = ((id & CANARD_CAN_STD_ID_MASK) << 21U);
80  }
81 
82  if (id & CANARD_CAN_FRAME_RTR)
83  {
85  }
86 
87  return out;
88 }
89 
92 {
93 #if (CANARD_STM32_CAN_TIR_RTR != CANARD_STM32_CAN_RIR_RTR) ||\
94  (CANARD_STM32_CAN_TIR_IDE != CANARD_STM32_CAN_RIR_IDE)
95 # error "RIR bits do not match TIR bits, TIR --> libcanard conversion is not possible"
96 #endif
97 
98  uint32_t out = 0;
99 
100  if ((id & CANARD_STM32_CAN_RIR_IDE) == 0)
101  {
102  out = (CANARD_CAN_STD_ID_MASK & (id >> 21U));
103  }
104  else
105  {
106  out = (CANARD_CAN_EXT_ID_MASK & (id >> 3U)) | CANARD_CAN_FRAME_EFF;
107  }
108 
109  if ((id & CANARD_STM32_CAN_RIR_RTR) != 0)
110  {
111  out |= CANARD_CAN_FRAME_RTR;
112  }
113 
114  return out;
115 }
116 
117 
118 static bool waitMSRINAKBitStateChange(volatile const CanardSTM32CANType* const bxcan, const bool target_state)
119 {
128  static const uint16_t TimeoutMilliseconds = 1000;
129 
130  for (uint16_t wait_ack = 0; wait_ack < TimeoutMilliseconds; wait_ack++)
131  {
132  const bool state = (bxcan->MSR & CANARD_STM32_CAN_MSR_INAK) != 0;
133  if (state == target_state)
134  {
135  return true;
136  }
137 
138  // Sleep 1 millisecond
139  usleep(1000); // TODO: This function may be missing on some platforms
140  }
141 
142  return false;
143 }
144 
145 
146 static void processErrorStatus(void)
147 {
148  /*
149  * Aborting TX transmissions if abort on error was requested
150  * Updating error counter
151  */
153 
154  if (lec != 0)
155  {
156  BXCAN->ESR = 0; // This action does only affect the LEC bits, other bits are read only!
158 
159  // Abort pending transmissions if auto abort on error is enabled, or if we're in bus off mode
161  {
163  }
164  }
165 }
166 
167 
169  const CanardSTM32IfaceMode iface_mode)
170 {
171  /*
172  * Paranoia time.
173  */
174  if ((iface_mode != CanardSTM32IfaceModeNormal) &&
175  (iface_mode != CanardSTM32IfaceModeSilent) &&
177  {
178  return -CANARD_ERROR_INVALID_ARGUMENT;
179  }
180 
181  if ((timings == NULL) ||
182  (timings->bit_rate_prescaler < 1) || (timings->bit_rate_prescaler > 1024) ||
183  (timings->max_resynchronization_jump_width < 1) || (timings->max_resynchronization_jump_width > 4) ||
184  (timings->bit_segment_1 < 1) || (timings->bit_segment_1 > 16) ||
185  (timings->bit_segment_2 < 1) || (timings->bit_segment_2 > 8))
186  {
187  return -CANARD_ERROR_INVALID_ARGUMENT;
188  }
189 
190  /*
191  * Initial setup
192  */
193  memset(&g_stats, 0, sizeof(g_stats));
194 
196 
197 #if CANARD_STM32_USE_CAN2
198  // If we're using CAN2, we MUST initialize CAN1 first, because CAN2 is a slave to CAN1.
199  CANARD_STM32_CAN1->IER = 0; // We need no interrupts
200  CANARD_STM32_CAN1->MCR &= ~CANARD_STM32_CAN_MCR_SLEEP; // Exit sleep mode
201  CANARD_STM32_CAN1->MCR |= CANARD_STM32_CAN_MCR_INRQ; // Request init
202 
203  if (!waitMSRINAKBitStateChange(CANARD_STM32_CAN1, true)) // Wait for synchronization
204  {
207  }
208  // CAN1 will be left in the initialization mode forever, in this mode it does not affect the bus at all.
209 #endif
210 
211  BXCAN->IER = 0; // We need no interrupts
212  BXCAN->MCR &= ~CANARD_STM32_CAN_MCR_SLEEP; // Exit sleep mode
213  BXCAN->MCR |= CANARD_STM32_CAN_MCR_INRQ; // Request init
214 
215  if (!waitMSRINAKBitStateChange(BXCAN, true)) // Wait for synchronization
216  {
219  }
220 
221  /*
222  * Hardware initialization (the hardware has already confirmed initialization mode, see above)
223  */
225 
226  BXCAN->BTR = (((timings->max_resynchronization_jump_width - 1U) & 3U) << 24U) |
227  (((timings->bit_segment_1 - 1U) & 15U) << 16U) |
228  (((timings->bit_segment_2 - 1U) & 7U) << 20U) |
229  ((timings->bit_rate_prescaler - 1U) & 1023U) |
231 
232  CANARD_ASSERT(0 == BXCAN->IER); // Making sure the iterrupts are indeed disabled
233 
234  BXCAN->MCR &= ~CANARD_STM32_CAN_MCR_INRQ; // Leave init mode
235 
236  if (!waitMSRINAKBitStateChange(BXCAN, false))
237  {
240  }
241 
242  /*
243  * Default filter configuration. Note that ALL filters are available ONLY via CAN1!
244  * CAN2 filters are offset by 14.
245  * We use 14 filters at most always which simplifies the code and ensures compatibility with all
246  * MCU within the STM32 family.
247  */
248  {
249  uint32_t fmr = CANARD_STM32_CAN1->FMR & 0xFFFFC0F1U;
250  fmr |= CANARD_STM32_NUM_ACCEPTANCE_FILTERS << 8U; // CAN2 start bank = 14 (if CAN2 is present)
252  }
253 
254  CANARD_ASSERT(((CANARD_STM32_CAN1->FMR >> 8U) & 0x3FU) == CANARD_STM32_NUM_ACCEPTANCE_FILTERS);
255 
256  CANARD_STM32_CAN1->FM1R = 0; // Indentifier Mask mode
257  CANARD_STM32_CAN1->FS1R = 0x0FFFFFFF; // All 32-bit
258 
259  // Filters are alternating between FIFO0 and FIFO1 in order to equalize the load.
260  // This will cause occasional priority inversion and frame reordering on reception,
261  // but that is acceptable for UAVCAN, and a majority of other protocols will tolerate
262  // this too, since there will be no reordering within the same CAN ID.
263  CANARD_STM32_CAN1->FFA1R = 0x0AAAAAAA;
264 
265 #if CANARD_STM32_USE_CAN2
268  CANARD_STM32_CAN1->FA1R = (1 << CANARD_STM32_NUM_ACCEPTANCE_FILTERS); // One filter enabled
269 #else
270  CANARD_STM32_CAN1->FilterRegister[0].FR1 = 0;
271  CANARD_STM32_CAN1->FilterRegister[0].FR2 = 0;
272  CANARD_STM32_CAN1->FA1R = 1; // One filter enabled
273 #endif
274 
275  CANARD_STM32_CAN1->FMR &= ~CANARD_STM32_CAN_FMR_FINIT; // Leave initialization mode
276 
277  return 0;
278 }
279 
280 
281 int16_t canardSTM32Transmit(const CanardCANFrame* const frame)
282 {
283  if (frame == NULL)
284  {
285  return -CANARD_ERROR_INVALID_ARGUMENT;
286  }
287 
288  if (frame->id & CANARD_CAN_FRAME_ERR)
289  {
291  }
292 
293  /*
294  * Handling error status might free up some slots through aborts
295  */
297 
298  /*
299  * Seeking an empty slot, checking if priority inversion would occur if we enqueued now.
300  * We can always enqueue safely if all TX mailboxes are free and no transmissions are pending.
301  */
302  uint8_t tx_mailbox = 0xFF;
303 
305 
306  if ((BXCAN->TSR & AllTME) != AllTME) // At least one TX mailbox is used, detailed check is needed
307  {
308  const bool tme[3] =
309  {
310  (BXCAN->TSR & CANARD_STM32_CAN_TSR_TME0) != 0,
311  (BXCAN->TSR & CANARD_STM32_CAN_TSR_TME1) != 0,
312  (BXCAN->TSR & CANARD_STM32_CAN_TSR_TME2) != 0
313  };
314 
315  for (uint8_t i = 0; i < 3; i++)
316  {
317  if (tme[i]) // This TX mailbox is free, we can use it
318  {
319  tx_mailbox = i;
320  }
321  else // This TX mailbox is pending, check for priority inversion
322  {
324  {
325  // There's a mailbox whose priority is higher or equal the priority of the new frame.
326  return 0; // Priority inversion would occur! Reject transmission.
327  }
328  }
329  }
330 
331  if (tx_mailbox == 0xFF)
332  {
333  /*
334  * All TX mailboxes are busy (this is highly unlikely); at the same time we know that there is no
335  * higher or equal priority frame that is currently pending. Therefore, priority inversion has
336  * just happend (sic!), because we can't enqueue the higher priority frame due to all TX mailboxes
337  * being busy. This scenario is extremely unlikely, because in order for it to happen, the application
338  * would need to transmit 4 (four) or more CAN frames with different CAN ID ordered from high ID to
339  * low ID nearly at the same time. For example:
340  * 1. 0x123 <-- Takes mailbox 0 (or any other)
341  * 2. 0x122 <-- Takes mailbox 2 (or any other)
342  * 3. 0x121 <-- Takes mailbox 1 (or any other)
343  * 4. 0x120 <-- INNER PRIORITY INVERSION HERE (only if all three TX mailboxes are still busy)
344  * This situation is even less likely to cause any noticeable disruptions on the CAN bus. Despite that,
345  * it is better to warn the developer about that during debugging, so we fire an assertion failure here.
346  * It is perfectly safe to remove it.
347  */
348 #if CANARD_STM32_DEBUG_INNER_PRIORITY_INVERSION
349  CANARD_ASSERT(!"CAN PRIO INV");
350 #endif
351  return 0;
352  }
353  }
354  else // All TX mailboxes are free, use first
355  {
356  tx_mailbox = 0;
357  }
358 
359  CANARD_ASSERT(tx_mailbox < 3); // Index check - the value must be correct here
360 
361  /*
362  * By this time we've proved that a priority inversion would not occur, and we've also found a free TX mailbox.
363  * Therefore it is safe to enqueue the frame now.
364  */
365  volatile CanardSTM32TxMailboxType* const mb = &BXCAN->TxMailbox[tx_mailbox];
366 
367  mb->TDTR = frame->data_len; // DLC equals data length except in CAN FD
368 
369  mb->TDHR = (((uint32_t)frame->data[7]) << 24U) |
370  (((uint32_t)frame->data[6]) << 16U) |
371  (((uint32_t)frame->data[5]) << 8U) |
372  (((uint32_t)frame->data[4]) << 0U);
373  mb->TDLR = (((uint32_t)frame->data[3]) << 24U) |
374  (((uint32_t)frame->data[2]) << 16U) |
375  (((uint32_t)frame->data[1]) << 8U) |
376  (((uint32_t)frame->data[0]) << 0U);
377 
379 
380  /*
381  * The frame is now enqueued and pending transmission.
382  */
383  return 1;
384 }
385 
386 
387 int16_t canardSTM32Receive(CanardCANFrame* const out_frame)
388 {
389  if (out_frame == NULL)
390  {
391  return -CANARD_ERROR_INVALID_ARGUMENT;
392  }
393 
394  static volatile uint32_t* const RFxR[2] =
395  {
396  &BXCAN->RF0R,
397  &BXCAN->RF1R
398  };
399 
400  /*
401  * This function must be polled periodically, so we use this opportunity to do it.
402  */
404 
405  /*
406  * Reading the TX FIFO
407  */
408  for (uint_fast8_t i = 0; i < 2; i++)
409  {
410  volatile CanardSTM32RxMailboxType* const mb = &BXCAN->RxMailbox[i];
411 
412  if (((*RFxR[i]) & CANARD_STM32_CAN_RFR_FMP_MASK) != 0)
413  {
414  if (*RFxR[i] & CANARD_STM32_CAN_RFR_FOVR)
415  {
417  }
418 
419  out_frame->id = convertFrameIDRegisterToCanard(mb->RIR);
420 
421  out_frame->data_len = (uint8_t)(mb->RDTR & CANARD_STM32_CAN_RDTR_DLC_MASK);
422 
423  // Caching to regular (non volatile) memory for faster reads
424  const uint32_t rdlr = mb->RDLR;
425  const uint32_t rdhr = mb->RDHR;
426 
427  out_frame->data[0] = (uint8_t)(0xFFU & (rdlr >> 0U));
428  out_frame->data[1] = (uint8_t)(0xFFU & (rdlr >> 8U));
429  out_frame->data[2] = (uint8_t)(0xFFU & (rdlr >> 16U));
430  out_frame->data[3] = (uint8_t)(0xFFU & (rdlr >> 24U));
431  out_frame->data[4] = (uint8_t)(0xFFU & (rdhr >> 0U));
432  out_frame->data[5] = (uint8_t)(0xFFU & (rdhr >> 8U));
433  out_frame->data[6] = (uint8_t)(0xFFU & (rdhr >> 16U));
434  out_frame->data[7] = (uint8_t)(0xFFU & (rdhr >> 24U));
435 
436  // Release FIFO entry we just read
438 
439  // Reading successful
440  return 1;
441  }
442  }
443 
444  // No frames to read
445  return 0;
446 }
447 
448 
450  const uint8_t num_filter_configs)
451 {
452  // Note that num_filter_configs = 0 is a valid configuration, which rejects all frames.
453  if ((filter_configs == NULL) ||
454  (num_filter_configs > CANARD_STM32_NUM_ACCEPTANCE_FILTERS))
455  {
456  return -CANARD_ERROR_INVALID_ARGUMENT;
457  }
458 
459  /*
460  * First we disable all filters. This may cause momentary RX frame losses, but the application
461  * should be able to tolerate that.
462  */
463  CANARD_STM32_CAN1->FA1R = 0;
464 
465  /*
466  * Having filters disabled we can update the configuration.
467  * Register mapping: FR1 - ID, FR2 - Mask
468  */
469  for (uint8_t i = 0; i < num_filter_configs; i++)
470  {
471  /*
472  * Converting the ID and the Mask into the representation that can be chewed by the hardware.
473  * If Mask asks us to accept both STDID and EXTID, we need to use EXT mode on the filter,
474  * otherwise it will reject all EXTID frames. This logic is not documented in the RM.
475  *
476  * The logic of the hardware acceptance filters can be described as follows:
477  *
478  * accepted = (received_id & filter_mask) == (filter_id & filter_mask)
479  *
480  * Where:
481  * - accepted - if true, the frame will be accepted by the filter.
482  * - received_id - the CAN ID of the received frame, either 11-bit or 29-bit, with extension bits
483  * marking extended frames, error frames, etc.
484  * - filter_id - the value of the filter ID register.
485  * - filter_mask - the value of the filter mask register.
486  *
487  * There are special bits that are not members of the CAN ID field:
488  * - EFF - set for extended frames (29-bit), cleared for standard frames (11-bit)
489  * - RTR - like above, indicates Remote Transmission Request frames.
490  *
491  * The following truth table summarizes the logic (where: FM - filter mask, FID - filter ID, RID - received
492  * frame ID, A - true if accepted, X - any state):
493  *
494  * FM FID RID A
495  * 0 X X 1
496  * 1 0 0 1
497  * 1 1 0 0
498  * 1 0 1 0
499  * 1 1 1 1
500  *
501  * One would expect that for the purposes of hardware filtering, the special bits should be treated
502  * in the same way as the real ID bits. However, this is not the case with bxCAN. The following truth
503  * table has been determined empirically (this behavior was not documented as of 2017):
504  *
505  * FM FID RID A
506  * 0 0 0 1
507  * 0 0 1 0 <-- frame rejected!
508  * 0 1 X 1
509  * 1 0 0 1
510  * 1 1 0 0
511  * 1 0 1 0
512  * 1 1 1 1
513  */
514  uint32_t id = 0;
515  uint32_t mask = 0;
516 
517  const CanardSTM32AcceptanceFilterConfiguration* const cfg = filter_configs + i;
518 
519  if ((cfg->id & CANARD_CAN_FRAME_EFF) || !(cfg->mask & CANARD_CAN_FRAME_EFF))
520  {
521  id = (cfg->id & CANARD_CAN_EXT_ID_MASK) << 3U;
522  mask = (cfg->mask & CANARD_CAN_EXT_ID_MASK) << 3U;
524  }
525  else
526  {
527  id = (cfg->id & CANARD_CAN_STD_ID_MASK) << 21U;
528  mask = (cfg->mask & CANARD_CAN_STD_ID_MASK) << 21U;
529  }
530 
531  if (cfg->id & CANARD_CAN_FRAME_RTR)
532  {
534  }
535 
536  if (cfg->mask & CANARD_CAN_FRAME_EFF)
537  {
538  mask |= CANARD_STM32_CAN_RIR_IDE;
539  }
540 
541  if (cfg->mask & CANARD_CAN_FRAME_RTR)
542  {
543  mask |= CANARD_STM32_CAN_RIR_RTR;
544  }
545 
546  /*
547  * Applying the converted representation to the registers.
548  */
549  const uint8_t filter_index =
550 #if CANARD_STM32_USE_CAN2
552 #else
553  i;
554 #endif
555  CANARD_STM32_CAN1->FilterRegister[filter_index].FR1 = id;
556  CANARD_STM32_CAN1->FilterRegister[filter_index].FR2 = mask;
557 
558  CANARD_STM32_CAN1->FA1R |= 1U << filter_index; // Enable
559  }
560 
561  return 0;
562 }
563 
564 
566 {
567  return g_stats;
568 }
CanardSTM32TxMailboxType::TDLR
volatile uint32_t TDLR
Definition: _internal_bxcan.h:19
CanardSTM32AcceptanceFilterConfiguration::id
uint32_t id
Definition: canard_stm32.h:93
convertFrameIDCanardToRegister
static uint32_t convertFrameIDCanardToRegister(const uint32_t id)
Converts libcanard ID value into the bxCAN TX ID register format.
Definition: canard_stm32.c:69
CanardSTM32CANType
Definition: _internal_bxcan.h:37
CanardSTM32TxMailboxType::TIR
volatile uint32_t TIR
Definition: _internal_bxcan.h:17
CanardSTM32RxMailboxType::RDLR
volatile uint32_t RDLR
Definition: _internal_bxcan.h:27
uavcan::uint32_t
std::uint32_t uint32_t
Definition: std.hpp:26
CANARD_STM32_CAN_MCR_AWUM
#define CANARD_STM32_CAN_MCR_AWUM
Definition: _internal_bxcan.h:76
CanardSTM32RxMailboxType
Definition: _internal_bxcan.h:23
CANARD_STM32_CAN_FMR_FINIT
#define CANARD_STM32_CAN_FMR_FINIT
Definition: _internal_bxcan.h:220
CANARD_STM32_ERROR_MSR_INAK_NOT_CLEARED
#define CANARD_STM32_ERROR_MSR_INAK_NOT_CLEARED
Definition: canard_stm32.h:43
CANARD_STM32_CAN_TSR_ABRQ2
#define CANARD_STM32_CAN_TSR_ABRQ2
Definition: _internal_bxcan.h:110
CANARD_STM32_CAN_MCR_ABOM
#define CANARD_STM32_CAN_MCR_ABOM
Definition: _internal_bxcan.h:77
CANARD_STM32_NUM_ACCEPTANCE_FILTERS
#define CANARD_STM32_NUM_ACCEPTANCE_FILTERS
Definition: canard_stm32.h:54
CANARD_STM32_CAN_TSR_ABRQ1
#define CANARD_STM32_CAN_TSR_ABRQ1
Definition: _internal_bxcan.h:105
CanardSTM32TxMailboxType::TDHR
volatile uint32_t TDHR
Definition: _internal_bxcan.h:20
CANARD_STM32_CAN_RFR_FMP_MASK
#define CANARD_STM32_CAN_RFR_FMP_MASK
Definition: _internal_bxcan.h:123
CanardSTM32RxMailboxType::RDTR
volatile uint32_t RDTR
Definition: _internal_bxcan.h:26
g_abort_tx_on_error
static bool g_abort_tx_on_error
Definition: canard_stm32.c:25
BXCAN
#define BXCAN
Definition: canard_stm32.c:17
CanardSTM32CANTimings
Definition: canard_stm32.h:103
CANARD_STM32_CAN_RIR_RTR
#define CANARD_STM32_CAN_RIR_RTR
Definition: _internal_bxcan.h:202
CANARD_STM32_CAN_TIR_TXRQ
#define CANARD_STM32_CAN_TIR_TXRQ
Definition: _internal_bxcan.h:184
CANARD_STM32_CAN_MSR_INAK
#define CANARD_STM32_CAN_MSR_INAK
Definition: _internal_bxcan.h:84
uavcan::CanFrame::id
uint32_t id
CAN ID with flags (above)
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:34
canard_stm32.h
CANARD_STM32_CAN_MCR_SLEEP
#define CANARD_STM32_CAN_MCR_SLEEP
Definition: _internal_bxcan.h:72
canardSTM32Receive
int16_t canardSTM32Receive(CanardCANFrame *const out_frame)
Definition: canard_stm32.c:387
CanardSTM32AcceptanceFilterConfiguration
Definition: canard_stm32.h:91
uavcan::uint16_t
std::uint16_t uint16_t
Definition: std.hpp:25
CANARD_STM32_CAN_TSR_ABRQ0
#define CANARD_STM32_CAN_TSR_ABRQ0
Definition: _internal_bxcan.h:100
uavcan::int16_t
std::int16_t int16_t
Definition: std.hpp:30
isFramePriorityHigher
static bool isFramePriorityHigher(uint32_t a, uint32_t b)
Definition: canard_stm32.c:28
CanardSTM32TxMailboxType::TDTR
volatile uint32_t TDTR
Definition: _internal_bxcan.h:18
CanardSTM32IfaceModeNormal
@ CanardSTM32IfaceModeNormal
Normal mode.
Definition: canard_stm32.h:73
uavcan::uint8_t
std::uint8_t uint8_t
Definition: std.hpp:24
CANARD_STM32_CAN_TSR_TME0
#define CANARD_STM32_CAN_TSR_TME0
Definition: _internal_bxcan.h:113
CanardSTM32Stats::error_count
uint64_t error_count
Definition: canard_stm32.h:84
CANARD_STM32_CAN_RFR_FULL
#define CANARD_STM32_CAN_RFR_FULL
Definition: _internal_bxcan.h:124
convertFrameIDRegisterToCanard
static uint32_t convertFrameIDRegisterToCanard(const uint32_t id)
Converts bxCAN TX/RX (sic! both RX/TX are supported) ID register value into the libcanard ID format.
Definition: canard_stm32.c:91
CanardSTM32TxMailboxType
Definition: _internal_bxcan.h:15
CANARD_STM32_CAN_ESR_BOFF
#define CANARD_STM32_CAN_ESR_BOFF
Definition: _internal_bxcan.h:149
waitMSRINAKBitStateChange
static bool waitMSRINAKBitStateChange(volatile const CanardSTM32CANType *const bxcan, const bool target_state)
Definition: canard_stm32.c:118
CanardSTM32IfaceModeAutomaticTxAbortOnError
@ CanardSTM32IfaceModeAutomaticTxAbortOnError
Abort pending TX if a bus error has occurred.
Definition: canard_stm32.h:75
CanardSTM32CANType::MSR
volatile uint32_t MSR
CAN master status register 0x004.
Definition: _internal_bxcan.h:40
CanardSTM32RxMailboxType::RIR
volatile uint32_t RIR
Definition: _internal_bxcan.h:25
CANARD_STM32_CAN_RFR_RFOM
#define CANARD_STM32_CAN_RFR_RFOM
Definition: _internal_bxcan.h:126
CanardSTM32CANTimings::bit_rate_prescaler
uint16_t bit_rate_prescaler
Definition: canard_stm32.h:105
CanardSTM32Stats::rx_overflow_count
uint64_t rx_overflow_count
Definition: canard_stm32.h:83
g_stats
static CanardSTM32Stats g_stats
Definition: canard_stm32.c:23
CanardSTM32RxMailboxType::RDHR
volatile uint32_t RDHR
Definition: _internal_bxcan.h:28
uavcan::CanFrame::data
uint8_t data[MaxDataLen]
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:35
CANARD_STM32_CAN_RFR_FOVR
#define CANARD_STM32_CAN_RFR_FOVR
Definition: _internal_bxcan.h:125
CANARD_STM32_CAN_RIR_IDE
#define CANARD_STM32_CAN_RIR_IDE
Definition: _internal_bxcan.h:203
CANARD_STM32_CAN_TSR_TME1
#define CANARD_STM32_CAN_TSR_TME1
Definition: _internal_bxcan.h:114
frame
uavcan::CanFrame frame
Definition: can.cpp:78
CANARD_STM32_CAN_TIR_IDE
#define CANARD_STM32_CAN_TIR_IDE
Definition: _internal_bxcan.h:186
canardSTM32GetStats
CanardSTM32Stats canardSTM32GetStats(void)
Definition: canard_stm32.c:565
_internal_bxcan.h
CanardSTM32IfaceModeSilent
@ CanardSTM32IfaceModeSilent
Do not affect the bus, only listen.
Definition: canard_stm32.h:74
CANARD_STM32_CAN_TSR_TME2
#define CANARD_STM32_CAN_TSR_TME2
Definition: _internal_bxcan.h:115
processErrorStatus
static void processErrorStatus(void)
Definition: canard_stm32.c:146
canardSTM32Transmit
int16_t canardSTM32Transmit(const CanardCANFrame *const frame)
Definition: canard_stm32.c:281
CANARD_STM32_CAN_MCR_INRQ
#define CANARD_STM32_CAN_MCR_INRQ
Definition: _internal_bxcan.h:71
CanardSTM32CANTimings::bit_segment_2
uint8_t bit_segment_2
[1, 16]
Definition: canard_stm32.h:107
CanardSTM32CANTimings::max_resynchronization_jump_width
uint8_t max_resynchronization_jump_width
[1, 8]
Definition: canard_stm32.h:108
CANARD_STM32_CAN_TIR_RTR
#define CANARD_STM32_CAN_TIR_RTR
Definition: _internal_bxcan.h:185
CANARD_STM32_ERROR_UNSUPPORTED_FRAME_FORMAT
#define CANARD_STM32_ERROR_UNSUPPORTED_FRAME_FORMAT
Definition: canard_stm32.h:44
CanardSTM32AcceptanceFilterConfiguration::mask
uint32_t mask
Definition: canard_stm32.h:94
CANARD_STM32_CAN_MCR_RESET
#define CANARD_STM32_CAN_MCR_RESET
Definition: _internal_bxcan.h:79
CANARD_STM32_ERROR_MSR_INAK_NOT_SET
#define CANARD_STM32_ERROR_MSR_INAK_NOT_SET
Definition: canard_stm32.h:42
NULL
#define NULL
Nullzeiger.
Definition: utils.h:64
CanardSTM32Stats
Definition: canard_stm32.h:81
canardSTM32Init
int16_t canardSTM32Init(const CanardSTM32CANTimings *const timings, const CanardSTM32IfaceMode iface_mode)
Definition: canard_stm32.c:168
CANARD_STM32_CAN_BTR_SILM
#define CANARD_STM32_CAN_BTR_SILM
Definition: _internal_bxcan.h:176
canardSTM32ConfigureAcceptanceFilters
int16_t canardSTM32ConfigureAcceptanceFilters(const CanardSTM32AcceptanceFilterConfiguration *const filter_configs, const uint8_t num_filter_configs)
Definition: canard_stm32.c:449
CANARD_STM32_CAN_RDTR_DLC_MASK
#define CANARD_STM32_CAN_RDTR_DLC_MASK
Definition: _internal_bxcan.h:212
CanardSTM32CANTimings::bit_segment_1
uint8_t bit_segment_1
[1, 1024]
Definition: canard_stm32.h:106
CANARD_STM32_CAN_ESR_LEC_SHIFT
#define CANARD_STM32_CAN_ESR_LEC_SHIFT
Definition: _internal_bxcan.h:150
CanardSTM32IfaceMode
CanardSTM32IfaceMode
Definition: canard_stm32.h:71
CANARD_STM32_CAN_ESR_LEC_MASK
#define CANARD_STM32_CAN_ESR_LEC_MASK
Definition: _internal_bxcan.h:151
CANARD_STM32_CAN1
#define CANARD_STM32_CAN1
Definition: _internal_bxcan.h:66


uavcan_communicator
Author(s):
autogenerated on Fri Dec 13 2024 03:10:02