/*FUNCTION********************************************************************** * * Function Name : SPI_DRV_DmaMasterIRQHandler * Description : Interrupt handler for SPI master mode. * This handler is used when the extraByte flag is set to retrieve the received last byte. * *END**************************************************************************/ void SPI_DRV_DmaMasterIRQHandler(uint32_t instance) { #if FSL_FEATURE_SPI_16BIT_TRANSFERS /* instantiate local variable of type spi_master_state_t and point to global state */ spi_dma_master_state_t * spiDmaState = (spi_dma_master_state_t *)g_spiStatePtr[instance]; SPI_Type *base = g_spiBase[instance]; /* If the SPI module contains a FIFO (and if it is enabled), check the FIFO empty flag */ if ((g_spiFifoSize[instance] != 0) && (SPI_HAL_GetFifoCmd(base))) { if (SPI_HAL_GetFifoStatusFlag(base, kSpiRxFifoEmpty) == 0) { /* If there is a receive buffer, copy the final byte from the SPI data register * to the receive buffer */ if (spiDmaState->receiveBuffer) { spiDmaState->receiveBuffer[spiDmaState->transferByteCnt-2] = SPI_HAL_ReadDataLow(base); } /* Else, read out the data register and throw away the bytes read */ else { /* Read and throw away the lower data buffer to clear it out */ s_rxBuffIfNull = SPI_HAL_ReadDataLow(base); } /* Read and throw away the upper data buffer to clear it out */ s_rxBuffIfNull = SPI_HAL_ReadDataHigh(base); SPI_DRV_DmaMasterCompleteTransfer(instance); } } else /* Check the read pending flag */ { if (SPI_HAL_IsReadBuffFullPending(base) == 1) { /* If there is a receive buffer, copy the final byte from the SPI data register * to the receive buffer */ if (spiDmaState->receiveBuffer) { spiDmaState->receiveBuffer[spiDmaState->transferByteCnt-2] = SPI_HAL_ReadDataLow(base); } /* Else, read out the data register and throw away the bytes read */ else { /* Read and throw away the lower data buffer to clear it out */ s_rxBuffIfNull = SPI_HAL_ReadDataLow(base); } /* Read and throw away the upper data buffer to clear it out */ s_rxBuffIfNull = SPI_HAL_ReadDataHigh(base); SPI_DRV_DmaMasterCompleteTransfer(instance); } } #endif /* FSL_FEATURE_SPI_16BIT_TRANSFERS */ }
/*FUNCTION********************************************************************** * * Function Name : SPI_DRV_DmaMasterAbortTransfer * Description : Terminates an asynchronous transfer early with DMA support. * * During an async transfer, the user has the option to terminate the transfer early if the transfer * is still in progress. * *END**************************************************************************/ spi_status_t SPI_DRV_DmaMasterAbortTransfer(uint32_t instance) { /* instantiate local variable of type spi_dma_master_state_t and point to global state */ spi_dma_master_state_t * spiDmaState = (spi_dma_master_state_t *)g_spiStatePtr[instance]; /* Check if a transfer is running.*/ if (!spiDmaState->isTransferInProgress) { return kStatus_SPI_NoTransferInProgress; } /* Stop the running transfer.*/ SPI_DRV_DmaMasterCompleteTransfer(instance); return kStatus_SPI_Success; }
/*FUNCTION********************************************************************** * * Function Name : SPI_DRV_DmaMasterCallback * Description : This function is called when the DMA generates an interrupt. * The DMA generates an interrupt when the channel is "done", meaning that the * expected number of bytes have been transferred. When the interrupt occurs, * the DMA will jump to this callback as it was registered in the DMA register * callback service function. The user will defined their own callback function * to take whatever action they deem necessary for handling the end of a transfer. * For example, the user may simply want their callback function to set a global * flag to indicate that the transfer is complete. The user defined callback * is passed in through the "param" parameter. * The parameter chanStatus is currently not used. * *END**************************************************************************/ void SPI_DRV_DmaMasterCallback(void *param, dma_channel_status_t chanStatus) { uint32_t instance = (uint32_t)(param); /* instantiate local variable of type spi_master_state_t and point to global state */ spi_dma_master_state_t * spiDmaState = (spi_dma_master_state_t *)g_spiStatePtr[instance]; SPI_Type *base = g_spiBase[instance]; /* If the extraByte flag was set, need to enable the TX empty interrupt to get the last byte */ if (spiDmaState->extraByte) { SPI_HAL_SetTxDmaCmd(base, false); /* If the TX buffer is already empty then it may not generate an interrupt so soon * after the TX DMA is disabled, therefore read the RX data and put into RX buffer. */ if (SPI_HAL_GetIntStatusFlag(base, kSpiTxBufferEmptyFlag)) { #if FSL_FEATURE_SPI_16BIT_TRANSFERS /* If the SPI module contains a FIFO (and if it is enabled), check the FIFO empty flag */ if ((g_spiFifoSize[instance] != 0) && (SPI_HAL_GetFifoCmd(base))) { /* Wait till the rx buffer has data */ while (SPI_HAL_GetFifoStatusFlag(base, kSpiRxFifoEmpty) == 1) {} } else /* Check the read pending flag */ { /* Wait till the rx buffer has data */ while (SPI_HAL_IsReadBuffFullPending(base) == 0) {} } /* If there is a receive buffer, copy the final byte from the SPI data register * to the receive buffer */ if (spiDmaState->receiveBuffer) { spiDmaState->receiveBuffer[spiDmaState->transferByteCnt-2] = SPI_HAL_ReadDataLow(base); } /* Else, read out the data register and throw away the bytes read */ else { /* Read and throw away the lower data buffer to clear it out */ s_rxBuffIfNull = SPI_HAL_ReadDataLow(base); } /* Read and throw away the upper data buffer to clear it out */ s_rxBuffIfNull = SPI_HAL_ReadDataHigh(base); SPI_DRV_DmaMasterCompleteTransfer(instance); #endif } else { /* Else, if the TX buffer is not empty, enable the interrupt and handle the * receive in the ISR */ SPI_HAL_SetIntMode(base, kSpiTxEmptyInt, true); } } else /* If no extra byte is needing to be receive, complete the transfer */ { SPI_DRV_DmaMasterCompleteTransfer(instance); } }
/*FUNCTION********************************************************************** * * Function Name : SPI_DRV_DmaMasterCallback * Description : This function is called when the DMA generates an interrupt. * The DMA generates an interrupt when the channel is "done", meaning that the * expected number of bytes have been transferred. When the interrupt occurs, * the DMA will jump to this callback as it was registered in the DMA register * callback service function. The user will defined their own callback function * to take whatever action they deem necessary for handling the end of a transfer. * For example, the user may simply want their callback function to set a global * flag to indicate that the transfer is complete. The user defined callback * is passed in through the "param" parameter. * The parameter chanStatus is currently not used. * *END**************************************************************************/ void SPI_DRV_DmaMasterCallback(void *param, dma_channel_status_t chanStatus) { uint32_t instance = (uint32_t)(param); SPI_DRV_DmaMasterCompleteTransfer(instance); }