Exemplo n.º 1
0
//*****************************************************************************
//
// The spi1 slaver interrupt handler.
//
//*****************************************************************************
void SPI_spi0_int_handler(void)
{
    unsigned long status;
    unsigned long buf;

    status = SSIIntStatus(SSI0_BASE, true);        // »ñÈ¡ÖжÏ״̬
#if 0  // for test
    if (status)
    {
        SSIIntClear(SSI0_BASE, status);
        UARTSend((unsigned char *)"\r\nSSI0", 6);
        return;
    }
#else
    if (!status)
    {
        return;
    }

    SSIIntClear(SSI0_BASE, status);

    switch (status)
    {
        case SSI_RXFF:
        case SSI_RXOR:
            while (1)
            {
                if (SSIDataGetNonBlocking(SSI0_BASE, &buf))
                {
                    spi_rx_buf[spi_rx_idx++] = (unsigned char)buf;
                    UARTSend(&spi_rx_buf[spi_rx_idx-1], 1);  // test
                }
                else
                {
                    spi_rx_len = spi_rx_idx;
                    spi_rx_idx = 0;
                    //OSSemPost();
                    UARTSend("\r\n", 2);                    // test
                    break;
                }
            }
            break;

        case SSI_RXTO:
            // do something for timeout
            break;

        default:
            break;
    }
#endif
}
Exemplo n.º 2
0
void Spi::interruptHandler(void)
{
    uint32_t status;

    // Read interrupt source
    status = SSIIntStatus(config_.base, true);

    // Clear SPI interrupt in the NVIC
    IntPendClear(config_.interrupt);

    // Process TX interrupt
    if (status & SSI_TXFF) {
        interruptHandlerTx();
    }

    // Process RX interrupt
    if (status & SSI_RXFF) {
        interruptHandlerRx();
    }
}
Exemplo n.º 3
0
//--------------------------------
void ssi_peripheral::OnInterrupt() {
	uint32_t nIntStatus = SSIIntStatus(m_rSpecification.m_nSSIBase, false);
	uint32_t nSsiStatus = (HWREG(m_rSpecification.m_nSSIBase + SSI_O_SR));
	SSIIntClear(m_rSpecification.m_nSSIBase, nIntStatus);
	if (SSI_SR_TFE & nSsiStatus) { // SSI Transmit FIFO Empty (status)
		m_nSRTFE++;
		OnTx();
	}
	if ( SSI_TXFF & nIntStatus) { // TX FIFO half full or less
		m_nTXFF++;
	}
	if ( SSI_RXFF & nIntStatus) { // RX FIFO half full or more
		m_nRXFF++;
		UnloadRxFIFO();
	}
	if ( SSI_RXTO & nIntStatus) {  // RX timeout
		m_nRXTO++;
	}
	if ( SSI_RXOR & nIntStatus) {  // RX overrun
		m_nRXOR++;
	}
}
Exemplo n.º 4
0
/*
 *  ======== SPICC26XXDMA_hwiFxn ========
 *  ISR for the SPI when we use the UDMA
 */
static void SPICC26XXDMA_hwiFxn (UArg arg) {
    SPI_Transaction         *msg;
    SPICC26XX_Object        *object;
    SPICC26XX_HWAttrs const *hwAttrs;
    uint32_t                intStatus;

    /* Get the pointer to the object and hwAttrs */
    object = ((SPI_Handle)arg)->object;
    hwAttrs = ((SPI_Handle)arg)->hwAttrs;

    Log_print1(Diags_USER2, "SPI:(%p) interrupt context start", hwAttrs->baseAddr);

    /* Get the interrupt status of the SPI controller */
    intStatus = SSIIntStatus(hwAttrs->baseAddr, true);
    SSIIntClear(hwAttrs->baseAddr, intStatus);

    /* Error handling:
     * Overrun in the RX Fifo -> at least one sample in the shift
     * register has been discarded  */
    if (intStatus & SSI_RXOR) {
        /* disable the interrupt */
        SSIIntDisable(hwAttrs->baseAddr, SSI_RXOR);

        /* If the RX overrun occurred during a transfer */
        if (object->currentTransaction) {
            /* Then cancel the ongoing transfer */
            SPICC26XXDMA_transferCancel((SPI_Handle)arg);
        }
        else {
            /* Otherwise disable the SPI and DMA modules and flush FIFOs */
            SSIDisable(hwAttrs->baseAddr);

            /* Disable SPI TX/RX DMA and clear DMA done interrupt just in case it finished */
            SSIDMADisable(hwAttrs->baseAddr, SSI_DMA_TX | SSI_DMA_RX);
            UDMACC26XX_clearInterrupt(object->udmaHandle, (hwAttrs->rxChannelBitMask) | (hwAttrs->txChannelBitMask));

            /* Clear out the FIFO by resetting SPI module and re-initting */
            HapiResetPeripheral(hwAttrs->baseAddr == SSI0_BASE ? PRCM_PERIPH_SSI0 : PRCM_PERIPH_SSI1);
            SPICC26XXDMA_initHw((SPI_Handle)arg);
        }
        Log_print1(Diags_USER1, "RX FIFO overrun occurred in SPI: (%p) !\n", hwAttrs->baseAddr);
    }
    else {
        /* Determine if the TX DMA channel has completed... */
        if (UDMACC26XX_channelDone(object->udmaHandle, hwAttrs->txChannelBitMask)) {
            /* Disable SPI TX DMA and clear DMA done interrupt. */
            SSIDMADisable(hwAttrs->baseAddr, SSI_DMA_TX);
            UDMACC26XX_clearInterrupt(object->udmaHandle, hwAttrs->txChannelBitMask);
            /* All transfers will set up both TX and RX DMA channels and both will finish.
             * Even if the transaction->rxBuf == NULL, it will setup a dummy RX transfer to
             * a scratch memory location which is then discarded.
             * Therefore all cleanup is only done when the RX DMA channel has completed,
             * since it will always run at some point after the TX DMA channel has completed.
             */
        }

        /* Determine if the RX DMA channel has completed... */
        if(UDMACC26XX_channelDone(object->udmaHandle, hwAttrs->rxChannelBitMask)) {
            /* Disable SPI RX DMA and clear DMA done interrupt. */
            SSIDMADisable(hwAttrs->baseAddr, SSI_DMA_RX);
            UDMACC26XX_clearInterrupt(object->udmaHandle, hwAttrs->rxChannelBitMask);

            /* Transaction is complete */
            object->currentTransaction->status = SPI_TRANSFER_COMPLETED;

            /* Use a temporary transaction pointer in case the callback function
             * attempts to perform another SPI_transfer call
             */
            msg = object->currentTransaction;

            Log_print2(Diags_USER1,"SPI:(%p) DMA transaction: %p complete",
                                    hwAttrs->baseAddr, (UArg)msg);

            /* Release constraint since transaction is done */
            threadSafeConstraintRelease((uint32_t)(object->currentTransaction->txBuf));

            /* Indicate we are done with this transfer */
            object->currentTransaction = NULL;

            /* Perform callback */
            object->transferCallbackFxn((SPI_Handle)arg, msg);
        }
    }

    Log_print1(Diags_USER2, "SPI:(%p) interrupt context end",
                             hwAttrs->baseAddr);
}