]> rtime.felk.cvut.cz Git - lincan.git/blobdiff - embedded/app/usbcan/lpc17xx_can.c
Used sysless functions for IRQ handling. Used access functions to the chip register...
[lincan.git] / embedded / app / usbcan / lpc17xx_can.c
index ec827575c503c3cd22c112d66822fe1424ddd71b..8b3a773839fdc7319df5cd02af899997050107ca 100644 (file)
@@ -1,32 +1,7 @@
 #include "can/lpc17xx_can.h"
 
 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);
-
-}
-
+static void CAN_setBusTiming(struct canchip_t *chip);
 
 //---------------------------------------------------------------------------------
 //---------------------------------------------------------------------------------
@@ -43,6 +18,7 @@ int can_lmc1_register(struct hwspecops_t *hwspecops){
        hwspecops->init_obj_data = can_lmc1_init_obj_data;
        hwspecops->write_register = can_lmc1_write_register;
        hwspecops->read_register = can_lmc1_read_register;
+       hwspecops->program_irq = can_lmc1_program_irq;
 
        return 0;
 }
@@ -53,16 +29,17 @@ int can_lmc1_init_hw_data(struct candevice_t *candev){
        candev->nr_82527_chips=0;
        candev->nr_sja1000_chips=0;
        candev->nr_all_chips=1;
-       candev->flags |= 0;
+       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;
+       // used CAN1 peripherial -> CAN1 registers base 
+       candev->chip[chipnr]->chip_base_addr = CAN1_REGS_BASE;
+
+       lpc17xx_fill_chipspecops(candev->chip[chipnr]);
 
        candev->chip[chipnr]->chip_data=(void *)malloc(sizeof(struct can_lmc1_chip_data));
        if (candev->chip[chipnr]->chip_data==NULL)
@@ -73,21 +50,15 @@ int can_lmc1_init_chip_data(struct candevice_t *candev, int chipnr){
 
 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");
-
+       (*(volatile uint32_t*)(address)) = data;
 }
 
 unsigned can_lmc1_read_register(unsigned long address){
-
-       printf("UNSUPPORTED NOW\n");
-
+       return (*(volatile uint32_t*)(address));
 }
 
 int can_lmc1_request_io(struct candevice_t *candev)
@@ -100,6 +71,10 @@ int can_lmc1_reset(struct candevice_t *candev)
        return 0;
 }
 
+int can_lmc1_program_irq(struct candevice_t *candev)
+{
+       return 0;
+}
 
 //---------------------------------------------------------------------------------
 //---------------------------------------------------------------------------------
@@ -110,7 +85,7 @@ int can_lmc1_reset(struct candevice_t *candev)
 
 int lpc17xx_chip_config(struct canchip_t *chip){
 
-       CAN_init( (uint32_t) chip->baudrate);
+       CAN_init(chip);
 
        return 0;
 }
@@ -119,7 +94,7 @@ int lpc17xx_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj,
                                                        struct canmsg_t *msg)
 {
        
-       CAN_send(msg);
+       CAN_send(chip, msg);
 
        return 0;
 }
@@ -129,7 +104,7 @@ int lpc17xx_send_msg(struct canchip_t *chip, struct msgobj_t *obj,
 {
        
        // write transmission request
-       CAN1CMR = (CAN_CMR_TR | CAN_CMR_STB1); 
+       can_write_reg(chip, (CAN_CMR_TR | CAN_CMR_STB1), CAN_CMR_o); 
 
        return 0;
 }
@@ -145,8 +120,7 @@ int lpc17xx_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj)
        while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){
                can_msgobj_clear_fl(obj,TX_REQUEST);
 
-
-               if (CAN1SR & CAN_SR_TBS1){
+               if (can_read_reg(chip, CAN_SR_o) & CAN_SR_TBS1){
                        obj->tx_retry_cnt=0;
                        lpc17xx_irq_write_handler(chip, obj);
                }
@@ -164,29 +138,45 @@ int lpc17xx_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj)
 int lpc17xx_irq_handler(int irq, struct canchip_t *chip)
 {
 
+       uint32_t i;
        struct msgobj_t *obj;   
        obj = chip->msgobj[0];
 
+       
+       i = can_read_reg(chip, CAN_ICR_o);
+
+       if(i & (CAN_ICR_TI1 | CAN_ICR_RI)){
 
-       if ((can_msgobj_test_fl(obj,TX_PENDING)) || (can_msgobj_test_fl(obj,TX_REQUEST))) {
+               if(can_read_reg(chip, CAN_SR_o) & CAN_SR_RBS) {
+                               lpc17xx_read(chip,obj);
+                               obj->ret = 0;
+               }
+       
+       
+               if ((can_msgobj_test_fl(obj,TX_PENDING)) || (can_msgobj_test_fl(obj,TX_REQUEST))) {
                        
-               can_msgobj_set_fl(obj,TX_REQUEST);
+                       can_msgobj_set_fl(obj,TX_REQUEST);
 
-               while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){
+                       while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){
 
-                       obj->ret=0;
-                       can_msgobj_clear_fl(obj,TX_REQUEST);
+                               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);
-                       }
+                               if (can_read_reg(chip, CAN_SR_o) & 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_msgobj_clear_fl(obj,TX_LOCK);
+                               if(!can_msgobj_test_fl(obj,TX_REQUEST)) break;
+
+                       }       
+               }
 
-               }       
        }
+       if(i & CAN_ICR_DOI)
+               can_write_reg(chip, CAN_CMR_CDO, CAN_CMR_o);    // clear data overrun
+
 
        return CANCHIP_IRQ_HANDLED;
 
@@ -233,12 +223,28 @@ void lpc17xx_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj)
 
 }
 
+void lpc17xx_read(struct canchip_t *chip, struct msgobj_t *obj) {
+
+
+               CAN_recv(chip, &obj->rx_msg);
+               
+               // fill CAN message timestamp
+               can_filltimestamp(&obj->rx_msg.timestamp);
+
+               canque_filter_msg2edges(obj->qends, &obj->rx_msg);
+
+               // release Receive buffer
+               can_write_reg(chip, CAN_CMR_RRB, CAN_CMR_o);
+
+}
+
 int lpc17xx_fill_chipspecops(struct canchip_t *chip){
 
        chip->max_objects=1;
-       chip->baudrate=1000000;
-
+       chip->chip_irq = CAN_IRQn;
+       
        lpc17xx_register(chip->chipspecops);
+
        return 0;
 }
 
@@ -287,21 +293,21 @@ static void CAN_configPin(){
        uint8_t pinmode_od0_val = 0;
 
 
-       pinsel0 = PINSEL0;
+       pinsel0 = PINCON->PINSEL0;
        pinsel0 &= ~CAN1_RX_MASK;
        pinsel0 &= ~CAN1_TX_MASK;
        pinsel0 |= __val2mfld(CAN1_RX_MASK, pinsel0_val);
        pinsel0 |= __val2mfld(CAN1_TX_MASK, pinsel0_val);
-       PINSEL0 = pinsel0;
+       PINCON->PINSEL0 = pinsel0;
 
-       pinmode0 = PINMODE0;
+       pinmode0 = PINCON->PINMODE0;
        pinmode0 &= ~CAN1_RX_MASK;
        pinmode0 &= ~CAN1_TX_MASK;
        pinmode0 |= __val2mfld(CAN1_RX_MASK, pinmode0_val);
        pinmode0 |= __val2mfld(CAN1_TX_MASK, pinmode0_val);
-       PINMODE0 = pinmode0;
+       PINCON->PINMODE0 = pinmode0;
 
-       pinmode_od0 = PINMODE_OD0;
+       pinmode_od0 = PINCON->PINMODE_OD0;
        if (pinmode_od0_val){
                pinmode_od0 |= CAN1_RX_BIT;
                pinmode_od0 |= CAN1_TX_BIT;
@@ -310,58 +316,97 @@ static void CAN_configPin(){
                pinmode_od0 &= ~CAN1_RX_BIT;
                pinmode_od0 &= ~CAN1_TX_BIT;
        }
-       PINMODE_OD0 = pinmode_od0;
+       PINCON->PINMODE_OD0 = pinmode_od0;
        
 
 }
 
-void CAN_send(canmsg_t* msg){
+void CAN_recv(struct canchip_t *chip, canmsg_t* msg){
 
-       uint32_t data;
+       volatile uint32_t data;
        uint32_t i;
 
-       // check status of TB1
-       while (!(CAN1SR & CAN_SR_TBS1)){}
+       // read data lenght
+       msg->length = (can_read_reg(chip, CAN_RFS_o)>>16) & 0xF;
+
+       // read identifier
+       msg->id = can_read_reg(chip, CAN_RID_o);
+
+       // EXT frame
+       if(can_read_reg(chip, CAN_RFS_o) & CAN_RFS_EXT)
+               msg->flags |= MSG_EXT;
+       else
+               msg->flags &= ~MSG_EXT;
+
        
-       CAN1TFI1 &= ~0x000F0000;
-       CAN1TFI1 |= (msg->length)<<16;
+       // RTR frame
+       if(can_read_reg(chip, CAN_RFS_o) & CAN_RFS_RTR)
+               msg->flags |= MSG_RTR;
+       else
+               msg->flags &= ~MSG_RTR;
+
+
+       // read data            
+       data = can_read_reg(chip, CAN_RDA_o);           
+       for(i=0; i<4; i++)
+               msg->data[i] = (data>>(i*8)) & 0xFF;
+
+       data = can_read_reg(chip, CAN_RDB_o);   
+       for(i=4; i<8; i++)
+               msg->data[i] = (data>>((i-4)*8)) & 0xFF;
+
+}
+
+void CAN_send(struct canchip_t *chip, canmsg_t* msg){
+
+       volatile uint32_t data;
+       volatile uint32_t can_tfi1;
+       uint32_t i;
+
+       // check status of TB1
+       while (!(can_read_reg(chip, CAN_SR_o) & CAN_SR_TBS1)){} 
+
+       can_tfi1 = can_read_reg(chip, CAN_TFI1_o);
+
+       can_tfi1 &= ~0x000F0000;
+       can_tfi1 |= (msg->length)<<16;
 
        // EXT frame
        if(msg->flags & MSG_EXT)
-               CAN1TFI1 |= CAN_TFI1_EXT;
+               can_tfi1 |= CAN_TFI1_EXT;
        else
-               CAN1TFI1 &= ~CAN_TFI1_EXT;
+               can_tfi1 &= ~CAN_TFI1_EXT;
                
        // RTR frame
        if(msg->flags & MSG_RTR)
-               CAN1TFI1 |= CAN_TFI1_RTR;
+               can_tfi1 |= CAN_TFI1_RTR;
        else
-               CAN1TFI1 &= ~CAN_TFI1_RTR;
+               can_tfi1 &= ~CAN_TFI1_RTR;
+
+       can_write_reg(chip, can_tfi1, CAN_TFI1_o);
+
 
        // write CAN ID
-       CAN1TID1 = msg->id;
+       can_write_reg(chip, msg->id, CAN_TID1_o);
 
-       // write first 4 data bytes
 
+       // write first 4 data bytes
        data=0;
        for(i=0; i<4; i++)
                data |= (msg->data[i])<<(i*8);
 
-       CAN1TDA1 = data;
+       can_write_reg(chip, data, CAN_TDA1_o);
 
        // write second 4 data bytes
-
        data=0;
        for(i=4; i<8; i++)
                data |= (msg->data[i])<<((i-4)*8);
-               CAN1TDB1 = data;
-
-       // write transmission request
-       //CAN1CMR = 0x21;
+       
+       can_write_reg(chip, data, CAN_TDB1_o);
 
 }
 
-void CAN_setBusTiming(uint32_t baudrate){
+void CAN_setBusTiming(struct canchip_t *chip){
 
        uint32_t PCLK_CAN;
        uint32_t res;
@@ -373,6 +418,8 @@ void CAN_setBusTiming(uint32_t baudrate){
        uint8_t SAM;
        uint8_t div;
 
+       TSEG1 = TSEG2 = BRP = 0;
+
        // 0 = the bus is sampled once
        SAM = 0;
 
@@ -380,7 +427,7 @@ void CAN_setBusTiming(uint32_t baudrate){
        SJW = 3;
 
        // get clock divide for CAN1    
-       div = __mfld2val(PCLK_CAN1_MASK, PCLKSEL0);
+       div = __mfld2val(PCLK_CAN1_MASK, SC->PCLKSEL0);
        switch(div){
                case 0:
                        div = 4;
@@ -400,7 +447,7 @@ void CAN_setBusTiming(uint32_t baudrate){
 
        PCLK_CAN = system_frequency / div;
 
-       res = PCLK_CAN / baudrate;
+       res = PCLK_CAN / (chip->baudrate);
 
 
        // calculation of tq_numb - number of time quantum (must be in <8,25>)
@@ -426,62 +473,86 @@ void CAN_setBusTiming(uint32_t baudrate){
                }
        }
 
-       CAN1BTR = ((SAM<<23)|(TSEG2<<20)|(TSEG1<<16)|(SJW<<14)|(BRP<<0));
+       can_write_reg(chip, ((SAM<<23)|(TSEG2<<20)|(TSEG1<<16)|(SJW<<14)|(BRP<<0)), CAN_BTR_o);
 
 }
 
-void CAN_init(uint32_t baudrate)
-{
+void CAN_init(struct canchip_t *chip){
+
        uint32_t tmp;
        uint32_t pclksel0;
        uint32_t val;
+       uint32_t i;
        
-       printf("CAN INIT, baudrate: %d\n", baudrate);
+       printf("CAN INIT, baudrate: %d\n", (int) chip->baudrate);
 
        // configure CAN1 pins 
        CAN_configPin();
 
        // turn on power and clock for CAN1 
-       PCONP |= PCCAN1;
+       SC->PCONP |= PCCAN1;
        
        // set clock divide for CAN1 
 
        val = 0x00; // 00       PCLK_peripheral = CCLK/4 
-       pclksel0 = PCLKSEL0;
+       pclksel0 = SC->PCLKSEL0;
        pclksel0 &= ~PCLK_CAN1_MASK;
        pclksel0 &= ~PCLK_CAN2_MASK;
        pclksel0 &= ~PCLK_ACF_MASK;
        pclksel0 |= __val2mfld(PCLK_CAN1_MASK, val);
        pclksel0 |= __val2mfld(PCLK_CAN2_MASK, val);
        pclksel0 |= __val2mfld(PCLK_ACF_MASK, val);
-       PCLKSEL0 = pclksel0;
+       SC->PCLKSEL0 = pclksel0;
        
        // enter reset mode
-       CAN1MOD = 1;
+       can_write_reg(chip, 1, CAN_MOD_o);
 
        // disable all CAN interrupts
-       CAN1IER = 0;
+       can_write_reg(chip, 0, CAN_IER_o);
 
        // reset value of Global Status Register (global controller status and error counters) 
-       CAN1GSR = 0x3C;
+       can_write_reg(chip, 0x3C, CAN_GSR_o);
 
        // request command to release Rx, Tx buffer and clear data overrun 
-       CAN1CMR = (CAN_CMR_AT | CAN_CMR_RRB | CAN_CMR_CDO);
+       can_write_reg(chip, (CAN_CMR_AT | CAN_CMR_RRB | CAN_CMR_CDO), CAN_CMR_o);
 
        // read to clear interrupt pending in Interrupt Capture Register 
-       tmp = CAN1ICR;
+       tmp = can_read_reg(chip, CAN_ICR_o);
 
        // set bus timing 
-       CAN_setBusTiming(baudrate);
+       CAN_setBusTiming(chip);
 
        // return to normal operating 
-       CAN1MOD = 0;
+       can_write_reg(chip, 0, CAN_MOD_o);
 
-       // enable interrupt after transmit
-       CAN1IER |= CAN_IER_TIE1;
-       // enable CAN interrupt 
-       NVIC_EnableIRQ(CAN_IRQn);
 
+       //--------------------------
+
+       // Acceptance Filter Off Mode
+       CANAF_AFMR = 0x01;
+
+       // clear RAM masks
+       for (i = 0; i < 512; i++) {
+               CANAF_RAM->mask[i] = 0x00;
+       }
+
+       CANAF_SFF_sa = 0x00;
+       CANAF_SFF_GRP_sa = 0x00;
+       CANAF_EFF_sa = 0x00;
+       CANAF_EFF_GRP_sa = 0x00;
+       CANAF_ENDofTable = 0x00;
+
+       // Acceptance Filter Bypass Mode - all messages accepted
+       CANAF_AFMR = 0x02;
+
+       //--------------------------
+
+
+       // enable interrupt after transmit
+       // enable receive interrupt
+       // enable data overrun interrupt
+       can_write_reg(chip, (CAN_IER_TIE1 | CAN_IER_RIE | CAN_IER_DOIE), CAN_IER_o);
+       
        
 }