/**
 * Handle the SPI interrupt
 * Read frames until the RX FIFO is empty.  Write at most as many frames as were read.  This way,
 * it is unlikely that the RX FIFO will overflow.
 * @param[in] obj The SPI peripheral that generated the interrupt
 * @return
 */
uint32_t spi_irq_handler_asynch(spi_t *obj)
{
    uint32_t result = 0;
    if (obj->spi.dma_state == DMA_USAGE_ALLOCATED || obj->spi.dma_state == DMA_USAGE_TEMPORARY_ALLOCATED) {
        /* DMA implementation */
    } else {
        // Read frames until the RX FIFO is empty
        uint32_t r = spi_master_read_asynch(obj);
        // Write at most the same number of frames as were received
        spi_master_write_asynch(obj, r);

        // Check for SPI events
        uint32_t event = spi_event_check(obj);
        if (event) {
            result = event;
            if (event & SPI_EVENT_COMPLETE) {
                // adjust buffer positions
                obj->tx_buff.pos = obj->tx_buff.length;
                obj->rx_buff.pos = obj->rx_buff.length;
            }
        }
    }

    if (result) {
        spi_master_enable_interrupt(obj, false);
        DSPI_HAL_SetFlushFifoCmd(obj->spi.address,true,true);
    }
    return result;
}
void spi_master_transfer(spi_t *obj, void *tx, size_t tx_length, void *rx, size_t rx_length, uint32_t handler, uint32_t event, DMAUsage hint)
{
    if (hint != DMA_USAGE_NEVER && obj->spi.dma_state == DMA_USAGE_ALLOCATED) {
        // setup dma done, activate
    } else if (hint == DMA_USAGE_NEVER) {
        obj->spi.dma_state = DMA_USAGE_NEVER;
        spi_enable_event_flags(obj, event, true);
        spi_buffer_set(obj, tx, tx_length, rx, rx_length);
        // Clear the FIFO
        DSPI_HAL_SetFlushFifoCmd(obj->spi.address,true,true);
        // Enable the FIFO
        DSPI_HAL_SetFifoCmd(obj->spi.address, true, true);
        // Start writing to the SPI peripheral
        spi_master_write_asynch(obj,SPI_ASYNCH_INITIAL_TX);
        // use IRQ
        spi_master_enable_interrupt(obj, true);
        spi_enable_vector_interrupt(obj, handler, true);
    } else {
        // setup and activate
    }
}
Exemple #3
0
/*!
 * @brief DSPI master Polling.
 *
 * Thid function uses DSPI master to send an array to slave
 * and receive the array back from slave,
 * thencompare whether the two buffers are the same.
 */
int main(void)
{
    uint32_t i;
    uint32_t loopCount = 1;
    SPI_Type * dspiBaseAddr = (SPI_Type*)SPI0_BASE;
    uint32_t dspiSourceClock;
    uint32_t calculatedBaudRate;
    dspi_device_t masterDevice;
    dspi_command_config_t commandConfig = 
    {
        .isChipSelectContinuous = false,
        .whichCtar              = kDspiCtar0,
        .whichPcs               = kDspiPcs0,
        .clearTransferCount     = true,
        .isEndOfQueue           = false
    };

    // Init hardware
    hardware_init();
    // Init OSA layer, used in DSPI_DRV_MasterTransferBlocking.
    OSA_Init();
    // Call this function to initialize the console UART.  This function
    // enables the use of STDIO functions (printf, scanf, etc.)
    dbg_uart_init();
    // Print a note.
    printf("\r\n DSPI board to board polling example");
    printf("\r\n This example run on instance 0 ");
    printf("\r\n Be sure DSPI0-DSPI0 are connected ");

    // Configure SPI pins.
    configure_spi_pins(DSPI_MASTER_INSTANCE);

    // Enable DSPI clock.
    CLOCK_SYS_EnableSpiClock(DSPI_MASTER_INSTANCE);
    // Initialize the DSPI module registers to default value, which disables the module
    DSPI_HAL_Init(dspiBaseAddr);
    // Set to master mode.
    DSPI_HAL_SetMasterSlaveMode(dspiBaseAddr, kDspiMaster);
    // Configure for continuous SCK operation
    DSPI_HAL_SetContinuousSckCmd(dspiBaseAddr, false);
    // Configure for peripheral chip select polarity
    DSPI_HAL_SetPcsPolarityMode(dspiBaseAddr, kDspiPcs0, kDspiPcs_ActiveLow);
    // Disable FIFO operation.
    DSPI_HAL_SetFifoCmd(dspiBaseAddr, false, false);
    // Initialize the configurable delays: PCS-to-SCK, prescaler = 0, scaler = 1
    DSPI_HAL_SetDelay(dspiBaseAddr, kDspiCtar0, 0, 1, kDspiPcsToSck);
    // DSPI system enable
    DSPI_HAL_Enable(dspiBaseAddr);

    // Configure baudrate.
    masterDevice.dataBusConfig.bitsPerFrame = 8;
    masterDevice.dataBusConfig.clkPhase     = kDspiClockPhase_FirstEdge;
    masterDevice.dataBusConfig.clkPolarity  = kDspiClockPolarity_ActiveHigh;
    masterDevice.dataBusConfig.direction    = kDspiMsbFirst;

    DSPI_HAL_SetDataFormat(dspiBaseAddr, kDspiCtar0, &masterDevice.dataBusConfig);
    // Get DSPI source clock.
    dspiSourceClock = CLOCK_SYS_GetSpiFreq(DSPI_MASTER_INSTANCE);
    calculatedBaudRate = DSPI_HAL_SetBaudRate(dspiBaseAddr, kDspiCtar0, TRANSFER_BAUDRATE, dspiSourceClock);
    printf("\r\n Transfer at baudrate %lu \r\n", calculatedBaudRate);

    while(1)
    {
        // Initialize the transmit buffer.
        for (i = 0; i < TRANSFER_SIZE; i++)
        {
            sendBuffer[i] = i + loopCount;
        }

        // Print out transmit buffer.
        printf("\r\n Master transmit:");
        for (i = 0; i < TRANSFER_SIZE; i++)
        {
            // Print 16 numbers in a line.
            if ((i & 0x0F) == 0)
            {
                printf("\r\n    ");
            }
            printf(" %02X", sendBuffer[i]);
        }

        // Reset the receive buffer.
        for (i = 0; i < TRANSFER_SIZE; i++)
        {
            receiveBuffer[i] = 0;
        }

        // Restart the transfer by stop then start again, this will clear out the shift register
        DSPI_HAL_StopTransfer(dspiBaseAddr);
        // Flush the FIFOs
        DSPI_HAL_SetFlushFifoCmd(dspiBaseAddr, true, true);
        // Clear status flags that may have been set from previous transfers.
        DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiTxComplete);
        DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiEndOfQueue);
        DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiTxFifoUnderflow);
        DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiTxFifoFillRequest);
        DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiRxFifoOverflow);
        DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiRxFifoDrainRequest);
        // Clear the transfer count.
        DSPI_HAL_PresetTransferCount(dspiBaseAddr, 0);
        // Start the transfer process in the hardware
        DSPI_HAL_StartTransfer(dspiBaseAddr);
        // Send the data to slave.
        for (i = 0; i < TRANSFER_SIZE; i++)
        {
            // Write data to PUSHR
            DSPI_HAL_WriteDataMastermodeBlocking(dspiBaseAddr, &commandConfig, sendBuffer[i]);
            // Delay to wait slave is ready.
            OSA_TimeDelay(1);
        }

        // Delay to wait slave is ready.
        OSA_TimeDelay(10);

        // Restart the transfer by stop then start again, this will clear out the shift register
        DSPI_HAL_StopTransfer(dspiBaseAddr);
        // Flush the FIFOs
        DSPI_HAL_SetFlushFifoCmd(dspiBaseAddr, true, true);
        //Clear status flags that may have been set from previous transfers.
        DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiTxComplete);
        DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiEndOfQueue);
        DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiTxFifoUnderflow);
        DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiTxFifoFillRequest);
        DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiRxFifoOverflow);
        DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiRxFifoDrainRequest);
        // Clear the transfer count.
        DSPI_HAL_PresetTransferCount(dspiBaseAddr, 0);
        // Start the transfer process in the hardware
        DSPI_HAL_StartTransfer(dspiBaseAddr);
        // Receive the data from slave.
        for (i = 0; i < TRANSFER_SIZE; i++)
        {
            // Write command to PUSHR.
            DSPI_HAL_WriteDataMastermodeBlocking(dspiBaseAddr, &commandConfig, 0);
            // Check RFDR flag
            while (DSPI_HAL_GetStatusFlag(dspiBaseAddr, kDspiRxFifoDrainRequest)== false)
            {}
            // Read data from POPR
            receiveBuffer[i] = DSPI_HAL_ReadData(dspiBaseAddr);
            // Clear RFDR flag
            DSPI_HAL_ClearStatusFlag(dspiBaseAddr,kDspiRxFifoDrainRequest);
            // Delay to wait slave is ready.
            OSA_TimeDelay(1);
        }

        // Print out receive buffer.
        printf("\r\n Master receive:");
        for (i = 0; i < TRANSFER_SIZE; i++)
        {
            // Print 16 numbers in a line.
            if ((i & 0x0F) == 0)
            {
                printf("\r\n    ");
            }
            printf(" %02X", receiveBuffer[i]);
        }

        // Check receiveBuffer.
        for (i = 0; i < TRANSFER_SIZE; ++i)
        {
            if (receiveBuffer[i] != sendBuffer[i])
            {
                // Master received incorrect.
                printf("\r\n ERROR: master received incorrect ");
                return -1;
            }
        }

        printf("\r\n DSPI Master Sends/ Recevies Successfully");
        // Wait for press any key.
        printf("\r\n Press any key to run again");
        getchar();
        // Increase loop count to change transmit buffer.
        loopCount++;
    }
}
/*!
 * @brief Initiate (start) a transfer using DMA. This is not a public API as it is called from
 *  other driver functions
 */
static dspi_status_t DSPI_DRV_DmaMasterStartTransfer(uint32_t instance,
        const dspi_dma_device_t * device,
        const uint8_t * sendBuffer,
        uint8_t * receiveBuffer,
        size_t transferByteCount)
{
    /* instantiate local variable of type dspi_dma_master_state_t and point to global state */
    dspi_dma_master_state_t * dspiDmaState = (dspi_dma_master_state_t *)g_dspiStatePtr[instance];
    /* For temporarily storing DMA instance and channel */
    uint8_t transferSizeInBytes = 1U;

    uint32_t calculatedBaudRate;
    dspi_command_config_t command;  /* create an instance of the data command struct*/
    SPI_Type *base = g_dspiBase[instance];
    uint32_t txTransferByteCnt = 0;
    uint32_t rxTransferByteCnt = 0;

    /* Initialize s_wordToSend */
    s_wordToSend = 0;

    /* Check that we're not busy.*/
    if (dspiDmaState->isTransferInProgress)
    {
        return kStatus_DSPI_Busy;
    }

    /* Calculate the transfer size on bits/frame */
    if (dspiDmaState->bitsPerFrame <= 8)
    {
        transferSizeInBytes = 1U;
    }
    else if (dspiDmaState->bitsPerFrame <= 16)
    {
        transferSizeInBytes = 2U;
    }
    else
    {
        transferSizeInBytes = 4U;
    }

    /* Configure bus for this device. If NULL is passed, we assume the caller has
     * preconfigured the bus using DSPI_DRV_DmaMasterConfigureBus().
     * Do nothing for calculatedBaudRate. If the user wants to know the calculatedBaudRate
     * then they can call this function separately.
     */
    if (device)
    {
        DSPI_DRV_DmaMasterConfigureBus(instance, device, &calculatedBaudRate);
        dspiDmaState->bitsPerFrame = device->dataBusConfig.bitsPerFrame; /*update bits/frame*/
    }

    /* Check the transfer byte count. If bits/frame > 8, meaning 2 bytes, and if
     * the transfer byte count is an odd count we'll have to increase the TX transfer byte count
     * by one and assert a flag to indicate to the send functions that it will
     * need to handle an extra byte.
     * For receive, we actually round down the transfer count to the next lowest even number.
     * Then in the interrupt handler, we take care of geting this last byte.
     */
    if ((dspiDmaState->bitsPerFrame > 8) && (transferByteCount & 1UL))
    {
        dspiDmaState->extraByte = true;
        txTransferByteCnt = transferByteCount + 1U;  /* Increment to next even byte count */
        rxTransferByteCnt = transferByteCount & ~1U;  /* Decrement to next even byte count */
    }
    else
    {
        dspiDmaState->extraByte = false;
        txTransferByteCnt = transferByteCount;
        rxTransferByteCnt = transferByteCount;
    }
    /* Store the receiveBuffer pointer and receive byte count to the run-time state struct
     * for later use in the interrupt handler.
     */
    dspiDmaState->rxBuffer = (uint8_t *)receiveBuffer;
    dspiDmaState->rxTransferByteCnt = rxTransferByteCnt;

    /* Save information about the transfer for use by the ISR.*/
    dspiDmaState->isTransferInProgress = true;

    /* Reset the transfer counter to 0. Normally this is done via the PUSHR[CTCNT], but as we
     * are under DMA controller, we won't be able to change this bit dynamically after the
     * first word is transferred.
     */
    DSPI_HAL_PresetTransferCount(base, 0);

    /* flush the fifos*/
    DSPI_HAL_SetFlushFifoCmd(base, true, true);

    /* Clear status flags that may have been set from previous transfers */
    DSPI_HAL_ClearStatusFlag(base, kDspiTxComplete);
    DSPI_HAL_ClearStatusFlag(base, kDspiEndOfQueue);
    DSPI_HAL_ClearStatusFlag(base, kDspiTxFifoUnderflow);
    DSPI_HAL_ClearStatusFlag(base, kDspiTxFifoFillRequest);
    DSPI_HAL_ClearStatusFlag(base, kDspiRxFifoOverflow);
    DSPI_HAL_ClearStatusFlag(base, kDspiRxFifoDrainRequest);

    /************************************************************************************
     * Set up the RX DMA channel Transfer Control Descriptor (TCD)
     * Do this before filling the TX FIFO.
     * Note, if there is no remaining receive count, then bypass RX DMA set up.
     * This means we only have one byte to read of a 16-bit data word and will read this
     * in the complete transfer function.
     ***********************************************************************************/
    /* If a receive buffer is used and if rxTransferByteCnt > 0 */
    if (rxTransferByteCnt)
    {
        if (!receiveBuffer)
        {
            /* Set up this channel's control which includes enabling the DMA interrupt */
            DMA_DRV_ConfigTransfer(&dspiDmaState->dmaRxChannel,
                                   kDmaPeripheralToPeripheral,
                                   transferSizeInBytes,
                                   DSPI_HAL_GetPoprRegAddr(base), /* src is data register */
                                   (uint32_t)(&s_rxBuffIfNull), /* dest is temporary location */
                                   (uint32_t)(rxTransferByteCnt));
        }
        else
        {
            /* Set up this channel's control which includes enabling the DMA interrupt */
            DMA_DRV_ConfigTransfer(&dspiDmaState->dmaRxChannel,
                                   kDmaPeripheralToMemory,
                                   transferSizeInBytes,
                                   DSPI_HAL_GetPoprRegAddr(base), /* src is data register */
                                   (uint32_t)(receiveBuffer), /* dest is rx buffer */
                                   (uint32_t)(rxTransferByteCnt));

            /* Destination size is only 1 byte */
            DMA_DRV_SetDestTransferSize(&dspiDmaState->dmaRxChannel, 1U);
        }

        /* Enable the DMA peripheral request */
        DMA_DRV_StartChannel(&dspiDmaState->dmaRxChannel);
    }
    else if (dspiDmaState->extraByte)
    {
        /* Need to receive only one frame - extra byte by calling Rx callback function*/
        DSPI_DRV_DmaRxCallback((void *)instance, kDmaIdle);
    }

    /************************************************************************************
     * Set up the Last Command/data Word Intermediate Buffer and fill up the TX FIFO.
     ***********************************************************************************/
    /* Before sending the data, we first need to initialize the data command struct
     * Configure the data command attributes for the desired PCS, CTAR, and continuous PCS
     * which are derived from the run-time state struct
     */
    command.whichPcs = dspiDmaState->whichPcs;
    command.whichCtar = dspiDmaState->whichCtar;
    command.clearTransferCount = false; /* don't clear the transfer count */

    /************************************************************************
     * Next, set up the Last Command/data Word Intermediate Buffer before
     * filling up the TX FIFO
     * Create a 32-bit word with the final 16-bit command settings. This means
     * that EOQ = 1 and CONT = 0.
     * This 32-bit word will also be initialized with the final data byte/word
     * from the send source buffer and then the entire 32-bit word will be
     * transferred to the DSPI PUSHR.
     ************************************************************************/
    /* Declare a variable for storing the last send data (either 8- or 16-bit) */
    uint32_t lastWord = 0;

    /* If a send buffer was provided, the word comes from there. Otherwise we just send
     * a zero (initialized above).
     */
    if (sendBuffer)
    {
        /* Store the last byte from the send buffer */
        if (dspiDmaState->bitsPerFrame <= 8)
        {
            lastWord = sendBuffer[txTransferByteCnt-1]; /* Last byte */
        }
        /* Store the last two bytes the send buffer */
        else
        {
            /* If 16-bit transfers and odd transfer byte count then an extra byte was added
             * to the transfer byte count, but we cannot access more of the send buffer
             */
            if(!dspiDmaState->extraByte)
            {
                lastWord = sendBuffer[txTransferByteCnt-1] ; /* Save off the last byte */
                lastWord = lastWord << 8U; /* Shift to MSB (separate step due to MISHA) */
            }
            lastWord |= sendBuffer[txTransferByteCnt-2]; /* OR with next to last byte */
        }
    }

    /* Now, build the last command/data word intermediate buffer */
    command.isChipSelectContinuous = false; /* Always clear CONT for last data word */
    command.isEndOfQueue = true; /* Set EOQ for last data word */
    s_lastCmdData = DSPI_HAL_GetFormattedCommand(base, &command) | lastWord;
    /************************************************************************
     * Begin TX DMA channels transfer control descriptor set up.
     * 1. First, set up intermediate buffers which contain 16-bit commands.
     * 2. Set up the DMA Software Transfer Control Descriptors (STCD) for various
     *    scenarios:
     *    - Channel for intermediate buffer to TX FIFO
     *    - Channel for source buffer to intermediate buffer
     *    - STCD for scatter/gather for end of previous channel to replace
     *      intermediate buffer with last-command buffer.
     ************************************************************************/

    /************************************************************************
     * Intermediate Buffer
     * Create a 32-bit word with the 16-bit command settings. Data from
     * the send source buffer will be transferred here and then the entire
     * 32-bit word will be transferred to the DSPI PUSHR.
     * This buffer will be preloaded with the next data word in the send buffer
     ************************************************************************/
    /* restore the isChipSelectContinuous setting to the original value as it was cleared above */
    command.isChipSelectContinuous = dspiDmaState->isChipSelectContinuous;
    command.isEndOfQueue = false; /* Clear End of Queue (previously set for last cmd/data word)*/
    s_cmdData = DSPI_HAL_GetFormattedCommand(base, &command);

    /* Place the next data from the send buffer into the intermediate buffer (preload it)
     * based on whether it is one byte or two.
     */
    if (dspiDmaState->bitsPerFrame <= 8)
    {
        /* If a send buffer was provided, the word comes from there. Otherwise we just send
         * a zero (initialized above).
         */
        if (sendBuffer)
        {
            s_wordToSend = *sendBuffer;  /* queue up the next data */
            ++sendBuffer; /* increment to next data word*/
        }
        --txTransferByteCnt; /* decrement txTransferByteCnt*/
    }
    else
    {
        /* If a send buffer was provided, the word comes from there. Otherwise we just send
         * a zero (initialized above).
         */
        if (sendBuffer)
        {
            s_wordToSend = *sendBuffer;
            ++sendBuffer; /* increment to next data byte */

            /* Note, if the extraByte flag is set and we're down to the last two bytes we can still
             * do this even though we're going past the sendBuffer size. We're just reading data we
             * don't care about anyways since it is dummy data to make up for the last byte.
             */
            s_wordToSend |= (unsigned)(*sendBuffer) << 8U;
            ++sendBuffer; /* increment to next data byte */

        }
        txTransferByteCnt -= 2;  /* decrement txTransferByteCnt by 2 bytes */
    }

    s_cmdData |= s_wordToSend; /* write s_wordToSend to intermediate buffer */

    /* For Tx, DSPI need two DMA channel, one for calculate the command and data into one value
     * (dmaTxCmdChannel), and another for push the value into DSPI PUSHR register (dmaTxDataChannel).
     * The dmaTxCmdChannel DMA channel will be triggered by DSPI Tx FIFO, and the dmaTxDataChannel
     * DMA channel will be linked to calculate DMA channel and triggered by this channel also.
     */

    /* If the transfer size is less than size of one frame, only transmit the last byte that calculated */
    if (!txTransferByteCnt)
    {
        DMA_DRV_ConfigTransfer(&dspiDmaState->dmaTxDataChannel, kDmaMemoryToPeripheral,
                               4u, (uint32_t)(&s_lastCmdData),
                               DSPI_HAL_GetMasterPushrRegAddr(base), 4u);
        /* Register callback for last byte transmitting */
        DMA_DRV_RegisterCallback(&dspiDmaState->dmaTxDataChannel, DSPI_DRV_DmaTxLastCallback, (void *)instance);
    }
    else
    {
        /* Config DMA to copy data from generated cmd data to FIFO */
        if (dspiDmaState->bitsPerFrame <= 8)
        {
            DMA_DRV_ConfigTransfer(&dspiDmaState->dmaTxDataChannel, kDmaPeripheralToPeripheral,
                                   4u, (uint32_t)(&s_cmdData),
                                   DSPI_HAL_GetMasterPushrRegAddr(base),
                                   (uint32_t)((txTransferByteCnt) * 4));
        }
        else
        {
            DMA_DRV_ConfigTransfer(&dspiDmaState->dmaTxDataChannel, kDmaPeripheralToPeripheral,
                                   4u, (uint32_t)(&s_cmdData),
                                   DSPI_HAL_GetMasterPushrRegAddr(base),
                                   (uint32_t)((txTransferByteCnt) * 2));
        }
        /* Register Tx callback function */
        DMA_DRV_RegisterCallback(&dspiDmaState->dmaTxDataChannel, DSPI_DRV_DmaTxCallback, (void *)instance);

        /* Config dmaTxCmdChannel channel if send buffer is provided */
        if (sendBuffer)
        {
            dma_channel_link_config_t config;
            DMA_DRV_ConfigTransfer(&dspiDmaState->dmaTxCmdChannel, kDmaMemoryToPeripheral,
                                   1u, (uint32_t)(sendBuffer),
                                   (uint32_t)(&s_cmdData),
                                   (uint32_t)(txTransferByteCnt - transferSizeInBytes));
            if (dspiDmaState->bitsPerFrame > 8)
            {
                DMA_DRV_SetDestTransferSize(&dspiDmaState->dmaTxCmdChannel, 2U);
            }

            /* Link dmaTxCmdChannel after dmaTxDataChannel */
            config.channel1 = dspiDmaState->dmaTxCmdChannel.channel;
            config.channel2 = 0;
            config.linkType = kDmaChannelLinkChan1;
            DMA_DRV_ConfigChanLink(&dspiDmaState->dmaTxDataChannel, &config);
            /* start channel */
            DMA_DRV_StartChannel(&dspiDmaState->dmaTxCmdChannel);
        }
    }

    /* Register callback */
    DMA_DRV_RegisterCallback(&dspiDmaState->dmaRxChannel, DSPI_DRV_DmaRxCallback, (void *)instance);

    /* Enable the Receive FIFO Drain DMA Request */
    DSPI_HAL_SetRxFifoDrainDmaIntMode(base, kDspiGenerateDmaReq, true);

    /* Enable TFFF DMA request */
    DSPI_HAL_SetTxFifoFillDmaIntMode(base, kDspiGenerateDmaReq, true);

    /* Enable the DMA peripheral request */
    DMA_DRV_StartChannel(&dspiDmaState->dmaTxDataChannel);

    return kStatus_DSPI_Success;
}
Exemple #5
0
/*!
 * @brief DSPI slave Polling.
 *
 * This function sends back received buffer from master through DSPI interface.
 */
int main(void)
{
    uint32_t i;
    SPI_Type * dspiBaseAddr = (SPI_Type*)SPI0_BASE;
    dspi_slave_user_config_t slaveConfig;

    // Init hardware
    hardware_init();
    // Init OSA layer, used in DSPI_DRV_MasterTransferBlocking.
    OSA_Init();
    // Call this function to initialize the console UART.  This function
    // enables the use of STDIO functions (printf, scanf, etc.)
    dbg_uart_init();
    // Configure SPI pins.
    configure_spi_pins(DSPI_SLAVE_INSTANCE);

    // Print a note.
    printf("\r\n DSPI board to board polling example");
    printf("\r\n This example run on instance 0 ");
    printf("\r\n Be sure DSPI0-DSPI0 are connected ");

    // Enable clock for DSPI
    CLOCK_SYS_EnableSpiClock(DSPI_SLAVE_INSTANCE);
    // Reset the DSPI module, which also disables the DSPI module
    DSPI_HAL_Init(dspiBaseAddr);
    // Set to slave mode.
    DSPI_HAL_SetMasterSlaveMode(dspiBaseAddr, kDspiSlave);
    // Set data format
    slaveConfig.dataConfig.clkPhase     = kDspiClockPhase_FirstEdge;
    slaveConfig.dataConfig.clkPolarity  = kDspiClockPolarity_ActiveHigh;
    slaveConfig.dataConfig.bitsPerFrame = 8;
    DSPI_HAL_SetDataFormat(dspiBaseAddr, kDspiCtar0, &(slaveConfig.dataConfig));
    // DSPI system enable
    DSPI_HAL_Enable(dspiBaseAddr);
    // Disable FIFO operation.
    DSPI_HAL_SetFifoCmd(dspiBaseAddr, false, false);

    while(1)
    {
         printf("\r\n Slave example is running...");
        // Reset the receive buffer.
        for (i = 0; i < TRANSFER_SIZE; i++)
        {
            receiveBuffer[i] = 0;
        }

        // Restart the transfer by stop then start again, this will clear out the shift register
        DSPI_HAL_StopTransfer(dspiBaseAddr);
        // Flush the FIFOs
        DSPI_HAL_SetFlushFifoCmd(dspiBaseAddr, true, true);
        // Clear status flags that may have been set from previous transfers
        DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiTxComplete);
        DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiEndOfQueue);
        DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiTxFifoUnderflow);
        DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiTxFifoFillRequest);
        DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiRxFifoOverflow);
        DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiRxFifoDrainRequest);
        // Clear the transfer count
        DSPI_HAL_PresetTransferCount(dspiBaseAddr, 0);
        // Start the transfer process in the hardware
        DSPI_HAL_StartTransfer(dspiBaseAddr);
        for (i = 0; i < TRANSFER_SIZE; i++)
        {
                // Check RFDR flag
                while (DSPI_HAL_GetStatusFlag(dspiBaseAddr, kDspiRxFifoDrainRequest)== false)
                {}
                // Read data from POPR
                receiveBuffer[i] = DSPI_HAL_ReadData(dspiBaseAddr);
                // Clear RFDR flag
                DSPI_HAL_ClearStatusFlag(dspiBaseAddr,kDspiRxFifoDrainRequest);
        }

        // Restart the transfer by stop then start again, this will clear out the shift register
        DSPI_HAL_StopTransfer(dspiBaseAddr);
        // Flush the FIFOs
        DSPI_HAL_SetFlushFifoCmd(dspiBaseAddr, true, true);
        // Clear status flags that may have been set from previous transfers
        DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiTxComplete);
        DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiEndOfQueue);
        DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiTxFifoUnderflow);
        DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiTxFifoFillRequest);
        DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiRxFifoOverflow);
        DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiRxFifoDrainRequest);
        // Clear the transfer count
        DSPI_HAL_PresetTransferCount(dspiBaseAddr, 0);
        // Start the transfer process in the hardware
        DSPI_HAL_StartTransfer(dspiBaseAddr);
        // Send the data to slave.
        for (i = 0; i < TRANSFER_SIZE; i++)
        {
            // Write data to PUSHR
            DSPI_HAL_WriteDataSlavemodeBlocking(dspiBaseAddr, receiveBuffer[i]);
        }

        // Print out receive buffer.
        printf("\r\n Slave receive:");
        for (i = 0; i < TRANSFER_SIZE; i++)
        {
            // Print 16 numbers in a line.
            if ((i & 0x0F) == 0)
            {
                printf("\r\n    ");
            }
            printf(" %02X", receiveBuffer[i]);
        }
    }
}
/*!
 * @brief Initiate (start) a transfer. This is not a public API as it is called from other
 *  driver functions
 */
static dspi_status_t DSPI_DRV_MasterStartTransfer(uint32_t instance,
                                                  const dspi_device_t * device)
{
    /* instantiate local variable of type dspi_master_state_t and point to global state */
    dspi_master_state_t * dspiState = (dspi_master_state_t *)g_dspiStatePtr[instance];
    SPI_Type *base = g_dspiBase[instance];
    uint32_t calculatedBaudRate;

    /* Check that we're not busy.*/
    if (dspiState->isTransferInProgress)
    {
        return kStatus_DSPI_Busy;
    }

    /* Configure bus for this device. If NULL is passed, we assume the caller has
     * preconfigured the bus using DSPI_DRV_MasterConfigureBus().
     * Do nothing for calculatedBaudRate. If the user wants to know the calculatedBaudRate
     * then they can call this function separately.
     */
    if (device)
    {
        DSPI_DRV_MasterConfigureBus(instance, device, &calculatedBaudRate);
        dspiState->bitsPerFrame = device->dataBusConfig.bitsPerFrame;/*update dspiState bits/frame*/
    }

    /* Check the transfer byte count. If bits/frame > 8, meaning 2 bytes and if
     * the transfer byte count is an odd count we'll have to increase the transfer byte count
     * by one and assert a flag to indicate to the send and receive functions that it will
     * need to handle an extra byte.
     */
    if ((dspiState->bitsPerFrame > 8) && (dspiState->remainingSendByteCount & 1UL))
    {
        dspiState->remainingSendByteCount += 1;
        dspiState->remainingReceiveByteCount += 1;
        dspiState->extraByte = true;
    }
    else
    {
        dspiState->extraByte = false;
    }


    /* Save information about the transfer for use by the ISR.*/
    dspiState->isTransferInProgress = true;

    /* Restart the transfer by stop then start again, this will clear out the shift register */
    DSPI_HAL_StopTransfer(base);

    /* flush the fifos*/
    DSPI_HAL_SetFlushFifoCmd(base, true, true);

    /* Clear status flags that may have been set from previous transfers */
    DSPI_HAL_ClearStatusFlag(base, kDspiTxComplete);
    DSPI_HAL_ClearStatusFlag(base, kDspiEndOfQueue);
    DSPI_HAL_ClearStatusFlag(base, kDspiTxFifoUnderflow);
    DSPI_HAL_ClearStatusFlag(base, kDspiTxFifoFillRequest);
    DSPI_HAL_ClearStatusFlag(base, kDspiRxFifoOverflow);
    DSPI_HAL_ClearStatusFlag(base, kDspiRxFifoDrainRequest);

    /* Clear the transfer count */
    DSPI_HAL_PresetTransferCount(base, 0);

    /* Start the transfer, make sure to do this before filling the FIFO */
    DSPI_HAL_StartTransfer(base);

    /* Fill up the DSPI FIFO (even if one word deep, data still written to data buffer) */
    DSPI_DRV_MasterFillupTxFifo(instance);

    /* RX FIFO Drain request: RFDF_RE to enable RFDF interrupt
     * Since SPI is a synchronous interface, we only need to enable the RX interrupt.
     * The IRQ handler will get the status of RX and TX interrupt flags.
     */
    DSPI_HAL_SetRxFifoDrainDmaIntMode(base, kDspiGenerateIntReq, true);

    return kStatus_DSPI_Success;
}
/**
 * Abort an SPI transfer
 * This is a helper function for event handling. When any of the events listed occurs, the HAL will abort any ongoing
 * transfers
 * @param[in] obj The SPI peripheral to stop
 */
void spi_abort_asynch(spi_t *obj)
{
    spi_enable_vector_interrupt(obj, 0, false);
    DSPI_HAL_SetFlushFifoCmd(obj->spi.address,true,true);
    DSPI_HAL_SetFifoCmd(obj->spi.address, false, false);
}
uint16_t SpiInOut(Spi_t *obj, uint16_t outData)
{
    uint16_t data = 0x00;

    if ((obj == NULL) || (obj->Spi) == NULL) {
        while (1)
            ;
    }

    if (obj->isSlave) {

    } else {
        dspi_command_config_t
        commandConfig =
        {
            .isChipSelectContinuous = false,
            .whichCtar = kDspiCtar0,
            .whichPcs = kDspiPcs0,
            .clearTransferCount = true,
            .isEndOfQueue = false
        };
        if (outData != 0x00) {
            // Restart the transfer by stop then start again, this will clear out the shift register
            DSPI_HAL_StopTransfer(obj->Spi);
            // Flush the FIFOs
            DSPI_HAL_SetFlushFifoCmd(obj->Spi, true, true);
            // Clear status flags that may have been set from previous transfers.
            DSPI_HAL_ClearStatusFlag(obj->Spi, kDspiTxComplete);
            DSPI_HAL_ClearStatusFlag(obj->Spi, kDspiEndOfQueue);
            DSPI_HAL_ClearStatusFlag(obj->Spi, kDspiTxFifoUnderflow);
            DSPI_HAL_ClearStatusFlag(obj->Spi, kDspiTxFifoFillRequest);
            DSPI_HAL_ClearStatusFlag(obj->Spi, kDspiRxFifoOverflow);
            DSPI_HAL_ClearStatusFlag(obj->Spi, kDspiRxFifoDrainRequest);
            // Clear the transfer count.
            DSPI_HAL_PresetTransferCount(obj->Spi, 0);
            // Start the transfer process in the hardware
            DSPI_HAL_StartTransfer(obj->Spi);
            // Send the data to slave.
            // Write data to PUSHR
            DSPI_HAL_WriteDataMastermode(obj->Spi, &commandConfig, outData);
        } else {
            // Restart the transfer by stop then start again, this will clear out the shift register
            DSPI_HAL_StopTransfer(obj->Spi);
            // Flush the FIFOs
            DSPI_HAL_SetFlushFifoCmd(obj->Spi, true, true);
            //Clear status flags that may have been set from previous transfers.
            DSPI_HAL_ClearStatusFlag(obj->Spi, kDspiTxComplete);
            DSPI_HAL_ClearStatusFlag(obj->Spi, kDspiEndOfQueue);
            DSPI_HAL_ClearStatusFlag(obj->Spi, kDspiTxFifoUnderflow);
            DSPI_HAL_ClearStatusFlag(obj->Spi, kDspiTxFifoFillRequest);
            DSPI_HAL_ClearStatusFlag(obj->Spi, kDspiRxFifoOverflow);
            DSPI_HAL_ClearStatusFlag(obj->Spi, kDspiRxFifoDrainRequest);
            // Clear the transfer count.
            DSPI_HAL_PresetTransferCount(obj->Spi, 0);
            // Start the transfer process in the hardware
            DSPI_HAL_StartTransfer(obj->Spi);
            // Write command to PUSHR.
            DSPI_HAL_WriteDataMastermode(obj->Spi, &commandConfig, 0);
            // Check RFDR flag
            while (DSPI_HAL_GetStatusFlag(obj->Spi, kDspiRxFifoDrainRequest) == false) {
            }
            // Read data from POPR
            data = DSPI_HAL_ReadData(obj->Spi);
            // Clear RFDR flag
            DSPI_HAL_ClearStatusFlag(obj->Spi, kDspiRxFifoDrainRequest);
        }
    }
    return data;
}