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