1 /* Copyright (C) 2013 Czech Technical University in Prague
4 * - Carlos Jenkins <carlos@jenkins.co.cr>
5 * - Karolína Burešová <karry@karryanna.cz>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 * CAN Bus Communication RPP API implementation file.
26 * RPP API documentation.
33 #if rppCONFIG_INCLUDE_CAN == 1
35 static const struct rpp_can_config *can_config = NULL;
39 typedef volatile struct CANBase
41 uint32_t CTL; /**< 0x0000: Control Register */
42 uint32_t ES; /**< 0x0004: Error and Status Register */
43 uint32_t EERC; /**< 0x0008: Error Counter Register */
44 uint32_t BTR; /**< 0x000C: Bit Timing Register */
45 uint32_t INT; /**< 0x0010: Interrupt Register */
46 uint32_t TEST; /**< 0x0014: Test Register */
47 uint32_t : 32U; /**< 0x0018: Reserved */
48 uint32_t PERR; /**< 0x001C: Parity/SECDED Error Code Register */
49 uint32_t REL; /**< 0x0020: Core Release Register */
50 uint32_t ECCDIAG; /**< 0x0024: ECC Diagnostic Register */
51 uint32_t ECCDIADSTAT; /**< 0x0028: ECC Diagnostic Status Register */
52 uint32_t : 32U; /**< 0x002C: Reserved */
53 uint32_t : 32U; /**< 0x0030: Reserved */
54 uint32_t : 32U; /**< 0x0034: Reserved */
55 uint32_t : 32U; /**< 0x0038: Reserved */
56 uint32_t : 32U; /**< 0x003C: Reserved */
57 uint32_t : 32U; /**< 0x0040: Reserved */
58 uint32_t : 32U; /**< 0x0044: Reserved */
59 uint32_t : 32U; /**< 0x0048: Reserved */
60 uint32_t : 32U; /**< 0x004C: Reserved */
61 uint32_t : 32U; /**< 0x0050: Reserved */
62 uint32_t : 32U; /**< 0x0054: Reserved */
63 uint32_t : 32U; /**< 0x0058: Reserved */
64 uint32_t : 32U; /**< 0x005C: Reserved */
65 uint32_t : 32U; /**< 0x0060: Reserved */
66 uint32_t : 32U; /**< 0x0064: Reserved */
67 uint32_t : 32U; /**< 0x0068: Reserved */
68 uint32_t : 32U; /**< 0x006C: Reserved */
69 uint32_t : 32U; /**< 0x0070: Reserved */
70 uint32_t : 32U; /**< 0x0074: Reserved */
71 uint32_t : 32U; /**< 0x0078: Reserved */
72 uint32_t : 32U; /**< 0x007C: Reserved */
73 uint32_t ABOTR; /**< 0x0080: Auto Bus On Time Register */
74 uint32_t TXRQX; /**< 0x0084: Transmission Request X Register */
75 uint32_t TXRQx[4U]; /**< 0x0088-0x0094: Transmission Request Registers */
76 uint32_t NWDATX; /**< 0x0098: New Data X Register */
77 uint32_t NWDATx[4U]; /**< 0x009C-0x00A8: New Data Registers */
78 uint32_t INTPNDX; /**< 0x00AC: Interrupt Pending X Register */
79 uint32_t INTPNDx[4U]; /**< 0x00B0-0x00BC: Interrupt Pending Registers */
80 uint32_t MSGVALX; /**< 0x00C0: Message Valid X Register */
81 uint32_t MSGVALx[4U]; /**< 0x00C4-0x00D0: Message Valid Registers */
82 uint32_t : 32U; /**< 0x00D4: Reserved */
83 uint32_t INTMUXx[4U]; /**< 0x00D8-0x00E4: Interrupt Multiplexer Registers */
84 uint32_t : 32U; /**< 0x00E8: Reserved */
85 uint32_t : 32U; /**< 0x00EC: Reserved */
86 uint32_t : 32U; /**< 0x00F0: Reserved */
87 uint32_t : 32U; /**< 0x00F4: Reserved */
88 uint32_t : 32U; /**< 0x00F8: Reserved */
89 uint32_t : 32U; /**< 0x00FC: Reserved */
90 #if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
91 uint8_t IF1NO; /**< 0x0100: IF1 Command Register, Msg Number */
92 uint8_t IF1STAT; /**< 0x0100: IF1 Command Register, Status */
93 uint8_t IF1CMD; /**< 0x0100: IF1 Command Register, Command */
94 uint32_t : 8U; /**< 0x0100: IF1 Command Register, Reserved */
96 uint32_t : 8U; /**< 0x0100: IF1 Command Register, Reserved */
97 uint8_t IF1CMD; /**< 0x0100: IF1 Command Register, Command */
98 uint8_t IF1STAT; /**< 0x0100: IF1 Command Register, Status */
99 uint8_t IF1NO; /**< 0x0100: IF1 Command Register, Msg Number */
101 uint32_t IF1MSK; /**< 0x0104: IF1 Mask Register */
102 uint32_t IF1ARB; /**< 0x0108: IF1 Arbitration Register */
103 uint32_t IF1MCTL; /**< 0x010C: IF1 Message Control Register */
104 uint8_t IF1DATx[8U]; /**< 0x0110-0x0114: IF1 Data A and B Registers */
105 uint32_t : 32U; /**< 0x0118: Reserved */
106 uint32_t : 32U; /**< 0x011C: Reserved */
107 #if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
108 uint8_t IF2NO; /**< 0x0120: IF2 Command Register, Msg No */
109 uint8_t IF2STAT; /**< 0x0120: IF2 Command Register, Status */
110 uint8_t IF2CMD; /**< 0x0120: IF2 Command Register, Command */
111 uint32_t : 8U; /**< 0x0120: IF2 Command Register, Reserved */
113 uint32_t : 8U; /**< 0x0120: IF2 Command Register, Reserved */
114 uint8_t IF2CMD; /**< 0x0120: IF2 Command Register, Command */
115 uint8_t IF2STAT; /**< 0x0120: IF2 Command Register, Status */
116 uint8_t IF2NO; /**< 0x0120: IF2 Command Register, Msg Number */
118 uint32_t IF2MSK; /**< 0x0124: IF2 Mask Register */
119 uint32_t IF2ARB; /**< 0x0128: IF2 Arbitration Register */
120 uint32_t IF2MCTL; /**< 0x012C: IF2 Message Control Register */
121 uint8_t IF2DATx[8U]; /**< 0x0130-0x0134: IF2 Data A and B Registers */
122 uint32_t : 32U; /**< 0x0138: Reserved */
123 uint32_t : 32U; /**< 0x013C: Reserved */
124 uint32_t IF3OBS; /**< 0x0140: IF3 Observation Register */
125 uint32_t IF3MSK; /**< 0x0144: IF3 Mask Register */
126 uint32_t IF3ARB; /**< 0x0148: IF3 Arbitration Register */
127 uint32_t IF3MCTL; /**< 0x014C: IF3 Message Control Register */
128 uint8_t IF3DATx[8U]; /**< 0x0150-0x0154: IF3 Data A and B Registers */
129 uint32_t : 32U; /**< 0x0158: Reserved */
130 uint32_t : 32U; /**< 0x015C: Reserved */
131 uint32_t IF3UEy[4U]; /**< 0x0160-0x016C: IF3 Update Enable Registers */
132 uint32_t : 32U; /**< 0x0170: Reserved */
133 uint32_t : 32U; /**< 0x0174: Reserved */
134 uint32_t : 32U; /**< 0x0178: Reserved */
135 uint32_t : 32U; /**< 0x017C: Reserved */
136 uint32_t : 32U; /**< 0x0180: Reserved */
137 uint32_t : 32U; /**< 0x0184: Reserved */
138 uint32_t : 32U; /**< 0x0188: Reserved */
139 uint32_t : 32U; /**< 0x018C: Reserved */
140 uint32_t : 32U; /**< 0x0190: Reserved */
141 uint32_t : 32U; /**< 0x0194: Reserved */
142 uint32_t : 32U; /**< 0x0198: Reserved */
143 uint32_t : 32U; /**< 0x019C: Reserved */
144 uint32_t : 32U; /**< 0x01A0: Reserved */
145 uint32_t : 32U; /**< 0x01A4: Reserved */
146 uint32_t : 32U; /**< 0x01A8: Reserved */
147 uint32_t : 32U; /**< 0x01AC: Reserved */
148 uint32_t : 32U; /**< 0x01B0: Reserved */
149 uint32_t : 32U; /**< 0x01B4: Reserved */
150 uint32_t : 32U; /**< 0x01B8: Reserved */
151 uint32_t : 32U; /**< 0x01BC: Reserved */
152 uint32_t : 32U; /**< 0x01C0: Reserved */
153 uint32_t : 32U; /**< 0x01C4: Reserved */
154 uint32_t : 32U; /**< 0x01C8: Reserved */
155 uint32_t : 32U; /**< 0x01CC: Reserved */
156 uint32_t : 32U; /**< 0x01D0: Reserved */
157 uint32_t : 32U; /**< 0x01D4: Reserved */
158 uint32_t : 32U; /**< 0x01D8: Reserved */
159 uint32_t : 32U; /**< 0x01DC: Reserved */
160 uint32_t TIOC; /**< 0x01E0: TX IO Control Register */
161 uint32_t RIOC; /**< 0x01E4: RX IO Control Register */
164 #define canREG1 ((canBASE_t *) 0xFFF7DC00U)
165 #define canREG2 ((canBASE_t *) 0xFFF7DE00U)
166 #define canREG3 ((canBASE_t *) 0xFFF7E000U)
168 #ifndef __little_endian__
169 static const uint32_t s_can_byte_order[] = {3, 2, 1, 0, 7, 6, 5, 4};
176 static canBASE_t * map_controller(uint8_t controller)
192 static int8_t init_tx_box(struct rpp_can_tx_config cfg)
194 canBASE_t *controller;
196 if (!(controller = map_controller(cfg.controller)))
199 // Wait until IF1 is ready to use
200 while (controller->IF1STAT & (1U << 7));
203 * 31 Set whether use of std/ext ID should have effect on acceptance filtering
205 controller->IF1MSK = ((cfg.type == RPP_CAN_MIXED ? 0 : 1) << 31);
208 * 31 Message object is valid
209 * 30 Set whether to use extented identifier
210 * 29 Set direction as transmit
212 controller->IF1ARB = (1U << 31)
213 | ((cfg.type == RPP_CAN_STANDARD ? 0 : 1) << 30)
218 * 4-1 Data length code
220 controller->IF1MCTL = (1 << 7)
224 * Note that IF1CMD does not refer to whole CMD register
225 * (it refers to bits 23-16 of that register)
226 * 7 Transfer from IF to message object
227 * 5 Transfer arbitration bits
228 * 4 Transfer control bits
230 controller->IF1CMD = (1U << 7)
234 // Write MSG object number and enable transfer
235 controller->IF1NO = cfg.msg_obj;
240 static int8_t init_rx_box(struct rpp_can_rx_config cfg)
242 canBASE_t *controller;
244 if (!(controller = map_controller(cfg.controller)))
247 // Wait until IF2 is ready to use
248 while (controller->IF2STAT & (1U << 7));
251 * 31 Set whether use of std/ext ID should have effect on acceptance filtering
254 controller->IF2MSK = ((cfg.type == RPP_CAN_MIXED ? 0 : 1U) << 31)
258 * 31 Message object is valid
259 * 30 Set whether extended ID should be used
260 * 29 Direction is read
261 * 28-18 / 28-1 Object ID
263 controller->IF2ARB = (1U << 31)
264 | ((cfg.type == RPP_CAN_STANDARD ? 0 : 1) << 30)
266 | cfg.id << (cfg.type == RPP_CAN_STANDARD ? 18 : 0);
269 * 12 Use mask for filtering
271 * 4-1 Data length code
273 controller->IF2MCTL = (1 << 12)
278 * Note that IF2CMD does not refer to whole CMD register
279 * (it refers to bits 23-16 of that register)
280 * 7 Transfer from IF to message object
281 * 6 Transfer mask bits
282 * 5 Transfer arbitration bits
283 * 4 Transfer control bits
285 controller->IF2CMD = (1 << 7)
290 // Write MSG object number and enable transfer
291 controller->IF2NO = cfg.msg_obj;
298 static int8_t can_reset(canBASE_t *controller)
301 * 6 Request write access to config registers
302 * 0 Enter initialization mode
309 controller->ABOTR = 0;
311 controller->TIOC = (0 << 0);
312 controller->RIOC = (0 << 0);
317 static int8_t can_configure(canBASE_t *controller, const struct rpp_can_ctrl_config cfg)
319 const uint32_t FREQ = 80000000;
321 // Minimal propagation time
322 // NOTE: The time is just guessed from working code
323 const double PROP_MIN = 0.00000075;
325 double bit_time, prop_part;
326 uint32_t prescaler, ts, ts1, ts2, prop;
331 * Refer to TMS570LS3137 manual (spnu499a) for more information
332 * about calculation of bit timing parameters
335 bit_time = 1.0/cfg.baudrate;
337 // We shall abort if bit time isn't integer multiple of CAN clock
339 * Some tolerance is needed due to the inaccuracy of binary representation
340 * Feel free to replace those few lines with more elegant solution
342 check = bit_time * FREQ;
343 if (fabs(check - nearbyint(check)) >= 0.001)
350 * If baudrate is low enough, we set
351 * Prop_Seg = 1, Phase_Seg1 = Phase_Seg2 = SJW = 4
352 * which should be optimal.
354 if (cfg.baudrate <= 250000)
356 // 10 stands for 10 time quanta of bit time
357 prescaler = FREQ*bit_time / 10;
365 prop_part = PROP_MIN / bit_time;
367 if (prop_part <= 0.5)
370 prop = (int) (prop_part / 0.1) + 1;
375 prop = (int) (prop_part / 0.05) + 1;
380 ts2 = (ts % 2 ? ts1 + 1 : ts1);
382 prescaler = FREQ*bit_time / n;
386 * We make TSeg2 equal SJW since our calculation guarantees
387 * that TSeg1 >= TSeg2 AND Tseg2 <= 4
389 // All actual values are by 1 higher than those programmed
390 controller->BTR = (((prescaler-1) >> 6) << 16)
392 | (((ts1+prop)-1) << 8)
394 | ((prescaler-1) & 63);
399 static inline can_leave_init(canBASE_t *controller)
401 controller->CTL &= ~( (1 << 6) | (1 << 0) );
404 static int8_t reset_box(canBASE_t *controller, uint32_t msg_obj)
406 // Wait until IF1 is ready
407 while (controller->IF1STAT & (1U << 7));
409 controller->IF1MSK = 0;
410 controller->IF1ARB = 0;
411 controller->IF1MCTL = (1 << 7) | 8;
412 controller->IF1CMD = (1 << 7)
416 controller->IF1NO = msg_obj;
421 static int8_t reset_boxes(void)
425 for (i=1; i<=64; i++)
427 reset_box(canREG1, i);
430 for (i=1; i<=64; i++)
432 reset_box(canREG2, i);
435 for (i=1; i<=32; i++)
437 reset_box(canREG3, i);
443 int8_t can_setup_IF(canBASE_t *controller)
445 // Wait until IF1 is ready
446 while (controller->IF1STAT & (1U << 7));
449 * 7 Transfer from IF to message object
450 * 5 Transfer arbitration bits
451 * 4 Transfer control bits
453 * 1 Access data bytes 7-4
454 * 0 Access data bytes 3-0
456 controller->IF1CMD = (1 << 7)
463 // Wait until IF2 is ready
464 while (controller->IF2STAT & (1U << 7));
467 * 7 Transfer from message object to IF
468 * 5 Transfer arbitration bits
469 * 4 Transfer control bits
471 * 1 Access data bytes 7-4
472 * 0 Access data bytes 3-0
474 controller->IF2CMD = (0 << 7)
484 int8_t rpp_can_init(const struct rpp_can_config *config)
490 if (can_reset(canREG1) == FAILURE)
492 if (can_reset(canREG2) == FAILURE)
494 if (can_reset(canREG3) == FAILURE)
497 if (reset_boxes() == FAILURE)
500 for (i=0; i<config->num_tx_obj; i++)
502 if (init_tx_box(config->tx_config[i]) == FAILURE)
506 for (i=0; i<config->num_rx_obj; i++)
508 if (init_rx_box(config->rx_config[i]) == FAILURE)
512 if (can_setup_IF(canREG1) == FAILURE)
514 if (can_setup_IF(canREG2) == FAILURE)
516 if (can_setup_IF(canREG3) == FAILURE)
519 if (can_configure(canREG1, config->ctrl[0]) == FAILURE)
521 if (can_configure(canREG2, config->ctrl[1]) == FAILURE)
523 if (can_configure(canREG3, config->ctrl[2]) == FAILURE)
526 if (can_leave_init(canREG1) == FAILURE)
528 if (can_leave_init(canREG2) == FAILURE)
530 if (can_leave_init(canREG3) == FAILURE)
537 int8_t rpp_can_write(rpp_can_hw_obj hw_obj, const struct rpp_can_pdu *pdu)
539 uint32_t reg_index, bit_index;
541 canBASE_t *controller;
542 struct rpp_can_tx_config *tx_cfg = &can_config->tx_config[hw_obj];
544 if (!(controller = map_controller(tx_cfg->controller)))
549 reg_index = (tx_cfg->msg_obj - 1) >> 5;
550 bit_index = 1 << ((tx_cfg->msg_obj - 1) & 0x1FU);
552 // FIXME: Check whether sending should be aborted or message overwritten
553 if (controller->TXRQx[reg_index] & bit_index)
559 // Wait until IF1 is ready to use
560 while (controller->IF1STAT & (1U << 7));
562 // Reset data length code
563 controller->IF1MCTL &= ~15;
564 controller->IF1MCTL |= pdu->dlc & 0xF;
567 * 31 Message is valid
568 * 30 Whether std/ext ID should be used
569 * 29 Direction is transmit
570 * 28-18 / 28-0 Message ID
572 controller->IF1ARB = (1 << 31)
573 | ((tx_cfg->type == RPP_CAN_STANDARD ? 0 : 1) << 30)
575 | (pdu->id << (tx_cfg->type == RPP_CAN_STANDARD ? 18 : 0));
577 for (i=0; i<pdu->dlc; i++)
579 #ifdef __little_endian__
580 controller->IF1DATx[i] = pdu->data[i];
582 controller->IF1DATx[s_can_byte_order[i]] = pdu->data[i];
586 // Copy TX data into message box
587 controller->IF1NO = tx_cfg->msg_obj;
593 int8_t rpp_can_check_tx_con(rpp_can_hw_obj hw_obj, bool *tx_con)
595 uint32_t reg_index, bit_index;
596 canBASE_t *controller;
598 if (!(controller = map_controller(can_config->tx_config[hw_obj].controller)))
603 reg_index = can_config->tx_config[hw_obj].msg_obj >> 5;
604 bit_index = 1 << ((can_config->tx_config[hw_obj].msg_obj - 1) & 0x1FU);
606 *tx_con = controller->TXRQx[reg_index] & bit_index;
611 int8_t rpp_can_read(rpp_can_hw_obj hw_obj, struct rpp_can_pdu *pdu)
613 uint32_t reg_index, bit_index;
615 canBASE_t *controller;
617 if (!(controller = map_controller(can_config->rx_config[hw_obj].controller)))
622 reg_index = (can_config->rx_config[hw_obj].msg_obj - 1) >> 5;
623 bit_index = 1 << ((can_config->rx_config[hw_obj].msg_obj - 1) & 0x1FU);
625 // FIXME: Check whether to abort if there are no new data
626 if (!(controller->NWDATx[reg_index] & bit_index))
631 // Wait until IF2 is ready to use
632 while (controller->IF2STAT & (1U << 7));
634 // Copy data into IF2
635 controller->IF2NO = can_config->rx_config[hw_obj].msg_obj;
637 // Wait until IF2 is ready to use
638 while (controller->IF2STAT & (1U << 7));
640 // Get length of data received
641 pdu->dlc = controller->IF2MCTL & 0xFU;
643 // Copy RX data into pdu
644 for (i=0; i<pdu->dlc; i++)
646 #ifdef __little_endian__
647 pdu->data[i] = controller->IF2DATx[i];
649 pdu->data[i] = controller->IF2DATx[s_can_byte_order[i]];
656 int8_t rpp_can_check_rx_ind(rpp_can_hw_obj hw_obj, bool *rx_ind)
658 uint32_t reg_index, bit_index;
659 canBASE_t *controller;
661 if (!(controller = map_controller(can_config->rx_config[hw_obj].controller)))
666 reg_index = (can_config->rx_config[hw_obj].msg_obj - 1) >> 5;
667 bit_index = 1 << ((can_config->rx_config[hw_obj].msg_obj - 1) & 0x1FU);
669 *rx_ind = controller->NWDATx[reg_index] & bit_index;
676 #endif /* rppCONFIG_INCLUDE_CAN */