]> rtime.felk.cvut.cz Git - lincan.git/blob - embedded/app/usbcan/main.c
b9271e3407ffad0ccac4dc106d27596283ac2ef9
[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 #ifdef USB_MAX_PACKET
40         #undef USB_MAX_PACKET
41         #define USB_MAX_PACKET 16
42 #endif
43
44 #define CAN_OP_MASK 0x80
45 #define CAN_OP_READ 0x80
46 #define CAN_OP_WRITE 0x00
47
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[2];
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 int processlocal;
86
87 int baudrate[MAX_TOT_CHIPS];
88 struct canhardware_t canhardware;
89 struct canhardware_t *hardware_p=&canhardware;
90 struct canchip_t *chips_p[MAX_TOT_CHIPS];
91 struct msgobj_t *objects_p[MAX_TOT_MSGOBJS];
92
93 struct canuser_t *canuser;
94
95
96 /***********************************************************************
97  * SOMETHING BAD HAPPENED
98  ***********************************************************************/
99
100 int sys_err(){
101   unsigned char i=0;
102
103   while(1) {
104     if (lt_100msec_expired(100)) {
105       i++;
106       if (i&1) {
107         SET_OUT_PIN(LED_PORT,LED_ERR);
108       } else {
109         CLR_OUT_PIN(LED_PORT,LED_ERR);
110       }
111      #ifdef WATCHDOG_ENABLED
112       watchdog_feed();
113      #endif /* WATCHDOG_ENABLED */
114     }
115   }
116 }
117
118 /***********************************************************************
119  * Routine for visible LED blinking (on USB transmission)
120  ***********************************************************************/
121
122 void timer_10ms(void)
123 {
124   if (timer_tx_off!=0) timer_tx_off--;
125   else SET_OUT_PIN(LED_PORT,LED1_BIT);
126   if (timer_rx_off!=0) timer_rx_off--;
127   else SET_OUT_PIN(LED_PORT,LED2_BIT);
128 /*  if (timer_configured!=0) timer_configured--;
129   else {
130     timer_configured=20;
131                 CLR_OUT_PIN(LED_PORT,LED1_BIT);
132                 CLR_OUT_PIN(LED_PORT,LED2_BIT);
133                 timer_rx_off=timer_tx_off=5;
134   }*/
135 }
136
137 /***********************************************************************
138  * Main routine
139  ***********************************************************************/
140
141 int main(void)
142 {
143         struct candevice_t *candev;
144         struct canchip_t *chip=NULL;
145         struct msgobj_t *obj;
146         struct canque_ends_t *qends;
147         struct canque_edge_t *edge,*qedge;
148         struct canque_slot_t *slot;
149         struct canmsg_t canmsg;
150         can_spin_irqflags_t iflags;
151
152         int chipnr,bd;
153         int i,size;
154
155 //      volatile int i=0;
156         bootloader_run=0;
157         /***********************************/
158         lt_10msec_init();
159         lt_100msec_init();
160         lt_2sec_init();
161
162         SET_OUT_PIN(LED_PORT,LED_ERR);
163         CLR_OUT_PIN(LED_PORT,LED_GP);
164
165         /***********************************************************************
166          * CAN device initialization - device side (adapted from LinCAN setup.c)
167          ***********************************************************************/
168
169
170         baudrate[0]=1000;
171
172         canqueue_kern_initialize();
173
174         hardware_p->nr_boards=1;
175
176         candev=(struct candevice_t *)malloc(sizeof(struct candevice_t));
177                 if (candev==NULL) sys_err();
178                 memset(candev, 0, sizeof(struct candevice_t));
179
180         hardware_p->candevice[0]=candev;
181         candev->candev_idx=0;
182         candev->io_addr=0;
183         candev->dev_base_addr=0;
184
185         candev->hwspecops=(struct hwspecops_t *)malloc(sizeof(struct hwspecops_t));
186                 if (candev->hwspecops==NULL) sys_err();
187                 memset(candev->hwspecops, 0, sizeof(struct hwspecops_t));
188
189         ul_usb1_register(candev->hwspecops);
190
191         bd=baudrate[0];
192         if (candev->hwspecops->init_hw_data(candev)) sys_err();
193         /* Alocate and initialize the chip structures */
194         for (chipnr=0; chipnr < candev->nr_all_chips; chipnr++) {
195 /*              if(chipnr<irqnum)
196                         irqsig=irq[*irq_param_idx_p+chipnr];*/
197                 if (init_chip_struct(candev, chipnr, 0, bd*1000)) sys_err();
198         }
199         if (candev->hwspecops->request_io(candev))
200                 sys_err();
201         candev->flags|=CANDEV_IO_RESERVED;
202         if (candev->hwspecops->reset(candev))
203                 sys_err();
204         for(chipnr=0; chipnr<candev->nr_all_chips; chipnr++) {
205                 if((chip=candev->chip[chipnr])==NULL)
206                         continue;
207
208                 if(chip->chipspecops->attach_to_chip(chip)<0) {
209 //                      CANMSG("Initial attach to the chip HW failed\n");
210                         sys_err();
211                 }
212
213                 chip->flags |= CHIP_ATTACHED;
214
215 // Interrupts from chip are served in main cycle
216 /*              if(can_chip_setup_irq(chip)<0) {
217 //                      CANMSG("Error to setup chip IRQ\n");
218                         sys_err();
219                 }*/
220         }
221
222         if (candev->flags & CANDEV_PROGRAMMABLE_IRQ)
223                 if (candev->hwspecops->program_irq(candev)){
224 //                      CANMSG("Error to program board interrupt\n");
225                         sys_err();
226                 }
227
228         /***********************************************************************
229          * CAN device initialization - client side (adapted from LinCAN open.c)
230          ***********************************************************************/
231
232         chip=candev->chip[0];
233         obj=chip->msgobj[0];
234         atomic_inc(&obj->obj_used);
235         can_msgobj_set_fl(obj,OPENED);
236
237         if (chip->flags & CHIP_CONFIGURED)
238                 DEBUGMSG("Device is already configured.\n");
239         else {
240                 if (chip->chipspecops->chip_config(chip))
241                         CANMSG("Error configuring chip.\n");
242                 else
243                         chip->flags |= CHIP_CONFIGURED;
244
245                 if (chip->chipspecops->pre_read_config(chip,obj)<0)
246                         CANMSG("Error initializing chip for receiving\n");
247
248         } /* End of chip configuration */
249
250         canuser = (struct canuser_t *)malloc(sizeof(struct canuser_t));
251         if(canuser == NULL) sys_err();
252         canuser->flags=0;
253 //      canuser->userinfo.fileinfo.file = file;
254         canuser->msgobj = obj;
255 //      canuser->magic = CAN_USER_MAGIC;
256 //      file->private_data = canuser;
257
258         qends = (struct canque_ends_t *)malloc(sizeof(struct canque_ends_t));
259         if(qends == NULL) sys_err();
260         canqueue_ends_init_kern(qends);
261         canuser->qends = qends;
262
263         /*required to synchronize with RT-Linux context*/
264         can_spin_lock_irqsave(&canuser_manipulation_lock, iflags);
265         list_add(&canuser->peers, &obj->obj_users);
266         can_spin_unlock_irqrestore(&canuser_manipulation_lock, iflags);
267
268         if(canqueue_connect_edge(edge=canque_new_edge_kern(MAX_BUF_LENGTH),
269                 canuser->qends, obj->qends)<0) sys_err();
270
271         if(canqueue_connect_edge(canuser->rx_edge0=canque_new_edge_kern(MAX_BUF_LENGTH),
272                 obj->qends, canuser->qends)<0) sys_err();
273         /*FIXME: more generic model should be used there*/
274         canque_edge_decref(canuser->rx_edge0);
275         canque_edge_decref(edge);
276
277
278         /***********************************************************************
279          * USB Init
280          ***********************************************************************/
281
282         memset( &usb_device, 0, sizeof( usb_device));
283         usb_device.id = 1;
284         usb_device.init = usb_lpc_init;
285         usb_debug_set_level(DEBUG_LEVEL_NONE);
286         usb_device.cntep = 3;
287         usb_device.ep = eps;
288
289         eps[0].max_packet_size = USB_MAX_PACKET;
290         eps[1].max_packet_size = USB_MAX_PACKET;
291         eps[0].epnum = 0x01;
292         eps[1].epnum = 0x81;
293         eps[0].event_mask = 0x04;
294         eps[1].event_mask = 0x08;
295         eps[0].udev = &usb_device;
296         eps[1].udev = &usb_device;
297
298 //  usb_device.vendor_fnc=usb_loader;
299
300         usb_init(&usb_device);
301         usb_connect(&usb_device);
302
303         can_init();
304
305         /***********************************************************************
306          * Start
307          ***********************************************************************/
308
309   timer_rx_off=timer_tx_off=timer_str=timer_configured=0;
310         while (1) {
311
312                 usb_check_events(&usb_device);
313                 usb_control_response(&usb_device);
314
315                 if (!(IO0PIN&P0_SJA1000_INT_PIN))
316                         chip->chipspecops->irq_handler(0,chip);
317
318                 if (usb_device.ep_events & MASK_EP1RX) {  //EP1RX - data waiting to receive
319                         uint8_t val;
320                         if (canque_get_inslot(qends, &qedge, &slot, 0)>=0){ //Free slot obtained
321                                 size=usb_udev_read_endpoint(&eps[0],ep1_rx_buff,USB_MAX_PACKET);
322                                 if (size==16){
323                                         uint16_t msgflags;
324                                         uint32_t msgid;
325                                         canmsg.cob=0;
326                                         canmsg.length=*(uint8_t *)(ep1_rx_buff+1);
327                                         if (canmsg.length > CAN_MSG_LENGTH)
328                                                 canmsg.length=CAN_MSG_LENGTH;
329                                         msgflags=*(uint16_t *)(ep1_rx_buff+2);
330                                         msgid=*(uint32_t *)(ep1_rx_buff+4);
331                                         #if __BYTE_ORDER == __BIG_ENDIAN
332                                                 msgflags  = bswap_16( msgflags);
333                                                 msgid  = bswap_32( msgid);
334                                         #endif
335                                         canmsg.flags=msgflags;
336                                         canmsg.id=msgid;
337
338                                         for (i=0;i<canmsg.length;i++){
339                                                 canmsg.data[i]=*(unsigned char*)(ep1_rx_buff+8+i);
340                                         }
341                                         for (;i<CAN_MSG_LENGTH;i++){
342                                                 canmsg.data[i]=0;
343                                         }
344                                         /* Automatic selection of extended format if ID>2047 */
345                                         if (canmsg.id & ~0x7ffl & MSG_ID_MASK ) canmsg.flags |= MSG_EXT;
346                                         /* has been dependent on "extended" option */
347                                         slot->msg=canmsg;
348                                         canque_put_inslot(qends, qedge, slot);
349                                 }
350                                 else
351                                         canque_abort_inslot(qends,qedge,slot);
352                                 timer_rx_off=50;        //rosviceni diody pri prijmu
353                                 CLR_OUT_PIN(LED_PORT,LED2_BIT);
354                                 usb_device.ep_events &= ~MASK_EP1RX;
355                         }
356
357
358 /*                      if (size==2){
359                                 if (((*data)&CAN_OP_MASK)==CAN_OP_READ){ // Get data from CAN device and return to caller
360                                         can_read((*data) & 0x7F,&val);
361                                         *(data+1)=val;
362                                         usb_udev_write_endpoint(&eps[1],(unsigned char *)data,size);
363                                         timer_rx_off=50;        //rosviceni diody pri prijmu
364                                         CLR_OUT_PIN(LED_PORT,LED2_BIT);
365                                         usb_can_send=0;
366                                 }
367                                 if (((*data)&CAN_OP_MASK)==CAN_OP_WRITE){ // Save data to CAN device
368                                         can_write((*data)&(~CAN_OP_MASK),data+1);
369                                         timer_tx_off=50;                //rozsviceni diod pri vysilani
370                                         CLR_OUT_PIN(LED_PORT,LED1_BIT);
371                                 }
372                         }*/
373                 }
374
375                 if(usb_device.ep_events & MASK_EP1TX){ //EP1TX - data transmitted
376                         if(canque_test_outslot(qends, &qedge, &slot)>=0){
377                                 uint16_t msgflags;
378                                 uint32_t msgid;
379
380                                 *(uint8_t *)(ep1_tx_buff)=0;
381                                 *(uint8_t *)(ep1_tx_buff+1)=slot->msg.length;
382
383                                 msgflags=slot->msg.flags;
384                                 msgid=slot->msg.id;
385                                 #if __BYTE_ORDER == __BIG_ENDIAN
386                                         msgflags  = bswap_16( msgflags);
387                                         msgid  = bswap_32( msgid);
388                                 #endif
389
390                                 *(uint16_t *)(ep1_tx_buff+2)=msgflags;
391                                 *(uint32_t *)(ep1_tx_buff+4)=msgid;
392                                 for (i=0;i<slot->msg.length;i++){
393                                         *(uint8_t *)(ep1_tx_buff+8+i)=slot->msg.data[i];
394                                 }
395                                 for (;i<CAN_MSG_LENGTH;i++){
396                                         *(uint8_t *)(ep1_tx_buff+8+i)=0;
397                                 }
398                                 usb_udev_write_endpoint(&eps[1],ep1_tx_buff,USB_MAX_PACKET);
399
400                                 canque_free_outslot(qends, qedge, slot);
401                                 timer_tx_off=50;                //rozsviceni diod pri vysilani
402                                 CLR_OUT_PIN(LED_PORT,LED1_BIT);
403                                 usb_device.ep_events &= ~MASK_EP1TX;
404                         }
405                 }
406
407                 //if (usb_can_send && )
408
409 #ifdef WATCHDOG_ENABLED
410                 watchdog_feed();
411 #endif /* WATCHDOG_ENABLED */
412
413                 /* 10ms timer */
414                 if (lt_10msec_expired(10))
415                         timer_10ms();
416         }
417
418         SET_OUT_PIN(LED_PORT,LED_GP);
419         SET_OUT_PIN(LED_PORT,LED_ERR);
420
421         /* unreachable code */
422 #ifdef SDCC
423         vec_jmp(0x0);  /* need to call a function from misc to correct linking */
424 #endif
425         return 0;
426 }