]> rtime.felk.cvut.cz Git - lincan.git/blob - embedded/app/usbcan/main.c
0aff2218bee382771d2a40ffbe8532ee352dd1ad
[lincan.git] / embedded / app / usbcan / main.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <cpu_def.h>
4 #include <system_def.h>
5 #include <lt_timer.h>
6 #include <local_config.h>
7 #include <usb/usbdebug.h>
8 #include <usb/usb.h>
9 #include <usb/lpc.h>
10 #include <usb/usb_srq.h>
11 #include <mem_loc.h>
12 #include <keyval_id.h>
13 #include <hal_machperiph.h>
14 #include <keyval_loc.h>
15 #include <lpciap.h>
16 #include <lpciap_kvpb.h>
17
18 #include <endian.h>
19 #if __BYTE_ORDER == __BIG_ENDIAN
20   #include <byteswap.h>
21 #endif
22
23 #include "./can/can.h"
24 #include "./can/sja1000p.h"
25 #include "./can/main.h"
26
27 // #include "./can/can_sysdep.h"
28 #include "./can/modparms.h"
29 #include "./can/devcommon.h"
30
31 #include "./can/ul_usb1.h"
32 //#include "./can/setup.h"
33
34 #include "./usb/usb_defs.h"
35 #include "./usb/usb_vend.h"
36
37 #define MASK_EP1RX  0x01
38 #define MASK_EP1TX  0x02
39
40 #define CAN_OP_MASK 0x80
41 #define CAN_OP_READ 0x80
42 #define CAN_OP_WRITE 0x00
43
44 #ifdef USB_MAX_PACKET
45         #undef USB_MAX_PACKET
46         #define USB_MAX_PACKET 16
47 #endif
48 /***********************************************************************
49  * Note:
50  * Comparing to LinCAN, there is no need to sleep for processes
51  * because the degree of filling of fifo from the client side
52  * is solved in main cycle (no new messages are accepted when full)
53  * and on the server side by speed of USB interface. FIFO in edge
54  * from SJA chip to USB interface should never be filled.
55  ***********************************************************************/
56
57 /***********************************************************************
58  * Note:
59  * Code is wittingly complex in order to ease future changes in hardware
60  * configuration and to make it as much similar as the code of LinCAN
61  ***********************************************************************/
62
63 LT_TIMER_DEC(lt_10msec)
64 LT_TIMER_IMP(lt_10msec)
65 LT_TIMER_DEC(lt_100msec)
66 LT_TIMER_IMP(lt_100msec)
67 LT_TIMER_DEC(lt_2sec)
68 LT_TIMER_IMP(lt_2sec)
69
70 typedef void (*FNC)(); //function ptr
71
72 /***********************************************************************
73  * global variables
74  ***********************************************************************/
75
76
77 usb_device_t usb_device;
78
79 usb_ep_t eps[NUM_ENDPOINTS];
80 unsigned char ep1_rx_buff[USB_MAX_PACKET];
81 unsigned char ep1_tx_buff[USB_MAX_PACKET];
82 uint8_t timer_str,timer_rx_off,timer_tx_off,timer_configured;
83 volatile uint8_t bootloader_run;
84
85 uint8_t vendor_ret;
86
87 int processlocal;
88
89 int baudrate[MAX_TOT_CHIPS];
90 struct canhardware_t canhardware;
91 struct canhardware_t *hardware_p=&canhardware;
92 struct canchip_t *chips_p[MAX_TOT_CHIPS];
93 struct msgobj_t *objects_p[MAX_TOT_MSGOBJS];
94
95 struct canuser_t *canuser;
96
97 extern int init_chip_struct(struct candevice_t *candev, int chipnr, int irq, long baudrate);
98 extern int register_chip_struct(struct canchip_t *chip, int minorbase);
99 extern int register_obj_struct(struct msgobj_t *obj, int minorbase);
100
101 /***********************************************************************
102  * IF SOMETHING BAD HAPPENED
103  ***********************************************************************/
104
105 int sys_err(){
106   unsigned char i=0;
107
108   while(1) {
109     if (lt_100msec_expired(100)) {
110       i++;
111       if (i&1) {
112         SET_OUT_PIN(LED_PORT,LED_ERR);
113       } else {
114         CLR_OUT_PIN(LED_PORT,LED_ERR);
115       }
116      #ifdef WATCHDOG_ENABLED
117       watchdog_feed();
118      #endif /* WATCHDOG_ENABLED */
119     }
120   }
121 }
122
123 /***********************************************************************
124  * Routine for visible LED blinking (on USB transmission)
125  ***********************************************************************/
126
127 void timer_10ms(void)
128 {
129   if (timer_tx_off!=0) timer_tx_off--;
130   else SET_OUT_PIN(LED_PORT,LED1_BIT);
131   if (timer_rx_off!=0) timer_rx_off--;
132   else SET_OUT_PIN(LED_PORT,LED2_BIT);
133 /*  if (timer_configured!=0) timer_configured--;
134   else {
135     timer_configured=20;
136                 CLR_OUT_PIN(LED_PORT,LED1_BIT);
137                 CLR_OUT_PIN(LED_PORT,LED2_BIT);
138                 timer_rx_off=timer_tx_off=5;
139   }*/
140 }
141
142 /***********************************************************************
143  * Main routine
144  ***********************************************************************/
145
146 int main(void)
147 {
148         struct candevice_t *candev;
149         struct canchip_t *chip=NULL;
150         struct msgobj_t *obj;
151         struct canque_ends_t *qends;
152         struct canque_edge_t *edge,*qedge;
153         struct canque_slot_t *slot;
154         struct canmsg_t canmsg;
155         can_spin_irqflags_t iflags;
156
157         int chipnr,bd;
158         int i,size,m=0;
159
160         CANMSG("Starting USBCAN module firmware...\n");
161
162 //      volatile int i=0;
163         bootloader_run=0;
164         /***********************************/
165         lt_10msec_init();
166         lt_100msec_init();
167         lt_2sec_init();
168
169         SET_OUT_PIN(LED_PORT,LED_ERR);
170         CLR_OUT_PIN(LED_PORT,LED_GP);
171
172         if (USB_MAX_PACKET<16){
173                 CANMSG("Maximum packet size less than 16B (is %dB)\n",USB_MAX_PACKET);
174                 sys_err();
175         }
176
177         /***********************************************************************
178          * CAN device initialization - device side (adapted from LinCAN setup.c)
179          ***********************************************************************/
180
181         can_init();
182
183         DEBUGMSG("Initiating CAN device initialization\n");
184         baudrate[0]=1000;
185
186         canqueue_kern_initialize();
187
188         hardware_p->nr_boards=1;
189
190         candev=(struct candevice_t *)malloc(sizeof(struct candevice_t));
191         if (!candev){
192                 CANMSG("No space left in memory\n");
193                 sys_err();
194         }
195         memset(candev, 0, sizeof(struct candevice_t));
196
197         hardware_p->candevice[0]=candev;
198         candev->candev_idx=0;
199         candev->io_addr=0;
200         candev->dev_base_addr=0;
201
202         candev->hwspecops=(struct hwspecops_t *)malloc(sizeof(struct hwspecops_t));
203         if (!candev->hwspecops){
204                 CANMSG("No space left in memory\n");
205                 sys_err();
206         }
207         memset(candev->hwspecops, 0, sizeof(struct hwspecops_t));
208
209         ul_usb1_register(candev->hwspecops);
210
211         bd=baudrate[0];
212         if (candev->hwspecops->init_hw_data(candev)){
213                 CANMSG("HW data could not be initialized\n");
214                 sys_err();
215         }
216         /* Alocate and initialize the chip structures */
217         for (chipnr=0; chipnr < candev->nr_all_chips; chipnr++) {
218 /*              if(chipnr<irqnum)
219                         irqsig=irq[*irq_param_idx_p+chipnr];*/
220                 if (init_chip_struct(candev, chipnr, 0, bd*1000)){
221                         CANMSG("Chip structure could not be initialized\n");
222                         sys_err();
223                 }
224         }
225         for (chipnr=0; chipnr < candev->nr_all_chips; chipnr++) {
226                 struct canchip_t *chip=candev->chip[chipnr];
227                 int objnr;
228
229                 register_chip_struct(chip, m);
230
231                 for (objnr=0; objnr<chip->max_objects; objnr++) {
232                         register_obj_struct(chip->msgobj[objnr], m);
233                         if(m>=0) m++;
234                 }
235         }
236         if (candev->hwspecops->request_io(candev))
237                 sys_err();
238         candev->flags|=CANDEV_IO_RESERVED;
239         if (candev->hwspecops->reset(candev))
240                 sys_err();
241         for(chipnr=0; chipnr<candev->nr_all_chips; chipnr++) {
242                 if((chip=candev->chip[chipnr])==NULL)
243                         continue;
244
245                 if(chip->chipspecops->attach_to_chip(chip)<0) {
246 //                      CANMSG("Initial attach to the chip HW failed\n");
247                         sys_err();
248                 }
249
250                 chip->flags |= CHIP_ATTACHED;
251
252 // Interrupts from chip are served in main cycle
253 /*              if(can_chip_setup_irq(chip)<0) {
254 //                      CANMSG("Error to setup chip IRQ\n");
255                         sys_err();
256                 }*/
257         }
258
259         if (candev->flags & CANDEV_PROGRAMMABLE_IRQ)
260                 if (candev->hwspecops->program_irq(candev)){
261 //                      CANMSG("Error to program board interrupt\n");
262                         sys_err();
263                 }
264
265         /***********************************************************************
266          * CAN device initialization - client side (adapted from LinCAN open.c)
267          ***********************************************************************/
268
269         chip=candev->chip[0];
270         obj=chip->msgobj[0];
271         atomic_inc(&obj->obj_used);
272         can_msgobj_set_fl(obj,OPENED);
273
274         if (chip->flags & CHIP_CONFIGURED)
275                 DEBUGMSG("Device is already configured.\n");
276         else {
277                 if (chip->chipspecops->chip_config(chip))
278                         CANMSG("Error configuring chip.\n");
279                 else
280                         chip->flags |= CHIP_CONFIGURED;
281
282                 if (chip->chipspecops->pre_read_config(chip,obj)<0)
283                         CANMSG("Error initializing chip for receiving\n");
284
285         } /* End of chip configuration */
286
287         canuser = (struct canuser_t *)malloc(sizeof(struct canuser_t));
288         if(canuser == NULL) sys_err();
289         canuser->flags=0;
290 //      canuser->userinfo.fileinfo.file = file;
291         canuser->msgobj = obj;
292 //      canuser->magic = CAN_USER_MAGIC;
293 //      file->private_data = canuser;
294
295         qends = (struct canque_ends_t *)malloc(sizeof(struct canque_ends_t));
296         if(qends == NULL) sys_err();
297         canqueue_ends_init_kern(qends);
298         canuser->qends = qends;
299
300         /*required to synchronize with RT-Linux context*/
301         can_spin_lock_irqsave(&canuser_manipulation_lock, iflags);
302         list_add(&canuser->peers, &obj->obj_users);
303         can_spin_unlock_irqrestore(&canuser_manipulation_lock, iflags);
304
305         if(canqueue_connect_edge(edge=canque_new_edge_kern(MAX_BUF_LENGTH),
306                 canuser->qends, obj->qends)<0) sys_err();
307
308         if(canqueue_connect_edge(canuser->rx_edge0=canque_new_edge_kern(MAX_BUF_LENGTH),
309                 obj->qends, canuser->qends)<0) sys_err();
310         /*FIXME: more generic model should be used there*/
311         canque_edge_decref(canuser->rx_edge0);
312         canque_edge_decref(edge);
313
314
315         /***********************************************************************
316          * USB Init
317          ***********************************************************************/
318
319         memset( &usb_device, 0, sizeof( usb_device));
320         usb_device.id = 1;
321         usb_device.devdes_table = &usb_devdes_table;
322         usb_device.init = usb_lpc_init;
323         usb_debug_set_level(DEBUG_LEVEL_NONE);
324         usb_device.cntep = NUM_ENDPOINTS;
325         usb_device.ep = eps;
326
327         eps[0].max_packet_size = USB_MAX_PACKET;
328         eps[1].max_packet_size = USB_MAX_PACKET;
329         eps[0].epnum = 0x01;
330         eps[1].epnum = 0x81;
331         eps[0].event_mask = 0x04;
332         eps[1].event_mask = 0x08;
333         eps[0].udev = &usb_device;
334         eps[1].udev = &usb_device;
335
336         usb_device.vendor_fnc=usbcan_vendor;
337
338         usb_init(&usb_device);
339         usb_connect(&usb_device);
340         usb_device.ep_events |= MASK_EP1TX;
341
342         /***********************************************************************
343          * Start
344          ***********************************************************************/
345
346         timer_rx_off=timer_tx_off=timer_str=timer_configured=0;
347         while (1) {
348
349                 usb_check_events(&usb_device);
350                 usb_control_response(&usb_device);
351
352                 if (!(IO0PIN&P0_SJA1000_INT_PIN)) //INT PIN is inverted
353                         chip->chipspecops->irq_handler(0,chip);
354
355                 if (usb_device.ep_events & MASK_EP1RX) {  //EP1RX - data waiting to receive
356                         if (canque_get_inslot(qends, &qedge, &slot, 0)>=0){ //Free slot obtained
357                                 size=usb_udev_read_endpoint(&eps[0],ep1_rx_buff,16);
358                                 if (size==16){
359                                         uint16_t msgflags;
360                                         uint32_t msgid;
361                                         canmsg.cob=0;
362                                         canmsg.length=*(uint8_t *)(ep1_rx_buff+1);
363                                         if (canmsg.length > CAN_MSG_LENGTH)
364                                                 canmsg.length=CAN_MSG_LENGTH;
365                                         msgflags=*(uint16_t *)(ep1_rx_buff+2);
366                                         msgid=*(uint32_t *)(ep1_rx_buff+4);
367                                         #if __BYTE_ORDER == __BIG_ENDIAN
368                                                 msgflags  = bswap_16( msgflags);
369                                                 msgid  = bswap_32( msgid);
370                                         #endif
371                                         canmsg.flags=msgflags;
372                                         canmsg.id=msgid;
373
374                                         for (i=0;i<canmsg.length;i++){
375                                                 canmsg.data[i]=*(unsigned char*)(ep1_rx_buff+8+i);
376                                         }
377                                         for (;i<CAN_MSG_LENGTH;i++){
378                                                 canmsg.data[i]=0;
379                                         }
380                                         /* Automatic selection of extended format if ID>2047 */
381                                         if (canmsg.id & ~0x7ffl & MSG_ID_MASK ) canmsg.flags |= MSG_EXT;
382                                         /* has been dependent on "extended" option */
383                                         slot->msg=canmsg;
384                                         canque_put_inslot(qends, qedge, slot);
385                                 }
386                                 else
387                                         canque_abort_inslot(qends,qedge,slot);
388                                 timer_rx_off=50;        //rosviceni diody pri prijmu
389                                 CLR_OUT_PIN(LED_PORT,LED2_BIT);
390                                 usb_device.ep_events &= ~MASK_EP1RX;
391                         }
392
393
394 /*                      if (size==2){
395                                 uint8_t val;
396                                 if ((data[0]&CAN_OP_MASK)==CAN_OP_READ){ // Get data from CAN device and return to caller
397                                         val = can_read(data[0] & ~CAN_OP_MASK);
398                                         *(data+1)=val;
399                                         usb_udev_write_endpoint(&eps[1],(unsigned char *)data,size);
400                                         timer_rx_off=50;        //rosviceni diody pri prijmu
401                                         CLR_OUT_PIN(LED_PORT,LED2_BIT);
402                                         usb_can_send=0;
403                                 }
404                                 if ((data[0]&CAN_OP_MASK)==CAN_OP_WRITE){ // Save data to CAN device
405                                         can_write(data[1], data[0] & ~CAN_OP_MASK);
406                                         timer_tx_off=50;                //rozsviceni diod pri vysilani
407                                         CLR_OUT_PIN(LED_PORT,LED1_BIT);
408                                 }
409                         }*/
410                 }
411
412                 if(usb_device.ep_events & MASK_EP1TX){ //EP1TX - data transmitted
413                         if(canque_test_outslot(qends, &qedge, &slot)>=0){
414                                 DEBUGMSG("CAN message ready to send over usb\n");
415                                 uint16_t msgflags;
416                                 uint32_t msgid;
417
418                                 *(uint8_t *)(ep1_tx_buff)=0;
419                                 *(uint8_t *)(ep1_tx_buff+1)=slot->msg.length;
420
421                                 msgflags=slot->msg.flags;
422                                 msgid=slot->msg.id;
423                                 #if __BYTE_ORDER == __BIG_ENDIAN
424                                         msgflags  = bswap_16( msgflags);
425                                         msgid  = bswap_32( msgid);
426                                 #endif
427
428                                 *(uint16_t *)(ep1_tx_buff+2)=msgflags;
429                                 *(uint32_t *)(ep1_tx_buff+4)=msgid;
430                                 for (i=0;i<slot->msg.length;i++){
431                                         *(uint8_t *)(ep1_tx_buff+8+i)=slot->msg.data[i];
432                                 }
433                                 for (;i<CAN_MSG_LENGTH;i++){
434                                         *(uint8_t *)(ep1_tx_buff+8+i)=0;
435                                 }
436                                 usb_udev_write_endpoint(&eps[1],ep1_tx_buff,16);
437
438                                 canque_free_outslot(qends, qedge, slot);
439                                 timer_tx_off=50;                //rozsviceni diod pri vysilani
440                                 CLR_OUT_PIN(LED_PORT,LED1_BIT);
441                                 usb_device.ep_events &= ~MASK_EP1TX;
442                         }
443                 }
444
445                 //if (usb_can_send && )
446
447 #ifdef WATCHDOG_ENABLED
448                 watchdog_feed();
449 #endif /* WATCHDOG_ENABLED */
450
451                 /* 10ms timer */
452                 if (lt_10msec_expired(10))
453                         timer_10ms();
454         }
455
456         SET_OUT_PIN(LED_PORT,LED_GP);
457         SET_OUT_PIN(LED_PORT,LED_ERR);
458
459         /* unreachable code */
460 #ifdef SDCC
461         vec_jmp(0x0);  /* need to call a function from misc to correct linking */
462 #endif
463         return 0;
464 }