示例#1
0
/*
*  ======== SPICC26XXDMA_hwInit ========
*  This functions initializes the SPI hardware module.
*
*  @pre    Function assumes that the SPI handle is pointing to a hardware
*          module which has already been opened.
*/
static void SPICC26XXDMA_initHw(SPI_Handle handle) {
    SPICC26XX_Object        *object;
    SPICC26XX_HWAttrs const *hwAttrs;
    Types_FreqHz            freq;

    /* Get the pointer to the object and hwAttrs */
    object = handle->object;
    hwAttrs = handle->hwAttrs;

    /* Disable SSI operation */
    SSIDisable(hwAttrs->baseAddr);

    /* Disable SPI module interrupts */
    SSIIntDisable(hwAttrs->baseAddr, SSI_RXOR | SSI_RXFF | SSI_RXTO | SSI_TXFF);
    SSIIntClear(hwAttrs->baseAddr, SSI_RXOR | SSI_RXTO);

    /* Set the SPI configuration */
    BIOS_getCpuFreq(&freq);
    SSIConfigSetExpClk(hwAttrs->baseAddr, freq.lo, frameFormat[object->frameFormat],
                       mode[object->mode], object->bitRate, object->dataSize);

    /* Print the configuration */
    Log_print3(Diags_USER1, "SPI:(%p) CPU freq: %d; SPI freq to %d",
               hwAttrs->baseAddr, freq.lo, object->bitRate);
}
示例#2
0
void Spi::disableInterrupts(void)
{
    // Disable the SPI interrupt
    SSIIntDisable(config_.base, (SSI_TXFF | SSI_RXFF | SSI_RXTO | SSI_RXOR));

    // Disable the SPI interrupt
    IntDisable(config_.interrupt);
}
示例#3
0
文件: Spi.cpp 项目: JKLLBF/firmware
void Spi::disableInterrupts(void)
{
    // Disable the SPI interrupt
    SSIIntDisable(base_, (SSI_TXFF | SSI_RXFF | SSI_RXTO | SSI_RXOR));

    // Disable the SPI interrupt
    IntDisable(interrupt_);
}
示例#4
0
//--------------------------------
void ssi_peripheral::Initialize() {
	MAP_SysCtlPeripheralEnable(m_rSpecification.m_nSSIPeripheral);
	MAP_SysCtlPeripheralEnable(m_rSpecification.m_nGPIOPeripheral);
	// Assign the SSI signals to the appropriate pins
	MAP_GPIOPinConfigure(m_rSpecification.m_nSSIPinRx);
	MAP_GPIOPinConfigure(m_rSpecification.m_nSSIPinClk);
	MAP_GPIOPinConfigure(m_rSpecification.m_nSSIPinTx);
	if (m_rSpecification.m_nSSIPinFss) {
		MAP_GPIOPinConfigure(m_rSpecification.m_nSSIPinFss);
	}
	// Set the GPIO AFSEL bits for the appropriate pins
	MAP_GPIOPinTypeSSI(m_rSpecification.m_nGPIOBase,
			m_rSpecification.m_nGPIOPins);
	// Set pull-up on the SSI Rx pin
	GPIOPadConfigSet(m_rSpecification.m_nGPIOBase,
			m_rSpecification.m_nGPIOInputPin, GPIO_STRENGTH_2MA,
			GPIO_PIN_TYPE_STD_WPU);
	// Set standard on the SSI output pins
	GPIOPadConfigSet(m_rSpecification.m_nGPIOBase,
			m_rSpecification.m_nGPIOOutputPins, GPIO_STRENGTH_2MA,
			GPIO_PIN_TYPE_STD);
	// Configure the SSI peripheral
	SSIConfigSetExpClk(m_rSpecification.m_nSSIBase, SysCtlClockGet(),
			m_nProtocol, SSI_MODE_MASTER, m_nBitRate, 16);
	// Enable the SSI module.
	MAP_SSIEnable(m_rSpecification.m_nSSIBase);
	// Read any residual data from the SSI port.
	while (MAP_SSIDataGetNonBlocking(m_rSpecification.m_nSSIBase, &m_nDataRx[0])) {
	}
	m_bEmpty = true;
	// Enable the SSI interrupt
	switch (m_nDevice) {
	case ssi_peripheral::SSI0:
		g_pTheSSI0 = this;
		break;
	case ssi_peripheral::SSI1:
		g_pTheSSI1 = this;
		break;
	case ssi_peripheral::SSI2:
		g_pTheSSI2 = this;
		break;
	case ssi_peripheral::SSI3:
		g_pTheSSI3 = this;
		break;
	default:
		break;
	}
	SSIIntDisable(m_rSpecification.m_nSSIBase,
	SSI_TXFF | SSI_RXFF | SSI_RXTO | SSI_RXOR);
	SSIIntClear(m_rSpecification.m_nSSIBase,
	SSI_TXFF | SSI_RXFF | SSI_RXTO | SSI_RXOR);
	(*((volatile uint32_t *) m_rSpecification.m_nSSI_CR1_R)) |= SSI_CR1_EOT; /* switch tx interrupt to eot int */
	if (m_bNonBlocking) {
		SSIIntEnable(m_rSpecification.m_nSSIBase, SSI_TXFF); /* SSI_TXFF | SSI_RXFF | SSI_RXTO | SSI_RXOR  */
		MAP_IntEnable(m_rSpecification.m_nInterrupt);
	}
}
示例#5
0
//--------------------------------
void ssi_peripheral::Terminate() {
	switch (m_nDevice) {
	case ssi_peripheral::SSI0:
		g_pTheSSI0 = 0;
		break;
	case ssi_peripheral::SSI1:
		g_pTheSSI1 = 0;
		break;
	case ssi_peripheral::SSI2:
		g_pTheSSI2 = 0;
		break;
	case ssi_peripheral::SSI3:
		g_pTheSSI3 = 0;
		break;
	default:
		break;
	}
	SSIIntDisable(m_rSpecification.m_nSSIBase, SSI_TXFF); /* SSI_TXFF | SSI_RXFF | SSI_RXTO | SSI_RXOR  */
	MAP_IntDisable(m_rSpecification.m_nInterrupt);
	MAP_SSIDisable(m_rSpecification.m_nSSIBase);
}
示例#6
0
/*!
 *  @brief Function that cancels a SPI transfer. Will disable SPI and UDMA modules
 *         and allow standby.
 *
 *  @pre    SPICC26XXDMA_open() has to be called first.
 *          Calling context: Task
 *
 *  @param handle         The SPI_Handle for ongoing transaction.
 */
void SPICC26XXDMA_transferCancel(SPI_Handle handle) {
    SPICC26XX_Object          *object;
    SPI_Transaction           *msg;
    SPICC26XX_HWAttrs const   *hwAttrs;
    volatile tDMAControlTable *dmaControlTableEntry;
    unsigned int              key;

    /* Get the pointer to the object and hwAttrs */
    object = handle->object;
    hwAttrs = handle->hwAttrs;

    /* Check if a transfer is in progress */
    key = Hwi_disable();

    /* Check if there is an active transaction */
    if(!(object->currentTransaction)) {
        Hwi_restore(key);
        return;
    }
    Hwi_restore(key);

    /* Disable the SPI module */
    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));

    /* Disable and clear any pending interrupts */
    SSIIntDisable(hwAttrs->baseAddr, SSI_RXOR);
    SSIIntClear(hwAttrs->baseAddr, SSI_RXOR);

    /* Clear out the FIFO by resetting SPI module and re-initting */
    HapiResetPeripheral(hwAttrs->baseAddr == SSI0_BASE ? PRCM_PERIPH_SSI0 : PRCM_PERIPH_SSI1);
    SPICC26XXDMA_initHw(handle);

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

    /* Mark the transaction as failed if we didn't end up here due to a CSN deassertion */
    if (object->currentTransaction->status != SPI_TRANSFER_CSN_DEASSERT) {
        object->currentTransaction->status = SPI_TRANSFER_FAILED;
    }

    /* Disable the UDMA channels */
    UDMACC26XX_channelDisable(object->udmaHandle, (hwAttrs->rxChannelBitMask) | (hwAttrs->txChannelBitMask));

    /* Update the SPI_Transaction.count parameter */
    /* rxChannel always finishes after txChannel so remaining bytes of the rxChannel is used to update count */
    dmaControlTableEntry = (hwAttrs->baseAddr == SSI0_BASE ? &dmaRxControlTableEntry0 : &dmaRxControlTableEntry1);
    object->currentTransaction->count -= UDMACC26XX_GET_TRANSFER_SIZE(dmaControlTableEntry->ui32Control);

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

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

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

    /* Perform callback */
    object->transferCallbackFxn(handle, msg);

    /* Transaction was successfully canceled */
    return;
}
示例#7
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);
}