📄 irq.c
字号:
#ifdef REGDUMP c_can_registerdump(pchip);#endif /* Handle change in status register */ if ( irqreg == INT_STAT ) { pchip->last_chip_status = pchip->chip_status; pchip->chip_status = pchip->read_register( pchip, CCSR ); DEBUGMSG( "(c%d)Status register: 0x%x", pchip->chip_nr, pchip->chip_status ); if ( pchip->chip_status & SR_EWARN ) { /* There is an abnormal number of errors */ pchip->stat.cntWarnings++; errcount = pchip->read_register( pchip, CCEC); DEBUGMSG( "(c%d)stat: Abnormal number of Error Warnings (txErr=%d, rxErr=%d)", pchip->chip_nr, (errcount&0x00ff), ((errcount&0x7f00)>>8)); } if ( pchip->chip_status & SR_EPASS ) { /* Chip entered errorpassive state */ if ( !( pchip->last_chip_status & SR_EPASS ) ) { /* it's a new errorpassive state */ pchip->stat.cntErrPassive++; CANMSG( "(c%d)stat: Chip entered Error Passive state", pchip->chip_nr); if ( ! pchip->time_triggered ) { CANMSG( " Switching to time triggered mode to avoid blocking by"); CANMSG( " ACK ERR interrupts."); pchip->intreg_backup = pchip->read_register( pchip, CCCR & 0xe ); /* stop interrupt generation */ pchip->config_irqs( pchip, CR_SIE | CR_EIE ); /* start timer */ start_time_trig( pchip ); return; } } } else if ( pchip->last_chip_status & SR_EPASS ) { CANMSG( "(c%d)stat: Chip left Error Passive state", pchip->chip_nr); if ( ! pchip->time_triggered ) { CANMSG( " Switching back to interrupt mode."); stop_time_trig( pchip ); c_can_config_irqs(pchip, pchip->intreg_backup); } } if ( pchip->chip_status & SR_BOFF ) { /* Chip is in busoff state */ if ( !( pchip->last_chip_status & SR_BOFF ) ) { /* it's a new busoff */ pchip->stat.cntBusOff ++; /* reset TX_IN_PROGRESS bit of all message objects so that devices can be closed */ for ( i=0; i<pchip->obj_cnt; i++ ) { if ( pchip->pmsgobj[i]->flags & CHANNEL_OPENED ) { pchip->pmsgobj[i]->fifo->flags &= ~TX_IN_PROGRESS; /* In- and output buffer initialization */ //pchip->pmsgobj[i]->fifo->txrp = pchip->pmsgobj[i]->fifo->ptxbuf; //pchip->pmsgobj[i]->fifo->txwp = pchip->pmsgobj[i]->fifo->ptxbuf; } } CANMSG( "(c%d)stat: Chip in Bus Off state", pchip->chip_nr ); CANMSG( "(c%d) try to restart chip and check state in 1s", pchip->chip_nr ); /* return from normal and Error Passive time trigger mode */ stop_time_trig( pchip ); if ( ! pchip->time_triggered ) { c_can_config_irqs(pchip, pchip->intreg_backup); /* backup interrupt register */ pchip->intreg_backup = pchip->read_register(pchip, CCCR & 0xe); /* stop interrupt generation */ pchip->config_irqs( pchip, CR_SIE | CR_EIE ); } /* restart chip */ pchip->disable_configuration( pchip ); /* start timer */ startTimer( pchip, 1, 0, functBusOffTimer ); /* return from interrupt handler */ return; } } else if ( pchip->last_chip_status & SR_BOFF ) { CANMSG( "(c%d)stat: Chip left Bus Off state", pchip->chip_nr); } if (pchip->chip_status & SR_TXOK) { DEBUGMSG("(c%d)stat: Transmitted a Message successfully", pchip->chip_nr); pchip->write_register(pchip->chip_status & ~SR_TXOK, pchip, CCSR); } if (pchip->chip_status & SR_RXOK) { DEBUGMSG("(c%d)stat: Received a Message successfully", pchip->chip_nr); pchip->write_register(pchip->chip_status & ~SR_RXOK, pchip, CCSR); } /* Errors to statistics */ switch( pchip->chip_status & 0x07 ) { case SRLEC_NE: /* No error */ break; case SRLEC_SE: /* Stuff error */ pchip->stat.cntStuffErr++; DEBUGMSG( "(c%d)stat: stuff error", pchip->chip_nr); break; case SRLEC_FE: /* Form error */ pchip->stat.cntFormErr++; DEBUGMSG( "(c%d)stat: form error", pchip->chip_nr); break; case SRLEC_AE: /* Ack error */ pchip->stat.cntAckErr++; DEBUGMSG( "(c%d)stat: acknowledge error", pchip->chip_nr); break; case SRLEC_B1: /* Bit 1 error */ pchip->stat.cntBit1Err++; DEBUGMSG( "(c%d)stat: bit 1 error", pchip->chip_nr); break; case SRLEC_B0: /* Bit 0 error */ pchip->stat.cntBit0Err++; DEBUGMSG( "(c%d)stat: bit 0 error", pchip->chip_nr); break; case SRLEC_CR: /* CRC error */ pchip->stat.cntCrcErr++; DEBUGMSG( "(c%d)stat: crc error", pchip->chip_nr); break; case 7: /* unused */ break; } } else { if ( irqreg >0 && irqreg <33 ) { /* get kernel time */ do_gettimeofday(&tv); /*get number of interrupt causing message object */ idxobj = irqreg-1; /*DEBUGMSG( "Interrupt handler: addr=%lx devid=%lx irqreq=%x status=0x%x\n",*/ // (unsigned long)pchip->vbase_addr + iIRQ, // (unsigned long)dev_id, // irqreg, // statreg ); // spin_lock( &pchip->if1lock ); /* Message Lost Check */ c_can_if1_busycheck( pchip ); pchip->write_register( msgLstReadMaskCM, pchip, CCIF1CM ); pchip->write_register( idxobj+1, pchip, CCIF1CR ); c_can_if1_busycheck( pchip ); tempCntlReg = pchip->read_register( pchip, CCIF1DMC ); if (tempCntlReg & IFXMC_MSGLST) { CANMSG( "(c%dm%d)Chip lost a message", pchip->chip_nr, pchip->pmsgobj[idxobj]->object ); pchip->stat.cntMsgLst++; /* Reset Message Lost Bit */ tempCntlReg = tempCntlReg & (~IFXMC_MSGLST); pchip->write_register( tempCntlReg, pchip, CCIF1DMC ); pchip->write_register( msgLstWriteMaskCM, pchip, CCIF1CM ); pchip->write_register( idxobj+1, pchip, CCIF1CR ); } /* Transfer Message Object to IF1 Buffer */ c_can_if1_busycheck( pchip ); pchip->write_register( readMaskCM, pchip, CCIF1CM ); pchip->write_register( idxobj+1, pchip, CCIF1CR ); /* Call irq sub functions depending on direction of message (send/receive) */ c_can_if1_busycheck( pchip ); if ( pchip->read_register( pchip, CCIF1A2 ) & IFXARB2_DIR ) { spin_unlock( &pchip->if1lock ); c_can_irq_write_handler( pchip ); } else { if (pchip->pmsgobj[idxobj]->msg_mode & 1) { id0 = pchip->read_register( pchip, CCIF1A1 ); id1 = ( pchip->read_register( pchip, CCIF1A2 ) & 0x1FFF ) << 16; msgid = id0 | id1; } else msgid =( ( pchip->read_register( pchip, CCIF1A2 ) & 0x1FFC ) >> 2 ) & 0x7FF; /* check if message is a rtr */ spin_unlock( &pchip->if1lock ); spin_lock( &pchip->rtr_lock ); while ( rtr_search != NULL ) { if ( rtr_search->id == msgid ) break; rtr_search = rtr_search->next; } spin_unlock( &pchip->rtr_lock ); spin_lock( &pchip->if1lock ); /* transfer Message Object to IF1 Buffer */ c_can_if1_busycheck( pchip ); pchip->write_register( readMaskCM, pchip, CCIF1CM ); pchip->write_register( idxobj+1, pchip, CCIF1CR ); /* call read or rtr handler */ c_can_if1_busycheck(pchip); if ( ( rtr_search != NULL ) && ( rtr_search->id == msgid )) c_can_irq_rtr_handler( pchip, msgid, tv ); else c_can_irq_read_handler( pchip, msgid, tv ); spin_unlock( &pchip->if1lock ); } /* else */ } /* if */ } /* Get irq status again */ irqreg = pchip->read_register( pchip, CCINTR ); } return;}/* * Starts a timer with given settings */void startTimer (struct chip_t *pchip, time_t seconds, long nanosecs, void (*function)(unsigned long)){ struct timespec value = { seconds, nanosecs }; /* init the timer structure */ init_timer( &pchip->interrupt_timer ); /* pointer to function that will be executed after timer expired */ pchip->interrupt_timer.function = function; /* store pointer to chip structure in timer structure */ pchip->interrupt_timer.data = (unsigned long)pchip; /* set timer to ms */ pchip->interrupt_timer.expires = jiffies + timespec_to_jiffies( &value ); add_timer( &pchip->interrupt_timer );}void functBusOffTimer (unsigned long chip_ptr){ static u8 busoff_counter = 1; struct chip_t *pchip = (struct chip_t *)chip_ptr; pchip->chip_status = pchip->read_register( pchip, CCSR ); DEBUGMSG( "(c%d)Status register: 0x%x", pchip->chip_nr, pchip->chip_status ); if ( !(pchip->chip_status & SR_BOFF) ) { CANMSG("(c%d) restart successfull, chip left busoff state", pchip->chip_nr); /* chip left busoff state */ busoff_counter = 0; if ( ! pchip->time_triggered ) { /* reallow interrupt generation */ c_can_config_irqs(pchip, pchip->intreg_backup); } else { /* restart time triggered mode */ start_time_trig ( pchip ); } return; } busoff_counter++; CANMSG("(c%d) restart not successfull, try again", pchip->chip_nr); if (busoff_counter == 15 ) CANMSG("(c%d) busoff since 15 seconds, switching to 5s delay", pchip->chip_nr); /* reset init bit of C_CAN controller */ pchip->disable_configuration(pchip); /* restart timer */ startTimer (pchip, (busoff_counter>14 ? 5 : 1), 0, functBusOffTimer);}void functTimeTrigTimer (unsigned long chip_ptr){ struct chip_t *pchip = (struct chip_t *)chip_ptr; static spinlock_t timtriglock = SPIN_LOCK_UNLOCKED; unsigned long intflags; /* restart timer */ startTimer (pchip, 0, pchip->time_trig_nanosec, functTimeTrigTimer); /* call interrupt function with spinlock so that int function won't be interrupted */ spin_lock_irqsave( &timtriglock, intflags ); c_can_irq_handler( pchip->irq, pchip, 0 ); spin_unlock_irqrestore( &timtriglock, intflags );}void start_time_trig ( struct chip_t *pchip ){ startTimer( pchip, 0, pchip->time_trig_nanosec, functTimeTrigTimer );}void stop_time_trig ( struct chip_t *pchip ){ del_timer( &pchip->interrupt_timer );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -