X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/f9522530e37184c3dcfb818a35f55ec3f177406f..a9296605ae899d82c9e8f682eafe63d999c4a57b:/embedded/app/usbcan/main.c diff --git a/embedded/app/usbcan/main.c b/embedded/app/usbcan/main.c index b9271e3..71fb5e7 100644 --- a/embedded/app/usbcan/main.c +++ b/embedded/app/usbcan/main.c @@ -1,3 +1,35 @@ +/**************************************************************************/ +/* File: main.c - setup and main loop of USB<->CAN converter */ +/* */ +/* LinCAN - (Not only) Linux CAN bus driver */ +/* Copyright (C) 2002-2011 DCE FEE CTU Prague */ +/* Copyright (C) 2008 Jan Kriz email:johen@post.cz */ +/* */ +/* LinCAN is free software; you can redistribute it and/or modify it */ +/* under terms of the GNU General Public License as published by the */ +/* Free Software Foundation; either version 2, or (at your option) any */ +/* later version. LinCAN is distributed in the hope that it will be */ +/* useful, but WITHOUT ANY WARRANTY; without even the implied warranty */ +/* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. You should have received a */ +/* copy of the GNU General Public License along with LinCAN; see file */ +/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/* */ +/* To allow use of LinCAN in the compact embedded systems firmware */ +/* and RT-executives (RTEMS for example), main authors agree with next */ +/* special exception: */ +/* */ +/* Including LinCAN header files in a file, instantiating LinCAN generics */ +/* or templates, or linking other files with LinCAN objects to produce */ +/* an application image/executable, does not by itself cause the */ +/* resulting application image/executable to be covered by */ +/* the GNU General Public License. */ +/* This exception does not however invalidate any other reasons */ +/* why the executable file might be covered by the GNU Public License. */ +/* Publication of enhanced or derived LinCAN files is required although. */ +/**************************************************************************/ + #include #include #include @@ -24,27 +56,31 @@ #include "./can/sja1000p.h" #include "./can/main.h" -#include "./can/can_sysdep.h" +// #include "./can/can_sysdep.h" #include "./can/modparms.h" #include "./can/devcommon.h" -#include "./can/ul_usb1.h" -//#include "./can/setup.h" +//#include "./can/ul_usb1.h" + +#include "./can/setup.h" +#include "./usb/usb_defs.h" #include "./usb/usb_vend.h" + +#include "can/lpc17xx_can.h" + #define MASK_EP1RX 0x01 #define MASK_EP1TX 0x02 -#ifdef USB_MAX_PACKET - #undef USB_MAX_PACKET - #define USB_MAX_PACKET 16 -#endif - #define CAN_OP_MASK 0x80 #define CAN_OP_READ 0x80 #define CAN_OP_WRITE 0x00 +#ifdef USB_MAX_PACKET + #undef USB_MAX_PACKET + #define USB_MAX_PACKET 16 +#endif /*********************************************************************** * Note: * Comparing to LinCAN, there is no need to sleep for processes @@ -57,7 +93,7 @@ /*********************************************************************** * 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 + * configuration and to make it as much similar as the code of LinCAN ***********************************************************************/ LT_TIMER_DEC(lt_10msec) @@ -70,18 +106,19 @@ LT_TIMER_IMP(lt_2sec) typedef void (*FNC)(); //function ptr /*********************************************************************** - * global variables - ***********************************************************************/ - + * global variables + ***********************************************************************/ usb_device_t usb_device; -usb_ep_t eps[2]; +usb_ep_t eps[NUM_ENDPOINTS]; 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; volatile uint8_t bootloader_run; +uint8_t vendor_ret; + int processlocal; int baudrate[MAX_TOT_CHIPS]; @@ -92,12 +129,16 @@ struct msgobj_t *objects_p[MAX_TOT_MSGOBJS]; struct canuser_t *canuser; +extern int init_chip_struct(struct candevice_t *candev, int chipnr, int irq, long baudrate); +extern int register_chip_struct(struct canchip_t *chip, int minorbase); +extern int register_obj_struct(struct msgobj_t *obj, int minorbase); /*********************************************************************** - * SOMETHING BAD HAPPENED + * IF SOMETHING BAD HAPPENED ***********************************************************************/ int sys_err(){ + unsigned char i=0; while(1) { @@ -115,6 +156,19 @@ int sys_err(){ } } +/*********************************************************************** + * Microsecond delay routine + ***********************************************************************/ +/* +void udelay(long time) +{ + volatile long ticks=(time * CCLK) / 2000000; + do{ + ticks--; + } while(ticks>0); +} +*/ + /*********************************************************************** * Routine for visible LED blinking (on USB transmission) ***********************************************************************/ @@ -125,6 +179,7 @@ void timer_10ms(void) 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; @@ -150,23 +205,37 @@ int main(void) can_spin_irqflags_t iflags; int chipnr,bd; - int i,size; + int i,size,m=0; + + CANMSG("Starting USBCAN module firmware...\n"); // volatile int i=0; bootloader_run=0; /***********************************/ + lt_10msec_init(); lt_100msec_init(); lt_2sec_init(); - SET_OUT_PIN(LED_PORT,LED_ERR); - CLR_OUT_PIN(LED_PORT,LED_GP); + // DEBUG + //SET_OUT_PIN(LED_PORT,LED_ERR); + //CLR_OUT_PIN(LED_PORT,LED_GP); - /*********************************************************************** - * CAN device initialization - device side (adapted from LinCAN setup.c) - ***********************************************************************/ + if (USB_MAX_PACKET<16){ + CANMSG("Maximum packet size less than 16B (is %dB)\n",USB_MAX_PACKET); + sys_err(); + } + + + //*********************************************************************** + // * CAN device initialization - device side (adapted from LinCAN setup.c) + // *********************************************************************** +// useless with lpc17xx (defined in can_lpcbusemu.c) +// can_init(); + + DEBUGMSG("Initiating CAN device initialization\n"); baudrate[0]=1000; canqueue_kern_initialize(); @@ -174,8 +243,11 @@ int main(void) hardware_p->nr_boards=1; candev=(struct candevice_t *)malloc(sizeof(struct candevice_t)); - if (candev==NULL) sys_err(); - memset(candev, 0, sizeof(struct candevice_t)); + if (!candev){ + CANMSG("No space left in memory\n"); + sys_err(); + } + memset(candev, 0, sizeof(struct candevice_t)); hardware_p->candevice[0]=candev; candev->candev_idx=0; @@ -183,24 +255,61 @@ int main(void) candev->dev_base_addr=0; candev->hwspecops=(struct hwspecops_t *)malloc(sizeof(struct hwspecops_t)); - if (candev->hwspecops==NULL) sys_err(); - memset(candev->hwspecops, 0, sizeof(struct hwspecops_t)); + if (!candev->hwspecops){ + CANMSG("No space left in memory\n"); + sys_err(); + } + memset(candev->hwspecops, 0, sizeof(struct hwspecops_t)); + + - ul_usb1_register(candev->hwspecops); + // DEBUG + //ul_usb1_register(candev->hwspecops); //(defined in ul_usb1.c) + // register for another board: + can_lmc1_register(candev->hwspecops); + + bd=baudrate[0]; - if (candev->hwspecops->init_hw_data(candev)) sys_err(); - /* Alocate and initialize the chip structures */ + if (candev->hwspecops->init_hw_data(candev)){ + CANMSG("HW data could not be initialized\n"); + sys_err(); + } + + // Alocate and initialize the chip structures + for (chipnr=0; chipnr < candev->nr_all_chips; chipnr++) { +// if(chipnrnr_all_chips; chipnr++) { -/* if(chipnrchip[chipnr]; + int objnr; + + register_chip_struct(chip, m); + + for (objnr=0; objnrmax_objects; objnr++) { + register_obj_struct(chip->msgobj[objnr], m); + if(m>=0) m++; + } } + + if (candev->hwspecops->request_io(candev)) sys_err(); candev->flags|=CANDEV_IO_RESERVED; + + if (candev->hwspecops->reset(candev)) sys_err(); + + for(chipnr=0; chipnrnr_all_chips; chipnr++) { if((chip=candev->chip[chipnr])==NULL) continue; @@ -212,11 +321,12 @@ int main(void) chip->flags |= CHIP_ATTACHED; -// Interrupts from chip are served in main cycle -/* if(can_chip_setup_irq(chip)<0) { -// CANMSG("Error to setup chip IRQ\n"); + // used with lpc17xx: + if(can_chip_setup_irq(chip)<0) { + CANMSG("Error to setup chip IRQ\n"); sys_err(); - }*/ + } + } if (candev->flags & CANDEV_PROGRAMMABLE_IRQ) @@ -225,9 +335,10 @@ int main(void) sys_err(); } - /*********************************************************************** - * CAN device initialization - client side (adapted from LinCAN open.c) - ***********************************************************************/ + //*********************************************************************** + // * CAN device initialization - client side (adapted from LinCAN open.c) + // *********************************************************************** + chip=candev->chip[0]; obj=chip->msgobj[0]; @@ -245,7 +356,8 @@ int main(void) if (chip->chipspecops->pre_read_config(chip,obj)<0) CANMSG("Error initializing chip for receiving\n"); - } /* End of chip configuration */ + } // End of chip configuration + canuser = (struct canuser_t *)malloc(sizeof(struct canuser_t)); if(canuser == NULL) sys_err(); @@ -260,7 +372,7 @@ int main(void) canqueue_ends_init_kern(qends); canuser->qends = qends; - /*required to synchronize with RT-Linux context*/ + //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); @@ -270,20 +382,22 @@ int main(void) 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*/ + //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; + usb_device.devdes_table = &usb_devdes_table; usb_device.init = usb_lpc_init; usb_debug_set_level(DEBUG_LEVEL_NONE); - usb_device.cntep = 3; + usb_device.cntep = NUM_ENDPOINTS; usb_device.ep = eps; eps[0].max_packet_size = USB_MAX_PACKET; @@ -295,30 +409,35 @@ int main(void) eps[0].udev = &usb_device; eps[1].udev = &usb_device; -// usb_device.vendor_fnc=usb_loader; + usb_device.vendor_fnc=usbcan_vendor; usb_init(&usb_device); usb_connect(&usb_device); - - can_init(); + usb_device.ep_events |= MASK_EP1TX; /*********************************************************************** * Start ***********************************************************************/ - timer_rx_off=timer_tx_off=timer_str=timer_configured=0; + timer_rx_off=timer_tx_off=timer_str=timer_configured=0; + + + printf("Main loop\n"); + while (1) { usb_check_events(&usb_device); usb_control_response(&usb_device); - if (!(IO0PIN&P0_SJA1000_INT_PIN)) - chip->chipspecops->irq_handler(0,chip); +// useless with lpc17xx: +// if (!(IO0PIN&P0_SJA1000_INT_PIN)) //INT PIN is inverted +// chip->chipspecops->irq_handler(0,chip); if (usb_device.ep_events & MASK_EP1RX) { //EP1RX - data waiting to receive - uint8_t val; + 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); + + size=usb_udev_read_endpoint(&eps[0],ep1_rx_buff,16); if (size==16){ uint16_t msgflags; uint32_t msgid; @@ -344,36 +463,45 @@ int main(void) /* 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); + uint8_t val; + if ((data[0]&CAN_OP_MASK)==CAN_OP_READ){ // Get data from CAN device and return to caller + val = can_read(data[0] & ~CAN_OP_MASK); *(data+1)=val; usb_udev_write_endpoint(&eps[1],(unsigned char *)data,size); timer_rx_off=50; //rosviceni diody pri prijmu CLR_OUT_PIN(LED_PORT,LED2_BIT); usb_can_send=0; } - if (((*data)&CAN_OP_MASK)==CAN_OP_WRITE){ // Save data to CAN device - can_write((*data)&(~CAN_OP_MASK),data+1); + if ((data[0]&CAN_OP_MASK)==CAN_OP_WRITE){ // Save data to CAN device + can_write(data[1], data[0] & ~CAN_OP_MASK); timer_tx_off=50; //rozsviceni diod pri vysilani CLR_OUT_PIN(LED_PORT,LED1_BIT); } }*/ } + if(usb_device.ep_events & MASK_EP1TX){ //EP1TX - data transmitted if(canque_test_outslot(qends, &qedge, &slot)>=0){ + DEBUGMSG("CAN message ready to send over usb\n"); uint16_t msgflags; uint32_t msgid; @@ -395,14 +523,17 @@ int main(void) for (;i