Example #1
0
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);
        }
    }

}
Example #4
0
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;
        }

    }
}
Example #5
0
/*!
 * \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;
    }
}
Example #6
0
/*
 * 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;
    }
}
Example #7
0
/*!
 * \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);
}
Example #11
0
/*
 * 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;
    }
}