+/**************************************************************************/
+/* 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 <http://dce.felk.cvut.cz> */
+/* 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 <stdio.h>
#include <string.h>
#include <cpu_def.h>
#include <lpciap.h>
#include <lpciap_kvpb.h>
+#include <endian.h>
+#if __BYTE_ORDER == __BIG_ENDIAN
+ #include <byteswap.h>
+#endif
+
#include "./can/can.h"
#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 "./usb/usb_defs.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 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
/***********************************************************************
* 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)
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];
struct canchip_t *chips_p[MAX_TOT_CHIPS];
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(){
}
}
+/***********************************************************************
+ * 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)
***********************************************************************/
struct candevice_t *candev;
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;
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;
SET_OUT_PIN(LED_PORT,LED_ERR);
CLR_OUT_PIN(LED_PORT,LED_GP);
+ 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)
***********************************************************************/
+ can_init();
+ DEBUGMSG("Initiating CAN device initialization\n");
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));
+ 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;
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);
bd=baudrate[0];
- if (candev->hwspecops->init_hw_data(candev)) sys_err();
+ 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(chipnr<irqnum)
irqsig=irq[*irq_param_idx_p+chipnr];*/
- if (init_chip_struct(candev, chipnr, 0, bd*1000)) sys_err();
+ if (init_chip_struct(candev, chipnr, 0, bd*1000)){
+ CANMSG("Chip structure could not be initialized\n");
+ sys_err();
+ }
+ }
+ for (chipnr=0; chipnr < candev->nr_all_chips; chipnr++) {
+ struct canchip_t *chip=candev->chip[chipnr];
+ int objnr;
+
+ register_chip_struct(chip, m);
+
+ for (objnr=0; objnr<chip->max_objects; objnr++) {
+ register_obj_struct(chip->msgobj[objnr], m);
+ if(m>=0) m++;
+ }
}
if (candev->hwspecops->request_io(candev))
sys_err();
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;
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;
while (1) {
usb_check_events(&usb_device);
usb_control_response(&usb_device);
- if (!(IO0PIN&P0_SJA1000_INT_PIN))
+ 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;
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));
+ 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;i<canmsg.length;i++){
+ canmsg.data[i]=*(unsigned char*)(ep1_rx_buff+8+i);
+ }
+ for (;i<CAN_MSG_LENGTH;i++){
+ canmsg.data[i]=0;
}
/* Automatic selection of extended format if ID>2047 */
if (canmsg.id & ~0x7ffl & MSG_ID_MASK ) canmsg.flags |= MSG_EXT;
/* 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){
- (*((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];
+ DEBUGMSG("CAN message ready to send over usb\n");
+ 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;i<slot->msg.length;i++){
+ *(uint8_t *)(ep1_tx_buff+8+i)=slot->msg.data[i];
+ }
+ for (;i<CAN_MSG_LENGTH;i++){
+ *(uint8_t *)(ep1_tx_buff+8+i)=0;
}
- usb_udev_write_endpoint(&eps[1],ep1_tx_buff,USB_MAX_PACKET);
+ usb_udev_write_endpoint(&eps[1],ep1_tx_buff,16);
canque_free_outslot(qends, qedge, slot);
timer_tx_off=50; //rozsviceni diod pri vysilani