]> rtime.felk.cvut.cz Git - lincan.git/blob - embedded/app/usbcan/lpc17xx_can.c
5565d8c346ada07eb00a7c1b06421b9b8b66094e
[lincan.git] / embedded / app / usbcan / lpc17xx_can.c
1 #include "can/lpc17xx_can.h"
2
3 static void CAN_configPin();
4 static void CAN_setBusTiming(struct canchip_t *chip);
5
6 extern struct canhardware_t *hardware_p;
7
8 //---------------------------------------------------------------------------------
9 //---------------------------------------------------------------------------------
10
11
12 static inline void can_write_register(struct canchip_t *chip, uint32_t data, uint32_t reg_offs){
13
14         uint32_t address = chip->chip_base_addr + reg_offs;
15         (*(volatile uint32_t*)(address)) = data;
16
17 }
18
19 static inline uint32_t can_read_register(struct canchip_t *chip, uint32_t reg_offs){
20
21         uint32_t address = chip->chip_base_addr + reg_offs;
22         return (*(volatile uint32_t*)(address));
23
24 }
25
26 //---------------------------------------------------------------------------------
27 //---------------------------------------------------------------------------------
28
29
30 // interrupt handler
31 // for transmitting - irq when one message was transmitted (for check if another message is pending in can msg queue)
32 // for receiving - irq when message was received and is available in Receive buffer
33
34 void CAN_IRQHandler(){
35
36         uint32_t i;
37
38         struct canchip_t *chip;
39         chip = hardware_p->candevice[0]->chip[0];
40
41         i = can_read_register(chip, CAN_ICR_o);
42
43         if(i & (CAN_ICR_TI1 | CAN_ICR_RI))
44                 lpc17xx_irq_handler(0, chip);
45
46         if(i & CAN_ICR_DOI)
47                 can_write_register(chip, CAN_CMR_CDO, CAN_CMR_o);
48         
49         
50 }
51
52 //---------------------------------------------------------------------------------
53 //---------------------------------------------------------------------------------
54
55
56 // board can-lmc1 specific functions:
57
58 int can_lmc1_register(struct hwspecops_t *hwspecops){
59
60         hwspecops->request_io = can_lmc1_request_io;
61         hwspecops->reset = can_lmc1_reset;
62         hwspecops->init_hw_data = can_lmc1_init_hw_data;
63         hwspecops->init_chip_data = can_lmc1_init_chip_data;
64         hwspecops->init_obj_data = can_lmc1_init_obj_data;
65         hwspecops->write_register = can_lmc1_write_register;
66         hwspecops->read_register = can_lmc1_read_register;
67
68         return 0;
69 }
70
71 int can_lmc1_init_hw_data(struct candevice_t *candev){
72
73         candev->res_addr=0;
74         candev->nr_82527_chips=0;
75         candev->nr_sja1000_chips=0;
76         candev->nr_all_chips=1;
77         candev->flags |= 0;
78
79         return 0;
80 }
81
82 int can_lmc1_init_chip_data(struct candevice_t *candev, int chipnr){
83         
84         lpc17xx_fill_chipspecops(candev->chip[chipnr]);
85
86         candev->chip[chipnr]->flags|= CHIP_IRQ_CUSTOM;
87
88         //debug
89         candev->chip[chipnr]->chip_base_addr = CAN1_REGS_BASE;
90
91         candev->chip[chipnr]->chip_data=(void *)malloc(sizeof(struct can_lmc1_chip_data));
92         if (candev->chip[chipnr]->chip_data==NULL)
93                 return -ENOMEM;
94
95         return 0;
96 }
97
98 int can_lmc1_init_obj_data(struct canchip_t *chip, int objnr){
99         
100         return 0;
101 }
102
103 void can_lmc1_write_register(unsigned data, unsigned long address){
104
105         printf("UNSUPPORTED NOW\n");
106 }
107
108 unsigned can_lmc1_read_register(unsigned long address){
109
110         printf("UNSUPPORTED NOW\n");
111         return 0;
112
113 }
114
115 int can_lmc1_request_io(struct candevice_t *candev)
116 {
117         return 0;
118 }
119
120 int can_lmc1_reset(struct candevice_t *candev)
121 {
122         return 0;
123 }
124
125
126 //---------------------------------------------------------------------------------
127 //---------------------------------------------------------------------------------
128
129
130 // lpc17xx can chip specific functions:
131
132
133 int lpc17xx_chip_config(struct canchip_t *chip){
134
135         CAN_init(chip);
136
137         return 0;
138 }
139
140 int lpc17xx_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj,
141                                                         struct canmsg_t *msg)
142 {
143         
144         CAN_send(chip, msg);
145
146         return 0;
147 }
148
149 int lpc17xx_send_msg(struct canchip_t *chip, struct msgobj_t *obj,
150                                                         struct canmsg_t *msg)
151 {
152         
153         // write transmission request
154         can_write_register(chip, (CAN_CMR_TR | CAN_CMR_STB1), CAN_CMR_o); 
155
156         return 0;
157 }
158
159 int lpc17xx_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj)
160 {
161
162         can_preempt_disable();
163
164         can_msgobj_set_fl(obj,TX_PENDING);
165         can_msgobj_set_fl(obj,TX_REQUEST);
166
167         while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){
168                 can_msgobj_clear_fl(obj,TX_REQUEST);
169
170                 if (can_read_register(chip, CAN_SR_o) & CAN_SR_TBS1){
171                         obj->tx_retry_cnt=0;
172                         lpc17xx_irq_write_handler(chip, obj);
173                 }
174
175                 can_msgobj_clear_fl(obj,TX_LOCK);
176                 if(!can_msgobj_test_fl(obj,TX_REQUEST)) break;
177
178         }
179
180         can_preempt_enable();
181
182         return 0;
183 }
184
185 int lpc17xx_irq_handler(int irq, struct canchip_t *chip)
186 {
187
188         struct msgobj_t *obj;   
189         obj = chip->msgobj[0];
190
191         if(can_read_register(chip, CAN_SR_o) & CAN_SR_RBS) {
192                         lpc17xx_read(chip,obj);
193                         obj->ret = 0;
194         }
195         
196         
197         if ((can_msgobj_test_fl(obj,TX_PENDING)) || (can_msgobj_test_fl(obj,TX_REQUEST))) {
198                         
199                 can_msgobj_set_fl(obj,TX_REQUEST);
200
201                 while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){
202
203                         obj->ret=0;
204                         can_msgobj_clear_fl(obj,TX_REQUEST);
205
206                         if (can_read_register(chip, CAN_SR_o) & CAN_SR_TBS1){
207                                 obj->tx_retry_cnt=0;
208                                 lpc17xx_irq_write_handler(chip, obj);
209                         }
210
211                         can_msgobj_clear_fl(obj,TX_LOCK);
212                         if(!can_msgobj_test_fl(obj,TX_REQUEST)) break;
213
214                 }       
215         }
216
217
218         return CANCHIP_IRQ_HANDLED;
219
220 }
221
222 void lpc17xx_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj)
223 {
224         int cmd;
225
226         if(obj->tx_slot){
227                 /* Do local transmitted message distribution if enabled */
228                 if (processlocal){
229                         /* fill CAN message timestamp */
230                         can_filltimestamp(&obj->tx_slot->msg.timestamp);
231
232                         obj->tx_slot->msg.flags |= MSG_LOCAL;
233                         canque_filter_msg2edges(obj->qends, &obj->tx_slot->msg);
234                 }
235                 /* Free transmitted slot */
236                 canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
237                 obj->tx_slot=NULL;
238         }
239
240         can_msgobj_clear_fl(obj,TX_PENDING);
241         cmd=canque_test_outslot(obj->qends, &obj->tx_qedge, &obj->tx_slot);
242         if(cmd<0)
243                 return;
244         can_msgobj_set_fl(obj,TX_PENDING);
245
246         if (chip->chipspecops->pre_write_config(chip, obj, &obj->tx_slot->msg)) {
247                 obj->ret = -1;
248                 canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_PREP);
249                 canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
250                 obj->tx_slot=NULL;
251                 return;
252         }
253         if (chip->chipspecops->send_msg(chip, obj, &obj->tx_slot->msg)) {
254                 obj->ret = -1;
255                 canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_SEND);
256                 canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
257                 obj->tx_slot=NULL;
258                 return;
259         }
260
261 }
262
263 void lpc17xx_read(struct canchip_t *chip, struct msgobj_t *obj) {
264
265
266                 CAN_recv(chip, &obj->rx_msg);
267                 
268                 // fill CAN message timestamp
269                 can_filltimestamp(&obj->rx_msg.timestamp);
270
271                 canque_filter_msg2edges(obj->qends, &obj->rx_msg);
272
273                 // release Receive buffer
274                 can_write_register(chip, CAN_CMR_RRB, CAN_CMR_o);
275
276 }
277
278 int lpc17xx_fill_chipspecops(struct canchip_t *chip){
279
280         chip->max_objects=1;
281         
282         lpc17xx_register(chip->chipspecops);
283
284         return 0;
285 }
286
287 int lpc17xx_register(struct chipspecops_t *chipspecops){
288
289         CANMSG("initializing lpc17xx can chip operations\n");
290
291         chipspecops->attach_to_chip = lpc17xx_attach_to_chip;
292         chipspecops->pre_read_config = lpc17xx_pre_read_config;
293         chipspecops->chip_config = lpc17xx_chip_config;
294         chipspecops->pre_write_config = lpc17xx_pre_write_config;
295         chipspecops->send_msg = lpc17xx_send_msg;
296         chipspecops->wakeup_tx = lpc17xx_wakeup_tx;
297         chipspecops->irq_handler = lpc17xx_irq_handler;
298
299         return 0;       
300
301 }
302
303
304 int lpc17xx_attach_to_chip(struct canchip_t *chip){
305
306         return 0;
307 }
308
309 int lpc17xx_pre_read_config(struct canchip_t *chip, struct msgobj_t *obj){
310
311         return 1;
312 }
313
314
315
316 //---------------------------------------------------------------------------------
317 //---------------------------------------------------------------------------------
318
319
320 static void CAN_configPin(){
321
322 //      CAN1 - select P0.0 as RD1. P0.1 as TD1
323
324         uint32_t pinsel0;
325         uint32_t pinmode0;
326         uint32_t pinmode_od0;
327         uint8_t pinsel0_val = 1;
328         uint8_t pinmode0_val = 0;
329         uint8_t pinmode_od0_val = 0;
330
331
332         pinsel0 = PINCON->PINSEL0;
333         pinsel0 &= ~CAN1_RX_MASK;
334         pinsel0 &= ~CAN1_TX_MASK;
335         pinsel0 |= __val2mfld(CAN1_RX_MASK, pinsel0_val);
336         pinsel0 |= __val2mfld(CAN1_TX_MASK, pinsel0_val);
337         PINCON->PINSEL0 = pinsel0;
338
339         pinmode0 = PINCON->PINMODE0;
340         pinmode0 &= ~CAN1_RX_MASK;
341         pinmode0 &= ~CAN1_TX_MASK;
342         pinmode0 |= __val2mfld(CAN1_RX_MASK, pinmode0_val);
343         pinmode0 |= __val2mfld(CAN1_TX_MASK, pinmode0_val);
344         PINCON->PINMODE0 = pinmode0;
345
346         pinmode_od0 = PINCON->PINMODE_OD0;
347         if (pinmode_od0_val){
348                 pinmode_od0 |= CAN1_RX_BIT;
349                 pinmode_od0 |= CAN1_TX_BIT;
350         }
351         else{
352                 pinmode_od0 &= ~CAN1_RX_BIT;
353                 pinmode_od0 &= ~CAN1_TX_BIT;
354         }
355         PINCON->PINMODE_OD0 = pinmode_od0;
356         
357
358 }
359
360 void CAN_recv(struct canchip_t *chip, canmsg_t* msg){
361
362         volatile uint32_t data;
363         uint32_t i;
364
365         // read data lenght
366         msg->length = (can_read_register(chip, CAN_RFS_o)>>16) & 0xF;
367
368         // read identifier
369         msg->id = can_read_register(chip, CAN_RID_o);
370
371         // EXT frame
372         if(can_read_register(chip, CAN_RFS_o) & CAN_RFS_EXT)
373                 msg->flags |= MSG_EXT;
374         else
375                 msg->flags &= ~MSG_EXT;
376
377         
378         // RTR frame
379         if(can_read_register(chip, CAN_RFS_o) & CAN_RFS_RTR)
380                 msg->flags |= MSG_RTR;
381         else
382                 msg->flags &= ~MSG_RTR;
383
384
385         // read data            
386         data = can_read_register(chip, CAN_RDA_o);              
387         for(i=0; i<4; i++)
388                 msg->data[i] = (data>>(i*8)) & 0xFF;
389
390         data = can_read_register(chip, CAN_RDB_o);      
391         for(i=4; i<8; i++)
392                 msg->data[i] = (data>>((i-4)*8)) & 0xFF;
393
394 }
395
396 void CAN_send(struct canchip_t *chip, canmsg_t* msg){
397
398         volatile uint32_t data;
399         volatile uint32_t can_tfi1;
400         uint32_t i;
401
402         // check status of TB1
403         while (!(can_read_register(chip, CAN_SR_o) & CAN_SR_TBS1)){}    
404
405         can_tfi1 = can_read_register(chip, CAN_TFI1_o);
406
407         can_tfi1 &= ~0x000F0000;
408         can_tfi1 |= (msg->length)<<16;
409
410         // EXT frame
411         if(msg->flags & MSG_EXT)
412                 can_tfi1 |= CAN_TFI1_EXT;
413         else
414                 can_tfi1 &= ~CAN_TFI1_EXT;
415                 
416         // RTR frame
417         if(msg->flags & MSG_RTR)
418                 can_tfi1 |= CAN_TFI1_RTR;
419         else
420                 can_tfi1 &= ~CAN_TFI1_RTR;
421
422         can_write_register(chip, can_tfi1, CAN_TFI1_o);
423
424
425         // write CAN ID
426         can_write_register(chip, msg->id, CAN_TID1_o);
427
428
429         // write first 4 data bytes
430         data=0;
431         for(i=0; i<4; i++)
432                 data |= (msg->data[i])<<(i*8);
433
434         can_write_register(chip, data, CAN_TDA1_o);
435
436         // write second 4 data bytes
437         data=0;
438         for(i=4; i<8; i++)
439                 data |= (msg->data[i])<<((i-4)*8);
440         
441         can_write_register(chip, data, CAN_TDB1_o);
442
443 }
444
445 void CAN_setBusTiming(struct canchip_t *chip){
446
447         uint32_t PCLK_CAN;
448         uint32_t res;
449
450         uint8_t tq_numb; // number of time quantum
451         uint8_t TSEG1, TSEG2;
452         uint8_t BRP;
453         uint8_t SJW;
454         uint8_t SAM;
455         uint8_t div;
456
457         // 0 = the bus is sampled once
458         SAM = 0;
459
460         // the Synchronization Jump Width (this value plus one) 
461         SJW = 3;
462
463         // get clock divide for CAN1    
464         div = __mfld2val(PCLK_CAN1_MASK, SC->PCLKSEL0);
465         switch(div){
466                 case 0:
467                         div = 4;
468                         break;
469                 case 1:
470                         div = 1;
471                         break;
472                 case 2:
473                         div = 2;
474                         break;
475                 case 3:
476                         // only for CAN, for other peripherials '11' value means div=8
477                         div = 6;
478                         break;
479         }
480
481
482         PCLK_CAN = system_frequency / div;
483
484         res = PCLK_CAN / (chip->baudrate);
485
486
487         // calculation of tq_numb - number of time quantum (must be in <8,25>)
488         // tq_numb = TSEG1 + TSEG2 + 3
489
490         for(tq_numb=25; tq_numb>=8; tq_numb--){
491                 
492                 if ((res%tq_numb)==0){
493                 
494                         // Baud Rate Prescaler. The PCLK clock is divided by (this value plus one) to produce the CAN clock.
495                         BRP = (res / tq_numb) - 1;
496
497                         // sync. segment allways 1 tq
498                         tq_numb--;
499
500                         // number of tq from the sample point to the next nominal Sync. point (this value plus one)                     
501                         TSEG2 = (tq_numb/3) - 1;
502
503                         // number of tq from Sync. point to the sample point (this value plus one)                      
504                         TSEG1 = tq_numb - (tq_numb/3) - 1;
505
506                         break;
507                 }
508         }
509
510         can_write_register(chip, ((SAM<<23)|(TSEG2<<20)|(TSEG1<<16)|(SJW<<14)|(BRP<<0)), CAN_BTR_o);
511
512 }
513
514 void CAN_init(struct canchip_t *chip){
515
516         uint32_t tmp;
517         uint32_t pclksel0;
518         uint32_t val;
519         uint32_t i;
520         
521         printf("CAN INIT, baudrate: %d\n", chip->baudrate);
522
523         // configure CAN1 pins 
524         CAN_configPin();
525
526         // turn on power and clock for CAN1 
527         SC->PCONP |= PCCAN1;
528         
529         // set clock divide for CAN1 
530
531         val = 0x00; // 00       PCLK_peripheral = CCLK/4 
532         pclksel0 = SC->PCLKSEL0;
533         pclksel0 &= ~PCLK_CAN1_MASK;
534         pclksel0 &= ~PCLK_CAN2_MASK;
535         pclksel0 &= ~PCLK_ACF_MASK;
536         pclksel0 |= __val2mfld(PCLK_CAN1_MASK, val);
537         pclksel0 |= __val2mfld(PCLK_CAN2_MASK, val);
538         pclksel0 |= __val2mfld(PCLK_ACF_MASK, val);
539         SC->PCLKSEL0 = pclksel0;
540         
541         // enter reset mode
542         can_write_register(chip, 1, CAN_MOD_o);
543
544         // disable all CAN interrupts
545         can_write_register(chip, 0, CAN_IER_o);
546
547         // reset value of Global Status Register (global controller status and error counters) 
548         can_write_register(chip, 0x3C, CAN_GSR_o);
549
550         // request command to release Rx, Tx buffer and clear data overrun 
551         can_write_register(chip, (CAN_CMR_AT | CAN_CMR_RRB | CAN_CMR_CDO), CAN_CMR_o);
552
553         // read to clear interrupt pending in Interrupt Capture Register 
554         tmp = can_read_register(chip, CAN_ICR_o);
555
556         // set bus timing 
557         CAN_setBusTiming(chip);
558
559         // return to normal operating 
560         can_write_register(chip, 0, CAN_MOD_o);
561
562
563         //--------------------------
564
565         // Acceptance Filter Off Mode
566         CANAF_AFMR = 0x01;
567
568         // clear RAM masks
569         for (i = 0; i < 512; i++) {
570                 CANAF_RAM->mask[i] = 0x00;
571         }
572
573         CANAF_SFF_sa = 0x00;
574         CANAF_SFF_GRP_sa = 0x00;
575         CANAF_EFF_sa = 0x00;
576         CANAF_EFF_GRP_sa = 0x00;
577         CANAF_ENDofTable = 0x00;
578
579         // Acceptance Filter Bypass Mode - all messages accepted
580         CANAF_AFMR = 0x02;
581
582         //--------------------------
583
584
585         // enable interrupt after transmit
586         // enable receive interrupt
587         // enable data overrun interrupt
588         can_write_register(chip, (CAN_IER_TIE1 | CAN_IER_RIE | CAN_IER_DOIE), CAN_IER_o);
589         
590         // enable CAN interrupt 
591         NVIC_EnableIRQ(CAN_IRQn);
592
593
594         
595 }
596