source: EcnlProtoTool/trunk/asp3_dcre/mbed/targets/TARGET_RENESAS/TARGET_RZA1XX/can_api.c@ 439

Last change on this file since 439 was 439, checked in by coas-nagasima, 4 years ago

mrubyを2.1.1に更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 30.9 KB
Line 
1/* mbed Microcontroller Library
2 * Copyright (c) 2006-2013 ARM Limited
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include <string.h>
17#include "mbed_assert.h"
18#include "can_api.h"
19#include "RZ_A1_Init.h"
20#include "cmsis.h"
21#include "PeripheralPins.h"
22#include "iodefine.h"
23#include "r_typedefs.h"
24#include "mbed_drv_cfg.h"
25
26#if defined(TARGET_RZA1H)
27#define CAN_NUM 5
28#else
29#define CAN_NUM 2
30#endif
31#define CAN_SND_RCV 2
32#define IRQ_NUM 8
33
34static void can_rec_irq(uint32_t ch);
35static void can_trx_irq(uint32_t ch);
36static void can_err_irq(uint32_t ch, CanIrqType type);
37static void can0_rec_irq(void);
38static void can0_trx_irq(void);
39static void can0_err_warning_irq(void);
40static void can0_overrun_irq(void);
41static void can0_passive_irq(void);
42static void can0_arb_lost_irq(void);
43static void can0_bus_err_irq(void);
44static void can1_rec_irq(void);
45static void can1_trx_irq(void);
46static void can1_err_warning_irq(void);
47static void can1_overrun_irq(void);
48static void can1_passive_irq(void);
49static void can1_arb_lost_irq(void);
50static void can1_bus_err_irq(void);
51#if defined(TARGET_RZA1H)
52static void can2_rec_irq(void);
53static void can2_trx_irq(void);
54static void can2_err_warning_irq(void);
55static void can2_overrun_irq(void);
56static void can2_passive_irq(void);
57static void can2_arb_lost_irq(void);
58static void can2_bus_err_irq(void);
59static void can3_rec_irq(void);
60static void can3_trx_irq(void);
61static void can3_err_warning_irq(void);
62static void can3_overrun_irq(void);
63static void can3_passive_irq(void);
64static void can3_arb_lost_irq(void);
65static void can3_bus_err_irq(void);
66static void can4_rec_irq(void);
67static void can4_trx_irq(void);
68static void can4_err_warning_irq(void);
69static void can4_overrun_irq(void);
70static void can4_passive_irq(void);
71static void can4_arb_lost_irq(void);
72static void can4_bus_err_irq(void);
73#endif
74
75static void can_reset_reg(can_t *obj);
76static void can_reset_recv_rule(can_t *obj);
77static void can_reset_buffer(can_t *obj);
78static void can_reconfigure_channel(void);
79static void can_set_frequency(can_t *obj, int f);
80static void can_set_global_mode(int mode);
81static void can_set_channel_mode(uint32_t ch, int mode);
82
83typedef enum {
84 CAN_SEND = 0,
85 CAN_RECV
86} CANfunc;
87
88typedef enum {
89 GL_OPE = 0,
90 GL_RESET,
91 GL_TEST
92} Globalmode;
93
94typedef enum {
95 CH_COMM = 0,
96 CH_RESET,
97 CH_HOLD
98} Channelmode;
99
100typedef struct {
101 IRQn_Type int_num; /* Interrupt number */
102 IRQHandler handler; /* Interrupt handler */
103} can_info_int_t;
104
105static can_irq_handler irq_handler;
106static uint32_t can_irq_id[CAN_NUM];
107static int can_initialized[CAN_NUM] = {0};
108
109
110static __IO uint32_t *CTR_MATCH[] = {
111 &RSCAN0C0CTR,
112 &RSCAN0C1CTR,
113#if defined(TARGET_RZA1H)
114 &RSCAN0C2CTR,
115 &RSCAN0C3CTR,
116 &RSCAN0C4CTR,
117#endif
118};
119
120static __IO uint32_t *CFG_MATCH[] = {
121 &RSCAN0C0CFG,
122 &RSCAN0C1CFG,
123#if defined(TARGET_RZA1H)
124 &RSCAN0C2CFG,
125 &RSCAN0C3CFG,
126 &RSCAN0C4CFG,
127#endif
128};
129
130static __IO uint32_t *RFCC_MATCH[] = {
131 &RSCAN0RFCC0,
132 &RSCAN0RFCC1,
133 &RSCAN0RFCC2,
134 &RSCAN0RFCC3,
135 &RSCAN0RFCC4,
136 &RSCAN0RFCC5,
137 &RSCAN0RFCC6,
138 &RSCAN0RFCC7
139};
140
141static __IO uint32_t *TXQCC_MATCH[] = {
142 &RSCAN0TXQCC0,
143 &RSCAN0TXQCC1,
144#if defined(TARGET_RZA1H)
145 &RSCAN0TXQCC2,
146 &RSCAN0TXQCC3,
147 &RSCAN0TXQCC4,
148#endif
149};
150
151static __IO uint32_t *THLCC_MATCH[] = {
152 &RSCAN0THLCC0,
153 &RSCAN0THLCC1,
154#if defined(TARGET_RZA1H)
155 &RSCAN0THLCC2,
156 &RSCAN0THLCC3,
157 &RSCAN0THLCC4,
158#endif
159};
160
161static __IO uint32_t *STS_MATCH[] = {
162 &RSCAN0C0STS,
163 &RSCAN0C1STS,
164#if defined(TARGET_RZA1H)
165 &RSCAN0C2STS,
166 &RSCAN0C3STS,
167 &RSCAN0C4STS,
168#endif
169};
170
171static __IO uint32_t *ERFL_MATCH[] = {
172 &RSCAN0C0ERFL,
173 &RSCAN0C1ERFL,
174#if defined(TARGET_RZA1H)
175 &RSCAN0C2ERFL,
176 &RSCAN0C3ERFL,
177 &RSCAN0C4ERFL,
178#endif
179};
180
181static __IO uint32_t *CFCC_TBL[CAN_NUM][CAN_SND_RCV] = {
182 { &RSCAN0CFCC0 , &RSCAN0CFCC1 },
183 { &RSCAN0CFCC3 , &RSCAN0CFCC4 },
184#if defined(TARGET_RZA1H)
185 { &RSCAN0CFCC6 , &RSCAN0CFCC7 },
186 { &RSCAN0CFCC9 , &RSCAN0CFCC10 },
187 { &RSCAN0CFCC12, &RSCAN0CFCC13 },
188#endif
189};
190
191static __IO uint32_t *CFSTS_TBL[CAN_NUM][CAN_SND_RCV] = {
192 { &RSCAN0CFSTS0 , &RSCAN0CFSTS1 },
193 { &RSCAN0CFSTS3 , &RSCAN0CFSTS4 },
194#if defined(TARGET_RZA1H)
195 { &RSCAN0CFSTS6 , &RSCAN0CFSTS7 },
196 { &RSCAN0CFSTS9 , &RSCAN0CFSTS10 },
197 { &RSCAN0CFSTS12, &RSCAN0CFSTS13 },
198#endif
199};
200
201static __IO uint32_t *CFPCTR_TBL[CAN_NUM][CAN_SND_RCV] = {
202 { &RSCAN0CFPCTR0 , &RSCAN0CFPCTR1 },
203 { &RSCAN0CFPCTR3 , &RSCAN0CFPCTR4 },
204#if defined(TARGET_RZA1H)
205 { &RSCAN0CFPCTR6 , &RSCAN0CFPCTR7 },
206 { &RSCAN0CFPCTR9 , &RSCAN0CFPCTR10 },
207 { &RSCAN0CFPCTR12, &RSCAN0CFPCTR13 },
208#endif
209};
210
211static __IO uint32_t *CFID_TBL[CAN_NUM][CAN_SND_RCV] = {
212 { &RSCAN0CFID0 , &RSCAN0CFID1 },
213 { &RSCAN0CFID3 , &RSCAN0CFID4 },
214#if defined(TARGET_RZA1H)
215 { &RSCAN0CFID6 , &RSCAN0CFID7 },
216 { &RSCAN0CFID9 , &RSCAN0CFID10 },
217 { &RSCAN0CFID12, &RSCAN0CFID13 },
218#endif
219};
220
221static __IO uint32_t *CFPTR_TBL[CAN_NUM][CAN_SND_RCV] = {
222 { &RSCAN0CFPTR0 , &RSCAN0CFPTR1 },
223 { &RSCAN0CFPTR3 , &RSCAN0CFPTR4 },
224#if defined(TARGET_RZA1H)
225 { &RSCAN0CFPTR6 , &RSCAN0CFPTR7 },
226 { &RSCAN0CFPTR9 , &RSCAN0CFPTR10 },
227 { &RSCAN0CFPTR12, &RSCAN0CFPTR13 }
228#endif
229};
230
231static __IO uint32_t *CFDF0_TBL[CAN_NUM][CAN_SND_RCV] = {
232 { &RSCAN0CFDF00 , &RSCAN0CFDF01 },
233 { &RSCAN0CFDF03 , &RSCAN0CFDF04 },
234#if defined(TARGET_RZA1H)
235 { &RSCAN0CFDF06 , &RSCAN0CFDF07 },
236 { &RSCAN0CFDF09 , &RSCAN0CFDF010 },
237 { &RSCAN0CFDF012, &RSCAN0CFDF013 },
238#endif
239};
240
241static __IO uint32_t *CFDF1_TBL[CAN_NUM][CAN_SND_RCV] = {
242 { &RSCAN0CFDF10 , &RSCAN0CFDF11 },
243 { &RSCAN0CFDF13 , &RSCAN0CFDF14 },
244#if defined(TARGET_RZA1H)
245 { &RSCAN0CFDF16 , &RSCAN0CFDF17 },
246 { &RSCAN0CFDF19 , &RSCAN0CFDF110 },
247 { &RSCAN0CFDF112, &RSCAN0CFDF113 },
248#endif
249};
250
251static const can_info_int_t can_int_info[CAN_NUM][IRQ_NUM] =
252{
253 { /* ch0 */
254 { INTRCAN0REC_IRQn, can0_rec_irq }, /* RxIrq */
255 { INTRCAN0TRX_IRQn, can0_trx_irq }, /* TxIrq */
256 { INTRCAN0ERR_IRQn, can0_err_warning_irq }, /* EwIrq */
257 { INTRCAN0ERR_IRQn, can0_overrun_irq }, /* DoIrq */
258 { INTRCAN0ERR_IRQn, NULL }, /* WuIrq(not supported) */
259 { INTRCAN0ERR_IRQn, can0_passive_irq }, /* EpIrq */
260 { INTRCAN0ERR_IRQn, can0_arb_lost_irq }, /* AlIrq */
261 { INTRCAN0ERR_IRQn, can0_bus_err_irq } /* BeIrq */
262 },
263 { /* ch1 */
264 { INTRCAN1REC_IRQn, can1_rec_irq }, /* RxIrq */
265 { INTRCAN1TRX_IRQn, can1_trx_irq }, /* TxIrq */
266 { INTRCAN1ERR_IRQn, can1_err_warning_irq }, /* EwIrq */
267 { INTRCAN1ERR_IRQn, can1_overrun_irq }, /* DoIrq */
268 { INTRCAN1ERR_IRQn, NULL }, /* WuIrq(not supported) */
269 { INTRCAN1ERR_IRQn, can1_passive_irq }, /* EpIrq */
270 { INTRCAN1ERR_IRQn, can1_arb_lost_irq }, /* AlIrq */
271 { INTRCAN1ERR_IRQn, can1_bus_err_irq } /* BeIrq */
272 },
273#if defined(TARGET_RZA1H)
274 { /* ch2 */
275 { INTRCAN2REC_IRQn, can2_rec_irq }, /* RxIrq */
276 { INTRCAN2TRX_IRQn, can2_trx_irq }, /* TxIrq */
277 { INTRCAN2ERR_IRQn, can2_err_warning_irq }, /* EwIrq */
278 { INTRCAN2ERR_IRQn, can2_overrun_irq }, /* DoIrq */
279 { INTRCAN2ERR_IRQn, NULL }, /* WuIrq(not supported) */
280 { INTRCAN2ERR_IRQn, can2_passive_irq }, /* EpIrq */
281 { INTRCAN2ERR_IRQn, can2_arb_lost_irq }, /* AlIrq */
282 { INTRCAN2ERR_IRQn, can2_bus_err_irq } /* BeIrq */
283 },
284 { /* ch3 */
285 { INTRCAN3REC_IRQn, can3_rec_irq }, /* RxIrq */
286 { INTRCAN3TRX_IRQn, can3_trx_irq }, /* TxIrq */
287 { INTRCAN3ERR_IRQn, can3_err_warning_irq }, /* EwIrq */
288 { INTRCAN3ERR_IRQn, can3_overrun_irq }, /* DoIrq */
289 { INTRCAN3ERR_IRQn, NULL }, /* WuIrq(not supported) */
290 { INTRCAN3ERR_IRQn, can3_passive_irq }, /* EpIrq */
291 { INTRCAN3ERR_IRQn, can3_arb_lost_irq }, /* AlIrq */
292 { INTRCAN3ERR_IRQn, can3_bus_err_irq } /* BeIrq */
293 },
294 { /* ch4 */
295 { INTRCAN4REC_IRQn, can4_rec_irq }, /* RxIrq */
296 { INTRCAN4TRX_IRQn, can4_trx_irq }, /* TxIrq */
297 { INTRCAN4ERR_IRQn, can4_err_warning_irq }, /* EwIrq */
298 { INTRCAN4ERR_IRQn, can4_overrun_irq }, /* DoIrq */
299 { INTRCAN4ERR_IRQn, NULL }, /* WuIrq(not supported) */
300 { INTRCAN4ERR_IRQn, can4_passive_irq }, /* EpIrq */
301 { INTRCAN4ERR_IRQn, can4_arb_lost_irq }, /* AlIrq */
302 { INTRCAN4ERR_IRQn, can4_bus_err_irq } /* BeIrq */
303 },
304#endif
305};
306
307static __IO uint32_t *dmy_gaflid = &RSCAN0GAFLID0;
308static __IO uint32_t *dmy_gaflm = &RSCAN0GAFLM0;
309static __IO uint32_t *dmy_gaflp0 = &RSCAN0GAFLP00;
310static __IO uint32_t *dmy_gaflp1 = &RSCAN0GAFLP10;
311
312void can_irq_init(can_t *obj, can_irq_handler handler, uint32_t id) {
313 irq_handler = handler;
314 can_irq_id[obj->ch] = id;
315}
316
317void can_irq_free(can_t *obj) {
318 can_irq_id[obj->ch] = 0;
319}
320
321void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable) {
322 __IO uint32_t *dmy_ctr;
323
324 /* Wake-up Irq is not supported */
325 if (type != IRQ_WAKEUP) {
326 if (enable) {
327 dmy_ctr = CTR_MATCH[obj->ch];
328 if (type == IRQ_ERROR) {
329 /* EWIE interrupts is enable */
330 *dmy_ctr |= 0x00000200;
331 } else if (type == IRQ_OVERRUN) {
332 /* OLIE interrupts is enable */
333 *dmy_ctr |= 0x00002000;
334 } else if (type == IRQ_PASSIVE) {
335 /* EPIE interrupts is enable */
336 *dmy_ctr |= 0x00000400;
337 } else if (type == IRQ_ARB) {
338 /* ALIE interrupts is enable */
339 *dmy_ctr |= 0x00008000;
340 } else if (type == IRQ_BUS) {
341 /* BEIE interrupts is enable */
342 *dmy_ctr |= 0x00000100;
343 }
344 InterruptHandlerRegister(can_int_info[obj->ch][type].int_num, can_int_info[obj->ch][type].handler);
345 GIC_SetPriority(can_int_info[obj->ch][type].int_num, 5);
346 GIC_SetConfiguration(can_int_info[obj->ch][type].int_num, 1);
347 GIC_EnableIRQ(can_int_info[obj->ch][type].int_num);
348 } else {
349 GIC_DisableIRQ(can_int_info[obj->ch][type].int_num);
350 }
351 }
352}
353
354static void can_rec_irq(uint32_t ch) {
355 __IO uint32_t *dmy_cfsts;
356
357 dmy_cfsts = CFSTS_TBL[ch][CAN_RECV];
358 *dmy_cfsts &= 0xFFFFFFF7; // Clear CFRXIF
359
360 irq_handler(can_irq_id[ch], IRQ_RX);
361}
362
363static void can_trx_irq(uint32_t ch) {
364 __IO uint32_t *dmy_cfsts;
365
366 dmy_cfsts = CFSTS_TBL[ch][CAN_SEND];
367 *dmy_cfsts &= 0xFFFFFFEF; // Clear CFTXIF
368
369 irq_handler(can_irq_id[ch], IRQ_TX);
370}
371
372static void can_err_irq(uint32_t ch, CanIrqType type) {
373 __IO uint32_t *dmy_erfl;
374 int val = 1;
375
376 dmy_erfl = ERFL_MATCH[ch];
377 switch (type) {
378 case IRQ_ERROR:
379 *dmy_erfl &= 0xFFFFFFFD; // Clear EWF
380 break;
381 case IRQ_OVERRUN:
382 *dmy_erfl &= 0xFFFFFFDF; // Clear OVLF
383 break;
384 case IRQ_PASSIVE:
385 *dmy_erfl &= 0xFFFFFFFB; // Clear EPF
386 break;
387 case IRQ_ARB:
388 *dmy_erfl &= 0xFFFFFF7F; // Clear ALF
389 break;
390 case IRQ_BUS:
391 *dmy_erfl &= 0xFFFF00FF; // Clear ADERR、B0ERR、B1ERR、CERR、AERR、FERR、SERR
392 *dmy_erfl &= 0xFFFFFFFE; // Clear BEF
393 break;
394 case IRQ_WAKEUP:
395 /* not supported */
396 /* fall through */
397 default:
398 val = 0;
399 break;
400 }
401 if (val == 1) {
402 irq_handler(can_irq_id[ch], type);
403 }
404}
405
406static void can0_rec_irq(void) {
407 can_rec_irq(CAN_0);
408}
409
410static void can0_trx_irq(void) {
411 can_trx_irq(CAN_0);
412}
413
414static void can0_err_warning_irq(void) {
415 can_err_irq(CAN_0, IRQ_ERROR);
416}
417
418static void can0_overrun_irq(void) {
419 can_err_irq(CAN_0, IRQ_OVERRUN);
420}
421
422static void can0_passive_irq(void) {
423 can_err_irq(CAN_0, IRQ_PASSIVE);
424}
425
426static void can0_arb_lost_irq(void) {
427 can_err_irq(CAN_0, IRQ_ARB);
428}
429
430static void can0_bus_err_irq(void) {
431 can_err_irq(CAN_0, IRQ_BUS);
432}
433
434static void can1_rec_irq(void) {
435 can_rec_irq(CAN_1);
436}
437
438static void can1_trx_irq(void) {
439 can_trx_irq(CAN_1);
440}
441
442static void can1_err_warning_irq(void) {
443 can_err_irq(CAN_1, IRQ_ERROR);
444}
445
446static void can1_overrun_irq(void) {
447 can_err_irq(CAN_1, IRQ_OVERRUN);
448}
449
450static void can1_passive_irq(void) {
451 can_err_irq(CAN_1, IRQ_PASSIVE);
452}
453
454static void can1_arb_lost_irq(void) {
455 can_err_irq(CAN_1, IRQ_ARB);
456}
457
458static void can1_bus_err_irq(void) {
459 can_err_irq(CAN_1, IRQ_BUS);
460}
461
462#if defined(TARGET_RZA1H)
463static void can2_rec_irq(void) {
464 can_rec_irq(CAN_2);
465}
466
467static void can2_trx_irq(void) {
468 can_trx_irq(CAN_2);
469}
470
471static void can2_err_warning_irq(void) {
472 can_err_irq(CAN_2, IRQ_ERROR);
473}
474
475static void can2_overrun_irq(void) {
476 can_err_irq(CAN_2, IRQ_OVERRUN);
477}
478
479static void can2_passive_irq(void) {
480 can_err_irq(CAN_2, IRQ_PASSIVE);
481}
482
483static void can2_arb_lost_irq(void) {
484 can_err_irq(CAN_2, IRQ_ARB);
485}
486
487static void can2_bus_err_irq(void) {
488 can_err_irq(CAN_2, IRQ_BUS);
489}
490
491static void can3_rec_irq(void) {
492 can_rec_irq(CAN_3);
493}
494
495static void can3_trx_irq(void) {
496 can_trx_irq(CAN_3);
497}
498
499static void can3_err_warning_irq(void) {
500 can_err_irq(CAN_3, IRQ_ERROR);
501}
502
503static void can3_overrun_irq(void) {
504 can_err_irq(CAN_3, IRQ_OVERRUN);
505}
506
507static void can3_passive_irq(void) {
508 can_err_irq(CAN_3, IRQ_PASSIVE);
509}
510
511static void can3_arb_lost_irq(void) {
512 can_err_irq(CAN_3, IRQ_ARB);
513}
514
515static void can3_bus_err_irq(void) {
516 can_err_irq(CAN_3, IRQ_BUS);
517}
518
519static void can4_rec_irq(void) {
520 can_rec_irq(CAN_4);
521}
522
523static void can4_trx_irq(void) {
524 can_trx_irq(CAN_4);
525}
526
527static void can4_err_warning_irq(void) {
528 can_err_irq(CAN_4, IRQ_ERROR);
529}
530
531static void can4_overrun_irq(void) {
532 can_err_irq(CAN_4, IRQ_OVERRUN);
533}
534
535static void can4_passive_irq(void) {
536 can_err_irq(CAN_4, IRQ_PASSIVE);
537}
538
539static void can4_arb_lost_irq(void) {
540 can_err_irq(CAN_4, IRQ_ARB);
541}
542
543static void can4_bus_err_irq(void) {
544 can_err_irq(CAN_4, IRQ_BUS);
545}
546#endif
547
548void can_init_freq(can_t *obj, PinName rd, PinName td, int hz) {
549 __IO uint32_t *dmy_ctr;
550
551 /* determine the CAN to use */
552 uint32_t can_rx = pinmap_peripheral(rd, PinMap_CAN_RD);
553 uint32_t can_tx = pinmap_peripheral(td, PinMap_CAN_TD);
554 obj->ch = pinmap_merge(can_tx, can_rx);
555 MBED_ASSERT((int)obj->ch != NC);
556
557 /* enable CAN clock */
558 CPGSTBCR3 &= ~(CPG_STBCR3_BIT_MSTP32);
559 /* Has CAN RAM initialisation completed ? */
560 while ((RSCAN0GSTS & 0x08) == 0x08) {
561 __NOP();
562 }
563 /* clear Global Stop mode bit */
564 RSCAN0GCTR &= 0xFFFFFFFB;
565 /* clear Channel Stop mode bit */
566 dmy_ctr = CTR_MATCH[obj->ch];
567 *dmy_ctr &= 0xFFFFFFFB;
568 /* Enter global reset mode */
569 can_set_global_mode(GL_RESET);
570 /* Enter channel reset mode */
571 can_set_channel_mode(obj->ch, CH_RESET);
572 /* reset register */
573 can_reset_reg(obj);
574
575 can_initialized[obj->ch] = 1;
576 /* reconfigure channel which is already initialized */
577 can_reconfigure_channel();
578
579 /* pin out the can pins */
580 pinmap_pinout(rd, PinMap_CAN_RD);
581 pinmap_pinout(td, PinMap_CAN_TD);
582
583 /* set can frequency */
584 can_frequency(obj, hz);
585}
586
587void can_init(can_t *obj, PinName rd, PinName td) {
588 can_init_freq(obj, rd, td, 100000);
589}
590
591void can_free(can_t *obj) {
592 /* disable CAN clock */
593 CPGSTBCR3 |= CPG_STBCR3_BIT_MSTP32;
594}
595
596int can_frequency(can_t *obj, int f) {
597 __IO uint32_t *dmy_cfcc;
598 int retval = 0;
599
600 if (f <= 1000000) {
601 /* less than 1Mhz */
602 /* set Channel Reset mode */
603 can_set_channel_mode(obj->ch, CH_RESET);
604 can_set_frequency(obj, f);
605 /* set Channel Communication mode */
606 can_set_channel_mode(obj->ch, CH_COMM);
607 /* restore CFE bit since it is cleared */
608 /* Use send/receive FIFO buffer */
609 dmy_cfcc = CFCC_TBL[obj->ch][CAN_SEND];
610 *dmy_cfcc |= 0x01;
611 dmy_cfcc = CFCC_TBL[obj->ch][CAN_RECV];
612 *dmy_cfcc |= 0x01;
613 retval = 1;
614 }
615
616 return retval;
617}
618
619void can_reset(can_t *obj) {
620 /* Enter global reset mode */
621 can_set_global_mode(GL_RESET);
622 /* Enter channel reset mode */
623 can_set_channel_mode(obj->ch, CH_RESET);
624 /* reset register */
625 can_reset_reg(obj);
626 /* reconfigure channel which is already initialized */
627 can_reconfigure_channel();
628}
629
630int can_write(can_t *obj, CAN_Message msg, int cc) {
631 __IO uint32_t *dmy_sts;
632 __IO uint32_t *dmy_cfsts;
633 __IO uint32_t *dmy_cfid;
634 __IO uint32_t *dmy_cfptr;
635 __IO uint32_t *dmy_cfdf0;
636 __IO uint32_t *dmy_cfdf1;
637 __IO uint32_t *dmy_cfpctr;
638 int retval = 0;
639
640 /* Wait to become channel communication mode */
641 dmy_sts = STS_MATCH[obj->ch];
642 while ((*dmy_sts & 0x07) != 0) {
643 __NOP();
644 }
645
646 if (((msg.format == CANStandard) && (msg.id <= 0x07FF)) || ((msg.format == CANExtended) && (msg.id <= 0x1FFFFFFF))) {
647 /* send/receive FIFO buffer isn't full */
648 dmy_cfsts = CFSTS_TBL[obj->ch][CAN_SEND];
649 if ((*dmy_cfsts & 0x02) != 0x02) {
650 /* set format, frame type and send/receive FIFO buffer ID(b10-0 or b28-0) */
651 dmy_cfid = CFID_TBL[obj->ch][CAN_SEND];
652 *dmy_cfid = ((msg.format << 31) | (msg.type << 30));
653 if (msg.format == CANStandard) {
654 *dmy_cfid |= (msg.id & 0x07FF);
655 } else {
656 *dmy_cfid |= (msg.id & 0x1FFFFFFF);
657 }
658 /* set length */
659 dmy_cfptr = CFPTR_TBL[obj->ch][CAN_SEND];
660 *dmy_cfptr = msg.len << 28;
661 /* set data */
662 dmy_cfdf0 = CFDF0_TBL[obj->ch][CAN_SEND];
663 memcpy((void *)dmy_cfdf0, &msg.data[0], 4);
664 dmy_cfdf1 = CFDF1_TBL[obj->ch][CAN_SEND];
665 memcpy((void *)dmy_cfdf1, &msg.data[4], 4);
666 /* send request */
667 dmy_cfpctr = CFPCTR_TBL[obj->ch][CAN_SEND];
668 *dmy_cfpctr = 0xFF;
669 retval = 1;
670 }
671 }
672
673 return retval;
674}
675
676int can_read(can_t *obj, CAN_Message *msg, int handle) {
677 __IO uint32_t *dmy_sts;
678 __IO uint32_t *dmy_cfsts;
679 __IO uint32_t *dmy_cfid;
680 __IO uint32_t *dmy_cfptr;
681 __IO uint32_t *dmy_cfdf0;
682 __IO uint32_t *dmy_cfdf1;
683 __IO uint32_t *dmy_cfpctr;
684 int retval = 0;
685
686 /* Wait to become channel communication mode */
687 dmy_sts = STS_MATCH[obj->ch];
688 while ((*dmy_sts & 0x07) != 0) {
689 __NOP();
690 }
691
692 /* send/receive FIFO buffer isn't empty */
693 dmy_cfsts = CFSTS_TBL[obj->ch][CAN_RECV];
694 while ((*dmy_cfsts & 0x01) != 0x01) {
695 /* get format, frame type and send/receive FIFO buffer ID(b10-0 or b28-0) */
696 dmy_cfid = CFID_TBL[obj->ch][CAN_RECV];
697 msg->format = (CANFormat)(*dmy_cfid >> 31);
698 msg->type = (CANType)((*dmy_cfid >> 30) & 0x1);
699 if (msg->format == CANStandard) {
700 msg->id = (*dmy_cfid & 0x07FF);
701 } else {
702 msg->id = (*dmy_cfid & 0x1FFFFFFF);
703 }
704 /* get length */
705 dmy_cfptr = CFPTR_TBL[obj->ch][CAN_RECV];
706 msg->len = (unsigned char)(*dmy_cfptr >> 28);
707 /* get data */
708 dmy_cfdf0 = CFDF0_TBL[obj->ch][CAN_RECV];
709 memcpy(&msg->data[0], (void *)dmy_cfdf0, 4);
710 dmy_cfdf1 = CFDF1_TBL[obj->ch][CAN_RECV];
711 memcpy(&msg->data[4], (void *)dmy_cfdf1, 4);
712 /* receive(next data) request */
713 dmy_cfpctr = CFPCTR_TBL[obj->ch][CAN_RECV];
714 *dmy_cfpctr = 0xFF;
715 retval = 1;
716 }
717
718 return retval;
719}
720
721unsigned char can_rderror(can_t *obj) {
722 __IO uint32_t *dmy_sts;
723
724 dmy_sts = STS_MATCH[obj->ch];
725 return (unsigned char)((*dmy_sts >> 16) & 0xFF);
726}
727
728unsigned char can_tderror(can_t *obj) {
729 __IO uint32_t *dmy_sts;
730
731 dmy_sts = STS_MATCH[obj->ch];
732 return (unsigned char)((*dmy_sts >> 24) & 0xFF);
733}
734
735int can_mode(can_t *obj, CanMode mode) {
736 __IO uint32_t *dmy_ctr;
737 __IO uint32_t *dmy_sts;
738 __IO uint32_t *dmy_cfcc;
739 int ch_cnt;
740 can_t *tmp_obj;
741 tmp_obj = obj;
742 int retval = 1;
743
744 switch (mode) {
745 case MODE_RESET:
746 can_set_global_mode(GL_RESET);
747 can_set_channel_mode(obj->ch, CH_RESET);
748 for (ch_cnt = 0; ch_cnt < CAN_NUM; ch_cnt++) {
749 can_initialized[ch_cnt] = 0;
750 }
751 break;
752 case MODE_NORMAL:
753 can_set_global_mode(GL_OPE);
754 can_set_channel_mode(obj->ch, CH_COMM);
755 break;
756 case MODE_SILENT:
757 can_set_channel_mode(obj->ch, CH_HOLD);
758 /* set listen only mode, enable communication test mode */
759 dmy_ctr = CTR_MATCH[obj->ch];
760 *dmy_ctr = ((*dmy_ctr & 0x00FFFFFF) | 0x03000000);
761 can_set_channel_mode(obj->ch, CH_COMM);
762 break;
763 case MODE_TEST_LOCAL:
764 can_set_channel_mode(obj->ch, CH_HOLD);
765 /* set self test mode 0, enable communication test mode */
766 dmy_ctr = CTR_MATCH[obj->ch];
767 *dmy_ctr = ((*dmy_ctr & 0x00FFFFFF) | 0x05000000);
768 can_set_channel_mode(obj->ch, CH_COMM);
769 break;
770 case MODE_TEST_GLOBAL:
771 /* set the channel between the communication test on CAN_TEST_GLOBAL_CH and CAN_TEST_GLOBAL_CH+1 */
772 /* set Channel Hold mode */
773 for (tmp_obj->ch = CAN_TEST_GLOBAL_CH; tmp_obj->ch <= (CAN_TEST_GLOBAL_CH + 1); tmp_obj->ch++) {
774 dmy_sts = STS_MATCH[tmp_obj->ch];
775 if ((*dmy_sts & 0x04) == 0x04) {
776 /* Channel Stop mode */
777 /* clear Channel Stop mode bit */
778 dmy_ctr = CTR_MATCH[tmp_obj->ch];
779 *dmy_ctr &= 0xFFFFFFFB;
780 can_set_channel_mode(tmp_obj->ch, CH_RESET);
781 }
782 can_set_channel_mode(tmp_obj->ch, CH_HOLD);
783 }
784 can_set_global_mode(GL_TEST);
785 /* enable communication test between CAN_TEST_GLOBAL_CH and CAN_TEST_GLOBAL_CH+1 */
786 RSCAN0GTSTCFG = 0x06;
787 RSCAN0GTSTCTR = 0x01;
788 /* send and receive setting of channel1 and channel2 */
789 for (tmp_obj->ch = CAN_TEST_GLOBAL_CH; tmp_obj->ch <= (CAN_TEST_GLOBAL_CH + 1); tmp_obj->ch++) {
790 can_reset_buffer(tmp_obj);
791 /* set global interrrupt */
792 /* THLEIE, MEIE and DEIE interrupts are disable */
793 RSCAN0GCTR &= 0xFFFFF8FF;
794 /* BLIE, OLIE, BORIE and BOEIE interrupts are disable */
795 /* TAIE, ALIE, EPIE, EWIE and BEIE interrupts are enable */
796 dmy_ctr = CTR_MATCH[tmp_obj->ch];
797 *dmy_ctr &= 0x00018700;
798 can_set_global_mode(GL_OPE);
799 can_set_channel_mode(tmp_obj->ch, CH_COMM);
800 /* Use send/receive FIFO buffer */
801 dmy_cfcc = CFCC_TBL[tmp_obj->ch][CAN_SEND];
802 *dmy_cfcc |= 0x01;
803 dmy_cfcc = CFCC_TBL[tmp_obj->ch][CAN_RECV];
804 *dmy_cfcc |= 0x01;
805 }
806 break;
807 case MODE_TEST_SILENT:
808 /* not supported */
809 /* fall through */
810 default:
811 retval = 0;
812 break;
813 }
814
815 return retval;
816}
817
818int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle) {
819 int retval = 0;
820
821 if ((format == CANStandard) || (format == CANExtended)) {
822 if (((format == CANStandard) && (id <= 0x07FF)) || ((format == CANExtended) && (id <= 0x1FFFFFFF))) {
823 /* set Global Reset mode and Channel Reset mode */
824 can_set_global_mode(GL_RESET);
825 can_set_channel_mode(obj->ch, CH_RESET);
826 /* enable receive rule table writing */
827 RSCAN0GAFLECTR = 0x00000100;
828 /* set the page number of receive rule table(page number = 0) */
829 RSCAN0GAFLECTR |= (obj->ch * 4);
830 /* set IDE format */
831 *dmy_gaflid = (format << 31);
832 if (format == CANExtended) {
833 /* set receive rule ID for bit28-0 */
834 *dmy_gaflid |= (id & 0x1FFFFFFF);
835 } else {
836 /* set receive rule ID for bit10-0 */
837 *dmy_gaflid |= (id & 0x07FF);
838 }
839 /* set ID mask bit */
840 *dmy_gaflm = (0xC0000000 | mask);
841 /* disable receive rule table writing */
842 RSCAN0GAFLECTR &= 0xFFFFFEFF;
843 /* reconfigure channel which is already initialized */
844 can_reconfigure_channel();
845 retval = 1;
846 }
847 }
848
849 return retval;
850}
851
852void can_monitor(can_t *obj, int silent) {
853 __IO uint32_t *dmy_ctr;
854
855 /* set Channel Hold mode */
856 can_set_channel_mode(obj->ch, CH_HOLD);
857 if (silent) {
858 /* set listen only mode, enable communication test mode */
859 dmy_ctr = CTR_MATCH[obj->ch];
860 *dmy_ctr = ((*dmy_ctr & 0x00FFFFFF) | 0x03000000);
861 can_set_channel_mode(obj->ch, CH_COMM);
862 } else {
863 /* set normal test mode, disable communication test mode */
864 dmy_ctr = CTR_MATCH[obj->ch];
865 *dmy_ctr &= 0x00FFFFFF;
866 /* reset register */
867 can_reset_reg(obj);
868 /* reconfigure channel which is already initialized */
869 can_reconfigure_channel();
870 }
871}
872
873static void can_reset_reg(can_t *obj) {
874 __IO uint32_t *dmy_ctr;
875
876 /* time stamp source uses peripheral clock (pclk(P1_phi)/2), CAN clock uses clkc(P1_phi/2), */
877 /* mirror off, DLC not transfer, DLC check permit, transmit buffer priority, clock source not divided */
878 RSCAN0GCFG = 0x00000003;
879 /* set default frequency at 100k */
880 can_set_frequency(obj, 100000);
881 /* set receive rule */
882 can_reset_recv_rule(obj);
883 /* set buffer */
884 can_reset_buffer(obj);
885 /* set global interrrupt */
886 /* THLEIE, MEIE and DEIE interrupts are disable */
887 RSCAN0GCTR &= 0xFFFFF8FF;
888 /* ALIE, BLIE, OLIE, BORIE, BOEIE, EPIE, EWIE and BEIE interrupts are disable */
889 dmy_ctr = CTR_MATCH[obj->ch];
890 *dmy_ctr &= 0xFFFF00FF;
891}
892
893static void can_reset_recv_rule(can_t *obj) {
894 /* number of receive rules of each chanel = 64 */
895 RSCAN0GAFLCFG0 = 0x40404040;
896#if defined(TARGET_RZA1H)
897 RSCAN0GAFLCFG1 = 0x40000000;
898#endif
899 /* enable receive rule table writing */
900 RSCAN0GAFLECTR = 0x00000100;
901 /* set the page number of receive rule table(ex: id ch = 1, page number = 4) */
902 RSCAN0GAFLECTR |= (obj->ch * 4);
903 /* set standard ID, data frame and receive rule ID */
904 *dmy_gaflid = 0x07FF;
905 /* IDE bit, RTR bit and ID bit(28-0) are not compared */
906 *dmy_gaflm = 0;
907 /* DLC check is 1 bytes, not use a receive buffer */
908 *dmy_gaflp0 = 0x10000000;
909 /* use a send/receive FIFO buffer(ex: if ch = 1, FIFO buffer number = 4 and bit = 12) */
910 *dmy_gaflp1 = (1 << ((obj->ch + 3) * 3));
911 /* disable receive rule table writing */
912 RSCAN0GAFLECTR &= 0xFFFFFEFF;
913}
914
915static void can_reset_buffer(can_t *obj) {
916 __IO uint32_t *dmy_rfcc;
917 __IO uint32_t *dmy_cfcc;
918 __IO uint32_t *dmy_txqcc;
919 __IO uint32_t *dmy_thlcc;
920 int cnt;
921
922 /* set linked send buffer number(ex: if ch = 1 and mode = send, buffer number = 16), interval timer is pclk/2 */
923 /* number of rows of send/receive FIFO buffer = 4 */
924 dmy_cfcc = CFCC_TBL[obj->ch][CAN_SEND];
925 *dmy_cfcc = 0x00011100; /* send/receive FIFO mode is send */
926 dmy_cfcc = CFCC_TBL[obj->ch][CAN_RECV];
927 *dmy_cfcc = 0x00001100; /* send/receive FIFO mode is receive */
928 /* receive buffer is not used */
929 RSCAN0RMNB = 0;
930 /* receive FIFO buffer is not used */
931 for (cnt = 0; cnt < 8; cnt++) {
932 dmy_rfcc = RFCC_MATCH[cnt];
933 *dmy_rfcc = 0;
934 }
935 /* send queue is not used */
936 dmy_txqcc = TXQCC_MATCH[obj->ch];
937 *dmy_txqcc = 0;
938 /* send history is not used */
939 dmy_thlcc = THLCC_MATCH[obj->ch];
940 *dmy_thlcc = 0;
941
942 /* CFTXIE and CFRXIE interrupts are enable */
943 dmy_cfcc = CFCC_TBL[obj->ch][CAN_SEND];
944 *dmy_cfcc |= 0x04;
945 dmy_cfcc = CFCC_TBL[obj->ch][CAN_RECV];
946 *dmy_cfcc |= 0x02;
947 /* TMIEp interrupt is disable */
948 RSCAN0TMIEC0 = 0x00000000;
949#if defined(TARGET_RZA1H)
950 RSCAN0TMIEC1 = 0x00000000;
951 RSCAN0TMIEC2 = 0x00000000;
952#endif
953}
954
955static void can_reconfigure_channel(void) {
956 __IO uint32_t *dmy_cfcc;
957 int ch_cnt;
958
959 for (ch_cnt = 0; ch_cnt < CAN_NUM; ch_cnt++) {
960 if (can_initialized[ch_cnt] == 1) {
961 /* set Global Operation mode and Channel Communication mode */
962 can_set_global_mode(GL_OPE);
963 can_set_channel_mode(ch_cnt, CH_COMM);
964 /* Use send/receive FIFO buffer */
965 dmy_cfcc = CFCC_TBL[ch_cnt][CAN_SEND];
966 *dmy_cfcc |= 0x01;
967 dmy_cfcc = CFCC_TBL[ch_cnt][CAN_RECV];
968 *dmy_cfcc |= 0x01;
969 }
970 }
971}
972
973static void can_set_frequency(can_t *obj, int f) {
974 __IO uint32_t *dmy_cfg;
975 int oldfreq = 0;
976 int newfreq = 0;
977 uint32_t clkc_val;
978 uint8_t tmp_tq;
979 uint8_t tq = 0;
980 uint8_t tmp_brp;
981 uint8_t brp = 0;
982 uint8_t tseg1 = 0;
983 uint8_t tseg2 = 0;
984 uint8_t sjw = 0;
985
986 /* set clkc */
987 if (RZ_A1_IsClockMode0() == false) {
988 clkc_val = CM1_RENESAS_RZ_A1_P1_CLK / 2;
989 } else {
990 clkc_val = CM0_RENESAS_RZ_A1_P1_CLK / 2;
991 }
992 /* calculate BRP bit and Choose max value of calculated frequency */
993 for (tmp_tq = 8; tmp_tq <= 25; tmp_tq++) {
994 /* f = fCAN / ((BRP+1) * Tq) */
995 /* BRP = (fCAN / (f * Tq)) - 1 */
996 tmp_brp = ((clkc_val / (f * tmp_tq)) - 1) + 1; // carry(decimal point is carry)
997 newfreq = clkc_val / ((tmp_brp + 1) * tmp_tq);
998 if (newfreq >= oldfreq) {
999 oldfreq = newfreq;
1000 tq = tmp_tq;
1001 brp = tmp_brp;
1002 }
1003 }
1004 /* calculate TSEG1 bit and TSEG2 bit */
1005 tseg1 = (tq - 1) * 0.666666667;
1006 tseg2 = (tq - 1) - tseg1;
1007 sjw = (tseg2 > 4)? 4 : tseg2;
1008 /* set RSCAN0CmCFG register */
1009 dmy_cfg = CFG_MATCH[obj->ch];
1010 *dmy_cfg = ((sjw - 1) << 24) | ((tseg2 - 1) << 20) | ((tseg1 - 1) << 16) | brp;
1011}
1012
1013static void can_set_global_mode(int mode) {
1014 /* set Global mode */
1015 RSCAN0GCTR = ((RSCAN0GCTR & 0xFFFFFFFC) | (uint32_t)mode);
1016 /* Wait to cahnge into Global XXXX mode */
1017 while ((RSCAN0GSTS & 0x07) != (uint32_t)mode) {
1018 __NOP();
1019 }
1020}
1021
1022static void can_set_channel_mode(uint32_t ch, int mode) {
1023 __IO uint32_t *dmy_ctr;
1024 __IO uint32_t *dmy_sts;
1025
1026 /* set Channel mode */
1027 dmy_ctr = CTR_MATCH[ch];
1028 *dmy_ctr = ((*dmy_ctr & 0xFFFFFFFC) | (uint32_t)mode);
1029 /* Wait to cahnge into Channel XXXX mode */
1030 dmy_sts = STS_MATCH[ch];
1031 while ((*dmy_sts & 0x07) != (uint32_t)mode) {
1032 __NOP();
1033 }
1034}
1035
Note: See TracBrowser for help on using the repository browser.