4 #include <system_def.h>
6 #include <local_config.h>
7 #include <usb/usbdebug.h>
10 #include <usb/usb_srq.h>
12 #include <keyval_id.h>
13 #include <hal_machperiph.h>
14 #include <keyval_loc.h>
16 #include <lpciap_kvpb.h>
19 #if __BYTE_ORDER == __BIG_ENDIAN
23 #include "./can/can.h"
24 #include "./can/sja1000p.h"
25 #include "./can/main.h"
27 // #include "./can/can_sysdep.h"
28 #include "./can/modparms.h"
29 #include "./can/devcommon.h"
31 #include "./can/ul_usb1.h"
32 //#include "./can/setup.h"
34 #include "./usb/usb_defs.h"
35 #include "./usb/usb_vend.h"
37 #define MASK_EP1RX 0x01
38 #define MASK_EP1TX 0x02
40 #define CAN_OP_MASK 0x80
41 #define CAN_OP_READ 0x80
42 #define CAN_OP_WRITE 0x00
46 #define USB_MAX_PACKET 16
48 /***********************************************************************
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 ***********************************************************************/
57 /***********************************************************************
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 ***********************************************************************/
63 LT_TIMER_DEC(lt_10msec)
64 LT_TIMER_IMP(lt_10msec)
65 LT_TIMER_DEC(lt_100msec)
66 LT_TIMER_IMP(lt_100msec)
70 typedef void (*FNC)(); //function ptr
72 /***********************************************************************
74 ***********************************************************************/
77 usb_device_t usb_device;
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;
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];
95 struct canuser_t *canuser;
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);
101 /***********************************************************************
102 * IF SOMETHING BAD HAPPENED
103 ***********************************************************************/
109 if (lt_100msec_expired(100)) {
112 SET_OUT_PIN(LED_PORT,LED_ERR);
114 CLR_OUT_PIN(LED_PORT,LED_ERR);
116 #ifdef WATCHDOG_ENABLED
118 #endif /* WATCHDOG_ENABLED */
123 /***********************************************************************
124 * Routine for visible LED blinking (on USB transmission)
125 ***********************************************************************/
127 void timer_10ms(void)
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--;
136 CLR_OUT_PIN(LED_PORT,LED1_BIT);
137 CLR_OUT_PIN(LED_PORT,LED2_BIT);
138 timer_rx_off=timer_tx_off=5;
142 /***********************************************************************
144 ***********************************************************************/
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;
160 CANMSG("Starting USBCAN module firmware...\n");
164 /***********************************/
169 SET_OUT_PIN(LED_PORT,LED_ERR);
170 CLR_OUT_PIN(LED_PORT,LED_GP);
172 if (USB_MAX_PACKET<16){
173 CANMSG("Maximum packet size less than 16B (is %dB)\n",USB_MAX_PACKET);
177 /***********************************************************************
178 * CAN device initialization - device side (adapted from LinCAN setup.c)
179 ***********************************************************************/
183 DEBUGMSG("Initiating CAN device initialization\n");
186 canqueue_kern_initialize();
188 hardware_p->nr_boards=1;
190 candev=(struct candevice_t *)malloc(sizeof(struct candevice_t));
192 CANMSG("No space left in memory\n");
195 memset(candev, 0, sizeof(struct candevice_t));
197 hardware_p->candevice[0]=candev;
198 candev->candev_idx=0;
200 candev->dev_base_addr=0;
202 candev->hwspecops=(struct hwspecops_t *)malloc(sizeof(struct hwspecops_t));
203 if (!candev->hwspecops){
204 CANMSG("No space left in memory\n");
207 memset(candev->hwspecops, 0, sizeof(struct hwspecops_t));
209 ul_usb1_register(candev->hwspecops);
212 if (candev->hwspecops->init_hw_data(candev)){
213 CANMSG("HW data could not be initialized\n");
216 /* Alocate and initialize the chip structures */
217 for (chipnr=0; chipnr < candev->nr_all_chips; chipnr++) {
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");
225 for (chipnr=0; chipnr < candev->nr_all_chips; chipnr++) {
226 struct canchip_t *chip=candev->chip[chipnr];
229 register_chip_struct(chip, m);
231 for (objnr=0; objnr<chip->max_objects; objnr++) {
232 register_obj_struct(chip->msgobj[objnr], m);
236 if (candev->hwspecops->request_io(candev))
238 candev->flags|=CANDEV_IO_RESERVED;
239 if (candev->hwspecops->reset(candev))
241 for(chipnr=0; chipnr<candev->nr_all_chips; chipnr++) {
242 if((chip=candev->chip[chipnr])==NULL)
245 if(chip->chipspecops->attach_to_chip(chip)<0) {
246 // CANMSG("Initial attach to the chip HW failed\n");
250 chip->flags |= CHIP_ATTACHED;
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");
259 if (candev->flags & CANDEV_PROGRAMMABLE_IRQ)
260 if (candev->hwspecops->program_irq(candev)){
261 // CANMSG("Error to program board interrupt\n");
265 /***********************************************************************
266 * CAN device initialization - client side (adapted from LinCAN open.c)
267 ***********************************************************************/
269 chip=candev->chip[0];
271 atomic_inc(&obj->obj_used);
272 can_msgobj_set_fl(obj,OPENED);
274 if (chip->flags & CHIP_CONFIGURED)
275 DEBUGMSG("Device is already configured.\n");
277 if (chip->chipspecops->chip_config(chip))
278 CANMSG("Error configuring chip.\n");
280 chip->flags |= CHIP_CONFIGURED;
282 if (chip->chipspecops->pre_read_config(chip,obj)<0)
283 CANMSG("Error initializing chip for receiving\n");
285 } /* End of chip configuration */
287 canuser = (struct canuser_t *)malloc(sizeof(struct canuser_t));
288 if(canuser == NULL) sys_err();
290 // canuser->userinfo.fileinfo.file = file;
291 canuser->msgobj = obj;
292 // canuser->magic = CAN_USER_MAGIC;
293 // file->private_data = canuser;
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;
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);
305 if(canqueue_connect_edge(edge=canque_new_edge_kern(MAX_BUF_LENGTH),
306 canuser->qends, obj->qends)<0) sys_err();
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);
315 /***********************************************************************
317 ***********************************************************************/
319 memset( &usb_device, 0, sizeof( usb_device));
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;
327 eps[0].max_packet_size = USB_MAX_PACKET;
328 eps[1].max_packet_size = USB_MAX_PACKET;
331 eps[0].event_mask = 0x04;
332 eps[1].event_mask = 0x08;
333 eps[0].udev = &usb_device;
334 eps[1].udev = &usb_device;
336 usb_device.vendor_fnc=usbcan_vendor;
338 usb_init(&usb_device);
339 usb_connect(&usb_device);
340 usb_device.ep_events |= MASK_EP1TX;
342 /***********************************************************************
344 ***********************************************************************/
346 timer_rx_off=timer_tx_off=timer_str=timer_configured=0;
349 usb_check_events(&usb_device);
350 usb_control_response(&usb_device);
352 if (!(IO0PIN&P0_SJA1000_INT_PIN)) //INT PIN is inverted
353 chip->chipspecops->irq_handler(0,chip);
355 if (usb_device.ep_events & MASK_EP1RX) { //EP1RX - data waiting to receive
357 if (canque_get_inslot(qends, &qedge, &slot, 0)>=0){ //Free slot obtained
358 size=usb_udev_read_endpoint(&eps[0],ep1_rx_buff,16);
363 canmsg.length=*(uint8_t *)(ep1_rx_buff+1);
364 if (canmsg.length > CAN_MSG_LENGTH)
365 canmsg.length=CAN_MSG_LENGTH;
366 msgflags=*(uint16_t *)(ep1_rx_buff+2);
367 msgid=*(uint32_t *)(ep1_rx_buff+4);
368 #if __BYTE_ORDER == __BIG_ENDIAN
369 msgflags = bswap_16( msgflags);
370 msgid = bswap_32( msgid);
372 canmsg.flags=msgflags;
375 for (i=0;i<canmsg.length;i++){
376 canmsg.data[i]=*(unsigned char*)(ep1_rx_buff+8+i);
378 for (;i<CAN_MSG_LENGTH;i++){
381 /* Automatic selection of extended format if ID>2047 */
382 if (canmsg.id & ~0x7ffl & MSG_ID_MASK ) canmsg.flags |= MSG_EXT;
383 /* has been dependent on "extended" option */
385 canque_put_inslot(qends, qedge, slot);
388 canque_abort_inslot(qends,qedge,slot);
389 timer_rx_off=50; //rosviceni diody pri prijmu
390 CLR_OUT_PIN(LED_PORT,LED2_BIT);
391 usb_device.ep_events &= ~MASK_EP1RX;
396 if (((*data)&CAN_OP_MASK)==CAN_OP_READ){ // Get data from CAN device and return to caller
397 can_read((*data) & 0x7F,&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);
404 if (((*data)&CAN_OP_MASK)==CAN_OP_WRITE){ // Save data to CAN device
405 can_write((*data)&(~CAN_OP_MASK),data+1);
406 timer_tx_off=50; //rozsviceni diod pri vysilani
407 CLR_OUT_PIN(LED_PORT,LED1_BIT);
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");
418 *(uint8_t *)(ep1_tx_buff)=0;
419 *(uint8_t *)(ep1_tx_buff+1)=slot->msg.length;
421 msgflags=slot->msg.flags;
423 #if __BYTE_ORDER == __BIG_ENDIAN
424 msgflags = bswap_16( msgflags);
425 msgid = bswap_32( msgid);
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];
433 for (;i<CAN_MSG_LENGTH;i++){
434 *(uint8_t *)(ep1_tx_buff+8+i)=0;
436 usb_udev_write_endpoint(&eps[1],ep1_tx_buff,16);
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;
445 //if (usb_can_send && )
447 #ifdef WATCHDOG_ENABLED
449 #endif /* WATCHDOG_ENABLED */
452 if (lt_10msec_expired(10))
456 SET_OUT_PIN(LED_PORT,LED_GP);
457 SET_OUT_PIN(LED_PORT,LED_ERR);
459 /* unreachable code */
461 vec_jmp(0x0); /* need to call a function from misc to correct linking */