static void STMCanTXInterrupt( void *arg) { NUTCANBUS *bus = arg; CANBUSINFO *ci = bus->bus_ci; __IO uint32_t *CANBBx = bus->bb_base; CANBBx[CM3BB_OFFSET(CAN_TypeDef, IER,_BI32(CAN_IER_TMEIE))]= 0; ci->can_tx_interrupts++; NutEventPostFromIrq(&(ci->can_tx_rdy)); }
void NutUnixThreadYieldHook() { uint8_t irq; for (irq = 0; irq < IRQ_MAX; irq++) { if (irq_eventqueues[irq] != 0) { // printf("NutUnixThreadYield posting event nr %d\n\r", irq); NutEventPostFromIrq(irq_eventqueues[irq]); irq_eventqueues[irq] = 0; } } }
/*! * \brief USART interrupt handler. * * \param arg Pointer to the device specific control block. */ static void At91UsartInterrupt(void *arg) { AHDLCDCB *dcb = arg; uint16_t count, i; ureg_t csr = inr(US1_CSR); if (csr & (US_ENDRX | US_RXBUFF | US_TIMEOUT)) { // Todo, handle error flags if (csr & US_TIMEOUT) { count = NUT_AHDLC_RECV_DMA_SIZE - inr(USART1_BASE + PERIPH_RCR_OFF); } else { count = NUT_AHDLC_RECV_DMA_SIZE; } for (i = 0; i < count; i++) { dcb->dcb_rx_buf[dcb->dcb_rx_idx] = DMA_RxBuf0[i]; dcb->dcb_rx_idx++; } outr(USART1_BASE + PERIPH_RPR_OFF, (unsigned int) DMA_RxBuf0); outr(USART1_BASE + PERIPH_RCR_OFF, NUT_AHDLC_RECV_DMA_SIZE); outr(USART1_BASE + PERIPH_PTCR_OFF, PDC_RXTEN); outr(US1_CR, inr(US1_CR) | US_STTTO); NutEventPostFromIrq(&dcb->dcb_rx_rdy); } if (csr & US_TXRDY) { if (dcb->dcb_tx_idx != dcb->dcb_wr_idx) { outr(US1_THR, dcb->dcb_tx_buf[dcb->dcb_tx_idx]); dcb->dcb_tx_idx++; } else { outr(US1_IDR, US_TXRDY); NutEventPostFromIrq(&dcb->dcb_tx_rdy); } } }
static void STMCanRX1Interrupt( void *arg) { NUTCANBUS *bus = arg; CAN_TypeDef *CANx = (CAN_TypeDef*)bus->bus_base; CANBUSINFO *ci = bus->bus_ci; CANBUFFER *rxbuf = &(ci->can_RxBuf); __IO uint32_t *CANBBx = bus->bb_base; if (CANBBx[CM3BB_OFFSET(CAN_TypeDef, RF1R,_BI32(CAN_RF1R_FOVR1))]) { CANBBx[CM3BB_OFFSET(CAN_TypeDef, RF1R,_BI32(CAN_RF1R_FOVR1))]=0; ci->can_overruns++; } ci->can_rx_interrupts++; while(CANx->RF1R & 3) { // Space in buffer ? if (rxbuf->datalength < rxbuf->size) { int index = (rxbuf->dataindex + rxbuf->datalength) % rxbuf->size; CAN_FIFOMailBox_TypeDef*bufPtr = &rxbuf->dataptr[index]; memcpy(bufPtr, &CANx->sFIFOMailBox[1], sizeof(CAN_FIFOMailBox_TypeDef)); // Increment buffer length rxbuf->datalength++; NutEventPostFromIrq(&ci->can_rx_rdy); // Stat houskeeping ci->can_rx_frames++; CANBBx[CM3BB_OFFSET(CAN_TypeDef, RF1R,_BI32(CAN_RF1R_RFOM1))]=1; while(CANBBx[CM3BB_OFFSET(CAN_TypeDef, RF1R,_BI32(CAN_RF1R_RFOM1))]); } else { /* No overrun yet, but we can't clean the FIFO yet */ /* Disable the FIFO message pending interrupt*/ CANBBx[CM3BB_OFFSET(CAN_TypeDef, IER,_BI32(CAN_IER_FMPIE1))]= 0; return; } } }
/*! * \brief Interrupt handler for RTC Alarm * */ static void Lpc17xxRtcInterrupt(void *arg) { NUTRTC *rtc = (NUTRTC *)arg; /* * there is only 1 interrupt for the RTC, so check here * if it was the CIIF or the CALF. We need the CALF here */ if (LPC_RTC->ILR & RTC_IRL_RTCCIF) { LPC_RTC->ILR |= RTC_IRL_RTCCIF; } /* Continue to check the Alarm match*/ if (LPC_RTC->ILR & RTC_IRL_RTCALF) { ((lpc17xx_rtc_dcb *)rtc->dcb)->flags |= RTC_STATUS_AL0; /* Signal alarm event queue */ NutEventPostFromIrq(&rtc->alarm); /* Clear pending interrupt */ LPC_RTC->ILR |= RTC_IRL_RTCALF; } }
/* * STM32V2 I2C Event interrupt function. */ static void I2cEventBusIrqHandler(void *arg) { STM32_I2CCB *icb = (STM32_I2CCB *) arg; NUTI2C_MSG *msg = icb->icb_msg; I2C_TypeDef *i2c; uint32_t cr2; i2c = (I2C_TypeDef *) icb->icb_base; cr2 = i2c->CR2; /* TX parts*/ if ((i2c->ISR & I2C_ISR_TCR) && !(cr2 & I2C_CR2_RD_WRN)) { uint32_t txbytes_left = msg->msg_wlen - msg->msg_widx; if (txbytes_left <= 0xff) { cr2 &= ~(I2C_CR2_NBYTES | I2C_CR2_RELOAD); cr2 |= txbytes_left << 16; } /* else I2C_CR2_NBYTES and I2C_CR2_RELOAD already set*/ i2c->CR2 = cr2; /* Write to NBYTES clears TCR*/ } if ((i2c->ISR & I2C_ISR_TC) && !(cr2 & I2C_CR2_RD_WRN)) { i2c->CR1 &= ~I2C_CR1_TXIE; cr2 &= ~I2C_CR2_NBYTES; if (msg->msg_rsiz == 0) /* No read transaction, stop after write*/ { i2c->CR2 = cr2 | I2C_CR2_STOP ; } else { i2c->CR1 |= I2C_CR1_RXIE; cr2 |= I2C_CR2_RD_WRN | msg->msg_rsiz << 16; i2c->CR2 = cr2 | I2C_CR2_START ; } } if ((i2c->ISR & I2C_ISR_TXIS) && !(cr2 & I2C_CR2_RD_WRN)) { i2c->TXDR = msg->msg_wdat[msg->msg_widx]; msg->msg_widx++; } /* RX parts*/ if ((i2c->ISR & I2C_ISR_TCR) && (cr2 & I2C_CR2_RD_WRN)) { uint32_t rxbytes_left = msg->msg_rsiz - msg->msg_ridx; if (rxbytes_left <= 0xff) { cr2 &= ~(I2C_CR2_NBYTES | I2C_CR2_RELOAD); cr2 |= rxbytes_left << 16; } /* else I2C_CR2_NBYTES and I2C_CR2_RELOAD already set*/ i2c->CR2 = cr2; /* Write to NBYTES clears TCR*/ } if ((i2c->ISR & I2C_ISR_TC) && (cr2 & I2C_CR2_RD_WRN)) { i2c->CR1 &= ~(I2C_CR1_TCIE | I2C_CR1_RXIE); i2c->CR2 = cr2 | I2C_CR2_STOP ; } if ((i2c->ISR & I2C_ISR_RXNE) && (cr2 & I2C_CR2_RD_WRN)) { msg->msg_rdat[msg->msg_ridx] = i2c->RXDR; msg->msg_ridx++; if (msg->msg_ridx == msg->msg_rsiz) /* No more RX Interrupts*/ i2c->CR1 &= ~I2C_CR1_RXIE; } if (i2c->ISR & I2C_ISR_STOPF) { i2c->CR1 &= ~I2C_CR1_STOPIE; i2c->ICR |= I2C_ICR_STOPCF; NutEventPostFromIrq(&icb->icb_queue); } if (i2c->ISR & I2C_ISR_NACKF) { /* Save error, but only exit through STOPF */ icb->errors |= I2C_ISR_NACKF; i2c->CR1 &= ~I2C_CR1_NACKIE; i2c->ICR |= I2C_ICR_NACKCF; } }
/*! * \brief AT91 SPI interrupt handler. */ static void At91SpiInterrupt(void *arg) { NutEventPostFromIrq((void **)arg); }
/* * NIC interrupt entry. */ static void NicInterrupt(void *arg) { phantom_device_t * dev = arg; uint8_t isr; uint8_t imr; lanc111_nic_t *ni = (lanc111_nic_t *) ((NUTDEVICE *) arg)->dev_dcb; ni->ni_interrupts++; /* Read the interrupt mask and disable all interrupts. */ nic_bs(2); imr = nic_inlb(NIC_MSK); nic_outlb(NIC_MSK, 0); /* Read the interrupt status and acknowledge all interrupts. */ isr = nic_inlb(NIC_IST); //printf("\n!%02X-%02X ", isr, imr); isr &= imr; /* * If this is a transmit interrupt, then a packet has been sent. * So we can clear the transmitter busy flag and wake up the * transmitter thread. */ if (isr & INT_TX_EMPTY) { nic_outlb(NIC_ACK, INT_TX_EMPTY); imr &= ~INT_TX_EMPTY; } /* Transmit error. */ else if (isr & INT_TX) { /* re-enable transmit */ nic_bs(0); nic_outw(NIC_TCR, nic_inlb(NIC_TCR) | TCR_TXENA); nic_bs(2); nic_outlb(NIC_ACK, INT_TX); /* kill the packet */ nic_outlb(NIC_MMUCR, MMU_PKT); } /* * If this is a receive interrupt, then wake up the receiver * thread. */ if (isr & INT_RX_OVRN) { nic_outlb(NIC_ACK, INT_RX_OVRN); //nic_outlb(NIC_MMUCR, MMU_TOP); NutEventPostFromIrq(&ni->ni_rx_rdy); } if (isr & INT_ERCV) { nic_outlb(NIC_ACK, INT_ERCV); NutEventPostFromIrq(&ni->ni_rx_rdy); } if (isr & INT_RCV) { nic_outlb(NIC_ACK, INT_RCV); imr &= ~INT_RCV; NutEventPostFromIrq(&ni->ni_rx_rdy); } if (isr & INT_ALLOC) { imr &= ~INT_ALLOC; NutEventPostFromIrq(&maq); } //printf(" -%02X-%02X- ", nic_inlb(NIC_IST), inb(PINE) & 0x20); nic_outlb(NIC_MSK, imr); }
/*! * \brief SPI0 interrupt handler. * * Called when PDC transmission done. */ static void Avr32Spi0Interrupt(void *arg) { NutEventPostFromIrq(&spi0_que); }
/*! * \brief SPI1 interrupt handler. * * Called when PDC transmission done. */ static void At91Spi1Interrupt(void *arg) { NutEventPostFromIrq(&spi1_que); }
/* * VLSI codec 0 interrupt handler. * * \param arg Pointer to an event queue. */ static void VsCodec0Interrupt(void *arg) { NutEventPostFromIrq((void **)arg); }
/* * TWI interrupt handler. */ static void TwInterrupt(void *arg) { u_char twsr; register u_char twcr = inb(TWCR); /* * Read the status and interpret its contents. */ twsr = inb(TWSR) & 0xF8; switch (twsr) { /* * 0x08: Start condition has been transmitted. * 0x10: Repeated start condition has been transmitted. */ case TW_START: case TW_REP_START: /* We are entering the master mode. Mark the interface busy. */ tw_if_bsy = 1; tw_mt_idx = 0; tw_mr_idx = 0; /* * If outgoing data is available, transmit SLA+W. Logic is in * master transmit mode. */ if (tw_mt_len) { outb(TWDR, tw_mm_sla); } /* * If outgoing data not available, transmit SLA+R. Logic will * switch to master receiver mode. */ else { outb(TWDR, tw_mm_sla | 1); } outb(TWCR, TWGO | (twcr & _BV(TWEA))); break; /* * 0x18: SLA+W has been transmitted and ACK has been received. * 0x28: Data byte has been transmitted and ACK has been received. */ case TW_MT_SLA_ACK: case TW_MT_DATA_ACK: /* * If outgoing data left to send, put the next byte in the data * register. */ if (tw_mt_idx < tw_mt_len) { outb(TWDR, tw_mt_buf[tw_mt_idx]); /* Late increment fixes ICCAVR bug. Thanks to Andreas Siebert and Michael Fischer. */ tw_mt_idx++; outb(TWCR, TWGO | (twcr & _BV(TWEA))); break; } /* * All outgoing data has been sent. If a response is expected, * transmit a repeated start condition. */ tw_mt_len = 0; if (tw_mr_siz) { outb(TWCR, TWGO | (twcr & _BV(TWEA)) | _BV(TWSTA)); break; } /* * 0x20: SLA+W has been transmitted, but not acknowledged. * 0x30: Data byte has been transmitted, but not acknowledged. * 0x48: SLA+R has been transmitted, but not acknowledged. */ case TW_MT_SLA_NACK: case TW_MT_DATA_NACK: case TW_MR_SLA_NACK: /* Set unique error code. */ if (twsr == TW_MT_SLA_NACK || twsr == TW_MR_SLA_NACK) { tw_mm_err = TWERR_SLA_NACK; tw_mt_len = 0; tw_mr_siz = 0; } /* Wake up the application. */ NutEventPostFromIrq(&tw_mm_que); /* * Send a stop condition. If we have a listener, generate * an acknowlegde on an incoming address byte. */ if(tw_sr_siz) { outb(TWCR, TWGO | _BV(TWEA) | _BV(TWSTO)); } else { outb(TWCR, TWGO | _BV(TWSTO)); } /* The interface is idle. */ tw_if_bsy = 0; break; /* * 0x38: Arbitration lost while in master mode. */ case TW_MT_ARB_LOST: /* * The start condition will be automatically resend after * the bus becomes available. */ sbi(TWCR, TWSTA); /* The interface is idle. */ tw_if_bsy = 0; break; /* * 0x50: Data byte has been received and acknowledged. */ case TW_MR_DATA_ACK: /* * Store the data byte in the master receive buffer. */ tw_mr_buf[tw_mr_idx] = inb(TWDR); /* Late increment fixes ICCAVR bug. Thanks to Andreas Siebert and Michael Fischer. */ tw_mr_idx++; /* * 0x40: SLA+R has been transmitted and ACK has been received. */ case TW_MR_SLA_ACK: /* * Acknowledge next data bytes except the last one. */ if (tw_mr_idx + 1 < tw_mr_siz) { outb(TWCR, TWGO | _BV(TWEA)); } else { outb(TWCR, TWGO); } break; /* * 0x58: Data byte has been received, but not acknowledged. */ case TW_MR_DATA_NACK: /* * Store the last data byte. */ tw_mr_buf[tw_mr_idx] = inb(TWDR); /* Late increment fixes ICCAVR bug. Thanks to Andreas Siebert and Michael Fischer. */ tw_mr_idx++; tw_mr_siz = 0; /* Wake up the application. */ NutEventPostFromIrq(&tw_mm_que); /* * Send a stop condition. If we have a listener, generate * an acknowlegde on an incoming address byte. */ if(tw_sr_siz) { outb(TWCR, TWGO | _BV(TWEA) | _BV(TWSTO)); } else { outb(TWCR, TWGO | _BV(TWSTO)); } /* The interface is idle. */ tw_if_bsy = 0; break; /* * 0x60: Own SLA+W has been received and acknowledged. * 0x68: Arbitration lost as master. Own SLA+W has been received * and acknowledged. * 0x70: General call address has been received and acknowledged. * 0x78: Arbitration lost as master. General call address has been * received and acknowledged. */ case TW_SR_SLA_ACK: case TW_SR_ARB_LOST_SLA_ACK: case TW_SR_GCALL_ACK: case TW_SR_ARB_LOST_GCALL_ACK: /* * Do only acknowledge incoming data bytes, if we got receive * buffer space. Fetch the slave address from the data register * and reset the receive index. */ if (tw_sr_siz) { /* We are entering the slave receive mode. Mark the interface busy. */ tw_if_bsy = 1; tw_sm_sla = inb(TWDR); outb(TWCR, TWGO | _BV(TWEA)); tw_sr_idx = 0; } /* * Do not acknowledge incoming data. */ else { outb(TWCR, TWGO); } break; /* * 0x80: Data byte for own SLA has been received and acknowledged. * 0x90: Data byte for general call address has been received and * acknowledged. */ case TW_SR_DATA_ACK: case TW_SR_GCALL_DATA_ACK: /* * If the receive buffer isn't filled up, store data byte. */ if (tw_sr_idx < tw_sr_siz) { tw_sr_buf[tw_sr_idx] = inb(TWDR); /* Late increment fixes ICCAVR bug. Thanks to Andreas Siebert and Michael Fischer. */ tw_sr_idx++; } else { tw_sr_siz = 0; } /* * If more space is available for incoming data, then continue * receiving. Otherwise do not acknowledge new data bytes. */ if (tw_sr_siz) { outb(TWCR, TWGO | _BV(TWEA)); break; } /* * 0x88: Data byte received, but not acknowledged. * 0x98: Data byte for general call address received, but not * acknowledged. */ case TW_SR_DATA_NACK: case TW_SR_GCALL_DATA_NACK: /* * Continue not accepting more data. */ if (tw_mt_len || tw_mr_siz) { outb(TWCR, inb(TWCR) | _BV(TWEA) | _BV(TWSTA)); } else { outb(TWCR, inb(TWCR) | _BV(TWEA)); } break; /* * 0xA0: Stop condition or repeated start condition received. */ case TW_SR_STOP: /* * Wake up the application. If successful, do nothing. This * will keep SCL low and thus block the bus. The application * must now setup the transmit buffer and re-enable the * interface. */ if (tw_sr_que == 0 || tw_sm_err) { /* * If no one has been waiting on the queue, the application * probably gave up waiting. So we continue on our own, either * in idle mode or switching to master mode if a master * request is waiting. */ if (tw_mt_len || tw_mr_siz) { outb(TWCR, TWGO | _BV(TWSTA)); } else { outb(TWCR, TWGO); } tw_if_bsy = 0; } else { NutEventPostFromIrq(&tw_sr_que); tw_sr_siz = 0; outb(TWCR, twcr & ~(_BV(TWINT) | _BV(TWIE))); } break; /* * 0xA8: Own SLA+R has been received and acknowledged. * 0xB0: Arbitration lost in master mode. Own SLA has been received * and acknowledged. */ case TW_ST_SLA_ACK: case TW_ST_ARB_LOST_SLA_ACK: /* Not idle. */ tw_if_bsy = 1; /* Reset transmit index and fall through for outgoing data. */ tw_st_idx = 0; /* * 0xB8: Data bytes has been transmitted and acknowledged. */ case TW_ST_DATA_ACK: /* * If outgoing data left to send, put the next byte in the * data register. Otherwise transmit a dummy byte. */ if (tw_st_idx < tw_st_len) { outb(TWDR, tw_st_buf[tw_st_idx]); /* Do not set acknowledge on the last data byte. */ /* Early increment fixes ICCAVR bug. Thanks to Andreas Siebert and Michael Fischer. */ ++tw_st_idx; if (tw_st_idx < tw_st_len) { outb(TWCR, TWGO | _BV(TWEA)); } else { tw_st_len = 0; outb(TWCR, TWGO); } break; } /* No more data. Continue sending dummies. */ outb(TWDR, 0); outb(TWCR, TWGO); break; /* * 0xC0: Data byte has been transmitted, but not acknowledged. * 0xC8: Last data byte has been transmitted and acknowledged. */ case TW_ST_DATA_NACK: case TW_ST_LAST_DATA: NutEventPostFromIrq(&tw_st_que); /* Transmit start condition, if a master transfer is waiting. */ if (tw_mt_len || tw_mr_siz) { outb(TWCR, TWGO | _BV(TWSTA) | /**/ _BV(TWEA)); } /* Otherwise enter idle state. */ else { outb(TWCR, TWGO | _BV(TWEA)); } tw_if_bsy = 0; break; /* * 0x00: Bus error. */ case TW_BUS_ERROR: outb(TWCR, inb(TWCR) | _BV(TWSTO)); #if 1 tw_if_bsy = 0; tw_mm_err = TWERR_BUS; tw_sm_err = TWERR_BUS; NutEventPostFromIrq(&tw_sr_que); NutEventPostFromIrq(&tw_st_que); NutEventPostFromIrq(&tw_mm_que); #endif break; } }