]> rtime.felk.cvut.cz Git - lincan.git/commitdiff
hw side seems complete,
authorJan Kriz <krizj1@fel.cvut.cz>
Wed, 9 Jul 2008 10:51:33 +0000 (12:51 +0200)
committerppisa <pisa@cmp.felk.cvut.cz>
Sun, 23 Nov 2008 23:12:54 +0000 (00:12 +0100)
remains LinCAN side

embedded/app/usbcan/main.c
embedded/app/usbcan/ul_usb1.c

index 205ae3561b025957db11be36a72a73a30d4bd40f..97d9785907fd158223ccb49d4c4fe452367385ee 100644 (file)
 
 #ifdef USB_MAX_PACKET
        #undef USB_MAX_PACKET
-       #define USB_MAX_PACKET 8
+       #define USB_MAX_PACKET 16
 #endif
 
 #define CAN_OP_MASK 0x80
 #define CAN_OP_READ 0x80
 #define CAN_OP_WRITE 0x00
 
+/***********************************************************************
+ * Note:
+ * Comparing to LinCAN, there is no need to sleep for processes
+ * because the degree of filling of fifo from the client side
+ * is solved in main cycle (no new messages are accepted when full)
+ * and on the server side by speed of USB interface. FIFO in edge
+ * from SJA chip to USB interface should never be filled.
+ ***********************************************************************/
+
+/***********************************************************************
+ * Note:
+ * Code is wittingly complex in order to ease future changes in hardware
+ * configuration and to make it as much similar as the code of LinCAN
+ ***********************************************************************/
 
 LT_TIMER_DEC(lt_10msec)
 LT_TIMER_IMP(lt_10msec)
@@ -48,15 +62,17 @@ LT_TIMER_IMP(lt_2sec)
 
 typedef void (*FNC)(); //function ptr
 
-/***********************************/
-// global variables
+/***********************************************************************
+       * global variables
+       ***********************************************************************/
+
 
 usb_device_t usb_device;
 
 usb_ep_t eps[2];
 unsigned char ep1_rx_buff[USB_MAX_PACKET];
 unsigned char ep1_tx_buff[USB_MAX_PACKET];
-uint8_t timer_str,timer_rx_off,timer_tx_off,timer_configured,usb_can_send;
+uint8_t timer_str,timer_rx_off,timer_tx_off,timer_configured;
 volatile uint8_t bootloader_run;
 
 int processlocal;
@@ -68,9 +84,10 @@ struct canchip_t *chips_p[MAX_TOT_CHIPS];
 struct msgobj_t *objects_p[MAX_TOT_MSGOBJS];
 
 
-/**
-       SOMETHING BAD HAPPENED
-*/
+/***********************************************************************
+ * SOMETHING BAD HAPPENED
+ ***********************************************************************/
+
 int sys_err(){
   unsigned char i=0;
 
@@ -89,16 +106,16 @@ int sys_err(){
   }
 }
 
-/**
-       Routine for visible LED blinking
-*/
+/***********************************************************************
+ * Routine for visible LED blinking (on USB transmission)
+ ***********************************************************************/
+
 void timer_10ms(void)
 {
   if (timer_tx_off!=0) timer_tx_off--;
   else SET_OUT_PIN(LED_PORT,LED1_BIT);
   if (timer_rx_off!=0) timer_rx_off--;
   else SET_OUT_PIN(LED_PORT,LED2_BIT);
-
 /*  if (timer_configured!=0) timer_configured--;
   else {
     timer_configured=20;
@@ -108,12 +125,24 @@ void timer_10ms(void)
   }*/
 }
 
-/***********************************/
+/***********************************************************************
+ * Main routine
+ ***********************************************************************/
+
 int main(void)
 {
        struct candevice_t *candev;
-       struct canchip_t *chip;
+       struct canchip_t *chip=NULL;
+       struct msgobj_t *obj;
+       struct canuser_t *canuser;
+       struct canque_ends_t *qends;
+       struct canque_edge_t *edge,*qedge;
+       struct canque_slot_t *slot;
+       struct canmsg_t canmsg;
+       can_spin_irqflags_t iflags;
+
        int chipnr,bd;
+       int i,size;
 
 //     volatile int i=0;
        bootloader_run=0;
@@ -125,8 +154,10 @@ int main(void)
        SET_OUT_PIN(LED_PORT,LED_ERR);
        CLR_OUT_PIN(LED_PORT,LED_GP);
 
-       /// *************************
-       /// CAN device initialization
+       /***********************************************************************
+        * CAN device initialization - device side (adapted from LinCAN setup.c)
+        ***********************************************************************/
+
 
        baudrate[0]=1000;
 
@@ -186,13 +217,59 @@ int main(void)
                        sys_err();
                }
 
+       /***********************************************************************
+        * CAN device initialization - client side (adapted from LinCAN open.c)
+        ***********************************************************************/
+
+       chip=candev->chip[0];
+       obj=chip->msgobj[0];
+       atomic_inc(&obj->obj_used);
+       can_msgobj_set_fl(obj,OPENED);
+
+       if (chip->flags & CHIP_CONFIGURED)
+               DEBUGMSG("Device is already configured.\n");
+       else {
+               if (chip->chipspecops->chip_config(chip))
+                       CANMSG("Error configuring chip.\n");
+               else
+                       chip->flags |= CHIP_CONFIGURED;
+
+               if (chip->chipspecops->pre_read_config(chip,obj)<0)
+                       CANMSG("Error initializing chip for receiving\n");
+
+       } /* End of chip configuration */
+
+       canuser = (struct canuser_t *)malloc(sizeof(struct canuser_t));
+       if(canuser == NULL) sys_err();
+       canuser->flags=0;
+//     canuser->userinfo.fileinfo.file = file;
+       canuser->msgobj = obj;
+//     canuser->magic = CAN_USER_MAGIC;
+//     file->private_data = canuser;
+
+       qends = (struct canque_ends_t *)malloc(sizeof(struct canque_ends_t));
+       if(qends == NULL) sys_err();
+       canqueue_ends_init_kern(qends);
+       canuser->qends = qends;
 
+       /*required to synchronize with RT-Linux context*/
+       can_spin_lock_irqsave(&canuser_manipulation_lock, iflags);
+       list_add(&canuser->peers, &obj->obj_users);
+       can_spin_unlock_irqrestore(&canuser_manipulation_lock, iflags);
 
-       /// ***************************************
-       /// CAN device initialization - client side
+       if(canqueue_connect_edge(edge=canque_new_edge_kern(MAX_BUF_LENGTH),
+               canuser->qends, obj->qends)<0) sys_err();
 
-       ///*********
-       /// USB init
+       if(canqueue_connect_edge(canuser->rx_edge0=canque_new_edge_kern(MAX_BUF_LENGTH),
+               obj->qends, canuser->qends)<0) sys_err();
+       /*FIXME: more generic model should be used there*/
+       canque_edge_decref(canuser->rx_edge0);
+       canque_edge_decref(edge);
+
+
+       /***********************************************************************
+        * USB Init
+        ***********************************************************************/
 
        memset( &usb_device, 0, sizeof( usb_device));
        usb_device.id = 1;
@@ -216,23 +293,47 @@ int main(void)
        usb_connect(&usb_device);
 
        can_init();
-       usb_can_send=1;
 
-       /********************/
-       // start
+       /***********************************************************************
+        * Start
+        ***********************************************************************/
+
   timer_rx_off=timer_tx_off=timer_str=timer_configured=0;
        while (1) {
 
                usb_check_events(&usb_device);
                usb_control_response(&usb_device);
 
-               if ((usb_device.ep_events & MASK_EP1RX)&&(usb_can_send)) {  //EP1RX
-                       int size;
-                       uint8_t *data;
+               if (!(IO0PIN&P0_SJA1000_INT_PIN))
+                       chip->chipspecops->irq_handler(0,chip);
+
+               if (usb_device.ep_events & MASK_EP1RX) {  //EP1RX - data waiting to receive
                        uint8_t val;
-                       size=usb_udev_read_endpoint(&eps[0],ep1_rx_buff,USB_MAX_PACKET);
-                       data=(uint8_t *)ep1_rx_buff;
-                       if (size==2){
+                       if (canque_get_inslot(qends, &qedge, &slot, 0)>=0){ //Free slot obtained
+                               size=usb_udev_read_endpoint(&eps[0],ep1_rx_buff,USB_MAX_PACKET);
+                               if (size==16){
+                                       canmsg.cob=0;
+                                       canmsg.id=*((uint32_t*)ep1_rx_buff);
+                                       canmsg.flags=(*((uint32_t*)(ep1_rx_buff+4)))>>8;
+                                       canmsg.length=(*((uint16_t*)(ep1_rx_buff+6)))&0x00FF;
+                                       for (i=0;i<CAN_MSG_LENGTH;i++){
+                                               canmsg.data[i]=*((unsigned char*)(ep1_rx_buff+8+i));
+                                       }
+                                       /* Automatic selection of extended format if ID>2047 */
+                                       if (canmsg.id & ~0x7ffl & MSG_ID_MASK ) canmsg.flags |= MSG_EXT;
+                                       /* has been dependent on "extended" option */
+                                       slot->msg=canmsg;
+                                       canque_put_inslot(qends, qedge, slot);
+                               }
+                               else
+                                       canque_abort_inslot(qends,qedge,slot);
+                               timer_rx_off=50;        //rosviceni diody pri prijmu
+                               CLR_OUT_PIN(LED_PORT,LED2_BIT);
+                               usb_device.ep_events &= ~MASK_EP1RX;
+                       }
+
+
+/*                     if (size==2){
                                if (((*data)&CAN_OP_MASK)==CAN_OP_READ){ // Get data from CAN device and return to caller
                                        can_read((*data) & 0x7F,&val);
                                        *(data+1)=val;
@@ -246,15 +347,27 @@ int main(void)
                                        timer_tx_off=50;                //rozsviceni diod pri vysilani
                                        CLR_OUT_PIN(LED_PORT,LED1_BIT);
                                }
-                       }
-                       usb_device.ep_events &= ~MASK_EP1RX;
+                       }*/
                }
 
-               if(usb_device.ep_events & MASK_EP1TX){
-                       usb_can_send=1;
-                       usb_device.ep_events &= ~MASK_EP1TX;
+               if(usb_device.ep_events & MASK_EP1TX){ //EP1TX - data transmitted
+                       if(canque_test_outslot(qends, &qedge, &slot)>=0){
+                               (*((uint32_t*)ep1_tx_buff))=slot->msg.id;
+                               (*((uint32_t*)(ep1_tx_buff+4)))=slot->msg.flags<<8 | (slot->msg.length&0xFF);
+                               for (i=0;i<CAN_MSG_LENGTH;i++){
+                                       (*((uint32_t*)(ep1_tx_buff+8+i)))=slot->msg.data[i];
+                               }
+                               usb_udev_write_endpoint(&eps[1],ep1_tx_buff,USB_MAX_PACKET);
+
+                               canque_free_outslot(qends, qedge, slot);
+                               timer_tx_off=50;                //rozsviceni diod pri vysilani
+                               CLR_OUT_PIN(LED_PORT,LED1_BIT);
+                               usb_device.ep_events &= ~MASK_EP1TX;
+                       }
                }
 
+               //if (usb_can_send && )
+
 #ifdef WATCHDOG_ENABLED
                watchdog_feed();
 #endif /* WATCHDOG_ENABLED */
index 0b3e388c8176e2df0737a677b3802dc7b7624043..e100f9008b0b236c73bbe7470614355d3a10efd2 100644 (file)
@@ -295,16 +295,42 @@ int ul_usb1_program_irq(struct candevice_t *candev)
  * Return Value: The function does not return a value
  * File: src/ul_usb1.c
  */
-void ul_usb1_write_register(struct candevice_t *candev,unsigned data, unsigned long address)
+void ul_usb1_write_register(unsigned data, unsigned long address)
 {
-       struct usb_ul_usb1 *dev;
-       int retval;
-       int bytes_transferred;
-       unsigned char buffer[2];
-       buffer[0]=((unsigned char)address & ~CAN_OP_MASK)+CAN_OP_WRITE;
-       buffer[1]=(unsigned char)data;
+       IO1DIR|=0x00FF0000; // Port as output to send data
+       IO1CLR=0x00FF0000; // Clear all data on port
+       // Init
+       SET_OUT_PIN(IO0,P0_SJA1000_RD_PIN);     // Stays high on write
+       SET_OUT_PIN(IO0,P0_SJA1000_WR_PIN); // Stays high on address write
+       SET_OUT_PIN(IO0,P0_SJA1000_CS_PIN); // Sets output buffers to third state
+       for (slowdown=0;slowdown<SJA1000_SCLK;slowdown++);
+       //SET_OUT_PIN(IO0,P0_SJA1000_ALE_PIN); // Start command
+
+       // Set memory address
+       IO1SET=__val2mfld(0x00FF0000,address&0xFF); // Shift data to SJA pins and output them
+       for (slowdown=0;slowdown<SJA1000_SCLK;slowdown++);
+       //CLR_OUT_PIN(IO0,P0_SJA1000_ALE_PIN); // Makes address active
+       CLR_OUT_PIN(IO0,P0_SJA1000_CS_PIN);
+       for (slowdown=0;slowdown<SJA1000_SCLK;slowdown++);
+
+       // Setting data
+       CLR_OUT_PIN(IO0,P0_SJA1000_WR_PIN);
+
+       IO1CLR=0x00FF0000;
+       IO1SET=__val2mfld(0x00FF0000,data&0xFF);
+       for (slowdown=0;slowdown<SJA1000_SCLK;slowdown++);
+       SET_OUT_PIN(IO0,P0_SJA1000_WR_PIN); // Data should be accepted by now
+       SET_OUT_PIN(IO0,P0_SJA1000_CS_PIN);
+       for (slowdown=0;slowdown<SJA1000_SCLK;slowdown++);
 
-       dev = (struct usb_ul_usb1 *)candev->sysdevptr.anydev;
+//     struct usb_ul_usb1 *dev;
+//     int retval;
+//     int bytes_transferred;
+//     unsigned char buffer[2];
+//     buffer[0]=((unsigned char)address & ~CAN_OP_MASK)+CAN_OP_WRITE;
+//     buffer[1]=(unsigned char)data;
+//
+//     dev = (struct usb_ul_usb1 *)candev->sysdevptr.anydev;
 
 //     mutex_lock(&dev->io_mutex);
 //     if (!dev) {             /* disconnect() was called */
@@ -340,16 +366,43 @@ exit:
  * Return Value: The function returns the value stored in @address
  * File: src/ul_usb1.c
  */
-unsigned ul_usb1_read_register(struct candevice_t *candev,unsigned long address)
+unsigned ul_usb1_read_register(unsigned long address)
 {
-       struct usb_ul_usb1 *dev;
-       int retval;
-       int bytes_transferred;
-       unsigned char buffer[2];
-       buffer[0]=((unsigned char)address & ~CAN_OP_MASK)+CAN_OP_READ;
-       buffer[1]=0x00;
-
-       dev = (struct usb_ul_usb1 *)candev->sysdevptr.anydev;
+       unsigned data;
+       IO1DIR|=0x00FF0000; // Port as output to set address
+       IO1CLR=0x00FF0000; // Clear all data
+       // Init
+       SET_OUT_PIN(IO0,P0_SJA1000_WR_PIN); // Stays high on read
+       SET_OUT_PIN(IO0,P0_SJA1000_RD_PIN); // Stays high while entering address
+       SET_OUT_PIN(IO0,P0_SJA1000_CS_PIN);
+       for (slowdown=0;slowdown<SJA1000_SCLK;slowdown++);
+       //SET_OUT_PIN(IO0,P0_SJA1000_ALE_PIN);
+
+       // Request memory address
+       IO1SET=__val2mfld(0x00FF0000,address&0xFF);
+       for (slowdown=0;slowdown<SJA1000_SCLK;slowdown++);
+       //CLR_OUT_PIN(IO0,P0_SJA1000_ALE_PIN);
+       CLR_OUT_PIN(IO0,P0_SJA1000_CS_PIN);
+
+       // Get data
+
+       IO1DIR&=~0x00FF0000; // Sets port as input
+       CLR_OUT_PIN(IO0,P0_SJA1000_RD_PIN);
+       for (slowdown=0;slowdown<SJA1000_SCLK;slowdown++);
+       data=__mfld2val(0x00FF0000,IO1PIN);
+       SET_OUT_PIN(IO0,P0_SJA1000_RD_PIN);
+       SET_OUT_PIN(IO0,P0_SJA1000_CS_PIN);
+       for (slowdown=0;slowdown<SJA1000_SCLK;slowdown++);
+       return data;
+
+//     struct usb_ul_usb1 *dev;
+//     int retval;
+//     int bytes_transferred;
+//     unsigned char buffer[2];
+//     buffer[0]=((unsigned char)address & ~CAN_OP_MASK)+CAN_OP_READ;
+//     buffer[1]=0x00;
+//
+//     dev = (struct usb_ul_usb1 *)candev->sysdevptr.anydev;
 
 //     mutex_lock(&dev->io_mutex);
 //     if (!dev) {             /* disconnect() was called */