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>
18 #include "./can/can.h"
19 #include "./can/sja1000p.h"
20 #include "./can/main.h"
22 #include "./can/can_sysdep.h"
23 #include "./can/modparms.h"
24 #include "./can/devcommon.h"
26 #include "./can/ul_usb1.h"
27 //#include "./can/setup.h"
29 #define MASK_EP1RX 0x01
30 #define MASK_EP1TX 0x02
34 #define USB_MAX_PACKET 16
37 #define CAN_OP_MASK 0x80
38 #define CAN_OP_READ 0x80
39 #define CAN_OP_WRITE 0x00
41 /***********************************************************************
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 ***********************************************************************/
50 /***********************************************************************
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 ***********************************************************************/
56 LT_TIMER_DEC(lt_10msec)
57 LT_TIMER_IMP(lt_10msec)
58 LT_TIMER_DEC(lt_100msec)
59 LT_TIMER_IMP(lt_100msec)
63 typedef void (*FNC)(); //function ptr
65 /***********************************************************************
67 ***********************************************************************/
70 usb_device_t usb_device;
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;
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];
87 /***********************************************************************
88 * SOMETHING BAD HAPPENED
89 ***********************************************************************/
95 if (lt_100msec_expired(100)) {
98 SET_OUT_PIN(LED_PORT,LED_ERR);
100 CLR_OUT_PIN(LED_PORT,LED_ERR);
102 #ifdef WATCHDOG_ENABLED
104 #endif /* WATCHDOG_ENABLED */
109 /***********************************************************************
110 * Routine for visible LED blinking (on USB transmission)
111 ***********************************************************************/
113 void timer_10ms(void)
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--;
122 CLR_OUT_PIN(LED_PORT,LED1_BIT);
123 CLR_OUT_PIN(LED_PORT,LED2_BIT);
124 timer_rx_off=timer_tx_off=5;
128 /***********************************************************************
130 ***********************************************************************/
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;
149 /***********************************/
154 SET_OUT_PIN(LED_PORT,LED_ERR);
155 CLR_OUT_PIN(LED_PORT,LED_GP);
157 /***********************************************************************
158 * CAN device initialization - device side (adapted from LinCAN setup.c)
159 ***********************************************************************/
164 canqueue_kern_initialize();
166 hardware_p->nr_boards=1;
168 candev=(struct candevice_t *)malloc(sizeof(struct candevice_t));
169 if (candev==NULL) sys_err();
170 memset(candev, 0, sizeof(struct candevice_t));
172 hardware_p->candevice[0]=candev;
173 candev->candev_idx=0;
175 candev->dev_base_addr=0;
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));
181 ul_usb1_register(candev->hwspecops);
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++) {
188 irqsig=irq[*irq_param_idx_p+chipnr];*/
189 if (init_chip_struct(candev, chipnr, 0, bd*1000)) sys_err();
191 if (candev->hwspecops->request_io(candev))
193 candev->flags|=CANDEV_IO_RESERVED;
194 if (candev->hwspecops->reset(candev))
196 for(chipnr=0; chipnr<candev->nr_all_chips; chipnr++) {
197 if((chip=candev->chip[chipnr])==NULL)
200 if(chip->chipspecops->attach_to_chip(chip)<0) {
201 // CANMSG("Initial attach to the chip HW failed\n");
205 chip->flags |= CHIP_ATTACHED;
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");
214 if (candev->flags & CANDEV_PROGRAMMABLE_IRQ)
215 if (candev->hwspecops->program_irq(candev)){
216 // CANMSG("Error to program board interrupt\n");
220 /***********************************************************************
221 * CAN device initialization - client side (adapted from LinCAN open.c)
222 ***********************************************************************/
224 chip=candev->chip[0];
226 atomic_inc(&obj->obj_used);
227 can_msgobj_set_fl(obj,OPENED);
229 if (chip->flags & CHIP_CONFIGURED)
230 DEBUGMSG("Device is already configured.\n");
232 if (chip->chipspecops->chip_config(chip))
233 CANMSG("Error configuring chip.\n");
235 chip->flags |= CHIP_CONFIGURED;
237 if (chip->chipspecops->pre_read_config(chip,obj)<0)
238 CANMSG("Error initializing chip for receiving\n");
240 } /* End of chip configuration */
242 canuser = (struct canuser_t *)malloc(sizeof(struct canuser_t));
243 if(canuser == NULL) sys_err();
245 // canuser->userinfo.fileinfo.file = file;
246 canuser->msgobj = obj;
247 // canuser->magic = CAN_USER_MAGIC;
248 // file->private_data = canuser;
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;
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);
260 if(canqueue_connect_edge(edge=canque_new_edge_kern(MAX_BUF_LENGTH),
261 canuser->qends, obj->qends)<0) sys_err();
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);
270 /***********************************************************************
272 ***********************************************************************/
274 memset( &usb_device, 0, sizeof( usb_device));
276 usb_device.init = usb_lpc_init;
277 usb_debug_set_level(DEBUG_LEVEL_NONE);
278 usb_device.cntep = 3;
281 eps[0].max_packet_size = USB_MAX_PACKET;
282 eps[1].max_packet_size = USB_MAX_PACKET;
285 eps[0].event_mask = 0x04;
286 eps[1].event_mask = 0x08;
287 eps[0].udev = &usb_device;
288 eps[1].udev = &usb_device;
290 // usb_device.vendor_fnc=usb_loader;
292 usb_init(&usb_device);
293 usb_connect(&usb_device);
297 /***********************************************************************
299 ***********************************************************************/
301 timer_rx_off=timer_tx_off=timer_str=timer_configured=0;
304 usb_check_events(&usb_device);
305 usb_control_response(&usb_device);
307 if (!(IO0PIN&P0_SJA1000_INT_PIN))
308 chip->chipspecops->irq_handler(0,chip);
310 if (usb_device.ep_events & MASK_EP1RX) { //EP1RX - data waiting to receive
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);
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));
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 */
326 canque_put_inslot(qends, qedge, slot);
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;
337 if (((*data)&CAN_OP_MASK)==CAN_OP_READ){ // Get data from CAN device and return to caller
338 can_read((*data) & 0x7F,&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);
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);
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];
360 usb_udev_write_endpoint(&eps[1],ep1_tx_buff,USB_MAX_PACKET);
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;
369 //if (usb_can_send && )
371 #ifdef WATCHDOG_ENABLED
373 #endif /* WATCHDOG_ENABLED */
376 if (lt_10msec_expired(10))
380 SET_OUT_PIN(LED_PORT,LED_GP);
381 SET_OUT_PIN(LED_PORT,LED_ERR);
383 /* unreachable code */
385 vec_jmp(0x0); /* need to call a function from misc to correct linking */