]> rtime.felk.cvut.cz Git - lincan.git/commitdiff
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 5559da00ab09ef29e69a3329861b2d3b2b9664f7..b777cade5b5659b217b0dbe42313e65673948812 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 216a9b904b8f755c8a5c4a91795c1489c3f1629d..59fa68dcb39ed4a807ca054fd9a04445c2f165a8 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);