]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lib.git/blob - rpp/src/rpp/can.c
Bugfix: Looking for message object in wrong part of config
[pes-rpp/rpp-lib.git] / rpp / src / rpp / can.c
1 /* Copyright (C) 2013 Czech Technical University in Prague
2  *
3  * Authors:
4  *     - Carlos Jenkins <carlos@jenkins.co.cr>
5  *     - Karolína Burešová <karry@karryanna.cz>
6  *
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.
11  *
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.
16  *
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/>.
19  *
20  * File : can.c
21  * Abstract:
22  *     CAN Bus Communication RPP API implementation file.
23  *
24  * References:
25  *     can.h
26  *     RPP API documentation.
27  */
28
29
30 #include "rpp/rpp.h"
31 #include <math.h>
32
33 #if rppCONFIG_INCLUDE_CAN == 1
34
35 static const struct rpp_can_config *can_config = NULL;
36
37
38
39 typedef volatile struct CANBase
40 {
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         */
95 #else
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       */
100 #endif
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         */
112 #else
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       */
117 #endif
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                 */
162 } canBASE_t;
163
164 #define canREG1 ((canBASE_t *) 0xFFF7DC00U)
165 #define canREG2 ((canBASE_t *) 0xFFF7DE00U)
166 #define canREG3 ((canBASE_t *) 0xFFF7E000U)
167
168 #ifndef __little_endian__
169     static const uint32_t s_can_byte_order[] = {3, 2, 1, 0, 7, 6, 5, 4};
170 #endif
171
172
173
174
175
176 static canBASE_t * map_controller(uint8_t controller)
177 {
178     switch (controller)
179     {
180         case 1:
181             return canREG1;
182         case 2:
183             return canREG2;
184         case 3:
185             return canREG3;
186         default:
187             return NULL;
188     }
189 }
190
191
192 static int8_t init_tx_box(struct rpp_can_tx_config cfg)
193 {
194     canBASE_t *controller;
195
196     if (!(controller = map_controller(cfg.controller)))
197         return FAILURE;
198
199     // Wait until IF1 is ready to use
200     while (controller->IF1STAT & (1U << 7));
201
202     /**
203     * 31 Set whether use of std/ext ID should have effect on acceptance filtering
204     */
205     controller->IF1MSK = ((cfg.type == RPP_CAN_MIXED ? 0 : 1) << 31);
206
207     /**
208     * 31 Message object is valid
209     * 30 Set whether to use extented identifier
210     * 29 Set direction as transmit
211     */
212     controller->IF1ARB = (1U << 31)
213                           | ((cfg.type == RPP_CAN_STANDARD ? 0 : 1) << 30)
214                           | (1 << 29);
215
216     /**
217     *  7 End of buffer
218     * 4-1 Data length code
219     */
220     controller->IF1MCTL = (1 << 7)
221                            | 8;
222
223     /**
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
229     */
230     controller->IF1CMD = (1U << 7)
231                           | (1 << 5)
232                           | (1 << 4);
233
234     // Write MSG object number and enable transfer
235     controller->IF1NO = cfg.msg_obj;
236
237     return SUCCESS;
238 }
239
240 static int8_t init_rx_box(struct rpp_can_rx_config cfg)
241 {
242     canBASE_t *controller;
243
244     if (!(controller = map_controller(cfg.controller)))
245         return FAILURE;
246
247     // Wait until IF2 is ready to use
248     while (controller->IF2STAT & (1U << 7));
249
250     /**
251     * 31 Set whether use of std/ext ID should have effect on acceptance filtering
252     * 28-1 Set mask
253     */
254     controller->IF2MSK = ((cfg.type == RPP_CAN_MIXED ? 0 : 1U) << 31)
255                           | cfg.mask;
256
257     /**
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
262     */
263     controller->IF2ARB = (1U << 31)
264                           | ((cfg.type == RPP_CAN_STANDARD ? 0 : 1) << 30)
265                           | (0 << 29)
266                           | cfg.id << (cfg.type == RPP_CAN_STANDARD ? 18 : 0);
267
268     /**
269     * 12 Use mask for filtering
270     *  7 End of buffer
271     * 4-1 Data length code
272     */
273     controller->IF2MCTL = (1 << 12)
274                            | (1 << 7)
275                            | 8;
276
277     /**
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
284     */
285     controller->IF2CMD = (1 << 7)
286                           | (1 << 6)
287                           | (1 << 5)
288                           | (1 << 4);
289
290     // Write MSG object number and enable transfer
291     controller->IF2NO = cfg.msg_obj;
292
293     return SUCCESS;
294 }
295
296
297
298 static int8_t can_reset(canBASE_t *controller)
299 {
300     /**
301     * 6 Request write access to config registers
302     * 0 Enter initialization mode
303     */
304     controller->CTL = 0
305                        | (1 << 6)
306                        | (1 << 0);
307
308     controller->ES;
309     controller->ABOTR = 0;
310
311     controller->TIOC = (0 << 0);
312     controller->RIOC = (0 << 0);
313
314     return SUCCESS;
315 }
316
317 static int8_t can_configure(canBASE_t *controller, const struct rpp_can_ctrl_config cfg)
318 {
319     const uint32_t FREQ = 80000000;
320
321     // Minimal propagation time
322     // NOTE: The time is just guessed from working code
323     const double PROP_MIN = 0.00000075;
324
325     double bit_time, prop_part;
326     uint32_t prescaler, ts, ts1, ts2, prop;
327     uint32_t n;
328     double check;
329
330     /**
331     * Refer to TMS570LS3137 manual (spnu499a) for more information
332     * about calculation of bit timing parameters
333     */
334
335     bit_time = 1.0/cfg.baudrate;
336
337     // We shall abort if bit time isn't integer multiple of CAN clock
338     /**
339     * Some tolerance is needed due to the inaccuracy of binary representation
340     * Feel free to replace those few lines with more elegant solution
341     */
342     check = bit_time * FREQ;
343     if (fabs(check - nearbyint(check)) >= 0.001)
344     {
345         return FAILURE;
346     }
347
348
349     /**
350     * If baudrate is low enough, we set
351     * Prop_Seg = 1, Phase_Seg1 = Phase_Seg2 = SJW = 4
352     * which should be optimal.
353     */
354     if (cfg.baudrate <= 250000)
355     {
356         // 10 stands for 10 time quanta of bit time
357         prescaler = FREQ*bit_time / 10;
358
359         ts2 = ts1 = 4;
360         prop = 1;
361     }
362
363     else
364     {
365         prop_part = PROP_MIN / bit_time;
366
367         if (prop_part <= 0.5)
368         {
369             n = 10;
370             prop = (int) (prop_part / 0.1) + 1;
371         }
372         else
373         {
374             n = 20;
375             prop = (int) (prop_part / 0.05) + 1;
376         }
377
378         ts = n - 1 - prop;
379         ts1 = ts / 2;
380         ts2 = (ts % 2 ? ts1 + 1 : ts1);
381
382         prescaler = FREQ*bit_time / n;
383     }
384
385     /**
386     * We make TSeg2 equal SJW since our calculation guarantees
387     * that TSeg1 >= TSeg2 AND Tseg2 <= 4
388     */
389     // All actual values are by 1 higher than those programmed
390     controller->BTR = (((prescaler-1) >> 6) << 16)
391                        | ((ts2-1) << 12)
392                        | (((ts1+prop)-1) << 8)
393                        | ((ts2-1) << 6)
394                        | ((prescaler-1) & 63);
395
396     return SUCCESS;
397 }
398
399 static inline can_leave_init(canBASE_t *controller)
400 {
401     controller->CTL &= ~( (1 << 6) | (1 << 0) );
402 }
403
404 static int8_t reset_box(canBASE_t *controller, uint32_t msg_obj)
405 {
406     // Wait until IF1 is ready
407     while (controller->IF1STAT & (1U << 7));
408
409     controller->IF1MSK = 0;
410     controller->IF1ARB = 0;
411     controller->IF1MCTL = (1 << 7) | 8;
412     controller->IF1CMD = (1 << 7)
413                           | (1 << 6)
414                           | (1 << 5)
415                           | (1 << 4);
416     controller->IF1NO = msg_obj;
417
418     return SUCCESS;
419 }
420
421 static int8_t reset_boxes(void)
422 {
423     uint32_t i;
424
425     for (i=1; i<=64; i++)
426     {
427         reset_box(canREG1, i);
428     }
429
430     for (i=1; i<=64; i++)
431     {
432         reset_box(canREG2, i);
433     }
434
435     for (i=1; i<=32; i++)
436     {
437         reset_box(canREG3, i);
438     }
439
440     return SUCCESS;
441 }
442
443 int8_t can_setup_IF(canBASE_t *controller)
444 {
445     // Wait until IF1 is ready
446     while (controller->IF1STAT & (1U << 7));
447
448     /**
449     * 7 Transfer from IF to message object
450     * 5 Transfer arbitration bits
451     * 4 Transfer control bits
452     * 2 Set TxRqst bit
453     * 1 Access data bytes 7-4
454     * 0 Access data bytes 3-0
455     */
456     controller->IF1CMD = (1 << 7)
457                           | (1 << 5)
458                           | (1 << 4)
459                           | (1 << 2)
460                           | (1 << 1)
461                           | (1 << 0);
462
463     // Wait until IF2 is ready
464     while (controller->IF2STAT & (1U << 7));
465
466     /**
467     * 7 Transfer from message object to IF
468     * 5 Transfer arbitration bits
469     * 4 Transfer control bits
470     * 2 Clear NewDat bit
471     * 1 Access data bytes 7-4
472     * 0 Access data bytes 3-0
473     */
474     controller->IF2CMD = (0 << 7)
475                           | (1 << 5)
476                           | (1 << 4)
477                           | (1 << 2)
478                           | (1 << 1)
479                           | (1 << 0);
480
481     return SUCCESS;
482 }
483
484 int8_t rpp_can_init(const struct rpp_can_config *config)
485 {
486     uint16_t i;
487
488     can_config = config;
489
490     if (can_reset(canREG1) == FAILURE)
491        return FAILURE;
492     if (can_reset(canREG2) == FAILURE)
493        return FAILURE;
494     if (can_reset(canREG3) == FAILURE)
495        return FAILURE;
496
497     if (reset_boxes() == FAILURE)
498        return FAILURE;
499
500     for (i=0; i<config->num_tx_obj; i++)
501     {
502         if (init_tx_box(config->tx_config[i]) == FAILURE)
503            return FAILURE;
504     }
505
506     for (i=0; i<config->num_rx_obj; i++)
507     {
508         if (init_rx_box(config->rx_config[i]) == FAILURE)
509            return FAILURE;
510     }
511
512     if (can_setup_IF(canREG1) == FAILURE)
513         return FAILURE;
514     if (can_setup_IF(canREG2) == FAILURE)
515         return FAILURE;
516     if (can_setup_IF(canREG3) == FAILURE)
517         return FAILURE;
518
519     if (can_configure(canREG1, config->ctrl[0]) == FAILURE)
520         return FAILURE;
521     if (can_configure(canREG2, config->ctrl[1]) == FAILURE)
522         return FAILURE;
523     if (can_configure(canREG3, config->ctrl[2]) == FAILURE)
524         return FAILURE;
525
526     if (can_leave_init(canREG1) == FAILURE)
527         return FAILURE;
528     if (can_leave_init(canREG2) == FAILURE)
529         return FAILURE;
530     if (can_leave_init(canREG3) == FAILURE)
531         return FAILURE;
532
533     return SUCCESS;
534 }
535
536
537 int8_t rpp_can_write(rpp_can_hw_obj hw_obj, const struct rpp_can_pdu *pdu)
538 {
539     uint32_t reg_index, bit_index;
540     uint8_t i;
541     canBASE_t *controller;
542     struct rpp_can_tx_config *tx_cfg = &can_config->tx_config[hw_obj];
543
544     if (!(controller = map_controller(tx_cfg->controller)))
545     {
546         return FAILURE;
547     }
548
549     reg_index = (tx_cfg->msg_obj - 1) >> 5;
550     bit_index = 1 << ((tx_cfg->msg_obj - 1) & 0x1FU);
551
552     // FIXME: Check whether sending should be aborted or message overwritten
553     if (controller->TXRQx[reg_index] & bit_index)
554     {
555         return FAILURE;
556     }
557
558
559     // Wait until IF1 is ready to use
560     while (controller->IF1STAT & (1U << 7));
561
562     // Reset data length code
563     controller->IF1MCTL &= ~15;
564     controller->IF1MCTL |= pdu->dlc & 0xF;
565
566     /**
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
571     */
572     controller->IF1ARB = (1 << 31)
573                           | ((tx_cfg->type == RPP_CAN_STANDARD ? 0 : 1) << 30)
574                           | (1 << 29)
575                           | (pdu->id << (tx_cfg->type == RPP_CAN_STANDARD ? 18 : 0));
576
577     for (i=0; i<pdu->dlc; i++)
578     {
579 #ifdef __little_endian__
580         controller->IF1DATx[i] = pdu->data[i];
581 #else
582         controller->IF1DATx[s_can_byte_order[i]] = pdu->data[i];
583 #endif
584     }
585
586     // Copy TX data into message box
587     controller->IF1NO = tx_cfg->msg_obj;
588
589     return SUCCESS;
590 }
591
592
593 int8_t rpp_can_check_tx_con(rpp_can_hw_obj hw_obj, bool *tx_con)
594 {
595     uint32_t reg_index, bit_index;
596     canBASE_t *controller;
597
598     if (!(controller = map_controller(can_config->tx_config[hw_obj].controller)))
599     {
600         return FAILURE;
601     }
602
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);
605
606     *tx_con = controller->TXRQx[reg_index] & bit_index;
607
608     return SUCCESS;
609 }
610
611 int8_t rpp_can_read(rpp_can_hw_obj hw_obj, struct rpp_can_pdu *pdu)
612 {
613     uint32_t reg_index, bit_index;
614     uint32_t i;
615     canBASE_t *controller;
616
617     if (!(controller = map_controller(can_config->rx_config[hw_obj].controller)))
618     {
619         return FAILURE;
620     }
621
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);
624
625     // FIXME: Check whether to abort if there are no new data
626     if (!(controller->NWDATx[reg_index] & bit_index))
627     {
628         return FAILURE;
629     }
630
631     // Wait until IF2 is ready to use
632     while (controller->IF2STAT & (1U << 7));
633
634     // Copy data into IF2
635     controller->IF2NO = can_config->rx_config[hw_obj].msg_obj;
636
637     // Wait until IF2 is ready to use
638     while (controller->IF2STAT & (1U << 7));
639
640     // Get length of data received
641     pdu->dlc = controller->IF2MCTL & 0xFU;
642
643     // Copy RX data into pdu
644     for (i=0; i<pdu->dlc; i++)
645     {
646 #ifdef __little_endian__
647         pdu->data[i] = controller->IF2DATx[i];
648 #else
649         pdu->data[i] = controller->IF2DATx[s_can_byte_order[i]];
650 #endif
651     }
652
653     return SUCCESS;
654 }
655
656 int8_t rpp_can_check_rx_ind(rpp_can_hw_obj hw_obj, bool *rx_ind)
657 {
658     uint32_t reg_index, bit_index;
659     canBASE_t *controller;
660
661     if (!(controller = map_controller(can_config->rx_config[hw_obj].controller)))
662     {
663         return FAILURE;
664     }
665
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);
668
669     *rx_ind = controller->NWDATx[reg_index] & bit_index;
670
671     return SUCCESS;
672 }
673
674
675
676 #endif /* rppCONFIG_INCLUDE_CAN */