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