SJA1000 driver interrupts processing modified to not rely on interrupt register for...
authorppisa <ppisa>
Tue, 11 Oct 2005 15:41:38 +0000 (15:41 +0000)
committerppisa <ppisa>
Tue, 11 Oct 2005 15:41:38 +0000 (15:41 +0000)
The information about free chip ready condition for Tx message is now
obtained from status register. This solution enables us to equip SJA1000
driver by irq_accept method. Then only this part has to be run in real IRQ
handler and rest of ISR can be done in other thread. This is required
for possible porting to QNX as well. Change should helps to better
recover form bus-off mode as well.

lincan/include/constants.h
lincan/src/sja1000p.c

index 5559da0..b777cad 100644 (file)
@@ -50,6 +50,7 @@
 #define MSGOBJ_FILTCH_REQUEST_b    5
 #define MSGOBJ_RX_MODE_b           6
 #define MSGOBJ_RX_MODE_EXT_b       7
+#define MSGOBJ_TX_PENDING_b        8
 
 #define MSGOBJ_OPENED              (1<<MSGOBJ_OPENED_b)
 #define MSGOBJ_TX_REQUEST          (1<<MSGOBJ_TX_REQUEST_b)
@@ -59,6 +60,7 @@
 #define MSGOBJ_FILTCH_REQUEST      (1<<MSGOBJ_FILTCH_REQUEST_b)
 #define MSGOBJ_RX_MODE             (1<<MSGOBJ_RX_MODE_b)
 #define MSGOBJ_RX_MODE_EXT         (1<<MSGOBJ_RX_MODE_EXT_b)
+#define MSGOBJ_TX_PENDING          (1<<MSGOBJ_TX_PENDING_b)
 
 #define can_msgobj_test_fl(obj,obj_fl) \
   test_bit(MSGOBJ_##obj_fl##_b,&(obj)->obj_flags)
index 216a9b9..59fa68d 100644 (file)
@@ -96,6 +96,10 @@ int sja1000p_chip_config(struct canchip_t *chip)
 
        /* Set mode, clock out, comparator */
        can_write_reg(chip,sjaCDR_PELICAN|chip->sja_cdr_reg,SJACDR); 
+
+       /* Ensure, that interrupts are disabled even on the chip level now */
+       can_write_reg(chip, sjaDISABLE_INTERRUPTS, SJAIER);
+
        /* Set driver output configuration */
        can_write_reg(chip,chip->sja_ocr_reg,SJAOCR); 
        
@@ -599,9 +603,11 @@ void sja1000p_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj)
                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;
@@ -653,6 +659,8 @@ int sja1000p_irq_handler(int irq, struct canchip_t *chip)
                return CANCHIP_IRQ_NONE;
        }
 
+       status=can_read_reg(chip,SJASR);
+
        do {
 
                if(!loop_cnt--) {
@@ -660,13 +668,18 @@ int sja1000p_irq_handler(int irq, struct canchip_t *chip)
                        return CANCHIP_IRQ_STUCK;
                }
 
-               if ((irq_register & sjaIR_RI) != 0) {
-                       DEBUGMSG("sja1000_irq_handler: RI\n");
+               /* (irq_register & sjaIR_RI) */
+               /*      old variant using SJAIR, collides with intended use with irq_accept */
+               if (status & sjaSR_RBS) {
+                       DEBUGMSG("sja1000_irq_handler: RI or RBS\n");
                        sja1000p_read(chip,obj);
                        obj->ret = 0;
                }
-               if ((irq_register & sjaIR_TI) != 0) {
-                       DEBUGMSG("sja1000_irq_handler: TI\n");
+
+               /* (irq_register & sjaIR_TI) */
+               /*      old variant using SJAIR, collides with intended use with irq_accept */
+               if ((status & sjaSR_TBS) && can_msgobj_test_fl(obj,TX_PENDING)) {
+                       DEBUGMSG("sja1000_irq_handler: TI or TX_PENDING and TBS\n");
                        obj->ret = 0;
                        can_msgobj_set_fl(obj,TX_REQUEST);
                        while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){
@@ -682,7 +695,6 @@ int sja1000p_irq_handler(int irq, struct canchip_t *chip)
                }
                if ((irq_register & (sjaIR_EI|sjaIR_BEI|sjaIR_EPI|sjaIR_DOI)) != 0) { 
                        // Some error happened
-                       status=can_read_reg(chip,SJASR);
                        error_code=can_read_reg(chip,SJAECC);
                        CANMSG("Error: status register: 0x%x irq_register: 0x%02x error: 0x%02x\n",
                                status, irq_register, error_code);
@@ -715,7 +727,11 @@ int sja1000p_irq_handler(int irq, struct canchip_t *chip)
 
                irq_register=can_read_reg(chip,SJAIR);
        
-       } while(irq_register & (sjaIR_BEI|sjaIR_EPI|sjaIR_DOI|sjaIR_EI|sjaIR_TI|sjaIR_RI));
+               status=can_read_reg(chip,SJASR);
+
+       } while((irq_register & (sjaIR_BEI|sjaIR_EPI|sjaIR_DOI|sjaIR_EI|sjaIR_TI|sjaIR_RI)) ||
+               ((status & sjaSR_TBS) && can_msgobj_test_fl(obj,TX_PENDING)) ||
+               (status & sjaSR_RBS));
 
        return CANCHIP_IRQ_HANDLED;
 }
@@ -736,6 +752,7 @@ int sja1000p_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);