1 /* Copyright (C) 2013-2014 Czech Technical University in Prague
4 * - Carlos Jenkins <carlos@jenkins.co.cr>
5 * - Karolína Burešová <karry@karryanna.cz>
7 * This document contains proprietary information belonging to Czech
8 * Technical University in Prague. Passing on and copying of this
9 * document, and communication of its contents is not permitted
10 * without prior written authorization.
14 * CAN Bus Communication RPP API implementation file.
18 * RPP API documentation.
24 #include "sys/ti_drv_dmm.h"
26 static const struct rpp_can_config *can_config = NULL;
28 typedef volatile struct CANBase
30 uint32_t CTL; /**< 0x0000: Control Register */
31 uint32_t ES; /**< 0x0004: Error and Status Register */
32 uint32_t EERC; /**< 0x0008: Error Counter Register */
33 uint32_t BTR; /**< 0x000C: Bit Timing Register */
34 uint32_t INT; /**< 0x0010: Interrupt Register */
35 uint32_t TEST; /**< 0x0014: Test Register */
36 uint32_t : 32U; /**< 0x0018: Reserved */
37 uint32_t PERR; /**< 0x001C: Parity/SECDED Error Code Register */
38 uint32_t REL; /**< 0x0020: Core Release Register */
39 uint32_t ECCDIAG; /**< 0x0024: ECC Diagnostic Register */
40 uint32_t ECCDIADSTAT; /**< 0x0028: ECC Diagnostic Status Register */
41 uint32_t : 32U; /**< 0x002C: Reserved */
42 uint32_t : 32U; /**< 0x0030: Reserved */
43 uint32_t : 32U; /**< 0x0034: Reserved */
44 uint32_t : 32U; /**< 0x0038: Reserved */
45 uint32_t : 32U; /**< 0x003C: Reserved */
46 uint32_t : 32U; /**< 0x0040: Reserved */
47 uint32_t : 32U; /**< 0x0044: Reserved */
48 uint32_t : 32U; /**< 0x0048: Reserved */
49 uint32_t : 32U; /**< 0x004C: Reserved */
50 uint32_t : 32U; /**< 0x0050: Reserved */
51 uint32_t : 32U; /**< 0x0054: Reserved */
52 uint32_t : 32U; /**< 0x0058: Reserved */
53 uint32_t : 32U; /**< 0x005C: Reserved */
54 uint32_t : 32U; /**< 0x0060: Reserved */
55 uint32_t : 32U; /**< 0x0064: Reserved */
56 uint32_t : 32U; /**< 0x0068: Reserved */
57 uint32_t : 32U; /**< 0x006C: Reserved */
58 uint32_t : 32U; /**< 0x0070: Reserved */
59 uint32_t : 32U; /**< 0x0074: Reserved */
60 uint32_t : 32U; /**< 0x0078: Reserved */
61 uint32_t : 32U; /**< 0x007C: Reserved */
62 uint32_t ABOTR; /**< 0x0080: Auto Bus On Time Register */
63 uint32_t TXRQX; /**< 0x0084: Transmission Request X Register */
64 uint32_t TXRQx[4U]; /**< 0x0088-0x0094: Transmission Request Registers */
65 uint32_t NWDATX; /**< 0x0098: New Data X Register */
66 uint32_t NWDATx[4U]; /**< 0x009C-0x00A8: New Data Registers */
67 uint32_t INTPNDX; /**< 0x00AC: Interrupt Pending X Register */
68 uint32_t INTPNDx[4U]; /**< 0x00B0-0x00BC: Interrupt Pending Registers */
69 uint32_t MSGVALX; /**< 0x00C0: Message Valid X Register */
70 uint32_t MSGVALx[4U]; /**< 0x00C4-0x00D0: Message Valid Registers */
71 uint32_t : 32U; /**< 0x00D4: Reserved */
72 uint32_t INTMUXx[4U]; /**< 0x00D8-0x00E4: Interrupt Multiplexer Registers */
73 uint32_t : 32U; /**< 0x00E8: Reserved */
74 uint32_t : 32U; /**< 0x00EC: Reserved */
75 uint32_t : 32U; /**< 0x00F0: Reserved */
76 uint32_t : 32U; /**< 0x00F4: Reserved */
77 uint32_t : 32U; /**< 0x00F8: Reserved */
78 uint32_t : 32U; /**< 0x00FC: Reserved */
79 #if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
80 uint8_t IF1NO; /**< 0x0100: IF1 Command Register, Msg Number */
81 uint8_t IF1STAT; /**< 0x0100: IF1 Command Register, Status */
82 uint8_t IF1CMD; /**< 0x0100: IF1 Command Register, Command */
83 uint32_t : 8U; /**< 0x0100: IF1 Command Register, Reserved */
85 uint32_t : 8U; /**< 0x0100: IF1 Command Register, Reserved */
86 uint8_t IF1CMD; /**< 0x0100: IF1 Command Register, Command */
87 uint8_t IF1STAT; /**< 0x0100: IF1 Command Register, Status */
88 uint8_t IF1NO; /**< 0x0100: IF1 Command Register, Msg Number */
90 uint32_t IF1MSK; /**< 0x0104: IF1 Mask Register */
91 uint32_t IF1ARB; /**< 0x0108: IF1 Arbitration Register */
92 uint32_t IF1MCTL; /**< 0x010C: IF1 Message Control Register */
93 uint8_t IF1DATx[8U]; /**< 0x0110-0x0114: IF1 Data A and B Registers */
94 uint32_t : 32U; /**< 0x0118: Reserved */
95 uint32_t : 32U; /**< 0x011C: Reserved */
96 #if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
97 uint8_t IF2NO; /**< 0x0120: IF2 Command Register, Msg No */
98 uint8_t IF2STAT; /**< 0x0120: IF2 Command Register, Status */
99 uint8_t IF2CMD; /**< 0x0120: IF2 Command Register, Command */
100 uint32_t : 8U; /**< 0x0120: IF2 Command Register, Reserved */
102 uint32_t : 8U; /**< 0x0120: IF2 Command Register, Reserved */
103 uint8_t IF2CMD; /**< 0x0120: IF2 Command Register, Command */
104 uint8_t IF2STAT; /**< 0x0120: IF2 Command Register, Status */
105 uint8_t IF2NO; /**< 0x0120: IF2 Command Register, Msg Number */
107 uint32_t IF2MSK; /**< 0x0124: IF2 Mask Register */
108 uint32_t IF2ARB; /**< 0x0128: IF2 Arbitration Register */
109 uint32_t IF2MCTL; /**< 0x012C: IF2 Message Control Register */
110 uint8_t IF2DATx[8U]; /**< 0x0130-0x0134: IF2 Data A and B Registers */
111 uint32_t : 32U; /**< 0x0138: Reserved */
112 uint32_t : 32U; /**< 0x013C: Reserved */
113 uint32_t IF3OBS; /**< 0x0140: IF3 Observation Register */
114 uint32_t IF3MSK; /**< 0x0144: IF3 Mask Register */
115 uint32_t IF3ARB; /**< 0x0148: IF3 Arbitration Register */
116 uint32_t IF3MCTL; /**< 0x014C: IF3 Message Control Register */
117 uint8_t IF3DATx[8U]; /**< 0x0150-0x0154: IF3 Data A and B Registers */
118 uint32_t : 32U; /**< 0x0158: Reserved */
119 uint32_t : 32U; /**< 0x015C: Reserved */
120 uint32_t IF3UEy[4U]; /**< 0x0160-0x016C: IF3 Update Enable Registers */
121 uint32_t : 32U; /**< 0x0170: Reserved */
122 uint32_t : 32U; /**< 0x0174: Reserved */
123 uint32_t : 32U; /**< 0x0178: Reserved */
124 uint32_t : 32U; /**< 0x017C: Reserved */
125 uint32_t : 32U; /**< 0x0180: Reserved */
126 uint32_t : 32U; /**< 0x0184: Reserved */
127 uint32_t : 32U; /**< 0x0188: Reserved */
128 uint32_t : 32U; /**< 0x018C: Reserved */
129 uint32_t : 32U; /**< 0x0190: Reserved */
130 uint32_t : 32U; /**< 0x0194: Reserved */
131 uint32_t : 32U; /**< 0x0198: Reserved */
132 uint32_t : 32U; /**< 0x019C: Reserved */
133 uint32_t : 32U; /**< 0x01A0: Reserved */
134 uint32_t : 32U; /**< 0x01A4: Reserved */
135 uint32_t : 32U; /**< 0x01A8: Reserved */
136 uint32_t : 32U; /**< 0x01AC: Reserved */
137 uint32_t : 32U; /**< 0x01B0: Reserved */
138 uint32_t : 32U; /**< 0x01B4: Reserved */
139 uint32_t : 32U; /**< 0x01B8: Reserved */
140 uint32_t : 32U; /**< 0x01BC: Reserved */
141 uint32_t : 32U; /**< 0x01C0: Reserved */
142 uint32_t : 32U; /**< 0x01C4: Reserved */
143 uint32_t : 32U; /**< 0x01C8: Reserved */
144 uint32_t : 32U; /**< 0x01CC: Reserved */
145 uint32_t : 32U; /**< 0x01D0: Reserved */
146 uint32_t : 32U; /**< 0x01D4: Reserved */
147 uint32_t : 32U; /**< 0x01D8: Reserved */
148 uint32_t : 32U; /**< 0x01DC: Reserved */
149 uint32_t TIOC; /**< 0x01E0: TX IO Control Register */
150 uint32_t RIOC; /**< 0x01E4: RX IO Control Register */
153 #define canREG1 ((canBASE_t *) 0xFFF7DC00U)
154 #define canREG2 ((canBASE_t *) 0xFFF7DE00U)
155 #define canREG3 ((canBASE_t *) 0xFFF7E000U)
157 #ifndef __little_endian__
158 static const uint32_t s_can_byte_order[] = {3, 2, 1, 0, 7, 6, 5, 4};
161 static canBASE_t *can_base[3] = { canREG1, canREG2, canREG3 };
163 static inline canBASE_t * map_controller(uint8_t controller)
165 if (controller < 1 || controller > 3)
167 return can_base[controller - 1];
171 static int8_t init_tx_box(struct rpp_can_tx_config cfg)
173 canBASE_t *controller;
175 if (!(controller = map_controller(cfg.controller)))
178 // Wait until IF1 is ready to use
179 while (controller->IF1STAT & (1U << 7));
182 * 31 Set whether use of std/ext ID should have effect on acceptance filtering
185 case RPP_CAN_STANDARD:
186 controller->IF1MSK = 0U << 31;
189 controller->IF1MSK = 1U << 31;
191 case RPP_CAN_EXTENDED:
192 controller->IF1MSK = 1U << 31;
197 * 31 Message object is valid
198 * 30 Set whether to use extented identifier
199 * 29 Set direction as transmit
201 controller->IF1ARB = (1U << 31)
202 | ((cfg.type == RPP_CAN_STANDARD ? 0 : 1) << 30)
207 * 4-1 Data length code
209 controller->IF1MCTL = (1 << 7)
213 * Note that IF1CMD does not refer to whole CMD register
214 * (it refers to bits 23-16 of that register)
215 * 7 Transfer from IF to message object
216 * 5 Transfer arbitration bits
217 * 4 Transfer control bits
219 controller->IF1CMD = (1U << 7)
223 // Write MSG object number and enable transfer
224 controller->IF1NO = cfg.msg_obj;
229 static int8_t init_rx_box(struct rpp_can_rx_config cfg)
231 canBASE_t *controller;
233 if (!(controller = map_controller(cfg.controller)))
236 // Wait until IF2 is ready to use
237 while (controller->IF2STAT & (1U << 7));
240 * 31 Set whether use of std/ext ID should have effect on acceptance filtering
244 case RPP_CAN_STANDARD:
245 controller->IF2MSK = (1U << 31) | (cfg.mask << 18);
248 controller->IF2MSK = (0U << 31) | cfg.mask;
250 case RPP_CAN_EXTENDED:
251 controller->IF2MSK = (1U << 31) | cfg.mask;
256 * 31 Message object is valid
257 * 30 Set whether extended ID should be used
258 * 29 Direction is read
259 * 28-18 / 28-1 Object ID
261 controller->IF2ARB = (1U << 31) // MsgVal
262 | ((cfg.type == RPP_CAN_STANDARD ? 0 : 1) << 30)
264 | cfg.id << (cfg.type == RPP_CAN_STANDARD ? 18 : 0);
266 * 12 Use mask for filtering
268 * 4-1 Data length code
270 controller->IF2MCTL = (1 << 12)
275 * Note that IF2CMD does not refer to whole CMD register
276 * (it refers to bits 23-16 of that register)
277 * 7 Transfer from IF to message object
278 * 6 Transfer mask bits
279 * 5 Transfer arbitration bits
280 * 4 Transfer control bits
282 controller->IF2CMD = (1 << 7)
287 // Write MSG object number and enable transfer
288 controller->IF2NO = cfg.msg_obj;
295 static int8_t can_reset(canBASE_t *controller)
298 * 6 Request write access to config registers
299 * 0 Enter initialization mode
306 controller->ABOTR = 0;
308 controller->TIOC = (0 << 0);
309 controller->RIOC = (0 << 0);
314 static int8_t can_set_timing(canBASE_t *controller, const struct rpp_can_timing_cfg cfg) {
315 controller->BTR = (((cfg.brp-1) >> 6) << 16)
316 | ((cfg.phase_seg2-1) << 12)
317 | (((cfg.phase_seg1+cfg.prop_seg)-1) << 8)
319 | ((cfg.brp-1) & 63);
323 /* This code has been taken from can-calc-bit-timing.c */
324 /* can-calc-bit-timing.c: Calculate CAN bit timing parameters
327 * can_baud.c - CAN baudrate calculation
328 * Code based on LinCAN sources and H8S2638 project
329 * Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz
330 * Copyright 2005 Stanislav Marek
331 * email:pisa@cmp.felk.cvut.cz
333 * With permission from Pavel Pisa to distribute the code and
334 * software under other license than GPL.
336 static int can_update_spt(int phase_seg2_min, int phase_seg2_max, int prop_seg_max, int phase_seg1_max,
337 int sampl_pt, int tseg, int *tseg1, int *tseg2)
339 *tseg2 = tseg + 1 - (sampl_pt * (tseg + 1)) / 1000;
340 if (*tseg2 < phase_seg2_min)
341 *tseg2 = phase_seg2_min;
342 if (*tseg2 > phase_seg2_max)
343 *tseg2 = phase_seg2_max;
344 *tseg1 = tseg - *tseg2;
345 if (*tseg1 > prop_seg_max + phase_seg1_max) {
346 *tseg1 = prop_seg_max + phase_seg1_max;
347 *tseg2 = tseg - *tseg1;
349 return 1000 * (tseg + 1 - *tseg2) / (tseg + 1);
352 /* This code has been taken from can-calc-bit-timing.c */
353 /* can-calc-bit-timing.c: Calculate CAN bit timing parameters
356 * can_baud.c - CAN baudrate calculation
357 * Code based on LinCAN sources and H8S2638 project
358 * Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz
359 * Copyright 2005 Stanislav Marek
360 * email:pisa@cmp.felk.cvut.cz
362 * With permission from Pavel Pisa to distribute the code and
363 * software under other license than GPL.
365 static int8_t can_calculate_timing(const struct rpp_can_ctrl_config cfg, struct rpp_can_timing_cfg *timing) {
366 static const int prop_seg_min = 1;
367 static const int prop_seg_max = 8;
368 static const int phase_seg1_min = 1;
369 static const int phase_seg1_max = 8;
370 static const int phase_seg2_min = 1;
371 static const int phase_seg2_max = 8;
372 static const int brp_min = 1;
373 static const int brp_max = 64;
374 static const int brp_inc = 1;
376 if (timing == NULL) {
381 long best_error = 1000000000, error;
382 int best_tseg = 0, best_brp = 0, brp = 0;
383 int spt_error = 1000, spt = 0;
385 int tseg = 0, tseg1 = 0, tseg2 = 0;
388 /* Use CIA recommended sample points */
389 if (cfg.baudrate > 800000) {
392 else if (cfg.baudrate > 500000) {
399 /* tseg even = round down, odd = round up */
400 for (tseg = (prop_seg_max + phase_seg1_max + phase_seg2_max) * 2 + 1;
401 tseg >= (prop_seg_min + phase_seg1_min + phase_seg2_min) * 2;
403 /* Compute all posibilities of tseg choices (tseg=tseg1+tseg2) */
404 brp = cfg.clk / ((1 + tseg / 2) * cfg.baudrate) + tseg % 2;
405 /* chose brp step which is possible in system */
406 brp = (brp / brp_inc) * brp_inc;
407 if ((brp < brp_min) || (brp > brp_max))
409 rate = cfg.clk / (brp * (1 + tseg / 2));
410 error = cfg.baudrate - rate;
411 /* tseg brp biterror */
415 if (error > best_error)
419 spt = can_update_spt(phase_seg2_min, phase_seg2_max, prop_seg_max, phase_seg1_max, sampl_pt, tseg / 2, &tseg1, &tseg2);
420 error = sampl_pt - spt;
423 if (error > spt_error)
427 best_tseg = tseg / 2;
433 if (best_error && (cfg.baudrate / best_error < 10))
436 tseg2 = best_tseg + 1 - (sampl_pt * (best_tseg + 1)) / 1000;
437 spt = can_update_spt(phase_seg2_min, phase_seg2_max, prop_seg_max, phase_seg1_max, sampl_pt, best_tseg, &tseg1, &tseg2);
440 /* sample point < 50% */
441 timing->phase_seg1 = tseg1 / 2;
443 /* keep phase_seg{1,2} equal around the sample point */
444 timing->phase_seg1 = tseg2;
446 timing->prop_seg = tseg1 - timing->phase_seg1;
447 /* Check prop_seg range if necessary */
448 if (prop_seg_min || prop_seg_max) {
449 if (timing->prop_seg < prop_seg_min)
450 timing->prop_seg = prop_seg_min;
451 else if (timing->prop_seg > prop_seg_max)
452 timing->prop_seg = prop_seg_max;
453 timing->phase_seg1 = tseg1 - timing->prop_seg;
455 timing->phase_seg2 = tseg2;
457 timing->brp = best_brp;
458 timing->error = best_error;
459 timing->sampl_pt = spt;
460 v64 = (uint64_t)timing->brp * 1000000000UL;
462 timing->tq = (int)v64;
467 static int8_t can_configure(canBASE_t *controller, const struct rpp_can_ctrl_config cfg)
469 if (cfg.timing_calc_method == RPP_CAN_TIMING_CALC_AUTO) {
470 struct rpp_can_timing_cfg timing_cfg;
471 if (can_calculate_timing(cfg, &timing_cfg) == SUCCESS) {
472 return can_set_timing(controller, timing_cfg);
478 else if (cfg.timing_calc_method == RPP_CAN_TIMING_CALC_MANUAL && cfg.timing_config != NULL) {
479 return can_set_timing(controller, *cfg.timing_config);
486 static inline void can_leave_init(canBASE_t *controller)
488 controller->CTL &= ~( (1 << 6) | (1 << 0) );
492 static int8_t reset_box(canBASE_t *controller, uint32_t msg_obj)
494 // Wait until IF1 is ready
495 while (controller->IF1STAT & (1U << 7));
497 controller->IF1MSK = 0;
498 controller->IF1ARB = 0;
499 controller->IF1MCTL = (1 << 7) | 8;
500 controller->IF1CMD = (1 << 7)
504 controller->IF1NO = msg_obj;
509 static int8_t reset_boxes(void)
513 for (i=1; i<=64; i++)
515 reset_box(canREG1, i);
518 for (i=1; i<=64; i++)
520 reset_box(canREG2, i);
523 for (i=1; i<=32; i++)
525 reset_box(canREG3, i);
531 int8_t can_setup_IF(canBASE_t *controller)
533 // Wait until IF1 is ready
534 while (controller->IF1STAT & (1U << 7));
537 * 7 Transfer from IF to message object
538 * 5 Transfer arbitration bits
539 * 4 Transfer control bits
541 * 1 Access data bytes 7-4
542 * 0 Access data bytes 3-0
544 controller->IF1CMD = (1 << 7)
551 // Wait until IF2 is ready
552 while (controller->IF2STAT & (1U << 7));
555 * 7 Transfer from message object to IF
556 * 5 Transfer arbitration bits
557 * 4 Transfer control bits
559 * 1 Access data bytes 7-4
560 * 0 Access data bytes 3-0
562 controller->IF2CMD = (0 << 7)
572 int8_t rpp_can_init(const struct rpp_can_config *config)
575 #ifndef FREERTOS_POSIX
579 * Reset the bus drivers to NORMAL MODE. Refer TJA1041A reference for more details
580 * about the states of the driver.
582 dmmREG->PC4 = 1<<13; // set CAN_NSTB
583 dmmREG->PC5 = 1<<15; // clr CAN_EN
584 dmmREG->PC5 = 1<<13; // clr CAN_NSTB
585 dmmREG->PC4 = 1<<13; // set CAN_NSTB
586 dmmREG->PC4 = 1<<15; // set CAN_EN
590 if (can_reset(canREG1) == FAILURE)
592 if (can_reset(canREG2) == FAILURE)
594 if (can_reset(canREG3) == FAILURE)
597 if (reset_boxes() == FAILURE)
600 for (i=0; i<config->num_tx_obj; i++)
602 if (init_tx_box(config->tx_config[i]) == FAILURE)
606 for (i=0; i<config->num_rx_obj; i++)
608 if (init_rx_box(config->rx_config[i]) == FAILURE)
612 if (can_setup_IF(canREG1) == FAILURE)
614 if (can_setup_IF(canREG2) == FAILURE)
616 if (can_setup_IF(canREG3) == FAILURE)
619 if (can_configure(canREG1, config->ctrl[0]) == FAILURE)
621 if (can_configure(canREG2, config->ctrl[1]) == FAILURE)
623 if (can_configure(canREG3, config->ctrl[2]) == FAILURE)
626 can_leave_init(canREG1);
627 can_leave_init(canREG2);
628 can_leave_init(canREG3);
634 int8_t rpp_can_write(rpp_can_hw_obj hw_obj, const struct rpp_can_pdu *pdu)
637 canBASE_t *controller;
638 struct rpp_can_tx_config *tx_cfg = &can_config->tx_config[hw_obj];
640 if (!(controller = map_controller(tx_cfg->controller)))
645 // Wait until IF1 is ready to use
646 while (controller->IF1STAT & (1U << 7));
648 // Reset data length code
649 controller->IF1MCTL &= ~15;
650 controller->IF1MCTL |= pdu->dlc & 0xF;
653 * 31 Message is valid
654 * 30 Whether std/ext ID should be used
655 * 29 Direction is transmit
656 * 28-18 / 28-0 Message ID
658 controller->IF1ARB = (1 << 31)
659 | ((tx_cfg->type == RPP_CAN_STANDARD ? 0 : 1) << 30)
661 | (pdu->id << (tx_cfg->type == RPP_CAN_STANDARD ? 18 : 0));
663 for (i=0; i<pdu->dlc; i++)
665 #ifdef __little_endian__
666 controller->IF1DATx[i] = pdu->data[i];
668 controller->IF1DATx[s_can_byte_order[i]] = pdu->data[i];
672 // Copy TX data into message box
673 controller->IF1NO = tx_cfg->msg_obj;
679 int8_t rpp_can_check_tx_pend(rpp_can_hw_obj hw_obj, bool *tx_pend)
681 uint32_t reg_index, bit_mask;
682 canBASE_t *controller;
684 if (!(controller = map_controller(can_config->tx_config[hw_obj].controller)))
689 reg_index = can_config->tx_config[hw_obj].msg_obj >> 5;
690 bit_mask = 1 << ((can_config->tx_config[hw_obj].msg_obj - 1) & 0x1FU);
692 *tx_pend = controller->TXRQx[reg_index] & bit_mask;
697 int8_t rpp_can_read(rpp_can_hw_obj hw_obj, struct rpp_can_pdu *pdu)
699 uint32_t reg_index, bit_mask;
701 canBASE_t *controller;
703 if (!(controller = map_controller(can_config->rx_config[hw_obj].controller)))
708 reg_index = (can_config->rx_config[hw_obj].msg_obj - 1) >> 5;
709 bit_mask = 1 << ((can_config->rx_config[hw_obj].msg_obj - 1) & 0x1FU);
711 // FIXME: Check whether to abort if there are no new data
712 if (!(controller->NWDATx[reg_index] & bit_mask))
717 // Wait until IF2 is ready to use
718 while (controller->IF2STAT & (1U << 7));
720 // Copy data into IF2
721 controller->IF2NO = can_config->rx_config[hw_obj].msg_obj;
723 // Wait until IF2 is ready to use
724 while (controller->IF2STAT & (1U << 7));
726 // Get length of data received
727 pdu->dlc = controller->IF2MCTL & 0xFU;
730 if (controller->IF2ARB & (1 << 30))
732 pdu->id = (controller->IF2ARB & 0x1FFFFFFF) | CAN_EFF_FLAG;
736 pdu->id = (controller->IF2ARB & (0x7FF << 18)) >> 18;
739 // Copy RX data into pdu
740 for (i=0; i<pdu->dlc; i++)
742 #ifdef __little_endian__
743 pdu->data[i] = controller->IF2DATx[i];
745 pdu->data[i] = controller->IF2DATx[s_can_byte_order[i]];
752 int8_t rpp_can_check_rx_ind(rpp_can_hw_obj hw_obj, bool *rx_ind)
754 uint32_t reg_index, bit_mask;
755 canBASE_t *controller;
757 if (!(controller = map_controller(can_config->rx_config[hw_obj].controller)))
762 reg_index = (can_config->rx_config[hw_obj].msg_obj - 1) >> 5;
763 bit_mask = 1 << ((can_config->rx_config[hw_obj].msg_obj - 1) & 0x1FU);
765 *rx_ind = controller->NWDATx[reg_index] & bit_mask;