Transmitting CAN messages with usage of queue system from LinCAN - first version...
authorJiri Vanek <vanekjir@fel.cvut.cz>
Thu, 22 Dec 2011 16:02:05 +0000 (17:02 +0100)
committerJiri Vanek <vanekjir@fel.cvut.cz>
Thu, 22 Dec 2011 16:02:05 +0000 (17:02 +0100)
embedded/app/usbcan/Makefile.omk
embedded/app/usbcan/can/lpc17xx_can.h
embedded/app/usbcan/lpc17xx_can.c
embedded/app/usbcan/main.c

index 588f007..3077876 100644 (file)
@@ -29,6 +29,6 @@ usbcan_MOREOBJS = $(USER_LIB_DIR)/system_stub.o
 # $(USER_LIB_DIR)/ivt.o
 nobase_include_HEADERS = usb/usb_defs.h
 
-link_VARIANTS = app boot
+#link_VARIANTS = app boot
 
 endif #CONFIG_ULBOOT
index 1b66997..dd3fdf2 100644 (file)
@@ -5,6 +5,8 @@
 #include "hal_machperiph.h"
 #include "cpu_def.h"
 #include "system_def.h"
+
+#include "can/can.h"
 #include "can/canmsg.h"
 
 #ifdef __cplusplus
@@ -71,6 +73,28 @@ extern "C"
 
 //----------------------------------
 
+//CAN Interrupt and Capture Register bits
+#define CAN_ICR_TI1            (1<<1)
+
+//CAN Status Register bits
+#define CAN_SR_TBS1            (1<<2)          
+
+//CAN Command Register bits
+#define CAN_CMR_TR             (1<<0)
+#define CAN_CMR_AT             (1<<1)
+#define CAN_CMR_RRB            (1<<2)
+#define CAN_CMR_CDO            (1<<3)
+#define CAN_CMR_STB1   (1<<5)
+
+//CAN Transmit Frame Information register 1 bits
+#define CAN_TFI1_RTR   (1<<30)
+#define CAN_TFI1_EXT   (1<<31)
+
+//CAN Interrupt Enable Register bits
+#define CAN_IER_TIE1   (1<<1)
+
+//----------------------------------
+
 #define PCONP SC->PCONP
 #define PCLKSEL0 SC->PCLKSEL0 
 
@@ -93,6 +117,38 @@ extern "C"
 
 void CAN_init(uint32_t baudrate);
 void CAN_send(canmsg_t* msg);
+void CAN_IRQHandler(void);
+
+//----------------------------------
+
+struct can_lmc1_chip_data
+{
+       int flags;
+};
+
+// board can-lmc1 specific functions:
+int can_lmc1_register(struct hwspecops_t *hwspecops);
+int can_lmc1_init_hw_data(struct candevice_t *candev);
+int can_lmc1_init_chip_data(struct candevice_t *candev, int chipnr);
+int can_lmc1_init_obj_data(struct canchip_t *chip, int objnr);
+void can_lmc1_write_register(unsigned data, unsigned long address);
+unsigned can_lmc1_read_register(unsigned long address);
+int can_lmc1_request_io(struct candevice_t *candev);
+int can_lmc1_reset(struct candevice_t *candev);
+
+// lpc17xx can chip specific functions:
+int lpc17xx_chip_config(struct canchip_t *chip);
+int lpc17xx_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj,
+                                                       struct canmsg_t *msg);
+int lpc17xx_send_msg(struct canchip_t *chip, struct msgobj_t *obj,
+                                                       struct canmsg_t *msg);
+int lpc17xx_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj);
+int lpc17xx_irq_handler(int irq, struct canchip_t *chip);
+void lpc17xx_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj);
+int lpc17xx_fill_chipspecops(struct canchip_t *chip);
+int lpc17xx_register(struct chipspecops_t *chipspecops);
+int lpc17xx_attach_to_chip(struct canchip_t *chip);
+int lpc17xx_pre_read_config(struct canchip_t *chip, struct msgobj_t *obj);
 
 #ifdef __cplusplus
 }
index eee3718..ec82757 100644 (file)
@@ -3,7 +3,277 @@
 static void CAN_configPin();
 static void CAN_setBusTiming(uint32_t baudrate);
 
-//------------------------------------------
+extern struct canhardware_t *hardware_p;
+
+//---------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------
+
+// interrupt handler
+// now only for transmitting - irq when one message was transmitted (for check if another message is pending in can msg queue)
+
+void CAN_IRQHandler(){
+
+       uint32_t i;
+       
+       i = CAN1ICR;
+       if(!(i & CAN_ICR_TI1))
+               return;
+
+       
+       struct canchip_t *chip;
+       chip = hardware_p->candevice[0]->chip[0];
+       
+       lpc17xx_irq_handler(0, chip);
+
+}
+
+
+//---------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------
+
+
+// board can-lmc1 specific functions:
+
+int can_lmc1_register(struct hwspecops_t *hwspecops){
+
+       hwspecops->request_io = can_lmc1_request_io;
+       hwspecops->reset = can_lmc1_reset;
+       hwspecops->init_hw_data = can_lmc1_init_hw_data;
+       hwspecops->init_chip_data = can_lmc1_init_chip_data;
+       hwspecops->init_obj_data = can_lmc1_init_obj_data;
+       hwspecops->write_register = can_lmc1_write_register;
+       hwspecops->read_register = can_lmc1_read_register;
+
+       return 0;
+}
+
+int can_lmc1_init_hw_data(struct candevice_t *candev){
+
+       candev->res_addr=0;
+       candev->nr_82527_chips=0;
+       candev->nr_sja1000_chips=0;
+       candev->nr_all_chips=1;
+       candev->flags |= 0;
+
+       return 0;
+}
+
+int can_lmc1_init_chip_data(struct candevice_t *candev, int chipnr){
+       
+       lpc17xx_fill_chipspecops(candev->chip[chipnr]);
+
+       candev->chip[chipnr]->flags|= CHIP_IRQ_CUSTOM;
+
+       candev->chip[chipnr]->chip_data=(void *)malloc(sizeof(struct can_lmc1_chip_data));
+       if (candev->chip[chipnr]->chip_data==NULL)
+               return -ENOMEM;
+
+       return 0;
+}
+
+int can_lmc1_init_obj_data(struct canchip_t *chip, int objnr){
+       
+       //chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr+(objnr+1)*0x10;
+
+       return 0;
+}
+
+void can_lmc1_write_register(unsigned data, unsigned long address){
+
+       printf("UNSUPPORTED NOW\n");
+
+}
+
+unsigned can_lmc1_read_register(unsigned long address){
+
+       printf("UNSUPPORTED NOW\n");
+
+}
+
+int can_lmc1_request_io(struct candevice_t *candev)
+{
+       return 0;
+}
+
+int can_lmc1_reset(struct candevice_t *candev)
+{
+       return 0;
+}
+
+
+//---------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------
+
+
+// lpc17xx can chip specific functions:
+
+
+int lpc17xx_chip_config(struct canchip_t *chip){
+
+       CAN_init( (uint32_t) chip->baudrate);
+
+       return 0;
+}
+
+int lpc17xx_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj,
+                                                       struct canmsg_t *msg)
+{
+       
+       CAN_send(msg);
+
+       return 0;
+}
+
+int lpc17xx_send_msg(struct canchip_t *chip, struct msgobj_t *obj,
+                                                       struct canmsg_t *msg)
+{
+       
+       // write transmission request
+       CAN1CMR = (CAN_CMR_TR | CAN_CMR_STB1); 
+
+       return 0;
+}
+
+int lpc17xx_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj)
+{
+
+       can_preempt_disable();
+
+       can_msgobj_set_fl(obj,TX_PENDING);
+       can_msgobj_set_fl(obj,TX_REQUEST);
+
+       while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){
+               can_msgobj_clear_fl(obj,TX_REQUEST);
+
+
+               if (CAN1SR & CAN_SR_TBS1){
+                       obj->tx_retry_cnt=0;
+                       lpc17xx_irq_write_handler(chip, obj);
+               }
+
+               can_msgobj_clear_fl(obj,TX_LOCK);
+               if(!can_msgobj_test_fl(obj,TX_REQUEST)) break;
+
+       }
+
+       can_preempt_enable();
+
+       return 0;
+}
+
+int lpc17xx_irq_handler(int irq, struct canchip_t *chip)
+{
+
+       struct msgobj_t *obj;   
+       obj = chip->msgobj[0];
+
+
+       if ((can_msgobj_test_fl(obj,TX_PENDING)) || (can_msgobj_test_fl(obj,TX_REQUEST))) {
+                       
+               can_msgobj_set_fl(obj,TX_REQUEST);
+
+               while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){
+
+                       obj->ret=0;
+                       can_msgobj_clear_fl(obj,TX_REQUEST);
+
+                       if (CAN1SR & CAN_SR_TBS1){
+                               obj->tx_retry_cnt=0;
+                               lpc17xx_irq_write_handler(chip, obj);
+                       }
+
+                       can_msgobj_clear_fl(obj,TX_LOCK);
+                       if(!can_msgobj_test_fl(obj,TX_REQUEST)) break;
+
+               }       
+       }
+
+       return CANCHIP_IRQ_HANDLED;
+
+}
+
+void lpc17xx_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj)
+{
+       int cmd;
+
+       if(obj->tx_slot){
+               /* Do local transmitted message distribution if enabled */
+               if (processlocal){
+                       /* fill CAN message timestamp */
+                       can_filltimestamp(&obj->tx_slot->msg.timestamp);
+
+                       obj->tx_slot->msg.flags |= MSG_LOCAL;
+                       canque_filter_msg2edges(obj->qends, &obj->tx_slot->msg);
+               }
+               /* Free transmitted slot */
+               canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
+               obj->tx_slot=NULL;
+       }
+
+       can_msgobj_clear_fl(obj,TX_PENDING);
+       cmd=canque_test_outslot(obj->qends, &obj->tx_qedge, &obj->tx_slot);
+       if(cmd<0)
+               return;
+       can_msgobj_set_fl(obj,TX_PENDING);
+
+       if (chip->chipspecops->pre_write_config(chip, obj, &obj->tx_slot->msg)) {
+               obj->ret = -1;
+               canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_PREP);
+               canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
+               obj->tx_slot=NULL;
+               return;
+       }
+       if (chip->chipspecops->send_msg(chip, obj, &obj->tx_slot->msg)) {
+               obj->ret = -1;
+               canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_SEND);
+               canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
+               obj->tx_slot=NULL;
+               return;
+       }
+
+}
+
+int lpc17xx_fill_chipspecops(struct canchip_t *chip){
+
+       chip->max_objects=1;
+       chip->baudrate=1000000;
+
+       lpc17xx_register(chip->chipspecops);
+       return 0;
+}
+
+int lpc17xx_register(struct chipspecops_t *chipspecops){
+
+       CANMSG("initializing lpc17xx can chip operations\n");
+
+       chipspecops->attach_to_chip = lpc17xx_attach_to_chip;
+       chipspecops->pre_read_config = lpc17xx_pre_read_config;
+       chipspecops->chip_config = lpc17xx_chip_config;
+       chipspecops->pre_write_config = lpc17xx_pre_write_config;
+       chipspecops->send_msg = lpc17xx_send_msg;
+       chipspecops->wakeup_tx = lpc17xx_wakeup_tx;
+       chipspecops->irq_handler = lpc17xx_irq_handler;
+
+       return 0;       
+
+}
+
+
+int lpc17xx_attach_to_chip(struct canchip_t *chip){
+
+       return 0;
+}
+
+int lpc17xx_pre_read_config(struct canchip_t *chip, struct msgobj_t *obj){
+
+       return 1;
+}
+
+
+
+//---------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------
+
 
 static void CAN_configPin(){
 
@@ -51,22 +321,22 @@ void CAN_send(canmsg_t* msg){
        uint32_t i;
 
        // check status of TB1
-       while (!(CAN1SR & (1<<2))){}
+       while (!(CAN1SR & CAN_SR_TBS1)){}
        
        CAN1TFI1 &= ~0x000F0000;
        CAN1TFI1 |= (msg->length)<<16;
 
        // EXT frame
        if(msg->flags & MSG_EXT)
-               CAN1TFI1 |= (1<<31);
+               CAN1TFI1 |= CAN_TFI1_EXT;
        else
-               CAN1TFI1 &= ~(1<<31);
+               CAN1TFI1 &= ~CAN_TFI1_EXT;
                
        // RTR frame
        if(msg->flags & MSG_RTR)
-               CAN1TFI1 |= (1<<30);
+               CAN1TFI1 |= CAN_TFI1_RTR;
        else
-               CAN1TFI1 &= ~(1<<30);
+               CAN1TFI1 &= ~CAN_TFI1_RTR;
 
        // write CAN ID
        CAN1TID1 = msg->id;
@@ -87,7 +357,7 @@ void CAN_send(canmsg_t* msg){
                CAN1TDB1 = data;
 
        // write transmission request
-       CAN1CMR = 0x21;
+       //CAN1CMR = 0x21;
 
 }
 
@@ -166,6 +436,7 @@ void CAN_init(uint32_t baudrate)
        uint32_t pclksel0;
        uint32_t val;
        
+       printf("CAN INIT, baudrate: %d\n", baudrate);
 
        // configure CAN1 pins 
        CAN_configPin();
@@ -195,7 +466,7 @@ void CAN_init(uint32_t baudrate)
        CAN1GSR = 0x3C;
 
        // request command to release Rx, Tx buffer and clear data overrun 
-       CAN1CMR = (1<<1)|(1<<2)|(1<<3);
+       CAN1CMR = (CAN_CMR_AT | CAN_CMR_RRB | CAN_CMR_CDO);
 
        // read to clear interrupt pending in Interrupt Capture Register 
        tmp = CAN1ICR;
@@ -206,6 +477,11 @@ void CAN_init(uint32_t baudrate)
        // return to normal operating 
        CAN1MOD = 0;
 
+       // enable interrupt after transmit
+       CAN1IER |= CAN_IER_TIE1;
+       // enable CAN interrupt 
+       NVIC_EnableIRQ(CAN_IRQn);
+
        
 }
 
index 4b91631..6053645 100644 (file)
@@ -106,7 +106,6 @@ LT_TIMER_IMP(lt_2sec)
 
 typedef void (*FNC)(); //function ptr
 
-
 /***********************************************************************
  * global variables
  ***********************************************************************/
@@ -230,13 +229,8 @@ int main(void)
                sys_err();
        }
 
-// !!! DEBUG - first version, only transmitting CAN messages withnout usage of queue system from LinCAN
-
-       // CAN
-       CAN_init(1000000);
-       // CAN end
+// !!! DEBUG - first version, only transmitting CAN messages with usage of queue system from LinCAN
 
-/*
 
        //***********************************************************************
        // * CAN device initialization - device side (adapted from LinCAN setup.c)
@@ -244,8 +238,6 @@ int main(void)
 
        // DEBUG
        //can_init(); // only for successful compiling (defined in can_lpcbusemu.c)
-       
-
 
 
        DEBUGMSG("Initiating CAN device initialization\n");
@@ -274,8 +266,13 @@ int main(void)
        }
        memset(candev->hwspecops, 0, sizeof(struct hwspecops_t));
 
+       
+
        // DEBUG
        //ul_usb1_register(candev->hwspecops);  // only for successful compiling (defined in ul_usb1.c)
+       // register for another board
+       can_lmc1_register(candev->hwspecops);
+
        
 
        bd=baudrate[0];
@@ -283,6 +280,7 @@ int main(void)
                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)
@@ -292,6 +290,9 @@ int main(void)
                        sys_err();
                }
        }
+
+
+
        for (chipnr=0; chipnr < candev->nr_all_chips; chipnr++) {
                struct canchip_t *chip=candev->chip[chipnr];
                int objnr;
@@ -303,11 +304,17 @@ int main(void)
                        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; chipnr<candev->nr_all_chips; chipnr++) {
                if((chip=candev->chip[chipnr])==NULL)
                        continue;
@@ -336,6 +343,7 @@ int main(void)
        // * CAN device initialization - client side (adapted from LinCAN open.c)
        // ***********************************************************************
 
+
        chip=candev->chip[0];
        obj=chip->msgobj[0];
        atomic_inc(&obj->obj_used);
@@ -354,6 +362,7 @@ int main(void)
 
        } // End of chip configuration
 
+
        canuser = (struct canuser_t *)malloc(sizeof(struct canuser_t));
        if(canuser == NULL) sys_err();
        canuser->flags=0;
@@ -381,7 +390,7 @@ int main(void)
        canque_edge_decref(canuser->rx_edge0);
        canque_edge_decref(edge);
 
-*/
+
 
        /***********************************************************************
         * USB Init
@@ -430,8 +439,7 @@ int main(void)
 
                if (usb_device.ep_events & MASK_EP1RX) {  //EP1RX - data waiting to receive
                        
-                       // DEBUG - unused queue system (yet)
-                       //if (canque_get_inslot(qends, &qedge, &slot, 0)>=0){ //Free slot obtained
+                       if (canque_get_inslot(qends, &qedge, &slot, 0)>=0){ //Free slot obtained
 
                                size=usb_udev_read_endpoint(&eps[0],ep1_rx_buff,16);
                                if (size==16){
@@ -459,24 +467,22 @@ 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 */
-
-                                       // DEBUG - unused queue system (yet)                            
-                                       //slot->msg=canmsg;
-                                       //canque_put_inslot(qends, qedge, slot);
-                                       CAN_send(&canmsg);
+                       
+                                       slot->msg=canmsg;
+                                       canque_put_inslot(qends, qedge, slot);
+                                       //CAN_send(&canmsg);
                                }
-
-                               // DEBUG - unused queue system (yet)
-                               //else
-                               //      canque_abort_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;
                        
-                       // DEBUG                        
-                       //}
-
+                                       
+                       }
+                       
 
 /*                     if (size==2){
                                uint8_t val;