X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/a0ec4dd6a947bc0bb5775ba1455ade73fa405d35..f9522530e37184c3dcfb818a35f55ec3f177406f:/embedded/app/usbcan/main.c diff --git a/embedded/app/usbcan/main.c b/embedded/app/usbcan/main.c index d28cc13..b9271e3 100644 --- a/embedded/app/usbcan/main.c +++ b/embedded/app/usbcan/main.c @@ -15,21 +15,50 @@ #include #include -#include "can/can.h" -#include "can/sja1000p.h" +#include +#if __BYTE_ORDER == __BIG_ENDIAN + #include +#endif + +#include "./can/can.h" +#include "./can/sja1000p.h" +#include "./can/main.h" + +#include "./can/can_sysdep.h" +#include "./can/modparms.h" +#include "./can/devcommon.h" + +#include "./can/ul_usb1.h" +//#include "./can/setup.h" + +#include "./usb/usb_vend.h" #define MASK_EP1RX 0x01 #define MASK_EP1TX 0x02 #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) @@ -40,22 +69,34 @@ 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; -/** - SOMETHING BAD HAPPENED -*/ +int baudrate[MAX_TOT_CHIPS]; +struct canhardware_t canhardware; +struct canhardware_t *hardware_p=&canhardware; +struct canchip_t *chips_p[MAX_TOT_CHIPS]; +struct msgobj_t *objects_p[MAX_TOT_MSGOBJS]; + +struct canuser_t *canuser; + + +/*********************************************************************** + * SOMETHING BAD HAPPENED + ***********************************************************************/ + int sys_err(){ unsigned char i=0; @@ -74,16 +115,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; @@ -93,9 +134,24 @@ void timer_10ms(void) }*/ } -/***********************************/ +/*********************************************************************** + * Main routine + ***********************************************************************/ + int main(void) { + struct candevice_t *candev; + struct canchip_t *chip=NULL; + struct msgobj_t *obj; + 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; /***********************************/ @@ -106,12 +162,127 @@ int main(void) SET_OUT_PIN(LED_PORT,LED_ERR); CLR_OUT_PIN(LED_PORT,LED_GP); - //******************** - // USB init - memset( &usb_device, 0, sizeof( usb_device)); - usb_device.id = 1; - usb_device.init = usb_lpc_init; - usb_debug_set_level(DEBUG_LEVEL_NONE); + /*********************************************************************** + * CAN device initialization - device side (adapted from LinCAN setup.c) + ***********************************************************************/ + + + baudrate[0]=1000; + + canqueue_kern_initialize(); + + 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)); + + hardware_p->candevice[0]=candev; + candev->candev_idx=0; + candev->io_addr=0; + 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)); + + ul_usb1_register(candev->hwspecops); + + bd=baudrate[0]; + if (candev->hwspecops->init_hw_data(candev)) sys_err(); + /* Alocate and initialize the chip structures */ + for (chipnr=0; chipnr < candev->nr_all_chips; chipnr++) { +/* if(chipnrhwspecops->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; + + if(chip->chipspecops->attach_to_chip(chip)<0) { +// CANMSG("Initial attach to the chip HW failed\n"); + sys_err(); + } + + 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"); + sys_err(); + }*/ + } + + if (candev->flags & CANDEV_PROGRAMMABLE_IRQ) + if (candev->hwspecops->program_irq(candev)){ +// CANMSG("Error to program board interrupt\n"); + 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); + + if(canqueue_connect_edge(edge=canque_new_edge_kern(MAX_BUF_LENGTH), + canuser->qends, obj->qends)<0) sys_err(); + + 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; + usb_device.init = usb_lpc_init; + usb_debug_set_level(DEBUG_LEVEL_NONE); usb_device.cntep = 3; usb_device.ep = eps; @@ -126,27 +297,65 @@ int main(void) // usb_device.vendor_fnc=usb_loader; - usb_init(&usb_device); - usb_connect(&usb_device); + usb_init(&usb_device); + 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){ + uint16_t msgflags; + uint32_t msgid; + canmsg.cob=0; + canmsg.length=*(uint8_t *)(ep1_rx_buff+1); + if (canmsg.length > CAN_MSG_LENGTH) + canmsg.length=CAN_MSG_LENGTH; + msgflags=*(uint16_t *)(ep1_rx_buff+2); + msgid=*(uint32_t *)(ep1_rx_buff+4); + #if __BYTE_ORDER == __BIG_ENDIAN + msgflags = bswap_16( msgflags); + msgid = bswap_32( msgid); + #endif + canmsg.flags=msgflags; + canmsg.id=msgid; + + for (i=0;i2047 */ + 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; @@ -160,15 +369,43 @@ 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){ + uint16_t msgflags; + uint32_t msgid; + + *(uint8_t *)(ep1_tx_buff)=0; + *(uint8_t *)(ep1_tx_buff+1)=slot->msg.length; + + msgflags=slot->msg.flags; + msgid=slot->msg.id; + #if __BYTE_ORDER == __BIG_ENDIAN + msgflags = bswap_16( msgflags); + msgid = bswap_32( msgid); + #endif + + *(uint16_t *)(ep1_tx_buff+2)=msgflags; + *(uint32_t *)(ep1_tx_buff+4)=msgid; + for (i=0;imsg.length;i++){ + *(uint8_t *)(ep1_tx_buff+8+i)=slot->msg.data[i]; + } + for (;i