]> rtime.felk.cvut.cz Git - lincan.git/blob - embedded/app/usbcan/main.c
Receiving CAN messages with usage of queue system from LinCAN - first version. Attemp...
[lincan.git] / embedded / app / usbcan / main.c
1 /**************************************************************************/
2 /* File: main.c - setup and main loop of USB<->CAN converter              */
3 /*                                                                        */
4 /* LinCAN - (Not only) Linux CAN bus driver                               */
5 /* Copyright (C) 2002-2011 DCE FEE CTU Prague <http://dce.felk.cvut.cz>   */
6 /* Copyright (C) 2008 Jan Kriz email:johen@post.cz                        */
7 /*                                                                        */
8 /* LinCAN is free software; you can redistribute it and/or modify it      */
9 /* under terms of the GNU General Public License as published by the      */
10 /* Free Software Foundation; either version 2, or (at your option) any    */
11 /* later version.  LinCAN is distributed in the hope that it will be      */
12 /* useful, but WITHOUT ANY WARRANTY; without even the implied warranty    */
13 /* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU    */
14 /* General Public License for more details. You should have received a    */
15 /* copy of the GNU General Public License along with LinCAN; see file     */
16 /* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
17 /* Cambridge, MA 02139, USA.                                              */
18 /*                                                                        */
19 /* To allow use of LinCAN in the compact embedded systems firmware        */
20 /* and RT-executives (RTEMS for example), main authors agree with next    */
21 /* special exception:                                                     */
22 /*                                                                        */
23 /* Including LinCAN header files in a file, instantiating LinCAN generics */
24 /* or templates, or linking other files with LinCAN objects to produce    */
25 /* an application image/executable, does not by itself cause the          */
26 /* resulting application image/executable to be covered by                */
27 /* the GNU General Public License.                                        */
28 /* This exception does not however invalidate any other reasons           */
29 /* why the executable file might be covered by the GNU Public License.    */
30 /* Publication of enhanced or derived LinCAN files is required although.  */
31 /**************************************************************************/
32
33 #include <stdio.h>
34 #include <string.h>
35 #include <cpu_def.h>
36 #include <system_def.h>
37 #include <lt_timer.h>
38 #include <local_config.h>
39 #include <usb/usbdebug.h>
40 #include <usb/usb.h>
41 #include <usb/lpc.h>
42 #include <usb/usb_srq.h>
43 #include <mem_loc.h>
44 #include <keyval_id.h>
45 #include <hal_machperiph.h>
46 #include <keyval_loc.h>
47 #include <lpciap.h>
48 #include <lpciap_kvpb.h>
49
50 #include <endian.h>
51 #if __BYTE_ORDER == __BIG_ENDIAN
52   #include <byteswap.h>
53 #endif
54
55 #include "./can/can.h"
56 #include "./can/sja1000p.h"
57 #include "./can/main.h"
58
59 // #include "./can/can_sysdep.h"
60 #include "./can/modparms.h"
61 #include "./can/devcommon.h"
62
63 //#include "./can/ul_usb1.h"
64
65 //#include "./can/setup.h"
66
67 #include "./usb/usb_defs.h"
68 #include "./usb/usb_vend.h"
69
70 // DEBUG CAN
71 #include "can/lpc17xx_can.h"
72 // DEBUG CAN - end
73
74 #define MASK_EP1RX  0x01
75 #define MASK_EP1TX  0x02
76
77 #define CAN_OP_MASK 0x80
78 #define CAN_OP_READ 0x80
79 #define CAN_OP_WRITE 0x00
80
81 #ifdef USB_MAX_PACKET
82         #undef USB_MAX_PACKET
83         #define USB_MAX_PACKET 16
84 #endif
85 /***********************************************************************
86  * Note:
87  * Comparing to LinCAN, there is no need to sleep for processes
88  * because the degree of filling of fifo from the client side
89  * is solved in main cycle (no new messages are accepted when full)
90  * and on the server side by speed of USB interface. FIFO in edge
91  * from SJA chip to USB interface should never be filled.
92  ***********************************************************************/
93
94 /***********************************************************************
95  * Note:
96  * Code is wittingly complex in order to ease future changes in hardware
97  * configuration and to make it as much similar as the code of LinCAN
98  ***********************************************************************/
99
100 LT_TIMER_DEC(lt_10msec)
101 LT_TIMER_IMP(lt_10msec)
102 LT_TIMER_DEC(lt_100msec)
103 LT_TIMER_IMP(lt_100msec)
104 LT_TIMER_DEC(lt_2sec)
105 LT_TIMER_IMP(lt_2sec)
106
107 typedef void (*FNC)(); //function ptr
108
109 /***********************************************************************
110  * global variables
111  ***********************************************************************/
112 volatile uint32_t cnt;
113
114 usb_device_t usb_device;
115
116 usb_ep_t eps[NUM_ENDPOINTS];
117 unsigned char ep1_rx_buff[USB_MAX_PACKET];
118 unsigned char ep1_tx_buff[USB_MAX_PACKET];
119 uint8_t timer_str,timer_rx_off,timer_tx_off,timer_configured;
120 volatile uint8_t bootloader_run;
121
122 uint8_t vendor_ret;
123
124 int processlocal;
125
126 int baudrate[MAX_TOT_CHIPS];
127 struct canhardware_t canhardware;
128 struct canhardware_t *hardware_p=&canhardware;
129 struct canchip_t *chips_p[MAX_TOT_CHIPS];
130 struct msgobj_t *objects_p[MAX_TOT_MSGOBJS];
131
132 struct canuser_t *canuser;
133
134 extern int init_chip_struct(struct candevice_t *candev, int chipnr, int irq, long baudrate);
135 extern int register_chip_struct(struct canchip_t *chip, int minorbase);
136 extern int register_obj_struct(struct msgobj_t *obj, int minorbase);
137
138 /***********************************************************************
139  * IF SOMETHING BAD HAPPENED
140  ***********************************************************************/
141
142 int sys_err(){
143   
144   unsigned char i=0;
145
146   while(1) {
147     if (lt_100msec_expired(100)) {
148       i++;
149       if (i&1) {
150         SET_OUT_PIN(LED_PORT,LED_ERR);
151       } else {
152         CLR_OUT_PIN(LED_PORT,LED_ERR);
153       }
154      #ifdef WATCHDOG_ENABLED
155       watchdog_feed();
156      #endif /* WATCHDOG_ENABLED */
157     }
158   }
159 }
160
161 /***********************************************************************
162  * Microsecond delay routine
163  ***********************************************************************/
164 /*
165 void udelay(long time)
166 {
167   volatile long ticks=(time * CCLK) / 2000000;
168   do{
169     ticks--;
170   } while(ticks>0);
171 }
172 */
173
174 /***********************************************************************
175  * Routine for visible LED blinking (on USB transmission)
176  ***********************************************************************/
177
178 void timer_10ms(void)
179 {
180   if (timer_tx_off!=0) timer_tx_off--;
181   else SET_OUT_PIN(LED_PORT,LED1_BIT);
182   if (timer_rx_off!=0) timer_rx_off--;
183   else SET_OUT_PIN(LED_PORT,LED2_BIT);
184
185 /*  if (timer_configured!=0) timer_configured--;
186   else {
187     timer_configured=20;
188                 CLR_OUT_PIN(LED_PORT,LED1_BIT);
189                 CLR_OUT_PIN(LED_PORT,LED2_BIT);
190                 timer_rx_off=timer_tx_off=5;
191   }*/
192 }
193
194 /***********************************************************************
195  * Main routine
196  ***********************************************************************/
197
198 int main(void)
199 {
200         struct candevice_t *candev;
201         struct canchip_t *chip=NULL;
202         struct msgobj_t *obj;
203         struct canque_ends_t *qends;
204         struct canque_edge_t *edge,*qedge;
205         struct canque_slot_t *slot;
206         struct canmsg_t canmsg;
207         can_spin_irqflags_t iflags;
208
209         int chipnr,bd;
210         int i,size,m=0;
211
212         cnt=0;
213
214         CANMSG("Starting USBCAN module firmware...\n");
215
216 //      volatile int i=0;
217         bootloader_run=0;
218         /***********************************/
219
220         lt_10msec_init();
221         lt_100msec_init();
222         lt_2sec_init();
223
224         // DEBUG
225         //SET_OUT_PIN(LED_PORT,LED_ERR);
226         //CLR_OUT_PIN(LED_PORT,LED_GP);
227
228         if (USB_MAX_PACKET<16){
229                 CANMSG("Maximum packet size less than 16B (is %dB)\n",USB_MAX_PACKET);
230                 sys_err();
231         }
232
233 // !!! DEBUG - transmitting and receiving CAN messages with usage of queue system from LinCAN - first version! 
234
235
236         //***********************************************************************
237         // * CAN device initialization - device side (adapted from LinCAN setup.c)
238         // ***********************************************************************
239
240         // DEBUG
241         //can_init(); // only for successful compiling (defined in can_lpcbusemu.c)
242
243
244         DEBUGMSG("Initiating CAN device initialization\n");
245         baudrate[0]=1000;
246
247         canqueue_kern_initialize();
248
249         hardware_p->nr_boards=1;
250
251         candev=(struct candevice_t *)malloc(sizeof(struct candevice_t));
252         if (!candev){
253                 CANMSG("No space left in memory\n");
254                 sys_err();
255         }
256         memset(candev, 0, sizeof(struct candevice_t));
257
258         hardware_p->candevice[0]=candev;
259         candev->candev_idx=0;
260         candev->io_addr=0;
261         candev->dev_base_addr=0;
262
263         candev->hwspecops=(struct hwspecops_t *)malloc(sizeof(struct hwspecops_t));
264         if (!candev->hwspecops){
265                 CANMSG("No space left in memory\n");
266                 sys_err();
267         }
268         memset(candev->hwspecops, 0, sizeof(struct hwspecops_t));
269
270         
271
272         // DEBUG
273         //ul_usb1_register(candev->hwspecops);  // only for successful compiling (defined in ul_usb1.c)
274         // register for another board
275         can_lmc1_register(candev->hwspecops);
276
277         
278
279         bd=baudrate[0];
280         if (candev->hwspecops->init_hw_data(candev)){
281                 CANMSG("HW data could not be initialized\n");
282                 sys_err();
283         }
284
285         // Alocate and initialize the chip structures
286         for (chipnr=0; chipnr < candev->nr_all_chips; chipnr++) {
287 //              if(chipnr<irqnum)
288 //                      irqsig=irq[*irq_param_idx_p+chipnr];
289                 if (init_chip_struct(candev, chipnr, 0, bd*1000)){
290                         CANMSG("Chip structure could not be initialized\n");
291                         sys_err();
292                 }
293         }
294
295
296
297         for (chipnr=0; chipnr < candev->nr_all_chips; chipnr++) {
298                 struct canchip_t *chip=candev->chip[chipnr];
299                 int objnr;
300
301                 register_chip_struct(chip, m);
302
303                 for (objnr=0; objnr<chip->max_objects; objnr++) {
304                         register_obj_struct(chip->msgobj[objnr], m);
305                         if(m>=0) m++;
306                 }
307         }
308
309
310         if (candev->hwspecops->request_io(candev))
311                 sys_err();
312         candev->flags|=CANDEV_IO_RESERVED;
313
314
315         if (candev->hwspecops->reset(candev))
316                 sys_err();
317
318
319         for(chipnr=0; chipnr<candev->nr_all_chips; chipnr++) {
320                 if((chip=candev->chip[chipnr])==NULL)
321                         continue;
322
323                 if(chip->chipspecops->attach_to_chip(chip)<0) {
324 //                      CANMSG("Initial attach to the chip HW failed\n");
325                         sys_err();
326                 }
327
328                 chip->flags |= CHIP_ATTACHED;
329
330 // Interrupts from chip are served in main cycle
331 //              if(can_chip_setup_irq(chip)<0) {
332 //                      CANMSG("Error to setup chip IRQ\n");
333 //                      sys_err();
334 //              }
335         }
336
337         if (candev->flags & CANDEV_PROGRAMMABLE_IRQ)
338                 if (candev->hwspecops->program_irq(candev)){
339 //                      CANMSG("Error to program board interrupt\n");
340                         sys_err();
341                 }
342
343         //***********************************************************************
344         // * CAN device initialization - client side (adapted from LinCAN open.c)
345         // ***********************************************************************
346
347
348         chip=candev->chip[0];
349         obj=chip->msgobj[0];
350         atomic_inc(&obj->obj_used);
351         can_msgobj_set_fl(obj,OPENED);
352
353         if (chip->flags & CHIP_CONFIGURED)
354                 DEBUGMSG("Device is already configured.\n");
355         else {
356                 if (chip->chipspecops->chip_config(chip))
357                         CANMSG("Error configuring chip.\n");
358                 else
359                         chip->flags |= CHIP_CONFIGURED;
360
361                 if (chip->chipspecops->pre_read_config(chip,obj)<0)
362                         CANMSG("Error initializing chip for receiving\n");
363
364         } // End of chip configuration
365
366
367         canuser = (struct canuser_t *)malloc(sizeof(struct canuser_t));
368         if(canuser == NULL) sys_err();
369         canuser->flags=0;
370 //      canuser->userinfo.fileinfo.file = file;
371         canuser->msgobj = obj;
372 //      canuser->magic = CAN_USER_MAGIC;
373 //      file->private_data = canuser;
374
375         qends = (struct canque_ends_t *)malloc(sizeof(struct canque_ends_t));
376         if(qends == NULL) sys_err();
377         canqueue_ends_init_kern(qends);
378         canuser->qends = qends;
379
380         //required to synchronize with RT-Linux context
381         can_spin_lock_irqsave(&canuser_manipulation_lock, iflags);
382         list_add(&canuser->peers, &obj->obj_users);
383         can_spin_unlock_irqrestore(&canuser_manipulation_lock, iflags);
384
385         if(canqueue_connect_edge(edge=canque_new_edge_kern(MAX_BUF_LENGTH),
386                 canuser->qends, obj->qends)<0) sys_err();
387
388         if(canqueue_connect_edge(canuser->rx_edge0=canque_new_edge_kern(MAX_BUF_LENGTH),
389                 obj->qends, canuser->qends)<0) sys_err();
390         //FIXME: more generic model should be used there
391         canque_edge_decref(canuser->rx_edge0);
392         canque_edge_decref(edge);
393
394
395
396         /***********************************************************************
397          * USB Init
398          ***********************************************************************/
399
400         memset( &usb_device, 0, sizeof( usb_device));
401         usb_device.id = 1;
402         usb_device.devdes_table = &usb_devdes_table;
403         usb_device.init = usb_lpc_init;
404         usb_debug_set_level(DEBUG_LEVEL_NONE);
405         usb_device.cntep = NUM_ENDPOINTS;
406         usb_device.ep = eps;
407
408         eps[0].max_packet_size = USB_MAX_PACKET;
409         eps[1].max_packet_size = USB_MAX_PACKET;
410         eps[0].epnum = 0x01;
411         eps[1].epnum = 0x81;
412         eps[0].event_mask = 0x04;
413         eps[1].event_mask = 0x08;
414         eps[0].udev = &usb_device;
415         eps[1].udev = &usb_device;
416
417         usb_device.vendor_fnc=usbcan_vendor;
418
419         usb_init(&usb_device);
420         usb_connect(&usb_device);
421         usb_device.ep_events |= MASK_EP1TX;
422
423         /***********************************************************************
424          * Start
425          ***********************************************************************/
426
427         timer_rx_off=timer_tx_off=timer_str=timer_configured=0;
428
429
430         printf("Main loop\n");
431
432         while (1) {
433
434                 usb_check_events(&usb_device);
435                 usb_control_response(&usb_device);
436
437 // DEBUG
438 //              if (!(IO0PIN&P0_SJA1000_INT_PIN)) //INT PIN is inverted
439 //                      chip->chipspecops->irq_handler(0,chip);
440
441 //              if (CAN1SR & CAN_SR_RBS)
442 //                      chip->chipspecops->irq_handler(0,chip);
443
444
445                 if (usb_device.ep_events & MASK_EP1RX) {  //EP1RX - data waiting to receive
446                         
447                         if (canque_get_inslot(qends, &qedge, &slot, 0)>=0){ //Free slot obtained
448
449                                 size=usb_udev_read_endpoint(&eps[0],ep1_rx_buff,16);
450                                 if (size==16){
451                                         uint16_t msgflags;
452                                         uint32_t msgid;
453                                         canmsg.cob=0;
454                                         canmsg.length=*(uint8_t *)(ep1_rx_buff+1);
455                                         if (canmsg.length > CAN_MSG_LENGTH)
456                                                 canmsg.length=CAN_MSG_LENGTH;
457                                         msgflags=*(uint16_t *)(ep1_rx_buff+2);
458                                         msgid=*(uint32_t *)(ep1_rx_buff+4);
459                                         #if __BYTE_ORDER == __BIG_ENDIAN
460                                                 msgflags  = bswap_16( msgflags);
461                                                 msgid  = bswap_32( msgid);
462                                         #endif
463                                         canmsg.flags=msgflags;
464                                         canmsg.id=msgid;
465
466                                         for (i=0;i<canmsg.length;i++){
467                                                 canmsg.data[i]=*(unsigned char*)(ep1_rx_buff+8+i);
468                                         }
469                                         for (;i<CAN_MSG_LENGTH;i++){
470                                                 canmsg.data[i]=0;
471                                         }
472                                         /* Automatic selection of extended format if ID>2047 */
473                                         if (canmsg.id & ~0x7ffl & MSG_ID_MASK ) canmsg.flags |= MSG_EXT;
474                                         /* has been dependent on "extended" option */
475                         
476                                         slot->msg=canmsg;
477                                         canque_put_inslot(qends, qedge, slot);
478                                         //CAN_send(&canmsg);
479                                 }
480                                 else
481                                         canque_abort_inslot(qends,qedge,slot);
482                                         
483
484                                 timer_rx_off=50;        //rosviceni diody pri prijmu
485                                 CLR_OUT_PIN(LED_PORT,LED2_BIT);
486                                 usb_device.ep_events &= ~MASK_EP1RX;
487                         
488                                         
489                         }
490                         
491
492 /*                      if (size==2){
493                                 uint8_t val;
494                                 if ((data[0]&CAN_OP_MASK)==CAN_OP_READ){ // Get data from CAN device and return to caller
495                                         val = can_read(data[0] & ~CAN_OP_MASK);
496                                         *(data+1)=val;
497                                         usb_udev_write_endpoint(&eps[1],(unsigned char *)data,size);
498                                         timer_rx_off=50;        //rosviceni diody pri prijmu
499                                         CLR_OUT_PIN(LED_PORT,LED2_BIT);
500                                         usb_can_send=0;
501                                 }
502                                 if ((data[0]&CAN_OP_MASK)==CAN_OP_WRITE){ // Save data to CAN device
503                                         can_write(data[1], data[0] & ~CAN_OP_MASK);
504                                         timer_tx_off=50;                //rozsviceni diod pri vysilani
505                                         CLR_OUT_PIN(LED_PORT,LED1_BIT);
506                                 }
507                         }*/
508                 }
509
510                 
511                 if(usb_device.ep_events & MASK_EP1TX){ //EP1TX - data transmitted
512                         if(canque_test_outslot(qends, &qedge, &slot)>=0){
513                                 DEBUGMSG("CAN message ready to send over usb\n");
514                                 uint16_t msgflags;
515                                 uint32_t msgid;
516
517                                 *(uint8_t *)(ep1_tx_buff)=0;
518                                 *(uint8_t *)(ep1_tx_buff+1)=slot->msg.length;
519
520                                 msgflags=slot->msg.flags;
521                                 msgid=slot->msg.id;
522                                 #if __BYTE_ORDER == __BIG_ENDIAN
523                                         msgflags  = bswap_16( msgflags);
524                                         msgid  = bswap_32( msgid);
525                                 #endif
526
527                                 *(uint16_t *)(ep1_tx_buff+2)=msgflags;
528                                 *(uint32_t *)(ep1_tx_buff+4)=msgid;
529                                 for (i=0;i<slot->msg.length;i++){
530                                         *(uint8_t *)(ep1_tx_buff+8+i)=slot->msg.data[i];
531                                 }
532                                 for (;i<CAN_MSG_LENGTH;i++){
533                                         *(uint8_t *)(ep1_tx_buff+8+i)=0;
534                                 }
535                                 usb_udev_write_endpoint(&eps[1],ep1_tx_buff,16);
536
537                                 //printf("ID: %d\n", msgid);
538
539                                 canque_free_outslot(qends, qedge, slot);
540                                 timer_tx_off=50;                //rozsviceni diod pri vysilani
541                                 CLR_OUT_PIN(LED_PORT,LED1_BIT);
542                                 usb_device.ep_events &= ~MASK_EP1TX;
543
544                         }
545                         
546                 }
547                 
548
549                 //if (usb_can_send && )
550
551 #ifdef WATCHDOG_ENABLED
552                 watchdog_feed();
553 #endif /* WATCHDOG_ENABLED */
554
555                 /* 10ms timer */
556                 if (lt_10msec_expired(10))
557                         timer_10ms();
558         }
559
560         SET_OUT_PIN(LED_PORT,LED_GP);
561         SET_OUT_PIN(LED_PORT,LED_ERR);
562
563         /* unreachable code */
564 #ifdef SDCC
565         vec_jmp(0x0);  /* need to call a function from misc to correct linking */
566 #endif
567         return 0;
568 }