static uint32_t spi_event_check(spi_t *obj) { uint32_t event = 0; // Get the TX FIFO underflow flag uint8_t U = DSPI_HAL_GetStatusFlag(obj->spi.address,kDspiTxFifoUnderflow); // Get the RX FIFO overflow flag uint8_t O = DSPI_HAL_GetStatusFlag(obj->spi.address,kDspiRxFifoOverflow); // Get the RX FIFO drain request flag uint8_t TXCTR = DSPI_HAL_GetFifoCountOrPtr(obj->spi.address, kDspiTxFifoCounter); // Get the number of words in the RX FIFO uint8_t RXCTR = DSPI_HAL_GetFifoCountOrPtr(obj->spi.address, kDspiRxFifoCounter); // The transfer is only complete if the TX buffer has been sent, the RX buffer has been filled, and there are no // values in the TX FIFO or RX FIFO if ((RXCTR == 0) && (TXCTR == 0) && (obj->rx_buff.pos >= obj->rx_buff.length) && (obj->tx_buff.pos >= obj->tx_buff.length)) { if (obj->spi.event & SPI_EVENT_COMPLETE) { event |= SPI_EVENT_COMPLETE; } event |= SPI_EVENT_INTERNAL_TRANSFER_COMPLETE; // process another transactions } // Signal an RX overflow event if ((obj->spi.event & SPI_EVENT_RX_OVERFLOW) && O) { event |= SPI_EVENT_RX_OVERFLOW; } // Signal a TX underflow event if ((obj->spi.event & SPI_EVENT_ERROR) && U) { event |= SPI_EVENT_ERROR; } return event; }
/*FUNCTION********************************************************************** * * Function Name : DSPI_DRV_MasterIRQHandler * Description : Interrupt handler for DSPI master mode. * This handler uses the buffers stored in the dspi_master_state_t structs to transfer data. * This is not a public API as it is called whenever an interrupt occurs. * *END**************************************************************************/ void DSPI_DRV_MasterIRQHandler(uint32_t instance) { /* 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]; /* RECEIVE IRQ handler: Check read buffer only if there are remaining bytes to read. */ if(dspiState->remainingReceiveByteCount) { /* Check read buffer.*/ uint16_t wordReceived; /* Maximum supported data bit length in master mode is 16-bits */ /* If bits/frame is greater than one byte */ if (dspiState->bitsPerFrame > 8) { while (DSPI_HAL_GetStatusFlag(base, kDspiRxFifoDrainRequest)) { wordReceived = DSPI_HAL_ReadData(base); /* clear the rx fifo drain request, needed for non-DMA applications as this flag * will remain set even if the rx fifo is empty. By manually clearing this flag, it * either remain clear if no more data is in the fifo, or it will set if there is * more data in the fifo. */ DSPI_HAL_ClearStatusFlag(base, kDspiRxFifoDrainRequest); /* Store read bytes into rx buffer only if a buffer pointer was provided */ if(dspiState->receiveBuffer) { /* For the last word received, if there is an extra byte due to the odd transfer * byte count, only save the the last byte and discard the upper byte */ if ((dspiState->remainingReceiveByteCount == 2) && (dspiState->extraByte)) { *dspiState->receiveBuffer = wordReceived; /* Write first data byte */ } else { *dspiState->receiveBuffer = wordReceived; /* Write first data byte */ ++dspiState->receiveBuffer; /* increment to next data byte */ *dspiState->receiveBuffer = wordReceived >> 8; /* Write second data byte */ ++dspiState->receiveBuffer; /* increment to next data byte */ } } dspiState->remainingReceiveByteCount -= 2; if (dspiState->remainingReceiveByteCount == 0) { break; } } /* End of RX FIFO drain while loop */ } /* Optimized for bits/frame less than or equal to one byte. */ else { while (DSPI_HAL_GetStatusFlag(base, kDspiRxFifoDrainRequest))
/** * Read SPI frames out of the RX FIFO * Continues reading frames out of the RX FIFO until the following condition is met: * o There are no more frames in the FIFO * OR BOTH OF: * o At least as many frames as the TX buffer have been received * o At least as many frames as the RX buffer have been received * This way, RX overflows are not generated when the TX buffer size exceeds the RX buffer size * @param[in] obj The SPI object on which to operate * @return Returns the number of frames extracted from the RX FIFO */ static uint32_t spi_master_read_asynch(spi_t *obj) { uint32_t ndata = 0; // Calculate the maximum number of frames to receive uint32_t txRemaining = obj->tx_buff.length - min(obj->rx_buff.pos, obj->tx_buff.length); uint32_t rxRemaining = obj->rx_buff.length - min(obj->rx_buff.pos, obj->rx_buff.length); uint32_t maxRx = max(txRemaining, rxRemaining); // Receive frames until the maximum is reached or the RX FIFO is empty while ((ndata < maxRx) && DSPI_HAL_GetStatusFlag(obj->spi.address, kDspiRxFifoDrainRequest)) { spi_buffer_rx_read(obj); ndata++; } // Return the number of frames received return ndata; }
/** * Send words from the SPI TX buffer until the send limit is reached or the TX FIFO is full * TxLimit is provided to ensure that the number of SPI frames (words) in flight can be managed. * @param[in] obj The SPI object on which to operate * @param[in] TxLimit The maximum number of words to send * @return The number of SPI frames that have been transfered */ static uint32_t spi_master_write_asynch(spi_t *obj, uint32_t TxLimit) { uint32_t ndata = 0; // Determine the number of frames to send uint32_t txRemaining = obj->tx_buff.length - min(obj->tx_buff.pos, obj->tx_buff.length); uint32_t rxRemaining = obj->rx_buff.length - min(obj->tx_buff.pos, obj->rx_buff.length); uint32_t maxTx = max(txRemaining, rxRemaining); maxTx = min(maxTx, TxLimit); // Send words until the FIFO is full or the send limit is reached while ((ndata < maxTx) && DSPI_HAL_GetStatusFlag(obj->spi.address, kDspiTxFifoFillRequest)) { spi_buffer_tx_write(obj); ndata++; } //Return the number of frames that have been sent return ndata; }
/*! * @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 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 Fill up the TX FIFO with data. * This function fills up the TX FIFO with initial data for start of transfers where it will * first clear the transfer count. Otherwise, if the TX FIFO fill is part of an ongoing transfer * then do not clear the transfer count. The param "isInitialData" is used to determine if this * is an initial data fill. * This is not a public API as it is called from other driver functions. */ static void DSPI_DRV_MasterFillupTxFifo(uint32_t instance) { /* 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]; dspi_command_config_t command; /* create an instance of the data command struct*/ uint32_t cmd; /* Command word to be OR'd with data word */ uint16_t wordToSend = 0; /* Declare variables for storing volatile data later in the code */ uint32_t remainingReceiveByteCount, remainingSendByteCount; /* 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 = dspiState->whichPcs; command.whichCtar = dspiState->whichCtar; command.isChipSelectContinuous = dspiState->isChipSelectContinuous; command.isEndOfQueue = 0; command.clearTransferCount = 0; /* "Build" the command word. Only do this once since the commad word members don't * change until the last word sent (which is when the end of queue flag gets set). */ cmd = DSPI_HAL_GetFormattedCommand(base, &command); /* Store the DSPI state struct volatile member variables into temporary * non-volatile variables to allow for MISRA compliant calculations */ remainingSendByteCount = dspiState->remainingSendByteCount; remainingReceiveByteCount = dspiState->remainingReceiveByteCount; /* Architectural note: When developing the TX FIFO fill functionality, it was found that to * achieve more efficient run-time performance, it was better to first check the bits/frame * setting and then proceed with the FIFO fill management process, rather than to clutter the * FIFO fill process with continual checks of the bits/frame setting. */ /* If bits/frame is greater than one byte */ if (dspiState->bitsPerFrame > 8) { /* Fill the fifo until it is full or until the send word count is 0 or until the difference * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. * The reason for checking the difference is to ensure we only send as much as the * RX FIFO can receive. * For this case where bitsPerFrame > 8, each entry in the FIFO contains 2 bytes of the * send data, hence the difference between the remainingReceiveByteCount and * remainingSendByteCount must be divided by 2 to convert this difference into a * 16-bit (2 byte) value. */ while((DSPI_HAL_GetStatusFlag(base, kDspiTxFifoFillRequest) == 1) && ((remainingReceiveByteCount - remainingSendByteCount)/2 < g_dspiFifoSize[instance])) { /* On the last word to be sent, set the end of queue flag in the data command struct * and ensure that the CONT bit in the PUSHR is also cleared even if it was cleared to * begin with. If CONT is set it means continuous chip select operation and to ensure * the chip select is de-asserted, this bit must be cleared on the last data word. */ if (dspiState->remainingSendByteCount == 2) { command.isEndOfQueue = 1; command.isChipSelectContinuous = 0; cmd = DSPI_HAL_GetFormattedCommand(base, &command); /* If there is an extra byte to send due to an odd byte count, prepare the final * wordToSend here */ if (dspiState->sendBuffer) { if (dspiState->extraByte) { wordToSend = *(dspiState->sendBuffer); } else { wordToSend = *(dspiState->sendBuffer); ++dspiState->sendBuffer; /* increment to next data byte */ wordToSend |= (unsigned)(*(dspiState->sendBuffer)) << 8U; } } } /* For all words except the last word */ else { /* If a send buffer was provided, the word comes from there. Otherwise we just send * a zero (initialized above). */ if (dspiState->sendBuffer) { wordToSend = *(dspiState->sendBuffer); ++dspiState->sendBuffer; /* increment to next data byte */ wordToSend |= (unsigned)(*(dspiState->sendBuffer)) << 8U; ++dspiState->sendBuffer; /* increment to next data byte */ } } DSPI_HAL_WriteCmdDataMastermode(base, cmd|wordToSend); /* Try to clear the TFFF; if the TX FIFO is full this will clear */ DSPI_HAL_ClearStatusFlag(base, kDspiTxFifoFillRequest); dspiState->remainingSendByteCount -= 2; /* decrement remainingSendByteCount by 2 */ /* exit loop if send count is zero, else update local variables for next loop */ if (dspiState->remainingSendByteCount == 0) { break; } else { /* Store the DSPI state struct volatile member variables into temporary * non-volatile variables to allow for MISRA compliant calculations */ remainingSendByteCount = dspiState->remainingSendByteCount; } } /* End of TX FIFO fill while loop */ } /* Optimized for bits/frame less than or equal to one byte. */ else { /* Fill the fifo until it is full or until the send word count is 0 or until the difference * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. * The reason for checking the difference is to ensure we only send as much as the * RX FIFO can receive. */ while((DSPI_HAL_GetStatusFlag(base, kDspiTxFifoFillRequest) == 1) && ((remainingReceiveByteCount - remainingSendByteCount) < g_dspiFifoSize[instance])) { /* On the last word to be sent, set the end of queue flag in the data command struct * and ensure that the CONT bit in the PUSHR is also cleared even if it was cleared to * begin with. If CONT is set it means continuous chip select operation and to ensure * the chip select is de-asserted, this bit must be cleared on the last data word. */ if (dspiState->remainingSendByteCount == 1) { command.isEndOfQueue = 1; command.isChipSelectContinuous = 0; cmd = DSPI_HAL_GetFormattedCommand(base, &command); } /* If a send buffer was provided, the word comes from there. Otherwise we just send * a zero (initialized above). */ if (dspiState->sendBuffer) { wordToSend = *(dspiState->sendBuffer); ++dspiState->sendBuffer; /* increment to next data word*/ } DSPI_HAL_WriteCmdDataMastermode(base, cmd|wordToSend); /* Try to clear the TFFF; if the TX FIFO is full this will clear */ DSPI_HAL_ClearStatusFlag(base, kDspiTxFifoFillRequest); --dspiState->remainingSendByteCount; /* decrement remainingSendByteCount*/ /* exit loop if send count is zero, else update local variables for next loop */ if (dspiState->remainingSendByteCount == 0) { break; } else { /* Store the DSPI state struct volatile member variables into temporary * non-volatile variables to allow for MISRA compliant calculations */ remainingSendByteCount = dspiState->remainingSendByteCount; } } /* End of TX FIFO fill while loop */ } }
static inline int spi_readable(spi_t * obj) { return DSPI_HAL_GetStatusFlag(obj->spi.address, kDspiRxFifoDrainRequest); }
static inline int spi_writeable(spi_t * obj) { return DSPI_HAL_GetStatusFlag(obj->spi.address, kDspiTxFifoFillRequest); }
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; }
/*FUNCTION********************************************************************** * * Function Name : DSPI_DRV_SlaveIRQHandler * Description : DSPI Slave Generic IRQ handler. * * This handler check errors of driver and it puts data into Tx FIFO, gets data * from Rx FIFO whenever data transmitting/received. * *END**************************************************************************/ void DSPI_DRV_SlaveIRQHandler(uint32_t instance) { SPI_Type *base = g_dspiBase[instance]; dspi_slave_state_t *dspiState = (dspi_slave_state_t *)g_dspiStatePtr[instance]; uint8_t nBytes; /* Calculate number of bytes in a frame */ nBytes = dspiState->bitsPerFrame >> 3; /* Number of bytes is bits/frame divide 8 */ if ((dspiState->bitsPerFrame & 0x07) != 0) /* Bits/frame module 8 is not zero */ { nBytes += 1; } /* Because SPI protocol is synchronous, the number of bytes that that slave received from the * master is the actual number of bytes that the slave transmitted to the master. So we only * monitor the received size to know when the transfer is complete. */ if (dspiState->remainingReceiveByteCount > 0) { /* Read data if remaining receive byte > 0 */ uint32_t dataReceived; uint32_t dataSend = 0; while (DSPI_HAL_GetStatusFlag(base, kDspiRxFifoDrainRequest)) { /* Have received data in the buffer. */ dataReceived = DSPI_HAL_ReadData(base); /* clear the rx fifo drain request, needed for non-DMA applications as this flag * will remain set even if the rx fifo is empty. By manually clearing this flag, it * either remain clear if no more data is in the fifo, or it will set if there is * more data in the fifo. */ DSPI_HAL_ClearStatusFlag(base, kDspiRxFifoDrainRequest); /* If bits/frame is one byte */ if (nBytes == 1) { if (dspiState->receiveBuffer) { /* Receive buffer is not null, store data into it */ *dspiState->receiveBuffer = dataReceived; ++dspiState->receiveBuffer; } if (dspiState->sendBuffer) { dataSend = *dspiState->sendBuffer; ++dspiState->sendBuffer; } /* Descrease remaining receive byte count */ --dspiState->remainingReceiveByteCount; --dspiState->remainingSendByteCount; } /* If bits/frame is 2 bytes */ else { /* With multibytes frame receiving, we only receive till the received size * matches user request. Other bytes will be ignored. */ if (dspiState->receiveBuffer) { /* Receive buffer is not null, store first byte into it */ *dspiState->receiveBuffer = dataReceived; ++dspiState->receiveBuffer; if (--dspiState->remainingReceiveByteCount > 0) { /* Receive buffer is not null, store second byte into it */ *dspiState->receiveBuffer = dataReceived >> 8; ++dspiState->receiveBuffer; } /* Decrease remaining receive byte count */ --dspiState->remainingReceiveByteCount; } else {