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